pptx/unicode-bmp-round-trip--thai

A single slide carries one shape whose text frame holds a characteristic Unicode sample. The DrawingML <a:t> must contain the text verbatim across every script range.

Library verdicts: python-pptx: — pptxjs: —

Metadata

Feature idpptx/unicode-bmp-round-trip--thai
Formatpptx
Categorytext-content
Familypptx/unicode-bmp-round-trip
Axis valuesscript=thai
Spececma-376-5-part-1 § 21.1.2.3.4 a:t

XPath assertions

ID / partPredicateXPathpython-pptxpptxjs
text-carries-sample-thai
ppt/slides/slide1.xml
exist
The slide's DrawingML <a:t> element must contain the characteristic sample substring for this script family.
//a:t[contains(., 'สวัสดี')]

Render assertions

No render assertions declared.

Generator source

scripts/gen_unicode_bmp_round_trip_pptx.py

#!/usr/bin/env python3
"""Generate ``fixtures/pptx/unicode-bmp-round-trip--<script>.pptx``.

Parameterised generator for the ``pptx/unicode-bmp-round-trip`` family.
Writes a minimal single-slide deck whose title placeholder carries the
payload for one Unicode range. The manifest assertion checks that the
DrawingML ``<a:t>`` element contains the sample substring for that
range via XPath ``contains()``.

The text table is held inline (mirroring the sibling docx/xlsx
generators) so shell quoting of RTL, combining-mark, and emoji-ZWJ
sequences is avoided.

Usage::

    python scripts/gen_unicode_bmp_round_trip_pptx.py \\
        --script chinese \\
        --out fixtures/pptx/unicode-bmp-round-trip--chinese.pptx
"""

from __future__ import annotations

import argparse
from pathlib import Path

from pptx import Presentation

_REPO_ROOT = Path(__file__).resolve().parent.parent

_PAYLOADS: dict[str, str] = {
    "ascii":      "Hello world",
    "latin1":     "café naïve résumé",
    "cyrillic":   "Привет мир",
    "greek":      "Γειά σου κόσμε",
    "hebrew":     "שלום עולם",
    "arabic":     "مرحبا بالعالم",
    "chinese":    "你好世界",
    "japanese":   "こんにちは世界",
    "korean":     "안녕하세요 세계",
    "devanagari": "नमस्ते दुनिया",
    "thai":       "สวัสดีชาวโลก",
    "emoji-bmp":  "Star ✨ ok",
    "emoji-smp":  "Grin \U0001F600 ok",
    "combining":  "combined à decomposed à",
    "zwj-family": "family \U0001F468‍\U0001F469‍\U0001F466",
}


def _write(script: str, out: Path) -> None:
    if script not in _PAYLOADS:
        raise SystemExit(
            f"Unknown script id {script!r}; expected one of {sorted(_PAYLOADS)}"
        )
    prs = Presentation()
    blank_layout = prs.slide_layouts[5]  # title only
    slide = prs.slides.add_slide(blank_layout)
    if slide.shapes.title is not None:
        slide.shapes.title.text = _PAYLOADS[script]
    out.parent.mkdir(parents=True, exist_ok=True)
    prs.save(out)


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("--script", required=True)
    parser.add_argument("--out", required=True)
    args = parser.parse_args()

    out_path = Path(args.out)
    if not out_path.is_absolute():
        out_path = _REPO_ROOT / out_path
    _write(args.script, out_path)
    print(out_path)
    return 0


if __name__ == "__main__":
    raise SystemExit(main())

Manifest (expanded)

{
  "$schema": "../manifest.schema.json",
  "id": "pptx/unicode-bmp-round-trip--thai",
  "kind": "literal",
  "title": "Unicode round-trip (pptx)",
  "format": "pptx",
  "category": "text-content",
  "summary": "A single slide carries one shape whose text frame holds a characteristic Unicode sample. The DrawingML <a:t> must contain the text verbatim across every script range.",
  "spec": {
    "source": "ecma-376-5-part-1",
    "clause": "21.1.2.3.4",
    "element": "a:t",
    "rnc_reference": "spec/ecma-376-5/part-1/rnc/DrawingML-Main.rnc",
    "xsd_reference": "spec/ecma-376-5/part-1/xsd/dml-main.xsd",
    "notes": "PresentationML text bodies use DrawingML runs (a:r / a:t) rather than WordprocessingML's w:t. The encoding question is identical: both literal UTF-8 and numeric-character-reference forms are spec-legal, and the XML infoset layer (what XPath sees) collapses them. python-pptx emits literal UTF-8 byte sequences. Covers the same 15-case Cartesian dimension as the docx and xlsx families for cross-format parity; a regression that only affects PowerPoint (e.g. a ZWJ emoji losing bytes during serialisation) will show up here but not in the docx family."
  },
  "fixtures": {
    "machine": "pptx/unicode-bmp-round-trip--thai"
  },
  "generator": {
    "python": "scripts/gen_unicode_bmp_round_trip_pptx.py",
    "arg_template": "--script {script.id} --out fixtures/pptx/unicode-bmp-round-trip--{script.id}.pptx"
  },
  "_expansion": {
    "parent_id": "pptx/unicode-bmp-round-trip",
    "bindings": {
      "script": "thai"
    }
  },
  "assertions": [
    {
      "id": "text-carries-sample-thai",
      "part": "ppt/slides/slide1.xml",
      "namespaces": {
        "a": "http://schemas.openxmlformats.org/drawingml/2006/main"
      },
      "xpath": "//a:t[contains(., 'สวัสดี')]",
      "must": "exist",
      "description": "The slide's DrawingML <a:t> element must contain the characteristic sample substring for this script family."
    }
  ]
}

Fixture

Download unicode-bmp-round-trip--thai.pptx (27.5 KB)

Reference preview

No rendered reference is available for this case.

Spec notes

PresentationML text bodies use DrawingML runs (a:r / a:t) rather than WordprocessingML's w:t. The encoding question is identical: both literal UTF-8 and numeric-character-reference forms are spec-legal, and the XML infoset layer (what XPath sees) collapses them. python-pptx emits literal UTF-8 byte sequences. Covers the same 15-case Cartesian dimension as the docx and xlsx families for cross-format parity; a regression that only affects PowerPoint (e.g. a ZWJ emoji losing bytes during serialisation) will show up here but not in the docx family.