pptx-ts 3.7.0 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -269
- package/dist/autopage-odPz7zZO.js +536 -0
- package/dist/autopage-odPz7zZO.js.map +1 -0
- package/dist/binary-string-CKVAYI3M.js +24 -0
- package/dist/binary-string-CKVAYI3M.js.map +1 -0
- package/dist/body-insets-Dw_BeWD_.js +54 -0
- package/dist/body-insets-Dw_BeWD_.js.map +1 -0
- package/dist/browser.d.ts +29 -9
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +41 -14
- package/dist/browser.js.map +1 -1
- package/dist/clip-Bl01BPcN.d.ts +67 -0
- package/dist/clip-Bl01BPcN.d.ts.map +1 -0
- package/dist/diagnostics-D8ot4Ei7.d.ts +244 -0
- package/dist/diagnostics-D8ot4Ei7.d.ts.map +1 -0
- package/dist/embedded-fonts-DarT9aoa.d.ts +20 -0
- package/dist/embedded-fonts-DarT9aoa.d.ts.map +1 -0
- package/dist/entry-compose-DCnvBZz2.d.ts +1046 -0
- package/dist/entry-compose-DCnvBZz2.d.ts.map +1 -0
- package/dist/{enums-CvRYniUA.d.ts → enums-BUKTUB6V.d.ts} +21 -13
- package/dist/{enums-CvRYniUA.d.ts.map → enums-BUKTUB6V.d.ts.map} +1 -1
- package/dist/{errors-Bvln0H-7.js → errors-C4oENPcu.js} +92 -2
- package/dist/errors-C4oENPcu.js.map +1 -0
- package/dist/families.d.ts +260 -0
- package/dist/families.d.ts.map +1 -0
- package/dist/families.js +57 -0
- package/dist/families.js.map +1 -0
- package/dist/{fit-BKs0zxMI.js → fit-Cb7naFj6.js} +249 -167
- package/dist/fit-Cb7naFj6.js.map +1 -0
- package/dist/font-metrics-v5fn7s7e.d.ts +613 -0
- package/dist/font-metrics-v5fn7s7e.d.ts.map +1 -0
- package/dist/grid-DikTjFey.js +187 -0
- package/dist/grid-DikTjFey.js.map +1 -0
- package/dist/{html-dom-B0I0QSbU.js → html-dom-Iuog2wdK.js} +121 -91
- package/dist/html-dom-Iuog2wdK.js.map +1 -0
- package/dist/html.d.ts +6 -6
- package/dist/html.d.ts.map +1 -1
- package/dist/html.js +7 -6
- package/dist/html.js.map +1 -1
- package/dist/image-size-CvN2iCA4.js +1611 -0
- package/dist/image-size-CvN2iCA4.js.map +1 -0
- package/dist/index.d.ts +24 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +31 -11
- package/dist/index.js.map +1 -1
- package/dist/inspect.d.ts +40 -31
- package/dist/inspect.d.ts.map +1 -1
- package/dist/inspect.js +40 -48
- package/dist/inspect.js.map +1 -1
- package/dist/math.d.ts +7 -5
- package/dist/math.d.ts.map +1 -1
- package/dist/math.js +16 -7
- package/dist/math.js.map +1 -1
- package/dist/measure.d.ts +12 -225
- package/dist/measure.d.ts.map +1 -1
- package/dist/measure.js +3 -3
- package/dist/node.d.ts +22 -8
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +27 -7
- package/dist/node.js.map +1 -1
- package/dist/notes-Dh12JAbn.js +3264 -0
- package/dist/notes-Dh12JAbn.js.map +1 -0
- package/dist/options-internal-WqgMf720.js +43 -0
- package/dist/options-internal-WqgMf720.js.map +1 -0
- package/dist/{package-CaOLXSNi.d.ts → package-J49Ck6S2.d.ts} +27 -12
- package/dist/package-J49Ck6S2.d.ts.map +1 -0
- package/dist/playbtn-CUqQdoDf.js +22 -0
- package/dist/playbtn-CUqQdoDf.js.map +1 -0
- package/dist/{slide-ZqAdVvHV.d.ts → pres-C6qgOFAa.d.ts} +1021 -1423
- package/dist/pres-C6qgOFAa.d.ts.map +1 -0
- package/dist/{presentation-DrJtj3-C.js → presentation-DGYlAWhl.js} +3208 -2727
- package/dist/presentation-DGYlAWhl.js.map +1 -0
- package/dist/{presentation-types-CDjScsev.d.ts → presentation-types-8jLQHI4M.d.ts} +1070 -683
- package/dist/presentation-types-8jLQHI4M.d.ts.map +1 -0
- package/dist/read.d.ts +9 -9
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +4 -4
- package/dist/script.d.ts +80 -66
- package/dist/script.d.ts.map +1 -1
- package/dist/script.js +2399 -1139
- package/dist/script.js.map +1 -1
- package/dist/{shapes-BemroU-z.js → shapes-re0KyQk_.js} +2807 -1609
- package/dist/shapes-re0KyQk_.js.map +1 -0
- package/dist/slide-Dx2ZeVZ6.d.ts +1256 -0
- package/dist/slide-Dx2ZeVZ6.d.ts.map +1 -0
- package/dist/slide-size-BalTjFuv.js +88 -0
- package/dist/slide-size-BalTjFuv.js.map +1 -0
- package/dist/{units-internal-Dg95w_YD.js → table-cell-margins-EVg0EwxT.js} +235 -273
- package/dist/table-cell-margins-EVg0EwxT.js.map +1 -0
- package/dist/table-dom-BTDP3lEP.js +21 -0
- package/dist/table-dom-BTDP3lEP.js.map +1 -0
- package/dist/text-anchor-CrYXAfUu.js +176 -0
- package/dist/text-anchor-CrYXAfUu.js.map +1 -0
- package/dist/text-sN64Otf_.js +3980 -0
- package/dist/text-sN64Otf_.js.map +1 -0
- package/dist/transition-speed-kUEWDWTx.js +14 -0
- package/dist/transition-speed-kUEWDWTx.js.map +1 -0
- package/dist/units-internal-XJlf-hOl.js +649 -0
- package/dist/units-internal-XJlf-hOl.js.map +1 -0
- package/dist/zip-C0leZZMj.d.ts +67 -0
- package/dist/zip-C0leZZMj.d.ts.map +1 -0
- package/dist/zip-CKd8ihcf.js +177 -0
- package/dist/zip-CKd8ihcf.js.map +1 -0
- package/dist/zip.d.ts +3 -68
- package/dist/zip.js +3 -163
- package/dist/zoom-DPUHh85d.js +8865 -0
- package/dist/zoom-DPUHh85d.js.map +1 -0
- package/package.json +106 -19
- package/skills/ts-pptx-upstream/SKILL.md +58 -57
- package/dist/autopage-DkjYZUFD.js +0 -423
- package/dist/autopage-DkjYZUFD.js.map +0 -1
- package/dist/diagnostics-DfBdDHre.d.ts +0 -829
- package/dist/diagnostics-DfBdDHre.d.ts.map +0 -1
- package/dist/errors-Bvln0H-7.js.map +0 -1
- package/dist/errors-PflMPWBn.d.ts +0 -182
- package/dist/errors-PflMPWBn.d.ts.map +0 -1
- package/dist/fit-BKs0zxMI.js.map +0 -1
- package/dist/html-dom-B0I0QSbU.js.map +0 -1
- package/dist/namespaces-BVnNu7sg.js +0 -666
- package/dist/namespaces-BVnNu7sg.js.map +0 -1
- package/dist/notes-CJFJaG6M.js +0 -1724
- package/dist/notes-CJFJaG6M.js.map +0 -1
- package/dist/package-CaOLXSNi.d.ts.map +0 -1
- package/dist/pres-BcBR3CSM.d.ts +0 -202
- package/dist/pres-BcBR3CSM.d.ts.map +0 -1
- package/dist/presentation-DrJtj3-C.js.map +0 -1
- package/dist/presentation-types-CDjScsev.d.ts.map +0 -1
- package/dist/shapes-BemroU-z.js.map +0 -1
- package/dist/slide-ZqAdVvHV.d.ts.map +0 -1
- package/dist/text-B8SLEaZx.js +0 -11327
- package/dist/text-B8SLEaZx.js.map +0 -1
- package/dist/units-1kRzYShk.js +0 -231
- package/dist/units-1kRzYShk.js.map +0 -1
- package/dist/units-internal-Dg95w_YD.js.map +0 -1
- package/dist/zip.d.ts.map +0 -1
- package/dist/zip.js.map +0 -1
package/dist/script.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"script.js","names":["#seen","#notes","ANCHOR","WRITABLE_DASHES","#byPartName","#assets","#counts","printSlides"],"sources":["../src/script/fidelity.ts","../src/script/ir.ts","../src/script/from-read/values.ts","../src/script/from-read/surface-fill.ts","../src/script/from-read/picture-fill.ts","../src/script/from-read/detect.ts","../src/script/from-read/text.ts","../src/script/from-read/table.ts","../src/script/from-read/chart.ts","../src/script/from-read/shape.ts","../src/script/from-read/chrome.ts","../src/script/from-read/transition.ts","../src/script/from-read/deck.ts","../src/script/print/literal.ts","../src/script/print/common.ts","../src/script/print/script.ts","../src/script/print/standalone.ts","../src/script/verify/canonical.ts","../src/script/verify/diff.ts"],"sourcesContent":["/**\n * Fidelity notes — the declared, machine-checkable list of what a deck loses on the way\n * to a script.\n *\n * A converter that warns about losses to a log has no way to be tested: the warnings are\n * prose, nothing consumes them, and a missing one looks exactly like a clean run. Making\n * the notes part of the IR inverts that. A note says \"field X of shape Y will not come\n * back\", so a round-trip check can exclude precisely those fields and treat **any**\n * remaining difference as a defect. Both directions then have teeth:\n *\n * - an *undeclared* loss fails the round-trip, because nothing excluded it;\n * - a *declared* loss that actually survives is a stale note, and the check can say so.\n *\n * That is the whole reason notes are first-class rather than a side channel. It also\n * means {@link FidelityNote.construct} is an identifier, not a sentence: it has to be\n * matchable against a field path, so it is a stable dotted key and the human explanation\n * lives in {@link FidelityNote.detail}.\n */\n\n/** What happened to the construct. */\nexport type Disposition =\n\t/** Gone: nothing in the output carries it. */\n\t| 'dropped'\n\t/**\n\t * Present but structurally simplified — a value survives while the structure around\n\t * it does not (threaded comment replies flattened into separate comments, a per-script\n\t * font scheme reduced to latin, a placeholder demoted to a plain shape).\n\t */\n\t| 'flattened'\n\t/**\n\t * Present and structurally intact, but not the same value — a re-encoding that a\n\t * viewer may or may not be able to tell apart (a modern transition mapped to the\n\t * nearest named one, a chart rebuilt from cached points rather than its workbook).\n\t */\n\t| 'approximated'\n\n/**\n * Which side of the library is responsible. Recording this is what makes the notes\n * actionable rather than merely honest: `unread` and `unwritable` are bugs waiting to be\n * fixed in a specific subsystem, while `unsupported` is a property of OOXML or of the\n * chosen output tier and will not be fixed by more converter work.\n */\nexport type Cause =\n\t/** The read API exposes no accessor for it, so the converter never saw it. */\n\t| 'unread'\n\t/** Read fine, but the write API has no option that expresses it. */\n\t| 'unwritable'\n\t/** Both sides can handle it; this output tier structurally cannot carry it. */\n\t| 'unsupported'\n\n/** One declared loss. */\nexport interface FidelityNote {\n\t/** 1-based source slide, or `null` for a deck-level loss. */\n\tslideNumber: number | null\n\t/** Source shape name (`p:cNvPr/@name`), or `null` when the loss is not shape-scoped. */\n\tshapeName: string | null\n\t/**\n\t * Stable dotted identifier for the lost construct — `line.width`, `text.tabStops`,\n\t * `chart.workbook`. Matched mechanically by the round-trip check, so it must name a\n\t * field path rather than describe one. Reuse an existing key for the same construct\n\t * instead of coining a synonym.\n\t */\n\tconstruct: string\n\tdisposition: Disposition\n\tcause: Cause\n\t/** Why, in a sentence, for a human reading the emitted script's header. */\n\tdetail: string\n}\n\n/**\n * Accumulates notes while a deck is walked, so the walk itself stays a plain\n * read-model → IR mapping and does not thread a growing array through every function.\n *\n * Deduplicates on the full note identity. Without that, a construct that is lost on every\n * run of a 400-run text body would produce 400 identical notes and bury the one-off losses\n * that actually need reading.\n */\nexport class NoteCollector {\n\treadonly #seen = new Set<string>()\n\treadonly #notes: FidelityNote[] = []\n\n\t/** Record a loss. A repeat of an identical note is ignored. */\n\tadd(note: FidelityNote): void {\n\t\tconst key = `${note.slideNumber}\\0${note.shapeName}\\0${note.construct}\\0${note.disposition}\\0${note.cause}\\0${note.detail}`\n\t\tif (this.#seen.has(key)) return\n\t\tthis.#seen.add(key)\n\t\tthis.#notes.push(note)\n\t}\n\n\t/**\n\t * The notes, in the order first recorded — which is deck order, since the walk is\n\t * ordered, so a reader meets them the way they meet the slides.\n\t */\n\tget notes(): FidelityNote[] {\n\t\treturn this.#notes\n\t}\n}\n\n/**\n * Namespace for a loss recorded against a shape on a **slide layout** rather than on a slide,\n * prepended to the construct by {@link layoutShapeScope}.\n *\n * The chrome mapper reuses the slide shape mapper wholesale — a rectangle on a layout is\n * transcribed by the same code that transcribes one on a slide, which is what keeps the two\n * from drifting. That sharing brings the slide vocabulary with it: a themed outline on a\n * layout records `line.width` exactly as a slide's would. Left unmarked, those notes would be\n * wrong twice over. A template-anchored script would report them, though it never rebuilds a\n * layout and loses nothing; and the round trip would let one excuse a *slide* difference,\n * because a layout note carries no slide number and a name like \"Rectangle 7\" repeats between\n * the tiers. The prefix keeps the shared vocabulary and states which tier it is about.\n *\n * `layout.` rather than `master.`, which is how the other chrome constructs are spelled: those\n * are named after the `defineSlideMaster` call that authors them, while these name the source\n * tier the loss is on — and a master's own decoration is not re-authored at all, so a note\n * under this prefix is always about a layout.\n */\nexport const LAYOUT_NOTE_PREFIX = 'layout.'\n\n/**\n * A {@link NoteCollector} bound to one slide and shape, so a mapping function can record\n * a loss without knowing where in the deck it sits. Obtained via {@link scopeNotes}.\n */\nexport interface NoteScope {\n\t/** Record a loss at this scope. */\n\tnote(construct: string, disposition: Disposition, cause: Cause, detail: string): void\n\t/** Re-scope to a shape within the same slide. */\n\tforShape(shapeName: string | null): NoteScope\n}\n\n/** Bind a collector to a slide (and optionally a shape). */\nexport function scopeNotes(\n\tcollector: NoteCollector,\n\tslideNumber: number | null,\n\tshapeName: string | null = null\n): NoteScope {\n\treturn {\n\t\tnote(construct, disposition, cause, detail) {\n\t\t\tcollector.add({ slideNumber, shapeName, construct, disposition, cause, detail })\n\t\t},\n\t\tforShape(name) {\n\t\t\treturn scopeNotes(collector, slideNumber, name)\n\t\t},\n\t}\n}\n\n/**\n * Wrap a scope so every construct recorded through it is namespaced under\n * {@link LAYOUT_NOTE_PREFIX} — see there for why.\n *\n * Constructs written at a call site inside the layout walk are therefore *relative*: the\n * decoration mapper records `decoration`, and what lands in the note list is\n * `layout.decoration`. The wrapper survives `forShape`, since a layout loss is scoped to a\n * shape name the same way a slide loss is.\n */\nexport function layoutShapeScope(notes: NoteScope): NoteScope {\n\treturn {\n\t\tnote(construct, disposition, cause, detail) {\n\t\t\tnotes.note(`${LAYOUT_NOTE_PREFIX}${construct}`, disposition, cause, detail)\n\t\t},\n\t\tforShape(name) {\n\t\t\treturn layoutShapeScope(notes.forShape(name))\n\t\t},\n\t}\n}\n","/**\n * The deck IR — a serializable description of a deck as a sequence of write-API calls.\n *\n * This is the seam between reading a `.pptx` and printing TypeScript for it. Everything\n * upstream of the IR knows about OOXML and the read model; everything downstream knows\n * only about strings. Neither half can see the other, which is the point: the decision\n * \"this `a:ln` becomes `line: { width: 2 }`\" is made once, here, and is testable without\n * a printer, while \"how a number is spelled in source text\" is a printer concern that\n * cannot silently change what the deck means.\n *\n * Two rules keep that seam honest, and both are load-bearing:\n *\n * 1. **The IR is data, not objects.** No DOM nodes, no read-model instances, no\n * functions — `structuredClone` and `JSON.stringify` both round-trip it. A round-trip\n * test can therefore compare two IRs directly (see {@link FidelityNote}), and an IR\n * can be cached or shipped without dragging a whole `Presentation` along.\n * 2. **`args` are literal write-API option objects.** A {@link CallIr} is exactly what\n * the emitted source will pass, so the printer never invents, reshapes, or defaults a\n * value — it spells out what is already there. If the printer had to interpret, the\n * same construct could mean two things depending on which half you asked.\n *\n * Media is the one thing that cannot be a literal, since bytes are not source text. It\n * is referenced by {@link AssetRef} and carried out-of-band in {@link DeckIr.assets}, so\n * the IR itself stays serializable and the printer decides between a file path and an\n * inline base64 literal.\n */\nimport type { FidelityNote } from './fidelity.js'\n\n/**\n * A reference to bytes held in {@link DeckIr.assets}, standing where a write-API option\n * wants image/media data. Printed as a `path` or an inline `data:` literal depending on\n * the print options — an IR-level decision would bake one choice into the IR and force a\n * re-read to change it.\n *\n * The `$asset` sigil is deliberate: no write-API option object has a `$`-prefixed key,\n * so a value carrying one is unambiguously a reference rather than user data.\n */\nexport interface AssetRef {\n\t$asset: string\n}\n\n/** `true` when `value` is an {@link AssetRef} rather than a plain IR object. */\nexport function isAssetRef(value: unknown): value is AssetRef {\n\treturn typeof value === 'object' && value !== null && typeof (value as AssetRef).$asset === 'string'\n}\n\n/**\n * Any value an IR may hold. Deliberately narrower than `unknown`: it excludes `undefined`\n * so that \"absent\" has exactly one spelling (a missing key), which is what makes two IRs\n * comparable field-by-field in a round-trip diff. `readModelToIr` never writes an\n * `undefined` value.\n */\nexport type IrValue = null | boolean | number | string | AssetRef | IrValue[] | { [key: string]: IrValue }\n\n/**\n * Widen one of the typed IR records below to {@link IrValue}, for the printer and the\n * canonicaliser, which walk the IR generically.\n *\n * A cast, and unavoidably so. An optional key on an interface types as `T | undefined`,\n * while `IrValue` deliberately excludes `undefined` so that \"absent\" has exactly one\n * spelling — which makes the two mutually unassignable even though every value a mapper\n * actually produces satisfies both. The invariant that closes the gap is enforced at the\n * source (`compact` and the conditional spreads in `from-read/`, pinned by the \"no value is\n * `undefined`\" corpus test) rather than by the type system, so it is stated once here\n * instead of re-argued at each call site.\n */\nexport function asIrValue(value: object): IrValue {\n\treturn value as unknown as IrValue\n}\n\n/** Bytes referenced by an {@link AssetRef}, plus what a printer needs to name and type them. */\nexport interface AssetIr {\n\t/** Stable key an {@link AssetRef} resolves against; also the emitted filename. */\n\tname: string\n\t/** MIME type from the source package's content types, for an inline `data:` URI. */\n\tcontentType: string\n\tbytes: Uint8Array\n}\n\n/**\n * One write-API call on a slide, in the order it must be made. `method` names a real\n * method on the authored slide and `args` are its positional arguments — so a printer is\n * a formatter, and `readModelToIr` owns every semantic choice.\n *\n * Ordering is z-order: OOXML paints a slide's shape tree front-to-back in document order,\n * and so does the write path, so preserving call order preserves overlap.\n */\nexport interface CallIr {\n\tmethod: 'addText' | 'addShape' | 'addImage' | 'addTable' | 'addChart' | 'addConnector' | 'addGroup' | 'addNotes'\n\targs: IrValue[]\n\t/**\n\t * The source shape's name (`p:cNvPr/@name`), when it had one. Not an argument —\n\t * carried so a printer can comment the call and a fidelity note can point at it.\n\t */\n\tsourceName?: string\n}\n\n/**\n * How a slide's content gets into the output deck.\n *\n * `authored` — every shape is transcribed into {@link CallIr}s and regenerated through\n * the write API. This is the goal: the emitted source is editable, and a reader can see\n * what the deck contains.\n *\n * `carried` — the slide holds at least one construct the write API cannot express at all\n * (`chartEx` is the clear case: a full reader, no emitter), so transcribing it would\n * silently produce a different deck. A printer that *can* copy the slide from the source\n * package should do so: fidelity is higher than transcription, though the emitted source then\n * says nothing about what is on the slide, which is a real cost and always carries a\n * {@link FidelityNote}.\n *\n * This is a recommendation, not an erasure. {@link SlideIr.calls} is populated either way, so\n * a printer with no source package to copy from prints them and loses only the unwritable\n * construct rather than the whole slide.\n */\nexport type SlideSource = 'authored' | 'carried'\n\n/**\n * A slide's background, already reduced to what the write API's `background` accepts.\n *\n * `data` rather than `image`, because `BackgroundProps` is `DataOrPathProps & ShapeFillProps`\n * and `data` is the key it actually reads — an `image` key would print, typecheck against\n * `IrValue`, and be ignored at run time.\n */\nexport interface BackgroundIr {\n\tcolor?: string\n\ttransparency?: number\n\tdata?: AssetRef\n}\n\n/**\n * A transition's sound (`p:sndAc`), reduced to what `TransitionSoundProps` accepts.\n *\n * `data` rather than `path`, for the same reason a background image uses `data`: the bytes\n * are the thing the IR carries, and a path would bind the script to a file layout the IR\n * knows nothing about. The stop-previous form has no bytes at all — it silences a sound\n * still playing from the previous slide — so it is the one shape here with no {@link AssetRef}.\n */\nexport interface TransitionSoundIr {\n\t/** Bytes of the embedded WAV, for a start sound. Absent for {@link stopPrevious}. */\n\tdata?: AssetRef\n\t/** `p:snd@name`, the display name PowerPoint shows for the sound. */\n\tname?: string\n\t/** `p:stSnd@loop` — repeat until the next sound starts. Omitted when false, its default. */\n\tloop?: boolean\n\t/** The `p:endSnd` form: stop the previous slide's sound rather than start one. */\n\tstopPrevious?: boolean\n}\n\n/**\n * A slide's show transition (`p:transition`), as a literal `TransitionProps`.\n *\n * Only the base ECMA-376 transitions reach this type. The read model reports\n * {@link TransitionInfo.type} as an *open string*, because PowerPoint's modern effects\n * (Morph, Vortex, …) live in the `p14`/`p15`/`p159` namespaces and it decodes those too —\n * but the write path names 21 base ones and nothing else, so `from-read/transition.ts`\n * filters against that vocabulary and notes what it drops. Anything that survives is a name\n * the write API's own `TransitionType` union accepts, which is what keeps a printed script\n * compiling.\n */\nexport interface TransitionIr {\n\t/** The transition-type element's local name, guaranteed to be a writable one. */\n\ttype: string\n\t/** `p:transition@spd`. Always present — see `from-read/transition.ts` for why it is not omitted. */\n\tspeed: 'slow' | 'med' | 'fast'\n\t/** `p14:dur` in milliseconds, when the source carried an exact duration. */\n\tdurationMs?: number\n\t/** `advClick`. Omitted when true, its default. */\n\tadvanceOnClick?: boolean\n\t/** `advTm` in milliseconds, when the slide auto-advances. */\n\tadvanceAfterMs?: number\n\t/** Type-specific attributes on the type element (`{ dir: 'd' }`, `{ spokes: '2' }`, …). */\n\tvariant?: { [key: string]: string }\n\tsound?: TransitionSoundIr\n}\n\n/**\n * The layout a slide should be bound to in the destination deck, identified two ways\n * because neither alone is sufficient.\n *\n * The **name** is the portable identity: it is what lets a script built from one deck be\n * re-pointed at a different template whose layouts happen to be named the same, and it is\n * what a reader recognises. But `p:cSld@name` is not unique — a deck with several masters\n * routinely carries several \"Title and Content\" layouts, and binding by an ambiguous name\n * is an error, not a coin flip. The **index** into the deck's layout gallery always\n * resolves, so it is the fallback, and {@link nameIsUnique} says which to trust.\n */\nexport interface SlideLayoutIr {\n\t/** `p:cSld@name` of the source layout (`''` when the layout is unnamed). */\n\tname: string\n\t/** Zero-based position in the source deck's layout gallery, in master-then-layout order. */\n\tindex: number\n\t/** `false` when another layout in that gallery shares {@link name}. */\n\tnameIsUnique: boolean\n}\n\n/** One slide of the deck. */\nexport interface SlideIr {\n\t/** 1-based index in the source deck; the identity a {@link FidelityNote} points at. */\n\tnumber: number\n\tsource: SlideSource\n\t/** The layout to bind to, or `null` when the source slide resolves none. */\n\tlayout: SlideLayoutIr | null\n\t/** `p:sld/@show=\"0\"` — a slide hidden from presentation but present in the deck. */\n\thidden: boolean\n\t/** `p:cSld/@name`, when the source slide had one. */\n\tname?: string\n\tbackground?: BackgroundIr\n\t/** Speaker notes as plain text. Notes-slide geometry and placeholders do not survive. */\n\tnotesText?: string\n\t/**\n\t * The show transition, when the source has one the write API can name. Slide-scoped\n\t * rather than a {@link CallIr} because the write API models it as a property assignment\n\t * on the slide, not a method — the IR's `method` union names real methods only.\n\t */\n\ttransition?: TransitionIr\n\t/**\n\t * Write-API calls in z-order.\n\t *\n\t * Populated for every slide, **including a `carried` one**. A printer that can copy the\n\t * source slide ignores these; one that cannot — a standalone output has no source package\n\t * to copy from — prints them and is left with only the unwritable construct missing rather\n\t * than the whole slide. Marking a slide `carried` is a recommendation, not an erasure.\n\t */\n\tcalls: CallIr[]\n}\n\n/**\n * A deck's theme, reduced to what `ThemeProps` accepts — the 12 `a:clrScheme` slots and the\n * major/minor Latin, East-Asian and complex-script faces.\n *\n * What is *not* here is the point of the tier split. `a:fmtScheme` — the three fill, three\n * line and three effect style lists a shape's `p:style` references — has no write-API\n * counterpart and no read accessor, so a theme cannot be reproduced, only approximated.\n */\nexport interface ThemeIr {\n\theadFontFace?: string\n\tbodyFontFace?: string\n\theadFontFaceEA?: string\n\tbodyFontFaceEA?: string\n\theadFontFaceCS?: string\n\tbodyFontFaceCS?: string\n\t/** The 12 `a:clrScheme` slots as bare 6-digit hex, omitting any the theme leaves unset. */\n\tcolorScheme?: { [slot: string]: string }\n}\n\n/**\n * One source slide layout approximated as a `defineSlideMaster` call.\n *\n * The naming is the write API's, not OOXML's: `defineSlideMaster` creates a *layout* under\n * the single shared master, which is exactly the granularity a source layout needs. A source\n * deck's masters have no counterpart at all — hence {@link ChromeIr}'s multi-master note.\n */\nexport interface MasterIr {\n\t/**\n\t * Gallery position of the source layout, matching {@link SlideLayoutIr.index}, so a slide\n\t * finds the master it should bind to without re-deriving a name.\n\t */\n\tlayoutIndex: number\n\t/**\n\t * A `SlideMasterProps` literal. `props.title` is made unique across the deck, because it\n\t * doubles as the key `addSlide({ masterTitle })` matches against and source layout names\n\t * are not unique.\n\t */\n\tprops: { [key: string]: IrValue }\n}\n\n/**\n * The deck's shared chrome, approximated for an output that has no template to inherit it\n * from. A template-anchored printer ignores this entirely — the source deck *is* the chrome.\n */\nexport interface ChromeIr {\n\ttheme: ThemeIr\n\t/** One entry per source layout, in gallery order. */\n\tmasters: MasterIr[]\n}\n\n/** Deck-level properties, reduced to the five `docProps` fields the write API sets. */\nexport interface DeckPropsIr {\n\ttitle?: string\n\tauthor?: string\n\tcompany?: string\n\tsubject?: string\n\trevision?: string\n}\n\n/**\n * A whole deck, ready to print.\n *\n * `widthEmu`/`heightEmu` are raw EMU rather than inches because that is what the read\n * model reports and what the write API's `Coord` accepts verbatim; converting here would\n * introduce a rounding decision at the wrong layer.\n */\nexport interface DeckIr {\n\tslideSize: { widthEmu: number; heightEmu: number }\n\tprops: DeckPropsIr\n\t/**\n\t * Theme and layouts, approximated. Only a standalone printer reads this; a\n\t * template-anchored one gets all of it byte-identical from the source deck instead.\n\t */\n\tchrome: ChromeIr\n\tslides: SlideIr[]\n\tassets: AssetIr[]\n\t/**\n\t * Every construct that did not survive into {@link slides} intact. This is a\n\t * *contract*, not a log: a round-trip check excludes exactly these fields from its\n\t * diff, so an unnoted difference is a bug and a note nothing else corroborates is a\n\t * stale claim. See {@link FidelityNote}.\n\t */\n\tfidelity: FidelityNote[]\n}\n","/**\n * Value-level conversions shared by every mapper: geometry, colour, and the small\n * discipline that keeps an IR diffable.\n *\n * The precision rules here are not style choices, they are the measured boundary of what\n * the write API can carry, and each is pinned by a regression test:\n *\n * - A `Coord`-typed option accepts `` `${n}emu` ``, so EMU passes through untouched and\n * the source geometry is reproduced exactly. That covers every position and size.\n * - `colW`, `rowH`, and `margin` are number/`Margin`-typed **inches** and reject a raw-EMU\n * string, so they are where exactness stops. `defineLayout`'s `width`/`height` are a\n * fourth, reached only by a printer: there the imprecision does not degrade quietly but\n * *throws*, since `appendSlides` compares the two decks' EMU sizes for equality after\n * converting the declared inches back. Six decimal places is the minimum\n * at which `Math.round(printed × 914400)` provably returns the original EMU, bounding the\n * drift at 0.4572 EMU — about half a millionth of an inch. Rounding shorter to suppress\n * `0.5000000001`-style noise trades a cosmetic problem for a real geometry loss.\n */\nimport type { IrValue } from '../ir.js'\nimport type { GraphicFrame } from '../../read.js'\nimport { EMU_PER_POINT } from '../../units.js'\n\n/** EMU per inch (ECMA-376 §20.1.2.1). */\nconst EMU_PER_INCH = 914400\n\n/**\n * Decimal places used for the inch-typed options. See the module header: this is the\n * proven minimum for an EMU-exact round-trip, not a formatting preference.\n */\nconst INCH_DECIMALS = 6\n\n/** Geometry as a `Coord` the write API takes verbatim, preserving the exact EMU. */\nexport function emu(value: number): string {\n\treturn `${Math.round(value)}emu`\n}\n\n/**\n * Geometry as inches, for the three options that reject a raw-EMU string. Rounded to\n * {@link INCH_DECIMALS}, which is EMU-exact on the way back.\n */\nexport function inches(emuValue: number): number {\n\treturn Number((emuValue / EMU_PER_INCH).toFixed(INCH_DECIMALS))\n}\n\n/** EMU → points, the unit the write API uses for line widths and font sizes. */\nexport function points(emuValue: number): number {\n\treturn emuValue / EMU_PER_POINT\n}\n\n/**\n * Points → inches, at the same proven precision as {@link inches}. Needed because the read\n * model reports text-body insets in points while the write API's `margin` takes inches —\n * and warns on a value `>= 1`, on the assumption that it is a points value passed by\n * mistake, so handing it points would both mis-scale the text and produce a warning.\n */\nexport function pointsToInches(pt: number): number {\n\treturn Number((pt / 72).toFixed(INCH_DECIMALS))\n}\n\n/**\n * A colour for a write-API `color` field. The read model splits a colour into a raw\n * `schemeClr` token and a resolved literal hex; this prefers the token, because a token\n * re-resolves against the destination theme and so keeps the deck recolourable, which is\n * the whole reason a theme colour was authored.\n *\n * Only the ten tokens the write path's `clrMap` covers survive as tokens — the other\n * seven `ST_SchemeColorVal` values degrade to a hex literal there anyway, so passing them\n * through would produce a silently different colour. Callers hand those to\n * {@link literalColor} instead after recording a note.\n */\nconst WRITABLE_SCHEME_TOKENS = new Set([\n\t'accent1',\n\t'accent2',\n\t'accent3',\n\t'accent4',\n\t'accent5',\n\t'accent6',\n\t'bg1',\n\t'bg2',\n\t'tx1',\n\t'tx2',\n])\n\n/** `true` when a `schemeClr` token survives as a token rather than degrading to hex. */\nexport function isWritableSchemeToken(token: string | null): boolean {\n\treturn token !== null && WRITABLE_SCHEME_TOKENS.has(token)\n}\n\n/** Normalize a hex to the bare 6-digit uppercase form the write API expects. */\nexport function literalColor(hex: string): string {\n\treturn hex.replace(/^#/, '').toUpperCase()\n}\n\n/**\n * Build an IR object from possibly-absent parts, dropping every `undefined`.\n *\n * Every mapper funnels through this. An IR must spell \"absent\" exactly one way — a\n * missing key — or two IRs describing the same deck compare unequal because one wrote\n * `{ bold: undefined }` and the other wrote `{}`. That would surface as phantom\n * round-trip failures, so the invariant is enforced in one place rather than trusted to\n * every call site.\n *\n * Returns `undefined` when nothing survived, so a caller can drop the whole option object\n * rather than emit an empty one.\n */\nexport function compact(source: Record<string, IrValue | undefined>): Record<string, IrValue> | undefined {\n\tconst out: Record<string, IrValue> = {}\n\tlet any = false\n\tfor (const key of Object.keys(source).sort()) {\n\t\tconst value = source[key]\n\t\tif (value === undefined) continue\n\t\tout[key] = value\n\t\tany = true\n\t}\n\treturn any ? out : undefined\n}\n\n/** {@link compact}, but always an object — for a required options argument. */\nexport function compactRequired(source: Record<string, IrValue | undefined>): Record<string, IrValue> {\n\treturn compact(source) ?? {}\n}\n\n/** Drop a value that is `null`, so the read model's \"unset\" becomes an absent IR key. */\nexport function orUndefined<T>(value: T | null): T | undefined {\n\treturn value === null ? undefined : value\n}\n\n/**\n * A 0–1 opacity as the write API's 0–100 transparency; `undefined` when unset.\n *\n * Fully opaque is *not* `0` here — a caller that means \"no transparency at all\" passes\n * `undefined`, because emitting `transparency: 0` for an `a:alphaModFix amt=\"100000\"`\n * would produce a key the output cannot have: the write path emits no `a:alphaModFix` for\n * a zero transparency, so the re-read deck reports no alpha and the round trip sees a\n * difference where there is no visible one.\n */\nexport function alphaToTransparency(alpha: number | null | undefined): number | undefined {\n\tif (alpha === undefined || alpha === null) return undefined\n\treturn Math.round((1 - alpha) * 100)\n}\n\n/**\n * A graphic frame's position as write-API options. Identical to a shape's, minus rotation and\n * flip: a `p:graphicFrame` has neither, so `a:xfrm` carries only the offset and extent.\n */\nexport function positionOfFrame(frame: GraphicFrame): Record<string, IrValue> {\n\tconst box = frame.absoluteFrame\n\tif (!box) return {}\n\treturn { x: emu(box.left), y: emu(box.top), w: emu(box.width), h: emu(box.height) }\n}\n","/**\n * The non-solid halves of a surface's fill — `a:gradFill` and `a:pattFill` — as\n * `ShapeFillProps`.\n *\n * Shared by a shape's fill, a table's background, and a table cell's, which are the same\n * two elements read from three containers. `ShapeProps.fill`, `TableProps.tableFill` and\n * `TableCellProps.fill` are all `ShapeFillProps`, so the mapping is identical and only the\n * note's `where` prefix differs — the same reasoning that keeps `pictureFillOption` in one\n * place rather than one copy per surface.\n */\nimport type { GradientFill } from '../../read/api/gradient.js'\nimport type { PatternFill } from '../../read/api/pattern-fill.js'\nimport type { NoteScope } from '../fidelity.js'\nimport type { IrValue } from '../ir.js'\nimport { alphaToTransparency, compact, isWritableSchemeToken, literalColor } from './values.js'\n\n/** How a note names the surface a gradient sits on: `fill.gradient`, `table.fill.gradient`, … */\ntype FillNoteScope = 'fill' | 'line' | 'table.fill' | 'table.cell.fill'\n\n/**\n * A read gradient as `GradientFillProps`. Stop positions convert from the read model's\n * 0–1 fraction to the write API's 0–100 percentage; the angle needs no conversion, since\n * both sides use OOXML degrees (clockwise from 3 o'clock).\n */\nexport function gradientStops(gradient: GradientFill, notes: NoteScope, where: FillNoteScope): IrValue | undefined {\n\tconst stops = gradient.stops\n\t\t.map((stop) => {\n\t\t\tconst color = isWritableSchemeToken(stop.schemeColor)\n\t\t\t\t? (stop.schemeColor as string)\n\t\t\t\t: stop.effectiveHex === null\n\t\t\t\t\t? null\n\t\t\t\t\t: literalColor(stop.effectiveHex)\n\t\t\tif (color === null) return null\n\t\t\treturn compact({\n\t\t\t\tcolor,\n\t\t\t\tposition: Math.round((stop.position ?? 0) * 100),\n\t\t\t\ttransparency: alphaToTransparency(stop.alpha),\n\t\t\t}) as IrValue\n\t\t})\n\t\t.filter((stop): stop is IrValue => stop !== null)\n\n\tif (stops.length < 2) {\n\t\tnotes.note(\n\t\t\t`${where}.gradient`,\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t'a gradient with fewer than two resolvable stops cannot be expressed, so this falls back to no gradient'\n\t\t)\n\t\treturn undefined\n\t}\n\n\tif (gradient.kind === 'path') {\n\t\t// `a:path` covers circle/rect/shape; the write API models only the radial case, so\n\t\t// a rectangular or shape-following gradient becomes a circular one.\n\t\tif (gradient.path !== null && gradient.path !== 'circle') {\n\t\t\tnotes.note(\n\t\t\t\t`${where}.gradient.path`,\n\t\t\t\t'approximated',\n\t\t\t\t'unwritable',\n\t\t\t\t`a \"${gradient.path}\" path gradient is emitted as a radial one; the write API models no other path shape`\n\t\t\t)\n\t\t}\n\t\treturn { kind: 'radial', stops }\n\t}\n\treturn compact({ kind: 'linear', angle: gradient.angleDeg ?? 0, stops })\n}\n\n/**\n * A read hatch as `ShapeFillProps` with `type: 'pattern'`, or `undefined` when the pattern\n * names no preset — `a:pattFill/@prst` is what selects the hatch, so without it there is\n * nothing to reproduce.\n *\n * Both colours are emitted as literals rather than scheme tokens: `PatternFillProps` types\n * `fgColor`/`bgColor` as hex, so a token would not survive the write side anyway.\n */\nexport function patternOption(pattern: PatternFill | null): IrValue | undefined {\n\tif (!pattern?.preset) return undefined\n\treturn {\n\t\ttype: 'pattern',\n\t\tpattern: compact({\n\t\t\tpreset: pattern.preset,\n\t\t\tfgColor: pattern.foreground ? literalColor(pattern.foreground.effectiveHex) : undefined,\n\t\t\tbgColor: pattern.background ? literalColor(pattern.background.effectiveHex) : undefined,\n\t\t}) ?? { preset: pattern.preset },\n\t}\n}\n","/**\n * `a:blipFill` on a *surface* → the write API's `fill: { type: 'image', image: { data } }`.\n *\n * Shared by a shape's fill and a table cell's, which are the same construct read from two\n * containers: `TableCellProps.fill` and `ShapeProps.fill` are both `ShapeFillProps`, so\n * the mapping is identical and only the note wording differs. Keeping one implementation\n * is what stops the two drifting into different answers for the same `a:blipFill`.\n *\n * The bytes and the blip's opacity carry. Nothing else does, and that is a property of the\n * write path rather than of this mapper: `genXmlImageFill` emits every picture fill as\n * `<a:blipFill dpi=\"0\" rotWithShape=\"1\">…<a:srcRect/><a:stretch><a:fillRect/></a:stretch>`,\n * so a tiled fill comes back stretched and a cropped one comes back whole. That is a\n * visible change, so it is noted when — and only when — the source actually uses it.\n */\nimport type { FillRect, PictureFill } from '../../read/api/picture-fill.js'\nimport type { NoteScope } from '../fidelity.js'\nimport type { AssetRef, IrValue } from '../ir.js'\nimport type { AssetResolver } from './shape.js'\nimport { alphaToTransparency, compactRequired } from './values.js'\n\n/** How a note names the surface it is about; the mapping itself does not vary. */\nexport interface PictureFillSubject {\n\t/** Note construct for a fill whose bytes cannot be carried at all. */\n\tconstruct: string\n\t/** The surface as a note's detail names it — \"this shape's surface\", \"this table cell\". */\n\tsubject: string\n\t/** Where the fill sits in the source XML, for a note's detail. */\n\telement: string\n}\n\n/**\n * A picture fill as `ShapeFillProps`, or `undefined` when its bytes cannot be carried —\n * in which case a `dropped` note has been recorded and the surface comes out unfilled.\n */\nexport function pictureFillOption(\n\tpicture: PictureFill,\n\tassets: AssetResolver,\n\tnotes: NoteScope,\n\tsubject: PictureFillSubject\n): IrValue | undefined {\n\tconst asset = pictureAsset(picture, assets, notes, subject)\n\tif (!asset) return undefined\n\n\tnoteUncarriedGeometry(picture, notes, subject)\n\n\treturn compactRequired({\n\t\ttype: 'image',\n\t\timage: { data: asset },\n\t\t// Fully opaque passes as `undefined` rather than `0`; see `alphaToTransparency`.\n\t\ttransparency: picture.alpha === 1 ? undefined : alphaToTransparency(picture.alpha),\n\t})\n}\n\n/** The fill's image as an asset, or `null` with a note saying why it could not be one. */\nfunction pictureAsset(\n\tpicture: PictureFill,\n\tassets: AssetResolver,\n\tnotes: NoteScope,\n\tsubject: PictureFillSubject\n): AssetRef | null {\n\tconst partName = picture.partName\n\tif (partName === null) {\n\t\tnotes.note(\n\t\t\tsubject.construct,\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t`${subject.subject} is filled with an image (${subject.element}) that embeds no image part — an external or linked blip — so there are no bytes to carry and it comes out unfilled`\n\t\t)\n\t\treturn null\n\t}\n\n\t// The write path refuses an SVG picture fill outright (`src/gen/define/image.ts` warns\n\t// and falls back to `type: 'none'`), so emitting one would produce a script that paints\n\t// nothing while claiming a fill. Checked *before* `assetFor`, which would otherwise\n\t// register bytes that no call ends up referencing.\n\tif (assets.contentTypeOf(partName) === 'image/svg+xml') {\n\t\tnotes.note(\n\t\t\tsubject.construct,\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t`${subject.subject} is filled with an SVG image (${subject.element} → ${partName}); a picture fill accepts raster bytes only on the write side, so it comes out unfilled`\n\t\t)\n\t\treturn null\n\t}\n\n\tconst asset = assets.assetFor(partName)\n\tif (!asset) {\n\t\tnotes.note(\n\t\t\tsubject.construct,\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t`the image filling ${subject.subject} (${subject.element} → ${partName}) is not present in the package, so there are no bytes to carry`\n\t\t)\n\t\treturn null\n\t}\n\treturn asset\n}\n\n/** `true` when a rect actually insets an edge; an explicit but empty rect reports zeros. */\nfunction isRectSet(rect: FillRect | null): boolean {\n\treturn rect !== null && (rect.left !== 0 || rect.top !== 0 || rect.right !== 0 || rect.bottom !== 0)\n}\n\n/**\n * Note the parts of the fill's geometry the write path's fixed stretch cannot express.\n *\n * Only the ones the source actually uses: a note on every picture fill would say nothing,\n * and the round-trip check reads an unmatched note as a candidate for review.\n */\nfunction noteUncarriedGeometry(picture: PictureFill, notes: NoteScope, subject: PictureFillSubject): void {\n\tconst lost: string[] = []\n\tif (picture.mode === 'tile' || picture.tile !== null) lost.push('tiling (a:tile)')\n\tif (isRectSet(picture.srcRect)) lost.push('the source crop (a:srcRect)')\n\tif (isRectSet(picture.fillRect)) lost.push('the destination inset (a:stretch/a:fillRect)')\n\tif (picture.dpi !== null && picture.dpi !== 0) lost.push(`the render resolution (@dpi=\"${picture.dpi}\")`)\n\t// Only the explicit `0`. Unset means \"whatever the application defaults to\", which is\n\t// not a claim this note can make about a difference.\n\tif (picture.rotWithShape === false) lost.push('not rotating with the shape (@rotWithShape=\"0\")')\n\tif (lost.length === 0) return\n\n\tnotes.note(\n\t\t`${subject.construct}.geometry`,\n\t\t'approximated',\n\t\t'unwritable',\n\t\t`the image filling ${subject.subject} is re-embedded, but the write path emits every picture fill as a plain stretched blip (dpi=\"0\" rotWithShape=\"1\", <a:srcRect/><a:stretch><a:fillRect/></a:stretch>), so ${lost.join(', ')} ${lost.length === 1 ? 'does' : 'do'} not carry`\n\t)\n}\n","/**\n * Presence checks for constructs the read model has no accessor for.\n *\n * These reach through the documented raw hatch (`element_`) rather than through a typed\n * accessor, which needs justifying. The rule they follow: **detect, never decode.** Each\n * function answers only \"is this here?\", so the answer can become a {@link FidelityNote}.\n * Nothing here interprets a value or feeds one into a call — that would be building a\n * private read path alongside the public one, and it would rot the moment the element's\n * meaning changed.\n *\n * The alternative is worse than the coupling. Without these checks, a deck with an embedded\n * video converts to a static poster image and a deck with an equation converts to an empty\n * box, both silently and both with a clean round-trip, because a diff cannot see what\n * neither side read. A loss you can name is a bug report; a loss nothing observes is a\n * defect that ships.\n *\n * Each check here is a standing argument for a real accessor. When one lands, the\n * corresponding function should be deleted, not kept in sync.\n */\n\nimport { OOXML_NS } from '../../ooxml/namespaces.js'\n\n/** Office MathML namespace — the equation body itself, wrapped by `a14:m` in a text run. */\nconst MATH_NS = 'http://schemas.openxmlformats.org/officeDocument/2006/math'\n\n/** Shape-tree children that carry drawing content, as opposed to the tree's own properties. */\nconst SHAPE_ELEMENTS = new Set(['sp', 'pic', 'graphicFrame', 'grpSp', 'cxnSp'])\n\n/** A minimal structural view of a DOM element, so this module needs no DOM lib types. */\ninterface ElementLike {\n\tnamespaceURI: string | null\n\tlocalName: string | null\n\tfirstChild: NodeLike | null\n\tgetAttribute(name: string): string | null\n\tgetElementsByTagNameNS(namespaceURI: string, localName: string): { length: number }\n}\n\ninterface NodeLike {\n\tnodeType: number\n\tnextSibling: NodeLike | null\n}\n\nconst ELEMENT_NODE = 1\n\nfunction has(element: unknown, namespaceURI: string, localName: string): boolean {\n\tconst el = element as ElementLike | null\n\tif (!el || typeof el.getElementsByTagNameNS !== 'function') return false\n\treturn el.getElementsByTagNameNS(namespaceURI, localName).length > 0\n}\n\n/**\n * The first *direct* child with this name.\n *\n * A subtree search is wrong for structural lookups, in two ways that both bite here.\n * `a:ext` names two unrelated elements — a shape extent (`@cx`/`@cy`) and an extension-list\n * entry (`@uri`) — so a subtree search finds whichever comes first in document order. And on\n * a group it descends into the group's own children, so a nested group's transform answers\n * for its parent's.\n */\nfunction child(element: ElementLike | null, namespaceURI: string, localName: string): ElementLike | null {\n\tif (!element) return null\n\tfor (let node = element.firstChild; node; node = node.nextSibling) {\n\t\tif (node.nodeType !== ELEMENT_NODE) continue\n\t\tconst el = node as unknown as ElementLike\n\t\tif (el.namespaceURI === namespaceURI && el.localName === localName) return el\n\t}\n\treturn null\n}\n\n/** Every direct element child, as {@link ElementLike}s. */\nfunction children(element: ElementLike | null): ElementLike[] {\n\tif (!element) return []\n\tconst out: ElementLike[] = []\n\tfor (let node = element.firstChild; node; node = node.nextSibling) {\n\t\tif (node.nodeType === ELEMENT_NODE) out.push(node as unknown as ElementLike)\n\t}\n\treturn out\n}\n\n/**\n * `true` when this shape is an embedded audio or video rather than a still picture.\n *\n * PowerPoint authors media as a `p:pic` whose `p:nvPr` carries an `a:videoFile` or\n * `a:audioFile`, with the poster frame as the picture's own blip. The read model reports\n * only the poster — `mediaKind` distinguishes raster from SVG, not still from moving — so\n * without this check a video converts to a static image that looks deliberate.\n */\nexport function isAudioVideo(element: unknown): boolean {\n\treturn has(element, OOXML_NS.a, 'videoFile') || has(element, OOXML_NS.a, 'audioFile')\n}\n\n/**\n * `true` when this shape's text body contains an OMML equation.\n *\n * An equation lives in `m:oMath` inside an `a14:m` run, which contributes nothing to\n * `TextFrame.text`, so an equation-only shape reads as an empty text frame. The write API\n * *can* author one (`TextProps.math`, plus the `ts-pptx/math` subpath for LaTeX/MathML\n * input), which makes this a read-side gap rather than a hard limit.\n */\nexport function hasEquation(element: unknown): boolean {\n\treturn has(element, MATH_NS, 'oMath')\n}\n\n/**\n * `true` when this `p:sp` is a text box rather than an auto shape.\n *\n * The discriminator is one attribute, `p:cNvSpPr/@txBox`, and nothing reads it. The\n * tempting substitute — \"it has no preset geometry\" — is wrong for the common case:\n * PowerPoint gives every text box an explicit `<a:prstGeom prst=\"rect\"/>`, so that test\n * calls every real text box an auto shape. The difference is not cosmetic. PowerPoint\n * autofits, wraps and resizes a text box by different rules, and offers a different\n * right-click menu for it.\n *\n * Direct child rather than a subtree search: `p:cNvSpPr` sits under `p:nvSpPr`, and a group\n * would otherwise answer for its first child.\n */\nexport function isTextBox(element: unknown): boolean {\n\tconst nvSpPr = child(element as ElementLike | null, OOXML_NS.p, 'nvSpPr')\n\treturn child(nvSpPr, OOXML_NS.p, 'cNvSpPr')?.getAttribute('txBox') === '1'\n}\n\n/**\n * `true` when a group's child coordinate space equals its own frame, so its children are\n * already in slide-absolute units.\n *\n * `addGroup` always emits an identity child space; a source group whose `a:chOff`/`a:chExt`\n * differ scales or shifts its contents, and that behaviour cannot be reproduced. The read\n * model has no accessor for the child space — `absoluteFrame` deliberately composes it away,\n * which is right for locating a shape and wrong for spotting this difference.\n *\n * A group with no explicit transform inherits an identity one, so a missing `a:xfrm` is\n * `true` rather than unknown.\n */\nexport function hasIdentityChildSpace(element: unknown): boolean {\n\tconst xfrm = child(child(element as ElementLike | null, OOXML_NS.p, 'grpSpPr'), OOXML_NS.a, 'xfrm')\n\tif (!xfrm) return true\n\n\tconst off = child(xfrm, OOXML_NS.a, 'off')\n\tconst ext = child(xfrm, OOXML_NS.a, 'ext')\n\tconst chOff = child(xfrm, OOXML_NS.a, 'chOff')\n\tconst chExt = child(xfrm, OOXML_NS.a, 'chExt')\n\tif (!off || !ext || !chOff || !chExt) return true\n\n\treturn (\n\t\toff.getAttribute('x') === chOff.getAttribute('x') &&\n\t\toff.getAttribute('y') === chOff.getAttribute('y') &&\n\t\text.getAttribute('cx') === chExt.getAttribute('cx') &&\n\t\text.getAttribute('cy') === chExt.getAttribute('cy')\n\t)\n}\n\n/**\n * `true` when this theme declares an `a:fmtScheme`.\n *\n * The format scheme holds the three fill, three line and three effect style lists a shape's\n * `p:style` indexes into. Neither half of the library touches it: nothing reads it, and the\n * write path emits a hardcoded Office one. So a deck whose theme carries a custom format\n * scheme is repainted with Office's, and this is the only way to notice.\n */\nexport function hasFormatScheme(element: unknown): boolean {\n\treturn has(element, OOXML_NS.a, 'fmtScheme')\n}\n\n/**\n * `true` when this slide master declares per-level text styles (`p:txStyles`) with content.\n *\n * `SlideMasterProps.textStyles` can author them, so this is purely a read-side gap — the\n * default size, face, colour and bullet of every placeholder level is invisible to the\n * converter and comes back as PowerPoint's built-in default.\n */\nexport function hasTextStyles(element: unknown): boolean {\n\tconst txStyles = child(element as ElementLike | null, OOXML_NS.p, 'txStyles')\n\treturn children(txStyles).some((group) => children(group).length > 0)\n}\n\n/**\n * `true` when this shape is a placeholder — the tier that *reserves* a region for a slide to\n * fill, as opposed to the decoration that is drawn as-is.\n *\n * A DOM predicate rather than `shape.placeholder !== null`, and that is not an oversight: only\n * `AutoShape` reports a `p:ph` through the read model, so the model-based spelling would call\n * a *picture* placeholder (`p:nvPicPr/p:nvPr/p:ph`, which PowerPoint does author) decoration\n * and re-draw it as a fixed image on every slide bound to the layout.\n *\n * Not a direct-child lookup, unlike its neighbours: the `p:ph` sits two or three levels down\n * inside whichever `p:nv*Pr` the shape kind uses. That means a *group* containing a\n * placeholder answers `true` for its child, which is the wanted answer anyway — a group is\n * never itself a placeholder, and a layout that put one inside a group is one whose grouping\n * cannot survive being flattened into loose objects.\n */\nexport function isPlaceholderShape(element: unknown): boolean {\n\treturn has(element, OOXML_NS.p, 'ph')\n}\n\n/**\n * `true` when this master or layout carries a shape that is not a placeholder — a logo, a\n * rule, a background image, a footer graphic.\n *\n * Only the **master** arm still needs this. A layout's decoration is now transcribed into its\n * `defineSlideMaster({ objects })` call, so what did not survive is reported per shape rather\n * than as a blanket count. A master's cannot be: `defineSlideMaster` authors a *layout* under\n * the one shared master, so a master's own shape tree has no write-side counterpart at all,\n * and a deck whose master carries none loses nothing — which is why this is a presence check\n * rather than an unconditional note.\n */\nexport function hasDecorativeShapes(element: unknown): boolean {\n\tconst spTree = child(child(element as ElementLike | null, OOXML_NS.p, 'cSld'), OOXML_NS.p, 'spTree')\n\treturn children(spTree).some(\n\t\t(shape) =>\n\t\t\tshape.namespaceURI === OOXML_NS.p && SHAPE_ELEMENTS.has(shape.localName ?? '') && !isPlaceholderShape(shape)\n\t)\n}\n","/**\n * `TextFrame` → `addText(TextProps[], TextPropsOptions)`.\n *\n * Two structural mismatches shape this mapper, and both are why the conversion is not a\n * field-by-field copy:\n *\n * 1. **The read model is a tree; `addText` takes a flat list.** OOXML nests runs inside\n * paragraphs; `TextProps[]` is one flat array where a paragraph boundary is a\n * `breakLine` flag on the item that *precedes* it. So the last run of each paragraph\n * carries the break, and a paragraph's own properties are replicated onto each of its\n * runs — the write path reads alignment and spacing off whichever run starts a line.\n *\n * 2. **Vocabularies differ on both sides of the same concept.** OOXML spells alignment\n * `l`/`ctr`/`r`/`just`, the write API spells it `left`/`center`/`right`/`justify`; two\n * of the six `@algn` values have no write spelling at all. Every such translation is a\n * table here rather than a pass-through, so an unmappable token produces a note instead\n * of an invalid option.\n *\n * Run-level reads prefer the *explicit* value over the resolved one, but only where leaving\n * the option out really does leave the value inherited. That is the part worth checking\n * rather than assuming: the round-trip harness found that an omitted run colour and an\n * omitted vertical anchor are both filled in by the write path — black, and centred — so\n * \"stay quiet and let it inherit\" was silently repainting text and re-anchoring bodies. Both\n * now emit the *resolved* value with a note, which freezes it against a later theme edit and\n * renders correctly, in preference to staying faithful in the IR and wrong on the slide.\n */\nimport type { BodyProperties, BulletDetail, BulletStyle, Paragraph, Run, TextFrame } from '../../read/api/text.js'\nimport type { NoteScope } from '../fidelity.js'\nimport type { IrValue } from '../ir.js'\nimport { compact, isWritableSchemeToken, literalColor, orUndefined, pointsToInches } from './values.js'\n\n/**\n * `a:pPr/@algn` → `HAlign`. `dist` and `thaiDist` (distributed justification) are\n * deliberately absent: the write API has no spelling for them, and mapping them onto\n * `justify` would be a silent visual change rather than a declared loss.\n */\nconst ALIGN: Record<string, string> = { l: 'left', ctr: 'center', r: 'right', just: 'justify' }\n\n/** `a:bodyPr/@anchor` → `VAlign`. */\nconst ANCHOR: Record<string, string> = { t: 'top', ctr: 'middle', b: 'bottom' }\n\n/** `AutofitMode` → the write API's `fit`. */\nconst FIT: Record<string, string> = { none: 'none', normAutofit: 'shrink', spAutoFit: 'resize' }\n\n/** `a:bodyPr/@vert` values the write API's `vert` accepts (`TextVertType`). */\nconst WRITABLE_VERT = new Set(['eaVert', 'horz', 'mongolianVert', 'vert', 'vert270', 'wordArtVert', 'wordArtVertRtl'])\n\n/**\n * The `a:buAutoNum/@type` values the write API's `numberType` names.\n *\n * This used to be the *discriminator* between a numbered and a character bullet, back when\n * the read model reported both as one tagged string. `BulletDetail.kind` does that now, so\n * the set has one job left: telling a scheme the write path can spell from one it cannot.\n */\nconst AUTO_NUMBER_TYPES = new Set([\n\t'alphaLcParenBoth',\n\t'alphaLcParenR',\n\t'alphaLcPeriod',\n\t'alphaUcParenBoth',\n\t'alphaUcParenR',\n\t'alphaUcPeriod',\n\t'arabicParenBoth',\n\t'arabicParenR',\n\t'arabicPeriod',\n\t'arabicPlain',\n\t'romanLcParenBoth',\n\t'romanLcParenR',\n\t'romanLcPeriod',\n\t'romanUcParenBoth',\n\t'romanUcParenR',\n\t'romanUcPeriod',\n])\n\n/**\n * `Paragraph.bulletDetail` → the write API's `bullet` option.\n *\n * This function used to take a **tagged** string — `'none'`, `'char:<glyph>'` or\n * `'autoNum:<type>'` — and its first version read it as a bare glyph. The result was silent\n * and universal: a paragraph that explicitly suppressed its bullet (`a:buNone`, which is most\n * of them) came back with a literal `n` bullet, because `'none'.codePointAt(0)` is `n`; a real\n * character bullet came back as `c`, from the `char:` tag; and a numbered list came back as\n * `a`. Every converted deck was affected and nothing failed, which is why the round-trip check\n * exists — and why the accessor is now a discriminated union with no parsing left to get wrong.\n */\nfunction bulletOption(bullet: BulletDetail, notes: NoteScope): IrValue {\n\t// Explicit suppression, and it must stay explicit: an omitted `bullet` lets the\n\t// destination list style put one back.\n\tif (bullet.kind === 'none') return false\n\n\t// A picture bullet's bytes would have to be re-embedded through the asset resolver, which\n\t// the paragraph mapper does not carry — `addText`'s `bullet.image` could author it.\n\tif (bullet.kind === 'picture') {\n\t\tnotes.note(\n\t\t\t'text.bullet.picture',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t'this paragraph uses an image as its bullet glyph (a:buBlip); the text mapper has no asset resolver to re-embed it with, so the bullet falls back to the default character'\n\t\t)\n\t\treturn true\n\t}\n\n\tconst style = bulletStyle(bullet, notes)\n\n\tif (bullet.kind === 'autoNum') {\n\t\tif (!AUTO_NUMBER_TYPES.has(bullet.scheme)) {\n\t\t\tnotes.note(\n\t\t\t\t'text.bullet.numberType',\n\t\t\t\t'approximated',\n\t\t\t\t'unwritable',\n\t\t\t\t`numbering scheme \"${bullet.scheme}\" is outside the set the write API names, so the list falls back to the default scheme`\n\t\t\t)\n\t\t\treturn compact({ type: 'number', ...startAtOption(bullet.startAt), ...style }) ?? { type: 'number' }\n\t\t}\n\t\treturn (\n\t\t\tcompact({ type: 'number', numberType: bullet.scheme, ...startAtOption(bullet.startAt), ...style }) ?? {\n\t\t\t\ttype: 'number',\n\t\t\t}\n\t\t)\n\t}\n\n\t// Zero-padded to four digits, and that is load-bearing rather than cosmetic: the write\n\t// path tests `characterCode` against /^[0-9A-Fa-f]{4}$/ and, on a miss, warns to the\n\t// console and substitutes its own default glyph. So \"6E\" — a perfectly good code point —\n\t// silently became a different bullet character, visible only in the rendered slide.\n\tconst code = bullet.char.codePointAt(0) ?? 0x2022\n\tif (code > 0xffff) {\n\t\tnotes.note(\n\t\t\t'text.bullet.glyph',\n\t\t\t'approximated',\n\t\t\t'unwritable',\n\t\t\t`bullet glyph U+${code.toString(16).toUpperCase()} is outside the Basic Multilingual Plane and characterCode takes a four-digit code, so the bullet falls back to the write path's default glyph`\n\t\t)\n\t}\n\treturn compact({ characterCode: code.toString(16).toUpperCase().padStart(4, '0'), ...style }) ?? {}\n}\n\n/**\n * `a:pPr/@marL` / `@indent` → `paraMarginLeft` / `paraIndent`.\n *\n * A stated margin carries as its number. An *absent* one is the interesting case, because\n * leaving the key out does not reproduce it: every `bullet` state except `'inherit'` makes the\n * write path put a margin on the element — its hanging default for a drawn bullet, zero for\n * `bullet: false` — so a paragraph that inherits its margin has to ask for silence explicitly.\n * Under `bullet: 'inherit'` nothing is written either way and the key would be noise, which is\n * why the bullet option decides rather than the paragraph being asked twice.\n * @param {number|null} valuePt - the paragraph's own margin in points, `null` when unset\n * @param {IrValue} bulletValue - the `bullet` option this paragraph maps onto\n * @return {IrValue|undefined} the option value, or `undefined` to leave the key out\n */\nfunction paraMarginOption(valuePt: number | null, bulletValue: IrValue): IrValue | undefined {\n\tif (valuePt !== null) return valuePt\n\treturn bulletValue === 'inherit' ? undefined : 'inherit'\n}\n\n/**\n * `a:buAutoNum/@startAt` → `numberStartAt`.\n *\n * Numbering is content rather than styling: a list continuing \"5. Deploy\" that comes back as\n * \"1. Deploy\" is a different slide. `1` is the schema default, so emitting it would only add\n * noise to the printed script.\n */\nfunction startAtOption(startAt: number | null): Record<string, IrValue> {\n\treturn startAt === null || startAt === 1 ? {} : { numberStartAt: startAt }\n}\n\n/**\n * The bullet's own font, size and colour (`a:buFont` / `a:buSzPct` / `a:buClr`) as the write\n * API's `fontFace` / `size` / `color`.\n *\n * `a:buSzPts` has no write-API counterpart — `bullet.size` is a percentage of the run size —\n * so an absolute bullet size is the one part of this that still cannot carry.\n */\nfunction bulletStyle(bullet: BulletStyle, notes: NoteScope): Record<string, IrValue> {\n\tif (bullet.sizePt !== null) {\n\t\tnotes.note(\n\t\t\t'text.bullet.sizePt',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'this bullet sets an absolute glyph size (a:buSzPts); bullet.size is a percentage of the run size, so the absolute value has no write-API expression and the glyph follows the text size'\n\t\t)\n\t}\n\n\t// 25–400% is the range the write path accepts; outside it the option is rejected with a\n\t// console warning and the glyph silently falls back to full size, so it is declared here.\n\tconst sizePct = bullet.sizePct\n\tif (sizePct !== null && (sizePct < 25 || sizePct > 400)) {\n\t\tnotes.note(\n\t\t\t'text.bullet.sizePct',\n\t\t\t'approximated',\n\t\t\t'unwritable',\n\t\t\t`bullet glyph size ${sizePct}% is outside the 25–400% range the write API accepts, so no a:buSzPct is emitted and the glyph size is left to be inherited`\n\t\t)\n\t}\n\n\treturn (\n\t\tcompact({\n\t\t\tfontFace: orUndefined(bullet.font),\n\t\t\tsize: sizePct === null || sizePct < 25 || sizePct > 400 ? undefined : sizePct,\n\t\t\tcolor: bulletColor(bullet, notes),\n\t\t}) ?? {}\n\t)\n}\n\n/**\n * The bullet's colour, preferring the raw `schemeClr` token over the resolved literal for the\n * same reason {@link runColor} does: a token keeps tracking the destination theme.\n */\nfunction bulletColor(bullet: BulletStyle, notes: NoteScope): string | undefined {\n\tconst scheme = bullet.schemeColor\n\tif (isWritableSchemeToken(scheme)) return scheme as string\n\tif (bullet.color !== null) return literalColor(bullet.color)\n\tconst resolved = bullet.resolvedColor\n\tif (!resolved) return undefined\n\tif (scheme !== null) {\n\t\tnotes.note(\n\t\t\t'text.bullet.schemeToken',\n\t\t\t'approximated',\n\t\t\t'unwritable',\n\t\t\t`bullet scheme colour \"${scheme}\" is outside the ten tokens the write path maps, so it is baked to a literal hex and stops tracking the theme`\n\t\t)\n\t}\n\treturn literalColor(resolved.effectiveHex)\n}\n\n/**\n * Per-run character formatting, shared by shape text and table-cell text.\n *\n * The three decoration tokens carry their **explicit off** — `u=\"none\"`, `strike=\"noStrike\"`,\n * `cap=\"none\"` — rather than collapsing it into the unstated case. Stating one is a different\n * fact from stating nothing: run properties resolve down the `a:lstStyle` → placeholder →\n * layout → master chain, so a run that would take `u=\"sng\"` from its list style and states\n * `u=\"none\"` is *not* underlined, while the same run with the attribute dropped is. Only an\n * absent attribute (`null` here) means \"state nothing\"; each off token is a member of its\n * enumeration in its own right (ECMA-376 §20.1.10.81 / §20.1.10.78) and would be redundant\n * with omission otherwise.\n */\nexport function runOptions(run: Run, notes: NoteScope): Record<string, IrValue> | undefined {\n\tconst underline = run.underline\n\n\treturn compact({\n\t\tbold: orUndefined(run.bold),\n\t\titalic: orUndefined(run.italic),\n\t\tunderline: underline === null ? undefined : { style: underline },\n\t\tstrike: orUndefined(run.strike),\n\t\tfontSize: orUndefined(run.fontSizePt),\n\t\tfontFace: orUndefined(run.fontName),\n\t\tcolor: runColor(run, notes),\n\t\thighlight: run.highlight ? literalColor(run.highlight.effectiveHex) : undefined,\n\t\tcaps: orUndefined(run.caps),\n\t\t// The write API spells baseline shift as a percentage, the same unit the read\n\t\t// model reports, so superscript/subscript survive without a preset round-trip.\n\t\tbaseline: orUndefined(run.baselinePct),\n\t\thyperlink: hyperlinkOption(run),\n\t})\n}\n\n/**\n * A run's colour, preferring the raw `schemeClr` token over the resolved literal so the\n * text keeps tracking the destination theme. Only the ten tokens the write path's `clrMap`\n * covers survive as tokens; the other seven degrade to a literal hex there anyway, so\n * passing one through unchanged would produce a silently different colour.\n */\nfunction runColor(run: Run, notes: NoteScope): string | undefined {\n\tconst scheme = run.schemeColor\n\tif (isWritableSchemeToken(scheme)) return scheme as string\n\tif (scheme !== null) {\n\t\tnotes.note(\n\t\t\t'text.color.schemeToken',\n\t\t\t'approximated',\n\t\t\t'unwritable',\n\t\t\t`scheme colour \"${scheme}\" is outside the ten tokens the write path maps, so it is baked to a literal hex and stops tracking the theme`\n\t\t)\n\t\tconst resolved = run.resolvedColor\n\t\treturn resolved ? literalColor(resolved.effectiveHex) : undefined\n\t}\n\tif (run.color !== null) return literalColor(run.color)\n\n\t// A run with no colour of its own inherits one, and leaving the option out does *not* pass\n\t// that inheritance along: `addText` fills an uncoloured non-placeholder run with\n\t// DEF_FONT_COLOR, so omitting it repaints the text black. That makes this a loss either\n\t// way, and which loss depends on whether the inherited colour can be resolved — so the two\n\t// outcomes are declared separately rather than under one note that would overstate one and\n\t// understate the other.\n\tconst inherited = run.resolvedColor\n\tif (!inherited) {\n\t\tnotes.note(\n\t\t\t'text.color.default',\n\t\t\t'approximated',\n\t\t\t'unread',\n\t\t\t'this run inherits its colour and nothing resolves what it inherits (a table style tier, or a list style the read model does not walk), so the write path paints it black — the one case where the output colour is not merely frozen but possibly wrong'\n\t\t)\n\t\treturn undefined\n\t}\n\tnotes.note(\n\t\t'text.color.inherited',\n\t\t'flattened',\n\t\t'unsupported',\n\t\t'this run inherits its colour from the placeholder, master or theme; the write path paints an uncoloured run black instead of leaving it to inherit, so the inherited colour is resolved and baked in and no longer tracks a theme change'\n\t)\n\treturn literalColor(inherited.effectiveHex)\n}\n\n/**\n * A run's hyperlink. Only external links map: the read model reports an internal jump as a\n * target part name, while the write API takes a slide *number*, which the deck-level walk\n * resolves — so a slide link is handled there, not here.\n */\nfunction hyperlinkOption(run: Run): IrValue | undefined {\n\tconst link = run.hyperlink\n\tif (!link?.url) return undefined\n\treturn compact({ url: link.url, tooltip: link.tooltip ?? undefined })\n}\n\n/** Paragraph-level properties, replicated onto each of the paragraph's runs. */\nfunction paragraphOptions(paragraph: Paragraph, notes: NoteScope): Record<string, IrValue> {\n\tconst spacing = paragraph.lineSpacing\n\tconst bullet = paragraph.bulletDetail\n\tconst align = paragraph.align\n\n\tif (align !== null && !(align in ALIGN)) {\n\t\tnotes.note(\n\t\t\t'text.align',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t`distributed alignment \"${align}\" has no write-API spelling, so the paragraph falls back to its inherited alignment`\n\t\t)\n\t}\n\tif (paragraph.spaceBeforePt === 0 || paragraph.spaceAfterPt === 0) {\n\t\tnotes.note(\n\t\t\t'text.paraSpaceZero',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'this paragraph explicitly sets zero space before or after (a:spcBef / a:spcAft of 0), which suppresses the spacing its list style would otherwise apply; the write path treats 0 as \"unset\" and emits nothing, so the inherited spacing comes back'\n\t\t)\n\t}\n\t// `text.indent` used to be filed here — a paragraph's own `a:pPr/@marL` and `@indent` had no\n\t// write option at all, so every margin it stated was replaced by whatever the `bullet` state\n\t// wrote. `paraMarginLeft` / `paraIndent` state them now, so the mapper carries the values\n\t// instead of excusing their loss and the note is gone rather than unmapped.\n\tconst bulletValue = bullet === null ? 'inherit' : bulletOption(bullet, notes)\n\n\treturn (\n\t\tcompact({\n\t\t\talign: align === null ? undefined : ALIGN[align],\n\t\t\tindentLevel: paragraph.level === 0 ? undefined : paragraph.level,\n\t\t\tparaMarginLeft: paraMarginOption(paragraph.marginLeftPt, bulletValue),\n\t\t\tparaIndent: paraMarginOption(paragraph.indentPt, bulletValue),\n\t\t\tparaSpaceBefore: orUndefined(paragraph.spaceBeforePt),\n\t\t\tparaSpaceAfter: orUndefined(paragraph.spaceAfterPt),\n\t\t\tlineSpacing: spacing?.type === 'points' ? spacing.valuePt : undefined,\n\t\t\tlineSpacingMultiple: spacing?.type === 'percent' ? spacing.percent / 100 : undefined,\n\t\t\t// A paragraph with no bullet child of its own states nothing, and `'inherit'` is\n\t\t\t// how the write path says that. `undefined` would NOT do — an omitted `bullet`\n\t\t\t// emits an explicit `a:buNone`, which suppresses whatever the destination list\n\t\t\t// style has. That was this converter's most frequent loss (`text.bullet.inherited`,\n\t\t\t// 34 of 44 corpus fixtures) until the option gained a third state. Resolved above\n\t\t\t// rather than here: the margin keys need to know which bullet state was chosen, and\n\t\t\t// calling `bulletOption` twice would file its notes twice.\n\t\t\tbullet: bulletValue,\n\t\t}) ?? {}\n\t)\n}\n\n/**\n * Flatten a text frame into the `TextProps[]` first argument of `addText`.\n *\n * An empty paragraph becomes an item with empty text and a `breakLine`, which is how a\n * blank line survives — dropping it would silently close up vertical space the author put\n * there deliberately.\n */\nexport function textRuns(frame: TextFrame, notes: NoteScope): IrValue[] {\n\tconst paragraphs = frame.paragraphs\n\tconst items: IrValue[] = []\n\n\tparagraphs.forEach((paragraph, paragraphIndex) => {\n\t\tconst paraOpts = paragraphOptions(paragraph, notes)\n\t\tconst runs = paragraph.runs\n\t\t// The paragraph break rides on the last run of every paragraph but the final one;\n\t\t// a trailing break would add an empty line the frame never had.\n\t\tconst breaks = paragraphIndex < paragraphs.length - 1\n\n\t\tif (runs.length === 0) {\n\t\t\titems.push({ text: '', options: compact({ ...paraOpts, breakLine: breaks }) ?? {} })\n\t\t\treturn\n\t\t}\n\n\t\truns.forEach((run, runIndex) => {\n\t\t\tconst isLastRun = runIndex === runs.length - 1\n\t\t\t// `bullet` goes on the first run only, unlike the other paragraph properties. The\n\t\t\t// write path treats a bullet on a run that is *not* starting a line as a request for\n\t\t\t// a new paragraph — and clears that run's `breakLine` while it is at it — so\n\t\t\t// replicating the bullet split every bulleted paragraph that had more than one run.\n\t\t\t// It reads paragraph properties off whichever run opens the line, so once is enough.\n\t\t\tconst continuation = { ...paraOpts }\n\t\t\tdelete continuation['bullet']\n\t\t\tconst options = compact({\n\t\t\t\t...(runIndex === 0 ? paraOpts : continuation),\n\t\t\t\t...runOptions(run, notes),\n\t\t\t\t...(isLastRun && breaks ? { breakLine: true } : {}),\n\t\t\t})\n\t\t\titems.push(compact({ text: run.text, options }) ?? { text: run.text })\n\t\t})\n\t})\n\n\treturn items\n}\n\n/**\n * Frame-level layout for the `TextPropsOptions` second argument — everything that belongs\n * to the body as a whole rather than to any paragraph.\n *\n * `resolvedAnchor` is the one place a *resolved* read is the right one: vertical anchoring\n * has no per-run fallback, so an unset `a:bodyPr/@anchor` genuinely means \"whatever the\n * placeholder says\", and an appended shape does not inherit that.\n */\nexport function textFrameOptions(frame: TextFrame, notes: NoteScope): Record<string, IrValue> {\n\tconst body = frame.bodyProperties\n\tconst anchor = frame.resolvedAnchor\n\tconst vert = body?.vert ?? null\n\n\tif (vert !== null && !WRITABLE_VERT.has(vert)) {\n\t\tnotes.note(\n\t\t\t'text.vert',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t`text direction \"${vert}\" is outside TextVertType, so the body falls back to horizontal`\n\t\t)\n\t}\n\n\treturn (\n\t\tcompact({\n\t\t\t// Spelled out even when nothing in the source set it. `resolvedAnchor` returning\n\t\t\t// null means PowerPoint would default the body to top — but `addText` defaults a\n\t\t\t// non-placeholder body to *centre*, so leaving the option out re-anchors the text.\n\t\t\tvalign: anchor === null ? 'top' : ANCHOR[anchor],\n\t\t\t// `@wrap` is `square`/`none` in OOXML and a boolean in the write API.\n\t\t\twrap: body?.wrap === null || body?.wrap === undefined ? undefined : body.wrap !== 'none',\n\t\t\tvert: vert !== null && WRITABLE_VERT.has(vert) ? vert : undefined,\n\t\t\tfit: fitOption(frame, notes),\n\t\t\tmargin: marginOption(body),\n\t\t}) ?? {}\n\t)\n}\n\n/**\n * `a:bodyPr`'s autofit as the write API's `fit`.\n *\n * A `normAutofit` that bakes `fontScale` or `lnSpcReduction` is a *different state* from a\n * bare `<a:normAutofit/>`, so the two get different spellings. ECMA-376 §21.1.2.1.3 defaults\n * each attribute to 100%/0% only when it is **omitted**; PowerPoint recomputes an unbaked\n * scale on edit and draws the baked one exactly as written until then. Flattening both to\n * `'shrink'` therefore re-emits a frame that paints its text at full size — a deck baked at\n * `fontScale=\"40000\"` comes back two and a half times too large — and the object form is\n * already what the write API accepts, so nothing has to be lost here.\n *\n * Out-of-range percentages are the one arm that still loses something. The write path rejects\n * anything outside 0–100 and drops the attribute with a warning, so passing one through would\n * turn a declared loss into a silent one; the frame falls back to bare `'shrink'` with a note.\n */\nfunction fitOption(frame: TextFrame, notes: NoteScope): IrValue | undefined {\n\tconst autofit = frame.autofit\n\tif (autofit === null) return undefined\n\tif (autofit !== 'normAutofit') return FIT[autofit]\n\n\tconst baked = compact({\n\t\tfontScale: bakedPct(frame.autofitFontScale, 'fontScale', notes),\n\t\tlnSpcReduction: bakedPct(frame.autofitLineSpaceReduction, 'lnSpcReduction', notes),\n\t})\n\treturn baked ? { type: 'shrink', ...baked } : FIT[autofit]\n}\n\n/** A baked `a:normAutofit` percentage, or `undefined` (with a note) when the write API would reject it. */\nfunction bakedPct(value: number | null, name: string, notes: NoteScope): number | undefined {\n\tif (value === null) return undefined\n\tif (value >= 0 && value <= 100) return value\n\tnotes.note(\n\t\t`text.autofit.${name}`,\n\t\t'dropped',\n\t\t'unwritable',\n\t\t`baked a:normAutofit/@${name} of ${value}% is outside the 0-100 the write API accepts, so the frame re-emits a bare <a:normAutofit/>`\n\t)\n\treturn undefined\n}\n\n/**\n * `a:bodyPr` insets as the write API's `margin`.\n *\n * A unit change, not just a copy: the read model reports insets in points, `margin` takes\n * **inches**, and it warns on any value `>= 1` on the assumption it is a stray points\n * value. Passing points straight through would therefore both inset the text by roughly\n * 72× too much and trip that warning.\n *\n * Emitted as the four-tuple whenever any inset is set, since a partial tuple is not\n * expressible; an unset side takes PowerPoint's own default rather than zero, so those are\n * spelled out — defaulting them to 0 would visibly reflow every body that sets one side.\n */\nconst DEFAULT_INSETS_PT = { left: 7.2, right: 7.2, top: 3.6, bottom: 3.6 }\n\nfunction marginOption(body: BodyProperties | null): IrValue | undefined {\n\tconst insets = body?.insetsPt\n\tif (!insets) return undefined\n\tconst { left, right, top, bottom } = insets\n\tif (left === undefined && right === undefined && top === undefined && bottom === undefined) return undefined\n\treturn [\n\t\tpointsToInches(top ?? DEFAULT_INSETS_PT.top),\n\t\tpointsToInches(right ?? DEFAULT_INSETS_PT.right),\n\t\tpointsToInches(bottom ?? DEFAULT_INSETS_PT.bottom),\n\t\tpointsToInches(left ?? DEFAULT_INSETS_PT.left),\n\t]\n}\n","/**\n * `Table` → `addTable(TableRow[], TableProps)`.\n *\n * Tables are the one place the exact-EMU rule stops. `colW` and `rowH` are number-typed\n * (inches) rather than `Coord`-typed, so they cannot take a raw-EMU string the way every\n * position and size can. They print at six decimal places, which is the measured minimum\n * at which `Math.round(inches × 914400)` returns the original EMU — the drift is bounded\n * at 0.4572 EMU, roughly half a millionth of an inch, and rounding shorter to make the\n * numbers look tidy would turn a cosmetic problem into a real geometry loss.\n *\n * Table *style* is the opposite story, and better than it looks. A style is a GUID into\n * the deck's `ppt/tableStyles.xml`, and a template-anchored output keeps that part intact,\n * so passing the source GUID through reproduces the banding, header shading, and borders\n * exactly rather than approximately. That is why per-cell fills read off the style graph\n * are deliberately *not* baked into each cell here: doing so would freeze the appearance\n * and stop the table responding to its own style.\n */\nimport type { CellBorder, Table, TableCell } from '../../read/api/table.js'\nimport type { GraphicFrame } from '../../read/api/shapes.js'\nimport type { NoteScope } from '../fidelity.js'\nimport type { CallIr, IrValue } from '../ir.js'\nimport type { AssetResolver } from './shape.js'\nimport { compact, inches, literalColor, orUndefined, positionOfFrame } from './values.js'\nimport { pictureFillOption, type PictureFillSubject } from './picture-fill.js'\nimport { gradientStops, patternOption } from './surface-fill.js'\nimport { runOptions, textRuns } from './text.js'\n\n/** How {@link pictureFillOption}'s notes name a cell. */\nconst CELL_PICTURE_FILL: PictureFillSubject = {\n\tconstruct: 'table.cell.fill.picture',\n\tsubject: 'this table cell',\n\telement: 'a:tcPr/a:blipFill',\n}\n\n/** How {@link pictureFillOption}'s notes name the table's own background. */\nconst TABLE_PICTURE_FILL: PictureFillSubject = {\n\tconstruct: 'table.fill.picture',\n\tsubject: 'this table',\n\telement: 'a:tblPr/a:blipFill',\n}\n\n/** `a:tcPr/@anchor` → the write API's `valign`. */\nconst ANCHOR: Record<string, string> = { t: 'top', ctr: 'middle', b: 'bottom' }\n\nexport function tableCall(frame: GraphicFrame, table: Table, notes: NoteScope, assets: AssetResolver): CallIr {\n\tconst styleId = table.styleId\n\tconst hasStyle = table.resolvedStyle !== null\n\tconst rows: IrValue[] = []\n\tconst rowHeights: number[] = []\n\n\tfor (const row of table.rows) {\n\t\tconst cells: IrValue[] = []\n\t\tfor (const cell of row.cells) {\n\t\t\t// A merge continuation is the covered half of a span: it carries no content and\n\t\t\t// exists only so the grid stays rectangular. The write path derives those from\n\t\t\t// colspan/rowspan, so emitting them would double-count the span.\n\t\t\tif (cell.isMergeContinuation) continue\n\t\t\tcells.push(cellIr(cell, hasStyle, notes, assets))\n\t\t}\n\t\trows.push(cells)\n\t\trowHeights.push(row.heightEmu ?? 0)\n\t}\n\n\t// A row of height 0 is PowerPoint's \"auto — as tall as its content needs\", not a\n\t// zero-height row, and neither the mixed nor the all-auto case survives the write path.\n\t// Nothing is visibly wrong either way; what is lost is the *implicitness*, which matters\n\t// the moment someone edits a cell and expects the row to grow.\n\t//\n\t// The all-auto case is the more common of the two — a table authored without explicit row\n\t// heights has `a:tr/@h=\"0\"` on every row — and it went undeclared for longer precisely\n\t// because it looks like the harmless one. It is the case where `rowH` is omitted entirely\n\t// below, and `addTable` then divides the frame height evenly rather than leaving the rows\n\t// auto, so three auto rows come back pinned to a third of the frame each.\n\tconst autoRows = rowHeights.filter((height) => height === 0).length\n\tif (autoRows === rowHeights.length && autoRows > 0) {\n\t\tnotes.note(\n\t\t\t'table.rowAuto',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t'every row is auto-height (a:tr/@h of 0), so no rowH is emitted and addTable divides the frame height evenly among the rows; the rows come back pinned to that even split rather than sized to their content'\n\t\t)\n\t} else if (autoRows > 0) {\n\t\tnotes.note(\n\t\t\t'table.rowAuto',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t'at least one row is auto-height (a:tr/@h of 0) while others are not; rowH must be given for every row or none, so the auto rows are emitted as 0 and come back pinned to the height their content produced'\n\t\t)\n\t}\n\n\tif (styleId === null) {\n\t\tnotes.note(\n\t\t\t'table.style',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t\"this table names no a:tableStyleId, so it takes the generated deck's default table style\"\n\t\t)\n\t}\n\n\tconst columnWidths = table.columnWidths\n\tconst options = compact({\n\t\t...positionOfFrame(frame),\n\t\tobjectName: frame.name || undefined,\n\t\t// The source GUID resolves against the destination's own tableStyles.xml, which a\n\t\t// template-anchored output carries over intact.\n\t\ttableStyle: orUndefined(styleId),\n\t\t// `tableFill`, not `fill`: the source has one fill on `a:tblPr`, and `fill` would\n\t\t// flatten it into a copy on every cell, which is a different package for the same\n\t\t// picture. See `TableProps.tableFill`.\n\t\ttableFill: tableFill(table, notes, assets),\n\t\thasHeader: table.firstRowHeader ? true : undefined,\n\t\thasBandedRows: table.bandedRows ? true : undefined,\n\t\tcolW: columnWidths.every((w) => w === null) ? undefined : columnWidths.map((w) => inches(w ?? 0)),\n\t\trowH: rowHeights.every((h) => h === 0) ? undefined : rowHeights.map(inches),\n\t})\n\n\treturn { method: 'addTable', args: [rows, options ?? {}], ...(frame.name ? { sourceName: frame.name } : {}) }\n}\n\n/**\n * The table's own background (`a:tblPr` fill).\n *\n * Simpler than {@link cellFill}, and for one reason: a `a:tblPr` fill can only be the\n * table's own. There is no style graph feeding into it, so there is no\n * own-versus-inherited ambiguity to be careful about and the resolved colour can be used\n * directly. A scheme token still wins over the literal when there is one, so the replica\n * keeps tracking its theme.\n */\nfunction tableFill(table: Table, notes: NoteScope, assets: AssetResolver): IrValue | undefined {\n\tconst gradient = table.gradientFill\n\tif (gradient) {\n\t\tconst stops = gradientStops(gradient, notes, 'table.fill')\n\t\tif (stops) return { type: 'gradient', gradient: stops }\n\t}\n\n\tconst pattern = patternOption(table.patternFill)\n\tif (pattern) return pattern\n\n\tconst picture = table.pictureFill\n\tif (picture) return pictureFillOption(picture, assets, notes, TABLE_PICTURE_FILL)\n\n\tconst scheme = table.fillSchemeColor\n\tif (scheme !== null) return { color: scheme }\n\n\tconst resolved = table.resolvedFill\n\treturn resolved ? { color: literalColor(resolved.effectiveHex) } : undefined\n}\n\n/**\n * One cell as a `TableCell`.\n *\n * Cell text reuses the shape text mapper, so a per-run format inside a cell behaves\n * identically to one on a shape — the read model already shares `TextFrame` between the\n * two, and diverging here would be a difference with no cause.\n */\nfunction cellIr(cell: TableCell, hasStyle: boolean, notes: NoteScope, assets: AssetResolver): IrValue {\n\tconst frame = cell.textFrame\n\tconst anchor = cell.anchor\n\tconst margins = cell.marginsEmu\n\n\t// `a:tc/@id` and `a:tcPr/a:headers` are the one pair here that is *deliberately* not\n\t// mapped. PowerPoint strips both on save (probe:\n\t// `test/read/fixtures/authoring/probe-table-cell-a11y-and-3d.ps1`), so there is no write\n\t// option to map them to and adding one would ship a feature that dies on the first save.\n\t// A source deck from another producer can still carry them, so the loss is recorded.\n\tif (cell.id !== null || cell.headerIds.length > 0) {\n\t\tnotes.note(\n\t\t\t'table.cell.headers',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'this cell carries a screen-reader header association (a:tc/@id / a:tcPr/a:headers); PowerPoint strips both on save, so there is no write option and the association is lost — hasHeader (a:tblPr/@firstRow) is the marker that survives'\n\t\t)\n\t}\n\n\tconst options = compact({\n\t\tfill: cellFill(cell, hasStyle, notes, assets),\n\t\tborder: cellBorders(cell, notes),\n\t\tdiagonal: cellDiagonals(cell, notes),\n\t\tanchorCtr: cell.anchorCtr ? true : undefined,\n\t\tcell3D: cellThreeD(cell),\n\t\tvalign: anchor === null ? undefined : ANCHOR[anchor],\n\t\t// `textDirection` reaches `a:tcPr/@vert` through the same table-cell inheritance list every\n\t\t// other cell option uses, so a vertical label survives the round trip. Anything outside the\n\t\t// option's own union would be written back out verbatim as an invalid attribute.\n\t\ttextDirection: cellTextDirection(cell, notes),\n\t\t// Only the two values the write option accepts survive; anything else in the source\n\t\t// deck would be written straight back out as an invalid attribute.\n\t\thorzOverflow: cell.horzOverflow === 'clip' || cell.horzOverflow === 'overflow' ? cell.horzOverflow : undefined,\n\t\tcolspan: cell.gridSpan > 1 ? cell.gridSpan : undefined,\n\t\trowspan: cell.rowSpan > 1 ? cell.rowSpan : undefined,\n\t\t// `margin` takes inches, and the read model reports the insets in EMU.\n\t\tmargin: margins\n\t\t\t? [inches(margins.top ?? 0), inches(margins.right ?? 0), inches(margins.bottom ?? 0), inches(margins.left ?? 0)]\n\t\t\t: undefined,\n\t\t// A cell's own runs may each carry formatting; the first run's options double as the\n\t\t// cell default, which is how the write path applies cell-level character formatting.\n\t\t...(frame?.paragraphs[0]?.runs[0] ? (runOptions(frame.paragraphs[0].runs[0], notes) ?? {}) : {}),\n\t})\n\n\treturn compact({ text: frame ? textRuns(frame, notes) : cell.text, options }) ?? { text: '' }\n}\n\n/**\n * The two corner-to-corner rules as `TableCellProps.diagonal`.\n *\n * Kept out of {@link cellBorders}' tuple for the same reason the write option is: they are\n * not edges. Every dash and colour a diagonal can carry is one an edge can, so they share\n * {@link borderIr} — including its out-of-enum dash note.\n */\nfunction cellDiagonals(cell: TableCell, notes: NoteScope): IrValue | undefined {\n\tconst borders = cell.borders\n\tif (!borders || (!borders.tlToBr && !borders.blToTr)) return undefined\n\treturn compact({\n\t\ttlToBr: borders.tlToBr ? borderIr(borders.tlToBr, notes) : undefined,\n\t\tblToTr: borders.blToTr ? borderIr(borders.blToTr, notes) : undefined,\n\t})\n}\n\n/**\n * A cell's `a:cell3D` as `TableCellProps.cell3D`.\n *\n * Every field is passed through as read: the write path vets each against its `ST_` union\n * before emission, so a value from a source deck that somehow falls outside one is caught\n * there rather than being screened twice with two chances to disagree. Sizes are already in\n * points on both sides.\n */\nfunction cellThreeD(cell: TableCell): IrValue | undefined {\n\tconst cell3D = cell.cell3D\n\tif (!cell3D) return undefined\n\tconst rig = cell3D.lightRig\n\treturn (\n\t\tcompact({\n\t\t\tpreset: orUndefined(cell3D.bevel.preset),\n\t\t\twidth: orUndefined(cell3D.bevel.widthPt),\n\t\t\theight: orUndefined(cell3D.bevel.heightPt),\n\t\t\tmaterial: orUndefined(cell3D.material),\n\t\t\t// CT_LightRig requires both, so a half-specified one from a source deck is dropped\n\t\t\t// rather than passed on for the emitter to reject.\n\t\t\tlightRig: rig?.rig && rig.dir ? { rig: rig.rig, dir: rig.dir } : undefined,\n\t\t}) ?? {}\n\t)\n}\n\n/** The `ST_TextVerticalType` values `TextBaseProps.textDirection` accepts. */\nconst WRITABLE_TEXT_DIRECTIONS = new Set(['horz', 'vert', 'vert270', 'wordArtVert'])\n\n/**\n * A cell's `a:tcPr/@vert` as the write API's `textDirection`.\n *\n * `ST_TextVerticalType` has nine values and the write option covers four. The rest\n * (`eaVert`, `mongolianVert`, the WordArt right-to-left variants) are East-Asian layout\n * modes with no `TextBaseProps` spelling, so they are noted rather than written — passing\n * one straight through would put a value the option does not admit into the attribute.\n */\nfunction cellTextDirection(cell: TableCell, notes: NoteScope): IrValue | undefined {\n\tconst vert = cell.verticalText\n\tif (vert === null || vert === 'horz') return undefined\n\tif (WRITABLE_TEXT_DIRECTIONS.has(vert)) return vert\n\tnotes.note(\n\t\t'table.cell.vert',\n\t\t'dropped',\n\t\t'unwritable',\n\t\t`this cell's a:tcPr/@vert is \\`${vert}\\`, which textDirection does not spell (it covers horz/vert/vert270/wordArtVert), so its text lands horizontal`\n\t)\n\treturn undefined\n}\n\n/**\n * A cell's fill.\n *\n * The question here is not \"what colour is this cell\" but \"what did the *source* say\", and\n * the two differ for a styled table: `resolvedFill` answers the first, folding the cell's\n * own `a:solidFill` together with the colour it merely inherits from the style's\n * header/banding rules. Writing an inherited colour back would turn every banded cell into\n * an explicitly-filled one — the copy looks right until someone changes its table style, and\n * then nothing moves.\n *\n * {@link TableCell.hasOwnFill} separates them: an `a:tcPr` either carries an\n * `EG_FillProperties` child or it does not. So a cell's own fill is emitted (in whatever\n * form it took), and a cell with none is left to the style GUID, which reproduces the\n * banding exactly rather than approximately. Neither case loses anything, which is why\n * neither records a note.\n */\nfunction cellFill(cell: TableCell, hasStyle: boolean, notes: NoteScope, assets: AssetResolver): IrValue | undefined {\n\t// An explicit `a:noFill` is a statement, and the one `EG_FillProperties` member whose\n\t// loss is invisible further down: a suppressed cell reports `null` from every colour\n\t// accessor, so without this it falls out of the bottom as \"no fill option\" and the copy\n\t// takes the style's banding — the opposite of what the source shows. Same distinction\n\t// `lineOption` makes for `lineNoFill` on the shape side.\n\tif (cell.fillNoFill) return { type: 'none' }\n\n\t// Every non-solid choice comes next, and for one shared reason: a cell whose `a:tcPr`\n\t// holds a `a:gradFill`/`a:pattFill`/`a:blipFill` holds no `a:solidFill` for the colour\n\t// legs below to find, so `resolvedFill` would answer with the table style's banding\n\t// colour and paint over the cell with something the source never showed.\n\tconst gradient = cell.gradientFill\n\tif (gradient) {\n\t\tconst stops = gradientStops(gradient, notes, 'table.cell.fill')\n\t\tif (stops) return { type: 'gradient', gradient: stops }\n\t}\n\n\tconst pattern = patternOption(cell.patternFill)\n\tif (pattern) return pattern\n\n\tconst picture = cell.pictureFill\n\tif (picture) return pictureFillOption(picture, assets, notes, CELL_PICTURE_FILL)\n\n\tconst scheme = cell.fillSchemeColor\n\tif (scheme !== null) return { color: scheme }\n\n\t// A styled cell with no fill of its own takes the style's banding, and the style GUID\n\t// travels with the table — so emitting nothing here is not a loss, it is what keeps the\n\t// copy responsive to its own style.\n\tif (hasStyle && !cell.hasOwnFill) return undefined\n\n\tconst resolved = cell.resolvedFill\n\tif (!resolved) return undefined\n\t// Reached only when the cell's fill IS its own: either there is no style to inherit from,\n\t// or `hasOwnFill` said so. The literal is exact for a `srgbClr`, and for the rarer colour\n\t// models (`a:sysClr`, `a:prstClr`, `a:hslClr`, …) it is the colour they resolve to, which\n\t// is the closest the write API's hex option can come.\n\treturn { color: literalColor(resolved.effectiveHex) }\n}\n\n/**\n * The four edge borders as the write API's `[top, right, bottom, left]` tuple.\n *\n * A suppressed edge (`a:noFill`) becomes `type: 'none'`, which is distinct from an absent\n * one — the first means \"deliberately no rule here\", the second means \"inherit\". The two\n * diagonals the read model also decodes are carried separately, by {@link cellDiagonals}.\n */\nfunction cellBorders(cell: TableCell, notes: NoteScope): IrValue | undefined {\n\tconst borders = cell.borders\n\tif (!borders) return undefined\n\n\tconst edges = [borders.top, borders.right, borders.bottom, borders.left]\n\tif (edges.every((edge) => edge === null)) return undefined\n\n\treturn edges.map((edge) => borderIr(edge, notes))\n}\n\n/** The `ST_PresetLineDashVal` tokens `BorderProps.dashType` accepts. */\nconst WRITABLE_DASHES = new Set([\n\t'solid',\n\t'dot',\n\t'dash',\n\t'lgDash',\n\t'dashDot',\n\t'lgDashDot',\n\t'lgDashDotDot',\n\t'sysDash',\n\t'sysDot',\n\t'sysDashDot',\n\t'sysDashDotDot',\n])\n\n/**\n * One decoded edge (or diagonal) as `BorderProps`.\n *\n * `type` stays the coarse on/off switch and `dashType` carries the exact preset, so a\n * `lgDashDot` rule comes back as itself rather than as the generic `sysDash` every dash\n * used to collapse onto. A dash outside `ST_PresetLineDashVal` cannot have come from a\n * conformant deck, so it is dropped to a plain dashed rule and noted.\n */\nfunction borderIr(edge: CellBorder | null, notes: NoteScope): IrValue {\n\tif (!edge) return {}\n\tif (edge.noFill) return { type: 'none' }\n\tconst dash = edge.dash\n\tconst known = dash === null || WRITABLE_DASHES.has(dash)\n\tif (!known) {\n\t\tnotes.note(\n\t\t\t'table.cell.borders.dash',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t`a cell border's a:prstDash/@val is \\`${dash}\\`, which is outside ST_PresetLineDashVal; it is written as a plain dashed rule`\n\t\t)\n\t}\n\treturn (\n\t\tcompact({\n\t\t\ttype: dash === null || dash === 'solid' ? 'solid' : 'dash',\n\t\t\t// `solid` is what an absent/solid dash already implies, so emitting it would be noise.\n\t\t\tdashType: known && dash !== null && dash !== 'solid' ? dash : undefined,\n\t\t\tcolor: edge.schemeColor ?? (edge.color === null ? undefined : literalColor(edge.color)),\n\t\t\twidth: orUndefined(edge.widthPt),\n\t\t}) ?? {}\n\t)\n}\n","/**\n * `Chart` → `addChart(OptsChartData[], ChartOpts)`.\n *\n * The open question this mapper settles is where the data comes from. A `.pptx` chart\n * carries its numbers twice: once in an embedded `.xlsx` workbook, and once as *cached*\n * values inside the chart XML itself (`c:tx`, `c:cat`, `c:val`) so a viewer can render\n * without opening the workbook. Probing the fixtures showed the cache is complete for\n * every chart the write API can express, so the workbook never needs cracking — which\n * removes a whole spreadsheet parser from this project's dependency surface.\n *\n * The one seam is blanks. The read model reports `(number | null)[]`, since a cached point\n * may legitimately be empty, while `OptsChartData.values` is `number[]`. A blank becomes\n * `0`, which is a visible change on a line chart — a gap turns into a dip to the axis — so\n * it is noted rather than quietly coerced.\n *\n * A rebuilt chart also gets a *regenerated* workbook rather than the source one, so\n * double-clicking it in PowerPoint opens data that matches the plot but has lost the source\n * sheet's formulas, extra columns, and formatting.\n */\nimport type { Chart } from '../../read/api/chart.js'\nimport type { GraphicFrame } from '../../read/api/shapes.js'\nimport type { NoteScope } from '../fidelity.js'\nimport type { CallIr, IrValue } from '../ir.js'\nimport { compact, literalColor, orUndefined, positionOfFrame } from './values.js'\n\n/**\n * Read chart-group token → `CHART_NAME`. The read model strips the `Chart` suffix from the\n * plot-area element name, so `c:barChart` arrives as `bar`. A 3-D group maps onto the\n * matching flat type where one exists; anything absent from this table has no write-API\n * chart type and is reported rather than guessed at.\n */\nconst CHART_TYPE: Record<string, string> = {\n\tarea: 'area',\n\tarea3D: 'area',\n\tbar: 'bar',\n\tbar3D: 'bar3D',\n\tbubble: 'bubble',\n\tbubble3D: 'bubble3D',\n\tdoughnut: 'doughnut',\n\tline: 'line',\n\tline3D: 'line',\n\tpie: 'pie',\n\tpie3D: 'pie',\n\tradar: 'radar',\n\tscatter: 'scatter',\n\tstock: 'stock',\n\tsurface: 'surface',\n\tsurface3D: 'surface',\n}\n\n/** `c:legendPos/@val` → the write API's `legendPos`. */\nconst LEGEND_POS: Record<string, string> = { r: 'r', l: 'l', t: 't', b: 'b', tr: 'tr' }\n\nexport function chartCall(frame: GraphicFrame, chart: Chart, notes: NoteScope): CallIr | null {\n\tconst sourceType = chart.chartType\n\tconst type = sourceType === null ? undefined : CHART_TYPE[sourceType]\n\tif (!type) {\n\t\tnotes.note(\n\t\t\t'chart.type',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t`chart type \"${sourceType ?? 'none'}\" has no write-API counterpart, so the chart is omitted`\n\t\t)\n\t\treturn null\n\t}\n\n\tif (chart.chartTypes.length > 1) {\n\t\tnotes.note(\n\t\t\t'chart.combo',\n\t\t\t'flattened',\n\t\t\t'unsupported',\n\t\t\t`a combo chart (${chart.chartTypes.join(' + ')}) is emitted as a single ${type} chart; addChart's multi-type form needs a per-series type the read model does not report`\n\t\t)\n\t}\n\n\tnotes.note(\n\t\t'chart.workbook',\n\t\t'approximated',\n\t\t'unsupported',\n\t\t\"the chart is rebuilt from its cached plot values, so its embedded workbook is regenerated: the plotted numbers match, but the source sheet's formulas, extra columns and formatting are gone\"\n\t)\n\n\tconst data = seriesData(chart, notes)\n\tif (data.length === 0) {\n\t\tnotes.note('chart.data', 'dropped', 'unsupported', 'this chart caches no plottable series values')\n\t\treturn null\n\t}\n\n\t// `type` is an *option*, not a positional argument: the signature is\n\t// `addChart(data, options & { type })`. Passing it separately produces a call that\n\t// typechecks nowhere and throws \"a chart `type` is required\" at run time.\n\tconst options = compact({\n\t\ttype,\n\t\t...positionOfFrame(frame),\n\t\tobjectName: frame.name || undefined,\n\t\t...titleOptions(chart),\n\t\t...legendOptions(chart),\n\t\t...labelOptions(chart),\n\t\t...axisOptions(chart),\n\t\tchartColors: seriesColors(chart),\n\t})\n\n\treturn {\n\t\tmethod: 'addChart',\n\t\targs: [data, options ?? { type }],\n\t\t...(frame.name ? { sourceName: frame.name } : {}),\n\t}\n}\n\n/**\n * Series as `OptsChartData[]`. Category labels ride on the first series, which is the shape\n * `addChart` expects; the read model reports them per-series but they are shared in\n * practice.\n */\nfunction seriesData(chart: Chart, notes: NoteScope): IrValue[] {\n\tconst categories = chart.categories.map((label) => label ?? '')\n\tlet sawBlank = false\n\n\tconst data = chart.series.map((series, index) => {\n\t\tconst values = series.values.map((value) => {\n\t\t\tif (value === null) sawBlank = true\n\t\t\treturn value ?? 0\n\t\t})\n\t\treturn (\n\t\t\tcompact({\n\t\t\t\tname: orUndefined(series.name),\n\t\t\t\tvalues,\n\t\t\t\t// Only the first series carries labels, matching how addChart reads them.\n\t\t\t\tlabels: index === 0 && categories.length > 0 ? categories : undefined,\n\t\t\t}) ?? { values }\n\t\t)\n\t})\n\n\tif (sawBlank) {\n\t\tnotes.note(\n\t\t\t'chart.blanks',\n\t\t\t'approximated',\n\t\t\t'unwritable',\n\t\t\t'a blank cached data point becomes 0, because OptsChartData.values is number[] and has no spelling for a gap; on a line chart this draws a dip to the axis where the source showed a break'\n\t\t)\n\t}\n\treturn data\n}\n\nfunction titleOptions(chart: Chart): Record<string, IrValue | undefined> {\n\tconst title = chart.title\n\treturn title === null ? {} : { showTitle: true, title }\n}\n\nfunction legendOptions(chart: Chart): Record<string, IrValue | undefined> {\n\tconst legend = chart.legend\n\tif (!legend) return { showLegend: false }\n\treturn {\n\t\tshowLegend: true,\n\t\tlegendPos: legend.position === null ? undefined : LEGEND_POS[legend.position],\n\t}\n}\n\nfunction labelOptions(chart: Chart): Record<string, IrValue | undefined> {\n\tconst labels = chart.dataLabels\n\tif (!labels) return {}\n\treturn {\n\t\tshowValue: labels.showValue ?? undefined,\n\t\tshowSerName: labels.showSeriesName ?? undefined,\n\t\tshowCatName: labels.showCategoryName ?? undefined,\n\t\tshowPercent: labels.showPercent ?? undefined,\n\t\tshowLegendKey: labels.showLegendKey ?? undefined,\n\t\tshowLeaderLines: labels.showLeaderLines ?? undefined,\n\t\tdataLabelPosition: orUndefined(labels.position),\n\t\tdataLabelFormatCode: labels.numberFormat?.formatCode ?? undefined,\n\t}\n}\n\n/**\n * Axis bounds, titles and gridlines. The write API spells these as a flat `catAxis*` /\n * `valAxis*` prefix set rather than an axis object, so each side is unpacked by hand.\n */\nfunction axisOptions(chart: Chart): Record<string, IrValue | undefined> {\n\tconst cat = chart.categoryAxis\n\tconst val = chart.valueAxis\n\treturn {\n\t\tcatAxisHidden: cat?.hidden ? true : undefined,\n\t\tcatAxisTitle: cat?.title ?? undefined,\n\t\tvalAxisHidden: val?.hidden ? true : undefined,\n\t\tvalAxisTitle: val?.title ?? undefined,\n\t\tvalAxisMinVal: val?.min ?? undefined,\n\t\tvalAxisMaxVal: val?.max ?? undefined,\n\t\tvalAxisMajorUnit: val?.majorUnit ?? undefined,\n\t\tvalAxisLabelFormatCode: val?.numberFormat?.formatCode ?? undefined,\n\t}\n}\n\n/**\n * Per-series fill colours as `chartColors`, which is positional — entry `n` colours series\n * `n`. A series with no explicit fill takes the theme's accent for its position, which the\n * read model does not resolve, so the whole option is dropped unless every series names a\n * colour; a partial list would silently recolour the unnamed ones.\n */\nfunction seriesColors(chart: Chart): IrValue | undefined {\n\tconst series = chart.series\n\tif (series.length === 0) return undefined\n\tconst colors: string[] = []\n\tfor (const one of series) {\n\t\tconst fill = one.fill\n\t\tconst hex = fill?.color\n\t\tif (!hex) return undefined\n\t\tcolors.push(literalColor(hex))\n\t}\n\treturn colors\n}\n","/**\n * `AnyShape` → one {@link CallIr}.\n *\n * The dispatch is on what the shape *is*, not on what it looks like: an `AutoShape` with a\n * text frame and no geometry is an `addText`, one with geometry is an `addShape` that may\n * also carry text, a `Picture` is an `addImage`, and a `GraphicFrame` delegates to the\n * table or chart mapper. A `GroupShape` recurses.\n *\n * The single most important thing this module does is record what it cannot carry.\n * Measurement against the fixture corpus found the binding constraint is the *read* side,\n * not the write side — several constructs the write API can express have no accessor at\n * all — so a converter that mapped only what it could see would produce clean-looking\n * output with silent visual losses. The clearest is theme-referenced line styling: a shape\n * whose outline comes from `p:style/a:lnRef` reports a colour through `resolvedLine` but\n * reports `null` for width and dash, because there is a resolved-colour path and no\n * resolved-width path. In the corpus that was every such shape, so a themed 2pt\n * border silently becomes a 1pt default. Each one is noted here rather than quietly thinned.\n *\n * The same dispatch serves the deck's *chrome*: {@link masterObject} re-tags a call as an\n * entry in a `defineSlideMaster({ objects })` array, so a rectangle on a layout is transcribed\n * by the code that transcribes one on a slide. Sharing it is the point — a second mapper would\n * be a second set of decisions about the same OOXML, drifting from this one silently.\n */\nimport {\n\tisAutoShape,\n\tisConnector,\n\tisGraphicFrame,\n\tisGroupShape,\n\tisPicture,\n\ttype AnyShape,\n\ttype AutoShape,\n\ttype Connector,\n\ttype CustomGeometry,\n\ttype GraphicFrame,\n\ttype GroupShape,\n\ttype Picture,\n} from '../../read/api/shapes.js'\nimport type { NoteScope } from '../fidelity.js'\nimport { isAssetRef, type AssetRef, type CallIr, type IrValue } from '../ir.js'\nimport { alphaToTransparency, compact, emu, isWritableSchemeToken, literalColor, orUndefined } from './values.js'\nimport { gradientStops, patternOption } from './surface-fill.js'\nimport { pictureFillOption, type PictureFillSubject } from './picture-fill.js'\nimport { hasEquation, hasIdentityChildSpace, isAudioVideo, isTextBox } from './detect.js'\nimport { textFrameOptions, textRuns } from './text.js'\nimport { tableCall } from './table.js'\nimport { chartCall } from './chart.js'\nimport { PERCENT_SCALE } from '../../units.js'\n\n/** Resolves an image/media part name to bytes the deck-level walk has registered. */\nexport interface AssetResolver {\n\t/** Register a part's bytes and hand back the reference that stands in for them. */\n\tassetFor(partName: string): AssetRef | null\n\t/**\n\t * The part's content type, or `null` when it is not in the package.\n\t *\n\t * Separate from {@link assetFor} because it has to be answerable *without* registering\n\t * anything: a caller that rejects a part on its type (a picture fill's SVG blip, which\n\t * the write path refuses) would otherwise leave bytes in the asset list that no call\n\t * references, and those bytes are emitted as a file next to the script.\n\t */\n\tcontentTypeOf(partName: string): string | null\n}\n\n/** How {@link pictureFillOption}'s notes name a shape's surface. */\nconst SHAPE_PICTURE_FILL: PictureFillSubject = {\n\tconstruct: 'fill.picture',\n\tsubject: \"this shape's surface\",\n\telement: 'a:blipFill',\n}\n\n/** Arrowhead types `ShapeLineProps` accepts; `a:headEnd/@type` uses the same tokens. */\nconst WRITABLE_ARROWS = new Set(['none', 'arrow', 'diamond', 'oval', 'stealth', 'triangle'])\n\n/** Dash tokens `ShapeLineProps.dashType` accepts — the whole `ST_PresetLineDashVal` set. */\nconst WRITABLE_DASHES = new Set([\n\t'solid',\n\t'dot',\n\t'dash',\n\t'lgDash',\n\t'dashDot',\n\t'lgDashDot',\n\t'lgDashDotDot',\n\t'sysDash',\n\t'sysDot',\n\t'sysDashDot',\n\t'sysDashDotDot',\n])\n\n/**\n * `a:ln/@cap` tokens → the `ShapeLineProps.cap` spelling that authors them. The read side\n * reports the raw OOXML token (`AutoShape.lineCap`) and the write side takes a friendly\n * name, so this is the whole of the mapping between them. `ST_LineCap` has exactly these\n * three members, so nothing falls off the end.\n */\nconst CAP_TOKENS: Record<string, 'flat' | 'square' | 'round'> = {\n\tflat: 'flat',\n\tsq: 'square',\n\trnd: 'round',\n}\n\n/**\n * Map one shape. Returns `null` when the shape produces no call at all — a note is always\n * recorded in that case, so a dropped shape is never silent.\n */\nexport function shapeCall(shape: AnyShape, notes: NoteScope, assets: AssetResolver): CallIr | null {\n\tconst scoped = notes.forShape(shape.name || null)\n\n\tif (shape.hidden) {\n\t\tnoteHidden(scoped)\n\t\treturn null\n\t}\n\n\tif (isGroupShape(shape)) return groupCall(shape, scoped, assets)\n\tif (isPicture(shape)) return pictureCall(shape, scoped, assets)\n\tif (isConnector(shape)) return connectorCall(shape, scoped)\n\tif (isGraphicFrame(shape)) return graphicFrameCall(shape, scoped, assets)\n\tif (isAutoShape(shape)) return autoShapeCall(shape, scoped, assets)\n\n\t// Unreachable: the five guards above exhaust `AnyShape`, which is why `shape` narrows to\n\t// `never` here. Left as a floor so a sixth shape kind fails to compile at the call sites\n\t// that assume a call, rather than silently falling through to a silent drop.\n\treturn null\n}\n\n/**\n * `p:cNvPr/@hidden` has no write-API counterpart, so a hidden shape would come back visible.\n * Omitting it preserves what the deck looks like, which is the lesser loss. Shared with the\n * layout-decoration mapper below, whose connector arm does not pass through {@link shapeCall}.\n */\nfunction noteHidden(notes: NoteScope): void {\n\tnotes.note(\n\t\t'shape.hidden',\n\t\t'dropped',\n\t\t'unwritable',\n\t\t'a hidden shape has no write-API expression; it is omitted rather than emitted visible'\n\t)\n}\n\n/* ===== position, fill, line, effects — shared by every shape kind ===== */\n\n/**\n * Position as `Coord`-typed EMU strings, so the source geometry survives exactly.\n *\n * `absoluteFrame` rather than the raw `left`/`top`: a shape inside a group is positioned in\n * its group's child coordinate space, which a flattened call list cannot express, so the\n * group transform has to be composed in here. For a top-level shape the two are identical.\n */\nfunction positionOptions(shape: AnyShape, notes?: NoteScope): Record<string, IrValue> {\n\tconst frame = shape.absoluteFrame\n\tif (frame) return { x: emu(frame.left), y: emu(frame.top), w: emu(frame.width), h: emu(frame.height) }\n\n\t// No transform of its own — a placeholder taking its geometry from the layout or master.\n\t// `resolvedFrame` walks that chain, and using it is not optional: omitting the geometry\n\t// does *not* leave it to be inherited, because a regenerated slide's placeholder inherits\n\t// nothing. It produces `x=0 y=0 w=<slide width> h=0` — a zero-height box in the corner,\n\t// which is broken output rather than lossy output.\n\tconst resolved = shape.resolvedFrame\n\tif (!resolved) return {}\n\tnotes?.note(\n\t\t'shape.frameInherited',\n\t\t'flattened',\n\t\t'unsupported',\n\t\t`this shape has no transform of its own and takes its geometry from the ${resolved.source}; a regenerated slide inherits nothing, so the resolved position is baked in and stops tracking later edits to that ${resolved.source}`\n\t)\n\treturn { x: emu(resolved.left), y: emu(resolved.top), w: emu(resolved.width), h: emu(resolved.height) }\n}\n\n/**\n * Rotation and flips. Taken from `absoluteFrame`, which composes enclosing group rotations\n * and XOR-composes group flips — the same reason position is absolute.\n */\nfunction transformOptions(shape: AnyShape): Record<string, IrValue | undefined> {\n\tconst frame = shape.absoluteFrame\n\tconst rotate = frame ? frame.rotation : (shape.rotation ?? 0)\n\treturn {\n\t\trotate: rotate === 0 ? undefined : rotate,\n\t\tflipH: (frame?.flipH ?? shape.flipH) ? true : undefined,\n\t\tflipV: (frame?.flipV ?? shape.flipV) ? true : undefined,\n\t}\n}\n\n/**\n * A shape's fill as `ShapeFillProps`.\n *\n * Prefers the raw scheme token over `resolvedFill` for the same reason run colour does: a\n * token keeps tracking the destination theme. `resolvedFill` is the fallback because it is\n * the only accessor that sees a `p:style/a:fillRef` — a shape styled entirely from the\n * theme has no `a:solidFill` of its own, so without it the shape would come out unfilled.\n */\nfunction fillOption(shape: AnyShape, notes: NoteScope, assets: AssetResolver): IrValue | undefined {\n\tconst gradient = shape.gradientFill\n\tif (gradient) {\n\t\tconst stops = gradientStops(gradient, notes, 'fill')\n\t\tif (stops) return { type: 'gradient', gradient: stops }\n\t}\n\n\tconst pattern = patternOption(shape.patternFill)\n\tif (pattern) return pattern\n\n\t// An image-filled *surface* is not a picture object — it is `ShapeFillProps.image`, so\n\t// the bytes are re-embedded through the same asset resolver an `addImage` uses. Before\n\t// the fill option itself, since a shape carrying a `a:blipFill` has no `a:solidFill` for\n\t// the colour legs below to find.\n\tconst picture = shape.pictureFill\n\tif (picture) return pictureFillOption(picture, assets, notes, SHAPE_PICTURE_FILL)\n\n\tconst scheme = shape.fillSchemeColor\n\tif (isWritableSchemeToken(scheme)) return { color: scheme as string }\n\tif (shape.fillColor !== null) return { color: literalColor(shape.fillColor) }\n\n\tconst resolved = shape.resolvedFill\n\tif (!resolved) return undefined\n\tif (scheme !== null) {\n\t\tnotes.note(\n\t\t\t'fill.schemeToken',\n\t\t\t'approximated',\n\t\t\t'unwritable',\n\t\t\t`fill scheme colour \"${scheme}\" is outside the ten tokens the write path maps, so it is baked to a literal hex and stops tracking the theme`\n\t\t)\n\t}\n\treturn compact({\n\t\tcolor: literalColor(resolved.effectiveHex),\n\t\ttransparency: alphaToTransparency(resolved.alpha),\n\t})\n}\n\n/**\n * A shape's outline as `ShapeLineProps`.\n *\n * This is where the measured silent loss lives. When a shape takes its outline from\n * `p:style/a:lnRef`, `resolvedLine` supplies the colour but `lineWidthPt` and `lineDash`\n * both report `null` — the theme's `a:lnStyleLst` entry, where the width and dash actually\n * live, has no accessor. Emitting the colour and noting the rest is the honest outcome;\n * inventing a width would be worse, because it would look deliberate.\n */\nfunction lineOption(shape: AnyShape, notes: NoteScope): Record<string, IrValue> | undefined {\n\tif (shape.lineNoFill) return { type: 'none' }\n\n\tconst gradient = shape.lineGradient\n\tif (gradient) {\n\t\tconst stops = gradientStops(gradient, notes, 'line')\n\t\tif (stops) return { type: 'gradient', gradient: stops }\n\t}\n\n\tconst widthPt = shape.lineWidthPt\n\tconst dash = shape.lineDash\n\tconst cap = shape.lineCap\n\tconst scheme = shape.lineSchemeColor\n\tconst resolved = shape.resolvedLine\n\n\tlet color: string | undefined\n\tif (isWritableSchemeToken(scheme)) color = scheme as string\n\telse if (shape.lineColor !== null) color = literalColor(shape.lineColor)\n\telse if (resolved) color = literalColor(resolved.effectiveHex)\n\n\t// A colour only `resolvedLine` could supply means the stroke came from the theme style\n\t// list, whose width and dash are unreadable.\n\tif (resolved !== null && shape.lineColor === null && scheme === null && widthPt === null) {\n\t\tnotes.note(\n\t\t\t'line.width',\n\t\t\t'dropped',\n\t\t\t'unread',\n\t\t\t'this outline comes from the theme style list (p:style/a:lnRef); its width and dash live in the theme fmtScheme a:lnStyleLst, which has no accessor, so only the colour carries'\n\t\t)\n\t}\n\tif (dash !== null && !WRITABLE_DASHES.has(dash)) {\n\t\tnotes.note(\n\t\t\t'line.dash',\n\t\t\t'approximated',\n\t\t\t'unwritable',\n\t\t\t`dash style \"${dash}\" is outside the eight the write API accepts, so the outline falls back to solid`\n\t\t)\n\t}\n\t// `@algn` is the one outline attribute both sides can see and neither can carry: the read\n\t// model reports it (`lineAlign`) and `ShapeLineProps` has no option for it. Only `in` is\n\t// noted — it insets the stroke by half its width, so it moves the border. `ctr` is what an\n\t// omitted `@algn` already renders as, so noting that would fire on most PowerPoint-authored\n\t// shapes while describing no loss at all.\n\tif (shape.lineAlign === 'in') {\n\t\tnotes.note(\n\t\t\t'line.align',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'this outline is inset (a:ln/@algn=\"in\", drawn wholly inside the shape); ShapeLineProps has no alignment option, so it comes back centred on the edge and sits half its width further out'\n\t\t)\n\t}\n\n\tconst options = compact({\n\t\tcolor,\n\t\twidth: orUndefined(widthPt),\n\t\tdashType: dash !== null && WRITABLE_DASHES.has(dash) ? dash : undefined,\n\t\tcap: cap === null ? undefined : CAP_TOKENS[cap],\n\t\ttransparency: alphaToTransparency(resolved?.alpha),\n\t\t...arrowOptions(shape, notes),\n\t})\n\treturn options\n}\n\n/** Arrowheads. Types map directly; the `sm`/`med`/`lg` size classes have no option. */\nfunction arrowOptions(shape: AnyShape, notes: NoteScope): Record<string, IrValue | undefined> {\n\tconst ends = shape.lineEnds\n\tif (!ends) return {}\n\tconst sized = [ends.head, ends.tail].some((end) => end && (end.width !== null || end.length !== null))\n\tif (sized) {\n\t\tnotes.note(\n\t\t\t'line.arrowSize',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'arrowhead width and length classes (@w / @len) have no write-API option, so arrowheads render at the default size'\n\t\t)\n\t}\n\treturn {\n\t\tbeginArrowType: ends.head && WRITABLE_ARROWS.has(ends.head.type) ? ends.head.type : undefined,\n\t\tendArrowType: ends.tail && WRITABLE_ARROWS.has(ends.tail.type) ? ends.tail.type : undefined,\n\t}\n}\n\n/** Outer shadow as `ShadowProps`; an inner shadow uses the same option with `type: 'inner'`. */\nfunction shadowOption(shape: AnyShape, notes: NoteScope): IrValue | undefined {\n\tif (shape.reflection || shape.softEdge) {\n\t\tnotes.note(\n\t\t\t'shape.effects',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'a:reflection and a:softEdge are read but have no write-API emitter, so those effects are lost'\n\t\t)\n\t}\n\n\tconst outer = shape.shadow\n\tconst source = outer ?? shape.innerShadow\n\tif (!source) return undefined\n\n\treturn compact({\n\t\ttype: outer ? 'outer' : 'inner',\n\t\tcolor: source.color === null ? undefined : literalColor(source.color),\n\t\tblur: source.blurPt,\n\t\toffset: source.offsetPt,\n\t\tangle: source.angleDeg,\n\t\ttransparency: alphaToTransparency(source.alpha),\n\t})\n}\n\n/** Glow. The read model reports opacity as a 0–1 alpha, which is the write API's unit too. */\nfunction glowOption(shape: AnyShape): IrValue | undefined {\n\tconst glow = shape.glow\n\tif (!glow) return undefined\n\treturn compact({\n\t\tsize: glow.radiusPt,\n\t\tcolor: glow.color === null ? undefined : literalColor(glow.color),\n\t\topacity: glow.alpha,\n\t})\n}\n\n/** The style block every shape kind shares. */\nfunction styleOptions(shape: AnyShape, notes: NoteScope, assets: AssetResolver): Record<string, IrValue | undefined> {\n\treturn {\n\t\tfill: fillOption(shape, notes, assets),\n\t\tline: lineOption(shape, notes),\n\t\tshadow: shadowOption(shape, notes),\n\t\tglow: glowOption(shape),\n\t}\n}\n\n/* ===== per-kind mappers ===== */\n\n/**\n * An `AutoShape` becomes an `addShape` when it is bare geometry and an `addText` when it\n * carries text. A shape with both takes the `addText` form, because `addShape` has no text\n * argument while `addText` accepts a `shape` option — so only that form expresses both.\n */\nfunction autoShapeCall(shape: AutoShape, notes: NoteScope, assets: AssetResolver): CallIr | null {\n\tconst preset = shape.presetGeometry\n\tconst custom = shape.customGeometry\n\tconst frame = shape.hasTextFrame ? shape.textFrame : null\n\n\t// \"Has text\" means text this converter can author, which is *runs*. `TextFrame.text` also\n\t// counts `a:fld` field text — a slide number, date or footer placeholder — and there is no\n\t// run behind it, so measuring by `text` made every field placeholder emit an `addText`\n\t// carrying a single empty string: an invisible empty box where a number used to be.\n\tconst runText = frame === null ? '' : frame.paragraphs.flatMap((p) => p.runs.map((run) => run.text)).join('')\n\tconst hasText = runText.length > 0\n\n\t// Run text is a subsequence of the frame's text, so anything longer came from a field.\n\tif (frame !== null && frame.text.replaceAll('\\n', '').length > runText.length) {\n\t\tnotes.note(\n\t\t\t'text.field',\n\t\t\t'dropped',\n\t\t\t'unread',\n\t\t\t'this shape holds an automatic field (a:fld — a slide number, date or footer), which has no accessor and no addText expression, so its text is not reproduced'\n\t\t)\n\t}\n\n\t// An OMML equation contributes nothing to `TextFrame.text`, so an equation-only shape\n\t// looks like an empty box and would otherwise emit as bare geometry.\n\tif (frame !== null && hasEquation(shape.element_)) {\n\t\tnotes.note(\n\t\t\t'text.equation',\n\t\t\t'dropped',\n\t\t\t'unread',\n\t\t\t'this shape holds an OMML equation, which no accessor exposes, so the shape is emitted without it — even though TextProps.math (and the ts-pptx/math subpath) could author one'\n\t\t)\n\t}\n\n\tif (shape.placeholder) {\n\t\tnotes.note(\n\t\t\t'shape.placeholder',\n\t\t\t'flattened',\n\t\t\t'unsupported',\n\t\t\t'a placeholder is emitted as a plain shape with its inherited geometry and styling baked in, so it no longer follows its layout'\n\t\t)\n\t}\n\n\tconst common = {\n\t\t...positionOptions(shape, notes),\n\t\t...transformOptions(shape),\n\t\t...styleOptions(shape, notes, assets),\n\t\tobjectName: shape.name || undefined,\n\t}\n\n\tif (custom) {\n\t\tnotes.note(\n\t\t\t'shape.custGeom.guides',\n\t\t\t'dropped',\n\t\t\t'unread',\n\t\t\t'custGeom guides, adjust handles and connection sites (a:gdLst / a:ahLst / a:cxnLst) have no accessor, so only the path outline carries'\n\t\t)\n\t\tconst options = compact({ ...common, points: customGeometryPoints(shape, custom) })\n\t\treturn { method: 'addShape', args: ['custGeom', options ?? {}], ...nameOf(shape) }\n\t}\n\n\tif (hasText && frame !== null) {\n\t\t// `isTextBox` and `shape` are independent, not alternatives: a PowerPoint text box\n\t\t// carries `txBox=\"1\"` *and* an explicit `prstGeom rect`, so reading text-box-ness off\n\t\t// the absence of geometry misclassified every one of them as an auto shape.\n\t\tconst options = compact({\n\t\t\t...common,\n\t\t\t...textFrameOptions(frame, notes),\n\t\t\t...(isTextBox(shape.element_) ? { isTextBox: true } : {}),\n\t\t\t...(preset === null ? {} : { shape: preset, ...adjustOptions(shape) }),\n\t\t})\n\t\treturn { method: 'addText', args: [textRuns(frame, notes), options ?? {}], ...nameOf(shape) }\n\t}\n\n\t// No text and no geometry of its own: an empty placeholder, whose shape comes from the\n\t// layout it inherits. `addShape` needs a preset name and `addText` would author an\n\t// invisible empty box, so the shape is dropped — which matches how it renders in a\n\t// slideshow, where an unfilled placeholder shows nothing. It is still a loss in the\n\t// editor, so it is declared rather than assumed harmless.\n\tif (preset === null) {\n\t\tnotes.note(\n\t\t\t'shape.empty',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t'this shape carries no text and no geometry of its own (an unfilled placeholder drawing its outline from the layout), so there is no addShape preset to name and it is omitted'\n\t\t)\n\t\treturn null\n\t}\n\tconst options = compact({ ...common, ...adjustOptions(shape) })\n\treturn { method: 'addShape', args: [preset, options ?? {}], ...nameOf(shape) }\n}\n\n/**\n * Preset-geometry adjust handles (`a:avLst`) as `shapeAdjust`.\n *\n * The read model reports each guide's raw formula string; a preset's adjust values are\n * `val <n>` where `<n>` is in 1000ths of a percent, and the write API takes the same handle\n * as a `0.0–1.0` fraction. Anything that is not a plain `val` is a computed guide, which\n * has no write-API expression, so it is skipped rather than mis-scaled.\n */\nfunction adjustOptions(shape: AutoShape): Record<string, IrValue | undefined> {\n\tconst values = shape.adjustValues\n\tconst guides: IrValue[] = []\n\tfor (const name of Object.keys(values).sort()) {\n\t\tconst match = /^val\\s+(-?\\d+)$/.exec((values[name] ?? '').trim())\n\t\tif (!match?.[1]) continue\n\t\tguides.push({ name, value: Number(match[1]) / PERCENT_SCALE })\n\t}\n\treturn guides.length ? { shapeAdjust: guides } : {}\n}\n\n/**\n * `custGeom` path commands as the write API's `points` array.\n *\n * Path coordinates are integers in the path's own `0..w`/`0..h` viewport, not EMU, so each\n * is scaled onto the shape's box before being printed as EMU. A path that declares no\n * viewport (`@w`/`@h` of 0) is already in the shape's own space and passes through.\n */\nfunction customGeometryPoints(shape: AutoShape, custom: CustomGeometry): IrValue {\n\tconst frame = shape.absoluteFrame\n\tconst points: IrValue[] = []\n\n\tfor (const path of custom.paths) {\n\t\tconst sx = path.w > 0 && frame ? frame.width / path.w : 1\n\t\tconst sy = path.h > 0 && frame ? frame.height / path.h : 1\n\t\tconst px = (v: number): string => emu(v * sx)\n\t\tconst py = (v: number): string => emu(v * sy)\n\n\t\tfor (const command of path.commands) {\n\t\t\tswitch (command.cmd) {\n\t\t\t\tcase 'moveTo':\n\t\t\t\t\tpoints.push({ x: px(command.x), y: py(command.y), moveTo: true })\n\t\t\t\t\tbreak\n\t\t\t\tcase 'lnTo':\n\t\t\t\t\tpoints.push({ x: px(command.x), y: py(command.y) })\n\t\t\t\t\tbreak\n\t\t\t\tcase 'cubicBezTo':\n\t\t\t\t\tpoints.push({\n\t\t\t\t\t\tx: px(command.x),\n\t\t\t\t\t\ty: py(command.y),\n\t\t\t\t\t\tcurve: { type: 'cubic', x1: px(command.x1), y1: py(command.y1), x2: px(command.x2), y2: py(command.y2) },\n\t\t\t\t\t})\n\t\t\t\t\tbreak\n\t\t\t\tcase 'quadBezTo':\n\t\t\t\t\tpoints.push({\n\t\t\t\t\t\tx: px(command.x),\n\t\t\t\t\t\ty: py(command.y),\n\t\t\t\t\t\tcurve: { type: 'quadratic', x1: px(command.x1), y1: py(command.y1) },\n\t\t\t\t\t})\n\t\t\t\t\tbreak\n\t\t\t\tcase 'arcTo':\n\t\t\t\t\t// An arcTo carries no end point on either side — the renderer derives it from\n\t\t\t\t\t// the pen position, radii and swept angle — so this maps one-to-one.\n\t\t\t\t\tpoints.push({\n\t\t\t\t\t\tcurve: { type: 'arc', wR: px(command.wR), hR: py(command.hR), stAng: command.stAng, swAng: command.swAng },\n\t\t\t\t\t})\n\t\t\t\t\tbreak\n\t\t\t\tcase 'close':\n\t\t\t\t\tpoints.push({ close: true })\n\t\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\treturn points\n}\n\n/**\n * A `Picture` becomes `addImage`, with its bytes carried as an asset.\n *\n * PowerPoint authors embedded audio and video as a picture too — the poster frame is the\n * blip, and the media itself hangs off `p:nvPr` as `a:videoFile`/`a:audioFile`. The read\n * model surfaces only the poster (`mediaKind` separates raster from SVG, not still from\n * moving), so a video would otherwise convert to a static image with nothing to show it had\n * ever moved. The write API has `addMedia`, so this is a read-side gap, and it is declared\n * rather than silently flattened.\n */\nfunction pictureCall(shape: Picture, notes: NoteScope, assets: AssetResolver): CallIr | null {\n\tif (isAudioVideo(shape.element_)) {\n\t\tnotes.note(\n\t\t\t'media.audioVideo',\n\t\t\t'flattened',\n\t\t\t'unread',\n\t\t\t'this is embedded audio or video: no accessor reports the media part or its kind, only the poster frame, so it is emitted as a still image even though addMedia could author it'\n\t\t)\n\t}\n\n\t// The vector part wins when there is one. A PowerPoint SVG picture is an `asvg:svgBlip`\n\t// extension over a raster fallback, and the fallback is the lossy copy — taking it would\n\t// throw away the vector for no reason, since `addImage` accepts SVG bytes directly and\n\t// regenerates a fallback of its own.\n\tconst partName = shape.svgPartName ?? shape.imagePartName\n\tif (!partName) {\n\t\tnotes.note(\n\t\t\t'image.data',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t'this picture references no embedded image part (an external or linked image), so there are no bytes to carry'\n\t\t)\n\t\treturn null\n\t}\n\tconst asset = assets.assetFor(partName)\n\tif (!asset) {\n\t\tnotes.note('image.data', 'dropped', 'unsupported', `image part ${partName} is not present in the package`)\n\t\treturn null\n\t}\n\n\tif (shape.svgPartName && shape.imagePartName) {\n\t\tnotes.note(\n\t\t\t'image.svg',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t\"the vector part of this SVG picture is carried and the source's own raster fallback is not; the write path generates a fresh fallback, so a renderer that cannot draw SVG shows a different image from the one the source deck shipped\"\n\t\t)\n\t}\n\tif (shape.recolor) {\n\t\tnotes.note(\n\t\t\t'image.recolor',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'a picture recolour (a:duotone / a:clrChange / a:grayscl) is read but has no write-API option'\n\t\t)\n\t}\n\n\tconst crop = shape.crop\n\tconst options = compact({\n\t\t...positionOptions(shape, notes),\n\t\t...transformOptions(shape),\n\t\tobjectName: shape.name || undefined,\n\t\t// `crop`, not `sizing`. Both exist and they are not interchangeable: `crop` is\n\t\t// `a:srcRect` emitted verbatim as percentage edge insets — the exact model the read\n\t\t// model reports — while `sizing: 'crop'` cuts a window in *displayed inches* against\n\t\t// the image's measured natural size. Feeding fractions to `sizing` read them as\n\t\t// inches, which shrank every cropped picture to a fraction of its box.\n\t\tcrop:\n\t\t\tcrop === null ? undefined : { l: crop.left * 100, t: crop.top * 100, r: crop.right * 100, b: crop.bottom * 100 },\n\t})\n\treturn { method: 'addImage', args: [{ ...options, data: asset }], ...nameOf(shape) }\n}\n\n/**\n * `ConnectorProps` keys that {@link lineOption} can produce. A connector styles its stroke\n * with *flat* options rather than the nested `line` object every other shape takes, and it\n * accepts a strict subset: no `transparency`, no gradient stroke, and its own `type` names\n * the routing (`straight`/`elbow`/`curved`), not a fill kind — so spreading a line option\n * object into it wholesale would both drop silently and collide.\n */\nconst CONNECTOR_LINE_KEYS = ['color', 'width', 'dashType', 'beginArrowType', 'endArrowType'] as const\n\n/**\n * A `Connector` becomes `addConnector`.\n *\n * The endpoints are the one real translation here. OOXML gives a connector a bounding box\n * plus flip flags; `addConnector` takes two points. `a:flipH`/`a:flipV` are what say which\n * diagonal of the box the line runs along, so dropping them would silently mirror every\n * connector that runs up or leftward.\n *\n * The *bindings* (`a:stCxn`/`a:endCxn`) reference source shape ids that have no counterpart\n * in the output, so a connector lands unbound and stops following its shapes when they move.\n */\nfunction connectorCall(shape: Connector, notes: NoteScope): CallIr | null {\n\tconst frame = shape.absoluteFrame\n\tif (!frame) return null\n\n\tif (shape.startConnection || shape.endConnection) {\n\t\tnotes.note(\n\t\t\t'connector.binding',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t'connector endpoint bindings reference source shape ids with no counterpart in the output, so the connector lands unbound and no longer follows its shapes'\n\t\t)\n\t}\n\tif (shape.rotation) {\n\t\tnotes.note(\n\t\t\t'connector.rotation',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'addConnector takes two endpoints and no rotation, so a rotated connector lands along the unrotated diagonal of its box'\n\t\t)\n\t}\n\n\tconst line = lineOption(shape, notes) ?? {}\n\tconst stroke: Record<string, IrValue> = {}\n\tfor (const key of CONNECTOR_LINE_KEYS) {\n\t\tconst value = line[key]\n\t\tif (value !== undefined) stroke[key] = value\n\t}\n\tif (line['type'] === 'gradient' || line['transparency'] !== undefined) {\n\t\tnotes.note(\n\t\t\t'connector.line',\n\t\t\t'flattened',\n\t\t\t'unwritable',\n\t\t\t'a connector styles its stroke with flat colour/width options, which cannot express a gradient stroke or a stroke transparency, so those fall back to a plain line'\n\t\t)\n\t}\n\n\tconst right = frame.left + frame.width\n\tconst bottom = frame.top + frame.height\n\treturn {\n\t\tmethod: 'addConnector',\n\t\targs: [\n\t\t\tcompact({\n\t\t\t\t// Routing is not readable — `presetGeometry` names the connector preset but the\n\t\t\t\t// bend count it implies is not exposed — so every connector emits straight.\n\t\t\t\ttype: 'straight',\n\t\t\t\tx1: emu(shape.flipH ? right : frame.left),\n\t\t\t\ty1: emu(shape.flipV ? bottom : frame.top),\n\t\t\t\tx2: emu(shape.flipH ? frame.left : right),\n\t\t\t\ty2: emu(shape.flipV ? frame.top : bottom),\n\t\t\t\tobjectName: shape.name || undefined,\n\t\t\t\t...stroke,\n\t\t\t}) ?? {},\n\t\t],\n\t\t...nameOf(shape),\n\t}\n}\n\n/**\n * Why a graphic frame cannot be authored from a script, or `null` when it can.\n *\n * The single enumeration of the payloads with no write-API emitter, and the reason it is a\n * function rather than a condition spelled at each site: `graphicFrameCall` needs it to pick\n * a fidelity note, and `hasUnwritableContent` in `from-read/deck.ts` needs it to decide\n * whether the printer must copy the slide instead of transcribing it. Those were two\n * hand-maintained lists, they disagreed — the deck-level one named extended charts only — and\n * a SmartArt slide was therefore transcribed with a hole where the graphic had been. The two\n * consequences are the same for every member, so the membership has to be too.\n */\nexport function unwritableFramePayload(shape: GraphicFrame): 'chartEx' | 'diagram' | 'unknown' | null {\n\tif (shape.table || shape.chart) return null\n\tif (shape.hasChartEx) return 'chartEx'\n\tif (shape.hasDiagram) return 'diagram'\n\treturn 'unknown'\n}\n\n/** A `GraphicFrame` hosts a table or a chart; both have their own mapper. */\nfunction graphicFrameCall(shape: GraphicFrame, notes: NoteScope, assets: AssetResolver): CallIr | null {\n\tconst table = shape.table\n\tif (table) return tableCall(shape, table, notes, assets)\n\n\tconst chart = shape.chart\n\tif (chart) return chartCall(shape, chart, notes)\n\n\t// Everything below emits no call. Reached even when the deck-level walk already marked the\n\t// slide `carried`, because the standalone tier has no source package to copy from and needs\n\t// the per-shape note to say what it lost.\n\tswitch (unwritableFramePayload(shape)) {\n\t\tcase 'chartEx':\n\t\t\tnotes.note(\n\t\t\t\t'chartEx.all',\n\t\t\t\t'dropped',\n\t\t\t\t'unwritable',\n\t\t\t\t'an extended chart (waterfall, funnel, box-and-whisker, …) has a full reader but no write-API counterpart'\n\t\t\t)\n\t\t\treturn null\n\t\tcase 'diagram':\n\t\t\t// Read but unwritable, so it takes the `chartEx.all` shape rather than the\n\t\t\t// `graphicFrame.unknown` one below: the loss is the *write* side's, and saying\n\t\t\t// \"not decoded\" of a construct whose text the read model now returns would be false.\n\t\t\tnotes.note(\n\t\t\t\t'diagram.all',\n\t\t\t\t'dropped',\n\t\t\t\t'unwritable',\n\t\t\t\t'a SmartArt diagram has a full reader and its text can be edited in place through it (DiagramPoint.text), but no write API authors one from a script, so a converted script cannot describe this frame'\n\t\t\t)\n\t\t\treturn null\n\t\tdefault:\n\t\t\tnotes.note(\n\t\t\t\t'graphicFrame.unknown',\n\t\t\t\t'dropped',\n\t\t\t\t'unread',\n\t\t\t\t'this graphic frame hosts none of a table, a chart or a SmartArt diagram (an OLE object or an ink annotation), which the read model does not decode'\n\t\t\t)\n\t\t\treturn null\n\t}\n}\n\n/**\n * A `GroupShape` becomes `addGroup`, with each child mapped and re-tagged into the\n * key-tagged `GroupChildProps` shape the write API expects.\n *\n * Children keep slide-absolute coordinates, which is not a compromise here: `addGroup`\n * holds an identity child coordinate space (`chOff/chExt == off/ext`) at every depth\n * precisely so they can. Nested groups therefore nest rather than flatten. What does not\n * survive is a source group with a *non*-identity child space — that group scales its\n * contents when resized and the emitted one will not — so that case, and only that case,\n * is noted.\n *\n * Charts, tables, media and placeholders are excluded from groups by the write API, so a\n * group holding one loses that child.\n */\nfunction groupCall(shape: GroupShape, notes: NoteScope, assets: AssetResolver): CallIr | null {\n\tconst children: IrValue[] = []\n\tfor (const child of shape.shapes) {\n\t\tconst call = shapeCall(child, notes, assets)\n\t\tif (!call) continue\n\t\tconst tagged = asGroupChild(call)\n\t\tif (!tagged) {\n\t\t\tnotes.note(\n\t\t\t\t'group.child',\n\t\t\t\t'dropped',\n\t\t\t\t'unsupported',\n\t\t\t\t`addGroup accepts no ${call.method.replace(/^add/, '').toLowerCase()} child (charts, tables and media are excluded by design), so this child is omitted from the group`\n\t\t\t)\n\t\t\tcontinue\n\t\t}\n\t\tchildren.push(tagged)\n\t}\n\tif (children.length === 0) {\n\t\tnotes.note(\n\t\t\t'group.empty',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t'no child of this group produced a call, and addGroup rejects an empty child list, so the group itself is omitted too'\n\t\t)\n\t\treturn null\n\t}\n\n\tif (!hasIdentityChildSpace(shape.element_)) {\n\t\tnotes.note(\n\t\t\t'group.childSpace',\n\t\t\t'flattened',\n\t\t\t'unsupported',\n\t\t\t\"this group scales its contents (its a:chOff/a:chExt differ from its a:off/a:ext); addGroup's child space is always identity, so the children are emitted pre-scaled and resizing the group no longer rescales them\"\n\t\t)\n\t}\n\n\t// The group's own rotation and flips are deliberately NOT emitted here. `absoluteFrame`\n\t// composes them into every child, and the children above were built from it, so the\n\t// transform is already baked in at slide-absolute coordinates. Emitting it on the group\n\t// as well would apply it a second time — measured: a group rotated 30° came back at 60°\n\t// with its children walked off their positions, and a flipped group came back unflipped\n\t// because the double flip cancelled. The group's frame is a bounding box and nothing else.\n\tif (shape.rotation !== 0 || shape.flipH || shape.flipV) {\n\t\tnotes.note(\n\t\t\t'group.transform',\n\t\t\t'flattened',\n\t\t\t'unsupported',\n\t\t\t\"the group's own rotation and flips are baked into its children's coordinates rather than kept on the group, because addGroup would otherwise apply them twice; the shapes render identically but rotating or resetting the group no longer moves them together\"\n\t\t)\n\t}\n\n\treturn {\n\t\tmethod: 'addGroup',\n\t\targs: [children, compact({ ...positionOptions(shape, notes), objectName: shape.name || undefined }) ?? {}],\n\t\t...nameOf(shape),\n\t}\n}\n\n/**\n * Re-tag a call as a `GroupChildProps` entry, or `null` when the content type is one\n * `addGroup` excludes. The tagged form is a single-key object, not a `{ type, args }` pair.\n */\nfunction asGroupChild(call: CallIr): IrValue | null {\n\tconst shared = commonShapeVariant(call)\n\tif (shared) return shared\n\tconst [first, second] = call.args\n\tswitch (call.method) {\n\t\tcase 'addGroup':\n\t\t\treturn { group: compact({ children: first, options: second }) ?? {} }\n\t\tdefault:\n\t\t\t// Charts, tables, connectors and media have no GroupChildProps variant.\n\t\t\treturn null\n\t}\n}\n\n/**\n * The three key-tagged variants both union-shaped call sites emit identically: a text box, an\n * auto shape, and an image. `null` when `call.method` is not one of them, which is the signal\n * for the caller to try its own extra arms.\n *\n * Shared rather than duplicated because this is exactly where a fourth common variant would be\n * added to one site and forgotten in the other. What is deliberately *not* shared is either\n * caller's `default`: a group child silently declines a chart, while a layout object reports it\n * as a fidelity loss, and that difference is the point of having two functions.\n */\nfunction commonShapeVariant(call: CallIr): IrValue | null {\n\tconst [first, second] = call.args\n\tswitch (call.method) {\n\t\tcase 'addText':\n\t\t\treturn { text: compact({ text: first, options: second }) ?? {} }\n\t\tcase 'addShape':\n\t\t\treturn { shape: compact({ type: first, options: second }) ?? {} }\n\t\tcase 'addImage':\n\t\t\treturn { image: first ?? {} }\n\t\tdefault:\n\t\t\treturn null\n\t}\n}\n\n/** Attach the source name to a call, when the shape had one. */\nfunction nameOf(shape: AnyShape): { sourceName?: string } {\n\treturn shape.name ? { sourceName: shape.name } : {}\n}\n\n/* ===== a layout's own shapes ===== */\n\n/**\n * One shape from a **layout's** shape tree as a `SlideMasterObject` — an entry in the\n * `objects` array of a `defineSlideMaster` call.\n *\n * Everything about the shape itself is decided by {@link shapeCall}, so a rectangle on a\n * layout is transcribed by the same code that transcribes one on a slide and cannot drift\n * from it. Only the *envelope* differs: `objects` is a key-tagged union rather than a method\n * name plus arguments — the same shape `GroupChildProps` takes — which is why this reads as a\n * sibling of {@link asGroupChild}.\n *\n * `notes` must already be a `layoutShapeScope`, so the slide vocabulary this borrows lands\n * under `layout.` and cannot be mistaken for a loss on a slide.\n *\n * Two methods have no variant in the union. `addGroup` never reaches here — the layout walk\n * flattens a group into its children first, since children already carry slide-absolute\n * coordinates. `addTable` genuinely has nowhere to go, and is the one kind this reports as\n * lost.\n */\nexport function masterObject(shape: AnyShape, notes: NoteScope, assets: AssetResolver): IrValue | null {\n\t// The connector arm bypasses `shapeCall`, so it carries the hidden check with it.\n\tif (isConnector(shape)) {\n\t\tconst scoped = notes.forShape(shape.name || null)\n\t\tif (shape.hidden) {\n\t\t\tnoteHidden(scoped)\n\t\t\treturn null\n\t\t}\n\t\treturn connectorObject(shape, scoped)\n\t}\n\n\tconst call = shapeCall(shape, notes, assets)\n\tif (!call) return null\n\n\tconst shared = commonShapeVariant(call)\n\tif (shared) return shared\n\n\tconst [first, second] = call.args\n\tswitch (call.method) {\n\t\tcase 'addChart': {\n\t\t\t// `addChart(data, options)` carries the chart type inside its options, while a master\n\t\t\t// object names it separately. Lifted back out rather than moved: `addChildDefinition`\n\t\t\t// passes the whole options object on to `addChartDefinition` as well, which is where a\n\t\t\t// chart's `type` is read from in the first place.\n\t\t\tconst options = second !== null && typeof second === 'object' && !Array.isArray(second) && !isAssetRef(second) ? second : null // prettier-ignore\n\t\t\tconst type = options?.['type']\n\t\t\tif (type === undefined || first === undefined) return null\n\t\t\treturn { chart: compact({ type, data: first, opts: options }) ?? {} }\n\t\t}\n\t\tdefault:\n\t\t\tnotes\n\t\t\t\t.forShape(shape.name || null)\n\t\t\t\t.note(\n\t\t\t\t\t'decoration',\n\t\t\t\t\t'dropped',\n\t\t\t\t\t'unwritable',\n\t\t\t\t\t`a ${call.method.replace(/^add/, '').toLowerCase()} on a slide layout has no defineSlideMaster({ objects }) variant — the union covers a chart, an image, a shape and a text box — so it is dropped from the layout the output rebuilds`\n\t\t\t\t)\n\t\t\treturn null\n\t}\n}\n\n/**\n * A `Connector` as a `line` shape descriptor, which is the only way one reaches a layout.\n *\n * The alternative to this arm is dropping every connector a layout carries, and in the fixture\n * corpus that is 18 of the 45 shapes every layout actually draws — because PowerPoint's\n * line tool authors a `p:cxnSp`, so a plain horizontal rule under a title is usually a\n * connector rather than a shape. Drawing it as a `line` preset paints the identical stroke.\n *\n * What that costs is the endpoint binding, and on a layout it costs nothing that was working:\n * `a:stCxn`/`a:endCxn` reference shapes in the *layout's* tree, and nothing a slide later puts\n * on top is one of them. The slide-side `addConnector` mapping loses the binding too.\n *\n * It is also better than that mapping in one respect. `addConnector` takes two endpoints and\n * no rotation, so a rotated connector lands along the unrotated diagonal of its box; a shape\n * carries `rotate`, so this keeps it.\n */\nfunction connectorObject(shape: Connector, notes: NoteScope): IrValue | null {\n\tif (!shape.absoluteFrame) return null\n\n\tif (shape.startConnection || shape.endConnection) {\n\t\tnotes.note(\n\t\t\t'connector.binding',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t'this connector is bound to shapes on the layout; it is re-authored as a line shape, which paints the same stroke but no longer follows them'\n\t\t)\n\t}\n\n\t// No `fill`: a connector's `p:spPr` has no fill that a line geometry could show, and asking\n\t// `fillOption` for one would resolve the `p:style/a:fillRef` a `p:cxnSp` always carries into\n\t// a colour that paints nothing on the source and a filled box on the output.\n\tconst options = compact({\n\t\t...positionOptions(shape, notes),\n\t\t...transformOptions(shape),\n\t\tline: lineOption(shape, notes),\n\t\tshadow: shadowOption(shape, notes),\n\t\tglow: glowOption(shape),\n\t\tobjectName: shape.name || undefined,\n\t})\n\t// Through `compact` like the other arms, so every emitted descriptor spells its keys in the\n\t// same order and the printed script does not read as two different mappers.\n\treturn { shape: compact({ type: 'line', options: options ?? {} }) ?? {} }\n}\n","/**\n * The deck's shared chrome → {@link ChromeIr}: theme colours and fonts, plus one\n * `defineSlideMaster` descriptor per source layout.\n *\n * **Only a standalone output needs any of this,** and it is the part of a deck that survives\n * a conversion worst. A template-anchored output reuses the source package, so its masters,\n * layouts and theme are the originals byte for byte; everything below is the approximation\n * that replaces them when there is no template to inherit from. The notes it records are\n * therefore tier-scoped: real for a standalone script, and suppressed by the template-anchored\n * printer because they do not describe its output.\n *\n * **Two ceilings meet here, and neither moves by working harder on this file:**\n *\n * 1. `a:fmtScheme` is unreachable from *both* directions — no read accessor, and the write\n * path emits a hardcoded Office one. A shape whose look comes from `p:style` is repainted.\n * 2. `p:txStyles` has a write counterpart (`SlideMasterProps.textStyles`) and no reader, so\n * the per-level placeholder defaults are invisible.\n *\n * **A layout's decoration used to be a third, and is not any more.** `SlideLayout.shapes`\n * decodes it, and {@link masterObject} re-tags each shape as an entry in the layout's\n * `defineSlideMaster({ objects })` array — through the *same* mapper the slides use, so a band\n * or a wordmark on a layout is transcribed exactly as one on a slide would be. What is left of\n * the ceiling is narrow and named per shape (`layout.*`): a table has no variant in that\n * union, and a group is flattened into its children because the union has no `group` either.\n * A **master's** own decoration is still lost outright, and structurally so — `defineSlideMaster`\n * creates a *layout* under the one shared master, so a master's shape tree has no counterpart\n * to be written to.\n *\n * **Layout placeholders are deliberately not emitted, and that is a write-path finding rather\n * than a read-path one.** `addPlaceholdersToSlideLayouts` seeds *every* slide with each layout\n * placeholder the slide did not populate, as an empty text shape\n * (`src/gen/define/placeholder.ts`). Since this converter transcribes every source shape as\n * concrete absolute-positioned content and never binds one to a placeholder, reproducing the\n * layout's placeholders would add a ghost shape to every slide for each of them — shapes the\n * source deck does not have. Dropping them costs an editing affordance; emitting them would\n * cost the output's shape tree. It is also what makes the decoration walk below a *filter*\n * rather than a straight transcription of `SlideLayout.shapes`.\n */\nimport type { Presentation } from '../../read/api/presentation.js'\nimport type { SlideLayout, SlideMaster, Theme } from '../../read/api/chrome.js'\nimport type { SlideBackground } from '../../read/api/slide-background.js'\nimport { isGroupShape, type AnyShape } from '../../read/api/shapes.js'\nimport type { ChromeIr, IrValue, MasterIr, ThemeIr } from '../ir.js'\nimport { layoutShapeScope, type NoteScope } from '../fidelity.js'\nimport { masterObject, type AssetResolver } from './shape.js'\nimport { hasDecorativeShapes, hasFormatScheme, hasTextStyles, isPlaceholderShape } from './detect.js'\nimport { compact, literalColor, orUndefined } from './values.js'\nimport { DEFAULT_COLOR_MAP } from '../../ooxml/st-enums.js'\n\n/** Build the chrome IR for a deck. */\nexport function chromeToIr(pres: Presentation, notes: NoteScope, assets: AssetResolver): ChromeIr {\n\tconst masters = pres.masters()\n\n\tif (masters.length > 1) {\n\t\tnotes.note(\n\t\t\t'master.multiple',\n\t\t\t'flattened',\n\t\t\t'unsupported',\n\t\t\t`this deck has ${masters.length} slide masters; the write API models a deck as one shared master with many layouts, so every layout is rebuilt under a single master and only the first master's theme and colour map survive`\n\t\t)\n\t}\n\n\tconst first = masters[0]\n\tconst theme = first?.theme ?? null\n\trecordMasterLosses(masters, theme, notes)\n\n\treturn { theme: themeToIr(theme), masters: layoutsToIr(masters, notes, assets) }\n}\n\n/** The theme's colour scheme and font faces, in `ThemeProps` spelling. */\nfunction themeToIr(theme: Theme | null): ThemeIr {\n\tif (!theme) return {}\n\n\tconst scheme = theme.colorScheme\n\tconst colors: Record<string, string> = {}\n\tfor (const [slot, hex] of Object.entries(scheme)) {\n\t\tif (hex !== null) colors[slot] = literalColor(hex)\n\t}\n\n\tconst fonts = theme.fontScheme\n\treturn compact({\n\t\theadFontFace: orUndefined(fonts?.major.latin ?? null),\n\t\tbodyFontFace: orUndefined(fonts?.minor.latin ?? null),\n\t\theadFontFaceEA: orUndefined(fonts?.major.ea ?? null),\n\t\tbodyFontFaceEA: orUndefined(fonts?.minor.ea ?? null),\n\t\theadFontFaceCS: orUndefined(fonts?.major.cs ?? null),\n\t\tbodyFontFaceCS: orUndefined(fonts?.minor.cs ?? null),\n\t\tcolorScheme: Object.keys(colors).length > 0 ? colors : undefined,\n\t}) as ThemeIr\n}\n\n/** The losses that belong to the master/theme tier as a whole rather than to one layout. */\nfunction recordMasterLosses(masters: SlideMaster[], theme: Theme | null, notes: NoteScope): void {\n\tif (theme && hasFormatScheme(theme.element_)) {\n\t\tnotes.note(\n\t\t\t'theme.fmtScheme',\n\t\t\t'approximated',\n\t\t\t'unread',\n\t\t\t\"the theme's format scheme (a:fmtScheme — the three fill, line and effect style lists a shape's p:style indexes into) has no read accessor and no write-API option, so the output carries Office's default; a shape whose fill or outline came from the theme rather than from its own a:ln keeps its colour but not its width, dash or effect\"\n\t\t)\n\t}\n\n\tfor (const master of masters) {\n\t\tconst root = master.part.dom.documentElement\n\t\tif (hasTextStyles(root)) {\n\t\t\tnotes.note(\n\t\t\t\t'master.txStyles',\n\t\t\t\t'dropped',\n\t\t\t\t'unread',\n\t\t\t\t\"the master's per-level text styles (p:txStyles — the default size, face, colour, indent and bullet of each of the nine list levels) have no read accessor, so placeholder text falls back to PowerPoint's built-in defaults; SlideMasterProps.textStyles could author them if they could be seen\"\n\t\t\t)\n\t\t}\n\t\tif (hasDecorativeShapes(root)) {\n\t\t\tnotes.note(\n\t\t\t\t'master.decoration',\n\t\t\t\t'dropped',\n\t\t\t\t'unwritable',\n\t\t\t\t\"this slide master carries shapes that are not placeholders (a logo, a rule, a background graphic); the read model decodes them (SlideMaster.shapes) and a layout's are re-authored, but a master's cannot be — defineSlideMaster creates a layout under the one shared master, so the master's own shape tree has no write-side counterpart to receive them\"\n\t\t\t)\n\t\t}\n\n\t\tconst map = master.colorMap\n\t\tconst remapped = Object.entries(DEFAULT_COLOR_MAP).filter(\n\t\t\t([token, slot]) => map[token as keyof typeof map] !== slot\n\t\t)\n\t\tif (remapped.length > 0) {\n\t\t\tnotes.note(\n\t\t\t\t'master.colorMap',\n\t\t\t\t'dropped',\n\t\t\t\t'unwritable',\n\t\t\t\t`this master remaps ${remapped.map(([token]) => token).join(', ')} to a different theme slot and the write path always emits the identity map, so every scheme colour that passes through as a token resolves to a different hex than it did in the source`\n\t\t\t)\n\t\t}\n\t}\n}\n\n/**\n * One `defineSlideMaster` descriptor per source layout, in the same gallery order\n * `Presentation.layouts()` reports — which is what lets a slide bind by index.\n *\n * Titles are made unique because they are the lookup key `addSlide({ masterTitle })` matches\n * on, and `p:cSld@name` is not unique: a multi-master deck routinely carries several layouts\n * called \"Title and Content\", and two `defineSlideMaster` calls sharing a title would make\n * every slide bind to whichever won.\n */\nfunction layoutsToIr(masters: SlideMaster[], notes: NoteScope, assets: AssetResolver): MasterIr[] {\n\tconst out: MasterIr[] = []\n\tconst used = new Set<string>()\n\t// Rolled up rather than noted per layout: a 12-layout deck loses the placeholder definitions\n\t// on most of them, and twelve near-identical paragraphs at the top of the emitted script bury\n\t// the per-shape notes underneath that a reader can actually act on.\n\tlet placeholderCount = 0\n\tlet placeholderLayouts = 0\n\n\tconst renamed: string[] = []\n\tconst collided: string[] = []\n\n\tfor (const master of masters) {\n\t\tfor (const layout of master.layouts) {\n\t\t\tconst index = out.length\n\t\t\tconst flattened = flattenAttributeValue(layout.name)\n\t\t\tif (flattened !== layout.name) renamed.push(`${JSON.stringify(layout.name)} → ${JSON.stringify(flattened)}`)\n\t\t\tconst base = flattened || `Layout ${index + 1}`\n\t\t\tlet title = base\n\t\t\tfor (let suffix = 2; used.has(title); suffix++) title = `${base} (${suffix})`\n\t\t\tif (title !== base) collided.push(`${JSON.stringify(base)} → ${JSON.stringify(title)}`)\n\t\t\tused.add(title)\n\n\t\t\tconst placeholders = layout.placeholders.length\n\t\t\tif (placeholders > 0) {\n\t\t\t\tplaceholderCount += placeholders\n\t\t\t\tplaceholderLayouts++\n\t\t\t}\n\n\t\t\t// The layout's own background if it has one, else the master's — which is what a slide\n\t\t\t// bound to that layout actually shows, and the only tier the write API can set it at.\n\t\t\tconst background = backgroundProps(layout.background ?? master.background, notes, assets)\n\t\t\tconst objects = layoutObjects(layout, notes, assets)\n\t\t\tout.push({\n\t\t\t\tlayoutIndex: index,\n\t\t\t\tprops: compact({\n\t\t\t\t\ttitle,\n\t\t\t\t\tbackground,\n\t\t\t\t\tobjects: objects.length > 0 ? objects : undefined,\n\t\t\t\t}) as Record<string, IrValue>,\n\t\t\t})\n\t\t}\n\t}\n\n\tif (collided.length > 0) {\n\t\tnotes.note(\n\t\t\t'master.nameCollision',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t`${collided.length} layout name(s) are not unique in the source — normally because the deck has several masters, each with its own \"Title and Content\" — and a layout title here is also the key addSlide({ masterTitle }) binds on, so duplicates cannot both exist. The later ones are suffixed and the slides bound to them follow: ${collided.join('; ')}`\n\t\t)\n\t}\n\tif (renamed.length > 0) {\n\t\tnotes.note(\n\t\t\t'master.name',\n\t\t\t'flattened',\n\t\t\t'unwritable',\n\t\t\t`${renamed.length} layout name(s) contain a line break or tab, which cannot survive as a layout title: the write path emits the name as a literal XML attribute value rather than a character reference, and XML normalises whitespace in an attribute to spaces. Collapsed here so the emitted script says what the output will contain — ${renamed.join('; ')}`\n\t\t)\n\t}\n\tif (placeholderCount > 0) {\n\t\tnotes.note(\n\t\t\t'master.placeholders',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t`the ${placeholderCount} placeholder definition(s) across ${placeholderLayouts} slide layout(s) are not reproduced: the write path seeds every slide with each layout placeholder the slide did not populate, and since every source shape is authored here as concrete content rather than into a placeholder, re-declaring them would add an empty shape to every slide rather than a prompt`\n\t\t)\n\t}\n\n\treturn out\n}\n\n/**\n * A layout's own shapes as the `objects` of its `defineSlideMaster` call — the bands, rules,\n * wordmarks and footer graphics that make a deck recognisable as somebody's template.\n *\n * **Placeholders are filtered out, not mapped.** They are the other half of a layout's tree and\n * the write path already reproduces them from the far side: `addPlaceholdersToSlideLayouts`\n * seeds every slide with each layout placeholder it did not populate, so re-declaring one here\n * would put an empty ghost shape on every slide bound to the layout (see the module header).\n * The test is a DOM predicate rather than `shape.placeholder`, because only `AutoShape` reports\n * one — see {@link isPlaceholderShape}.\n *\n * **A group is flattened into its children rather than dropped.** `SlideMasterObject` has no\n * `group` variant, and unlike the slide-side `addGroup` mapping this loses nothing visual:\n * `absoluteFrame` already composes an enclosing group's offset, rotation, flips *and* its\n * child-space scaling, so each child lands exactly where the group put it. What goes is the\n * grouping itself — one selectable object in PowerPoint becomes several.\n *\n * Notes are recorded through a {@link layoutShapeScope}, so the slide vocabulary the shared\n * mapper speaks lands under `layout.` and stays attributable to the layout tier. Constructs\n * written below are therefore relative to that prefix.\n */\nfunction layoutObjects(layout: SlideLayout, notes: NoteScope, assets: AssetResolver): IrValue[] {\n\tconst out: IrValue[] = []\n\tcollectObjects(layout.shapes, out, layoutShapeScope(notes), assets)\n\treturn out\n}\n\n/** {@link layoutObjects}'s walk, recursing through groups. */\nfunction collectObjects(shapes: AnyShape[], out: IrValue[], notes: NoteScope, assets: AssetResolver): void {\n\tfor (const shape of shapes) {\n\t\tif (isPlaceholderShape(shape.element_)) continue\n\n\t\tif (isGroupShape(shape)) {\n\t\t\tnotes\n\t\t\t\t.forShape(shape.name || null)\n\t\t\t\t.note(\n\t\t\t\t\t'group',\n\t\t\t\t\t'flattened',\n\t\t\t\t\t'unwritable',\n\t\t\t\t\t\"defineSlideMaster({ objects }) has no group variant, so this group's children are emitted as loose objects; they land in the same places — the group's offset, rotation, flips and child-space scaling are composed into each child's coordinates — but the layout no longer offers them as one selectable object\"\n\t\t\t\t)\n\t\t\tcollectObjects(shape.shapes, out, notes, assets)\n\t\t\tcontinue\n\t\t}\n\n\t\t// `null` is always already noted, either by the shared mapper (a hidden shape, a picture\n\t\t// with no bytes) or by `masterObject` itself (a kind with no variant in the union).\n\t\tconst object = masterObject(shape, notes, assets)\n\t\tif (object !== null) out.push(object)\n\t}\n}\n\n/**\n * Collapse the whitespace an XML attribute value cannot carry.\n *\n * Not a style choice: XML normalises a literal tab, carriage return or line feed inside an\n * attribute value to a space (XML 1.0 §3.3.3), and the write path emits a layout title as a\n * literal rather than as a ` ` character reference. So a PowerPoint layout named across\n * two lines — \"Abschnitts-⏎überschrift\" is a real one, in the German built-in set — comes back\n * with a space either way. Doing it here rather than leaving it to the serializer means the\n * emitted script states the title the output will actually have, and the round trip compares\n * two decks that agree instead of reporting a rename it cannot act on.\n */\nfunction flattenAttributeValue(value: string): string {\n\treturn value.replace(/[\\t\\r\\n]+/g, ' ')\n}\n\n/** A master/layout background reduced to what `BackgroundProps` accepts. */\nfunction backgroundProps(\n\tbackground: SlideBackground | null,\n\tnotes: NoteScope,\n\tassets: AssetResolver\n): IrValue | undefined {\n\tif (!background || background.type === 'none') return undefined\n\n\tswitch (background.type) {\n\t\tcase 'solid':\n\t\t\treturn background.color ? { color: literalColor(background.color.effectiveHex) } : undefined\n\t\tcase 'image': {\n\t\t\tconst asset = background.partName === null ? null : assets.assetFor(background.partName)\n\t\t\treturn asset ? { data: asset } : undefined\n\t\t}\n\t\tcase 'themeRef': {\n\t\t\t// `p:bgRef` indexes the theme's background fill list, which the write path cannot\n\t\t\t// author. The read model resolves it, so the flat colour survives even though the\n\t\t\t// reference — and therefore its response to a theme change — does not.\n\t\t\tconst fill = background.resolvedFill\n\t\t\tif (fill?.type === 'solid' && fill.color) {\n\t\t\t\tnotes.note(\n\t\t\t\t\t'master.background',\n\t\t\t\t\t'flattened',\n\t\t\t\t\t'unwritable',\n\t\t\t\t\t\"this layout's background is a theme reference (p:bgRef into the theme's background fill list), which has no write-API option; the colour it currently resolves to is baked in and stops following the theme\"\n\t\t\t\t)\n\t\t\t\treturn { color: literalColor(fill.color.effectiveHex) }\n\t\t\t}\n\t\t\tnotes.note(\n\t\t\t\t'master.background',\n\t\t\t\t'dropped',\n\t\t\t\t'unwritable',\n\t\t\t\t\"this layout's background is a theme reference to a non-solid fill, which has no write-API option; the layout is emitted with no background\"\n\t\t\t)\n\t\t\treturn undefined\n\t\t}\n\t\tdefault:\n\t\t\tnotes.note(\n\t\t\t\t'master.background',\n\t\t\t\t'dropped',\n\t\t\t\t'unsupported',\n\t\t\t\t`a ${background.type} layout background is not expressible through the write API's background option, so the layout is emitted with no background`\n\t\t\t)\n\t\t\treturn undefined\n\t}\n}\n","/**\n * A slide's show transition (`p:transition`) → the write API's `TransitionProps`.\n *\n * **The whole difficulty is one type mismatch.** `TransitionInfo.type` is an *open string*,\n * because the read model decodes PowerPoint's modern effects (Morph, Vortex, Ripple, …)\n * alongside the base ECMA-376 ones and tells them apart by namespace rather than by name.\n * The write API's `TransitionType` is a closed union of 21 base names. Passing the read\n * model's string straight through would therefore produce a script that does not compile\n * for exactly the decks a converter is most likely to meet — a modern transition is what\n * PowerPoint's own UI offers first. So {@link WRITABLE_TYPES} is the filter, and a name that\n * does not survive it becomes a fidelity note rather than a compile error.\n *\n * **Why `speed` is always emitted.** `spd` is absent from most PowerPoint-authored\n * transitions (its schema default is `fast`) and the read model reports the default rather\n * than the absence, so there is nothing to distinguish \"absent\" from \"explicitly fast\". That\n * is harmless on its own — both read back as `fast`. What is *not* harmless is omitting it\n * when a duration is present: the write path then derives the bucket from `durationMs`\n * (`transitionSpeedForDuration`), and PowerPoint's own pairing does not always agree with\n * that formula — the sound fixture carries `spd=\"slow\"` with `p14:dur=\"2000\"`, which the\n * derivation happens to reproduce, while a 600ms `fast` transition would come back `med`.\n * Emitting the read value verbatim removes the derivation from the path entirely, which is\n * the same discipline the rest of the IR follows: state what was read, never recompute it.\n */\nimport type { Slide } from '../../read/api/slide.js'\nimport type { TransitionInfo } from '../../read/api/transition.js'\nimport type { TransitionType } from '../../types/animation.js'\nimport type { NoteScope } from '../fidelity.js'\nimport type { TransitionIr, TransitionSoundIr } from '../ir.js'\nimport type { AssetResolver } from './shape.js'\n\n/**\n * The transitions the write API can author, as a lookup.\n *\n * Spelled as a `Record` keyed by `TransitionType` rather than as an array of strings so the\n * compiler polices it in *both* directions: a name the union does not have is rejected here,\n * and a name the union gains without being added here fails to satisfy the record. A plain\n * `Set<string>` would silently drift out of date, and the symptom would be a printed script\n * that does not compile — found by whoever runs it, not by this repository's test suite.\n */\nconst WRITABLE_TYPES: Record<TransitionType, true> = {\n\tblinds: true,\n\tchecker: true,\n\tcircle: true,\n\tcomb: true,\n\tcover: true,\n\tcut: true,\n\tdiamond: true,\n\tdissolve: true,\n\tfade: true,\n\tnewsflash: true,\n\tplus: true,\n\tpull: true,\n\tpush: true,\n\trandom: true,\n\trandomBar: true,\n\tsplit: true,\n\tstrips: true,\n\twedge: true,\n\twheel: true,\n\twipe: true,\n\tzoom: true,\n}\n\n/**\n * `true` when the write API has a name for this transition.\n *\n * The namespace check does no work on PowerPoint's own output and is kept anyway. Every one\n * of the 21 modern effect names in the probed table (`conveyor`, `morph`, `vortex`, …) is\n * distinct from every base name, so today the name lookup alone would reach the same verdict\n * — measured, not assumed. But \"is this a base ECMA-376 transition\" is a question about the\n * *namespace*, and answering it by name would be relying on that disjointness holding for\n * every namespace Microsoft ever adds. The write path emits `p:${type}` unconditionally, so\n * the cost of being wrong is a modern effect silently rewritten as a base one with the same\n * name and no note — a conversion that reports itself as faithful. `script-ir.test.js`\n * authors a `p14:fade` to keep this branch honest, since no fixture can.\n */\nfunction isWritable(info: TransitionInfo): boolean {\n\treturn info.namespace === 'p' && Object.hasOwn(WRITABLE_TYPES, info.type)\n}\n\n/**\n * Map a slide's transition, recording a note for anything that does not survive.\n *\n * Returns `undefined` both when the slide has no transition and when it has one this\n * library cannot author — the difference between those two is what the note carries.\n */\nexport function transitionToIr(slide: Slide, notes: NoteScope, assets: AssetResolver): TransitionIr | undefined {\n\tconst info = slide.transition\n\tif (!info) return undefined\n\n\tif (!isWritable(info)) {\n\t\tnotes.note(\n\t\t\t'slide.transition',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t`this slide's ${info.namespace === 'p' ? '' : `${info.namespace} `}${info.type} transition is not one of the 21 base ECMA-376 transitions the write API can author${\n\t\t\t\tinfo.namespace === 'p' ? '' : \" — it is one of PowerPoint's modern effects, which have no write-API vocabulary\"\n\t\t\t}, so the regenerated slide advances with no effect`\n\t\t)\n\t\treturn undefined\n\t}\n\n\t// Each optional key is spread in only when the source carried it, so an absent attribute\n\t// stays absent rather than becoming an explicit default the source never wrote.\n\tconst sound = soundToIr(slide, info, notes, assets)\n\treturn {\n\t\ttype: info.type,\n\t\tspeed: info.speed,\n\t\t...(info.durationMs === null ? {} : { durationMs: info.durationMs }),\n\t\t// Both are omitted at their OOXML default, so the emitted script says only what the\n\t\t// source said: `advClick` defaults to true and `advTm` to unset.\n\t\t...(info.advanceOnClick ? {} : { advanceOnClick: false }),\n\t\t...(info.advanceAfterMs === null ? {} : { advanceAfterMs: info.advanceAfterMs }),\n\t\t...(Object.keys(info.variant).length > 0 ? { variant: { ...info.variant } } : {}),\n\t\t...(sound ? { sound } : {}),\n\t}\n}\n\n/**\n * The transition's sound (`p:sndAc`), in the two forms OOXML gives it.\n *\n * The stop-previous form is pure structure — no relationship, no media part — so it maps\n * unconditionally. A start sound is an embedded WAV reached through the slide's own\n * relationships, which is the only place in this converter that resolves an `r:embed` by\n * hand: every other media reference arrives already resolved to a partname by the read\n * model's shape accessors, and a transition sound has no shape to hang off.\n */\nfunction soundToIr(\n\tslide: Slide,\n\tinfo: TransitionInfo,\n\tnotes: NoteScope,\n\tassets: AssetResolver\n): TransitionSoundIr | undefined {\n\tconst sound = info.sound\n\tif (!sound) return undefined\n\tif (sound.form === 'stop') return { stopPrevious: true }\n\n\tconst partName = soundPartName(slide, sound.embedRid)\n\tconst asset = partName === null ? null : assets.assetFor(partName)\n\tif (!asset) {\n\t\tnotes.note(\n\t\t\t'slide.transitionSound',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t`this transition's start sound (${sound.embedRid ?? 'no r:embed'}) does not resolve to an audio part in the package, so the regenerated transition is silent`\n\t\t)\n\t\treturn undefined\n\t}\n\n\treturn {\n\t\tdata: asset,\n\t\t...(sound.name === null ? {} : { name: sound.name }),\n\t\t// Omitted at its default, like `advanceOnClick`: `p:stSnd@loop` defaults to false.\n\t\t...(sound.loop ? { loop: true } : {}),\n\t}\n}\n\n/** Resolve `p:snd@r:embed` to the audio part it names, or `null` when it does not resolve. */\nfunction soundPartName(slide: Slide, embedRid: string | null): string | null {\n\tif (!embedRid) return null\n\tconst relationship = slide.relationships.get(embedRid)\n\t// An External audio rel has no partname to read bytes from; `resolveTarget` throws on\n\t// both cases, so they are screened here rather than caught.\n\tif (!relationship || relationship.targetMode === 'External') return null\n\treturn slide.relationships.resolveTarget(embedRid)\n}\n","/**\n * `Presentation` → {@link DeckIr}. The entry point of the read half.\n *\n * Pure in the sense that matters: it reads a loaded package and returns data, touching no\n * filesystem and mutating nothing. Given the same bytes it returns the same IR, so a\n * round-trip check can compare two runs directly.\n *\n * The one judgement made at this level rather than per-shape is {@link SlideSource}. A\n * slide holding a construct the write API cannot express *at all* — a graphic frame with a\n * complete reader and no emitter, which today means an extended chart, a SmartArt diagram,\n * an OLE object or ink — cannot be honestly transcribed, because the output would silently\n * differ from the source. Such a slide is marked `carried` so the printer copies it instead.\n * That decision has to be made here, before any shape is mapped, since it is a property of\n * the slide as a whole.\n */\nimport type { Presentation } from '../../read/api/presentation.js'\nimport type { Slide } from '../../read/api/slide.js'\nimport { isGraphicFrame, isGroupShape, type AnyShape } from '../../read/api/shapes.js'\nimport { NoteCollector, scopeNotes, type NoteScope } from '../fidelity.js'\nimport type { AssetIr, AssetRef, BackgroundIr, CallIr, DeckIr, DeckPropsIr, SlideIr, SlideLayoutIr } from '../ir.js'\nimport { shapeCall, unwritableFramePayload, type AssetResolver } from './shape.js'\nimport { chromeToIr } from './chrome.js'\nimport { transitionToIr } from './transition.js'\nimport { compact } from './values.js'\n\n/** Default slide size (10\" × 7.5\") for a deck whose `presentation.xml` declares none. */\nconst DEFAULT_SLIDE_SIZE = { widthEmu: 9144000, heightEmu: 6858000 }\n\n/** Extensions by content type, so an emitted asset filename is one a viewer recognises. */\nconst ASSET_EXTENSIONS: Record<string, string> = {\n\t'image/png': 'png',\n\t'image/jpeg': 'jpg',\n\t'image/gif': 'gif',\n\t'image/bmp': 'bmp',\n\t'image/webp': 'webp',\n\t'image/tiff': 'tif',\n\t'image/x-emf': 'emf',\n\t'image/x-wmf': 'wmf',\n\t'image/svg+xml': 'svg',\n\t// PowerPoint authors the `x-` form for an embedded transition sound; both spellings\n\t// appear in the wild and neither has `wav` as its trailing path component.\n\t'audio/x-wav': 'wav',\n\t'audio/wav': 'wav',\n\t'audio/mpeg': 'mp3',\n}\n\n/**\n * Collects media as shapes reference it, assigning each part a stable sequential name.\n *\n * Names are assigned in first-reference order rather than derived from the source part\n * name, so the output is deterministic for a given deck and does not leak whatever the\n * source package happened to call its files. A part referenced twice resolves to one asset.\n *\n * Numbering runs per *kind* (`image1.png`, `image2.png`, `audio1.wav`) rather than over one\n * shared counter. Not cosmetics: the asset name becomes a `const` identifier in the emitted\n * script and a filename in its asset directory, and a transition sound bound to `image7`\n * reads as a bug in the generated source every time anyone opens it.\n */\nclass Assets implements AssetResolver {\n\treadonly #byPartName = new Map<string, AssetRef>()\n\treadonly #assets: AssetIr[] = []\n\treadonly #counts = new Map<string, number>()\n\n\tconstructor(private readonly pres: Presentation) {}\n\n\tassetFor(partName: string): AssetRef | null {\n\t\tconst existing = this.#byPartName.get(partName)\n\t\tif (existing) return existing\n\n\t\tconst part = this.pres.opc.part(partName)\n\t\tif (!part) return null\n\n\t\tconst extension = ASSET_EXTENSIONS[part.contentType] ?? partName.split('.').pop() ?? 'bin'\n\t\tconst kind = part.contentType.startsWith('audio/') ? 'audio' : 'image'\n\t\tconst index = (this.#counts.get(kind) ?? 0) + 1\n\t\tthis.#counts.set(kind, index)\n\t\tconst name = `${kind}${index}.${extension}`\n\t\tconst ref: AssetRef = { $asset: name }\n\t\tthis.#byPartName.set(partName, ref)\n\t\tthis.#assets.push({ name, contentType: part.contentType, bytes: part.bytes })\n\t\treturn ref\n\t}\n\n\tcontentTypeOf(partName: string): string | null {\n\t\treturn this.pres.opc.part(partName)?.contentType ?? null\n\t}\n\n\tget assets(): AssetIr[] {\n\t\treturn this.#assets\n\t}\n}\n\n/** Convert a loaded deck into its IR. */\nexport function readModelToIr(pres: Presentation): DeckIr {\n\tconst collector = new NoteCollector()\n\tconst assets = new Assets(pres)\n\tconst size = pres.slideSize\n\tconst deckScope = scopeNotes(collector, null)\n\n\tif (!size) {\n\t\tdeckScope.note(\n\t\t\t'deck.slideSize',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t`this deck declares no slide size, so the output uses the ${DEFAULT_SLIDE_SIZE.widthEmu / 914400}in × ${DEFAULT_SLIDE_SIZE.heightEmu / 914400}in default`\n\t\t)\n\t}\n\n\tconst layouts = layoutGallery(pres)\n\t// Before the slides, so the chrome's deck-level notes lead the list the way the chrome\n\t// leads the deck. Assets are shared: a layout background image and a slide image that are\n\t// the same part resolve to one asset.\n\tconst chrome = chromeToIr(pres, deckScope, assets)\n\tconst slides = pres.slides.map((slide, index) => slideToIr(slide, index + 1, collector, assets, layouts))\n\n\treturn {\n\t\tslideSize: size ? { widthEmu: size.widthEmu, heightEmu: size.heightEmu } : DEFAULT_SLIDE_SIZE,\n\t\tprops: deckProps(pres, deckScope),\n\t\tchrome,\n\t\tslides,\n\t\tassets: assets.assets,\n\t\tfidelity: collector.notes,\n\t}\n}\n\n/**\n * Deck properties, reduced to the five `docProps` fields the write API sets. The other\n * seven the read model exposes have no setter — they survive anyway in a template-anchored\n * output, since the source deck itself becomes the template, so this is only a loss for a\n * standalone one.\n */\nfunction deckProps(pres: Presentation, notes: NoteScope): DeckPropsIr {\n\tconst core = pres.coreProperties\n\tconst carried = ['keywords', 'description', 'category', 'contentStatus', 'lastModifiedBy'] as const\n\tif (carried.some((key) => core[key] !== undefined)) {\n\t\tnotes.note(\n\t\t\t'deck.docProps',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'only title, author, company, subject and revision have write-API setters; keywords, description, category, content status and last-modified-by have none'\n\t\t)\n\t}\n\treturn (\n\t\tcompact({\n\t\t\ttitle: core.title,\n\t\t\tauthor: core.creator,\n\t\t\tsubject: core.subject,\n\t\t\trevision: core.revision,\n\t\t}) ?? {}\n\t)\n}\n\n/**\n * The deck's layouts keyed by partname, each resolved to what a printer needs to bind to\n * it: its gallery position and whether its name identifies it on its own.\n *\n * Built once per deck rather than per slide — `layouts()` walks every master's layout list,\n * and the uniqueness question is about the gallery as a whole, so asking it per slide would\n * be both quadratic and unable to see layouts no slide happens to use.\n */\nfunction layoutGallery(pres: Presentation): Map<string, SlideLayoutIr> {\n\tconst handles = pres.layouts()\n\tconst nameCounts = new Map<string, number>()\n\tfor (const handle of handles) nameCounts.set(handle.name, (nameCounts.get(handle.name) ?? 0) + 1)\n\n\treturn new Map(\n\t\thandles.map((handle, index) => [\n\t\t\thandle.partName,\n\t\t\t{ name: handle.name, index, nameIsUnique: (nameCounts.get(handle.name) ?? 0) === 1 },\n\t\t])\n\t)\n}\n\nfunction slideToIr(\n\tslide: Slide,\n\tnumber: number,\n\tcollector: NoteCollector,\n\tassets: Assets,\n\tlayouts: Map<string, SlideLayoutIr>\n): SlideIr {\n\tconst notes = scopeNotes(collector, number)\n\tconst layoutPartName = slide.layout?.partName\n\tconst base = {\n\t\tnumber,\n\t\tlayout: (layoutPartName === undefined ? undefined : layouts.get(layoutPartName)) ?? null,\n\t\thidden: slide.hidden,\n\t\t...(slide.name ? { name: slide.name } : {}),\n\t\t...backgroundOf(slide, notes),\n\t\t...notesOf(slide, notes),\n\t}\n\n\tconst transition = transitionToIr(slide, notes, assets)\n\tconst carried = hasUnwritableContent(slide)\n\tif (carried) {\n\t\tnotes.note(\n\t\t\t'slide.carried',\n\t\t\t'flattened',\n\t\t\t'unwritable',\n\t\t\t'this slide holds a graphic frame the write API cannot author (an extended chart, a SmartArt diagram, an OLE object or ink); a printer that can copy the source slide does so instead of transcribing it, so it renders correctly but the emitted script does not describe its contents. The per-shape note beside this one says which construct forced the copy'\n\t\t)\n\t}\n\n\t// Mapped even for a carried slide: a printer with no source package to copy from prints\n\t// these and loses only the unwritable construct, rather than the whole slide. Each shape\n\t// records its own note, so that loss is declared either way.\n\tconst calls: CallIr[] = []\n\tfor (const shape of slide.shapes) {\n\t\tconst call = shapeCall(shape, notes, assets)\n\t\tif (call) calls.push(call)\n\t}\n\n\t// Build animations are recorded once per slide rather than per shape, since they live in a\n\t// slide-scoped element with no shape to attribute them to.\n\trecordAnimationLoss(slide, notes)\n\n\treturn {\n\t\t...base,\n\t\t...(transition ? { transition } : {}),\n\t\tsource: carried ? 'carried' : 'authored',\n\t\tcalls,\n\t}\n}\n\n/**\n * `true` when the slide holds something with no write-API expression at all, forcing a\n * carried slide. Descends into groups, since a group can host a graphic frame.\n *\n * Membership comes from {@link unwritableFramePayload}, which `graphicFrameCall` also uses to\n * pick its note — one enumeration, so the two cannot drift apart again. This test named\n * extended charts alone until then, which is why a slide holding SmartArt (or an OLE object,\n * or ink) was transcribed as `authored` and rendered with a hole where the graphic had been.\n */\nfunction hasUnwritableContent(slide: Slide): boolean {\n\tconst check = (shapes: AnyShape[]): boolean =>\n\t\tshapes.some((shape) => {\n\t\t\tif (isGroupShape(shape)) return check(shape.shapes)\n\t\t\treturn isGraphicFrame(shape) && unwritableFramePayload(shape) !== null\n\t\t})\n\treturn check(slide.shapes)\n}\n\nfunction backgroundOf(slide: Slide, notes: NoteScope): { background?: BackgroundIr } {\n\tconst background = slide.background\n\t// An inherited background comes with the layout, so re-authoring it onto the slide would\n\t// pin a colour that should keep following the layout.\n\tif (!background || background.source !== 'slide') return {}\n\n\tswitch (background.type) {\n\t\tcase 'solid':\n\t\t\treturn background.color\n\t\t\t\t? { background: compact({ color: background.color.effectiveHex.replace(/^#/, '').toUpperCase() }) }\n\t\t\t\t: {}\n\t\tcase 'none':\n\t\t\treturn {}\n\t\tdefault:\n\t\t\tnotes.note(\n\t\t\t\t'slide.background',\n\t\t\t\t'dropped',\n\t\t\t\t'unsupported',\n\t\t\t\t`a ${background.type} slide background is not expressible through the write API's background option, so the slide takes its layout's background`\n\t\t\t)\n\t\t\treturn {}\n\t}\n}\n\nfunction notesOf(slide: Slide, notes: NoteScope): { notesText?: string } {\n\tconst text = slide.notesText\n\tif (!text) return {}\n\tconst frame = slide.notesTextFrame\n\tif (frame && frame.paragraphs.some((paragraph) => paragraph.runs.some((run) => run.bold || run.italic))) {\n\t\tnotes.note(\n\t\t\t'notes.formatting',\n\t\t\t'flattened',\n\t\t\t'unsupported',\n\t\t\t\"speaker notes carry as plain text; per-run formatting and the notes slide's own placeholder geometry do not\"\n\t\t)\n\t}\n\treturn { notesText: text }\n}\n\n/**\n * Build animations, which live in a slide-scoped `p:timing` element rather than in any\n * shape's subtree.\n *\n * The transition next door used to be recorded here for the same reason and is now mapped\n * instead (`from-read/transition.ts`), which leaves this the one genuinely slide-scoped\n * loss: there is no structural reader for `p:timing` at all, only spid manipulation for the\n * deck-to-deck import path, so a build sequence is invisible to this converter.\n */\nfunction recordAnimationLoss(slide: Slide, notes: NoteScope): void {\n\tif (slide.hasAnimations) {\n\t\tnotes.note(\n\t\t\t'slide.animation',\n\t\t\t'dropped',\n\t\t\t'unread',\n\t\t\t'build animations have no structural reader (p:timing is only manipulated by spid for the deck-to-deck import path), so every shape on this slide lands static'\n\t\t)\n\t}\n}\n","/**\n * {@link IrValue} → TypeScript source text.\n *\n * This module is deliberately the dumbest part of the subsystem. It knows nothing about\n * decks, shapes, or units — only how a value is spelled. Every semantic decision was made\n * upstream in the read half, which is what lets the printed text be checked by comparing\n * IRs rather than by reading source: if this file were allowed to interpret, the same\n * construct could mean two things depending on which half you asked.\n *\n * Two consequences worth stating, because they are easy to erode later:\n *\n * - **Numbers are printed, not reformatted.** The IR already holds geometry either as a\n * `` `${n}emu` `` string (exact) or as a six-decimal inch number (the proven minimum for\n * an EMU-exact round-trip). Rounding here to suppress `0.5000000001`-style noise would\n * turn a cosmetic problem into a real geometry loss, so `printNumber` only refuses\n * values JavaScript cannot spell back.\n * - **Layout is a function of the value alone.** Whether an object prints on one line or\n * several depends only on its rendered width, never on where it came from, so the same\n * deck prints byte-identical text every time.\n */\nimport { isAssetRef, type AssetRef, type IrValue } from '../ir.js'\nimport { InvalidOptionError } from '../../errors.js'\n\n/** Matches `.oxfmtrc.jsonc`: `printWidth: 120`. */\nconst MAX_WIDTH = 120\n\n/**\n * Columns a tab is assumed to occupy when measuring against {@link MAX_WIDTH}. The\n * formatter's default `tabWidth`, since the repo sets `useTabs` but not `tabWidth`.\n */\nconst TAB_COLUMNS = 2\n\n/** A bare object key needs no quotes only if it is a plain identifier. */\nconst IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/\n\n/**\n * Resolves an {@link AssetRef} to the source text that stands in for it — a `const`\n * identifier when assets are written as files, an inline `data:` literal otherwise. The\n * printer takes this as a callback rather than deciding itself, because the choice belongs\n * to the caller's output layout, not to how a value is spelled.\n */\nexport type AssetPrinter = (ref: AssetRef) => string\n\n/**\n * A string literal in the repo's style (`singleQuote: true`).\n *\n * Deck text is arbitrary user content, so every case below is reachable in practice: a\n * quote, a backslash, a hard line break inside a run. `JSON.stringify` would handle those\n * correctly — it is avoided here for the quote style, not for correctness.\n */\nexport function printString(value: string): string {\n\tlet out = \"'\"\n\tfor (const char of value) {\n\t\tswitch (char) {\n\t\t\tcase '\\\\':\n\t\t\t\tout += '\\\\\\\\'\n\t\t\t\tbreak\n\t\t\tcase \"'\":\n\t\t\t\tout += \"\\\\'\"\n\t\t\t\tbreak\n\t\t\tcase '\\n':\n\t\t\t\tout += '\\\\n'\n\t\t\t\tbreak\n\t\t\tcase '\\r':\n\t\t\t\tout += '\\\\r'\n\t\t\t\tbreak\n\t\t\tcase '\\t':\n\t\t\t\tout += '\\\\t'\n\t\t\t\tbreak\n\t\t\tdefault: {\n\t\t\t\tconst code = char.codePointAt(0) ?? 0\n\t\t\t\t// C0/C1 controls have no visible spelling, so a raw one is invisible corruption.\n\t\t\t\t// U+2028/U+2029 have been legal inside a string literal since ES2019 and do not\n\t\t\t\t// strictly need escaping for a modern engine — they are escaped anyway because\n\t\t\t\t// they remain line terminators everywhere *else* in the grammar, and a file that\n\t\t\t\t// depends on that distinction is a poor thing to hand to an unknown toolchain.\n\t\t\t\t// Everything else rides through, so the script stays readable in the deck's language.\n\t\t\t\tconst escape = code < 0x20 || (code >= 0x7f && code <= 0x9f) || code === 0x2028 || code === 0x2029\n\t\t\t\tout += escape ? '\\\\u' + code.toString(16).padStart(4, '0') : char\n\t\t\t}\n\t\t}\n\t}\n\treturn `${out}'`\n}\n\n/**\n * A number literal. `String` gives the shortest text that reads back as the same double,\n * which is exactly the guarantee needed: the printed script must produce the same value the\n * IR held. Non-finite values cannot satisfy that (`NaN` and `Infinity` are identifiers, not\n * literals) and never reach here from a well-formed IR, so they throw rather than emit\n * source that would not run.\n */\nfunction printNumber(value: number): string {\n\tif (!Number.isFinite(value))\n\t\tthrow new InvalidOptionError('script/non-finite-literal', `Cannot print a non-finite number: ${value}`)\n\treturn String(value)\n}\n\n/** An object key, bare when it is a plain identifier and quoted when it is not. */\nfunction printKey(key: string): string {\n\treturn IDENTIFIER.test(key) ? key : printString(key)\n}\n\n/** The value on a single line, however long that line comes out. */\nfunction inline(value: IrValue, asset: AssetPrinter): string {\n\tif (value === null) return 'null'\n\tif (typeof value === 'boolean') return String(value)\n\tif (typeof value === 'number') return printNumber(value)\n\tif (typeof value === 'string') return printString(value)\n\tif (isAssetRef(value)) return asset(value)\n\tif (Array.isArray(value)) return `[${value.map((item) => inline(item, asset)).join(', ')}]`\n\n\tconst keys = Object.keys(value)\n\tif (keys.length === 0) return '{}'\n\treturn `{ ${keys.map((key) => `${printKey(key)}: ${inline(value[key] as IrValue, asset)}`).join(', ')} }`\n}\n\n/**\n * The value as source text, broken across lines only where it would otherwise overflow\n * {@link MAX_WIDTH}.\n *\n * `indentLevel` is the depth the value *starts* at, so a caller that has already written a\n * prefix (`slide1.addText(`) passes the level its closing brace should line up with.\n */\nexport function printValue(value: IrValue, indentLevel: number, asset: AssetPrinter): string {\n\tconst flat = inline(value, asset)\n\tif (indentLevel * TAB_COLUMNS + flat.length <= MAX_WIDTH) return flat\n\n\t// Only containers can be broken up; a single long string or number stays long.\n\tconst pad = '\\t'.repeat(indentLevel)\n\tconst inner = '\\t'.repeat(indentLevel + 1)\n\n\tif (Array.isArray(value)) {\n\t\tif (value.length === 0) return '[]'\n\t\tconst items = value.map((item) => `${inner}${printValue(item, indentLevel + 1, asset)},`)\n\t\treturn `[\\n${items.join('\\n')}\\n${pad}]`\n\t}\n\n\tif (typeof value === 'object' && value !== null && !isAssetRef(value)) {\n\t\tconst keys = Object.keys(value)\n\t\tif (keys.length === 0) return '{}'\n\t\tconst entries = keys.map(\n\t\t\t(key) => `${inner}${printKey(key)}: ${printValue(value[key] as IrValue, indentLevel + 1, asset)},`\n\t\t)\n\t\treturn `{\\n${entries.join('\\n')}\\n${pad}}`\n\t}\n\n\treturn flat\n}\n\n/**\n * A call's argument list, either inline after `prefix` or one argument per line.\n *\n * The decision is made on the *whole* call rather than per argument, so a call either reads\n * as one line or as a list — never as a short first argument followed by a hanging brace,\n * which is what a per-argument rule produces.\n */\nexport function printArguments(prefix: string, args: IrValue[], indentLevel: number, asset: AssetPrinter): string {\n\tconst pad = '\\t'.repeat(indentLevel)\n\tconst flat = `${pad}${prefix}(${args.map((arg) => inline(arg, asset)).join(', ')})`\n\tif (indentLevel * TAB_COLUMNS + flat.length - pad.length <= MAX_WIDTH) return flat\n\n\t// No trailing comma after the final argument: `trailingComma: 'es5'` adds them inside\n\t// objects and arrays but not to an argument list, so one here would be reformatted away.\n\tconst inner = '\\t'.repeat(indentLevel + 1)\n\tconst printed = args.map((arg) => `${inner}${printValue(arg, indentLevel + 1, asset)}`)\n\treturn `${pad}${prefix}(\\n${printed.join(',\\n')}\\n${pad})`\n}\n","/**\n * The parts of printing a script that do not depend on which tier is being printed.\n *\n * Two printers target the same IR — one anchored to the source deck as a template, one\n * standalone — and they differ only in how a deck and its chrome are set up. Everything after\n * that is identical: a slide's statements, how image bytes reach the script, and how the\n * fidelity notes are rendered into the banner. Keeping that here is not tidiness. A slide body\n * printed two slightly different ways would mean the round-trip oracle certifies one tier and\n * only resembles a check on the other, and the drift would be invisible in review.\n */\nimport { asIrValue, type AssetRef, type DeckIr, type IrValue, type SlideIr } from '../ir.js'\nimport { scopeNotes, type FidelityNote, type NoteCollector } from '../fidelity.js'\nimport { printArguments, printString, printValue, type AssetPrinter } from './literal.js'\nimport { InvalidOptionError } from '../../errors.js'\n\n/** How image bytes reach the emitted script. */\nexport type AssetMode =\n\t/** Written beside the script and read at run time. Keeps the script readable. */\n\t| 'file'\n\t/** Inlined as `data:` literals. One self-contained file, at roughly 4/3 the byte size. */\n\t| 'inline'\n\nexport interface PrintedScript {\n\t/** The TypeScript module source. */\n\tcode: string\n\t/**\n\t * Image bytes the script expects to find in its asset directory, keyed by filename.\n\t * Empty when the print options asked for `'inline'`, since the bytes are then in\n\t * {@link code}.\n\t */\n\tassets: Map<string, Uint8Array>\n\t/**\n\t * The losses that apply to **this** output: the IR's own notes, minus any this tier\n\t * rescues, plus the ones this tier causes. Reproduced as a comment block at the top of\n\t * {@link code}, so the artifact carries its own caveats.\n\t */\n\tnotes: FidelityNote[]\n}\n\n/**\n * Default import specifier for an emitted script — this package's *published* name, which is\n * not its directory name. Getting it wrong produces a script that prints and typechecks and\n * then fails at `import`, so it is pinned by a test rather than left to a literal.\n */\nexport const PACKAGE_NAME = '@shbernal/ts-pptx'\n\n/** The print options both tiers share, with their defaults applied. */\nexport interface ResolvedPrintOptions {\n\t/** Where the emitted script writes its deck, resolved against the script's own location. */\n\toutputPath: string\n\t/** Where the emitted script reads image assets from, with any trailing slash stripped. */\n\tassetDir: string\n\t/** Whether image bytes are written beside the script or inlined as `data:` literals. */\n\tassetMode: AssetMode\n\t/** The import specifier the emitted script uses. */\n\tpackageName: string\n}\n\n/**\n * Apply the defaults both printers share.\n *\n * `templatePath` is deliberately not here: only the template-anchored tier has one, and that\n * difference is the whole reason there are two printers.\n * @param options - the caller's options, any of which may be absent\n */\nexport function resolvePrintOptions(options: {\n\toutputPath?: string\n\tassetDir?: string\n\tassets?: AssetMode\n\tpackageName?: string\n}): ResolvedPrintOptions {\n\treturn {\n\t\toutputPath: options.outputPath ?? './output.pptx',\n\t\t// A trailing slash would print `./assets/` and then join another, so it is stripped once\n\t\t// here rather than defended against at each of the places the directory is interpolated.\n\t\tassetDir: (options.assetDir ?? './assets').replace(/\\/$/, ''),\n\t\tassetMode: options.assets ?? 'file',\n\t\tpackageName: options.packageName ?? PACKAGE_NAME,\n\t}\n}\n\n/** Width the header comment's prose wraps at, leaving room for the ` * ` prefix. */\nconst COMMENT_WIDTH = 110\n\n/**\n * A stable JavaScript identifier per asset.\n *\n * Derived from the asset's own name rather than its index, so a reader can match a `const`\n * in the script against a file in the asset directory. The dedupe suffix is defensive: the\n * read half currently names assets `image1.png`, `image2.jpg`, … which cannot collide after\n * the extension is stripped, but nothing in the IR contract promises that.\n */\nexport function assetIdentifiers(ir: DeckIr): Map<string, string> {\n\tconst out = new Map<string, string>()\n\tconst used = new Set<string>()\n\tfor (const asset of ir.assets) {\n\t\tconst base = asset.name.replace(/\\.[^.]*$/, '').replace(/[^A-Za-z0-9_$]/g, '_')\n\t\tlet identifier = /^[A-Za-z_$]/.test(base) ? base : `_${base}`\n\t\tlet suffix = 2\n\t\twhile (used.has(identifier)) identifier = `${base}_${suffix++}`\n\t\tused.add(identifier)\n\t\tout.set(asset.name, identifier)\n\t}\n\treturn out\n}\n\n/** Resolve an {@link AssetRef} to the `const` identifier standing for its bytes. */\nexport function assetPrinter(identifiers: Map<string, string>): AssetPrinter {\n\treturn (ref: AssetRef): string => {\n\t\tconst identifier = identifiers.get(ref.$asset)\n\t\tif (!identifier)\n\t\t\tthrow new InvalidOptionError(\n\t\t\t\t'script/unresolved-asset-reference',\n\t\t\t\t`Asset reference ${ref.$asset} has no entry in DeckIr.assets`\n\t\t\t)\n\t\treturn identifier\n\t}\n}\n\n/**\n * One `const` per asset, each holding a complete `data:` URI.\n *\n * Both modes bind the same *kind* of value — a data URI string — so the call sites are\n * identical and `addImage`'s `data` option is used either way. Only where the bytes come\n * from changes. Rewriting the option key to `path` in file mode would have the printer\n * reshaping an argument, which is precisely the thing that keeps the IR checkable.\n */\nexport function printAssetBindings(\n\tir: DeckIr,\n\tidentifiers: Map<string, string>,\n\tassetDir: string,\n\tmode: AssetMode,\n\tinlineComment = '// Media bytes, inlined so this script needs no files but its template.'\n): string[] {\n\tif (ir.assets.length === 0) return []\n\n\tconst lines =\n\t\tmode === 'file' ? ['// Media bytes, loaded from the asset directory beside this script.'] : [inlineComment]\n\n\tfor (const asset of ir.assets) {\n\t\tconst identifier = identifiers.get(asset.name)\n\t\tif (!identifier) continue\n\t\tif (mode === 'file') {\n\t\t\tconst path = printString(`${assetDir}/${asset.name}`)\n\t\t\tlines.push(\n\t\t\t\t`const ${identifier} = \\`data:${asset.contentType};base64,\\${(await readFile(here(${path}))).toString('base64')}\\``\n\t\t\t)\n\t\t} else {\n\t\t\tlines.push(`const ${identifier} = ${printString(`data:${asset.contentType};base64,${toBase64(asset.bytes)}`)}`)\n\t\t}\n\t}\n\treturn lines\n}\n\n/** Base64 without `Buffer`, matching the rest of the library's isomorphic media handling. */\nfunction toBase64(bytes: Uint8Array): string {\n\tlet binary = ''\n\t// Chunked because String.fromCharCode is applied to the whole slice at once, and a\n\t// megabyte-sized spread overflows the argument limit.\n\tconst CHUNK = 0x8000\n\tfor (let i = 0; i < bytes.length; i += CHUNK) {\n\t\tbinary += String.fromCharCode(...bytes.subarray(i, i + CHUNK))\n\t}\n\treturn btoa(binary)\n}\n\n/**\n * One slide: a comment, the statement that creates it, then its slide-level properties and\n * its calls in z-order.\n *\n * `comment` and `construction` are the tier's business — one binds a layout by name at append\n * time, the other names a master up front — and everything after them is not.\n */\nexport function printSlide(\n\tslide: SlideIr,\n\tparts: { comment: string; construction: string },\n\tcollector: NoteCollector,\n\tprintAsset: AssetPrinter\n): string[] {\n\tconst notes = scopeNotes(collector, slide.number)\n\tconst identifier = `slide${slide.number}`\n\tconst lines = ['', `// ${parts.comment}`, `const ${identifier} = ${parts.construction}`]\n\n\tif (slide.name !== undefined) {\n\t\tnotes.note(\n\t\t\t'slide.name',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t`the slide's own name (p:cSld@name, here ${JSON.stringify(slide.name)}) has no public write-API setter, so the generated slide is unnamed`\n\t\t)\n\t}\n\n\tif (slide.hidden) lines.push(`${identifier}.hidden = true`)\n\tif (slide.background) {\n\t\tlines.push(`${identifier}.background = ${printValue(slide.background as IrValue, 0, printAsset)}`)\n\t}\n\tif (slide.transition) {\n\t\tlines.push(`${identifier}.transition = ${printValue(asIrValue(slide.transition), 0, printAsset)}`)\n\t}\n\tif (slide.notesText !== undefined) {\n\t\tlines.push(printArguments(`${identifier}.addNotes`, [slide.notesText], 0, printAsset))\n\t}\n\n\tfor (const call of slide.calls) {\n\t\t// The source shape name makes a fidelity note navigable: a note carries the same\n\t\t// name, and without it a reader has no way to find the call it refers to.\n\t\tif (call.sourceName) lines.push(`// ${call.sourceName.replace(/\\s+/g, ' ')}`)\n\t\tlines.push(printArguments(`${identifier}.${call.method}`, call.args, 0, printAsset))\n\t}\n\n\treturn lines\n}\n\n/** The banner comment: `prose` as written, then every loss that applies to this output. */\nexport function header(prose: string[], notes: FidelityNote[]): string {\n\tconst lines = [...prose, '']\n\n\tif (notes.length === 0) {\n\t\tlines.push('FIDELITY: nothing was lost that this converter can detect.')\n\t} else {\n\t\tlines.push(\n\t\t\t`FIDELITY: ${notes.length} declared loss(es). Everything not listed here is expected to`,\n\t\t\t'survive unchanged; a difference that is not in this list is a defect, not a caveat.',\n\t\t\t''\n\t\t)\n\t\tfor (const [scope, group] of groupNotes(notes)) {\n\t\t\tlines.push(`${scope}:`)\n\t\t\tfor (const note of group) {\n\t\t\t\tconst where = note.shapeName ? ` (${note.shapeName})` : ''\n\t\t\t\tlines.push(\n\t\t\t\t\t...wrap(\n\t\t\t\t\t\t`- ${note.construct}${where} [${note.disposition}, ${note.cause}] — ${note.detail}`,\n\t\t\t\t\t\tCOMMENT_WIDTH,\n\t\t\t\t\t\t' '\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn ['/*', ...lines.map((line) => (line ? ` * ${line}` : ' *')), ' */'].join('\\n')\n}\n\n/** Notes bucketed by slide, in deck order, so a reader meets them the way they meet the deck. */\nfunction groupNotes(notes: FidelityNote[]): Array<[string, FidelityNote[]]> {\n\tconst deckLevel = notes.filter((note) => note.slideNumber === null)\n\tconst bySlide = new Map<number, FidelityNote[]>()\n\tfor (const note of notes) {\n\t\tif (note.slideNumber === null) continue\n\t\tconst existing = bySlide.get(note.slideNumber)\n\t\tif (existing) existing.push(note)\n\t\telse bySlide.set(note.slideNumber, [note])\n\t}\n\n\tconst out: Array<[string, FidelityNote[]]> = []\n\tif (deckLevel.length > 0) out.push(['Deck', deckLevel])\n\tfor (const number of [...bySlide.keys()].sort((a, b) => a - b)) {\n\t\tout.push([`Slide ${number}`, bySlide.get(number) ?? []])\n\t}\n\treturn out\n}\n\n/** Wrap prose to `width`, indenting every line after the first by `continuation`. */\nfunction wrap(text: string, width: number, continuation: string): string[] {\n\tconst words = text.split(/\\s+/).filter(Boolean)\n\tconst lines: string[] = []\n\tlet current = ''\n\tfor (const word of words) {\n\t\tconst candidate = current ? `${current} ${word}` : `${continuation}${word}`\n\t\tif (current && candidate.length > width) {\n\t\t\tlines.push(current)\n\t\t\tcurrent = `${continuation}${word}`\n\t\t} else {\n\t\t\tcurrent = current ? candidate : word\n\t\t}\n\t}\n\tif (current) lines.push(current)\n\treturn lines\n}\n\n/**\n * Close out a printed script: the accumulated lines as one module source, plus the\n * asset side-car the caller has to write beside it.\n *\n * Both tiers end this way, and the `assetMode` test is the whole reason it is worth\n * naming. In `'inline'` mode the bytes are already in {@link PrintedScript.code} as\n * `data:` literals, so the map must come back **empty** — a tier that returned them\n * anyway would have its caller write every image to disk as well, and the script would\n * ignore the files it was handed.\n * @param {string[]} lines - the script's lines, in order\n * @param {DeckIr} ir - the IR being printed, for its assets\n * @param {AssetMode} assetMode - how image bytes reach the script\n * @param {FidelityNote[]} notes - the losses that apply to this output\n * @returns {PrintedScript} the finished script\n */\nexport function printedScript(lines: string[], ir: DeckIr, assetMode: AssetMode, notes: FidelityNote[]): PrintedScript {\n\treturn {\n\t\tcode: lines.join('\\n'),\n\t\tassets: new Map(\n\t\t\tassetMode === 'file' ? ir.assets.map((asset): [string, Uint8Array] => [asset.name, asset.bytes]) : []\n\t\t),\n\t\tnotes,\n\t}\n}\n","/**\n * {@link DeckIr} → a runnable TypeScript module, template-anchored. **Tier B.**\n *\n * **The tier.** The emitted script reuses the *source deck itself* as its template:\n * `Presentation.fromTemplate` strips a package's slides while leaving its masters, layouts,\n * theme, and document properties byte-identical, so the chrome is never regenerated — it is\n * the original. Only the slides are rebuilt, through the public write API, and grafted back\n * with `appendSlides`. That is why this tier's fidelity note list is short: everything the\n * converter cannot see or cannot write is confined to slide content, and the whole of the\n * deck's design survives because nothing ever tried to reproduce it.\n *\n * It also means the plan's \"strip the source slides\" step needs no helper. `fromTemplate`\n * already does exactly that, and does it without pruning shared parts, so the template\n * asset and the source deck are the same file.\n *\n * **Order is not rearranged.** Slides are emitted in source order and every operation\n * appends, so `p:sldIdLst` comes out in the original order without any position arithmetic.\n * Contiguous slides sharing a layout share one generator, because `appendSlides` binds\n * every slide in one call to a single layout — the batching is forced by that signature,\n * not chosen for tidiness.\n *\n * **This module may add fidelity notes.** A loss can belong to the *tier* rather than to\n * the conversion — a slide's `p:cSld@name` is read fine and would survive a byte copy, but\n * has no public write-API setter, so it dies here and nowhere else. {@link PrintedScript}\n * therefore returns the notes that actually apply to *this* output, which is also the set a\n * round-trip check should exclude from its diff.\n *\n * The standalone counterpart is `printStandaloneScript` (Tier A), which prints the same IR\n * with no template at all and pays for it in the note list.\n */\nimport type { DeckIr, SlideIr } from '../ir.js'\nimport { LAYOUT_NOTE_PREFIX, NoteCollector, scopeNotes } from '../fidelity.js'\nimport { inches } from '../from-read/values.js'\nimport { printString, type AssetPrinter } from './literal.js'\nimport {\n\tassetIdentifiers,\n\tassetPrinter,\n\theader,\n\tprintAssetBindings,\n\tprintSlide,\n\tprintedScript,\n\tresolvePrintOptions,\n\ttype AssetMode,\n\ttype PrintedScript,\n} from './common.js'\n\nexport type { AssetMode, PrintedScript } from './common.js'\n\nexport interface PrintScriptOptions {\n\t/**\n\t * Path the emitted script loads its template from, resolved against the script's own\n\t * location. This is the **source deck unchanged** — `fromTemplate` strips its slides.\n\t * @default './template.pptx'\n\t */\n\ttemplatePath?: string\n\t/** Path the emitted script writes to, resolved against the script's own location. @default './output.pptx' */\n\toutputPath?: string\n\t/** Directory the emitted script reads image assets from, when {@link assets} is `'file'`. @default './assets' */\n\tassetDir?: string\n\t/** @default 'file' */\n\tassets?: AssetMode\n\t/**\n\t * Import specifier the emitted script uses, with `/read` appended for the read half.\n\t * Defaults to this package's own published name; override it to point a generated\n\t * script at a local build or a fork.\n\t * @default '@shbernal/ts-pptx'\n\t */\n\tpackageName?: string\n}\n\n/**\n * Constructs the IR declares lost that a template-anchored output keeps anyway.\n *\n * Document properties are the obvious case: the read half notes that only five of the twelve\n * have write-API setters, which is true and matters for a standalone output — but this tier\n * never authors them at all. They ride in the template, untouched, all twelve of them.\n *\n * The whole of the chrome is the same story on a larger scale. The theme's format scheme, the\n * master's text styles and colour map, the layouts' decoration and placeholder definitions —\n * every one of them is a genuine loss for a script that has to rebuild the deck's design, and\n * none of them is touched here, because the design *is* the template. A caveat that does not\n * apply to the output in front of you is worse than no caveat: it teaches the reader to skim\n * the ones that do.\n *\n * Alongside this list, {@link isTemplateCarried} drops every note under\n * {@link LAYOUT_NOTE_PREFIX}. Those are the per-shape losses of re-authoring a layout's\n * decoration, recorded in the slide vocabulary because the shape mapper is shared — and every\n * one of them is about a layout, which this tier does not rebuild.\n */\nconst TEMPLATE_CARRIED_CONSTRUCTS = new Set([\n\t'deck.docProps',\n\t'master.background',\n\t'master.colorMap',\n\t'master.decoration',\n\t'master.multiple',\n\t// Both are about a layout *title* the standalone tier has to invent — deduplicated because\n\t// it doubles as a lookup key, whitespace-collapsed because the write path emits it as a raw\n\t// XML attribute value. Here the layout keeps its own `p:cSld@name`, untouched.\n\t'master.name',\n\t'master.nameCollision',\n\t'master.placeholders',\n\t'master.txStyles',\n\t'theme.fmtScheme',\n])\n\n/** `true` when the source deck carries this loss through untouched, so this tier does not have it. */\nfunction isTemplateCarried(construct: string): boolean {\n\treturn TEMPLATE_CARRIED_CONSTRUCTS.has(construct) || construct.startsWith(LAYOUT_NOTE_PREFIX)\n}\n\n/** Turn a deck IR into a runnable, template-anchored TypeScript module. */\nexport function printScript(ir: DeckIr, options: PrintScriptOptions = {}): PrintedScript {\n\tconst templatePath = options.templatePath ?? './template.pptx'\n\tconst { outputPath, assetDir, assetMode, packageName } = resolvePrintOptions(options)\n\n\tconst collector = new NoteCollector()\n\tconst assetNames = assetIdentifiers(ir)\n\tconst printAsset = assetPrinter(assetNames)\n\n\tconst body = printSlides(ir, collector, printAsset)\n\tconst needsSource = ir.slides.some((slide) => slide.source === 'carried')\n\tconst needsFallbackLayout = ir.slides.some((slide) => slide.source === 'authored' && slide.layout === null)\n\n\t// Built last: the tier's own notes are only known once the slides have been walked.\n\tconst notes = [...ir.fidelity.filter((note) => !isTemplateCarried(note.construct)), ...collector.notes]\n\n\tconst lines: string[] = [\n\t\theader(\n\t\t\t[\n\t\t\t\t'Generated from a .pptx by ts-pptx/script.',\n\t\t\t\t'',\n\t\t\t\t'Template-anchored: the source deck is reused as the template, so its slide masters,',\n\t\t\t\t'layouts, theme and document properties are the originals, byte for byte. Only the',\n\t\t\t\t'slide content below was rebuilt through the public write API.',\n\t\t\t\t'',\n\t\t\t\t`Expects ${templatePath} (the source deck, unmodified) beside this file${\n\t\t\t\t\tassetMode === 'file' && ir.assets.length > 0 ? `, plus ${ir.assets.length} media file(s) in ${assetDir}` : ''\n\t\t\t\t}.`,\n\t\t\t\t`Writes ${outputPath}. Needs an ESM context — it uses top-level await.`,\n\t\t\t],\n\t\t\tnotes\n\t\t),\n\t\t'',\n\t\t\"import { readFile, writeFile } from 'node:fs/promises'\",\n\t\t\"import { fileURLToPath } from 'node:url'\",\n\t\t`import TsPptx from ${printString(packageName)}`,\n\t\t`import { Presentation } from ${printString(`${packageName}/read`)}`,\n\t\t'',\n\t\t'/** Resolve a path against this script rather than against the working directory. */',\n\t\t'const here = (name: string): string => fileURLToPath(new URL(name, import.meta.url))',\n\t\t'',\n\t\t'// The source deck is the template: fromTemplate strips its slides and leaves its masters,',\n\t\t'// layouts, theme and document properties exactly as they were.',\n\t\t`const deck = await Presentation.fromTemplate(here(${printString(templatePath)}))`,\n\t]\n\n\tif (needsSource) {\n\t\tlines.push(\n\t\t\t'',\n\t\t\t'// A second, unstripped handle on the same file, for the slides copied verbatim.',\n\t\t\t`const source = await Presentation.load(here(${printString(templatePath)}))`\n\t\t)\n\t}\n\n\tif (needsFallbackLayout) {\n\t\tlines.push(\n\t\t\t'',\n\t\t\t'// Some source slides resolved no layout of their own; they bind to the first one.',\n\t\t\t'const fallbackLayout = deck.layouts()[0]',\n\t\t\t\"if (!fallbackLayout) throw new Error('the template declares no slide layouts to bind to')\"\n\t\t)\n\t}\n\n\tconst assetLines = printAssetBindings(ir, assetNames, assetDir, assetMode)\n\tif (assetLines.length > 0) lines.push('', ...assetLines)\n\n\tlines.push(\n\t\t'',\n\t\t'/**',\n\t\t' * A generator sized to the template. appendSlides compares slide sizes exactly and',\n\t\t' * throws when they differ, so the inches here must round-trip to the source EMU.',\n\t\t' */',\n\t\t'function generator(): TsPptx {',\n\t\t'\\tconst pptx = new TsPptx()',\n\t\t`\\tpptx.defineLayout({ name: 'source', width: ${inches(ir.slideSize.widthEmu)}, height: ${inches(ir.slideSize.heightEmu)} })`,\n\t\t\"\\tpptx.layout = 'source'\",\n\t\t'\\treturn pptx',\n\t\t'}',\n\t\t...body,\n\t\t'',\n\t\t`await writeFile(here(${printString(outputPath)}), await deck.save())`,\n\t\t''\n\t)\n\n\treturn printedScript(lines, ir, assetMode, notes)\n}\n\n/**\n * The slide statements, batched into generators, preceded by the layout handles they bind to.\n *\n * A batch ends when the layout changes or a carried slide interrupts, because\n * `appendSlides` binds one layout per call and a carried slide is not authored at all.\n *\n * Every layout `const` is hoisted above the first statement rather than emitted where it is\n * first used. `deck.layouts()` is a snapshot of the gallery, and `importSlide` — the call a\n * carried slide prints — grows that gallery with the source slide's own layout and master.\n * Resolving a handle after one has run is therefore resolving against a deck that has already\n * moved; capturing every handle up front is the only ordering that cannot.\n */\nfunction printSlides(ir: DeckIr, collector: NoteCollector, printAsset: AssetPrinter): string[] {\n\tconst declarations: string[] = []\n\tconst lines: string[] = []\n\tlet batch: SlideIr[] = []\n\tlet generatorIndex = 0\n\t// Two non-contiguous batches can share one layout, so its `const` must be emitted once.\n\tconst declaredLayouts = new Set<number>()\n\n\tconst flush = (): void => {\n\t\tif (batch.length === 0) return\n\t\tconst first = batch[0]\n\t\tif (!first) return\n\t\tconst name = `gen${++generatorIndex}`\n\t\tlines.push('', `const ${name} = generator()`)\n\t\tfor (const slide of batch) lines.push(...printAuthoredSlide(slide, name, collector, printAsset))\n\t\tlines.push('', printAppend(name, first, collector, declaredLayouts, declarations))\n\t\tbatch = []\n\t}\n\n\tfor (const slide of ir.slides) {\n\t\tif (slide.source === 'carried') {\n\t\t\tflush()\n\t\t\tlines.push(\n\t\t\t\t'',\n\t\t\t\t`// Slide ${slide.number} — copied from the source deck rather than rebuilt; see the fidelity notes.`,\n\t\t\t\t`deck.importSlide(source, ${slide.number - 1})`\n\t\t\t)\n\t\t\tcontinue\n\t\t}\n\t\t// A batch is one appendSlides call, which binds every slide in it to one layout.\n\t\tconst previous = batch[0]\n\t\tif (previous && previous.layout?.index !== slide.layout?.index) flush()\n\t\tbatch.push(slide)\n\t}\n\tflush()\n\n\treturn declarations.length > 0 ? ['', ...declarations, ...lines] : lines\n}\n\n/**\n * The `appendSlides` call closing a batch, binding by layout name where that is\n * unambiguous and by gallery position where it is not. Any handle it needs is appended to\n * `declarations`, which the caller hoists above every statement.\n *\n * Binding by name is preferred because it survives being re-pointed at a different\n * template and because it is legible. But `appendSlides` *throws* on an ambiguous name\n * rather than picking one, so the positional form resolves the case where the name does not\n * identify one layout: a multi-master deck that repeats layout names.\n *\n * A carried slide used to demote every binding in the script to a position too, because its\n * `importSlide` copied the source layout in under a second name-alike entry. `importSlide`\n * now binds to the chrome the template already holds (`read/api/ops/part-reuse.ts`), and\n * this deck's template *is* the source file, so the gallery no longer grows and the names\n * stay unambiguous.\n */\nfunction printAppend(\n\tgeneratorName: string,\n\tfirst: SlideIr,\n\tcollector: NoteCollector,\n\tdeclared: Set<number>,\n\tdeclarations: string[]\n): string {\n\tconst layout = first.layout\n\tif (!layout) return `await deck.appendSlides(${generatorName}, { layout: fallbackLayout })`\n\tif (layout.nameIsUnique) {\n\t\treturn `await deck.appendSlides(${generatorName}, { layout: ${printString(layout.name)} })`\n\t}\n\n\tscopeNotes(collector, first.number).note(\n\t\t'slide.layout',\n\t\t'approximated',\n\t\t'unsupported',\n\t\t`more than one layout in the source deck is named ${JSON.stringify(layout.name)}, so this slide binds to gallery position ${layout.index} instead; re-pointing the script at a different template will not track the name`\n\t)\n\tconst identifier = `layout${layout.index}`\n\tif (!declared.has(layout.index)) {\n\t\tdeclared.add(layout.index)\n\t\tdeclarations.push(\n\t\t\t`const ${identifier} = deck.layouts()[${layout.index}] // ${JSON.stringify(layout.name)}`,\n\t\t\t`if (!${identifier}) throw new Error('the template has no layout at position ${layout.index}')`\n\t\t)\n\t}\n\treturn `await deck.appendSlides(${generatorName}, { layout: ${identifier} })`\n}\n\n/** One authored slide, plus the layout-binding note this tier is responsible for. */\nfunction printAuthoredSlide(\n\tslide: SlideIr,\n\tgeneratorName: string,\n\tcollector: NoteCollector,\n\tprintAsset: AssetPrinter\n): string[] {\n\tif (slide.layout === null) {\n\t\tscopeNotes(collector, slide.number).note(\n\t\t\t'slide.layout',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t\"this slide resolves no layout of its own, so it binds to the template's first layout; that governs theme and clrMap resolution, which may differ from the source\"\n\t\t)\n\t}\n\n\t// A tier loss, and a narrow one: a transition's *stop-previous* form needs no relationship\n\t// and rides across fine, while an embedded start sound needs an audio part wired to the\n\t// appended slide. `extractSlides` never runs the registration pass that assigns it a\n\t// relationship id (`registerTransitionSounds` belongs to the package-assembly path), so the\n\t// emitter finds no `_sndRId` and writes no `p:sndAc` at all. That is a silent drop rather\n\t// than a dangling reference — which is the safe failure of the two, and still a loss the\n\t// reader has to be told about. The standalone tier writes a real package and keeps it.\n\tif (slide.transition?.sound?.data !== undefined) {\n\t\tscopeNotes(collector, slide.number).note(\n\t\t\t'slide.transitionSound',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t\"this transition's start sound is dropped: the append path this tier rides does not register a transition's embedded audio part, so the sound does not reach the template. The assignment below still spells it out, and the WAV still ships beside the script, because both describe the source deck faithfully and would take effect the day the append path carries them — but this output is silent. Print the standalone variant to keep the sound\"\n\t\t)\n\t}\n\n\tconst layout = slide.layout === null ? 'no layout' : `layout ${JSON.stringify(slide.layout.name)}`\n\treturn printSlide(\n\t\tslide,\n\t\t{ comment: `Slide ${slide.number} — ${layout}`, construction: `${generatorName}.addSlide()` },\n\t\tcollector,\n\t\tprintAsset\n\t)\n}\n","/**\n * {@link DeckIr} → a runnable TypeScript module that depends on nothing but this package.\n * **Tier A.**\n *\n * **The trade, stated once.** The template-anchored printer (`printScript`) reuses the source\n * `.pptx` and gets the deck's entire design back byte for byte, at the cost of shipping that\n * file alongside the script and of leaving the design uneditable. This one ships a single\n * `.ts` file. Everything the source deck's chrome contained has to be *re-authored* from what\n * the read model exposes, and the read model deliberately exposes the property tiers a slide\n * inherits — colours, fonts, placeholder geometry — not the parts a slide merely sits on top\n * of. So the output is a deck that renders its slides faithfully and wears a different suit.\n *\n * **The ceiling is measured, not estimated, and no amount of printer work moves it.** Two\n * constructs are unreachable from *both* directions: `a:fmtScheme` (nothing reads it, and the\n * write path emits a hardcoded Office one) and `p:txStyles` (no reader, though\n * `SlideMasterProps.textStyles` could author it). A third, `p:clrMap`, is readable and has no\n * setter. Each is a fidelity note here and a `pass` in the other tier, which is the whole\n * reason the other tier shipped first. A **master's** own decoration joins them for a\n * structural reason rather than a reading one: `defineSlideMaster` creates a layout, so there\n * is no master shape tree to write to. A *layout's* decoration used to be on this list and is\n * not any more — it is transcribed into that layout's `objects`.\n *\n * **One structural difference beyond the chrome.** A slide marked `carried` has no source\n * package to be carried from here, so it is transcribed like any other and loses only the\n * construct that made it uncarryable — which each shape has already declared for itself. That\n * is why {@link DeckIr}'s calls are populated even for a carried slide.\n */\nimport type { DeckIr, IrValue, MasterIr } from '../ir.js'\nimport { NoteCollector, scopeNotes } from '../fidelity.js'\nimport { inches } from '../from-read/values.js'\nimport { printArguments, printString, printValue, type AssetPrinter } from './literal.js'\nimport {\n\tassetIdentifiers,\n\tassetPrinter,\n\theader,\n\tprintAssetBindings,\n\tprintSlide,\n\tprintedScript,\n\tresolvePrintOptions,\n\ttype AssetMode,\n\ttype PrintedScript,\n} from './common.js'\n\nexport interface PrintStandaloneScriptOptions {\n\t/** Path the emitted script writes to, resolved against the script's own location. @default './output.pptx' */\n\toutputPath?: string\n\t/** Directory the emitted script reads image assets from, when {@link assets} is `'file'`. @default './assets' */\n\tassetDir?: string\n\t/** @default 'file' */\n\tassets?: AssetMode\n\t/**\n\t * Import specifier the emitted script uses. Defaults to this package's own published\n\t * name; override it to point a generated script at a local build or a fork.\n\t * @default '@shbernal/ts-pptx'\n\t */\n\tpackageName?: string\n}\n\n/**\n * Notes the IR declares that do not describe *this* output.\n *\n * Only one, and it is the mirror of the other tier's list. `slide.carried` says a slide will\n * be copied from the source package rather than transcribed; there is no source package here,\n * so the slide is transcribed and the construct that made it uncarryable has already recorded\n * its own note. Reporting both would double-count one loss and describe a behaviour this\n * script does not have.\n */\nconst NOT_APPLICABLE = new Set(['slide.carried'])\n\n/** Turn a deck IR into a runnable TypeScript module that needs no template. */\nexport function printStandaloneScript(ir: DeckIr, options: PrintStandaloneScriptOptions = {}): PrintedScript {\n\tconst { outputPath, assetDir, assetMode, packageName } = resolvePrintOptions(options)\n\n\tconst collector = new NoteCollector()\n\tconst assetNames = assetIdentifiers(ir)\n\tconst printAsset = assetPrinter(assetNames)\n\n\t// Walked before the header is built: this tier's own notes are only known afterwards.\n\tconst masters = printMasters(ir, collector, printAsset)\n\tconst body = printSlides(ir, collector, printAsset)\n\tconst notes = [...ir.fidelity.filter((note) => !NOT_APPLICABLE.has(note.construct)), ...collector.notes]\n\n\tconst needsReadFile = assetMode === 'file' && ir.assets.length > 0\n\tconst lines: string[] = [\n\t\theader(\n\t\t\t[\n\t\t\t\t'Generated from a .pptx by ts-pptx/script.',\n\t\t\t\t'',\n\t\t\t\t`Standalone: this script needs nothing but ${packageName}${\n\t\t\t\t\tneedsReadFile ? ` and ${ir.assets.length} media file(s) in ${assetDir}` : ''\n\t\t\t\t}.`,\n\t\t\t\t\"The deck's theme, layouts and slide content are all re-authored through the public write\",\n\t\t\t\t'API, so every one of them is editable here — and the parts of the original design the read',\n\t\t\t\t'model cannot see are gone. They are listed below. For a byte-identical design at the cost',\n\t\t\t\t'of shipping the source deck alongside the script, print the template-anchored variant',\n\t\t\t\t'instead.',\n\t\t\t\t'',\n\t\t\t\t`Writes ${outputPath}. Needs an ESM context — it uses top-level await.`,\n\t\t\t],\n\t\t\tnotes\n\t\t),\n\t\t'',\n\t\t...(needsReadFile ? [\"import { readFile } from 'node:fs/promises'\"] : []),\n\t\t\"import { fileURLToPath } from 'node:url'\",\n\t\t`import TsPptx from ${printString(packageName)}`,\n\t\t'',\n\t\t'/** Resolve a path against this script rather than against the working directory. */',\n\t\t'const here = (name: string): string => fileURLToPath(new URL(name, import.meta.url))',\n\t\t'',\n\t\t'const pptx = new TsPptx()',\n\t\t`pptx.defineLayout({ name: 'source', width: ${inches(ir.slideSize.widthEmu)}, height: ${inches(ir.slideSize.heightEmu)} })`,\n\t\t\"pptx.layout = 'source'\",\n\t]\n\n\tconst theme = ir.chrome.theme as IrValue\n\tif (Object.keys(ir.chrome.theme).length > 0) {\n\t\tlines.push(\n\t\t\t'',\n\t\t\t\"// The theme's colour scheme and font faces. Its format scheme — the fill, line and effect\",\n\t\t\t'// style lists a shape references through p:style — has no counterpart on either side of the',\n\t\t\t\"// library, so the output carries Office's.\",\n\t\t\t`pptx.theme = ${printValue(theme, 0, printAsset)}`\n\t\t)\n\t}\n\n\tconst props = printDocProps(ir, collector)\n\tif (props.length > 0) lines.push('', ...props)\n\n\tconst assetLines = printAssetBindings(\n\t\tir,\n\t\tassetNames,\n\t\tassetDir,\n\t\tassetMode,\n\t\t'// Media bytes, inlined so this script is a single self-contained file.'\n\t)\n\tif (assetLines.length > 0) lines.push('', ...assetLines)\n\n\tif (masters.length > 0) lines.push('', ...masters)\n\tlines.push(...body, '', `await pptx.writeFile({ fileName: here(${printString(outputPath)}) })`, '')\n\n\treturn printedScript(lines, ir, assetMode, notes)\n}\n\n/**\n * The document properties the write API can set.\n *\n * Four of the twelve the read model exposes, which is the loss `deck.docProps` already\n * declares — and unlike the template-anchored tier, here it is a real one, because nothing\n * else carries them.\n */\nfunction printDocProps(ir: DeckIr, collector: NoteCollector): string[] {\n\tconst entries = Object.entries(ir.props).filter(([, value]) => typeof value === 'string')\n\n\t// A deck built through the write API is stamped with the library's own author, company,\n\t// subject, title and revision in the constructor, and a property cannot be unset — writing\n\t// `''` emits an empty element rather than removing it. So whatever the source left blank\n\t// comes back filled in, which is a change to the deck rather than a formatting detail.\n\tconst stamped = ['title', 'author', 'company', 'subject', 'revision'].filter((key) => !(key in ir.props))\n\tif (stamped.length > 0) {\n\t\tscopeNotes(collector, null).note(\n\t\t\t'deck.docPropsDefault',\n\t\t\t'approximated',\n\t\t\t'unwritable',\n\t\t\t`the source deck declares no ${stamped.join(', ')}, and a deck built through the write API is stamped with the library's own value for each in its constructor with no way to unset it, so the output declares ${stamped.length === 1 ? 'one' : 'these'} the source did not`\n\t\t)\n\t}\n\n\tif (entries.length === 0) return []\n\treturn [\n\t\t'// Document properties. Only these have write-API setters; see the fidelity notes.',\n\t\t...entries.map(([key, value]) => `pptx.${key} = ${printString(value as string)}`),\n\t]\n}\n\n/**\n * One `defineSlideMaster` per source layout.\n *\n * The naming is the write API's rather than OOXML's: a `defineSlideMaster` call creates a\n * *layout* under the single shared master, which is the right granularity for a source layout.\n * It carries the layout's name, its background, and its decoration — the bands, rules and\n * wordmarks that make the gallery recognisable rather than a list of blank rectangles. What it\n * still cannot carry is the layout's *placeholder definitions*, and that is a write-path\n * consequence rather than a reading one (see `from-read/chrome.ts`). The name earns its place\n * twice over: it is also what `addSlide({ masterTitle })` binds on.\n */\nfunction printMasters(ir: DeckIr, collector: NoteCollector, printAsset: AssetPrinter): string[] {\n\t// Recorded before the early return, because the extra layout is there either way: it is\n\t// seeded in the constructor, not by anything printed below. Scoped to that layout's own\n\t// title rather than deck-wide, because the round trip matches a note's `shapeName` against\n\t// the identity of what differed, and an unscoped note would declare *any* extra layout.\n\tscopeNotes(collector, null, 'DEFAULT').note(\n\t\t'master.default',\n\t\t'approximated',\n\t\t'unsupported',\n\t\t\"the write path seeds every presentation with a blank layout of its own named DEFAULT, and there is no way to remove it, so the output deck's layout gallery carries one extra entry ahead of the source's layouts; nothing binds to it, but it is visible in PowerPoint's layout picker\"\n\t)\n\tif (ir.chrome.masters.length === 0) return []\n\treturn [\n\t\t'// One master per source layout, carrying its name, background and decoration. What a',\n\t\t'// layout does not bring across is its placeholder definitions; see the fidelity notes.',\n\t\t...ir.chrome.masters.map((master) => printArguments('pptx.defineSlideMaster', [master.props], 0, printAsset)),\n\t]\n}\n\n/** Every slide, in source order, each bound to the master its source layout became. */\nfunction printSlides(ir: DeckIr, collector: NoteCollector, printAsset: AssetPrinter): string[] {\n\tconst byLayout = new Map<number, MasterIr>()\n\tfor (const master of ir.chrome.masters) byLayout.set(master.layoutIndex, master)\n\n\tconst lines: string[] = []\n\tfor (const slide of ir.slides) {\n\t\tconst master = slide.layout === null ? undefined : byLayout.get(slide.layout.index)\n\t\tconst title = typeof master?.props['title'] === 'string' ? master.props['title'] : null\n\n\t\tif (title === null) {\n\t\t\tscopeNotes(collector, slide.number).note(\n\t\t\t\t'slide.layout',\n\t\t\t\t'approximated',\n\t\t\t\t'unsupported',\n\t\t\t\tslide.layout === null\n\t\t\t\t\t? \"this slide resolves no layout of its own, so it binds to the write path's default blank layout\"\n\t\t\t\t\t: `this slide's source layout (gallery position ${slide.layout.index}) produced no master to bind to, so it binds to the write path's default blank layout`\n\t\t\t)\n\t\t}\n\n\t\tlines.push(\n\t\t\t...printSlide(\n\t\t\t\tslide,\n\t\t\t\t{\n\t\t\t\t\tcomment: `Slide ${slide.number} — ${title === null ? 'no master' : `master ${JSON.stringify(title)}`}`,\n\t\t\t\t\tconstruction: title === null ? 'pptx.addSlide()' : `pptx.addSlide({ masterTitle: ${printString(title)} })`,\n\t\t\t\t},\n\t\t\t\tcollector,\n\t\t\t\tprintAsset\n\t\t\t)\n\t\t)\n\t}\n\treturn lines\n}\n","/**\n * A {@link DeckIr} reduced to the form a round-trip diff can compare.\n *\n * The round trip is `source → IR₁ → script → deck → IR₂`. Comparing those two IRs raw\n * produces thousands of differences, almost none of which are losses: the write path\n * spells out defaults that OOXML leaves implicit, and PowerPoint spells out defaults the\n * write path leaves implicit. Both directions are noise, and drowning the real losses in\n * it is the same as not checking at all.\n *\n * **Every rule here must be an equivalence, not a convenience.** A rule that merely makes\n * the report shorter hides a defect permanently and silently — the exact failure mode this\n * subsystem exists to catch. So each one below cites the OOXML default that makes the\n * explicit and the absent spelling mean the same thing, and none of them drops a value that\n * a viewer could render differently. When in doubt the value stays in and the difference is\n * reported: a noisy report is recoverable, a quiet one is not.\n *\n * Canonicalising is deliberately *symmetric* — it runs over both IRs, so it cannot favour\n * the output. A rule that only made sense in one direction would be an exclusion dressed up\n * as a normalisation.\n */\nimport { asIrValue, isAssetRef, type AssetIr, type DeckIr, type IrValue, type SlideIr } from '../ir.js'\n\n/** One write-API call, with the source shape name lifted out as an address rather than data. */\nexport interface CanonicalCall {\n\tmethod: string\n\t/** `p:cNvPr/@name` of the shape this call came from, used to point a difference at it. */\n\tshapeName: string | null\n\t/**\n\t * Every `objectName` appearing anywhere inside {@link args}, which for `addGroup` is the\n\t * group's children.\n\t *\n\t * A fidelity note about a group's child is scoped to that child's name, but the child is\n\t * not a call of its own — it is an argument to the group's. Without this the note and the\n\t * difference it predicted would carry different names and never match, and a declared loss\n\t * would be reported as a defect.\n\t */\n\tcontainedNames: string[]\n\targs: IrValue[]\n}\n\nexport interface CanonicalSlide {\n\tnumber: number\n\thidden: boolean\n\t/**\n\t * The name of the layout this slide binds to, which is the only part of the binding that\n\t * is portable — a gallery *index* shifts whenever the output's gallery differs from the\n\t * source's, which it always does for a standalone output.\n\t *\n\t * Here because the binding is otherwise invisible: a printer that bound every slide to the\n\t * wrong layout, or to none, would produce identical calls and compare clean. The layout\n\t * governs theme and colour-map resolution, so that is not a cosmetic difference.\n\t */\n\tlayoutName: string | null\n\tbackground: IrValue | null\n\tnotesText: string | null\n\t/**\n\t * The show transition, or `null`.\n\t *\n\t * Here for the same reason {@link layoutName} is: a printer that stopped emitting\n\t * transitions altogether would produce identical *calls* and compare clean, so the\n\t * projection has to carry the slide-level properties the write API sets by assignment\n\t * rather than by method. It is compared structurally (key by key), not as one opaque\n\t * value, so a note can declare the loss of a transition's *sound* without also excusing a\n\t * wrong transition *type*.\n\t */\n\ttransition: IrValue | null\n\tcalls: CanonicalCall[]\n}\n\n/**\n * The deck's chrome, reduced the same way its slides are.\n *\n * Included for one reason: without it the diff cannot see the standalone tier's whole job.\n * That tier re-authors the theme and one master per source layout, and a projection that\n * covers only slides would report a printer emitting *neither* as a clean round trip — the\n * same shape of hole mutation testing found in `added` differences, one level up. A\n * template-anchored output compares equal here by construction, which is the claim that tier\n * makes and is worth checking rather than assuming.\n */\nexport interface CanonicalChrome {\n\ttheme: IrValue\n\t/** Each master's `defineSlideMaster` props, in gallery order. */\n\tmasters: IrValue[]\n}\n\nexport interface CanonicalDeck {\n\tslideSize: { widthEmu: number; heightEmu: number }\n\t/** The `docProps` the write API can set. Absent from the projection, a printer that set none would compare clean. */\n\tprops: IrValue\n\tchrome: CanonicalChrome\n\tslides: CanonicalSlide[]\n}\n\n/**\n * Option values that mean exactly what their absence means.\n *\n * Keyed by option name because the IR's argument objects are the write API's own option\n * objects, where a name identifies a construct uniquely — there is no `bold` that means\n * something other than `a:rPr/@b`.\n *\n * Each entry is an OOXML default:\n *\n * - `bold`, `italic` — `a:rPr/@b` / `@i` are `ST_OnOff`, default `false`.\n * - `baseline` — `a:rPr/@baseline` is a percentage, default `0` (no super/subscript).\n * - `breakLine` — not OOXML but the IR's own flat encoding: a run that does not end its\n * paragraph. The final run of a text frame never carries one, so absent and `false` are\n * the same statement.\n * - `wrap` — `a:bodyPr/@wrap` defaults to `square`, which the write API spells `true`.\n * - `rotate` — `a:xfrm/@rot` defaults to `0`.\n * - `flipH`, `flipV` — `a:xfrm/@flipH` / `@flipV` default to `false`.\n * - `transparency` — an alpha of 0% removed, i.e. fully opaque, which is also the default\n * when no `a:alpha` transform is present.\n * - `indentLevel` — `a:p/@lvl` defaults to `0`.\n * - `dashType` — `a:ln`'s dash defaults to `solid` when no `a:prstDash` is present.\n * - `textDirection` — `a:bodyPr/@vert` and `a:tcPr/@vert` both default to `horz`.\n *\n * Line width is deliberately **absent**: `a:ln/@w` defaults to 0 (hairline) while the write\n * path defaults it to 1pt, so those two are not the same line and the difference is real.\n */\nconst IMPLIED_DEFAULTS: Record<string, IrValue> = {\n\tbold: false,\n\titalic: false,\n\tbaseline: 0,\n\tbreakLine: false,\n\twrap: true,\n\trotate: 0,\n\tflipH: false,\n\tflipV: false,\n\ttransparency: 0,\n\tindentLevel: 0,\n\tdashType: 'solid',\n\ttextDirection: 'horz',\n}\n\n/**\n * `a:bodyPr`'s default insets in inches, in the write API's `[top, right, bottom, left]`\n * order: 45720 EMU (0.05in, 3.6pt) top and bottom, 91440 EMU (0.1in, 7.2pt) left and right.\n * A body that spells them out is inset exactly as one that omits them.\n */\nconst DEFAULT_MARGIN: readonly number[] = [0.05, 0.1, 0.05, 0.1]\n\n/** Reduce a deck IR to the comparable form. */\nexport function canonicalDeckIr(ir: DeckIr): CanonicalDeck {\n\tconst digests = assetDigests(ir.assets)\n\treturn {\n\t\tslideSize: ir.slideSize,\n\t\tprops: canonicalValue(ir.props as IrValue, digests),\n\t\tchrome: {\n\t\t\ttheme: canonicalValue(ir.chrome.theme as IrValue, digests),\n\t\t\tmasters: ir.chrome.masters.map((master) => canonicalValue(master.props, digests)),\n\t\t},\n\t\tslides: ir.slides.map((slide) => canonicalSlide(slide, digests)),\n\t}\n}\n\nfunction canonicalSlide(slide: SlideIr, digests: Map<string, string>): CanonicalSlide {\n\treturn {\n\t\tnumber: slide.number,\n\t\thidden: slide.hidden,\n\t\tlayoutName: slide.layout?.name ?? null,\n\t\tbackground: slide.background === undefined ? null : canonicalValue(slide.background as IrValue, digests),\n\t\tnotesText: slide.notesText ?? null,\n\t\ttransition: slide.transition === undefined ? null : canonicalValue(asIrValue(slide.transition), digests),\n\t\tcalls: slide.calls.map((call) => {\n\t\t\tconst args = call.args.map((arg) => canonicalValue(arg, digests))\n\t\t\treturn {\n\t\t\t\tmethod: call.method,\n\t\t\t\tshapeName: call.sourceName ?? null,\n\t\t\t\tcontainedNames: [...collectObjectNames(args, new Set())],\n\t\t\t\targs,\n\t\t\t}\n\t\t}),\n\t}\n}\n\n/**\n * Every `objectName` value reachable in `value`, at any depth.\n *\n * Exported for the chrome half of the diff, which needs the same list for the same reason: a\n * layout's decoration is an argument to one `defineSlideMaster` call, so a note scoped to one\n * of those shapes has no call of its own to be matched against.\n */\nexport function collectObjectNames(value: IrValue, out: Set<string>): Set<string> {\n\tif (Array.isArray(value)) {\n\t\tfor (const item of value) collectObjectNames(item, out)\n\t\treturn out\n\t}\n\tif (value === null || typeof value !== 'object') return out\n\tfor (const [key, item] of Object.entries(value)) {\n\t\tif (key === 'objectName' && typeof item === 'string') out.add(item)\n\t\telse collectObjectNames(item as IrValue, out)\n\t}\n\treturn out\n}\n\n/**\n * Recursively drop implied defaults and resolve asset references to a content digest.\n *\n * The digest matters more than it looks: assets are named `image1.png`, `image2.png`, … in\n * the order the walk meets them, and the output deck can meet the same bytes in a different\n * order or under a different extension. Comparing names would report a swap that did not\n * happen and, worse, would *miss* one where two images traded places.\n */\nfunction canonicalValue(value: IrValue, digests: Map<string, string>): IrValue {\n\tif (isAssetRef(value)) return { $asset: digests.get(value.$asset) ?? `unknown:${value.$asset}` }\n\tif (Array.isArray(value)) return value.map((item) => canonicalValue(item, digests))\n\tif (value === null || typeof value !== 'object') return value\n\n\t// A run with no characters has no colour anyone can see, and the write path gives every\n\t// run it emits an explicit one. Narrowed to `color` deliberately: a size or a bullet on an\n\t// empty paragraph still affects line height and still draws a glyph, so those stay.\n\tconst blankRun = value['text'] === '' && typeof value['options'] === 'object' && value['options'] !== null\n\n\tconst out: Record<string, IrValue> = {}\n\tfor (const [key, item] of Object.entries(value)) {\n\t\tif (key in IMPLIED_DEFAULTS && item === IMPLIED_DEFAULTS[key]) continue\n\t\tif (key === 'margin' && isDefaultMargin(item)) continue\n\t\tif (blankRun && key === 'options') {\n\t\t\tconst visible = { ...(item as Record<string, IrValue>) }\n\t\t\tdelete visible['color']\n\t\t\tout[key] = canonicalValue(visible, digests)\n\t\t\tcontinue\n\t\t}\n\t\tout[key] = canonicalValue(item, digests)\n\t}\n\treturn out\n}\n\nfunction isDefaultMargin(value: IrValue): boolean {\n\treturn (\n\t\tArray.isArray(value) &&\n\t\tvalue.length === DEFAULT_MARGIN.length &&\n\t\tvalue.every((item, index) => item === DEFAULT_MARGIN[index])\n\t)\n}\n\n/**\n * Content digests keyed by asset name, so the same bytes compare equal under any name.\n *\n * FNV-1a rather than a real hash: this identifies bytes for a comparison both sides of\n * which are in hand, so collision resistance against an adversary is not a property it\n * needs, and the library stays free of `node:crypto` and of the isomorphism problem\n * importing it would create.\n */\nfunction assetDigests(assets: AssetIr[]): Map<string, string> {\n\tconst out = new Map<string, string>()\n\tfor (const asset of assets) {\n\t\tlet hash = 0x811c9dc5\n\t\tfor (const byte of asset.bytes) {\n\t\t\thash ^= byte\n\t\t\thash = Math.imul(hash, 0x01000193) >>> 0\n\t\t}\n\t\tout.set(asset.name, `${asset.bytes.length}:${hash.toString(16)}`)\n\t}\n\treturn out\n}\n","/**\n * The round-trip oracle: does the deck a printed script builds match the deck it was read\n * from, everywhere the fidelity notes did not say it would not?\n *\n * **Why a projection diff and not byte identity.** The output package is not the input\n * package and never will be — different rel ids, different shape ids, a regenerated shape\n * tree, `dirty=\"0\"` on every run. Comparing bytes would report a total mismatch for every\n * deck and prove nothing. So the comparison happens one level up, on the IR: run the same\n * `readModelToIr` over the source deck and over the deck the script produced, and compare\n * those. Two decks that produce the same IR make the same write-API calls, which is exactly\n * the claim a generated script makes.\n *\n * **What a note is worth here.** A {@link FidelityNote} says a named construct will not\n * survive. That makes it an *exclusion with a signature*: the difference it predicts is\n * allowed, and every other difference is a defect. Without the notes there would be no way\n * to tell a known cost from a regression, and the check could only ever be a snapshot.\n *\n * **Two blind spots, both stated plainly, because a clean report is worth exactly what its\n * limits allow.**\n *\n * 1. *The reader is shared.* Both IRs come from `readModelToIr`, so a construct the read\n * model cannot see is missing from both and compares equal. This check cannot certify\n * anything the read path does not read; `pnpm run read:census` measures that surface, and\n * the two are complementary rather than overlapping.\n * 2. *The converter need not be injective.* Two different source constructs can map to the\n * same call, and then the round trip agrees while the deck has changed. Measured, not\n * hypothetical: the mapper once read an explicit `a:buNone` as the glyph `n`, so a\n * bulletless paragraph gained a bullet — and because the output's real `n` bullet read\n * back through the same wrong mapping, the diff was clean. Mutation testing is what\n * catches that class, and a mutation that survives here is a statement about this\n * check's reach rather than a mistake in it.\n *\n * A clean report means \"nothing the converter can distinguish was lost\", never \"nothing was\n * lost\".\n */\nimport { LAYOUT_NOTE_PREFIX, type FidelityNote } from '../fidelity.js'\nimport {\n\tcollectObjectNames,\n\ttype CanonicalCall,\n\ttype CanonicalChrome,\n\ttype CanonicalDeck,\n\ttype CanonicalSlide,\n} from './canonical.js'\nimport type { IrValue } from '../ir.js'\n\n/**\n * Which way a difference points.\n *\n * `lost` and `changed` are the ones the fidelity contract governs — the source said\n * something the output does not, or says differently. `added` is the write path being\n * explicit where the source was implicit, which is *usually* harmless and is reported\n * separately for a reason worth stating: this diff cannot tell whether the value the write\n * path chose is the one the source was inheriting. An `added` `color` is benign if the\n * shape was inheriting that colour and a silent repaint if it was not.\n */\nexport type DifferenceKind = 'lost' | 'added' | 'changed'\n\n/**\n * Options the write path materialises that the source deck left implicit, with the reason\n * each is not judgeable from here.\n *\n * This list exists because `added` differences cannot simply be waved through. Mutation\n * testing settled that: dropping the converter's explicit `valign` left the write path to\n * centre every text body, which showed up as an `added` and nothing failed. So `added` is\n * held to the same standard as the rest — a note must declare it, or its field must appear\n * here with a reason.\n *\n * Every entry names a write-path default whose *correctness* the round trip has no way to\n * assess, because the source's counterpart was inherited and the read model cannot resolve\n * what it was inheriting. That is an honest \"unknown\", not an \"ignore\" — each one names a\n * gap in the reader that could be closed later, and teaching the reader to resolve one turns\n * its entry here into a real comparison.\n */\nconst WRITER_DEFAULTS: Record<string, string> = {\n\t// The write path copies the object-level and first-run character properties onto every\n\t// run it emits. The source's bare runs inherited theirs from the list style, which is\n\t// unread, so there is nothing to compare the copied value against.\n\tfontSize: 'runs inherit size from an unread list style; the write path copies the shape size onto each run',\n\toptions: 'a run or cell that carried no options at all in the source now carries the ones below',\n\t// `a:tcBdr` borders come from the table style graph, which `resolvedFill`/`borders` fold\n\t// together rather than separating; the write path spells out an explicit border per edge.\n\tborder:\n\t\t'table cell borders are resolved through the style graph, which the read model cannot separate from the cell’s own',\n\t// `a:ln/@w` defaults to a hairline in OOXML and to 1pt here, and a source outline with no\n\t// explicit width is exactly the theme-`lnRef` case `line.width` already declares unread.\n\twidth:\n\t\t'an outline with no explicit width takes the write path’s 1pt default; the source’s came from the unread theme line style',\n\t// A shape with no geometry of its own — an unfilled placeholder — has no preset to name.\n\tshape: 'a shape that inherits its geometry from a layout is emitted as a plain rectangle',\n\ttype: 'a fill or line with no explicit kind takes the write path’s solid default',\n\t// Chart options the write path always emits; the read side reports only what the chart\n\t// part contains, and these are defaults rather than authored values.\n\tchartColors: 'the write path assigns a series palette; the source’s came from the theme',\n\tdataLabelFormatCode: 'a data label with no explicit number format takes the write path’s default',\n\tshowLeaderLines: 'leader lines are on by default in the write path',\n\t// The five docProps the write path seeds in its constructor ('ts-pptx',\n\t// 'ts-pptx Presentation', '1'). A source deck that declared none of a given property gets\n\t// the library's, and there is no way to unset one — assigning `''` writes an empty element\n\t// rather than removing it. Unlike the entries above, this is a *write*-side candidate, not\n\t// a read-side one: the fix is a way to author a deck with a property genuinely absent.\n\t// Restricted to `added` by construction, so a printer that stopped writing docProps still\n\t// fails: the source's own values become `changed`, which nothing here excuses.\n\ttitle: 'a deck that declares no title gets the write path’s own',\n\tauthor: 'a deck that declares no author gets the write path’s own',\n\tsubject: 'a deck that declares no subject gets the write path’s own',\n\tcompany: 'a deck that declares no company gets the write path’s own',\n\trevision: 'a deck that declares no revision gets the write path’s own',\n}\n\nexport interface IrDifference {\n\t/** 1-based source slide. */\n\tslideNumber: number\n\t/** Source shape name, when the difference sits inside a call that has one. */\n\tshapeName: string | null\n\t/**\n\t * Shape names nested inside the same call — a group's children. A note scoped to one of\n\t * these also declares differences reported against the call that carries it.\n\t */\n\tnestedNames: string[]\n\t/** Where in the slide's projection, e.g. `calls[4].args[1].line.width`. */\n\tpath: string\n\t/**\n\t * The option name the difference is about — the last object key on {@link path}, or\n\t * `'*'` when a whole call is present on one side only. This is what a note's `construct`\n\t * is matched against, which is why `construct` has to name a field path rather than\n\t * describe one.\n\t */\n\tfield: string\n\tkind: DifferenceKind\n\t/** The source value, JSON-encoded and truncated for reporting. `'—'` when absent. */\n\texpected: string\n\t/** The output value, likewise. */\n\tactual: string\n\t/** The note that declares this difference, when one does. */\n\tdeclaredBy: FidelityNote | null\n}\n\nexport interface RoundTripReport {\n\tslideCount: number\n\t/** Every difference found, in deck order. */\n\tdifferences: IrDifference[]\n\t/**\n\t * Differences neither a note nor a known write-path default accounts for.\n\t * **These are the defects**, and the number this check gates on.\n\t */\n\tundeclared: IrDifference[]\n\t/** Differences a note declared. The contract working. */\n\tdeclared: IrDifference[]\n\t/** `added` differences: the write path spelling out what the source left implicit. */\n\tadded: IrDifference[]\n\t/**\n\t * Notes that matched no difference.\n\t *\n\t * **Not a defect signal, despite the obvious reading.** Most notes name constructs the\n\t * read model cannot see at all — a bullet's `a:buFont`, a shape's theme `effectRef` —\n\t * so they are absent from *both* IRs and there is nothing for them to match. A note\n\t * here is a candidate for review, not a stale claim.\n\t */\n\tunmatchedNotes: FidelityNote[]\n}\n\n/**\n * Option names each note construct is a promise about.\n *\n * This table is the fidelity catalogue made mechanical. A note claims a construct will not\n * survive; without a mapping from that claim to the fields it covers, the claim cannot\n * exclude anything and the round trip degenerates into a snapshot.\n *\n * `'*'` covers every difference inside the call it is scoped to — correct only where the\n * note says the whole shape is gone or was copied wholesale, never as a shortcut for a\n * construct whose fields are merely tedious to enumerate.\n *\n * An empty list is meaningful and common: the construct is invisible to the IR on both\n * sides (a slide's build animations, a paragraph's `a:pPr/@marL`, a connector's shape\n * binding), so the note is a caveat for a human and there is nothing here to exclude. Saying\n * so explicitly is what keeps it from looking like an oversight. A construct can leave that\n * state — `slide.transition` was an empty entry until the converter learned to transcribe\n * transitions, and the IR gaining a field is exactly when its note gains a mapping.\n */\nconst NOTE_FIELDS: Record<string, readonly string[]> = {\n\t'chart.blanks': ['values'],\n\t'chart.combo': ['type'],\n\t'chart.type': ['type'],\n\t'chart.workbook': ['*'],\n\t'chartEx.all': ['*'],\n\t'connector.binding': [],\n\t'connector.line': ['color', 'width', 'dashType', 'beginArrowType', 'endArrowType'],\n\t'connector.rotation': ['rotate'],\n\t// Empty, and the temptation to list title/author/subject/revision here has to be\n\t// resisted: this note is about the *other* seven docProps, which have no setter and are\n\t// absent from the IR. Listing the four that do have setters would excuse a printer that\n\t// stopped writing them — measured, by exactly that mutation.\n\t'deck.docProps': [],\n\t// Nothing to exclude: the differences it predicts are `added`, which WRITER_DEFAULTS covers\n\t// by kind. The note exists so a reader of the emitted script learns the deck gained them.\n\t'deck.docPropsDefault': [],\n\t'deck.slideSize': ['widthEmu', 'heightEmu'],\n\t'diagram.all': ['*'],\n\t'fill.gradient.path': ['gradient', 'fill'],\n\t// Recorded only when an image-filled surface cannot carry its *bytes* — a linked blip, an\n\t// SVG the write path refuses, a part missing from the package. The fill option is then\n\t// absent from the output entirely, which is the same two keys `fill.schemeToken` covers.\n\t'fill.picture': ['fill', 'color'],\n\t// Empty, and deliberately so: this note declares that a picture fill's tiling, crop, DPI\n\t// and rotWithShape do not survive, and *none of them is in the IR on either side* — the\n\t// write API expresses a picture fill as bytes plus transparency, so the converter never\n\t// emits them. Widening this to `fill` would be the mistake it looks like a fix for: it\n\t// would excuse an image fill that failed to come back at all, which is the thing the\n\t// round trip is here to catch.\n\t'fill.picture.geometry': [],\n\t'fill.schemeToken': ['fill', 'color'],\n\t'graphicFrame.unknown': ['*'],\n\t'group.child': ['*'],\n\t'group.childSpace': ['x', 'y', 'w', 'h', 'rotate', 'flipH', 'flipV'],\n\t'group.empty': ['*'],\n\t'group.transform': ['rotate', 'flipH', 'flipV'],\n\t'image.data': ['data', '$asset'],\n\t'image.recolor': ['duotone', 'grayscale', 'biLevel', 'clrChange'],\n\t// Covers the picture's bytes, not just an `svg` option: an SVG picture's raster fallback\n\t// is regenerated rather than carried, so the blip the round trip compares is a different\n\t// image from the source's — which is precisely the loss this note is about.\n\t'image.svg': ['svg', 'data', '$asset'],\n\t'line.arrowSize': ['beginArrowType', 'endArrowType'],\n\t// The chrome notes. Most are empty for the reason stated above and it is the common case\n\t// here rather than the exception: `a:fmtScheme`, `p:txStyles`, a *master's* decoration and a\n\t// layout's placeholder definitions are all absent from the IR on *both* sides — the first two\n\t// because nothing reads them, the other two because nothing writes them — so there is nothing\n\t// for a note to exclude and the note exists for a human. A *layout's* decoration is the one\n\t// that left this state: it is now in the IR as `objects` and is genuinely compared, which is\n\t// what makes the `layout.` entries below worth stating separately.\n\t// `p:clrMap` is the subtle one: a remapped token changes what every scheme colour in the\n\t// deck resolves to, and the round trip still cannot see it, because the IR reports the token\n\t// verbatim rather than its resolved hex. That is exactly the blind spot this file's header\n\t// describes, and writing `[]` is the honest spelling of it.\n\t'master.background': ['background', 'color', 'data', 'master'],\n\t'master.colorMap': [],\n\t'master.decoration': [],\n\t'master.default': ['master'],\n\t'master.multiple': [],\n\t'master.name': ['title', 'layoutName'],\n\t'master.nameCollision': ['title', 'layoutName'],\n\t'master.placeholders': [],\n\t'master.txStyles': [],\n\t'theme.fmtScheme': [],\n\t// The two layout-shape notes with no slide counterpart to inherit a mapping from. Both are\n\t// empty for the same reason, and it is worth spelling out because both *look* like they\n\t// should exclude something. A table on a layout is absent from the `objects` array on both\n\t// sides — the source's because this converter skips it, the output's because it was never\n\t// written — so there is no difference to excuse. A flattened group is stronger still: the\n\t// source layout's group becomes N loose objects here and the output layout genuinely *has*\n\t// N loose objects, so the two agree exactly and the note is a caveat for a human reading the\n\t// emitted script, not an exclusion.\n\t'layout.decoration': [],\n\t'layout.group': [],\n\t'line.dash': ['dashType'],\n\t'line.width': ['width'],\n\t'media.audioVideo': ['*'],\n\t'notes.formatting': ['notesText'],\n\t'shape.custGeom.guides': ['points'],\n\t'shape.effects': ['shadow', 'glow'],\n\t'shape.empty': ['*'],\n\t'shape.frameInherited': ['x', 'y', 'w', 'h'],\n\t'shape.hidden': ['*'],\n\t'shape.placeholder': ['placeholder'],\n\t'slide.animation': [],\n\t'slide.background': ['background', 'color', 'transparency', 'image'],\n\t'slide.carried': ['*'],\n\t'slide.layout': ['layoutName'],\n\t'slide.name': [],\n\t// A transition the write vocabulary cannot name is dropped whole, so the difference lands\n\t// on the slide's `transition` key itself. Deliberately *not* widened to the keys inside it:\n\t// this note is only ever recorded when the whole transition is gone.\n\t'slide.transition': ['transition'],\n\t// The sound alone, one level down. Scoped to `sound` so it cannot also excuse a transition\n\t// whose type or timing came back wrong — the loss it declares is exactly the missing\n\t// `p:sndAc`, and `data`/`$asset` cover the case where the sound survives with other bytes.\n\t'slide.transitionSound': ['sound', 'data', '$asset'],\n\t// A dash outside `ST_PresetLineDashVal` cannot be written back, so the edge comes out as\n\t// a plain dashed rule. Scoped to `border`, which is where that difference lands.\n\t'table.cell.borders.dash': ['border', 'diagonal'],\n\t// `table.cell.fill` used to live here, for a cell whose own fill could not be told apart\n\t// from the one it inherited from the table style. `TableCell.hasOwnFill` tells them apart,\n\t// so the mapper emits the right one and records nothing — the note is gone rather than\n\t// unmapped. Its `.gradient` / `.picture` children below are separate constructs and stay.\n\t// Empty, and correctly so: `a:tc/@id` and `a:tcPr/a:headers` have no write option — the\n\t// IR has nowhere to put them on either side, so there is nothing to exclude. The note\n\t// exists so a reader of the emitted script learns the association was there and is gone.\n\t'table.cell.headers': [],\n\t// The cell-side twins of `fill.picture` / `fill.picture.geometry`, and mapped for the\n\t// same reasons.\n\t'table.cell.fill.picture': ['fill'],\n\t'table.cell.fill.picture.geometry': [],\n\t// The table-background twins. Scoped to `tableFill` rather than `fill`, because those are\n\t// two different options: one lands on `a:tblPr`, the other is stamped onto every cell.\n\t'table.fill.picture': ['tableFill'],\n\t'table.fill.picture.geometry': [],\n\t// A gradient that cannot be expressed falls back to no gradient, so the difference lands\n\t// on the fill option itself — `tableFill` for the background, `fill` for a cell.\n\t'table.fill.gradient': ['tableFill'],\n\t'table.fill.gradient.path': ['tableFill'],\n\t'table.cell.fill.gradient': ['fill'],\n\t'table.cell.fill.gradient.path': ['fill'],\n\t// Narrowed to the East-Asian `ST_TextVerticalType` modes `textDirection` cannot spell —\n\t// the four it can now round-trip, so this no longer excuses every vertical cell.\n\t'table.cell.vert': ['textDirection', 'vert'],\n\t'table.rowAuto': ['rowH'],\n\t'table.style': ['tableStyle'],\n\t'text.align': ['align'],\n\t// `text.bullet.numberStartAt` and `text.bullet.style` used to live here, for\n\t// `a:buAutoNum/@startAt` and for a bullet's own font/size/colour. `Paragraph.bulletDetail`\n\t// reads all four, so the mapper emits `numberStartAt` / `fontFace` / `size` / `color` and\n\t// records nothing — the notes are gone rather than unmapped. What remains of the size half\n\t// is `text.bullet.sizePt`, which is a genuinely unwritable unit rather than an unread value.\n\t'text.bullet.numberType': ['bullet'],\n\t// An absolute bullet size (`a:buSzPts`) has no write option at all — `bullet.size` is a\n\t// percentage of the run size — so the difference lands on the bullet option.\n\t'text.bullet.sizePt': ['bullet'],\n\t// A percentage outside 25–400%, which the write path rejects with a warning and replaces\n\t// with the run's own size.\n\t'text.bullet.sizePct': ['bullet'],\n\t// A bullet colour outside the ten scheme tokens the write path maps, baked to a literal.\n\t'text.bullet.schemeToken': ['bullet'],\n\t// A picture bullet (`a:buBlip`): readable, and `bullet.image` could author it, but the\n\t// paragraph mapper carries no asset resolver to re-embed the bytes with.\n\t'text.bullet.picture': ['bullet'],\n\t'text.color.default': ['color'],\n\t'text.color.inherited': ['color'],\n\t'text.color.schemeToken': ['color'],\n\t'text.equation': ['*'],\n\t'text.field': ['*'],\n\t'text.bullet.glyph': ['bullet'],\n\t// `text.bullet.inherited` used to live here — a paragraph stating no bullet of its own was\n\t// re-emitted with an explicit `a:buNone`, because omitting the write API's `bullet` is that\n\t// element rather than silence. `bullet: 'inherit'` says silence now, so the mapper carries\n\t// the state instead of excusing its loss and the note is gone rather than unmapped.\n\t//\n\t// `text.indent` used to live here, empty, because a paragraph's `a:pPr/@marL` and `@indent`\n\t// were in neither IR — the write API had no option for them, so the mapper never emitted one\n\t// and the diff compared two models both missing the field. `paraMarginLeft` / `paraIndent`\n\t// put it in both, which is what turns an empty entry into a comparison rather than a caveat,\n\t// so the note is gone rather than unmapped.\n\t'text.paraSpaceZero': ['paraSpaceBefore', 'paraSpaceAfter'],\n\t'text.vert': ['vert'],\n}\n\n/**\n * Every note construct this table knows how to match, for a test to check against. The\n * `layout.` spellings are not listed — they resolve through {@link isKnownNoteConstruct},\n * which is what a corpus check should use.\n */\nexport function knownNoteConstructs(): string[] {\n\treturn Object.keys(NOTE_FIELDS).sort()\n}\n\n/**\n * Compare the deck a script was generated from against the deck it produced.\n *\n * `notes` must be the set that actually applies to the printed output — `printScript`'s\n * returned `notes`, not `DeckIr.fidelity`. The two differ in both directions: the printer\n * suppresses notes its tier rescues and adds ones its tier causes, so diffing against the\n * IR's own list would both over- and under-exclude.\n */\nexport function diffDeckIr(expected: CanonicalDeck, actual: CanonicalDeck, notes: FidelityNote[]): RoundTripReport {\n\tconst differences: IrDifference[] = []\n\n\tif (expected.slideSize.widthEmu !== actual.slideSize.widthEmu) {\n\t\tdifferences.push(scalarDifference(0, null, [], 'slideSize.widthEmu', 'widthEmu', expected.slideSize.widthEmu, actual.slideSize.widthEmu)) // prettier-ignore\n\t}\n\tif (expected.slideSize.heightEmu !== actual.slideSize.heightEmu) {\n\t\tdifferences.push(scalarDifference(0, null, [], 'slideSize.heightEmu', 'heightEmu', expected.slideSize.heightEmu, actual.slideSize.heightEmu)) // prettier-ignore\n\t}\n\n\tdiffValue(expected.props, actual.props, 'props', 'props', 0, null, [], differences)\n\tdiffChrome(expected.chrome, actual.chrome, differences)\n\n\tconst slideCount = Math.max(expected.slides.length, actual.slides.length)\n\tfor (let index = 0; index < slideCount; index++) {\n\t\tconst before = expected.slides[index]\n\t\tconst after = actual.slides[index]\n\t\tconst number = before?.number ?? after?.number ?? index + 1\n\t\tif (!before || !after) {\n\t\t\tdifferences.push({\n\t\t\t\tslideNumber: number,\n\t\t\t\tshapeName: null,\n\t\t\t\tnestedNames: [],\n\t\t\t\tpath: `slides[${index}]`,\n\t\t\t\tfield: '*',\n\t\t\t\tkind: before ? 'lost' : 'added',\n\t\t\t\texpected: before ? 'slide' : '—',\n\t\t\t\tactual: after ? 'slide' : '—',\n\t\t\t\tdeclaredBy: null,\n\t\t\t})\n\t\t\tcontinue\n\t\t}\n\t\tdiffSlide(before, after, differences)\n\t}\n\n\tfor (const difference of differences) difference.declaredBy = declaringNote(difference, notes)\n\tconst matched = new Set(differences.map((difference) => difference.declaredBy).filter(Boolean))\n\tconst accounted = (difference: IrDifference): boolean =>\n\t\tdifference.declaredBy !== null || (difference.kind === 'added' && difference.field in WRITER_DEFAULTS)\n\n\treturn {\n\t\tslideCount: expected.slides.length,\n\t\tdifferences,\n\t\tundeclared: differences.filter((difference) => !accounted(difference)),\n\t\tdeclared: differences.filter((difference) => difference.declaredBy !== null),\n\t\tadded: differences.filter((difference) => difference.kind === 'added'),\n\t\tunmatchedNotes: notes.filter((note) => !matched.has(note)),\n\t}\n}\n\n/**\n * The theme and the layout gallery.\n *\n * Reported at `slideNumber: 0`, the same deck-level bucket the slide size uses, so a\n * deck-scoped note (which carries `slideNumber: null` and matches any slide) can declare one.\n * Masters align by **title**, not by position, for the same reason calls align by shape name:\n * the write path always emits a blank layout of its own at gallery position 0, so positional\n * alignment reports every layout in the deck as renamed and buries the one real difference —\n * that extra layout — under a shift.\n *\n * And, exactly as with shape names, a title is only usable as a key where it is *unique on\n * both sides*. Uniqueness is supposed to be an invariant here — the converter deduplicates\n * titles because a title is also what `addSlide({ masterTitle })` binds on — but keying on it\n * unconditionally makes the check assume the thing it should be testing: a mutation that\n * removed the deduplication left two layouts sharing a title, both expected entries matched\n * the same actual one, and the round trip came back clean. Falling back to position when the\n * key repeats costs nothing when the invariant holds and catches it when it does not.\n */\nfunction diffChrome(expected: CanonicalChrome, actual: CanonicalChrome, out: IrDifference[]): void {\n\tdiffValue(expected.theme, actual.theme, 'chrome.theme', 'theme', 0, null, [], out)\n\n\t// A whole master appearing or disappearing is reported *scoped to its title*, using the\n\t// same `shapeName` channel a shape-scoped note uses. Without that, one note declaring the\n\t// blank layout the write path always adds would carry `field: 'master'` and excuse every\n\t// added layout — which is what a mutation that stopped deduplicating layout titles proved.\n\tconst report = (\n\t\tpath: string,\n\t\tkind: DifferenceKind,\n\t\tbefore: IrValue | undefined,\n\t\tafter: IrValue | undefined\n\t): void => {\n\t\tout.push({\n\t\t\tslideNumber: 0,\n\t\t\tshapeName: titleOf(before ?? after ?? null),\n\t\t\tnestedNames: decorationNames(before, after),\n\t\t\tpath,\n\t\t\tfield: 'master',\n\t\t\tkind,\n\t\t\texpected: brief(before),\n\t\t\tactual: brief(after),\n\t\t\tdeclaredBy: null,\n\t\t})\n\t}\n\n\tconst byTitle = uniqueByTitle(actual.masters)\n\tconst expectedTitles = uniqueByTitle(expected.masters)\n\tconst claimed = new Set<IrValue>()\n\tlet cursor = 0\n\tconst nextUnclaimed = (): IrValue | undefined => {\n\t\twhile (cursor < actual.masters.length) {\n\t\t\tconst candidate = actual.masters[cursor++]\n\t\t\tif (candidate !== undefined && !claimed.has(candidate)) return candidate\n\t\t}\n\t\treturn undefined\n\t}\n\n\texpected.masters.forEach((before, index) => {\n\t\tconst title = titleOf(before)\n\t\t// Usable only where the title identifies exactly one master on each side.\n\t\tconst named = title !== null && expectedTitles.has(title) ? byTitle.get(title) : undefined\n\t\tconst after = named !== undefined && !claimed.has(named) ? named : nextUnclaimed()\n\t\tif (after === undefined) {\n\t\t\treport(`chrome.masters[${index}]`, 'lost', before, undefined)\n\t\t\treturn\n\t\t}\n\t\tclaimed.add(after)\n\t\t// A layout's decoration rides inside this one value, so a note scoped to one of those\n\t\t// shapes has no call of its own to be matched against — the same problem a group's child\n\t\t// has on a slide, and the same answer.\n\t\tdiffValue(before, after, `chrome.masters[${index}]`, 'master', 0, null, decorationNames(before, after), out)\n\t})\n\n\tactual.masters.forEach((after, index) => {\n\t\tif (!claimed.has(after)) report(`chrome.masters[${index}]`, 'added', undefined, after)\n\t})\n}\n\n/** Masters keyed by title, keeping only titles that identify exactly one of them. */\nfunction uniqueByTitle(masters: IrValue[]): Map<string, IrValue> {\n\tconst counts = new Map<string, number>()\n\tfor (const master of masters) {\n\t\tconst title = titleOf(master)\n\t\tif (title !== null) counts.set(title, (counts.get(title) ?? 0) + 1)\n\t}\n\tconst out = new Map<string, IrValue>()\n\tfor (const master of masters) {\n\t\tconst title = titleOf(master)\n\t\tif (title !== null && counts.get(title) === 1) out.set(title, master)\n\t}\n\treturn out\n}\n\n/**\n * The `objectName`s of every decorative shape in a master's props, taking both sides so a\n * shape that dropped out is still named by the source's.\n */\nfunction decorationNames(before: IrValue | undefined, after: IrValue | undefined): string[] {\n\tconst names = new Set<string>()\n\tfor (const master of [before, after]) if (master !== undefined) collectObjectNames(master, names)\n\treturn [...names]\n}\n\n/** A canonical master's `title`, which is its identity across the round trip. */\nfunction titleOf(master: IrValue): string | null {\n\tif (master === null || typeof master !== 'object' || Array.isArray(master)) return null\n\tconst title = (master as Record<string, IrValue>)['title']\n\treturn typeof title === 'string' ? title : null\n}\n\nfunction diffSlide(expected: CanonicalSlide, actual: CanonicalSlide, out: IrDifference[]): void {\n\tconst number = expected.number\n\tconst at = (path: string, field: string, a: IrValue, b: IrValue): void => {\n\t\tif (JSON.stringify(a) !== JSON.stringify(b)) out.push(scalarDifference(number, null, [], path, field, a, b))\n\t}\n\tat('hidden', 'hidden', expected.hidden, actual.hidden)\n\tat('layoutName', 'layoutName', expected.layoutName, actual.layoutName)\n\tat('background', 'background', expected.background, actual.background)\n\tat('notesText', 'notesText', expected.notesText, actual.notesText)\n\t// Structural rather than whole-value, unlike the four above: a transition is a small object\n\t// whose parts are lost independently — the append path drops an embedded sound while\n\t// keeping the effect — and a whole-value compare would force the note that declares the\n\t// sound to carry `field: 'transition'`, which would then excuse a wrong type or duration too.\n\tdiffValue(expected.transition, actual.transition, 'transition', 'transition', number, null, [], out)\n\n\tfor (const [before, after] of alignCalls(expected.calls, actual.calls)) {\n\t\tconst name = before?.shapeName ?? after?.shapeName ?? null\n\t\t// Union of both sides: a child that dropped out is named only by the source's call.\n\t\tconst nested = [...new Set([...(before?.containedNames ?? []), ...(after?.containedNames ?? [])])]\n\t\tconst path = `calls[${before ? expected.calls.indexOf(before) : actual.calls.indexOf(after as CanonicalCall)}]`\n\t\tif (!before || !after) {\n\t\t\tout.push({\n\t\t\t\tslideNumber: number,\n\t\t\t\tshapeName: name,\n\t\t\t\tnestedNames: nested,\n\t\t\t\tpath,\n\t\t\t\tfield: '*',\n\t\t\t\tkind: before ? 'lost' : 'added',\n\t\t\t\texpected: before ? before.method : '—',\n\t\t\t\tactual: after ? after.method : '—',\n\t\t\t\tdeclaredBy: null,\n\t\t\t})\n\t\t\tcontinue\n\t\t}\n\t\tif (before.method !== after.method) {\n\t\t\tout.push(scalarDifference(number, name, nested, `${path}.method`, 'method', before.method, after.method))\n\t\t}\n\t\tdiffValue(before.args, after.args, `${path}.args`, 'args', number, name, nested, out)\n\t}\n}\n\n/**\n * Pair up the two slides' calls.\n *\n * Position alone is wrong the moment one shape drops out: every later call shifts by one\n * and the report fills with mismatches that are really one missing shape. Shape names\n * survive the round trip (the converter passes `objectName` through), so they are the\n * alignment key wherever they are present and unambiguous, with position as the fallback\n * for unnamed or duplicate-named shapes.\n */\nfunction alignCalls(\n\texpected: CanonicalCall[],\n\tactual: CanonicalCall[]\n): Array<[CanonicalCall | null, CanonicalCall | null]> {\n\tconst usable = (calls: CanonicalCall[]): Map<string, CanonicalCall> => {\n\t\tconst counts = new Map<string, number>()\n\t\tfor (const call of calls) {\n\t\t\tif (call.shapeName === null) continue\n\t\t\tcounts.set(call.shapeName, (counts.get(call.shapeName) ?? 0) + 1)\n\t\t}\n\t\tconst out = new Map<string, CanonicalCall>()\n\t\tfor (const call of calls) {\n\t\t\tif (call.shapeName !== null && counts.get(call.shapeName) === 1) out.set(call.shapeName, call)\n\t\t}\n\t\treturn out\n\t}\n\n\tconst byName = usable(actual)\n\tconst claimed = new Set<CanonicalCall>()\n\tconst pairs: Array<[CanonicalCall | null, CanonicalCall | null]> = []\n\t// Positional cursor for calls that names cannot align, advanced only past claimed calls\n\t// so a named match does not consume an unnamed call's slot.\n\tlet cursor = 0\n\tconst nextUnclaimed = (): CanonicalCall | null => {\n\t\twhile (cursor < actual.length) {\n\t\t\tconst candidate = actual[cursor++]\n\t\t\tif (candidate && !claimed.has(candidate)) return candidate\n\t\t}\n\t\treturn null\n\t}\n\n\tfor (const call of expected) {\n\t\tconst named = call.shapeName === null ? undefined : byName.get(call.shapeName)\n\t\tif (named && !claimed.has(named)) {\n\t\t\tclaimed.add(named)\n\t\t\tpairs.push([call, named])\n\t\t\tcontinue\n\t\t}\n\t\tconst positional = nextUnclaimed()\n\t\tif (positional) claimed.add(positional)\n\t\tpairs.push([call, positional])\n\t}\n\tfor (const call of actual) if (!claimed.has(call)) pairs.push([null, call])\n\treturn pairs\n}\n\nfunction diffValue(\n\texpected: IrValue,\n\tactual: IrValue,\n\tpath: string,\n\tfield: string,\n\tslideNumber: number,\n\tshapeName: string | null,\n\tnestedNames: string[],\n\tout: IrDifference[]\n): void {\n\tif (expected === actual) return\n\tconst kindOf = (value: IrValue): string => (value === null ? 'null' : Array.isArray(value) ? 'array' : typeof value)\n\tif (kindOf(expected) !== kindOf(actual)) {\n\t\tout.push(scalarDifference(slideNumber, shapeName, nestedNames, path, field, expected, actual))\n\t\treturn\n\t}\n\n\tif (Array.isArray(expected) && Array.isArray(actual)) {\n\t\tconst length = Math.max(expected.length, actual.length)\n\t\tfor (let index = 0; index < length; index++) {\n\t\t\tconst before = expected[index]\n\t\t\tconst after = actual[index]\n\t\t\tif (before === undefined || after === undefined) {\n\t\t\t\tout.push({\n\t\t\t\t\tslideNumber,\n\t\t\t\t\tshapeName,\n\t\t\t\t\tnestedNames,\n\t\t\t\t\tpath: `${path}[${index}]`,\n\t\t\t\t\tfield,\n\t\t\t\t\tkind: before === undefined ? 'added' : 'lost',\n\t\t\t\t\texpected: brief(before),\n\t\t\t\t\tactual: brief(after),\n\t\t\t\t\tdeclaredBy: null,\n\t\t\t\t})\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tdiffValue(before, after, `${path}[${index}]`, field, slideNumber, shapeName, nestedNames, out)\n\t\t}\n\t\treturn\n\t}\n\n\tif (expected !== null && typeof expected === 'object' && actual !== null && typeof actual === 'object') {\n\t\tconst record = expected as Record<string, IrValue>\n\t\tconst other = actual as Record<string, IrValue>\n\t\tfor (const key of new Set([...Object.keys(record), ...Object.keys(other)])) {\n\t\t\tconst before = record[key]\n\t\t\tconst after = other[key]\n\t\t\tif (before === undefined || after === undefined) {\n\t\t\t\tout.push({\n\t\t\t\t\tslideNumber,\n\t\t\t\t\tshapeName,\n\t\t\t\t\tnestedNames,\n\t\t\t\t\tpath: `${path}.${key}`,\n\t\t\t\t\tfield: key,\n\t\t\t\t\tkind: before === undefined ? 'added' : 'lost',\n\t\t\t\t\texpected: brief(before),\n\t\t\t\t\tactual: brief(after),\n\t\t\t\t\tdeclaredBy: null,\n\t\t\t\t})\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tdiffValue(before, after, `${path}.${key}`, key, slideNumber, shapeName, nestedNames, out)\n\t\t}\n\t\treturn\n\t}\n\n\tout.push(scalarDifference(slideNumber, shapeName, nestedNames, path, field, expected, actual))\n}\n\nfunction scalarDifference(\n\tslideNumber: number,\n\tshapeName: string | null,\n\tnestedNames: string[],\n\tpath: string,\n\tfield: string,\n\texpected: IrValue,\n\tactual: IrValue\n): IrDifference {\n\treturn {\n\t\tslideNumber,\n\t\tshapeName,\n\t\tnestedNames,\n\t\tpath,\n\t\tfield,\n\t\tkind: 'changed',\n\t\texpected: brief(expected),\n\t\tactual: brief(actual),\n\t\tdeclaredBy: null,\n\t}\n}\n\n/** The first note that covers this difference, or `null` if none does. */\nfunction declaringNote(difference: IrDifference, notes: FidelityNote[]): FidelityNote | null {\n\tfor (const note of notes) {\n\t\tif (note.slideNumber !== null && note.slideNumber !== difference.slideNumber) continue\n\t\t// A layout-shape note is about the chrome, which the diff reports in the deck-level bucket.\n\t\t// Without this a themed outline on a layout — recorded with no slide number, and named\n\t\t// after a shape whose name repeats between the layout and the slides bound to it — would\n\t\t// excuse the same difference on a *slide*, which is a loss nothing declared.\n\t\tif (note.construct.startsWith(LAYOUT_NOTE_PREFIX) && difference.slideNumber !== 0) continue\n\t\t// A shape-scoped note covers only that shape; a slide- or deck-scoped one covers any.\n\t\tif (\n\t\t\tnote.shapeName !== null &&\n\t\t\tnote.shapeName !== difference.shapeName &&\n\t\t\t!difference.nestedNames.includes(note.shapeName)\n\t\t) {\n\t\t\tcontinue\n\t\t}\n\t\tconst fields = noteFields(note.construct)\n\t\tif (!fields) continue\n\t\tif (fields.includes('*') || fields.includes(difference.field)) return note\n\t}\n\treturn null\n}\n\n/**\n * The fields a construct is a promise about.\n *\n * A layout-shape construct falls back to its slide counterpart, which is the whole point of\n * borrowing the vocabulary: `layout.line.width` is `line.width` on a layout and covers exactly\n * the same field. Only the two constructs with no slide twin need entries of their own.\n */\nfunction noteFields(construct: string): readonly string[] | undefined {\n\treturn NOTE_FIELDS[construct] ?? (construct.startsWith(LAYOUT_NOTE_PREFIX) ? NOTE_FIELDS[construct.slice(LAYOUT_NOTE_PREFIX.length)] : undefined) // prettier-ignore\n}\n\n/**\n * `true` when the coverage table can match this construct — directly or through the\n * layout-shape fallback. The check a corpus test runs over every note both printers emit.\n */\nexport function isKnownNoteConstruct(construct: string): boolean {\n\treturn noteFields(construct) !== undefined\n}\n\nfunction brief(value: IrValue | undefined): string {\n\tif (value === undefined) return '—'\n\tconst text = JSON.stringify(value)\n\treturn text.length > 80 ? `${text.slice(0, 80)}…` : text\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"script.js","names":["printSlides"],"sources":["../src/script/units.ts","../src/script/from-read/values.ts","../src/script/from-read/picture-fill.ts","../src/script/from-read/surface-fill.ts","../src/script/from-read/background.ts","../src/script/fidelity.ts","../src/script/ir.ts","../src/script/from-read/detect.ts","../src/script/from-read/text.ts","../src/script/from-read/table.ts","../src/script/from-read/chart.ts","../src/script/from-read/context.ts","../src/script/from-read/shape-paint.ts","../src/script/from-read/shape.ts","../src/script/from-read/chrome.ts","../src/script/from-read/transition.ts","../src/script/from-read/deck.ts","../src/script/print/literal.ts","../src/script/print/common.ts","../src/script/print/script.ts","../src/script/print/standalone.ts","../src/script/verify/canonical.ts","../src/script/verify/align.ts","../src/script/verify/diff.ts"],"sourcesContent":["/**\n * ts-pptx: the script converter's unit conversions, on the seam between its two halves.\n *\n * `docs/contributing/architecture.md` states the seam: \"`from-read/` knows OOXML and the read model,\n * `print/` knows only strings, and neither can see the other.\" Both halves nonetheless have\n * to turn an EMU slide size into inches — `ir.ts` keeps `slideSize` in EMU deliberately,\n * because \"converting here would introduce a rounding decision at the wrong layer\" — and the\n * printer was reaching across the seam into `from-read/values.ts` to do it.\n *\n * So the conversion lives here, beside `ir.ts`, which is the module both halves already\n * import. Nothing in here knows about the read model or about strings.\n */\n\nimport { EMU_PER_INCH } from '../units.js'\n\n/**\n * Decimal places used for the inch-typed options.\n *\n * The proven minimum for an EMU-exact round-trip, not a formatting preference: `appendSlides`\n * compares slide sizes exactly and throws when they differ, so a generated script's\n * `defineLayout` has to land back on the source EMU.\n */\nexport const INCH_DECIMALS = 6\n\n/**\n * Round a length already in inches to {@link INCH_DECIMALS}, which is EMU-exact on the way back.\n *\n * The one rounding: `inches` below and `pointsToInches` in the mapper each carried it, and the\n * second spelled the divisor as a bare `72`.\n */\nexport function toInches(value: number): number {\n\treturn Number(value.toFixed(INCH_DECIMALS))\n}\n\n/**\n * Geometry as inches, for the options that reject a raw-EMU string. Rounded to\n * {@link INCH_DECIMALS}, which is EMU-exact on the way back.\n */\nexport function inches(emuValue: number): number {\n\treturn toInches(emuValue / EMU_PER_INCH)\n}\n","/**\n * Value-level conversions shared by every mapper: geometry, colour, and the small\n * discipline that keeps an IR diffable.\n *\n * The precision rules here are not style choices, they are the measured boundary of what\n * the write API can carry, and each is pinned by a regression test:\n *\n * - A `Coord`-typed option accepts `` `${n}emu` ``, so EMU passes through untouched and\n * the source geometry is reproduced exactly. That covers every position and size.\n * - `colW`, `rowH`, and `margin` are number/`Margin`-typed **inches** and reject a raw-EMU\n * string, so they are where exactness stops. `defineLayout`'s `width`/`height` are a\n * fourth, reached only by a printer: there the imprecision does not degrade quietly but\n * *throws*, since `appendSlides` compares the two decks' EMU sizes for equality after\n * converting the declared inches back. Six decimal places is the minimum\n * at which `Math.round(printed × 914400)` provably returns the original EMU, bounding the\n * drift at 0.4572 EMU — about half a millionth of an inch. Rounding shorter to suppress\n * `0.5000000001`-style noise trades a cosmetic problem for a real geometry loss.\n */\nimport type { IrValue } from '../ir.js'\nimport type { Shape } from '../../read.js'\nimport type { NoteScope, RecordableConstruct } from '../fidelity.js'\nimport { emuToPoints, FIXED_PCT_PER_PERCENT, PERCENT_SCALE, POINTS_PER_INCH } from '../../units.js'\n// Re-exported so this module stays the one import the mappers reach for; it lives in\n// `script/units.ts` because the printer needs it too and may not import from here.\nexport { inches, INCH_DECIMALS } from '../units.js'\nimport { toInches } from '../units.js'\nimport { stripHash } from '../../hex-color.js'\nimport { PRESET_LINE_DASHES } from '../../ooxml/st-enums.js'\nimport { SchemeColor } from '../../enums.js'\nimport { VALIGN_BY_ANCHOR } from '../../ooxml/text-anchor.js'\n\n/** Geometry as a `Coord` the write API takes verbatim, preserving the exact EMU. */\nexport function emu(value: number): string {\n\treturn `${Math.round(value)}emu`\n}\n\n/** EMU → points, the unit the write API uses for line widths and font sizes. */\nexport function points(emuValue: number): number {\n\treturn emuToPoints(emuValue)\n}\n\n/**\n * Points → inches, at the same proven precision as {@link inches}. Needed because the read\n * model reports text-body insets in points while the write API's `margin` takes inches —\n * and warns on a value `>= 1`, on the assumption that it is a points value passed by\n * mistake, so handing it points would both mis-scale the text and produce a warning.\n */\nexport function pointsToInches(pt: number): number {\n\treturn toInches(pt / POINTS_PER_INCH)\n}\n\n/**\n * A colour for a write-API `color` field. The read model splits a colour into a raw\n * `schemeClr` token and a resolved literal hex; this prefers the token, because a token\n * re-resolves against the destination theme and so keeps the deck recolourable, which is\n * the whole reason a theme colour was authored.\n *\n * Only the tokens the write path's `clrMap` covers survive as tokens — the other seven\n * `ST_SchemeColorVal` values degrade to a hex literal there anyway, so passing them through\n * would produce a silently different colour. Callers hand those to {@link literalColor}\n * instead after recording a note.\n *\n * Derived from `SchemeColor` rather than transcribed from it. A hand-written copy of the ten\n * meant that a member added to the enum would keep being treated as unwritable here: baked to\n * a hex literal under an \"approximated\" note that had stopped being true, which is worse than\n * a loud failure. The write side already asks the same question of the same enum\n * (`gen/define/chart.ts`).\n */\nconst WRITABLE_SCHEME_TOKENS: ReadonlySet<string> = new Set(Object.values(SchemeColor))\n\n/** `true` when a `schemeClr` token survives as a token rather than degrading to hex. */\nexport function isWritableSchemeToken(token: string | null): boolean {\n\treturn token !== null && WRITABLE_SCHEME_TOKENS.has(token)\n}\n\n/**\n * A source's `schemeClr` token as the write API's `color`, baked to a literal hex (with a\n * note) when the token is one of the seven the write path cannot carry, or `undefined` when\n * the source names no token at all.\n *\n * `undefined` means \"this leg has nothing to say\" — the caller's own-colour ladder decides\n * from there. Seven sites make this decision and four of them made it correctly: the table\n * fill, the cell fill and the cell border all returned an unwritable token *raw*, so a cell\n * filled `<a:schemeClr val=\"dk1\"/>` emitted `fill: { color: 'dk1' }` and the generated script\n * warned and painted the cell the default text colour, with no note; the gradient stop baked\n * without recording one.\n *\n * @param scheme - the raw `a:schemeClr/@val`, or `null` when the source names none\n * @param resolvedHex - the literal the token resolves to, for the baking leg\n * @param notes - the scope the approximation is recorded on\n * @param construct - the note's construct id, e.g. `table.cell.fill.schemeToken`\n * @param label - how the note's prose names the thing, e.g. `cell fill`\n */\nexport function schemeColorOption(\n\tscheme: string | null,\n\tresolvedHex: string | null,\n\tnotes: NoteScope,\n\tconstruct: RecordableConstruct,\n\tlabel: string\n): string | undefined {\n\tif (isWritableSchemeToken(scheme)) return scheme as string\n\tif (scheme === null) return undefined\n\tnotes.note(\n\t\tconstruct,\n\t\t'approximated',\n\t\t'unwritable',\n\t\t`${label} scheme colour \"${scheme}\" is outside the ten tokens the write path maps, so it is baked to a literal hex and stops tracking the theme`\n\t)\n\treturn resolvedHex === null ? undefined : literalColor(resolvedHex)\n}\n\n/**\n * One colour, as the read model splits it, resolved into the write API's single `color` field.\n *\n * The ladder, in order:\n *\n * 1. a **writable scheme token** — kept as a token, so the copy keeps tracking its theme;\n * 2. the surface's **own literal**, where the read model separates it from the resolved one;\n * 3. an **unwritable token**, noted and baked to the literal it resolves to;\n * 4. the **resolved literal**, for the colour models the write API's hex option cannot name;\n * 5. `undefined` — nothing to say, and the caller's own arm decides from there.\n *\n * Steps 2 and 3 cannot both apply: `a:solidFill` holds exactly one colour child, so a surface\n * has either an `a:srgbClr` or an `a:schemeClr` and never both. That is what makes one order\n * safe for all six sites, which is worth stating because the six had three orders between them\n * — one put the own literal first, one never consulted it at all, and one tested the token for\n * `null` before calling. {@link schemeColorOption} extracted the middle step and the ladder\n * around it stayed copied.\n *\n * @param color - the three spellings the read model reports\n * @param notes - the scope an unwritable token is noted on\n * @param construct - the note's construct id, e.g. `table.cell.fill.schemeToken`\n * @param label - how the note's prose names the thing, e.g. `cell fill`\n */\nexport function colorOption(\n\tcolor: { scheme: string | null; ownHex?: string | null; resolvedHex: string | null },\n\tnotes: NoteScope,\n\tconstruct: RecordableConstruct,\n\tlabel: string\n): string | undefined {\n\tif (isWritableSchemeToken(color.scheme)) return color.scheme as string\n\tif (color.ownHex != null) return literalColor(color.ownHex)\n\treturn (\n\t\tschemeColorOption(color.scheme, color.resolvedHex, notes, construct, label) ??\n\t\t(color.resolvedHex === null ? undefined : literalColor(color.resolvedHex))\n\t)\n}\n\n/**\n * `a:bodyPr/@anchor` and `a:tcPr/@anchor` -> the write API's `valign`.\n *\n * Derived from the same table `resolveTextAnchor` reads, rather than written out again here:\n * this side cannot import `gen/`, so the two directions had no way to stay in step.\n */\nexport const ANCHOR_TO_VALIGN = VALIGN_BY_ANCHOR\n\n/**\n * The `a:prstDash` values the write API's `dashType` can spell.\n *\n * A dash outside `ST_PresetLineDashVal` cannot have come from a conformant deck; both mappers\n * that read one drop it to a plain dashed rule and note the loss, and both built this set.\n */\nexport const WRITABLE_DASHES: ReadonlySet<string> = new Set<string>(PRESET_LINE_DASHES)\n\n/**\n * A shape's or frame's Selection Pane name as the IR's `sourceName`, or nothing when it has none.\n *\n * `sourceName` is how a call in the emitted script says which shape it came from, so it is\n * omitted rather than written empty. Three mappers spelled the ternary; this is it.\n */\nexport function nameOf(subject: { name: string | null }): { sourceName?: string } {\n\treturn subject.name ? { sourceName: subject.name } : {}\n}\n\n/**\n * The write options that carry a source object's identity onto the object a call authors: its\n * Selection Pane name and its alt text.\n *\n * Seven call builders spelled `objectName: shape.name || undefined` beside {@link nameOf}, so what a\n * source's identity becomes on the write side was a decision made seven times over, and none of the\n * seven made it for the description: `p:cNvPr/@descr` was read and never emitted, so every picture's\n * and text box's alt text was lost with no note. An empty description is no description, which is\n * how the write side spells one it was not given.\n * @param subject - the source shape or graphic frame\n */\nexport function identityOptions(subject: {\n\tname: string | null\n\tdescription: string | null\n}): Record<string, IrValue | undefined> {\n\treturn { objectName: subject.name || undefined, altText: subject.description || undefined }\n}\n\n/** Normalize a hex to the bare 6-digit uppercase form the write API expects. */\nexport function literalColor(hex: string): string {\n\treturn stripHash(hex).toUpperCase()\n}\n\n/**\n * Build an IR object from possibly-absent parts, dropping every `undefined`.\n *\n * Every mapper funnels through this. An IR must spell \"absent\" exactly one way — a\n * missing key — or two IRs describing the same deck compare unequal because one wrote\n * `{ bold: undefined }` and the other wrote `{}`. That would surface as phantom\n * round-trip failures, so the invariant is enforced in one place rather than trusted to\n * every call site.\n *\n * Returns `undefined` when nothing survived, so a caller can drop the whole option object\n * rather than emit an empty one.\n */\nexport function compact(source: Record<string, IrValue | undefined>): Record<string, IrValue> | undefined {\n\tconst out: Record<string, IrValue> = {}\n\tlet any = false\n\tfor (const key of Object.keys(source).sort()) {\n\t\tconst value = source[key]\n\t\tif (value === undefined) continue\n\t\tout[key] = value\n\t\tany = true\n\t}\n\treturn any ? out : undefined\n}\n\n/** {@link compact}, but always an object — for a required options argument. */\nexport function compactRequired(source: Record<string, IrValue | undefined>): Record<string, IrValue> {\n\treturn compact(source) ?? {}\n}\n\n/** Drop a value that is `null`, so the read model's \"unset\" becomes an absent IR key. */\nexport function orUndefined<T>(value: T | null): T | undefined {\n\treturn value === null ? undefined : value\n}\n\n/**\n * A 0-1 fraction the read model took off a fixed-point percentage, as the write API's 0-100\n * percent.\n *\n * `parsePercent` divided the source's thousandths of a percent by `PERCENT_SCALE`; this undoes\n * exactly that, so the integer the writer re-derives (`Math.round(percent × 1000)`) is the one\n * the source held. A stop at `pos=\"33333\"` is `33.333`, not `33`: whole-percent rounding moved\n * it by up to half a percent and the re-read deck agreed with the rounded value, so the round\n * trip could not see it.\n */\nexport function fractionToPercent(fraction: number): number {\n\treturn Math.round(fraction * PERCENT_SCALE) / FIXED_PCT_PER_PERCENT\n}\n\n/**\n * A 0-1 opacity as the write API's 0-100 transparency, at the source's own precision;\n * `undefined` when unset **or fully opaque**.\n *\n * Fully opaque is not `0`, and that is this function's rule rather than each caller's:\n * emitting `transparency: 0` for an `a:alphaModFix amt=\"100000\"` produces a key the output\n * cannot have, because the write path emits no `a:alphaModFix` for a zero transparency, so\n * the re-read deck reports no alpha and the round trip sees a difference where there is no\n * visible one. One of five callers implemented that; the other four passed the value straight\n * through, and it stayed invisible only because the canonicaliser drops `transparency: 0` as\n * an implied default.\n */\nexport function alphaToTransparency(alpha: number | null | undefined): number | undefined {\n\tif (alpha === undefined || alpha === null) return undefined\n\t// `> 0` rather than `alpha < 1`, so an alpha past 1 and one a hair under it agree: both state\n\t// nothing. The background mapper kept its own copy with that rule and whole-percent rounding,\n\t// so an alpha of 0.996 was `undefined` there and `0` here.\n\tconst transparency = fractionToPercent(1 - alpha)\n\treturn transparency > 0 ? transparency : undefined\n}\n\n/** A shape's box in EMU, as {@link frameOf} resolves it. */\nexport interface ShapeBox {\n\tleft: number\n\ttop: number\n\twidth: number\n\theight: number\n}\n\n/**\n * Where a shape sits on the slide, or `null` when nothing places it — in which case a\n * `shape.frameUnresolved` note has been recorded and the caller drops the shape.\n *\n * `absoluteFrame` rather than the raw `left`/`top`: a shape inside a group is positioned in\n * its group's child coordinate space, which a flattened call list cannot express, so the\n * group transform has to be composed in here. For a top-level shape the two are identical.\n *\n * Neither frame resolves for a shape with no `a:xfrm` of its own that is not a placeholder, or a\n * placeholder whose layout and master define no geometry either. The mappers used to part ways\n * there: a connector returned `null` with no note, breaking the rule that a dropped shape is\n * never silent, and every other kind was emitted with no `x/y/w/h`, which the writer places at\n * its default position. Neither is where the source put it, and the second looks deliberate, so\n * every kind now drops the shape and says so.\n *\n * Takes the `Shape` base rather than `AnyShape` so a `p:graphicFrame` — a table or a chart —\n * gets the same fallback and the same note. It had its own `positionOfFrame`, which returned\n * `{}` in exactly the case this fallback exists for, with no note: `absoluteFrame` is `null`\n * whenever an enclosing group lacks a usable transform, so a table inside such a group emitted\n * `addTable(rows, { objectName, tableStyle })` with no geometry at all.\n */\nexport function frameOf(shape: Shape, notes: NoteScope): ShapeBox | null {\n\tconst frame = shape.absoluteFrame\n\tif (frame) return frame\n\n\t// No usable absolute frame — a placeholder taking its geometry from the layout or master, or\n\t// a shape inside a group whose own transform is missing or degenerate. `resolvedFrame` walks\n\t// that chain, and using it is not optional: omitting the geometry does *not* leave it to be\n\t// inherited, because a regenerated slide's placeholder inherits nothing. It produces\n\t// `x=0 y=0 w=<slide width> h=0` — a zero-height box in the corner, which is broken output\n\t// rather than lossy output.\n\tconst resolved = shape.resolvedFrame\n\tif (!resolved) {\n\t\tnotes.note(\n\t\t\t'shape.frameUnresolved',\n\t\t\t'dropped',\n\t\t\t'unread',\n\t\t\t'this shape has no transform of its own (a:xfrm) and no placeholder geometry to inherit, so nothing places it; it is omitted rather than emitted at the default position'\n\t\t)\n\t\treturn null\n\t}\n\t// `source: 'own'` means the shape DOES have its own `a:xfrm` and it is the enclosing group\n\t// that could not be composed, so the prose says that rather than \"takes its geometry from\n\t// the own\".\n\tnotes.note(\n\t\t'shape.frameInherited',\n\t\t'flattened',\n\t\t'unsupported',\n\t\tresolved.source === 'own'\n\t\t\t? 'this shape sits in a group whose transform could not be composed, so its own position is baked in as a slide-absolute one'\n\t\t\t: `this shape has no transform of its own and takes its geometry from the ${resolved.source}; a regenerated slide inherits nothing, so the resolved position is baked in and stops tracking later edits to that ${resolved.source}`\n\t)\n\treturn resolved\n}\n\n/** A box from {@link frameOf} as `Coord`-typed EMU strings, so the source geometry survives exactly. */\nexport function positionOptions(box: ShapeBox): Record<string, IrValue> {\n\treturn { x: emu(box.left), y: emu(box.top), w: emu(box.width), h: emu(box.height) }\n}\n","/**\n * `a:blipFill` on a *surface* → the write API's `fill: { type: 'image', image: { data } }`.\n *\n * Shared by a shape's fill and a table cell's, which are the same construct read from two\n * containers: `TableCellProps.fill` and `ShapeProps.fill` are both `ShapeFillProps`, so\n * the mapping is identical and only the note wording differs. Keeping one implementation\n * is what stops the two drifting into different answers for the same `a:blipFill`.\n *\n * The bytes, the blip's opacity and the source crop carry. Nothing else does, and that is a\n * property of the write path rather than of this mapper: `genXmlImageFill` emits every\n * picture fill as `<a:blipFill dpi=\"0\" rotWithShape=\"1\">…<a:stretch><a:fillRect/></a:stretch>`\n * with only its `<a:srcRect>` under the caller's control, so a tiled fill still comes back\n * stretched. That is a visible change, so it is noted when — and only when — the source\n * actually uses it.\n */\nimport type { FillRect, PictureFill } from '../../read/api/picture-fill.js'\nimport type { NoteScope } from '../fidelity.js'\nimport type { AssetRef, IrValue } from '../ir.js'\nimport type { AssetResolver } from './context.js'\nimport { alphaToTransparency, compact, compactRequired, fractionToPercent } from './values.js'\n\n/** How a note names the surface it is about; the mapping itself does not vary. */\nexport interface PictureFillSubject {\n\t/**\n\t * Note construct for a fill whose bytes cannot be carried at all. The union rather than\n\t * `string`, so that this and the `` `${construct}.geometry` `` spelling below are both\n\t * checked against the catalogue.\n\t */\n\tconstruct: 'fill.picture' | 'table.fill.picture' | 'table.cell.fill.picture'\n\t/** The surface as a note's detail names it — \"this shape's surface\", \"this table cell\". */\n\tsubject: string\n\t/** Where the fill sits in the source XML, for a note's detail. */\n\telement: string\n}\n\n/**\n * A picture fill as `ShapeFillProps`, or `undefined` when its bytes cannot be carried —\n * in which case a `dropped` note has been recorded and the surface comes out unfilled.\n */\nexport function pictureFillOption(\n\tpicture: PictureFill,\n\tassets: AssetResolver,\n\tnotes: NoteScope,\n\tsubject: PictureFillSubject\n): IrValue | undefined {\n\tconst asset = pictureAsset(picture, assets, notes, subject)\n\tif (!asset) return undefined\n\n\tconst crop = cropOption(picture.srcRect)\n\tnoteUncarriedGeometry(picture, notes, subject, crop !== undefined)\n\n\treturn compactRequired({\n\t\ttype: 'image',\n\t\timage: compactRequired({ crop, data: asset }),\n\t\ttransparency: alphaToTransparency(picture.alpha),\n\t})\n}\n\n/** The fill's image as an asset, or `null` with a note saying why it could not be one. */\nfunction pictureAsset(\n\tpicture: PictureFill,\n\tassets: AssetResolver,\n\tnotes: NoteScope,\n\tsubject: PictureFillSubject\n): AssetRef | null {\n\tconst partName = picture.partName\n\tif (partName === null) {\n\t\tnotes.note(\n\t\t\tsubject.construct,\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t`${subject.subject} is filled with an image (${subject.element}) that embeds no image part — an external or linked blip — so there are no bytes to carry and it comes out unfilled`\n\t\t)\n\t\treturn null\n\t}\n\n\t// The write path refuses an SVG picture fill outright (`src/gen/define/image.ts` warns\n\t// and falls back to `type: 'none'`), so emitting one would produce a script that paints\n\t// nothing while claiming a fill. Checked *before* `assetFor`, which would otherwise\n\t// register bytes that no call ends up referencing.\n\tif (assets.contentTypeOf(partName) === 'image/svg+xml') {\n\t\tnotes.note(\n\t\t\tsubject.construct,\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t`${subject.subject} is filled with an SVG image (${subject.element} → ${partName}); a picture fill accepts raster bytes only on the write side, so it comes out unfilled`\n\t\t)\n\t\treturn null\n\t}\n\n\tconst asset = assets.assetFor(partName)\n\tif (!asset) {\n\t\tnotes.note(\n\t\t\tsubject.construct,\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t`the image filling ${subject.subject} (${subject.element} → ${partName}) is not present in the package, so there are no bytes to carry`\n\t\t)\n\t\treturn null\n\t}\n\treturn asset\n}\n\n/** `true` when a rect actually insets an edge; an explicit but empty rect reports zeros. */\nexport function isRectSet(rect: FillRect | null): boolean {\n\treturn rect !== null && (rect.left !== 0 || rect.top !== 0 || rect.right !== 0 || rect.bottom !== 0)\n}\n\n/**\n * The source crop as the write API's `crop`, or `undefined` when this rect cannot be one — in which\n * case the caller notes it as uncarried instead. A picture fill's `image.crop` and a picture's own\n * `crop` take the same percentage insets, so both go through here.\n *\n * An all-zero rect is `undefined` rather than four zeros: `<a:srcRect/>` is what the write\n * path emits with no `crop` at all, so carrying zeros would add an option that changes\n * nothing and take the fill off its byte-identical path for no reason.\n *\n * Two shapes of rect are legal in a source and not expressible as `crop`, and both belong\n * to the write path rather than to this mapper (`gen/drawingml/src-rect.ts` throws on\n * each): a **negative** inset, which is how a `contain`-style fill bleeds the source past\n * the surface, and a pair of opposite insets summing to 100% or more, which leaves no\n * source area. Carrying either would emit a script that throws when it is run, so they\n * stay uncarried and keep their note.\n */\nexport function cropOption(srcRect: FillRect | null): IrValue | undefined {\n\tif (!isRectSet(srcRect) || srcRect === null) return undefined\n\t// Exact, so the crop survives the trip byte for byte rather than to within a rounding step.\n\tconst edges = {\n\t\tb: fractionToPercent(srcRect.bottom),\n\t\tl: fractionToPercent(srcRect.left),\n\t\tr: fractionToPercent(srcRect.right),\n\t\tt: fractionToPercent(srcRect.top),\n\t}\n\tif (Object.values(edges).some((v) => v < 0 || v > 100)) return undefined\n\tif (edges.l + edges.r >= 100 || edges.t + edges.b >= 100) return undefined\n\t// A zero edge is the option's own default, so it is left out rather than spelled.\n\treturn compact({\n\t\tb: edges.b || undefined,\n\t\tl: edges.l || undefined,\n\t\tr: edges.r || undefined,\n\t\tt: edges.t || undefined,\n\t})\n}\n\n/**\n * Note the parts of the fill's geometry the write path's fixed stretch cannot express.\n *\n * Only the ones the source actually uses: a note on every picture fill would say nothing,\n * and the round-trip check reads an unmatched note as a candidate for review. `cropCarried`\n * is the one that is conditional on more than the source — the crop is expressible as\n * `image.crop` unless its insets fall outside what that option accepts, so whether it is\n * lost is the caller's answer to give.\n */\nfunction noteUncarriedGeometry(\n\tpicture: PictureFill,\n\tnotes: NoteScope,\n\tsubject: PictureFillSubject,\n\tcropCarried: boolean\n): void {\n\tconst lost: string[] = []\n\tif (picture.mode === 'tile' || picture.tile !== null) lost.push('tiling (a:tile)')\n\tif (isRectSet(picture.srcRect) && !cropCarried)\n\t\tlost.push('the source crop (a:srcRect), whose insets fall outside the 0–100% `image.crop` accepts')\n\tif (isRectSet(picture.fillRect)) lost.push('the destination inset (a:stretch/a:fillRect)')\n\tif (picture.dpi !== null && picture.dpi !== 0) lost.push(`the render resolution (@dpi=\"${picture.dpi}\")`)\n\t// Only the explicit `0`. Unset means \"whatever the application defaults to\", which is\n\t// not a claim this note can make about a difference.\n\tif (picture.rotWithShape === false) lost.push('not rotating with the shape (@rotWithShape=\"0\")')\n\tif (lost.length === 0) return\n\n\tnotes.note(\n\t\t`${subject.construct}.geometry`,\n\t\t'approximated',\n\t\t'unwritable',\n\t\t`the image filling ${subject.subject} is re-embedded, but the write path emits every picture fill as a stretched blip at a fixed dpi=\"0\" rotWithShape=\"1\", with only its <a:srcRect> under the caller's control, so ${lost.join(', ')} ${lost.length === 1 ? 'does' : 'do'} not carry`\n\t)\n}\n","/**\n * The non-solid halves of a surface's fill — `a:gradFill` and `a:pattFill` — as\n * `ShapeFillProps`.\n *\n * Shared by a shape's fill, a table's background, and a table cell's, which are the same\n * two elements read from three containers. `ShapeProps.fill`, `TableProps.tableFill` and\n * `TableCellProps.fill` are all `ShapeFillProps`, so the mapping is identical and only the\n * note's `where` prefix differs — the same reasoning that keeps `pictureFillOption` in one\n * place rather than one copy per surface.\n */\nimport type { GradientFill } from '../../read/api/gradient.js'\nimport type { PatternFill } from '../../read/api/pattern-fill.js'\nimport type { PictureFill } from '../../read/api/picture-fill.js'\nimport type { ResolvedColor } from '../../read/api/theme-context.js'\nimport type { AssetResolver } from './context.js'\nimport { pictureFillOption, type PictureFillSubject } from './picture-fill.js'\nimport type { NoteScope } from '../fidelity.js'\nimport type { IrValue } from '../ir.js'\nimport {\n\talphaToTransparency,\n\tcolorOption,\n\tcompact,\n\tfractionToPercent,\n\tisWritableSchemeToken,\n\tliteralColor,\n} from './values.js'\n\n/**\n * The two background tiers, which read the same `a:gradFill` and `a:pattFill` out of `p:bgPr` and\n * record their notes under their own construct: a slide's and a layout's are separate losses.\n */\nexport type BackgroundSurface = 'slide.background' | 'master.background'\n\n/** How a note names the surface a gradient sits on: `fill.gradient`, `table.fill.gradient`, … */\ntype FillNoteScope = 'fill' | 'line' | 'table.fill' | 'table.cell.fill' | BackgroundSurface\n\n/** How a note's prose names a gradient stop's surface. */\nfunction stopLabel(where: FillNoteScope): string {\n\tif (where === 'line') return 'line gradient stop'\n\tif (where === 'slide.background' || where === 'master.background') return 'background gradient stop'\n\treturn 'fill gradient stop'\n}\n\n/**\n * A read gradient as `GradientFillProps`. Stop positions convert from the read model's\n * 0–1 fraction to the write API's 0–100 percentage; the angle needs no conversion, since\n * both sides use OOXML degrees (clockwise from 3 o'clock).\n */\nexport function gradientStops(gradient: GradientFill, notes: NoteScope, where: FillNoteScope): IrValue | undefined {\n\tconst stops = gradient.stops\n\t\t.map((stop) => {\n\t\t\t// Scoped by `where`, like the two notes below it. Hardcoding the shape spelling meant a\n\t\t\t// table background's gradient stop recorded `fill.gradient.schemeToken`, whose entry\n\t\t\t// excuses a difference on `fill` — while the difference itself lands on `tableFill`,\n\t\t\t// which the table mapper keeps deliberately distinct. A declared, genuine loss was\n\t\t\t// therefore reported as an undeclared defect, and on a line gradient the note's prose\n\t\t\t// said \"fill\" about a stroke.\n\t\t\tconst color = colorOption(\n\t\t\t\t{ scheme: stop.colorRef.scheme, resolvedHex: stop.colorRef.resolved?.effectiveHex ?? null },\n\t\t\t\tnotes,\n\t\t\t\t`${where}.gradient.schemeToken`,\n\t\t\t\tstopLabel(where)\n\t\t\t)\n\t\t\tif (color === undefined) return null\n\t\t\treturn compact({\n\t\t\t\tcolor,\n\t\t\t\tposition: fractionToPercent(stop.position ?? 0),\n\t\t\t\ttransparency: alphaToTransparency(stop.colorRef.resolved?.alpha),\n\t\t\t}) as IrValue\n\t\t})\n\t\t.filter((stop): stop is IrValue => stop !== null)\n\n\tif (stops.length < 2) {\n\t\tnotes.note(\n\t\t\t`${where}.gradient`,\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t'a gradient with fewer than two resolvable stops cannot be expressed, so this falls back to no gradient'\n\t\t)\n\t\treturn undefined\n\t}\n\n\tif (gradient.kind === 'path') {\n\t\t// `a:path` covers circle/rect/shape; the write API models only the radial case, so\n\t\t// a rectangular or shape-following gradient becomes a circular one.\n\t\tif (gradient.path !== null && gradient.path !== 'circle') {\n\t\t\tnotes.note(\n\t\t\t\t`${where}.gradient.path`,\n\t\t\t\t'approximated',\n\t\t\t\t'unwritable',\n\t\t\t\t`a \"${gradient.path}\" path gradient is emitted as a radial one; the write API models no other path shape`\n\t\t\t)\n\t\t}\n\t\treturn { kind: 'radial', stops }\n\t}\n\treturn compact({ kind: 'linear', angle: gradient.angleDeg ?? 0, stops })\n}\n\n/**\n * A read hatch as `ShapeFillProps` with `type: 'pattern'`, or `undefined` when the pattern\n * names no preset — `a:pattFill/@prst` is what selects the hatch, so without it there is\n * nothing to reproduce.\n *\n * Each colour takes the ladder every other colour does. `PatternFillProps.fgColor`/`bgColor` are\n * `Color`, and the pattern emitter writes a token as `a:schemeClr`, so a writable token stays a\n * token. Both used to be baked to hex, and a theme-coloured hatch could not be told from a literal\n * one, so the copy stopped tracking its theme with nothing to say so.\n */\nexport function patternOption(\n\tpattern: PatternFill | null,\n\tnotes: NoteScope,\n\twhere: FillSurface | BackgroundSurface\n): IrValue | undefined {\n\tif (!pattern?.preset) return undefined\n\tconst color = (scheme: string | null, resolved: ResolvedColor | null, label: string): string | undefined =>\n\t\tcolorOption({ scheme, resolvedHex: resolved?.effectiveHex ?? null }, notes, `${where}.pattern.schemeToken`, label)\n\treturn {\n\t\ttype: 'pattern',\n\t\tpattern: compact({\n\t\t\tpreset: pattern.preset,\n\t\t\tfgColor: color(pattern.foreground.scheme, pattern.foreground.resolved, 'pattern foreground'),\n\t\t\tbgColor: color(pattern.background.scheme, pattern.background.resolved, 'pattern background'),\n\t\t}) ?? { preset: pattern.preset },\n\t}\n}\n\n/**\n * The three surfaces a fill can sit on, and how a note names each. One record rather than three\n * constants in three modules, because every field of it is decided by `where`.\n */\nconst FILL_SURFACES: Record<FillSurface, { label: string; picture: PictureFillSubject }> = {\n\tfill: {\n\t\tlabel: 'fill',\n\t\tpicture: { construct: 'fill.picture', subject: \"this shape's surface\", element: 'a:blipFill' },\n\t},\n\t'table.fill': {\n\t\tlabel: 'table fill',\n\t\tpicture: { construct: 'table.fill.picture', subject: 'this table', element: 'a:tblPr/a:blipFill' },\n\t},\n\t'table.cell.fill': {\n\t\tlabel: 'cell fill',\n\t\tpicture: { construct: 'table.cell.fill.picture', subject: 'this table cell', element: 'a:tcPr/a:blipFill' },\n\t},\n}\n\n/** The surfaces {@link surfaceFill} serves; `line` is a stroke and has its own ladder. */\ntype FillSurface = 'fill' | 'table.fill' | 'table.cell.fill'\n\n/**\n * What {@link surfaceFill} reads. Structural rather than a union of the three read-model\n * classes, because that is exactly the point: a shape, a table and a table cell expose the same\n * accessor names for the same `EG_FillProperties`, which is why three copies of this ladder\n * could exist and drift.\n */\nexport interface FillSubject {\n\tfillNoFill?: boolean\n\tgradientFill: GradientFill | null\n\tpatternFill: PatternFill | null\n\tpictureFill: PictureFill | null\n\tfillSchemeColor: string | null\n\t/** The surface's OWN `a:srgbClr`, where the read model separates it from the resolved one. */\n\tfillColor?: string | null\n\tresolvedFill: ResolvedColor | null\n\t/** `false` on a styled surface means the fill came from the style, not from the surface. */\n\thasOwnFill?: boolean\n}\n\n/**\n * A surface's `EG_FillProperties` as the write API's fill option, or `undefined` when the\n * surface states none.\n *\n * The order is the whole of it, and it is not arbitrary: an explicit `a:noFill` is a statement\n * and comes first; then the non-solid members, because a surface carrying one holds no\n * `a:solidFill` for the colour legs to find and `resolvedFill` would answer with a style's\n * banding colour the source never showed; then the colour ladder — a writable scheme token, the\n * surface's own literal, the resolved literal.\n *\n * Three copies of this walked three subjects that expose the same accessor names, and they had\n * drifted: only the shape's read `alphaModFix`, so a table or cell whose `a:solidFill` carried\n * one lost its transparency with nothing declaring the loss.\n *\n * @param subject - the shape, table or cell\n * @param ctx - the mapping context, for notes and the asset resolver\n * @param where - which surface this is, deciding the note constructs and prose\n * @param opts - `styled` short-circuits a styled surface with no fill of its own\n */\nexport function surfaceFill(\n\tsubject: FillSubject,\n\tctx: { notes: NoteScope; assets: AssetResolver },\n\twhere: FillSurface,\n\topts: { styled?: boolean } = {}\n): IrValue | undefined {\n\tconst { notes, assets } = ctx\n\tconst surface = FILL_SURFACES[where]\n\n\tif (subject.fillNoFill) return { type: 'none' }\n\n\tconst gradient = subject.gradientFill\n\tif (gradient) {\n\t\tconst stops = gradientStops(gradient, notes, where)\n\t\tif (stops) return { type: 'gradient', gradient: stops }\n\t}\n\n\tconst pattern = patternOption(subject.patternFill, notes, where)\n\tif (pattern) return pattern\n\n\tconst picture = subject.pictureFill\n\tif (picture) return pictureFillOption(picture, assets, notes, surface.picture)\n\n\t// The token and the surface's own literal come before the style short-circuit: both are the\n\t// surface stating a colour of its own, which is what the short-circuit is testing for.\n\tconst scheme = subject.fillSchemeColor\n\tif (isWritableSchemeToken(scheme)) return { color: scheme as string }\n\tif (subject.fillColor != null) return { color: literalColor(subject.fillColor) }\n\n\t// A styled surface with no fill of its own takes the style's banding, and the style GUID\n\t// travels with the table — so emitting nothing here is not a loss, it is what keeps the copy\n\t// responsive to its own style.\n\tif (opts.styled && subject.hasOwnFill === false) return undefined\n\n\tconst resolved = subject.resolvedFill\n\tif (!resolved) return undefined\n\tconst color = colorOption(\n\t\t{ scheme, resolvedHex: resolved.effectiveHex },\n\t\tnotes,\n\t\t`${where}.schemeToken`,\n\t\tsurface.label\n\t)\n\t// The transparency an `a:alphaModFix` on the surface's own `a:solidFill` carries. Only the\n\t// shape's copy of this ladder read it, so a table or a cell lost it with nothing declaring\n\t// the loss.\n\treturn compact({ color, transparency: alphaToTransparency(resolved.alpha) })\n}\n","/**\n * A background (`p:cSld/p:bg`) → {@link BackgroundIr}, for whichever tier read it.\n *\n * There were two of these and only one of them could carry a picture. The layout/master arm\n * handled `solid`, `image` and `themeRef`; the slide arm handled `solid` and `none` and\n * recorded everything else as *not expressible through the write API*. That claim was not\n * true for `image`: `SlideProps.background` takes the same `BackgroundProps` the layout arm\n * authors, and `BackgroundIr.data` is a declared, documented field that nothing could produce\n * for a slide. So a slide-scoped picture background was dropped with a note that misdescribed\n * why.\n *\n * The same misclaim outlived that fix for a gradient and a pattern. `BackgroundProps` extends\n * `ShapeFillProps`, and the background emitter writes any fill a shape's would, so both map\n * through the shape fill's own gradient and pattern mappers.\n *\n * One mapper, two tiers. What stays per tier is the *note*: `slide.background` and\n * `master.background` are separate constructs in the fidelity catalogue, they carry different\n * wording (a slide falls back to its layout's background; a layout has nothing to fall back\n * to), and an existing declared loss keeps its own key.\n *\n * `transparency` had no producer on either arm and now has one on both: the read model\n * resolves an `a:alpha` on the background colour into {@link ResolvedColor.alpha}, and\n * `BackgroundProps.transparency` is the write option that emits it back.\n */\n\nimport type { BackgroundFill, SlideBackground } from '../../read/api/slide-background.js'\nimport type { ColorRef, ResolvedColor } from '../../read/api/theme-context.js'\nimport type { AssetResolver } from './context.js'\nimport type { BackgroundIr } from '../ir.js'\nimport type { NoteScope } from '../fidelity.js'\nimport { gradientStops, patternOption, type BackgroundSurface } from './surface-fill.js'\nimport { alphaToTransparency, colorOption } from './values.js'\n\n/** How one tier names itself in the note it records when a background cannot be carried. */\ninterface BackgroundTier {\n\t/** The fidelity construct this tier's losses are recorded under. */\n\tconstruct: BackgroundSurface\n\t/** How a note names the thing losing its background, e.g. `\"this layout\"`. */\n\tsubject: string\n\t/** What that thing shows instead, e.g. `\"the slide takes its layout's background\"`. */\n\tfallback: string\n}\n\n/** The slide tier: a slide's own `p:bg`, which a slide falls back from to its layout's. */\nexport const SLIDE_BACKGROUND: BackgroundTier = {\n\tconstruct: 'slide.background',\n\tsubject: \"this slide's background\",\n\tfallback: \"the slide takes its layout's background\",\n}\n\n/** The layout/master tier, which has nothing below it to inherit from. */\nexport const MASTER_BACKGROUND: BackgroundTier = {\n\tconstruct: 'master.background',\n\tsubject: \"this layout's background\",\n\tfallback: 'the layout is emitted with no background',\n}\n\n/**\n * Map one tier's background onto the write API's `background` option.\n *\n * `undefined` means *say nothing* — the caller omits the key, and the slide or layout takes\n * whatever it would have inherited. That is the right answer for an absent background and for\n * an explicit `a:noFill`, and it is also what a recorded loss falls back to.\n * @param background - the background the read model resolved, if any\n * @param notes - where a loss this mapper cannot avoid is recorded\n * @param assets - how a picture background's part becomes bytes the script can carry\n * @param tier - which tier is asking, for the note it records\n * @returns the IR background, or `undefined`\n */\nexport function backgroundIr(\n\tbackground: SlideBackground | null,\n\tnotes: NoteScope,\n\tassets: AssetResolver,\n\ttier: BackgroundTier\n): BackgroundIr | undefined {\n\tif (!background) return undefined\n\tif (background.type !== 'themeRef') return fillIr(background, notes, assets, tier)\n\n\t// `p:bgRef` indexes the theme's background fill list, which the write path cannot author.\n\t// The read model resolves it, so the fill survives even though the reference — and\n\t// therefore its response to a theme change — does not.\n\tconst fill = background.resolvedFill\n\tconst ir = fill ? fillIr(fill, notes, assets, tier) : undefined\n\tif (fill && ir) {\n\t\tnotes.note(\n\t\t\ttier.construct,\n\t\t\t'flattened',\n\t\t\t'unwritable',\n\t\t\t`${tier.subject} is a theme reference (p:bgRef into the theme's background fill list), which has no write-API option; the ${fill.type === 'solid' ? 'colour' : fill.type} it currently resolves to is baked in and stops following the theme`\n\t\t)\n\t\treturn ir\n\t}\n\tnotes.note(\n\t\ttier.construct,\n\t\t'dropped',\n\t\t'unwritable',\n\t\t`${tier.subject} is a theme reference whose fill does not resolve to one the write API can express, and a reference itself has no write-API option; ${tier.fallback}`\n\t)\n\treturn undefined\n}\n\n/** An explicit background fill, or `undefined` for none or for one with nothing to carry. */\nfunction fillIr(\n\tfill: BackgroundFill,\n\tnotes: NoteScope,\n\tassets: AssetResolver,\n\ttier: BackgroundTier\n): BackgroundIr | undefined {\n\tswitch (fill.type) {\n\t\tcase 'none':\n\t\t\treturn undefined\n\t\tcase 'solid':\n\t\t\treturn solidIr(fill.colorRef, notes, tier)\n\t\tcase 'image': {\n\t\t\tconst asset = fill.partName === null ? null : assets.assetFor(fill.partName)\n\t\t\treturn asset ? { data: asset } : undefined\n\t\t}\n\t\tcase 'gradient': {\n\t\t\tconst gradient = gradientStops(fill.gradient, notes, tier.construct)\n\t\t\treturn gradient ? { type: 'gradient', gradient } : undefined\n\t\t}\n\t\tcase 'pattern': {\n\t\t\tconst pattern = patternOption(fill, notes, tier.construct)\n\t\t\treturn pattern ? (pattern as BackgroundIr) : undefined\n\t\t}\n\t}\n}\n\n/**\n * A solid colour, with the transparency its `a:alpha` states.\n *\n * Through the shared colour ladder, not the resolved hex alone. This read the resolved colour\n * and only the resolved colour, so a background painted with a theme token came out as the\n * literal that token happened to resolve to and stopped following the theme -- silently, where\n * every other surface that bakes a token says so. A writable token is kept as a token; an\n * unwritable one is baked and noted, under this tier's own `…schemeToken` construct.\n */\nfunction solidIr(colorRef: ColorRef, notes: NoteScope, tier: BackgroundTier): BackgroundIr | undefined {\n\tconst resolved: ResolvedColor | null = colorRef.resolved\n\tconst color = colorOption(\n\t\t{ scheme: colorRef.scheme, ownHex: colorRef.srgb, resolvedHex: resolved?.effectiveHex ?? null },\n\t\tnotes,\n\t\t`${tier.construct}.schemeToken`,\n\t\t'background'\n\t)\n\tif (color === undefined) return undefined\n\tconst transparency = alphaToTransparency(resolved?.alpha)\n\treturn transparency === undefined ? { color } : { color, transparency }\n}\n","/**\n * Fidelity notes — the declared, machine-checkable list of what a deck loses on the way\n * to a script.\n *\n * A converter that warns about losses to a log has no way to be tested: the warnings are\n * prose, nothing consumes them, and a missing one looks exactly like a clean run. Making\n * the notes part of the IR inverts that. A note says \"field X of shape Y will not come\n * back\", so a round-trip check can exclude precisely those fields and treat **any**\n * remaining difference as a defect. Both directions then have teeth:\n *\n * - an *undeclared* loss fails the round-trip, because nothing excluded it;\n * - a *declared* loss that actually survives is a stale note, and the check can say so.\n *\n * That is the whole reason notes are first-class rather than a side channel. It also\n * means {@link FidelityNote.construct} is an identifier, not a sentence: it has to be\n * matchable against a field path, so it is a stable dotted key and the human explanation\n * lives in {@link FidelityNote.detail}.\n */\n\n/** The two printers a note can apply to: template-anchored (`printScript`) and standalone (`printStandaloneScript`). */\nexport type PrintTier = 'template' | 'standalone'\n\n/** One catalogue entry: the option paths a note excuses, and the printers whose output it describes. */\nexport interface NoteConstructEntry {\n\t/** Option paths the note is a promise about; see {@link NOTE_CONSTRUCTS}. */\n\treadonly fields: readonly string[]\n\t/** The printers that report the note. */\n\treadonly tiers: readonly PrintTier[]\n}\n\n/** A loss both printers have. */\nconst BOTH_TIERS = ['template', 'standalone'] as const\n\n/**\n * A loss only the standalone printer has, because the template-anchored one keeps the construct in\n * its template.\n *\n * Document properties are the plain case: the read half notes the ones with no write-API setter,\n * which matters for a script that rebuilds the deck, but the template-anchored tier never authors\n * them. They ride in the template, every one. The chrome is the same story on\n * a larger scale: the theme's format scheme, the master's text styles and colour map, the layouts'\n * decoration, names and placeholder definitions are genuine losses for a script that rebuilds the\n * design, and untouched by one whose template *is* the design. A caveat that does not apply to the\n * output in front of you is worse than none: it teaches the reader to skim the ones that do.\n */\nconst STANDALONE_ONLY = ['standalone'] as const\n\n/**\n * A loss only the template-anchored printer has. `slide.carried` says a slide is copied from the\n * source package rather than transcribed. The standalone tier has no source package, so it\n * transcribes the slide, and the construct that made it uncarryable records its own note; reporting\n * both would count one loss twice and describe a behaviour that script does not have.\n */\nconst TEMPLATE_ONLY = ['template'] as const\n\n/**\n * Option names each note construct is a promise about.\n *\n * This table is the fidelity catalogue made mechanical. A note claims a construct will not\n * survive; without a mapping from that claim to the fields it covers, the claim cannot\n * exclude anything and the round trip degenerates into a snapshot.\n *\n * Each entry is a dotted option PATH, matched one of two ways depending on the note that names it:\n *\n * - **A note scoped to a shape** is already confined to that shape's call, so its entries are\n * matched as a SUFFIX of where the difference sits inside it: a bare `fill` means \"the fill\n * option wherever it appears in the call\", and `line.width` means that width and not a table\n * cell border's. Write the bare form where the word is unambiguous and qualify it the moment\n * the same word names two different things. Matching the terminal key alone is how `type`,\n * written about a fill's solid default, came to excuse a character bullet that returned as a\n * numbered list, and how a bare `color` in a run-colour note excused the shape's fill and\n * outline colours, and in a cell note every colour in the table.\n * - **A note with no shape** (a slide or deck loss) has nothing confining it to one call, so its\n * entries are anchored at the root of the diff. Each names one node by its full path\n * (`background`, `chrome.masters.title`) and covers that node only, and a trailing `.*` extends\n * it to everything beneath (`transition.sound.*`). As suffixes they matched inside every call in\n * scope, and a deck's `master.background` excused every run colour and every lost image in the\n * deck.\n *\n * `'*'` covers every difference inside the note's scope — correct only where the note says the\n * whole shape or slide is gone or was copied wholesale, never as a shortcut for a construct\n * whose fields are merely tedious to enumerate.\n *\n * An empty list is meaningful and common: the construct is invisible to the IR on both\n * sides (a slide's build animations, a paragraph's `a:pPr/@marL`, a connector's shape\n * binding), so the note is a caveat for a human and there is nothing here to exclude. Saying\n * so explicitly is what keeps it from looking like an oversight. A construct can leave that\n * state — `slide.transition` was an empty entry until the converter learned to transcribe\n * transitions, and the IR gaining a field is exactly when its note gains a mapping.\n *\n * Each entry also names the printers whose output the note describes (`tiers`), and each printer\n * reports only the notes that apply to it. Two hand-kept sets used to decide that, one per printer,\n * so a new chrome construct was reported by the template-anchored tier unless someone remembered\n * to list it. An entry without `tiers` no longer satisfies the catalogue's type.\n */\nexport const NOTE_CONSTRUCTS = {\n\t'chart.blanks': { fields: ['values'], tiers: BOTH_TIERS },\n\t'chart.combo': { fields: ['type'], tiers: BOTH_TIERS },\n\t// A chart with no cached plottable series is not emitted at all, so the whole frame is\n\t// missing from the output. Distinct from `chart.workbook`, which is about a chart that IS\n\t// emitted, rebuilt from the cache.\n\t'chart.data': { fields: ['*'], tiers: BOTH_TIERS },\n\t// Label flags the writer has no spelling for: the legend key on any plot, the category name on any\n\t// but a pie or a doughnut. Absent from the IR on both sides, so there is nothing to exclude.\n\t'chart.labels': { fields: [], tiers: BOTH_TIERS },\n\t'chart.type': { fields: ['type'], tiers: BOTH_TIERS },\n\t// A 3-D line, area or pie rebuilt flat: `type` names the flat chart on both sides, and the 3-D\n\t// view is in neither IR.\n\t'chart.type3D': { fields: [], tiers: BOTH_TIERS },\n\t// Scatter or bubble series with X values of their own, rebuilt against the first series' X row.\n\t// The IR carries only that row on both sides, so the per-series X values are in neither.\n\t'chart.xValues': { fields: [], tiers: BOTH_TIERS },\n\t// Scatter or bubble series plotted against text X labels, rebuilt against the 1..n positions\n\t// PowerPoint plots them at. Both IRs carry those positions, and the labels are in neither.\n\t'chart.xLabels': { fields: [], tiers: BOTH_TIERS },\n\t'chart.workbook': { fields: ['*'], tiers: BOTH_TIERS },\n\t'chartEx.all': { fields: ['*'], tiers: BOTH_TIERS },\n\t'connector.binding': { fields: [], tiers: BOTH_TIERS },\n\t'connector.line': { fields: ['color', 'width', 'dashType', 'beginArrowType', 'endArrowType'], tiers: BOTH_TIERS },\n\t'connector.rotation': { fields: ['rotate'], tiers: BOTH_TIERS },\n\t// Empty, and the temptation to list title/author/subject/revision here has to be\n\t// resisted: this note is about the *other* seven docProps, which have no setter and are\n\t// absent from the IR. Listing the four that do have setters would excuse a printer that\n\t// stopped writing them — measured, by exactly that mutation.\n\t'deck.docProps': { fields: [], tiers: STANDALONE_ONLY },\n\t// Nothing to exclude: the differences it predicts are `added`, which WRITER_DEFAULTS covers\n\t// by kind. The note exists so a reader of the emitted script learns the deck gained them.\n\t'deck.docPropsDefault': { fields: [], tiers: STANDALONE_ONLY },\n\t'deck.slideSize': { fields: ['slideSize.*'], tiers: BOTH_TIERS },\n\t'diagram.all': { fields: ['*'], tiers: BOTH_TIERS },\n\t// A gradient that cannot be expressed falls back to no gradient, so the difference lands on\n\t// the fill option itself. The `line.` twins below are the same construct on a stroke —\n\t// `gradientStops` is shared by both surfaces and scopes its notes by which one it is on.\n\t'fill.gradient': { fields: ['gradient', 'fill'], tiers: BOTH_TIERS },\n\t'fill.gradient.path': { fields: ['gradient', 'fill'], tiers: BOTH_TIERS },\n\t'line.gradient': { fields: ['gradient', 'line'], tiers: BOTH_TIERS },\n\t'line.gradient.path': { fields: ['gradient', 'line'], tiers: BOTH_TIERS },\n\t'line.gradient.schemeToken': { fields: ['gradient', 'line'], tiers: BOTH_TIERS },\n\t// Recorded only when an image-filled surface cannot carry its *bytes* — a linked blip, an\n\t// SVG the write path refuses, a part missing from the package. The fill option is then\n\t// absent from the output entirely, so the difference lands on `fill` itself.\n\t'fill.picture': { fields: ['fill'], tiers: BOTH_TIERS },\n\t// Empty, and deliberately so: this note declares that a picture fill's tiling, crop, DPI\n\t// and rotWithShape do not survive, and *none of them is in the IR on either side* — the\n\t// write API expresses a picture fill as bytes plus transparency, so the converter never\n\t// emits them. Widening this to `fill` would be the mistake it looks like a fix for: it\n\t// would excuse an image fill that failed to come back at all, which is the thing the\n\t// round trip is here to catch.\n\t'fill.picture.geometry': { fields: [], tiers: BOTH_TIERS },\n\t'fill.gradient.schemeToken': { fields: ['gradient', 'fill'], tiers: BOTH_TIERS },\n\t// A hatch colour outside the tokens the write path maps, baked to a literal. The table twins\n\t// below are scoped to their own option, like the gradient-stop ones.\n\t'fill.pattern.schemeToken': { fields: ['fill.pattern.fgColor', 'fill.pattern.bgColor'], tiers: BOTH_TIERS },\n\t'fill.schemeToken': { fields: ['fill', 'fill.color'], tiers: BOTH_TIERS },\n\t// The outline's twin on a glow, and `shadow.schemeToken` below on a shadow: a colour outside the\n\t// ten tokens, baked to a literal.\n\t'glow.schemeToken': { fields: ['glow.color'], tiers: BOTH_TIERS },\n\t'graphicFrame.unknown': { fields: ['*'], tiers: BOTH_TIERS },\n\t'group.child': { fields: ['*'], tiers: BOTH_TIERS },\n\t'group.childSpace': { fields: ['x', 'y', 'w', 'h', 'rotate', 'flipH', 'flipV'], tiers: BOTH_TIERS },\n\t'group.empty': { fields: ['*'], tiers: BOTH_TIERS },\n\t'group.transform': { fields: ['rotate', 'flipH', 'flipV'], tiers: BOTH_TIERS },\n\t// A picture crop with no `crop` spelling is left off, so the difference lands on the option.\n\t'image.crop': { fields: ['crop'], tiers: BOTH_TIERS },\n\t'image.data': { fields: ['data', '$asset'], tiers: BOTH_TIERS },\n\t'image.recolor': { fields: ['duotone', 'grayscale', 'biLevel', 'clrChange'], tiers: BOTH_TIERS },\n\t// Covers the picture's bytes, not just an `svg` option: an SVG picture's raster fallback\n\t// is regenerated rather than carried, so the blip the round trip compares is a different\n\t// image from the source's — which is precisely the loss this note is about.\n\t'image.svg': { fields: ['svg', 'data', '$asset'], tiers: BOTH_TIERS },\n\t'line.arrowSize': { fields: ['beginArrowType', 'endArrowType'], tiers: BOTH_TIERS },\n\t// The chrome notes. Most are empty for the reason stated above and it is the common case\n\t// here rather than the exception: `a:fmtScheme`, `p:txStyles`, a *master's* decoration and a\n\t// layout's placeholder definitions are all absent from the IR on *both* sides — the first two\n\t// because nothing reads them, the other two because nothing writes them — so there is nothing\n\t// for a note to exclude and the note exists for a human. A *layout's* decoration is the one\n\t// that left this state: it is now in the IR as `objects` and is genuinely compared, which is\n\t// what makes the `layout.` entries below worth stating separately.\n\t// `p:clrMap` is the subtle one: a remapped token changes what every scheme colour in the\n\t// deck resolves to, and the round trip still cannot see it, because the IR reports the token\n\t// verbatim rather than its resolved hex. That is exactly the blind spot this file's header\n\t// describes, and writing `[]` is the honest spelling of it.\n\t// Deck-scoped, so anchored at the root: a layout's background and title sit under\n\t// `chrome.masters`, and a renamed layout also reaches every slide bound to it as `layoutName`.\n\t'master.background': { fields: ['chrome.masters.background.*'], tiers: STANDALONE_ONLY },\n\t// A background's gradient and pattern take the shape fill's notes, under the tier's construct.\n\t'master.background.gradient': { fields: ['chrome.masters.background.*'], tiers: STANDALONE_ONLY },\n\t'master.background.gradient.path': { fields: ['chrome.masters.background.*'], tiers: STANDALONE_ONLY },\n\t'master.background.gradient.schemeToken': { fields: ['chrome.masters.background.*'], tiers: STANDALONE_ONLY },\n\t'master.background.pattern.schemeToken': { fields: ['chrome.masters.background.*'], tiers: STANDALONE_ONLY },\n\t'master.background.schemeToken': { fields: ['chrome.masters.background.*'], tiers: STANDALONE_ONLY },\n\t'master.colorMap': { fields: [], tiers: STANDALONE_ONLY },\n\t'master.decoration': { fields: [], tiers: STANDALONE_ONLY },\n\t// Scoped to the `DEFAULT` layout's title, so a suffix: the whole added layout.\n\t'master.default': { fields: ['master'], tiers: STANDALONE_ONLY },\n\t'master.multiple': { fields: [], tiers: STANDALONE_ONLY },\n\t// Both are about a layout *title* the standalone tier has to invent: deduplicated because it doubles\n\t// as a lookup key, whitespace-collapsed because the write path emits it as a raw XML attribute\n\t// value. The template-anchored tier keeps the layout's own `p:cSld@name`.\n\t'master.name': { fields: ['chrome.masters.title', 'layoutName'], tiers: STANDALONE_ONLY },\n\t'master.nameCollision': { fields: ['chrome.masters.title', 'layoutName'], tiers: STANDALONE_ONLY },\n\t'master.placeholders': { fields: [], tiers: STANDALONE_ONLY },\n\t'master.txStyles': { fields: [], tiers: STANDALONE_ONLY },\n\t'theme.fmtScheme': { fields: [], tiers: STANDALONE_ONLY },\n\t// The two layout-shape notes with no slide counterpart to inherit a mapping from. Both are\n\t// empty for the same reason, and it is worth spelling out because both *look* like they\n\t// should exclude something. A table on a layout is absent from the `objects` array on both\n\t// sides — the source's because this converter skips it, the output's because it was never\n\t// written — so there is no difference to excuse. A flattened group is stronger still: the\n\t// source layout's group becomes N loose objects here and the output layout genuinely *has*\n\t// N loose objects, so the two agree exactly and the note is a caveat for a human reading the\n\t// emitted script, not an exclusion.\n\t'layout.decoration': { fields: [], tiers: STANDALONE_ONLY },\n\t'layout.group': { fields: [], tiers: STANDALONE_ONLY },\n\t// `a:ln/@algn=\"in\"` has no write option, so the stroke comes back centred on the edge. The\n\t// IR carries no alignment on either side, so there is nothing to exclude and the note is a\n\t// caveat for a human reading the emitted script.\n\t'line.align': { fields: [], tiers: BOTH_TIERS },\n\t// Path-qualified: the entries are matched as a suffix of the difference's own path, and a\n\t// bare `width` also excused a table cell's bevel or border width.\n\t'line.dash': { fields: ['line.dashType'], tiers: BOTH_TIERS },\n\t// An outline colour outside the ten scheme tokens the write path maps, baked to a literal.\n\t'line.schemeToken': { fields: ['line.color'], tiers: BOTH_TIERS },\n\t'line.width': { fields: ['line.width'], tiers: BOTH_TIERS },\n\t'media.audioVideo': { fields: ['*'], tiers: BOTH_TIERS },\n\t'notes.formatting': { fields: ['notesText'], tiers: BOTH_TIERS },\n\t'shadow.schemeToken': { fields: ['shadow.color'], tiers: BOTH_TIERS },\n\t'shape.custGeom.guides': { fields: ['points'], tiers: BOTH_TIERS },\n\t'shape.effects': { fields: ['shadow', 'glow'], tiers: BOTH_TIERS },\n\t'shape.empty': { fields: ['*'], tiers: BOTH_TIERS },\n\t'shape.frameInherited': { fields: ['x', 'y', 'w', 'h'], tiers: BOTH_TIERS },\n\t// A shape nothing places is dropped whole, so every difference on it is the loss.\n\t'shape.frameUnresolved': { fields: ['*'], tiers: BOTH_TIERS },\n\t'shape.hidden': { fields: ['*'], tiers: BOTH_TIERS },\n\t// A shape link the shape-level `hyperlink` cannot spell is left off, so the difference lands there.\n\t'shape.hyperlink': { fields: ['hyperlink'], tiers: BOTH_TIERS },\n\t'shape.placeholder': { fields: ['placeholder'], tiers: BOTH_TIERS },\n\t'slide.animation': { fields: [], tiers: BOTH_TIERS },\n\t// Slide-scoped, so anchored at the root. The diff compares the slide's `background` as one\n\t// value, so the colour, transparency and picture bytes all land on that one path.\n\t'slide.background': { fields: ['background'], tiers: BOTH_TIERS },\n\t'slide.background.gradient': { fields: ['background'], tiers: BOTH_TIERS },\n\t'slide.background.gradient.path': { fields: ['background'], tiers: BOTH_TIERS },\n\t'slide.background.gradient.schemeToken': { fields: ['background'], tiers: BOTH_TIERS },\n\t'slide.background.pattern.schemeToken': { fields: ['background'], tiers: BOTH_TIERS },\n\t// A solid background's own scheme token, the twin of `fill.schemeToken` on a shape.\n\t'slide.background.schemeToken': { fields: ['background'], tiers: BOTH_TIERS },\n\t'slide.carried': { fields: ['*'], tiers: TEMPLATE_ONLY },\n\t'slide.layout': { fields: ['layoutName'], tiers: BOTH_TIERS },\n\t'slide.name': { fields: [], tiers: BOTH_TIERS },\n\t// A transition the write vocabulary cannot name is dropped whole, so the difference lands\n\t// on the slide's `transition` key itself. Deliberately *not* widened to the keys inside it:\n\t// this note is only ever recorded when the whole transition is gone.\n\t'slide.transition': { fields: ['transition'], tiers: BOTH_TIERS },\n\t// The sound alone, one level down. Scoped to `transition.sound` so it cannot also excuse a\n\t// transition whose type or timing came back wrong — the loss it declares is exactly the missing\n\t// `p:sndAc`, and the `.*` also covers the case where the sound survives with other bytes.\n\t'slide.transitionSound': { fields: ['transition.sound.*'], tiers: BOTH_TIERS },\n\t// A dash outside `ST_PresetLineDashVal` cannot be written back, so the edge comes out as\n\t// a plain dashed rule. Scoped to `border`, which is where that difference lands.\n\t'table.cell.borders.dash': { fields: ['border', 'diagonal'], tiers: BOTH_TIERS },\n\t// `table.cell.fill` used to live here, for a cell whose own fill could not be told apart\n\t// from the one it inherited from the table style. `TableCell.hasOwnFill` tells them apart,\n\t// so the mapper emits the right one and records nothing — the note is gone rather than\n\t// unmapped. Its `.gradient` / `.picture` children below are separate constructs and stay.\n\t// Empty, and correctly so: `a:tc/@id` and `a:tcPr/a:headers` have no write option — the\n\t// IR has nowhere to put them on either side, so there is nothing to exclude. The note\n\t// exists so a reader of the emitted script learns the association was there and is gone.\n\t'table.cell.headers': { fields: [], tiers: BOTH_TIERS },\n\t// A field or an equation in a cell contributes no run, so its text is in neither IR. Not\n\t// `text.field`'s `*`, which on a cell's note would excuse the whole table.\n\t'table.cell.field': { fields: [], tiers: BOTH_TIERS },\n\t'table.cell.equation': { fields: [], tiers: BOTH_TIERS },\n\t// The cell-side twins of `fill.picture` / `fill.picture.geometry`, and mapped for the\n\t// same reasons.\n\t'table.cell.fill.picture': { fields: ['fill'], tiers: BOTH_TIERS },\n\t'table.cell.fill.picture.geometry': { fields: [], tiers: BOTH_TIERS },\n\t// The table-side twins of `fill.schemeToken` / `text.color.schemeToken`: one of the seven\n\t// `ST_SchemeColorVal` tokens the write path's `clrMap` does not carry, baked to the literal\n\t// it resolves to. Three sites used to pass one through RAW, so the generated script warned\n\t// `color/invalid-value` and painted the default text colour instead.\n\t'table.cell.fill.schemeToken': { fields: ['fill', 'fill.color'], tiers: BOTH_TIERS },\n\t'table.cell.borders.schemeToken': { fields: ['border', 'diagonal'], tiers: BOTH_TIERS },\n\t// The table-background twins. Scoped to `tableFill` rather than `fill`, because those are\n\t// two different options: one lands on `a:tblPr`, the other is stamped onto every cell.\n\t'table.fill.schemeToken': { fields: ['tableFill', 'tableFill.color'], tiers: BOTH_TIERS },\n\t'table.fill.picture': { fields: ['tableFill'], tiers: BOTH_TIERS },\n\t'table.fill.picture.geometry': { fields: [], tiers: BOTH_TIERS },\n\t// A gradient that cannot be expressed falls back to no gradient, so the difference lands\n\t// on the fill option itself — `tableFill` for the background, `fill` for a cell.\n\t'table.fill.gradient': { fields: ['tableFill'], tiers: BOTH_TIERS },\n\t'table.fill.gradient.path': { fields: ['tableFill'], tiers: BOTH_TIERS },\n\t// A gradient STOP whose scheme token the write path cannot carry, baked to a literal. Scoped\n\t// to the surface the stop sits on, like the two above it: the stop note used to hardcode the\n\t// shape spelling, so a table gradient recorded `fill.gradient.schemeToken` while its\n\t// difference landed on `tableFill` and the note could never match it.\n\t'table.fill.gradient.schemeToken': { fields: ['tableFill'], tiers: BOTH_TIERS },\n\t'table.fill.pattern.schemeToken': {\n\t\tfields: ['tableFill.pattern.fgColor', 'tableFill.pattern.bgColor'],\n\t\ttiers: BOTH_TIERS,\n\t},\n\t'table.cell.fill.gradient': { fields: ['fill'], tiers: BOTH_TIERS },\n\t'table.cell.fill.gradient.path': { fields: ['fill'], tiers: BOTH_TIERS },\n\t'table.cell.fill.gradient.schemeToken': { fields: ['fill'], tiers: BOTH_TIERS },\n\t'table.cell.fill.pattern.schemeToken': {\n\t\tfields: ['fill.pattern.fgColor', 'fill.pattern.bgColor'],\n\t\ttiers: BOTH_TIERS,\n\t},\n\t// Narrowed to the East-Asian `ST_TextVerticalType` modes `textDirection` cannot spell —\n\t// the four it can now round-trip, so this no longer excuses every vertical cell.\n\t'table.cell.vert': { fields: ['textDirection', 'vert'], tiers: BOTH_TIERS },\n\t'table.rowAuto': { fields: ['rowH'], tiers: BOTH_TIERS },\n\t'table.style': { fields: ['tableStyle'], tiers: BOTH_TIERS },\n\t'text.align': { fields: ['align'], tiers: BOTH_TIERS },\n\t// `text.bullet.numberStartAt` and `text.bullet.style` used to live here, for\n\t// `a:buAutoNum/@startAt` and for a bullet's own font/size/colour. `Paragraph.bulletDetail`\n\t// reads all four, so the mapper emits `numberStartAt` / `fontFace` / `size` / `color` and\n\t// records nothing — the notes are gone rather than unmapped. What remains of the size half\n\t// is `text.bullet.sizePt`, which is a genuinely unwritable unit rather than an unread value.\n\t'text.bullet.numberType': { fields: ['bullet'], tiers: BOTH_TIERS },\n\t// An absolute bullet size (`a:buSzPts`) has no write option at all — `bullet.size` is a\n\t// percentage of the run size — so the difference lands on the bullet option.\n\t'text.bullet.sizePt': { fields: ['bullet'], tiers: BOTH_TIERS },\n\t// A percentage outside 25–400%, which the write path rejects with a warning and replaces\n\t// with the run's own size.\n\t'text.bullet.sizePct': { fields: ['bullet'], tiers: BOTH_TIERS },\n\t// A bullet colour outside the ten scheme tokens the write path maps, baked to a literal.\n\t'text.bullet.schemeToken': { fields: ['bullet'], tiers: BOTH_TIERS },\n\t// A picture bullet (`a:buBlip`): readable, and `bullet.image` could author it, but the\n\t// paragraph mapper carries no asset resolver to re-embed the bytes with.\n\t'text.bullet.picture': { fields: ['bullet'], tiers: BOTH_TIERS },\n\t// A run's colour, wherever the run sits: a shape, a group child or a table cell.\n\t'text.color.default': { fields: ['options.color'], tiers: BOTH_TIERS },\n\t'text.color.inherited': { fields: ['options.color'], tiers: BOTH_TIERS },\n\t'text.color.schemeToken': { fields: ['options.color'], tiers: BOTH_TIERS },\n\t'text.equation': { fields: ['*'], tiers: BOTH_TIERS },\n\t'text.field': { fields: ['*'], tiers: BOTH_TIERS },\n\t// A run link the run-level `hyperlink` cannot spell is left off, so the difference lands there.\n\t'text.hyperlink': { fields: ['hyperlink'], tiers: BOTH_TIERS },\n\t// A link that states no underline comes back stating `u=\"sng\"`, the write path's default for a link.\n\t'text.hyperlink.underline': { fields: ['options.underline'], tiers: BOTH_TIERS },\n\t'text.bullet.glyph': { fields: ['bullet'], tiers: BOTH_TIERS },\n\t// `text.bullet.inherited` used to live here — a paragraph stating no bullet of its own was\n\t// re-emitted with an explicit `a:buNone`, because omitting the write API's `bullet` is that\n\t// element rather than silence. `bullet: 'inherit'` says silence now, so the mapper carries\n\t// the state instead of excusing its loss and the note is gone rather than unmapped.\n\t//\n\t// `text.indent` used to live here, empty, because a paragraph's `a:pPr/@marL` and `@indent`\n\t// were in neither IR — the write API had no option for them, so the mapper never emitted one\n\t// and the diff compared two models both missing the field. `paraMarginLeft` / `paraIndent`\n\t// put it in both, which is what turns an empty entry into a comparison rather than a caveat,\n\t// so the note is gone rather than unmapped.\n\t// A baked `a:normAutofit` percentage outside 0-100, which the write API rejects: the frame\n\t// re-emits a bare `<a:normAutofit/>`, so the difference lands on the `fit` option.\n\t'text.autofit.fontScale': { fields: ['fit'], tiers: BOTH_TIERS },\n\t'text.autofit.lnSpcReduction': { fields: ['fit'], tiers: BOTH_TIERS },\n\t'text.paraSpaceZero': { fields: ['paraSpaceBefore', 'paraSpaceAfter'], tiers: BOTH_TIERS },\n\t'text.vert': { fields: ['vert'], tiers: BOTH_TIERS },\n} as const satisfies Record<string, NoteConstructEntry>\n\n/**\n * Every construct a note may name.\n *\n * Derived from the table above rather than declared beside it, so a construct coined at a call\n * site and never mapped is a COMPILE error instead of a note that silently declares nothing --\n * which is what it was: seven constructs were emitted with no entry at all, and `declaringNote`\n * walked straight past each of them, so the difference the note predicted came back as a defect.\n */\nexport type NoteConstruct = keyof typeof NOTE_CONSTRUCTS\n\n/** A construct with {@link LAYOUT_NOTE_PREFIX} stripped, for the ones declared only under it. */\ntype StripLayoutPrefix<T> = T extends `layout.${infer Rest}` ? Rest : never\n\n/**\n * What a call site may name: the catalogue, plus the `layout.`-prefixed constructs spelled\n * relative to the prefix, which is how the layout walk records them.\n *\n * One union rather than two scope types, because a TypeScript method parameter is bivariant —\n * a narrower `LayoutNoteScope` would have been assignable to `NoteScope` in both directions and\n * enforced nothing. The cost is that a slide mapper could name a layout-relative construct; the\n * thing worth catching is a construct with no entry AT ALL, which this does catch.\n */\nexport type RecordableConstruct = NoteConstruct | StripLayoutPrefix<NoteConstruct>\n\n/** What happened to the construct. */\nexport type Disposition =\n\t/** Gone: nothing in the output carries it. */\n\t| 'dropped'\n\t/**\n\t * Present but structurally simplified — a value survives while the structure around\n\t * it does not (threaded comment replies flattened into separate comments, a per-script\n\t * font scheme reduced to latin, a placeholder demoted to a plain shape).\n\t */\n\t| 'flattened'\n\t/**\n\t * Present and structurally intact, but not the same value — a re-encoding that a\n\t * viewer may or may not be able to tell apart (a modern transition mapped to the\n\t * nearest named one, a chart rebuilt from cached points rather than its workbook).\n\t */\n\t| 'approximated'\n\n/**\n * Which side of the library is responsible. Recording this is what makes the notes\n * actionable rather than merely honest: `unread` and `unwritable` are bugs waiting to be\n * fixed in a specific subsystem, while `unsupported` is a property of OOXML or of the\n * chosen output tier and will not be fixed by more converter work.\n */\nexport type Cause =\n\t/** The read API exposes no accessor for it, so the converter never saw it. */\n\t| 'unread'\n\t/** Read fine, but the write API has no option that expresses it. */\n\t| 'unwritable'\n\t/** Both sides can handle it; this output tier structurally cannot carry it. */\n\t| 'unsupported'\n\n/** One declared loss. */\nexport interface FidelityNote {\n\t/** 1-based source slide, or `null` for a deck-level loss. */\n\tslideNumber: number | null\n\t/**\n\t * Source shape name (`p:cNvPr/@name`), `''` for a shape that has none, or `null` when the loss is\n\t * not shape-scoped.\n\t */\n\tshapeName: string | null\n\t/**\n\t * Stable dotted identifier for the lost construct — `line.width`, `text.tabStops`,\n\t * `chart.workbook`. Matched mechanically by the round-trip check, so it must name a\n\t * field path rather than describe one. Reuse an existing key for the same construct\n\t * instead of coining a synonym.\n\t *\n\t * A `string` rather than `NoteConstruct` because a note carries the `layout.`-prefixed\n\t * spelling too; the recording end is the typed one.\n\t */\n\tconstruct: string\n\tdisposition: Disposition\n\tcause: Cause\n\t/** Why, in a sentence, for a human reading the emitted script's header. */\n\tdetail: string\n}\n\n/**\n * Accumulates notes while a deck is walked, so the walk itself stays a plain\n * read-model → IR mapping and does not thread a growing array through every function.\n *\n * Deduplicates on the full note identity. Without that, a construct that is lost on every\n * run of a 400-run text body would produce 400 identical notes and bury the one-off losses\n * that actually need reading.\n */\nexport class NoteCollector {\n\treadonly #seen = new Set<string>()\n\treadonly #notes: FidelityNote[] = []\n\n\t/** Record a loss. A repeat of an identical note is ignored. */\n\tadd(note: FidelityNote): void {\n\t\tconst key = `${note.slideNumber}\\0${note.shapeName}\\0${note.construct}\\0${note.disposition}\\0${note.cause}\\0${note.detail}`\n\t\tif (this.#seen.has(key)) return\n\t\tthis.#seen.add(key)\n\t\tthis.#notes.push(note)\n\t}\n\n\t/**\n\t * The notes, in the order first recorded — which is deck order, since the walk is\n\t * ordered, so a reader meets them the way they meet the slides.\n\t */\n\tget notes(): FidelityNote[] {\n\t\treturn this.#notes\n\t}\n}\n\n/**\n * Namespace for a loss recorded against a shape on a **slide layout** rather than on a slide,\n * prepended to the construct by `layoutShapeScope`.\n *\n * The chrome mapper reuses the slide shape mapper wholesale — a rectangle on a layout is\n * transcribed by the same code that transcribes one on a slide, which is what keeps the two\n * from drifting. That sharing brings the slide vocabulary with it: a themed outline on a\n * layout records `line.width` exactly as a slide's would. Left unmarked, those notes would be\n * wrong twice over. A template-anchored script would report them, though it never rebuilds a\n * layout and loses nothing; and the round trip would let one excuse a *slide* difference,\n * because a layout note carries no slide number and a name like \"Rectangle 7\" repeats between\n * the tiers. The prefix keeps the shared vocabulary and states which tier it is about.\n *\n * `layout.` rather than `master.`, which is how the other chrome constructs are spelled: those\n * are named after the `defineSlideMaster` call that authors them, while these name the source\n * tier the loss is on — and a master's own decoration is not re-authored at all, so a note\n * under this prefix is always about a layout.\n */\nexport const LAYOUT_NOTE_PREFIX = 'layout.'\n\n/**\n * `true` when a note describes the output of the printer for `tier`.\n *\n * A construct's catalogue entry decides. A `layout.`-prefixed construct with no entry of its own is\n * a slide construct borrowed for a loss in re-authoring a layout's decoration, so whatever its\n * slide twin says, it applies only to the standalone tier: the template-anchored one does not\n * rebuild layouts.\n */\nexport function noteAppliesTo(construct: string, tier: PrintTier): boolean {\n\tconst entry = (NOTE_CONSTRUCTS as Record<string, NoteConstructEntry | undefined>)[construct]\n\tif (entry) return entry.tiers.includes(tier)\n\tif (construct.startsWith(LAYOUT_NOTE_PREFIX)) return tier === 'standalone'\n\treturn true\n}\n\n/**\n * `a`, `a and b`, `a, b and c` — a note is a sentence a human reads, and a bare\n * `join(', ')` made a two-item one read as a list that had lost its last member.\n */\nexport function andList(items: readonly string[]): string {\n\tif (items.length < 2) return items.join('')\n\treturn `${items.slice(0, -1).join(', ')} and ${items[items.length - 1]}`\n}\n\n/** A graphic frame payload with no write-API emitter. */\nexport type UnwritableFramePayload = 'chartEx' | 'diagram' | 'unknown'\n\n/**\n * The note each {@link UnwritableFramePayload} records.\n *\n * Here rather than beside the shape mapper that records them, because the printer reads it too\n * and the printer does not reach into `from-read/`. `graphicFrameCall` picks its note from it. The\n * template-anchored printer keeps these on a slide it copies whole and drops every other note\n * recorded there: these say which construct forced the copy, and the rest describe a\n * transcription that tier never prints.\n */\nexport const UNWRITABLE_FRAME_CONSTRUCTS = {\n\tchartEx: 'chartEx.all',\n\tdiagram: 'diagram.all',\n\tunknown: 'graphicFrame.unknown',\n} as const satisfies Record<UnwritableFramePayload, NoteConstruct>\n\n/**\n * A {@link NoteCollector} bound to one slide and shape, so a mapping function can record\n * a loss without knowing where in the deck it sits. Obtained via {@link scopeNotes}.\n */\nexport interface NoteScope {\n\t/** Record a loss at this scope. */\n\tnote(construct: RecordableConstruct, disposition: Disposition, cause: Cause, detail: string): void\n\t/** Re-scope to a shape within the same slide. */\n\tforShape(shapeName: string | null): NoteScope\n}\n\n/** Bind a collector to a slide (and optionally a shape). */\nexport function scopeNotes(\n\tcollector: NoteCollector,\n\tslideNumber: number | null,\n\tshapeName: string | null = null\n): NoteScope {\n\treturn {\n\t\tnote(construct, disposition, cause, detail) {\n\t\t\tcollector.add({ slideNumber, shapeName, construct, disposition, cause, detail })\n\t\t},\n\t\tforShape(name) {\n\t\t\treturn scopeNotes(collector, slideNumber, name)\n\t\t},\n\t}\n}\n\n/**\n * Wrap a scope so every construct recorded through it is namespaced under\n * {@link LAYOUT_NOTE_PREFIX} — see there for why.\n *\n * Constructs written at a call site inside the layout walk are therefore *relative*: the\n * decoration mapper records `decoration`, and what lands in the note list is\n * `layout.decoration`. The wrapper survives `forShape`, since a layout loss is scoped to a\n * shape name the same way a slide loss is.\n */\nexport function layoutShapeScope(notes: NoteScope): NoteScope {\n\treturn {\n\t\tnote(construct, disposition, cause, detail) {\n\t\t\t// The prefixed spelling is a `NoteConstruct` for the constructs declared under it and a\n\t\t\t// borrowed slide one otherwise, which `noteFields` resolves by stripping the prefix.\n\t\t\tnotes.note(`${LAYOUT_NOTE_PREFIX}${construct}` as RecordableConstruct, disposition, cause, detail)\n\t\t},\n\t\tforShape(name) {\n\t\t\treturn layoutShapeScope(notes.forShape(name))\n\t\t},\n\t}\n}\n","/**\n * The deck IR — a serializable description of a deck as a sequence of write-API calls.\n *\n * This is the seam between reading a `.pptx` and printing TypeScript for it. Everything\n * upstream of the IR knows about OOXML and the read model; everything downstream knows\n * only about strings. Neither half can see the other, which is the point: the decision\n * \"this `a:ln` becomes `line: { width: 2 }`\" is made once, here, and is testable without\n * a printer, while \"how a number is spelled in source text\" is a printer concern that\n * cannot silently change what the deck means.\n *\n * Two rules keep that seam honest, and both are load-bearing:\n *\n * 1. **The IR is data, not objects.** No DOM nodes, no read-model instances, no\n * functions — `structuredClone` and `JSON.stringify` both round-trip it. A round-trip\n * test can therefore compare two IRs directly (see {@link FidelityNote}), and an IR\n * can be cached or shipped without dragging a whole `Presentation` along.\n * 2. **`args` are literal write-API option objects.** A {@link CallIr} is exactly what\n * the emitted source will pass, so the printer never invents, reshapes, or defaults a\n * value — it spells out what is already there. If the printer had to interpret, the\n * same construct could mean two things depending on which half you asked.\n *\n * Media is the one thing that cannot be a literal, since bytes are not source text. It\n * is referenced by {@link AssetRef} and carried out-of-band in {@link DeckIr.assets}, so\n * the IR itself stays serializable and the printer decides between a file path and an\n * inline base64 literal.\n */\nimport type { FidelityNote } from './fidelity.js'\nimport type { CoreProperties, ExtendedProperties } from '../read/api/document-properties.js'\n\n/**\n * A reference to bytes held in {@link DeckIr.assets}, standing where a write-API option\n * wants image/media data. Printed as a `path` or an inline `data:` literal depending on\n * the print options — an IR-level decision would bake one choice into the IR and force a\n * re-read to change it.\n *\n * The `$asset` sigil is deliberate: no write-API option object has a `$`-prefixed key,\n * so a value carrying one is unambiguously a reference rather than user data.\n */\nexport interface AssetRef {\n\t$asset: string\n}\n\n/** `true` when `value` is an {@link AssetRef} rather than a plain IR object. */\nexport function isAssetRef(value: unknown): value is AssetRef {\n\treturn typeof value === 'object' && value !== null && typeof (value as AssetRef).$asset === 'string'\n}\n\n/**\n * Any value an IR may hold. Deliberately narrower than `unknown`: it excludes `undefined`\n * so that \"absent\" has exactly one spelling (a missing key), which is what makes two IRs\n * comparable field-by-field in a round-trip diff. `readModelToIr` never writes an\n * `undefined` value.\n */\nexport type IrValue = null | boolean | number | string | AssetRef | IrValue[] | { [key: string]: IrValue }\n\n/**\n * Widen one of the typed IR records below to {@link IrValue}, for the printer and the\n * canonicaliser, which walk the IR generically.\n *\n * A cast, and unavoidably so. An optional key on an interface types as `T | undefined`,\n * while `IrValue` deliberately excludes `undefined` so that \"absent\" has exactly one\n * spelling — which makes the two mutually unassignable even though every value a mapper\n * actually produces satisfies both. The invariant that closes the gap is enforced at the\n * source (`compact` and the conditional spreads in `from-read/`, pinned by the \"no value is\n * `undefined`\" corpus test) rather than by the type system, so it is stated once here\n * instead of re-argued at each call site.\n */\nexport function asIrValue(value: object): IrValue {\n\treturn value as unknown as IrValue\n}\n\n/** Bytes referenced by an {@link AssetRef}, plus what a printer needs to name and type them. */\nexport interface AssetIr {\n\t/** Stable key an {@link AssetRef} resolves against; also the emitted filename. */\n\tname: string\n\t/** MIME type from the source package's content types, for an inline `data:` URI. */\n\tcontentType: string\n\tbytes: Uint8Array\n}\n\n/**\n * One write-API call on a slide, in the order it must be made. `method` names a real\n * method on the authored slide and `args` are its positional arguments — so a printer is\n * a formatter, and `readModelToIr` owns every semantic choice.\n *\n * Ordering is z-order: OOXML paints a slide's shape tree front-to-back in document order,\n * and so does the write path, so preserving call order preserves overlap.\n */\nexport interface CallIr {\n\tmethod: 'addText' | 'addShape' | 'addImage' | 'addTable' | 'addChart' | 'addConnector' | 'addGroup' | 'addNotes'\n\targs: IrValue[]\n\t/**\n\t * The source shape's name (`p:cNvPr/@name`), when it had one. Not an argument —\n\t * carried so a printer can comment the call and a fidelity note can point at it.\n\t */\n\tsourceName?: string\n}\n\n/**\n * How a slide's content gets into the output deck.\n *\n * `authored` — every shape is transcribed into {@link CallIr}s and regenerated through\n * the write API. This is the goal: the emitted source is editable, and a reader can see\n * what the deck contains.\n *\n * `carried` — the slide holds at least one construct the write API cannot express at all\n * (`chartEx` is the clear case: a full reader, no emitter), so transcribing it would\n * silently produce a different deck. A printer that *can* copy the slide from the source\n * package should do so: fidelity is higher than transcription, though the emitted source then\n * says nothing about what is on the slide, which is a real cost and always carries a\n * {@link FidelityNote}.\n *\n * This is a recommendation, not an erasure. {@link SlideIr.calls} is populated either way, so\n * a printer with no source package to copy from prints them and loses only the unwritable\n * construct rather than the whole slide.\n */\nexport type SlideSource = 'authored' | 'carried'\n\n/**\n * A slide's background, already reduced to what the write API's `background` accepts.\n *\n * `data` rather than `image`, because `BackgroundProps` is `DataOrPathProps & ShapeFillProps`\n * and `data` is the key it actually reads — an `image` key would print, typecheck against\n * `IrValue`, and be ignored at run time.\n *\n * `type`, `gradient` and `pattern` are the `ShapeFillProps` keys a non-solid background is\n * spelled with, the same values a shape's `fill` carries for the same elements.\n */\nexport interface BackgroundIr {\n\ttype?: 'gradient' | 'pattern'\n\tcolor?: string\n\ttransparency?: number\n\tgradient?: IrValue\n\tpattern?: IrValue\n\tdata?: AssetRef\n}\n\n/**\n * A transition's sound (`p:sndAc`), reduced to what `TransitionSoundProps` accepts.\n *\n * `data` rather than `path`, for the same reason a background image uses `data`: the bytes\n * are the thing the IR carries, and a path would bind the script to a file layout the IR\n * knows nothing about. The stop-previous form has no bytes at all — it silences a sound\n * still playing from the previous slide — so it is the one shape here with no {@link AssetRef}.\n */\nexport interface TransitionSoundIr {\n\t/** Bytes of the embedded WAV, for a start sound. Absent for {@link stopPrevious}. */\n\tdata?: AssetRef\n\t/** `p:snd@name`, the display name PowerPoint shows for the sound. */\n\tname?: string\n\t/** `p:stSnd@loop` — repeat until the next sound starts. Omitted when false, its default. */\n\tloop?: boolean\n\t/** The `p:endSnd` form: stop the previous slide's sound rather than start one. */\n\tstopPrevious?: boolean\n}\n\n/**\n * A slide's show transition (`p:transition`), as a literal `TransitionProps`.\n *\n * Only the base ECMA-376 transitions reach this type. The read model reports\n * `TransitionInfo.type` as an *open string*, because PowerPoint's modern effects\n * (Morph, Vortex, …) live in the `p14`/`p15`/`p159` namespaces and it decodes those too —\n * but the write path names 21 base ones and nothing else, so `from-read/transition.ts`\n * filters against that vocabulary and notes what it drops. Anything that survives is a name\n * the write API's own `TransitionType` union accepts, which is what keeps a printed script\n * compiling.\n */\nexport interface TransitionIr {\n\t/** The transition-type element's local name, guaranteed to be a writable one. */\n\ttype: string\n\t/** `p:transition@spd`. Always present — see `from-read/transition.ts` for why it is not omitted. */\n\tspeed: 'slow' | 'med' | 'fast'\n\t/** `p14:dur` in milliseconds, when the source carried an exact duration. */\n\tdurationMs?: number\n\t/** `advClick`. Omitted when true, its default. */\n\tadvanceOnClick?: boolean\n\t/** `advTm` in milliseconds, when the slide auto-advances. */\n\tadvanceAfterMs?: number\n\t/** Type-specific attributes on the type element (`{ dir: 'd' }`, `{ spokes: '2' }`, …). */\n\tvariant?: { [key: string]: string }\n\tsound?: TransitionSoundIr\n}\n\n/**\n * The layout a slide should be bound to in the destination deck, identified two ways\n * because neither alone is sufficient.\n *\n * The **name** is the portable identity: it is what lets a script built from one deck be\n * re-pointed at a different template whose layouts happen to be named the same, and it is\n * what a reader recognises. But `p:cSld@name` is not unique — a deck with several masters\n * routinely carries several \"Title and Content\" layouts, and binding by an ambiguous name\n * is an error, not a coin flip. The **index** into the deck's layout gallery always\n * resolves, so it is the fallback, and {@link nameIsUnique} says which to trust.\n */\nexport interface SlideLayoutIr {\n\t/** `p:cSld@name` of the source layout (`''` when the layout is unnamed). */\n\tname: string\n\t/** Zero-based position in the source deck's layout gallery, in master-then-layout order. */\n\tindex: number\n\t/** `false` when another layout in that gallery shares {@link name}. */\n\tnameIsUnique: boolean\n}\n\n/** One slide of the deck. */\nexport interface SlideIr {\n\t/** 1-based index in the source deck; the identity a {@link FidelityNote} points at. */\n\tnumber: number\n\tsource: SlideSource\n\t/** The layout to bind to, or `null` when the source slide resolves none. */\n\tlayout: SlideLayoutIr | null\n\t/** `p:sld/@show=\"0\"` — a slide hidden from presentation but present in the deck. */\n\thidden: boolean\n\t/** `p:cSld/@name`, when the source slide had one. */\n\tname?: string\n\tbackground?: BackgroundIr\n\t/** Speaker notes as plain text. Notes-slide geometry and placeholders do not survive. */\n\tnotesText?: string\n\t/**\n\t * The show transition, when the source has one the write API can name. Slide-scoped\n\t * rather than a {@link CallIr} because the write API models it as a property assignment\n\t * on the slide, not a method — the IR's `method` union names real methods only.\n\t */\n\ttransition?: TransitionIr\n\t/**\n\t * Write-API calls in z-order.\n\t *\n\t * Populated for every slide, **including a `carried` one**. A printer that can copy the\n\t * source slide ignores these; one that cannot — a standalone output has no source package\n\t * to copy from — prints them and is left with only the unwritable construct missing rather\n\t * than the whole slide. Marking a slide `carried` is a recommendation, not an erasure.\n\t */\n\tcalls: CallIr[]\n}\n\n/**\n * A deck's theme, reduced to what `ThemeProps` accepts — the 12 `a:clrScheme` slots and the\n * major/minor Latin, East-Asian and complex-script faces.\n *\n * What is *not* here is the point of the tier split. `a:fmtScheme` — the three fill, three\n * line and three effect style lists a shape's `p:style` references — has no write-API\n * counterpart and no read accessor, so a theme cannot be reproduced, only approximated.\n */\nexport interface ThemeIr {\n\theadFontFace?: string\n\tbodyFontFace?: string\n\theadFontFaceEA?: string\n\tbodyFontFaceEA?: string\n\theadFontFaceCS?: string\n\tbodyFontFaceCS?: string\n\t/** The 12 `a:clrScheme` slots as bare 6-digit hex, omitting any the theme leaves unset. */\n\tcolorScheme?: { [slot: string]: string }\n}\n\n/**\n * One source slide layout approximated as a `defineSlideMaster` call.\n *\n * The naming is the write API's, not OOXML's: `defineSlideMaster` creates a *layout* under\n * the single shared master, which is exactly the granularity a source layout needs. A source\n * deck's masters have no counterpart at all — hence {@link ChromeIr}'s multi-master note.\n */\nexport interface MasterIr {\n\t/**\n\t * Gallery position of the source layout, matching {@link SlideLayoutIr.index}, so a slide\n\t * finds the master it should bind to without re-deriving a name.\n\t */\n\tlayoutIndex: number\n\t/**\n\t * A `SlideMasterProps` literal. `props.title` is made unique across the deck, because it\n\t * doubles as the key `addSlide({ masterTitle })` matches against and source layout names\n\t * are not unique.\n\t */\n\tprops: { [key: string]: IrValue }\n}\n\n/**\n * `base`, or `base (2)`, `base (3)`, … — the first spelling `used` does not already hold.\n *\n * The rule {@link MasterIr}'s `props.title` is made unique by. Shared because the standalone\n * printer has to predict the title the reader gives the write path's own `DEFAULT` layout when a\n * source layout already carries that name.\n */\nexport function uniqueTitle(base: string, used: ReadonlySet<string>): string {\n\tlet title = base\n\tfor (let suffix = 2; used.has(title); suffix++) title = `${base} (${suffix})`\n\treturn title\n}\n\n/**\n * The deck's shared chrome, approximated for an output that has no template to inherit it\n * from. A template-anchored printer ignores this entirely — the source deck *is* the chrome.\n */\nexport interface ChromeIr {\n\ttheme: ThemeIr\n\t/** One entry per source layout, in gallery order. */\n\tmasters: MasterIr[]\n}\n\n/**\n * The `docProps` fields that round-trip, each keyed by its write-API setter and naming the read\n * accessor it comes from: four are `docProps/core.xml`, read through `Presentation.coreProperties`\n * (`author` is `dc:creator`), and `company` is `<Company>` in `docProps/app.xml`, read through\n * `Presentation.appProperties`.\n *\n * The one spelling of the list. {@link DeckPropsIr}, the mapping, the core properties that are not\n * carried, the ones a written deck is stamped with and the round trip's writer defaults all derive\n * from it. They used to be spelled out at each of those sites, and `company`, added late, was\n * missing from one of them.\n */\nexport const DECK_PROPS = {\n\ttitle: { part: 'core', key: 'title' },\n\tauthor: { part: 'core', key: 'creator' },\n\tsubject: { part: 'core', key: 'subject' },\n\trevision: { part: 'core', key: 'revision' },\n\tcompany: { part: 'app', key: 'company' },\n} as const satisfies Record<\n\tstring,\n\t{ part: 'core'; key: keyof CoreProperties } | { part: 'app'; key: keyof ExtendedProperties }\n>\n\n/** A deck property the write API can set, named by its setter. */\nexport type DeckPropKey = keyof typeof DECK_PROPS\n\n/** {@link DECK_PROPS}' keys, in its order. */\nexport const DECK_PROP_KEYS = Object.keys(DECK_PROPS) as DeckPropKey[]\n\n/** Deck-level properties, reduced to the `DECK_PROPS` fields that round-trip. */\nexport type DeckPropsIr = { [K in DeckPropKey]?: string }\n\n/**\n * A whole deck, ready to print.\n *\n * `widthEmu`/`heightEmu` are raw EMU rather than inches because that is what the read\n * model reports and what the write API's `Coord` accepts verbatim; converting here would\n * introduce a rounding decision at the wrong layer.\n */\nexport interface DeckIr {\n\tslideSize: { widthEmu: number; heightEmu: number }\n\tprops: DeckPropsIr\n\t/**\n\t * Theme and layouts, approximated. Only a standalone printer reads this; a\n\t * template-anchored one gets all of it byte-identical from the source deck instead.\n\t */\n\tchrome: ChromeIr\n\tslides: SlideIr[]\n\tassets: AssetIr[]\n\t/**\n\t * Every construct that did not survive into {@link slides} intact. This is a\n\t * *contract*, not a log: a round-trip check excludes exactly these fields from its\n\t * diff, so an unnoted difference is a bug and a note nothing else corroborates is a\n\t * stale claim. See {@link FidelityNote}.\n\t */\n\tfidelity: FidelityNote[]\n}\n","/**\n * Presence checks for constructs the read model has no accessor for.\n *\n * These reach through the documented raw hatch (`element_`) rather than through a typed\n * accessor, which needs justifying. The rule they follow: **detect, never decode.** Each\n * function answers only \"is this here?\", so the answer can become a {@link FidelityNote}.\n * Nothing here interprets a value or feeds one into a call — that would be building a\n * private read path alongside the public one, and it would rot the moment the element's\n * meaning changed.\n *\n * The alternative is worse than the coupling. Without these checks, a deck with an embedded\n * video converts to a static poster image and a deck with an equation converts to an empty\n * box, both silently and both with a clean round-trip, because a diff cannot see what\n * neither side read. A loss you can name is a bug report; a loss nothing observes is a\n * defect that ships.\n *\n * Each check here is a standing argument for a real accessor. When one lands, the\n * corresponding function should be deleted, not kept in sync.\n */\n\nimport { OOXML_NS } from '../../ooxml/namespaces.js'\nimport { boolValue } from '../../ooxml/xsd-boolean.js'\n\n/** Shape-tree children that carry drawing content, as opposed to the tree's own properties. */\nconst SHAPE_ELEMENTS = new Set(['sp', 'pic', 'graphicFrame', 'grpSp', 'cxnSp'])\n\n/** A minimal structural view of a DOM element, so this module needs no DOM lib types. */\ninterface ElementLike {\n\tnamespaceURI: string | null\n\tlocalName: string | null\n\tfirstChild: NodeLike | null\n\tgetAttribute(name: string): string | null\n\tgetElementsByTagNameNS(namespaceURI: string, localName: string): { length: number }\n}\n\ninterface NodeLike {\n\tnodeType: number\n\tnextSibling: NodeLike | null\n}\n\nconst ELEMENT_NODE = 1\n\nfunction has(element: unknown, namespaceURI: string, localName: string): boolean {\n\tconst el = element as ElementLike | null\n\tif (!el || typeof el.getElementsByTagNameNS !== 'function') return false\n\treturn el.getElementsByTagNameNS(namespaceURI, localName).length > 0\n}\n\n/**\n * The first *direct* child with this name.\n *\n * A subtree search is wrong for structural lookups, in two ways that both bite here.\n * `a:ext` names two unrelated elements — a shape extent (`@cx`/`@cy`) and an extension-list\n * entry (`@uri`) — so a subtree search finds whichever comes first in document order. And on\n * a group it descends into the group's own children, so a nested group's transform answers\n * for its parent's.\n */\nfunction child(element: ElementLike | null, namespaceURI: string, localName: string): ElementLike | null {\n\tif (!element) return null\n\tfor (let node = element.firstChild; node; node = node.nextSibling) {\n\t\tif (node.nodeType !== ELEMENT_NODE) continue\n\t\tconst el = node as unknown as ElementLike\n\t\tif (el.namespaceURI === namespaceURI && el.localName === localName) return el\n\t}\n\treturn null\n}\n\n/** Every direct element child, as {@link ElementLike}s. */\nfunction children(element: ElementLike | null): ElementLike[] {\n\tif (!element) return []\n\tconst out: ElementLike[] = []\n\tfor (let node = element.firstChild; node; node = node.nextSibling) {\n\t\tif (node.nodeType === ELEMENT_NODE) out.push(node as unknown as ElementLike)\n\t}\n\treturn out\n}\n\n/**\n * `true` when this shape is an embedded audio or video rather than a still picture.\n *\n * PowerPoint authors media as a `p:pic` whose `p:nvPr` carries an `a:videoFile` or\n * `a:audioFile`, with the poster frame as the picture's own blip. The read model reports\n * only the poster — `mediaKind` distinguishes raster from SVG, not still from moving — so\n * without this check a video converts to a static image that looks deliberate.\n */\nexport function isAudioVideo(element: unknown): boolean {\n\treturn has(element, OOXML_NS.a, 'videoFile') || has(element, OOXML_NS.a, 'audioFile')\n}\n\n/**\n * `true` when this shape's text body contains an OMML equation.\n *\n * An equation lives in `m:oMath` inside an `a14:m` run, which contributes nothing to\n * `TextFrame.text`, so an equation-only shape reads as an empty text frame. The write API\n * *can* author one (`TextProps.math`, plus the `pptx-ts/math` subpath for LaTeX/MathML\n * input), which makes this a read-side gap rather than a hard limit.\n */\nexport function hasEquation(element: unknown): boolean {\n\t// The OMML body itself, wrapped by `a14:m` in a text run.\n\treturn has(element, OOXML_NS.m, 'oMath')\n}\n\n/**\n * `true` when this `p:sp` is a text box rather than an auto shape.\n *\n * The discriminator is one attribute, `p:cNvSpPr/@txBox`, and nothing reads it. The\n * tempting substitute — \"it has no preset geometry\" — is wrong for the common case:\n * PowerPoint gives every text box an explicit `<a:prstGeom prst=\"rect\"/>`, so that test\n * calls every real text box an auto shape. The difference is not cosmetic. PowerPoint\n * autofits, wraps and resizes a text box by different rules, and offers a different\n * right-click menu for it.\n *\n * Direct child rather than a subtree search: `p:cNvSpPr` sits under `p:nvSpPr`, and a group\n * would otherwise answer for its first child.\n *\n * Parsed through {@link boolValue} rather than compared to `'1'`: `txBox` is `xsd:boolean`, and\n * this module's whole job is reading decks this library did not write. PowerPoint and `gen/` both\n * emit `1`, so a bare comparison is right for every fixture here and wrong for a producer that\n * spells it `true` — which would convert that deck's text boxes as auto shapes, silently.\n */\nexport function isTextBox(element: unknown): boolean {\n\tconst nvSpPr = child(element as ElementLike | null, OOXML_NS.p, 'nvSpPr')\n\treturn boolValue(child(nvSpPr, OOXML_NS.p, 'cNvSpPr')?.getAttribute('txBox')) === true\n}\n\n/**\n * `true` when a group's child coordinate space equals its own frame, so its children are\n * already in slide-absolute units.\n *\n * `addGroup` always emits an identity child space; a source group whose `a:chOff`/`a:chExt`\n * differ scales or shifts its contents, and that behaviour cannot be reproduced. The read\n * model has no accessor for the child space — `absoluteFrame` deliberately composes it away,\n * which is right for locating a shape and wrong for spotting this difference.\n *\n * A group with no explicit transform inherits an identity one, so a missing `a:xfrm` is\n * `true` rather than unknown.\n */\nexport function hasIdentityChildSpace(element: unknown): boolean {\n\tconst xfrm = child(child(element as ElementLike | null, OOXML_NS.p, 'grpSpPr'), OOXML_NS.a, 'xfrm')\n\tif (!xfrm) return true\n\n\tconst off = child(xfrm, OOXML_NS.a, 'off')\n\tconst ext = child(xfrm, OOXML_NS.a, 'ext')\n\tconst chOff = child(xfrm, OOXML_NS.a, 'chOff')\n\tconst chExt = child(xfrm, OOXML_NS.a, 'chExt')\n\tif (!off || !ext || !chOff || !chExt) return true\n\n\treturn (\n\t\toff.getAttribute('x') === chOff.getAttribute('x') &&\n\t\toff.getAttribute('y') === chOff.getAttribute('y') &&\n\t\text.getAttribute('cx') === chExt.getAttribute('cx') &&\n\t\text.getAttribute('cy') === chExt.getAttribute('cy')\n\t)\n}\n\n/**\n * `true` when this theme declares an `a:fmtScheme`.\n *\n * The format scheme holds the three fill, three line and three effect style lists a shape's\n * `p:style` indexes into. Neither half of the library touches it: nothing reads it, and the\n * write path emits a hardcoded Office one. So a deck whose theme carries a custom format\n * scheme is repainted with Office's, and this is the only way to notice.\n */\nexport function hasFormatScheme(element: unknown): boolean {\n\treturn has(element, OOXML_NS.a, 'fmtScheme')\n}\n\n/**\n * `true` when this slide master declares per-level text styles (`p:txStyles`) with content.\n *\n * `SlideMasterProps.textStyles` can author them, so this is purely a read-side gap — the\n * default size, face, colour and bullet of every placeholder level is invisible to the\n * converter and comes back as PowerPoint's built-in default.\n */\nexport function hasTextStyles(element: unknown): boolean {\n\tconst txStyles = child(element as ElementLike | null, OOXML_NS.p, 'txStyles')\n\treturn children(txStyles).some((group) => children(group).length > 0)\n}\n\n/**\n * `true` when this shape is a placeholder — the tier that *reserves* a region for a slide to\n * fill, as opposed to the decoration that is drawn as-is.\n *\n * A DOM predicate rather than `shape.placeholder !== null`, and that is not an oversight: only\n * `AutoShape` reports a `p:ph` through the read model, so the model-based spelling would call\n * a *picture* placeholder (`p:nvPicPr/p:nvPr/p:ph`, which PowerPoint does author) decoration\n * and re-draw it as a fixed image on every slide bound to the layout.\n *\n * Not a direct-child lookup, unlike its neighbours: the `p:ph` sits two or three levels down\n * inside whichever `p:nv*Pr` the shape kind uses. That means a *group* containing a\n * placeholder answers `true` for its child, which is the wanted answer anyway — a group is\n * never itself a placeholder, and a layout that put one inside a group is one whose grouping\n * cannot survive being flattened into loose objects.\n */\nexport function isPlaceholderShape(element: unknown): boolean {\n\treturn has(element, OOXML_NS.p, 'ph')\n}\n\n/**\n * `true` when this master or layout carries a shape that is not a placeholder — a logo, a\n * rule, a background image, a footer graphic.\n *\n * Only the **master** arm still needs this. A layout's decoration is now transcribed into its\n * `defineSlideMaster({ objects })` call, so what did not survive is reported per shape rather\n * than as a blanket count. A master's cannot be: `defineSlideMaster` authors a *layout* under\n * the one shared master, so a master's own shape tree has no write-side counterpart at all,\n * and a deck whose master carries none loses nothing — which is why this is a presence check\n * rather than an unconditional note.\n */\nexport function hasDecorativeShapes(element: unknown): boolean {\n\tconst spTree = child(child(element as ElementLike | null, OOXML_NS.p, 'cSld'), OOXML_NS.p, 'spTree')\n\treturn children(spTree).some(\n\t\t(shape) =>\n\t\t\tshape.namespaceURI === OOXML_NS.p && SHAPE_ELEMENTS.has(shape.localName ?? '') && !isPlaceholderShape(shape)\n\t)\n}\n","/**\n * `TextFrame` → `addText(TextProps[], TextPropsOptions)`.\n *\n * Two structural mismatches shape this mapper, and both are why the conversion is not a\n * field-by-field copy:\n *\n * 1. **The read model is a tree; `addText` takes a flat list.** OOXML nests runs inside\n * paragraphs; `TextProps[]` is one flat array where a paragraph boundary is a\n * `breakLine` flag on the item that *precedes* it. So the last run of each paragraph\n * carries the break, and a paragraph's own properties are replicated onto each of its\n * runs — the write path reads alignment and spacing off whichever run starts a line.\n *\n * 2. **Vocabularies differ on both sides of the same concept.** OOXML spells alignment\n * `l`/`ctr`/`r`/`just`, the write API spells it `left`/`center`/`right`/`justify`; two\n * of the six `@algn` values have no write spelling at all. Every such translation is a\n * table here rather than a pass-through, so an unmappable token produces a note instead\n * of an invalid option.\n *\n * Run-level reads prefer the *explicit* value over the resolved one, but only where leaving\n * the option out really does leave the value inherited. That is the part worth checking\n * rather than assuming: the round-trip harness found that an omitted run colour and an\n * omitted vertical anchor are both filled in by the write path — black, and centred — so\n * \"stay quiet and let it inherit\" was silently repainting text and re-anchoring bodies. Both\n * now emit the *resolved* value with a note, which freezes it against a later theme edit and\n * renders correctly, in preference to staying faithful in the IR and wrong on the slide.\n */\nimport type { BodyProperties, BulletDetail, BulletStyle, Paragraph, Run, TextFrame } from '../../read/api/text.js'\nimport type { Hyperlink } from '../../read/api/hyperlink.js'\nimport type { AnyShape } from '../../read/api/shapes.js'\nimport { BODY_INSET_DEFAULTS_PT } from '../../ooxml/body-insets.js'\nimport { TEXT_AUTONUM_SCHEMES, TEXT_VERTICAL } from '../../ooxml/st-enums.js'\nimport { HALIGN_BY_TEXT_ALIGN } from '../../ooxml/text-align.js'\nimport type { NoteScope } from '../fidelity.js'\nimport type { IrValue } from '../ir.js'\nimport type { MapContext } from './context.js'\nimport { hasEquation } from './detect.js'\nimport {\n\tANCHOR_TO_VALIGN,\n\tcolorOption,\n\tcompact,\n\tliteralColor,\n\torUndefined,\n\tpointsToInches,\n\tschemeColorOption,\n} from './values.js'\n\n/**\n * `a:pPr/@algn` → `HAlign`. `dist` and `thaiDist` (distributed justification) are\n * deliberately absent: the write API has no spelling for them, and mapping them onto\n * `justify` would be a silent visual change rather than a declared loss.\n */\nconst ALIGN = HALIGN_BY_TEXT_ALIGN\n\n/** `AutofitMode` → the write API's `fit`. */\nconst FIT: Record<string, string> = { none: 'none', normAutofit: 'shrink', spAutoFit: 'resize' }\n\n/**\n * `a:bodyPr/@vert` values the write API's `vert` accepts. `TextVertType` is the whole\n * `ST_TextVerticalType`, so this is `TEXT_VERTICAL` itself, and `text.vert` fires only for a token\n * outside the schema.\n */\nconst WRITABLE_VERT: ReadonlySet<string> = new Set<string>(TEXT_VERTICAL)\n\n/**\n * The `a:buAutoNum/@type` values the write API's `numberType` names.\n *\n * This used to be the *discriminator* between a numbered and a character bullet, back when\n * the read model reported both as one tagged string. `BulletDetail.kind` does that now, so\n * the lookup has one job left: telling a scheme the write path can spell from one it cannot.\n *\n * Built from the tuple the write API's `numberType` is derived from and its emitter checks, so\n * the two cannot disagree about a scheme.\n */\nconst AUTO_NUMBER_TYPES: ReadonlySet<string> = new Set(TEXT_AUTONUM_SCHEMES)\n\n/**\n * `Paragraph.bulletDetail` → the write API's `bullet` option.\n *\n * This function used to take a **tagged** string — `'none'`, `'char:<glyph>'` or\n * `'autoNum:<type>'` — and its first version read it as a bare glyph. The result was silent\n * and universal: a paragraph that explicitly suppressed its bullet (`a:buNone`, which is most\n * of them) came back with a literal `n` bullet, because `'none'.codePointAt(0)` is `n`; a real\n * character bullet came back as `c`, from the `char:` tag; and a numbered list came back as\n * `a`. Every converted deck was affected and nothing failed, which is why the round-trip check\n * exists — and why the accessor is now a discriminated union with no parsing left to get wrong.\n */\nfunction bulletOption(bullet: BulletDetail, notes: NoteScope): IrValue {\n\t// Explicit suppression, and it must stay explicit: an omitted `bullet` lets the\n\t// destination list style put one back.\n\tif (bullet.kind === 'none') return false\n\n\t// A picture bullet's bytes would have to be re-embedded through the asset resolver, which\n\t// the paragraph mapper does not carry — `addText`'s `bullet.image` could author it.\n\tif (bullet.kind === 'picture') {\n\t\tnotes.note(\n\t\t\t'text.bullet.picture',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t'this paragraph uses an image as its bullet glyph (a:buBlip); the text mapper has no asset resolver to re-embed it with, so the bullet falls back to the default character'\n\t\t)\n\t\treturn true\n\t}\n\n\tconst style = bulletStyle(bullet, notes)\n\n\tif (bullet.kind === 'autoNum') {\n\t\tif (!AUTO_NUMBER_TYPES.has(bullet.scheme)) {\n\t\t\tnotes.note(\n\t\t\t\t'text.bullet.numberType',\n\t\t\t\t'approximated',\n\t\t\t\t'unwritable',\n\t\t\t\t`numbering scheme \"${bullet.scheme}\" is outside the set the write API names, so the list falls back to the default scheme`\n\t\t\t)\n\t\t\treturn compact({ type: 'number', ...startAtOption(bullet.startAt), ...style }) ?? { type: 'number' }\n\t\t}\n\t\treturn (\n\t\t\tcompact({ type: 'number', numberType: bullet.scheme, ...startAtOption(bullet.startAt), ...style }) ?? {\n\t\t\t\ttype: 'number',\n\t\t\t}\n\t\t)\n\t}\n\n\t// Zero-padded to four digits, and that is load-bearing rather than cosmetic: the write\n\t// path tests `characterCode` against /^[0-9A-Fa-f]{4}$/ and, on a miss, warns to the\n\t// console and substitutes its own default glyph. So \"6E\" — a perfectly good code point —\n\t// silently became a different bullet character, visible only in the rendered slide.\n\tconst code = bullet.char.codePointAt(0) ?? 0x2022\n\tif (code > 0xffff) {\n\t\tnotes.note(\n\t\t\t'text.bullet.glyph',\n\t\t\t'approximated',\n\t\t\t'unwritable',\n\t\t\t`bullet glyph U+${code.toString(16).toUpperCase()} is outside the Basic Multilingual Plane and characterCode takes a four-digit code, so the bullet falls back to the write path's default glyph`\n\t\t)\n\t}\n\treturn compact({ characterCode: code.toString(16).toUpperCase().padStart(4, '0'), ...style }) ?? {}\n}\n\n/**\n * `a:pPr/@marL` / `@indent` → `paraMarginLeft` / `paraIndent`.\n *\n * A stated margin carries as its number. An *absent* one is the interesting case, because\n * leaving the key out does not reproduce it: every `bullet` state except `'inherit'` makes the\n * write path put a margin on the element — its hanging default for a drawn bullet, zero for\n * `bullet: false` — so a paragraph that inherits its margin has to ask for silence explicitly.\n * Under `bullet: 'inherit'` nothing is written either way and the key would be noise, which is\n * why the bullet option decides rather than the paragraph being asked twice.\n * @param {number|null} valuePt - the paragraph's own margin in points, `null` when unset\n * @param {IrValue} bulletValue - the `bullet` option this paragraph maps onto\n * @return {IrValue|undefined} the option value, or `undefined` to leave the key out\n */\nfunction paraMarginOption(valuePt: number | null, bulletValue: IrValue): IrValue | undefined {\n\tif (valuePt !== null) return valuePt\n\treturn bulletValue === 'inherit' ? undefined : 'inherit'\n}\n\n/**\n * `a:buAutoNum/@startAt` → `numberStartAt`.\n *\n * Numbering is content rather than styling: a list continuing \"5. Deploy\" that comes back as\n * \"1. Deploy\" is a different slide. `1` is the schema default, so emitting it would only add\n * noise to the printed script.\n */\nfunction startAtOption(startAt: number | null): Record<string, IrValue> {\n\treturn startAt === null || startAt === 1 ? {} : { numberStartAt: startAt }\n}\n\n/**\n * The bullet's own font, size and colour (`a:buFont` / `a:buSzPct` / `a:buClr`) as the write\n * API's `fontFace` / `size` / `color`.\n *\n * `a:buSzPts` has no write-API counterpart — `bullet.size` is a percentage of the run size —\n * so an absolute bullet size is the one part of this that still cannot carry.\n */\nfunction bulletStyle(bullet: BulletStyle, notes: NoteScope): Record<string, IrValue> {\n\tif (bullet.sizePt !== null) {\n\t\tnotes.note(\n\t\t\t'text.bullet.sizePt',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'this bullet sets an absolute glyph size (a:buSzPts); bullet.size is a percentage of the run size, so the absolute value has no write-API expression and the glyph follows the text size'\n\t\t)\n\t}\n\n\t// 25–400% is ST_TextBulletSizePercent's range, and the write path clamps an out-of-range\n\t// value to the nearest bound rather than accepting it. Print the clamped number so the\n\t// script says what the deck will get, and declare the difference — printing the source\n\t// value instead would make the script warn on every run.\n\tconst sizePct = bullet.sizePct\n\tconst clampedPct = sizePct === null ? null : Math.min(400, Math.max(25, sizePct))\n\tif (sizePct !== null && clampedPct !== sizePct) {\n\t\tnotes.note(\n\t\t\t'text.bullet.sizePct',\n\t\t\t'approximated',\n\t\t\t'unwritable',\n\t\t\t`bullet glyph size ${sizePct}% is outside the 25–400% range the write API accepts, so it is printed as ${clampedPct}% — the bound the write path clamps it to`\n\t\t)\n\t}\n\n\treturn (\n\t\tcompact({\n\t\t\tfontFace: orUndefined(bullet.font),\n\t\t\tsize: clampedPct ?? undefined,\n\t\t\tcolor: bulletColor(bullet, notes),\n\t\t}) ?? {}\n\t)\n}\n\n/**\n * The bullet's colour, preferring the raw `schemeClr` token over the resolved literal for the\n * same reason {@link runColor} does: a token keeps tracking the destination theme.\n */\nfunction bulletColor(bullet: BulletStyle, notes: NoteScope): string | undefined {\n\treturn colorOption(\n\t\t{\n\t\t\tscheme: bullet.colorRef.scheme,\n\t\t\townHex: bullet.colorRef.srgb,\n\t\t\tresolvedHex: bullet.colorRef.resolved?.effectiveHex ?? null,\n\t\t},\n\t\tnotes,\n\t\t'text.bullet.schemeToken',\n\t\t'bullet'\n\t)\n}\n\n/**\n * Per-run character formatting, shared by shape text and table-cell text.\n *\n * The three decoration tokens carry their **explicit off** — `u=\"none\"`, `strike=\"noStrike\"`,\n * `cap=\"none\"` — rather than collapsing it into the unstated case. Stating one is a different\n * fact from stating nothing: run properties resolve down the `a:lstStyle` → placeholder →\n * layout → master chain, so a run that would take `u=\"sng\"` from its list style and states\n * `u=\"none\"` is *not* underlined, while the same run with the attribute dropped is. Only an\n * absent attribute (`null` here) means \"state nothing\"; each off token is a member of its\n * enumeration in its own right (ECMA-376 §20.1.10.81 / §20.1.10.78) and would be redundant\n * with omission otherwise.\n */\nexport function runOptions(run: Run, ctx: MapContext): Record<string, IrValue> | undefined {\n\tconst { notes } = ctx\n\tconst underline = run.underline\n\tconst hyperlink = hyperlinkOption(run, ctx)\n\t// PowerPoint paints a link underlined when the run states no `u`\n\t// (`test/read/fixtures/slide-jump-link.pptx` renders both its linked runs that way), and the\n\t// write path states `u=\"sng\"` on every link that sets no underline. The two look the same, but\n\t// the rebuilt run no longer leaves its underline to the link, and there is no option to say so.\n\tif (hyperlink !== undefined && underline === null) {\n\t\tnotes.note(\n\t\t\t'text.hyperlink.underline',\n\t\t\t'flattened',\n\t\t\t'unwritable',\n\t\t\t'this run links somewhere and states no underline, which PowerPoint paints underlined all the same; the write path writes u=\"sng\" on a link that sets none, so the text looks the same but states an underline it used to leave to the link'\n\t\t)\n\t}\n\n\treturn compact({\n\t\tbold: orUndefined(run.bold),\n\t\titalic: orUndefined(run.italic),\n\t\tunderline: underline === null ? undefined : { style: underline },\n\t\tstrike: orUndefined(run.strike),\n\t\tfontSize: orUndefined(run.fontSizePt),\n\t\tfontFace: orUndefined(run.fontName),\n\t\tcolor: runColor(run, notes),\n\t\thighlight: run.highlight ? literalColor(run.highlight.effectiveHex) : undefined,\n\t\tcaps: orUndefined(run.caps),\n\t\t// The write API spells baseline shift as a percentage, the same unit the read\n\t\t// model reports, so superscript/subscript survive without a preset round-trip.\n\t\tbaseline: orUndefined(run.baselinePct),\n\t\thyperlink,\n\t})\n}\n\n/**\n * A run's colour, preferring the raw `schemeClr` token over the resolved literal so the\n * text keeps tracking the destination theme. Only the ten tokens the write path's `clrMap`\n * covers survive as tokens; the other seven degrade to a literal hex there anyway, so\n * passing one through unchanged would produce a silently different colour.\n */\nfunction runColor(run: Run, notes: NoteScope): string | undefined {\n\tconst scheme = run.schemeColor\n\tif (scheme !== null)\n\t\treturn schemeColorOption(scheme, run.resolvedColor?.effectiveHex ?? null, notes, 'text.color.schemeToken', 'run')\n\tif (run.color !== null) return literalColor(run.color)\n\n\t// A run with no colour of its own inherits one, and leaving the option out does *not* pass\n\t// that inheritance along: `addText` fills an uncoloured non-placeholder run with\n\t// DEF_FONT_COLOR, so omitting it repaints the text black. That makes this a loss either\n\t// way, and which loss depends on whether the inherited colour can be resolved — so the two\n\t// outcomes are declared separately rather than under one note that would overstate one and\n\t// understate the other.\n\tconst inherited = run.resolvedColor\n\tif (!inherited) {\n\t\tnotes.note(\n\t\t\t'text.color.default',\n\t\t\t'approximated',\n\t\t\t'unread',\n\t\t\t'this run inherits its colour and nothing resolves what it inherits (a list style the read model does not walk), so the write path paints it black — the one case where the output colour is not merely frozen but possibly wrong'\n\t\t)\n\t\treturn undefined\n\t}\n\tnotes.note(\n\t\t'text.color.inherited',\n\t\t'flattened',\n\t\t'unsupported',\n\t\t'this run inherits its colour from the placeholder, master or theme; the write path paints an uncoloured run black instead of leaving it to inherit, so the inherited colour is resolved and baked in and no longer tracks a theme change'\n\t)\n\treturn literalColor(inherited.effectiveHex)\n}\n\n/** The `@action` of a jump to another slide of the deck. */\nconst SLIDE_JUMP = 'ppaction://hlinksldjump'\n\n/**\n * A run's hyperlink: a URL, or a jump to another slide of this deck by its number.\n *\n * The read model reports a slide jump as the target's part name, and the write API takes a slide\n * number, which {@link MapContext.slideNumberOf} resolves. Anything else a run can link to has no\n * run-level spelling (a show jump such as \"next slide\", which the write side emits at shape level\n * only; a custom show; another file; a slide jump from a layout's shape) and is noted. A slide\n * jump used to be dropped with a comment saying the deck-level walk handled it, which it did not,\n * so the text kept its link formatting and went nowhere.\n */\nfunction hyperlinkOption(run: Run, ctx: MapContext): IrValue | undefined {\n\treturn linkOption(run.hyperlink, ctx, RUN_LINK)\n}\n\n/** The show-jump actions `HyperlinkProps.action` spells, by the `@action` each one is written as. */\nconst SHOW_JUMP_ACTIONS: ReadonlyMap<string, string> = new Map(\n\t['firstslide', 'previousslide', 'nextslide', 'lastslide', 'lastslideviewed', 'endshow'].map((jump) => [\n\t\t`ppaction://hlinkshowjump?jump=${jump}`,\n\t\tjump,\n\t])\n)\n\n/** What {@link linkOption} can spell where the link hangs, and how to describe a loss there. */\ninterface LinkSite {\n\t/** The fidelity note's construct key. */\n\tconstruct: 'text.hyperlink' | 'shape.hyperlink'\n\t/** Whether this site's option takes `action`; only a shape's does. */\n\ttakesAction: boolean\n\t/** Names the thing that carries the link, opening the note. */\n\tsubject: string\n\t/** What the option can spell, for the note. */\n\tspells: string\n\t/** What is lost, closing the note. */\n\tloss: string\n}\n\nconst RUN_LINK: LinkSite = {\n\tconstruct: 'text.hyperlink',\n\ttakesAction: false,\n\tsubject: \"this run's hyperlink\",\n\tspells:\n\t\t\"all a run's hyperlink option spells (a show jump, a custom show, another file, or a slide jump from a layout's shape)\",\n\tloss: 'the text keeps its formatting and links nowhere',\n}\n\nconst SHAPE_LINK: LinkSite = {\n\tconstruct: 'shape.hyperlink',\n\ttakesAction: false,\n\tsubject: \"this shape's hyperlink\",\n\tspells: \"all a shape's hyperlink option spells (a custom show, another file, or a slide jump from a layout's shape)\",\n\tloss: 'the shape is emitted without it and clicking it does nothing',\n}\n\n/**\n * The `@action` PowerPoint puts on an audio or video picture's `p:cNvPr`. It is structural rather\n * than a link anyone set -- the media emitter writes it itself (`gen/slide/objects/media.ts`), and\n * `addMedia` writes it again -- so it is not a hyperlink to carry and not a loss to note.\n */\nconst MEDIA_ACTION = 'ppaction://media'\n\n/** A shape's own click hyperlink, as `addShape`/`addText`/`addImage` take it. */\nexport function shapeHyperlinkOption(shape: AnyShape, ctx: MapContext): IrValue | undefined {\n\tconst link = shape.hyperlink\n\tif (link?.action === MEDIA_ACTION) return undefined\n\treturn linkOption(link, ctx, { ...SHAPE_LINK, takesAction: true })\n}\n\n/**\n * One reading of a click hyperlink for both sites that carry one. A run and a shape take the same\n * `HyperlinkProps` apart from `action`, which only a shape's is written as, so the difference is a\n * flag rather than a second copy of the mapping.\n */\nfunction linkOption(link: Hyperlink | null, ctx: MapContext, site: LinkSite): IrValue | undefined {\n\tif (!link) return undefined\n\tconst tooltip = link.tooltip ?? undefined\n\tif (link.url) return compact({ url: link.url, tooltip })\n\tconst slide = link.action === SLIDE_JUMP && link.targetPartName ? ctx.slideNumberOf(link.targetPartName) : null\n\tif (slide !== null) return compact({ slide, tooltip })\n\tconst jump = link.action === null ? undefined : SHOW_JUMP_ACTIONS.get(link.action)\n\tif (site.takesAction && jump !== undefined) return compact({ action: jump, tooltip })\n\tctx.notes.note(\n\t\tsite.construct,\n\t\t'dropped',\n\t\t'unwritable',\n\t\t`${site.subject} (${link.action ?? 'an internal target'}) is neither a URL nor a jump to another slide of the deck, which is ${site.spells}, so ${site.loss}`\n\t)\n\treturn undefined\n}\n\n/** The constructs and wording {@link noteUnreadText} records a shape's or a table cell's losses in. */\nconst UNREAD_TEXT = {\n\tshape: {\n\t\tfield: 'text.field',\n\t\tequation: 'text.equation',\n\t\tsubject: 'this shape',\n\t\tcall: 'addText',\n\t\tequationLoss:\n\t\t\t'the shape is emitted without it - even though TextProps.math (and the ts-pptx/math subpath) could author one',\n\t},\n\tcell: {\n\t\tfield: 'table.cell.field',\n\t\tequation: 'table.cell.equation',\n\t\tsubject: 'this table cell',\n\t\tcall: 'addTable',\n\t\tequationLoss: 'the cell is emitted without it',\n\t},\n} as const\n\n/**\n * Note the text a frame holds that no run carries, and return the text its runs do.\n *\n * Authorable text is *runs*. `TextFrame.text` also counts `a:fld` field text (a slide number, date\n * or footer placeholder), which has no run behind it, and an OMML equation contributes to neither.\n * Both were checked for an auto shape only, so the same field in a table cell was lost with no note.\n * @param frame - the text frame\n * @param element - the element holding it, searched for an equation\n * @param notes - the scope the losses are recorded on\n * @param holder - whether the frame belongs to a shape or a table cell\n * @returns the frame's run text\n */\nexport function noteUnreadText(\n\tframe: TextFrame,\n\telement: unknown,\n\tnotes: NoteScope,\n\tholder: keyof typeof UNREAD_TEXT\n): string {\n\tconst wording = UNREAD_TEXT[holder]\n\tconst runText = frame.paragraphs.flatMap((p) => p.runs.map((run) => run.text)).join('')\n\n\t// Run text is a subsequence of the frame's text, so anything longer came from a field.\n\tif (frame.text.replaceAll('\\n', '').length > runText.length) {\n\t\tnotes.note(\n\t\t\twording.field,\n\t\t\t'dropped',\n\t\t\t'unread',\n\t\t\t`${wording.subject} holds an automatic field (a:fld - a slide number, date or footer), which has no accessor and no ${wording.call} expression, so its text is not reproduced`\n\t\t)\n\t}\n\n\t// An OMML equation contributes nothing to `TextFrame.text`, so an equation-only shape looks like\n\t// an empty box and would otherwise emit as bare geometry.\n\tif (hasEquation(element)) {\n\t\tnotes.note(\n\t\t\twording.equation,\n\t\t\t'dropped',\n\t\t\t'unread',\n\t\t\t`${wording.subject} holds an OMML equation, which no accessor exposes, so ${wording.equationLoss}`\n\t\t)\n\t}\n\treturn runText\n}\n\n/** Paragraph-level properties, replicated onto each of the paragraph's runs. */\nfunction paragraphOptions(paragraph: Paragraph, notes: NoteScope): Record<string, IrValue> {\n\tconst spacing = paragraph.lineSpacing\n\tconst bullet = paragraph.bulletDetail\n\tconst align = paragraph.align\n\n\tif (align !== null && !(align in ALIGN)) {\n\t\tnotes.note(\n\t\t\t'text.align',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t`distributed alignment \"${align}\" has no write-API spelling, so the paragraph falls back to its inherited alignment`\n\t\t)\n\t}\n\tif (paragraph.spaceBeforePt === 0 || paragraph.spaceAfterPt === 0) {\n\t\tnotes.note(\n\t\t\t'text.paraSpaceZero',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'this paragraph explicitly sets zero space before or after (a:spcBef / a:spcAft of 0), which suppresses the spacing its list style would otherwise apply; the write path treats 0 as \"unset\" and emits nothing, so the inherited spacing comes back'\n\t\t)\n\t}\n\t// `text.indent` used to be filed here — a paragraph's own `a:pPr/@marL` and `@indent` had no\n\t// write option at all, so every margin it stated was replaced by whatever the `bullet` state\n\t// wrote. `paraMarginLeft` / `paraIndent` state them now, so the mapper carries the values\n\t// instead of excusing their loss and the note is gone rather than unmapped.\n\tconst bulletValue = bullet === null ? 'inherit' : bulletOption(bullet, notes)\n\n\treturn (\n\t\tcompact({\n\t\t\talign: align === null ? undefined : ALIGN[align],\n\t\t\tindentLevel: paragraph.level === 0 ? undefined : paragraph.level,\n\t\t\tparaMarginLeft: paraMarginOption(paragraph.marginLeftPt, bulletValue),\n\t\t\tparaIndent: paraMarginOption(paragraph.indentPt, bulletValue),\n\t\t\tparaSpaceBefore: orUndefined(paragraph.spaceBeforePt),\n\t\t\tparaSpaceAfter: orUndefined(paragraph.spaceAfterPt),\n\t\t\tlineSpacing: spacing?.type === 'points' ? spacing.valuePt : undefined,\n\t\t\tlineSpacingMultiple: spacing?.type === 'percent' ? spacing.percent / 100 : undefined,\n\t\t\t// A paragraph with no bullet child of its own states nothing, and `'inherit'` is\n\t\t\t// how the write path says that. `undefined` would NOT do — an omitted `bullet`\n\t\t\t// emits an explicit `a:buNone`, which suppresses whatever the destination list\n\t\t\t// style has. That was this converter's most frequent loss (`text.bullet.inherited`,\n\t\t\t// 34 of 44 corpus fixtures) until the option gained a third state. Resolved above\n\t\t\t// rather than here: the margin keys need to know which bullet state was chosen, and\n\t\t\t// calling `bulletOption` twice would file its notes twice.\n\t\t\tbullet: bulletValue,\n\t\t}) ?? {}\n\t)\n}\n\n/**\n * Flatten a text frame into the `TextProps[]` first argument of `addText`.\n *\n * An empty paragraph becomes an item with empty text and a `breakLine`, which is how a\n * blank line survives — dropping it would silently close up vertical space the author put\n * there deliberately.\n */\nexport function textRuns(frame: TextFrame, ctx: MapContext): IrValue[] {\n\tconst paragraphs = frame.paragraphs\n\tconst items: IrValue[] = []\n\n\tparagraphs.forEach((paragraph, paragraphIndex) => {\n\t\tconst paraOpts = paragraphOptions(paragraph, ctx.notes)\n\t\tconst runs = paragraph.runs\n\t\t// The paragraph break rides on the last run of every paragraph but the final one;\n\t\t// a trailing break would add an empty line the frame never had.\n\t\tconst breaks = paragraphIndex < paragraphs.length - 1\n\n\t\tif (runs.length === 0) {\n\t\t\titems.push({ text: '', options: compact({ ...paraOpts, breakLine: breaks }) ?? {} })\n\t\t\treturn\n\t\t}\n\n\t\truns.forEach((run, runIndex) => {\n\t\t\tconst isLastRun = runIndex === runs.length - 1\n\t\t\t// `bullet` goes on the first run only, unlike the other paragraph properties. The\n\t\t\t// write path treats a bullet on a run that is *not* starting a line as a request for\n\t\t\t// a new paragraph — and clears that run's `breakLine` while it is at it — so\n\t\t\t// replicating the bullet split every bulleted paragraph that had more than one run.\n\t\t\t// It reads paragraph properties off whichever run opens the line, so once is enough.\n\t\t\tconst continuation = { ...paraOpts }\n\t\t\tdelete continuation['bullet']\n\t\t\tconst options = compact({\n\t\t\t\t...(runIndex === 0 ? paraOpts : continuation),\n\t\t\t\t...runOptions(run, ctx),\n\t\t\t\t...(isLastRun && breaks ? { breakLine: true } : {}),\n\t\t\t})\n\t\t\titems.push(compact({ text: run.text, options }) ?? { text: run.text })\n\t\t})\n\t})\n\n\treturn items\n}\n\n/**\n * Frame-level layout for the `TextPropsOptions` second argument — everything that belongs\n * to the body as a whole rather than to any paragraph.\n *\n * `resolvedAnchor` is the one place a *resolved* read is the right one: vertical anchoring\n * has no per-run fallback, so an unset `a:bodyPr/@anchor` genuinely means \"whatever the\n * placeholder says\", and an appended shape does not inherit that.\n */\nexport function textFrameOptions(frame: TextFrame, notes: NoteScope): Record<string, IrValue> {\n\tconst body = frame.bodyProperties\n\tconst anchor = frame.resolvedAnchor\n\tconst vert = body?.vert ?? null\n\n\tif (vert !== null && !WRITABLE_VERT.has(vert)) {\n\t\tnotes.note(\n\t\t\t'text.vert',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t`text direction \"${vert}\" is outside TextVertType, so the body falls back to horizontal`\n\t\t)\n\t}\n\n\treturn (\n\t\tcompact({\n\t\t\t// Spelled out even when nothing in the source set it. `resolvedAnchor` returning\n\t\t\t// null means PowerPoint would default the body to top — but `addText` defaults a\n\t\t\t// non-placeholder body to *centre*, so leaving the option out re-anchors the text.\n\t\t\tvalign: anchor === null ? 'top' : ANCHOR_TO_VALIGN[anchor],\n\t\t\t// `@wrap` is `square`/`none` in OOXML and a boolean in the write API.\n\t\t\twrap: body?.wrap === null || body?.wrap === undefined ? undefined : body.wrap !== 'none',\n\t\t\tvert: vert !== null && WRITABLE_VERT.has(vert) ? vert : undefined,\n\t\t\tfit: fitOption(frame, notes),\n\t\t\tmargin: marginOption(body),\n\t\t}) ?? {}\n\t)\n}\n\n/**\n * `a:bodyPr`'s autofit as the write API's `fit`.\n *\n * A `normAutofit` that bakes `fontScale` or `lnSpcReduction` is a *different state* from a\n * bare `<a:normAutofit/>`, so the two get different spellings. ECMA-376 §21.1.2.1.3 defaults\n * each attribute to 100%/0% only when it is **omitted**; PowerPoint recomputes an unbaked\n * scale on edit and draws the baked one exactly as written until then. Flattening both to\n * `'shrink'` therefore re-emits a frame that paints its text at full size — a deck baked at\n * `fontScale=\"40000\"` comes back two and a half times too large — and the object form is\n * already what the write API accepts, so nothing has to be lost here.\n *\n * Out-of-range percentages are the one arm that still loses something. The write path rejects\n * anything outside 0–100 and drops the attribute with a warning, so passing one through would\n * turn a declared loss into a silent one; the frame falls back to bare `'shrink'` with a note.\n */\nfunction fitOption(frame: TextFrame, notes: NoteScope): IrValue | undefined {\n\tconst autofit = frame.autofit\n\tif (autofit === null) return undefined\n\tif (autofit !== 'normAutofit') return FIT[autofit]\n\n\tconst baked = compact({\n\t\tfontScale: bakedPct(frame.autofitFontScale, 'fontScale', notes),\n\t\tlnSpcReduction: bakedPct(frame.autofitLineSpaceReduction, 'lnSpcReduction', notes),\n\t})\n\treturn baked ? { type: 'shrink', ...baked } : FIT[autofit]\n}\n\n/** A baked `a:normAutofit` percentage, or `undefined` (with a note) when the write API would reject it. */\nfunction bakedPct(value: number | null, name: 'fontScale' | 'lnSpcReduction', notes: NoteScope): number | undefined {\n\tif (value === null) return undefined\n\tif (value >= 0 && value <= 100) return value\n\tnotes.note(\n\t\t`text.autofit.${name}`,\n\t\t'dropped',\n\t\t'unwritable',\n\t\t`baked a:normAutofit/@${name} of ${value}% is outside the 0-100 the write API accepts, so the frame re-emits a bare <a:normAutofit/>`\n\t)\n\treturn undefined\n}\n\n/**\n * `a:bodyPr` insets as the write API's `margin`.\n *\n * A unit change, not just a copy: the read model reports insets in points, `margin` takes\n * **inches**, and it warns on any value `>= 1` on the assumption it is a stray points\n * value. Passing points straight through would therefore both inset the text by roughly\n * 72× too much and trip that warning.\n *\n * Emitted as the four-tuple whenever any inset is set, since a partial tuple is not\n * expressible; an unset side takes PowerPoint's own default rather than zero, so those are\n * spelled out — defaulting them to 0 would visibly reflow every body that sets one side.\n */\n\nfunction marginOption(body: BodyProperties | null): IrValue | undefined {\n\tconst insets = body?.insetsPt\n\tif (!insets) return undefined\n\tconst { left, right, top, bottom } = insets\n\tif (left === undefined && right === undefined && top === undefined && bottom === undefined) return undefined\n\treturn [\n\t\tpointsToInches(top ?? BODY_INSET_DEFAULTS_PT.top),\n\t\tpointsToInches(right ?? BODY_INSET_DEFAULTS_PT.right),\n\t\tpointsToInches(bottom ?? BODY_INSET_DEFAULTS_PT.bottom),\n\t\tpointsToInches(left ?? BODY_INSET_DEFAULTS_PT.left),\n\t]\n}\n","/**\n * `Table` → `addTable(TableRow[], TableProps)`.\n *\n * Tables are the one place the exact-EMU rule stops. `colW` and `rowH` are number-typed\n * (inches) rather than `Coord`-typed, so they cannot take a raw-EMU string the way every\n * position and size can. They print at six decimal places, which is the measured minimum\n * at which `Math.round(inches × 914400)` returns the original EMU — the drift is bounded\n * at 0.4572 EMU, roughly half a millionth of an inch, and rounding shorter to make the\n * numbers look tidy would turn a cosmetic problem into a real geometry loss.\n *\n * Table *style* is the opposite story, and better than it looks. A style is a GUID into\n * the deck's `ppt/tableStyles.xml`, and a template-anchored output keeps that part intact,\n * so passing the source GUID through reproduces the banding, header shading, and borders\n * exactly rather than approximately. That is why per-cell fills read off the style graph\n * are deliberately *not* baked into each cell here: doing so would freeze the appearance\n * and stop the table responding to its own style.\n */\nimport type { CellBorder, Table, TableCell } from '../../read/api/table.js'\nimport type { GraphicFrame } from '../../read/api/shapes.js'\nimport type { TextBaseProps } from '../../types/text.js'\nimport type { NoteScope } from '../fidelity.js'\nimport type { CallIr, IrValue } from '../ir.js'\nimport type { MapContext } from './context.js'\nimport { TABLE_CELL_MARGIN_DEFAULTS_EMU } from '../../ooxml/body-insets.js'\nimport {\n\tANCHOR_TO_VALIGN,\n\tcolorOption,\n\tcompact,\n\tframeOf,\n\tidentityOptions,\n\tinches,\n\tnameOf,\n\torUndefined,\n\tpositionOptions,\n\tWRITABLE_DASHES,\n} from './values.js'\nimport { surfaceFill } from './surface-fill.js'\nimport { noteUnreadText, runOptions, textRuns } from './text.js'\n\nexport function tableCall(frame: GraphicFrame, table: Table, ctx: MapContext): CallIr | null {\n\tconst { notes } = ctx\n\tconst box = frameOf(frame, notes)\n\tif (!box) return null\n\tconst styleId = table.styleId\n\tconst hasStyle = table.resolvedStyle !== null\n\tconst rows: IrValue[] = []\n\tconst rowHeights: number[] = []\n\n\tfor (const row of table.rows) {\n\t\tconst cells: IrValue[] = []\n\t\tfor (const cell of row.cells) {\n\t\t\t// A merge continuation is the covered half of a span: it carries no content and\n\t\t\t// exists only so the grid stays rectangular. The write path derives those from\n\t\t\t// colspan/rowspan, so emitting them would double-count the span.\n\t\t\tif (cell.isMergeContinuation) continue\n\t\t\tcells.push(cellIr(cell, hasStyle, ctx))\n\t\t}\n\t\trows.push(cells)\n\t\trowHeights.push(row.heightEmu ?? 0)\n\t}\n\n\t// A row of height 0 is PowerPoint's \"auto — as tall as its content needs\", not a\n\t// zero-height row, and neither the mixed nor the all-auto case survives the write path.\n\t// Nothing is visibly wrong either way; what is lost is the *implicitness*, which matters\n\t// the moment someone edits a cell and expects the row to grow.\n\t//\n\t// The all-auto case is the more common of the two — a table authored without explicit row\n\t// heights has `a:tr/@h=\"0\"` on every row — and it went undeclared for longer precisely\n\t// because it looks like the harmless one. It is the case where `rowH` is omitted entirely\n\t// below, and `addTable` then divides the frame height evenly rather than leaving the rows\n\t// auto, so three auto rows come back pinned to a third of the frame each.\n\tconst autoRows = rowHeights.filter((height) => height === 0).length\n\tif (autoRows === rowHeights.length && autoRows > 0) {\n\t\tnotes.note(\n\t\t\t'table.rowAuto',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t'every row is auto-height (a:tr/@h of 0), so no rowH is emitted and addTable divides the frame height evenly among the rows; the rows come back pinned to that even split rather than sized to their content'\n\t\t)\n\t} else if (autoRows > 0) {\n\t\tnotes.note(\n\t\t\t'table.rowAuto',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t'at least one row is auto-height (a:tr/@h of 0) while others are not; the auto rows are emitted as null in rowH, which pins nothing, so addTable gives each of them an even share of the table height rather than sizing it to its content'\n\t\t)\n\t}\n\n\tif (styleId === null) {\n\t\tnotes.note(\n\t\t\t'table.style',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t\"this table names no a:tableStyleId, so it takes the generated deck's default table style\"\n\t\t)\n\t}\n\n\tconst columnWidths = table.columnWidths\n\tconst options = compact({\n\t\t...positionOptions(box),\n\t\t...identityOptions(frame),\n\t\t// The source GUID resolves against the destination's own tableStyles.xml, which a\n\t\t// template-anchored output carries over intact.\n\t\ttableStyle: orUndefined(styleId),\n\t\t// `tableFill`, not `fill`: the source has one fill on `a:tblPr`, and `fill` would\n\t\t// flatten it into a copy on every cell, which is a different package for the same\n\t\t// picture. See `TableProps.tableFill`.\n\t\ttableFill: tableFill(table, ctx),\n\t\t// All six Table Style Options, not the two the read model used to expose: each decides\n\t\t// which region of the table style paints, and a missing one is a differently styled table.\n\t\thasHeader: table.firstRowHeader ? true : undefined,\n\t\thasFooter: table.lastRowFooter ? true : undefined,\n\t\thasBandedRows: table.bandedRows ? true : undefined,\n\t\thasBandedColumns: table.bandedColumns ? true : undefined,\n\t\thasFirstColumn: table.firstColumnHeader ? true : undefined,\n\t\thasLastColumn: table.lastColumnFooter ? true : undefined,\n\t\tcolW: columnWidths.every((w) => w === null) ? undefined : columnWidths.map((w) => inches(w ?? 0)),\n\t\t// An auto row among fixed ones is `null`, the silent spelling of an unpinned row. It used to be\n\t\t// `0`, which `addTable` rejects as not a height, with a `table/invalid-row-height` warning.\n\t\trowH: rowHeights.every((h) => h === 0) ? undefined : rowHeights.map((h) => (h === 0 ? null : inches(h))),\n\t})\n\n\treturn { method: 'addTable', args: [rows, options ?? {}], ...nameOf(frame) }\n}\n\n/**\n * The table's own background (`a:tblPr` fill).\n *\n * Simpler than {@link cellFill}, and for one reason: a `a:tblPr` fill can only be the\n * table's own. There is no style graph feeding into it, so there is no\n * own-versus-inherited ambiguity to be careful about and the resolved colour can be used\n * directly. A scheme token still wins over the literal when there is one, so the replica\n * keeps tracking its theme.\n */\nfunction tableFill(table: Table, ctx: MapContext): IrValue | undefined {\n\treturn surfaceFill(table, ctx, 'table.fill')\n}\n\n/**\n * One cell as a `TableCell`.\n *\n * Cell text reuses the shape text mapper, so a per-run format inside a cell behaves\n * identically to one on a shape — the read model already shares `TextFrame` between the\n * two, and diverging here would be a difference with no cause.\n */\nfunction cellIr(cell: TableCell, hasStyle: boolean, ctx: MapContext): IrValue {\n\tconst { notes } = ctx\n\tconst frame = cell.textFrame\n\tconst anchor = cell.anchor\n\tconst margins = cell.marginsEmu\n\n\t// `a:tc/@id` and `a:tcPr/a:headers` are the one pair here that is *deliberately* not\n\t// mapped. PowerPoint strips both on save (probe:\n\t// `test/read/fixtures/authoring/probe-table-cell-a11y-and-3d.ps1`), so there is no write\n\t// option to map them to and adding one would ship a feature that dies on the first save.\n\t// A source deck from another producer can still carry them, so the loss is recorded.\n\tif (cell.id !== null || cell.headerIds.length > 0) {\n\t\tnotes.note(\n\t\t\t'table.cell.headers',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'this cell carries a screen-reader header association (a:tc/@id / a:tcPr/a:headers); PowerPoint strips both on save, so there is no write option and the association is lost — hasHeader (a:tblPr/@firstRow) is the marker that survives'\n\t\t)\n\t}\n\tif (frame) noteUnreadText(frame, cell.element_, notes, 'cell')\n\n\tconst options = compact({\n\t\tfill: cellFill(cell, hasStyle, ctx),\n\t\tborder: cellBorders(cell, notes),\n\t\tdiagonal: cellDiagonals(cell, notes),\n\t\tanchorCtr: cell.anchorCtr ? true : undefined,\n\t\tcell3D: cellThreeD(cell),\n\t\tvalign: anchor === null ? undefined : ANCHOR_TO_VALIGN[anchor],\n\t\t// `textDirection` reaches `a:tcPr/@vert` through the same table-cell inheritance list every\n\t\t// other cell option uses, so a vertical label survives the round trip. Anything outside the\n\t\t// option's own union would be written back out verbatim as an invalid attribute.\n\t\ttextDirection: cellTextDirection(cell, notes),\n\t\t// Only the two values the write option accepts survive; anything else in the source\n\t\t// deck would be written straight back out as an invalid attribute.\n\t\thorzOverflow: cell.horzOverflow === 'clip' || cell.horzOverflow === 'overflow' ? cell.horzOverflow : undefined,\n\t\tcolspan: cell.gridSpan > 1 ? cell.gridSpan : undefined,\n\t\trowspan: cell.rowSpan > 1 ? cell.rowSpan : undefined,\n\t\t// `margin` takes inches, and the read model reports the insets in EMU. A side the cell does\n\t\t// not state takes the schema default, not zero: `<a:tcPr marL=\"0\">` is a cell with no left\n\t\t// inset and the default 0.05in/0.1in on the other three, and filling those with 0 wrote a\n\t\t// cell with no insets at all.\n\t\tmargin: margins\n\t\t\t? [\n\t\t\t\t\tinches(margins.top ?? TABLE_CELL_MARGIN_DEFAULTS_EMU.top),\n\t\t\t\t\tinches(margins.right ?? TABLE_CELL_MARGIN_DEFAULTS_EMU.right),\n\t\t\t\t\tinches(margins.bottom ?? TABLE_CELL_MARGIN_DEFAULTS_EMU.bottom),\n\t\t\t\t\tinches(margins.left ?? TABLE_CELL_MARGIN_DEFAULTS_EMU.left),\n\t\t\t\t]\n\t\t\t: undefined,\n\t\t// A cell's own runs may each carry formatting; the first run's options double as the\n\t\t// cell default, which is how the write path applies cell-level character formatting.\n\t\t...(frame?.paragraphs[0]?.runs[0] ? (runOptions(frame.paragraphs[0].runs[0], ctx) ?? {}) : {}),\n\t})\n\n\treturn compact({ text: frame ? textRuns(frame, ctx) : cell.text, options }) ?? { text: '' }\n}\n\n/**\n * The two corner-to-corner rules as `TableCellProps.diagonal`.\n *\n * Kept out of {@link cellBorders}' tuple for the same reason the write option is: they are\n * not edges. Every dash and colour a diagonal can carry is one an edge can, so they share\n * {@link borderIr} — including its out-of-enum dash note.\n */\nfunction cellDiagonals(cell: TableCell, notes: NoteScope): IrValue | undefined {\n\tconst borders = cell.borders\n\tif (!borders || (!borders.tlToBr && !borders.blToTr)) return undefined\n\treturn compact({\n\t\ttlToBr: borders.tlToBr ? borderIr(borders.tlToBr, notes) : undefined,\n\t\tblToTr: borders.blToTr ? borderIr(borders.blToTr, notes) : undefined,\n\t})\n}\n\n/**\n * A cell's `a:cell3D` as `TableCellProps.cell3D`.\n *\n * Every field is passed through as read: the write path vets each against its `ST_` union\n * before emission, so a value from a source deck that somehow falls outside one is caught\n * there rather than being screened twice with two chances to disagree. Sizes are already in\n * points on both sides.\n */\nfunction cellThreeD(cell: TableCell): IrValue | undefined {\n\tconst cell3D = cell.cell3D\n\tif (!cell3D) return undefined\n\tconst rig = cell3D.lightRig\n\treturn (\n\t\tcompact({\n\t\t\tpreset: orUndefined(cell3D.bevel.preset),\n\t\t\twidth: orUndefined(cell3D.bevel.widthPt),\n\t\t\theight: orUndefined(cell3D.bevel.heightPt),\n\t\t\tmaterial: orUndefined(cell3D.material),\n\t\t\t// CT_LightRig requires both, so a half-specified one from a source deck is dropped\n\t\t\t// rather than passed on for the emitter to reject.\n\t\t\tlightRig: rig?.rig && rig.dir ? { rig: rig.rig, dir: rig.dir } : undefined,\n\t\t}) ?? {}\n\t)\n}\n\n/**\n * The `ST_TextVerticalType` values `TextBaseProps.textDirection` accepts, as a `Record` over that\n * union so the compiler catches a direction either side gains.\n */\nconst WRITABLE_TEXT_DIRECTIONS: Record<NonNullable<TextBaseProps['textDirection']>, true> = {\n\thorz: true,\n\tvert: true,\n\tvert270: true,\n\twordArtVert: true,\n}\n\n/**\n * A cell's `a:tcPr/@vert` as the write API's `textDirection`.\n *\n * `ST_TextVerticalType` has seven values and the write option covers four. The other three\n * (`eaVert`, `mongolianVert` and `wordArtVertRtl`) are East-Asian and right-to-left layout\n * modes with no `TextBaseProps` spelling, so they are noted rather than written — passing\n * one straight through would put a value the option does not admit into the attribute.\n */\nfunction cellTextDirection(cell: TableCell, notes: NoteScope): IrValue | undefined {\n\tconst vert = cell.verticalText\n\tif (vert === null || vert === 'horz') return undefined\n\tif (Object.hasOwn(WRITABLE_TEXT_DIRECTIONS, vert)) return vert\n\tnotes.note(\n\t\t'table.cell.vert',\n\t\t'dropped',\n\t\t'unwritable',\n\t\t`this cell's a:tcPr/@vert is \\`${vert}\\`, which textDirection does not spell (it covers horz/vert/vert270/wordArtVert), so its text lands horizontal`\n\t)\n\treturn undefined\n}\n\n/**\n * A cell's fill.\n *\n * The question here is not \"what colour is this cell\" but \"what did the *source* say\", and\n * the two differ for a styled table: `resolvedFill` answers the first, folding the cell's\n * own `a:solidFill` together with the colour it merely inherits from the style's\n * header/banding rules. Writing an inherited colour back would turn every banded cell into\n * an explicitly-filled one — the copy looks right until someone changes its table style, and\n * then nothing moves.\n *\n * {@link TableCell.hasOwnFill} separates them: an `a:tcPr` either carries an\n * `EG_FillProperties` child or it does not. So a cell's own fill is emitted (in whatever\n * form it took), and a cell with none is left to the style GUID, which reproduces the\n * banding exactly rather than approximately. Neither case loses anything, which is why\n * neither records a note.\n */\nfunction cellFill(cell: TableCell, hasStyle: boolean, ctx: MapContext): IrValue | undefined {\n\treturn surfaceFill(cell, ctx, 'table.cell.fill', { styled: hasStyle })\n}\n\n/**\n * The four edge borders as the write API's `[top, right, bottom, left]` tuple.\n *\n * A suppressed edge (`a:noFill`) becomes `type: 'none'`, which is distinct from an absent\n * one — the first means \"deliberately no rule here\", the second means \"inherit\". The two\n * diagonals the read model also decodes are carried separately, by {@link cellDiagonals}.\n */\nfunction cellBorders(cell: TableCell, notes: NoteScope): IrValue | undefined {\n\tconst borders = cell.borders\n\tif (!borders) return undefined\n\n\tconst edges = [borders.top, borders.right, borders.bottom, borders.left]\n\tif (edges.every((edge) => edge === null)) return undefined\n\n\treturn edges.map((edge) => borderIr(edge, notes))\n}\n\n/**\n * One decoded edge (or diagonal) as `BorderProps`.\n *\n * `type` stays the coarse on/off switch and `dashType` carries the exact preset, so a\n * `lgDashDot` rule comes back as itself rather than as the generic `sysDash` every dash\n * used to collapse onto. A dash outside `ST_PresetLineDashVal` cannot have come from a\n * conformant deck, so it is dropped to a plain dashed rule and noted.\n */\nfunction borderIr(edge: CellBorder | null, notes: NoteScope): IrValue {\n\tif (!edge) return {}\n\tif (edge.noFill) return { type: 'none' }\n\tconst dash = edge.dash\n\tconst known = dash === null || WRITABLE_DASHES.has(dash)\n\tif (!known) {\n\t\tnotes.note(\n\t\t\t'table.cell.borders.dash',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t`a cell border's a:prstDash/@val is \\`${dash}\\`, which is outside ST_PresetLineDashVal; it is written as a plain dashed rule`\n\t\t)\n\t}\n\treturn (\n\t\tcompact({\n\t\t\ttype: dash === null || dash === 'solid' ? 'solid' : 'dash',\n\t\t\t// `solid` is what an absent/solid dash already implies, so emitting it would be noise.\n\t\t\tdashType: known && dash !== null && dash !== 'solid' ? dash : undefined,\n\t\t\tcolor: colorOption(\n\t\t\t\t{ scheme: edge.colorRef.scheme, resolvedHex: edge.colorRef.resolved?.effectiveHex ?? null },\n\t\t\t\tnotes,\n\t\t\t\t'table.cell.borders.schemeToken',\n\t\t\t\t'cell border'\n\t\t\t),\n\t\t\twidth: orUndefined(edge.widthPt),\n\t\t}) ?? {}\n\t)\n}\n","/**\n * `Chart` → `addChart(OptsChartData[], ChartOpts)`.\n *\n * The open question this mapper settles is where the data comes from. A `.pptx` chart\n * carries its numbers twice: once in an embedded `.xlsx` workbook, and once as *cached*\n * values inside the chart XML itself (`c:tx`, `c:cat`, `c:val`) so a viewer can render\n * without opening the workbook. Probing the fixtures showed the cache is complete for\n * every chart the write API can express, so the workbook never needs cracking — which\n * removes a whole spreadsheet parser from this project's dependency surface.\n *\n * The one seam is blanks. The read model reports `(number | null)[]`, since a cached point\n * may legitimately be empty, while `OptsChartData.values` is `number[]`. A blank becomes\n * `0`, which is a visible change on a line chart — a gap turns into a dip to the axis — so\n * it is noted rather than quietly coerced.\n *\n * A rebuilt chart also gets a *regenerated* workbook rather than the source one, so\n * double-clicking it in PowerPoint opens data that matches the plot but has lost the source\n * sheet's formulas, extra columns, and formatting.\n */\nimport type { Chart, ChartSeries } from '../../read/api/chart.js'\nimport type { GraphicFrame } from '../../read/api/shapes.js'\nimport type { NoteScope } from '../fidelity.js'\nimport type { CallIr, IrValue } from '../ir.js'\nimport { compact, frameOf, identityOptions, literalColor, nameOf, orUndefined, positionOptions } from './values.js'\n\n/**\n * Read chart-group token → `CHART_NAME`. The read model strips the `Chart` suffix from the\n * plot-area element name, so `c:barChart` arrives as `bar`. A 3-D group maps onto the\n * matching flat type where one exists; anything absent from this table has no write-API\n * chart type and is reported rather than guessed at.\n */\nconst CHART_TYPE: Record<string, string> = {\n\tarea: 'area',\n\tarea3D: 'area',\n\tbar: 'bar',\n\tbar3D: 'bar3D',\n\tbubble: 'bubble',\n\tbubble3D: 'bubble3D',\n\tdoughnut: 'doughnut',\n\tline: 'line',\n\tline3D: 'line',\n\tpie: 'pie',\n\tpie3D: 'pie',\n\tradar: 'radar',\n\tscatter: 'scatter',\n\tstock: 'stock',\n\tsurface: 'surface',\n\tsurface3D: 'surface',\n}\n\n/**\n * The 3-D groups rebuilt flat, because the write API has no 3-D type for them. `bar3D` and\n * `bubble3D` keep their own, and a 3-D surface is what the write side's `surface` already draws.\n */\nconst FLATTENED_3D: ReadonlySet<string> = new Set(['area3D', 'line3D', 'pie3D'])\n\n/**\n * The plot types whose `showLabel` writes the category name. A scatter's writes nothing unless a\n * `dataLabelFormatScatter` is also set, so a scatter is not among them.\n */\nconst CATEGORY_NAME_TYPES: ReadonlySet<string> = new Set(['doughnut', 'pie'])\n\n/**\n * The plot types that pair every value with an X value of its own (`c:xVal` and `c:yVal`, plus\n * `c:bubbleSize` on a bubble) rather than with a category. `addChart` spells them as a leading row\n * of X values followed by one row per series.\n */\nconst XY_TYPES: ReadonlySet<string> = new Set(['bubble', 'bubble3D', 'scatter'])\n\n/** `c:legendPos/@val` → the write API's `legendPos`. */\nconst LEGEND_POS: Record<string, string> = { r: 'r', l: 'l', t: 't', b: 'b', tr: 'tr' }\n\nexport function chartCall(frame: GraphicFrame, chart: Chart, notes: NoteScope): CallIr | null {\n\tconst box = frameOf(frame, notes)\n\tif (!box) return null\n\tconst sourceType = chart.chartType\n\tconst type = sourceType === null ? undefined : CHART_TYPE[sourceType]\n\tif (!type) {\n\t\tnotes.note(\n\t\t\t'chart.type',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t`chart type \"${sourceType ?? 'none'}\" has no write-API counterpart, so the chart is omitted`\n\t\t)\n\t\treturn null\n\t}\n\n\tif (sourceType !== null && FLATTENED_3D.has(sourceType)) {\n\t\tnotes.note(\n\t\t\t'chart.type3D',\n\t\t\t'flattened',\n\t\t\t'unwritable',\n\t\t\t`a 3-D ${type} chart (c:${sourceType}Chart) is rebuilt as a flat ${type} chart: the write API has no 3-D ${type} type, so its depth, rotation and perspective are gone`\n\t\t)\n\t}\n\n\tif (chart.chartTypes.length > 1) {\n\t\tnotes.note(\n\t\t\t'chart.combo',\n\t\t\t'flattened',\n\t\t\t'unsupported',\n\t\t\t`a combo chart (${chart.chartTypes.join(' + ')}) is emitted as a single ${type} chart; addChart's multi-type form needs a per-series type the read model does not report`\n\t\t)\n\t}\n\n\tconst xy = XY_TYPES.has(type)\n\tconst data = xy ? xyData(chart, type, notes) : seriesData(chart, notes)\n\t// Series that all read no points plot nothing either. `addChart` would draw an empty frame the\n\t// source never showed as a chart, and checking only for zero series let those through.\n\tif (data.length === 0 || chart.series.every((series) => (xy ? series.yValues : series.values).length === 0)) {\n\t\tnotes.note('chart.data', 'dropped', 'unsupported', 'this chart caches no plottable series values')\n\t\treturn null\n\t}\n\n\t// BELOW the guard above, deliberately. Recorded unconditionally, a chart with no cached\n\t// series emitted two notes — one saying it was dropped, one saying it was rebuilt — and this\n\t// one maps to `['*']`, so on a dropped chart it also excused every difference on that frame:\n\t// the widest exclusion in the table, applied to the case it least describes.\n\tnotes.note(\n\t\t'chart.workbook',\n\t\t'approximated',\n\t\t'unsupported',\n\t\t\"the chart is rebuilt from its cached plot values, so its embedded workbook is regenerated: the plotted numbers match, but the source sheet's formulas, extra columns and formatting are gone\"\n\t)\n\n\t// `type` is an *option*, not a positional argument: the signature is\n\t// `addChart(data, options & { type })`. Passing it separately produces a call that\n\t// typechecks nowhere and throws \"a chart `type` is required\" at run time.\n\tconst options = compact({\n\t\ttype,\n\t\t// `c:surfaceChart` is the 2-D contour; the write side's `surface` draws the 3-D one unless told\n\t\t// otherwise, so a flat surface came back tilted.\n\t\tsurface3D: sourceType === 'surface' ? false : undefined,\n\t\t...positionOptions(box),\n\t\t...identityOptions(frame),\n\t\t...titleOptions(chart),\n\t\t...legendOptions(chart),\n\t\t...labelOptions(chart, type, notes),\n\t\t...axisOptions(chart),\n\t\tchartColors: seriesColors(chart),\n\t})\n\n\treturn {\n\t\tmethod: 'addChart',\n\t\targs: [data, options ?? { type }],\n\t\t...nameOf(frame),\n\t}\n}\n\n/**\n * Series as `OptsChartData[]`. Category labels ride on the first series, which is the shape\n * `addChart` expects; the read model reports them per-series but they are shared in\n * practice.\n */\nfunction seriesData(chart: Chart, notes: NoteScope): IrValue[] {\n\t// Leaf level first, which is also how `OptsChartData.labels` takes several levels. An outer\n\t// level names each group once, and the writer spells the rest of the group as `''`.\n\tconst levels = chart.categoryLevels.map((level) => level.map((label) => label ?? ''))\n\tconst labels = levels.length > 1 ? levels : levels[0]\n\tconst dense = blanksToZero(notes)\n\n\treturn chart.series.map((series, index) => {\n\t\tconst values = dense(series.values)\n\t\treturn (\n\t\t\tcompact({\n\t\t\t\tname: orUndefined(series.name),\n\t\t\t\tvalues,\n\t\t\t\t// Only the first series carries labels, matching how addChart reads them.\n\t\t\t\tlabels: index === 0 && levels[0]?.length ? labels : undefined,\n\t\t\t}) ?? { values }\n\t\t)\n\t})\n}\n\n/**\n * A scatter or bubble chart as `OptsChartData[]`: the X row, then one row per series with its Y\n * values and, on a bubble, its sizes. The X row is not a series and has no name in the chart part;\n * its column header lives only in the workbook, which is regenerated anyway.\n *\n * `addChart` plots every series against that one X row, while a chart part gives each series a\n * `c:xVal` of its own. The first series' X values are taken, and a series whose own differ is noted.\n * @param type - the write-API chart type the chart is rebuilt as\n */\nfunction xyData(chart: Chart, type: string, notes: NoteScope): IrValue[] {\n\tconst series = chart.series\n\tconst first = series[0]\n\tif (!first) return []\n\tconst dense = blanksToZero(notes)\n\tconst xValues = plottedX(first)\n\tconst withSizes = type !== 'scatter'\n\n\tconst rows: IrValue[] = [{ values: dense(xValues) }]\n\tlet ownX = false\n\tfor (const one of series) {\n\t\tconst own = plottedX(one)\n\t\tif (own.length !== xValues.length || own.some((value, i) => value !== xValues[i])) ownX = true\n\t\tconst values = dense(one.yValues)\n\t\trows.push(\n\t\t\tcompact({\n\t\t\t\tname: orUndefined(one.name),\n\t\t\t\tvalues,\n\t\t\t\tsizes: withSizes ? dense(one.bubbleSizes) : undefined,\n\t\t\t}) ?? { values }\n\t\t)\n\t}\n\n\tif (ownX) {\n\t\tnotes.note(\n\t\t\t'chart.xValues',\n\t\t\t'approximated',\n\t\t\t'unwritable',\n\t\t\t`the series of this ${type} chart do not share one set of X values, and addChart plots every series against a single X row, so each is rebuilt against the first series' X values`\n\t\t)\n\t}\n\tif (series.some((one) => one.xLabels !== null)) {\n\t\tnotes.note(\n\t\t\t'chart.xLabels',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t`this ${type} chart is plotted against text X labels, which PowerPoint places at 1 to n in point order; it is rebuilt against those positions and plots the same, but addChart takes numbers for its X row, so the labels are gone`\n\t\t)\n\t}\n\treturn rows\n}\n\n/**\n * The X coordinates a series is plotted at. A series plotted against text has none of its own, and\n * neither has a series with no `c:xVal`: PowerPoint places the points of both at 1 to n, and an X row\n * of those positions draws the same chart. Taking the X values instead turned every label into a\n * blank and the blank into a 0, and gave a series with no `c:xVal` an empty X row, against which\n * `addChart` plots no point at all.\n */\nfunction plottedX(series: ChartSeries): (number | null)[] {\n\tconst labels = series.xLabels\n\tif (labels !== null) return positions(labels.length)\n\tconst xValues = series.xValues\n\treturn xValues.length === 0 ? positions(series.yValues.length) : xValues\n}\n\n/** The positions 1 to `count`. */\nfunction positions(count: number): number[] {\n\treturn Array.from({ length: count }, (_unused, i) => i + 1)\n}\n\n/**\n * Densify cached points for `number[]`, noting once per chart when a blank had to become 0.\n * The returned function is called once per point list, and the note is recorded on the first blank.\n */\nfunction blanksToZero(notes: NoteScope): (points: (number | null)[]) => number[] {\n\tlet noted = false\n\treturn (points) =>\n\t\tpoints.map((value) => {\n\t\t\tif (value !== null) return value\n\t\t\tif (!noted) {\n\t\t\t\tnoted = true\n\t\t\t\tnotes.note(\n\t\t\t\t\t'chart.blanks',\n\t\t\t\t\t'approximated',\n\t\t\t\t\t'unwritable',\n\t\t\t\t\t'a blank cached data point becomes 0, because OptsChartData.values is number[] and has no spelling for a gap; on a line chart this draws a dip to the axis where the source showed a break'\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn 0\n\t\t})\n}\n\nfunction titleOptions(chart: Chart): Record<string, IrValue | undefined> {\n\tconst title = chart.title\n\treturn title === null ? {} : { showTitle: true, title }\n}\n\nfunction legendOptions(chart: Chart): Record<string, IrValue | undefined> {\n\tconst legend = chart.legend\n\tif (!legend) return { showLegend: false }\n\treturn {\n\t\tshowLegend: true,\n\t\tlegendPos: legend.position === null ? undefined : LEGEND_POS[legend.position],\n\t}\n}\n\n/**\n * Data-label flags as `ChartOpts`.\n *\n * Two of the read model's flags have no key of their own on the write side, and they were emitted\n * as `showCatName` and `showLegendKey` anyway. Neither is a `ChartOpts` key, so the writer ignored\n * both and nothing said so. `ChartOpts` spells the category name `showLabel`, which a pie and a\n * doughnut write as one; nothing spells the legend-key swatch.\n *\n * A pie and a doughnut are read from the series' own block. PowerPoint writes the flags the user set\n * there and an all-off block for the group, so reading the group block rebuilt a labelled pie\n * without its labels.\n * @param type - the write-API chart type the chart is rebuilt as\n */\nfunction labelOptions(chart: Chart, type: string, notes: NoteScope): Record<string, IrValue | undefined> {\n\tconst carriesCategoryName = CATEGORY_NAME_TYPES.has(type)\n\tconst labels = (carriesCategoryName ? chart.series[0]?.dataLabels : null) ?? chart.dataLabels\n\tif (!labels) return {}\n\n\tif (labels.showLegendKey === true) {\n\t\tnotes.note(\n\t\t\t'chart.labels',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'the data labels show the legend key swatch (c:showLegendKey), which no ChartOpts option spells, so the labels come back without it'\n\t\t)\n\t}\n\tif (labels.showCategoryName === true && !carriesCategoryName) {\n\t\tnotes.note(\n\t\t\t'chart.labels',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t`the data labels show the category name (c:showCatName); ChartOpts spells that showLabel, which only a pie and a doughnut write as the category name, so on this ${type} chart the labels come back without it`\n\t\t)\n\t}\n\n\treturn {\n\t\tshowValue: labels.showValue ?? undefined,\n\t\tshowSerName: labels.showSeriesName ?? undefined,\n\t\tshowLabel: carriesCategoryName ? (labels.showCategoryName ?? undefined) : undefined,\n\t\tshowPercent: labels.showPercent ?? undefined,\n\t\tshowLeaderLines: labels.showLeaderLines ?? undefined,\n\t\t// A pie's labels with no `c:dLblPos` sit at best fit (PowerPoint reports\n\t\t// `xlLabelPositionBestFit` for them), and the writer spells an unset pie position `ctr`.\n\t\tdataLabelPosition: orUndefined(labels.position) ?? (type === 'pie' ? 'bestFit' : undefined),\n\t\tdataLabelFormatCode: labels.numberFormat?.formatCode ?? undefined,\n\t}\n}\n\n/**\n * Axis bounds, titles and gridlines. The write API spells these as a flat `catAxis*` /\n * `valAxis*` prefix set rather than an axis object, so each side is unpacked by hand.\n */\nfunction axisOptions(chart: Chart): Record<string, IrValue | undefined> {\n\tconst cat = chart.categoryAxis\n\tconst val = chart.valueAxis\n\treturn {\n\t\tcatAxisHidden: cat?.hidden ? true : undefined,\n\t\tcatAxisTitle: cat?.title ?? undefined,\n\t\tvalAxisHidden: val?.hidden ? true : undefined,\n\t\tvalAxisTitle: val?.title ?? undefined,\n\t\tvalAxisMinVal: val?.min ?? undefined,\n\t\tvalAxisMaxVal: val?.max ?? undefined,\n\t\tvalAxisMajorUnit: val?.majorUnit ?? undefined,\n\t\tvalAxisLabelFormatCode: val?.numberFormat?.formatCode ?? undefined,\n\t}\n}\n\n/**\n * Per-series fill colours as `chartColors`, which is positional — entry `n` colours series\n * `n`. A series with no explicit fill takes the theme's accent for its position, which the\n * read model does not resolve, so the whole option is dropped unless every series names a\n * colour; a partial list would silently recolour the unnamed ones.\n */\nfunction seriesColors(chart: Chart): IrValue | undefined {\n\tconst series = chart.series\n\tif (series.length === 0) return undefined\n\tconst colors: string[] = []\n\tfor (const one of series) {\n\t\tconst fill = one.fill\n\t\tconst hex = fill?.colorRef.srgb\n\t\tif (!hex) return undefined\n\t\tcolors.push(literalColor(hex))\n\t}\n\treturn colors\n}\n","/**\n * ts-pptx: the two things every read-side mapper needs, in one parameter.\n *\n * A mapper records what it could not carry (`notes`) and registers the bytes it references\n * (`assets`), and the pair was threaded positionally through about twenty signatures — several\n * of which had already grown a third and fourth parameter around them. A pair that always\n * travels together and is never split is one argument.\n *\n * `AssetResolver` lives here rather than in `shape.ts` for the same reason: it is a contract\n * between the deck-level walk and every mapper, not part of the shape mapper, and putting it\n * beside the context keeps `context.ts` a leaf that the mappers can all import.\n */\n\nimport type { AssetRef } from '../ir.js'\nimport type { NoteScope } from '../fidelity.js'\n\n/** Resolves an image/media part name to bytes the deck-level walk has registered. */\nexport interface AssetResolver {\n\t/** Register a part's bytes and hand back the reference that stands in for them. */\n\tassetFor(partName: string): AssetRef | null\n\t/**\n\t * The part's content type, or `null` when it is not in the package.\n\t *\n\t * Separate from {@link assetFor} because it has to be answerable *without* registering\n\t * anything: a caller that rejects a part on its type (a picture fill's SVG blip, which\n\t * the write path refuses) would otherwise leave bytes in the asset list that no call\n\t * references, and those bytes are emitted as a file next to the script.\n\t */\n\tcontentTypeOf(partName: string): string | null\n}\n\n/** What every `from-read/` mapper is handed alongside the thing it is mapping. */\nexport interface MapContext {\n\t/** Where a loss this mapper cannot avoid is recorded. */\n\treadonly notes: NoteScope\n\t/** How a referenced part's bytes become an asset the emitted script can carry. */\n\treadonly assets: AssetResolver\n\t/**\n\t * The 1-based number of the slide at `partName` in the deck being converted, or `null` when it is\n\t * not one of the deck's slides, or when the shapes being mapped cannot link to a slide at all: a\n\t * layout's shapes are re-authored under `defineSlideMaster`, where a slide link does not resolve.\n\t */\n\treadonly slideNumberOf: (partName: string) => number | null\n}\n\n/**\n * The same context, with its notes bound to one shape.\n *\n * A note recorded through the result names that shape, which is what lets a reader of the\n * emitted script find the shape a loss belongs to. Callers used to re-derive this inline as\n * `notes.forShape(shape.name || null)`, sometimes twice in one function and once in a callee\n * that already had a scoped one.\n *\n * An unnamed shape scopes to `''`, not `null`. `null` is how a slide or deck note is scoped, and\n * the round trip matches such a note's fields from the root of the diff, where a shape's\n * `line.width` is never found, so a correctly noted loss on an unnamed shape was reported as\n * undeclared.\n * @param ctx - the enclosing context\n * @param shape - the shape to scope to; an unnamed one scopes to `''`\n */\nexport function forShape(ctx: MapContext, shape: { name: string | null }): MapContext {\n\treturn { ...ctx, notes: ctx.notes.forShape(shape.name || '') }\n}\n","/**\n * The paint and placement a shape carries whatever kind it is: transform, fill, line, arrows,\n * shadow, glow, and the `p:style` tier behind them.\n *\n * Split out of `shape.ts`, where these sat above the five per-kind call builders and were\n * called by all of them. They are also where most of this converter's *fidelity notes* are\n * recorded, because the binding constraint is the read side: a shape whose outline comes from\n * `p:style/a:lnRef` reports a colour through `resolvedLine` and `null` for width and dash,\n * since there is a resolved-colour path and no resolved-width path. Each such loss is declared\n * here rather than quietly thinned.\n */\nimport type { AnyShape } from '../../read/api/shapes.js'\nimport type { NoteScope } from '../fidelity.js'\nimport { type IrValue } from '../ir.js'\nimport { LINE_END_TYPES } from '../../ooxml/st-enums.js'\nimport { LINE_CAP_BY_TOKEN } from '../../ooxml/line-cap.js'\nimport { alphaToTransparency, colorOption, compact, orUndefined, WRITABLE_DASHES } from './values.js'\nimport { type FillSubject, gradientStops, surfaceFill } from './surface-fill.js'\nimport { type MapContext } from './context.js'\n\n/** Arrowhead types `ShapeLineProps` accepts: every `ST_LineEndType`, the tokens `a:headEnd/@type` uses. */\nconst WRITABLE_ARROWS: ReadonlySet<string> = new Set<string>(LINE_END_TYPES)\n\n/**\n * `p:cNvPr/@hidden` has no write-API counterpart, so a hidden shape would come back visible.\n * Omitting it preserves what the deck looks like, which is the lesser loss. Shared with the\n * layout-decoration mapper below, whose connector arm does not pass through {@link shapeCall}.\n */\nexport function noteHidden(notes: NoteScope): void {\n\tnotes.note(\n\t\t'shape.hidden',\n\t\t'dropped',\n\t\t'unwritable',\n\t\t'a hidden shape has no write-API expression; it is omitted rather than emitted visible'\n\t)\n}\n\n/* ===== position, fill, line, effects — shared by every shape kind ===== */\n\n/**\n * Rotation and flips. Taken from `absoluteFrame`, which composes enclosing group rotations\n * and XOR-composes group flips — the same reason position is absolute.\n */\nexport function transformOptions(shape: AnyShape): Record<string, IrValue | undefined> {\n\tconst frame = shape.absoluteFrame\n\tconst rotate = frame ? frame.rotation : (shape.rotation ?? 0)\n\treturn {\n\t\trotate: rotate === 0 ? undefined : rotate,\n\t\tflipH: (frame?.flipH ?? shape.flipH) ? true : undefined,\n\t\tflipV: (frame?.flipV ?? shape.flipV) ? true : undefined,\n\t}\n}\n\n/**\n * A shape's fill as `ShapeFillProps`.\n *\n * Prefers the raw scheme token over `resolvedFill` for the same reason run colour does: a\n * token keeps tracking the destination theme. `resolvedFill` is the fallback because it is\n * the only accessor that sees a `p:style/a:fillRef` — a shape styled entirely from the\n * theme has no `a:solidFill` of its own, so without it the shape would come out unfilled.\n */\nexport function fillOption(shape: AnyShape, ctx: MapContext): IrValue | undefined {\n\t// A shape has no explicit-noFill leg here: `lineOption` handles the stroke's, and a shape's\n\t// own `a:noFill` reaches the write side as an absent fill option, which is the same output.\n\treturn surfaceFill({ ...fillAccessors(shape), fillColor: shape.fillColor }, ctx, 'fill')\n}\n\n/**\n * The `EG_FillProperties` accessors {@link surfaceFill} reads, projected off a read-model shape.\n *\n * A projection rather than passing the shape itself: `AnyShape` is a union whose members carry\n * far more than this, and naming the six keys is what makes \"a shape, a table and a cell answer\n * the same six questions\" a checked statement rather than an observation.\n */\nfunction fillAccessors(shape: AnyShape): FillSubject {\n\treturn {\n\t\tgradientFill: shape.gradientFill,\n\t\tpatternFill: shape.patternFill,\n\t\tpictureFill: shape.pictureFill,\n\t\tfillSchemeColor: shape.fillSchemeColor,\n\t\tresolvedFill: shape.resolvedFill,\n\t}\n}\n\n/**\n * Everything about an outline that does not survive, noted.\n *\n * Three independent conditions, none of which decides any of `lineOption`'s emitted values --\n * they were interleaved with the option build, which is what made that function four\n * decisions wearing one name.\n *\n * @param values - the outline's already-read parts, so this does not re-read the DOM\n */\nfunction noteLineLosses(\n\tshape: AnyShape,\n\tvalues: {\n\t\twidthPt: number | null\n\t\tdash: string | null\n\t\tscheme: string | null\n\t\tresolved: { effectiveHex: string } | null\n\t},\n\tnotes: NoteScope\n): void {\n\tconst { widthPt, dash, scheme, resolved } = values\n\n\t// A colour only `resolvedLine` could supply means the stroke came from the theme style\n\t// list, whose width and dash are unreadable.\n\tif (resolved !== null && shape.lineColor === null && scheme === null && widthPt === null) {\n\t\tnotes.note(\n\t\t\t'line.width',\n\t\t\t'dropped',\n\t\t\t'unread',\n\t\t\t'this outline comes from the theme style list (p:style/a:lnRef); its width and dash live in the theme fmtScheme a:lnStyleLst, which has no accessor, so only the colour carries'\n\t\t)\n\t}\n\tif (dash !== null && !WRITABLE_DASHES.has(dash)) {\n\t\tnotes.note(\n\t\t\t'line.dash',\n\t\t\t'approximated',\n\t\t\t'unwritable',\n\t\t\t`dash style \"${dash}\" is outside the eight the write API accepts, so the outline falls back to solid`\n\t\t)\n\t}\n\t// `@algn` is the one outline attribute both sides can see and neither can carry: the read\n\t// model reports it (`lineAlign`) and `ShapeLineProps` has no option for it. Only `in` is\n\t// noted -- it insets the stroke by half its width, so it moves the border. `ctr` is what an\n\t// omitted `@algn` already renders as, so noting that would fire on most PowerPoint-authored\n\t// shapes while describing no loss at all.\n\tif (shape.lineAlign === 'in') {\n\t\tnotes.note(\n\t\t\t'line.align',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'this outline is inset (a:ln/@algn=\"in\", drawn wholly inside the shape); ShapeLineProps has no alignment option, so it comes back centred on the edge and sits half its width further out'\n\t\t)\n\t}\n}\n\n/**\n * A shape's outline as `ShapeLineProps`.\n *\n * This is where the measured silent loss lives. When a shape takes its outline from\n * `p:style/a:lnRef`, `resolvedLine` supplies the colour but `lineWidthPt` and `lineDash`\n * both report `null` — the theme's `a:lnStyleLst` entry, where the width and dash actually\n * live, has no accessor. Emitting the colour and noting the rest is the honest outcome;\n * inventing a width would be worse, because it would look deliberate.\n */\nexport function lineOption(shape: AnyShape, notes: NoteScope): Record<string, IrValue> | undefined {\n\tif (shape.lineNoFill) return { type: 'none' }\n\n\tconst gradient = shape.lineGradient\n\tif (gradient) {\n\t\tconst stops = gradientStops(gradient, notes, 'line')\n\t\tif (stops) return { type: 'gradient', gradient: stops }\n\t}\n\n\tconst widthPt = shape.lineWidthPt\n\tconst dash = shape.lineDash\n\tconst cap = shape.lineCap\n\tconst scheme = shape.lineSchemeColor\n\tconst resolved = shape.resolvedLine\n\n\t// The shared colour ladder: a writable token kept as a token, then the line's own literal, then\n\t// an unwritable token baked to what it resolves to. This kept its own copy of that ladder, and\n\t// the copy baked a token such as `dk1` or `hlink` without the note every other surface records.\n\tconst color = colorOption(\n\t\t{ scheme, ownHex: shape.lineColor, resolvedHex: resolved?.effectiveHex ?? null },\n\t\tnotes,\n\t\t'line.schemeToken',\n\t\t'outline'\n\t)\n\n\tnoteLineLosses(shape, { widthPt, dash, scheme, resolved }, notes)\n\n\tconst options = compact({\n\t\tcolor,\n\t\twidth: orUndefined(widthPt),\n\t\tdashType: dash !== null && WRITABLE_DASHES.has(dash) ? dash : undefined,\n\t\t// The read side reports the raw `a:ln/@cap` token (`AutoShape.lineCap`) and the write side\n\t\t// takes the friendly name that authors it.\n\t\tcap: cap === null ? undefined : LINE_CAP_BY_TOKEN[cap],\n\t\ttransparency: alphaToTransparency(resolved?.alpha),\n\t\t...arrowOptions(shape, notes),\n\t})\n\treturn options\n}\n\n/** Arrowheads. Types map directly; the `sm`/`med`/`lg` size classes have no option. */\nfunction arrowOptions(shape: AnyShape, notes: NoteScope): Record<string, IrValue | undefined> {\n\tconst ends = shape.lineEnds\n\tif (!ends) return {}\n\tconst sized = [ends.head, ends.tail].some((end) => end && (end.width !== null || end.length !== null))\n\tif (sized) {\n\t\tnotes.note(\n\t\t\t'line.arrowSize',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'arrowhead width and length classes (@w / @len) have no write-API option, so arrowheads render at the default size'\n\t\t)\n\t}\n\treturn {\n\t\tbeginArrowType: ends.head && WRITABLE_ARROWS.has(ends.head.type) ? ends.head.type : undefined,\n\t\tendArrowType: ends.tail && WRITABLE_ARROWS.has(ends.tail.type) ? ends.tail.type : undefined,\n\t}\n}\n\n/** Outer shadow as `ShadowProps`; an inner shadow uses the same option with `type: 'inner'`. */\nexport function shadowOption(shape: AnyShape, notes: NoteScope): IrValue | undefined {\n\tif (shape.reflection || shape.softEdge) {\n\t\tnotes.note(\n\t\t\t'shape.effects',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'a:reflection and a:softEdge are read but have no write-API emitter, so those effects are lost'\n\t\t)\n\t}\n\n\tconst outer = shape.shadow\n\tconst source = outer ?? shape.innerShadow\n\tif (!source) return undefined\n\n\treturn compact({\n\t\ttype: outer ? 'outer' : 'inner',\n\t\t// A shadow takes a scheme token too (`createColorElement` writes it as `a:schemeClr`), so a\n\t\t// writable one is kept and the copy keeps tracking its theme; this baked every token to hex.\n\t\tcolor: colorOption(\n\t\t\t{ scheme: source.colorRef.scheme, resolvedHex: source.colorRef.resolved?.effectiveHex ?? null },\n\t\t\tnotes,\n\t\t\t'shadow.schemeToken',\n\t\t\t'shadow'\n\t\t),\n\t\tblur: source.blurPt,\n\t\toffset: source.offsetPt,\n\t\tangle: source.angleDeg,\n\t\ttransparency: alphaToTransparency(source.colorRef.resolved?.alpha),\n\t})\n}\n\n/** Glow. The read model reports opacity as a 0–1 alpha, which is the write API's unit too. */\nexport function glowOption(shape: AnyShape, notes: NoteScope): IrValue | undefined {\n\tconst glow = shape.glow\n\tif (!glow) return undefined\n\treturn compact({\n\t\tsize: glow.radiusPt,\n\t\t// The same ladder as the shadow: a glow writes a scheme token as `a:schemeClr` as well.\n\t\tcolor: colorOption(\n\t\t\t{ scheme: glow.colorRef.scheme, resolvedHex: glow.colorRef.resolved?.effectiveHex ?? null },\n\t\t\tnotes,\n\t\t\t'glow.schemeToken',\n\t\t\t'glow'\n\t\t),\n\t\topacity: glow.colorRef.resolved?.alpha,\n\t})\n}\n\n/** The style block every shape kind shares. */\nexport function styleOptions(shape: AnyShape, ctx: MapContext): Record<string, IrValue | undefined> {\n\tconst { notes } = ctx\n\treturn {\n\t\tfill: fillOption(shape, ctx),\n\t\tline: lineOption(shape, notes),\n\t\tshadow: shadowOption(shape, notes),\n\t\tglow: glowOption(shape, notes),\n\t}\n}\n\n/* ===== per-kind mappers ===== */\n\n/**\n * An `AutoShape` becomes an `addShape` when it is bare geometry and an `addText` when it\n * carries text. A shape with both takes the `addText` form, because `addShape` has no text\n * argument while `addText` accepts a `shape` option — so only that form expresses both.\n */\n","/**\n * `AnyShape` → one {@link CallIr}.\n *\n * The dispatch is on what the shape *is*, not on what it looks like: an `AutoShape` with a\n * text frame and no geometry is an `addText`, one with geometry is an `addShape` that may\n * also carry text, a `Picture` is an `addImage`, and a `GraphicFrame` delegates to the\n * table or chart mapper. A `GroupShape` recurses.\n *\n * The single most important thing this module does is record what it cannot carry.\n * Measurement against the fixture corpus found the binding constraint is the *read* side,\n * not the write side — several constructs the write API can express have no accessor at\n * all — so a converter that mapped only what it could see would produce clean-looking\n * output with silent visual losses. The clearest is theme-referenced line styling: a shape\n * whose outline comes from `p:style/a:lnRef` reports a colour through `resolvedLine` but\n * reports `null` for width and dash, because there is a resolved-colour path and no\n * resolved-width path. In the corpus that was every such shape, so a themed 2pt\n * border silently becomes a 1pt default. Each one is noted here rather than quietly thinned.\n *\n * The same dispatch serves the deck's *chrome*: {@link masterObject} re-tags a call as an\n * entry in a `defineSlideMaster({ objects })` array, so a rectangle on a layout is transcribed\n * by the code that transcribes one on a slide. Sharing it is the point — a second mapper would\n * be a second set of decisions about the same OOXML, drifting from this one silently.\n */\nimport {\n\tisAutoShape,\n\tisConnector,\n\tisGraphicFrame,\n\tisGroupShape,\n\tisPicture,\n\ttype AnyShape,\n\ttype AutoShape,\n\ttype Connector,\n\ttype CustomGeometry,\n\ttype GraphicFrame,\n\ttype GroupShape,\n\ttype Picture,\n} from '../../read/api/shapes.js'\nimport { UNWRITABLE_FRAME_CONSTRUCTS, type NoteScope, type UnwritableFramePayload } from '../fidelity.js'\nimport { isAssetRef, type CallIr, type IrValue } from '../ir.js'\nimport type { ConnectorProps, ShapeLineProps } from '../../types/style.js'\nimport {\n\tcompact,\n\tcompactRequired,\n\temu,\n\tframeOf,\n\tidentityOptions,\n\tnameOf,\n\tpositionOptions,\n\ttype ShapeBox,\n} from './values.js'\nimport { hasIdentityChildSpace, isAudioVideo, isTextBox } from './detect.js'\nimport { noteUnreadText, shapeHyperlinkOption, textFrameOptions, textRuns } from './text.js'\nimport type { TextFrame } from '../../read/api/text.js'\nimport { tableCall } from './table.js'\nimport { chartCall } from './chart.js'\nimport { forShape, type MapContext } from './context.js'\nimport { cropOption, isRectSet } from './picture-fill.js'\nexport type { AssetResolver } from './context.js'\nimport { PERCENT_SCALE } from '../../units.js'\n\nimport { glowOption, lineOption, noteHidden, shadowOption, styleOptions, transformOptions } from './shape-paint.js'\n\n/**\n * Map one shape. Returns `null` when the shape produces no call at all — a note is always\n * recorded in that case, so a dropped shape is never silent.\n */\nexport function shapeCall(shape: AnyShape, ctx: MapContext): CallIr | null {\n\tconst scoped = forShape(ctx, shape)\n\n\tif (shape.hidden) {\n\t\tnoteHidden(scoped.notes)\n\t\treturn null\n\t}\n\n\tif (isGroupShape(shape)) return groupCall(shape, scoped)\n\tif (isPicture(shape)) return pictureCall(shape, scoped)\n\tif (isConnector(shape)) return connectorCall(shape, scoped.notes)\n\tif (isGraphicFrame(shape)) return graphicFrameCall(shape, scoped)\n\tif (isAutoShape(shape)) return autoShapeCall(shape, scoped)\n\n\t// Unreachable: the five guards above exhaust `AnyShape`, which is why `shape` narrows to\n\t// `never` here. Left as a floor so a sixth shape kind fails to compile at the call sites\n\t// that assume a call, rather than silently falling through to a silent drop.\n\treturn null\n}\n\n/**\n * The shape's authorable text, and the notes for what it holds that cannot be authored.\n *\n * \"Has text\" means text this converter can author, which is *runs*. `TextFrame.text` also\n * counts `a:fld` field text -- a slide number, date or footer placeholder -- and there is no\n * run behind it, so measuring by `text` made every field placeholder emit an `addText`\n * carrying a single empty string: an invisible empty box where a number used to be.\n *\n * Extracted from `autoShapeCall`, which inlined this alongside the placeholder note, the\n * common-option assembly and three mutually exclusive emission arms.\n * @returns the frame when it holds authorable runs, else `null`\n */\nfunction autoShapeText(shape: AutoShape, notes: NoteScope): TextFrame | null {\n\tconst frame = shape.hasTextFrame ? shape.textFrame : null\n\tif (frame === null) return null\n\treturn noteUnreadText(frame, shape.element_, notes, 'shape').length > 0 ? frame : null\n}\n\nfunction autoShapeCall(shape: AutoShape, ctx: MapContext): CallIr | null {\n\tconst { notes } = ctx\n\tconst box = frameOf(shape, notes)\n\tif (!box) return null\n\tconst preset = shape.presetGeometry\n\tconst custom = shape.customGeometry\n\tconst frame = autoShapeText(shape, notes)\n\n\tif (shape.placeholder) {\n\t\tnotes.note(\n\t\t\t'shape.placeholder',\n\t\t\t'flattened',\n\t\t\t'unsupported',\n\t\t\t'a placeholder is emitted as a plain shape with its inherited geometry and styling baked in, so it no longer follows its layout'\n\t\t)\n\t}\n\n\tconst common = {\n\t\t...positionOptions(box),\n\t\t...transformOptions(shape),\n\t\t...styleOptions(shape, ctx),\n\t\t...identityOptions(shape),\n\t\t// The shape's own `p:cNvPr/a:hlinkClick`, distinct from a run's. Both `addShape` and\n\t\t// `addText` take it, and neither used to receive it: a linked shape converted to an\n\t\t// unlinked one.\n\t\thyperlink: shapeHyperlinkOption(shape, ctx),\n\t}\n\n\tif (custom) {\n\t\tnoteCustGeomGuides(notes)\n\t\tconst points = customGeometryPoints(box, custom)\n\t\t// A freeform holding text is an `addText` with the same points: this arm used to return\n\t\t// `addShape` before the text arm below, so a freeform's text was discarded.\n\t\tif (frame !== null) {\n\t\t\tconst options = compact({\n\t\t\t\t...common,\n\t\t\t\t...textFrameOptions(frame, notes),\n\t\t\t\t...(isTextBox(shape.element_) ? { isTextBox: true } : {}),\n\t\t\t\tshape: 'custGeom',\n\t\t\t\tpoints,\n\t\t\t})\n\t\t\treturn { method: 'addText', args: [textRuns(frame, ctx), options ?? {}], ...nameOf(shape) }\n\t\t}\n\t\tconst options = compact({ ...common, points })\n\t\treturn { method: 'addShape', args: ['custGeom', options ?? {}], ...nameOf(shape) }\n\t}\n\n\tif (frame !== null) {\n\t\t// `isTextBox` and `shape` are independent, not alternatives: a PowerPoint text box\n\t\t// carries `txBox=\"1\"` *and* an explicit `prstGeom rect`, so reading text-box-ness off\n\t\t// the absence of geometry misclassified every one of them as an auto shape.\n\t\tconst options = compact({\n\t\t\t...common,\n\t\t\t...textFrameOptions(frame, notes),\n\t\t\t...(isTextBox(shape.element_) ? { isTextBox: true } : {}),\n\t\t\t...(preset === null ? {} : { shape: preset, ...adjustOptions(shape) }),\n\t\t})\n\t\treturn { method: 'addText', args: [textRuns(frame, ctx), options ?? {}], ...nameOf(shape) }\n\t}\n\n\t// No text and no geometry of its own: an empty placeholder, whose shape comes from the\n\t// layout it inherits. `addShape` needs a preset name and `addText` would author an\n\t// invisible empty box, so the shape is dropped — which matches how it renders in a\n\t// slideshow, where an unfilled placeholder shows nothing. It is still a loss in the\n\t// editor, so it is declared rather than assumed harmless.\n\tif (preset === null) {\n\t\tnotes.note(\n\t\t\t'shape.empty',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t'this shape carries no text and no geometry of its own (an unfilled placeholder drawing its outline from the layout), so there is no addShape preset to name and it is omitted'\n\t\t)\n\t\treturn null\n\t}\n\tconst options = compact({ ...common, ...adjustOptions(shape) })\n\treturn { method: 'addShape', args: [preset, options ?? {}], ...nameOf(shape) }\n}\n\n/** The note for what a `custGeom` holds beside its path, shared by a freeform shape and a picture clipped to one. */\nfunction noteCustGeomGuides(notes: NoteScope): void {\n\tnotes.note(\n\t\t'shape.custGeom.guides',\n\t\t'dropped',\n\t\t'unread',\n\t\t'custGeom guides, adjust handles and connection sites (a:gdLst / a:ahLst / a:cxnLst) have no accessor, so only the path outline carries'\n\t)\n}\n\n/**\n * A picture's clip as `addImage` spells it: `points` for a freeform, `shape` and `shapeAdjust` for\n * a preset.\n *\n * PowerPoint writes `rect` for a picture that has not been cropped to a shape, and `addImage` writes\n * `rect` when it is given no `shape`, so a `rect` is left off rather than printed on every picture.\n */\nfunction pictureClipOptions(shape: Picture, box: ShapeBox, notes: NoteScope): Record<string, IrValue | undefined> {\n\tconst custom = shape.customGeometry\n\tif (custom) {\n\t\tnoteCustGeomGuides(notes)\n\t\treturn { points: customGeometryPoints(box, custom) }\n\t}\n\tconst preset = shape.presetGeometry\n\treturn preset === null || preset === 'rect' ? {} : { shape: preset, ...adjustOptions(shape) }\n}\n\n/**\n * Preset-geometry adjust handles (`a:avLst`) as `shapeAdjust`.\n *\n * The read model reports each guide's raw formula string; a preset's adjust values are\n * `val <n>` where `<n>` is in 1000ths of a percent, and the write API takes the same handle\n * as a `0.0–1.0` fraction. Anything that is not a plain `val` is a computed guide, which\n * has no write-API expression, so it is skipped rather than mis-scaled.\n */\nfunction adjustOptions(shape: AutoShape | Picture): Record<string, IrValue | undefined> {\n\tconst values = shape.adjustValues\n\tconst guides: IrValue[] = []\n\tfor (const name of Object.keys(values).sort()) {\n\t\tconst match = /^val\\s+(-?\\d+)$/.exec((values[name] ?? '').trim())\n\t\tif (!match?.[1]) continue\n\t\tguides.push({ name, value: Number(match[1]) / PERCENT_SCALE })\n\t}\n\treturn guides.length ? { shapeAdjust: guides } : {}\n}\n\n/**\n * `custGeom` path commands as the write API's `points` array.\n *\n * Path coordinates are integers in the path's own `0..w`/`0..h` viewport, not EMU, so each\n * is scaled onto the box the call is placed at before being printed as EMU. A path that\n * declares no viewport (`@w`/`@h` of 0) is already in the shape's own space and passes through.\n *\n * The box is the one {@link frameOf} placed the call at, not `absoluteFrame`: in a group whose\n * transform cannot be composed that is `null`, the shape is placed at its resolved box, and\n * scaling by 1 would print its points in raw path units.\n */\nfunction customGeometryPoints(box: ShapeBox, custom: CustomGeometry): IrValue {\n\tconst points: IrValue[] = []\n\n\tfor (const path of custom.paths) {\n\t\tconst sx = path.w > 0 ? box.width / path.w : 1\n\t\tconst sy = path.h > 0 ? box.height / path.h : 1\n\t\tconst px = (v: number): string => emu(v * sx)\n\t\tconst py = (v: number): string => emu(v * sy)\n\n\t\tfor (const command of path.commands) {\n\t\t\tswitch (command.cmd) {\n\t\t\t\tcase 'moveTo':\n\t\t\t\t\tpoints.push({ x: px(command.x), y: py(command.y), moveTo: true })\n\t\t\t\t\tbreak\n\t\t\t\tcase 'lnTo':\n\t\t\t\t\tpoints.push({ x: px(command.x), y: py(command.y) })\n\t\t\t\t\tbreak\n\t\t\t\tcase 'cubicBezTo':\n\t\t\t\t\tpoints.push({\n\t\t\t\t\t\tx: px(command.x),\n\t\t\t\t\t\ty: py(command.y),\n\t\t\t\t\t\tcurve: { type: 'cubic', x1: px(command.x1), y1: py(command.y1), x2: px(command.x2), y2: py(command.y2) },\n\t\t\t\t\t})\n\t\t\t\t\tbreak\n\t\t\t\tcase 'quadBezTo':\n\t\t\t\t\tpoints.push({\n\t\t\t\t\t\tx: px(command.x),\n\t\t\t\t\t\ty: py(command.y),\n\t\t\t\t\t\tcurve: { type: 'quadratic', x1: px(command.x1), y1: py(command.y1) },\n\t\t\t\t\t})\n\t\t\t\t\tbreak\n\t\t\t\tcase 'arcTo':\n\t\t\t\t\t// An arcTo carries no end point on either side — the renderer derives it from\n\t\t\t\t\t// the pen position, radii and swept angle — so this maps one-to-one.\n\t\t\t\t\tpoints.push({\n\t\t\t\t\t\tcurve: { type: 'arc', wR: px(command.wR), hR: py(command.hR), stAng: command.stAng, swAng: command.swAng },\n\t\t\t\t\t})\n\t\t\t\t\tbreak\n\t\t\t\tcase 'close':\n\t\t\t\t\tpoints.push({ close: true })\n\t\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\treturn points\n}\n\n/**\n * A `Picture` becomes `addImage`, with its bytes carried as an asset.\n *\n * PowerPoint authors embedded audio and video as a picture too — the poster frame is the\n * blip, and the media itself hangs off `p:nvPr` as `a:videoFile`/`a:audioFile`. The read\n * model surfaces only the poster (`mediaKind` separates raster from SVG, not still from\n * moving), so a video would otherwise convert to a static image with nothing to show it had\n * ever moved. The write API has `addMedia`, so this is a read-side gap, and it is declared\n * rather than silently flattened.\n */\nfunction pictureCall(shape: Picture, ctx: MapContext): CallIr | null {\n\tconst { notes, assets } = ctx\n\tconst box = frameOf(shape, notes)\n\tif (!box) return null\n\tif (isAudioVideo(shape.element_)) {\n\t\tnotes.note(\n\t\t\t'media.audioVideo',\n\t\t\t'flattened',\n\t\t\t'unread',\n\t\t\t'this is embedded audio or video: no accessor reports the media part or its kind, only the poster frame, so it is emitted as a still image even though addMedia could author it'\n\t\t)\n\t}\n\n\t// The vector part wins when there is one. A PowerPoint SVG picture is an `asvg:svgBlip`\n\t// extension over a raster fallback, and the fallback is the lossy copy — taking it would\n\t// throw away the vector for no reason, since `addImage` accepts SVG bytes directly and\n\t// regenerates a fallback of its own.\n\tconst partName = shape.svgPartName ?? shape.imagePartName\n\tif (!partName) {\n\t\tnotes.note(\n\t\t\t'image.data',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t'this picture references no embedded image part (an external or linked image), so there are no bytes to carry'\n\t\t)\n\t\treturn null\n\t}\n\tconst asset = assets.assetFor(partName)\n\tif (!asset) {\n\t\tnotes.note('image.data', 'dropped', 'unsupported', `image part ${partName} is not present in the package`)\n\t\treturn null\n\t}\n\n\tif (shape.svgPartName && shape.imagePartName) {\n\t\tnotes.note(\n\t\t\t'image.svg',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t\"the vector part of this SVG picture is carried and the source's own raster fallback is not; the write path generates a fresh fallback, so a renderer that cannot draw SVG shows a different image from the one the source deck shipped\"\n\t\t)\n\t}\n\tif (shape.recolor) {\n\t\tnotes.note(\n\t\t\t'image.recolor',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'a picture recolour (a:duotone / a:clrChange / a:grayscl) is read but has no write-API option'\n\t\t)\n\t}\n\n\t// The same guard a picture fill's crop takes. A negative inset (PowerPoint writes one for a fit\n\t// crop) or opposite insets summing to 100% or more have no `crop` spelling, and passing them\n\t// through put a crop in the IR that made the printed script throw at `addImage`.\n\tconst crop = cropOption(shape.crop)\n\tif (crop === undefined && isRectSet(shape.crop)) {\n\t\tnotes.note(\n\t\t\t'image.crop',\n\t\t\t'approximated',\n\t\t\t'unwritable',\n\t\t\t\"this picture's source crop (a:srcRect) has an inset outside the 0–100% `crop` accepts, or opposite insets that leave no image, so the picture is emitted uncropped\"\n\t\t)\n\t}\n\tconst options = compact({\n\t\t...positionOptions(box),\n\t\t...transformOptions(shape),\n\t\t...identityOptions(shape),\n\t\t...pictureClipOptions(shape, box, notes),\n\t\t// `ImageBaseProps.shadow` takes the same `ShadowProps` every other shape does; a picture's\n\t\t// shadow was read and never mapped.\n\t\tshadow: shadowOption(shape, notes),\n\t\t// `addImage` takes a `hyperlink` too, and a linked picture lost its link the same way.\n\t\thyperlink: shapeHyperlinkOption(shape, ctx),\n\t\t// Nor was its border, though `ImageBaseProps.line` takes the same `ShapeLineProps` and the\n\t\t// read side has always reported a picture's own `p:spPr/a:ln`. It goes through the shared\n\t\t// `lineOption`, so a picture's outline takes the same colour ladder and the same loss notes\n\t\t// as every other shape's.\n\t\tline: lineOption(shape, notes),\n\t\t// `crop`, not `sizing`. Both exist and they are not interchangeable: `crop` is\n\t\t// `a:srcRect` emitted verbatim as percentage edge insets — the exact model the read\n\t\t// model reports — while `sizing: 'crop'` cuts a window in *displayed inches* against\n\t\t// the image's measured natural size. Feeding fractions to `sizing` read them as\n\t\t// inches, which shrank every cropped picture to a fraction of its box.\n\t\tcrop,\n\t})\n\treturn { method: 'addImage', args: [{ ...options, data: asset }], ...nameOf(shape) }\n}\n\n/**\n * `ConnectorProps` keys that {@link lineOption} can produce. A connector styles its stroke\n * with *flat* options rather than the nested `line` object every other shape takes, and it\n * accepts a strict subset: no `transparency`, no gradient stroke, and its own `type` names\n * the routing (`straight`/`elbow`/`curved`), not a fill kind — so spreading a line option\n * object into it wholesale would both drop silently and collide.\n */\nconst CONNECTOR_LINE_KEYS = [\n\t'color',\n\t'width',\n\t'dashType',\n\t'beginArrowType',\n\t'endArrowType',\n] as const satisfies readonly (keyof ConnectorProps & keyof ShapeLineProps)[]\n\n/**\n * Every other `ShapeLineProps` key: what a connector's flat stroke options cannot express, which\n * the `connector.line` note declares.\n *\n * Typed as the complement of {@link CONNECTOR_LINE_KEYS}, so a stroke option the write API gains\n * does not compile here until it is placed, carried or noted. Unplaced, it would reach `lineOption`'s\n * output and the copy loop would drop it without a note. `type` is the fill kind, and gets this far\n * only as `'gradient'`: a `'none'` outline has already become a `line` shape.\n */\nconst CONNECTOR_FLATTENED_LINE_KEYS: Record<\n\tExclude<keyof ShapeLineProps, (typeof CONNECTOR_LINE_KEYS)[number]>,\n\ttrue\n> = {\n\ttype: true,\n\tgradient: true,\n\tpattern: true,\n\ttransparency: true,\n\tcap: true,\n}\n\n/**\n * A `Connector` becomes `addConnector`.\n *\n * The endpoints are the one real translation here. OOXML gives a connector a bounding box\n * plus flip flags; `addConnector` takes two points. `a:flipH`/`a:flipV` are what say which\n * diagonal of the box the line runs along, so dropping them would silently mirror every\n * connector that runs up or leftward.\n *\n * The *bindings* (`a:stCxn`/`a:endCxn`) reference source shape ids that have no counterpart\n * in the output, so a connector lands unbound and stops following its shapes when they move.\n */\nfunction connectorCall(shape: Connector, notes: NoteScope): CallIr | null {\n\tconst drawn = connectorLine(\n\t\tshape,\n\t\tnotes,\n\t\t'connector endpoint bindings reference source shape ids with no counterpart in the output, so the connector lands unbound and no longer follows its shapes'\n\t)\n\tif (!drawn) return null\n\t// A connector with no outline has no `addConnector` spelling: its stroke options take no `type`,\n\t// and one given none is drawn with the write path's default line. The `line` shape it paints as\n\t// states `line: { type: 'none' }` and stays invisible, the way a layout's connectors already do.\n\tif (drawn.line?.['type'] === 'none') {\n\t\treturn { method: 'addShape', args: ['line', drawn.options], ...nameOf(shape) }\n\t}\n\tconst frame = drawn.box\n\n\tif (shape.rotation) {\n\t\tnotes.note(\n\t\t\t'connector.rotation',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'addConnector takes two endpoints and no rotation, so a rotated connector lands along the unrotated diagonal of its box'\n\t\t)\n\t}\n\n\tconst line = drawn.line ?? {}\n\tconst stroke: Record<string, IrValue> = {}\n\tfor (const key of CONNECTOR_LINE_KEYS) {\n\t\tconst value = line[key]\n\t\tif (value !== undefined) stroke[key] = value\n\t}\n\tif (Object.keys(CONNECTOR_FLATTENED_LINE_KEYS).some((key) => line[key] !== undefined)) {\n\t\tnotes.note(\n\t\t\t'connector.line',\n\t\t\t'flattened',\n\t\t\t'unwritable',\n\t\t\t'a connector styles its stroke with flat colour, width, dash and arrowhead options, which cannot express a gradient stroke, a stroke transparency or a line cap, so a gradient or a transparency falls back to a plain line and a cap to the default'\n\t\t)\n\t}\n\n\tconst right = frame.left + frame.width\n\tconst bottom = frame.top + frame.height\n\treturn {\n\t\tmethod: 'addConnector',\n\t\targs: [\n\t\t\tcompact({\n\t\t\t\t// Routing is not readable — `presetGeometry` names the connector preset but the\n\t\t\t\t// bend count it implies is not exposed — so every connector emits straight.\n\t\t\t\ttype: 'straight',\n\t\t\t\tx1: emu(shape.flipH ? right : frame.left),\n\t\t\t\ty1: emu(shape.flipV ? bottom : frame.top),\n\t\t\t\tx2: emu(shape.flipH ? frame.left : right),\n\t\t\t\ty2: emu(shape.flipV ? frame.top : bottom),\n\t\t\t\t...identityOptions(shape),\n\t\t\t\t...stroke,\n\t\t\t}) ?? {},\n\t\t],\n\t\t...nameOf(shape),\n\t}\n}\n\n/**\n * Why a graphic frame cannot be authored from a script, or `null` when it can.\n *\n * The single enumeration of the payloads with no write-API emitter, and the reason it is a\n * function rather than a condition spelled at each site: `graphicFrameCall` needs it to pick\n * a fidelity note, and `hasUnwritableContent` in `from-read/deck.ts` needs it to decide\n * whether the printer must copy the slide instead of transcribing it. Those were two\n * hand-maintained lists, they disagreed — the deck-level one named extended charts only — and\n * a SmartArt slide was therefore transcribed with a hole where the graphic had been. The two\n * consequences are the same for every member, so the membership has to be too.\n */\nexport function unwritableFramePayload(shape: GraphicFrame): UnwritableFramePayload | null {\n\tif (shape.table || shape.chart) return null\n\tif (shape.hasChartEx) return 'chartEx'\n\tif (shape.hasDiagram) return 'diagram'\n\treturn 'unknown'\n}\n\n/** A `GraphicFrame` hosts a table or a chart; both have their own mapper. */\nfunction graphicFrameCall(shape: GraphicFrame, ctx: MapContext): CallIr | null {\n\tconst { notes } = ctx\n\tconst table = shape.table\n\tif (table) return tableCall(shape, table, ctx)\n\n\tconst chart = shape.chart\n\tif (chart) return chartCall(shape, chart, notes)\n\n\t// Everything below emits no call. Reached even when the deck-level walk already marked the\n\t// slide `carried`, because the standalone tier has no source package to copy from and needs\n\t// the per-shape note to say what it lost.\n\tswitch (unwritableFramePayload(shape)) {\n\t\tcase 'chartEx':\n\t\t\tnotes.note(\n\t\t\t\tUNWRITABLE_FRAME_CONSTRUCTS.chartEx,\n\t\t\t\t'dropped',\n\t\t\t\t'unwritable',\n\t\t\t\t'an extended chart (waterfall, funnel, box-and-whisker, …) has a full reader but no write-API counterpart'\n\t\t\t)\n\t\t\treturn null\n\t\tcase 'diagram':\n\t\t\t// Read but unwritable, so it takes the `chartEx.all` shape rather than the\n\t\t\t// `graphicFrame.unknown` one below: the loss is the *write* side's, and saying\n\t\t\t// \"not decoded\" of a construct whose text the read model now returns would be false.\n\t\t\tnotes.note(\n\t\t\t\tUNWRITABLE_FRAME_CONSTRUCTS.diagram,\n\t\t\t\t'dropped',\n\t\t\t\t'unwritable',\n\t\t\t\t'a SmartArt diagram has a full reader and its text can be edited in place through it (DiagramPoint.text), but no write API authors one from a script, so a converted script cannot describe this frame'\n\t\t\t)\n\t\t\treturn null\n\t\tdefault:\n\t\t\tnotes.note(\n\t\t\t\tUNWRITABLE_FRAME_CONSTRUCTS.unknown,\n\t\t\t\t'dropped',\n\t\t\t\t'unread',\n\t\t\t\t'this graphic frame hosts none of a table, a chart or a SmartArt diagram (an OLE object or an ink annotation), which the read model does not decode'\n\t\t\t)\n\t\t\treturn null\n\t}\n}\n\n/**\n * A `GroupShape` becomes `addGroup`, with each child mapped and re-tagged into the\n * key-tagged `GroupChildProps` shape the write API expects.\n *\n * Children keep slide-absolute coordinates, which is not a compromise here: `addGroup`\n * holds an identity child coordinate space (`chOff/chExt == off/ext`) at every depth\n * precisely so they can. Nested groups therefore nest rather than flatten. What does not\n * survive is a source group with a *non*-identity child space — that group scales its\n * contents when resized and the emitted one will not — so that case, and only that case,\n * is noted.\n *\n * Charts, tables and placeholders are excluded from groups by the write API, so a group holding\n * one loses that child. A connector is kept as the `line` shape it paints as, which a group takes.\n */\nfunction groupCall(shape: GroupShape, ctx: MapContext): CallIr | null {\n\tconst { notes } = ctx\n\tconst box = frameOf(shape, notes)\n\tif (!box) return null\n\tconst children: IrValue[] = []\n\tfor (const child of shape.shapes) {\n\t\t// `addConnector` has no group child variant, and a connector child used to be dropped.\n\t\tif (isConnector(child)) {\n\t\t\tconst drawn = connectorLine(\n\t\t\t\tchild,\n\t\t\t\tforShape(ctx, child).notes,\n\t\t\t\t'this connector is bound to shapes; it is re-authored as a line shape inside its group, which paints the same stroke but no longer follows them'\n\t\t\t)\n\t\t\tif (drawn) children.push(lineShape(drawn.options))\n\t\t\tcontinue\n\t\t}\n\t\tconst call = shapeCall(child, ctx)\n\t\tif (!call) continue\n\t\tconst tagged = asGroupChild(call)\n\t\tif (!tagged) {\n\t\t\tnotes.note(\n\t\t\t\t'group.child',\n\t\t\t\t'dropped',\n\t\t\t\t'unsupported',\n\t\t\t\t`addGroup accepts no ${kindLabel(call.method)} child (a group takes text, shapes, images and other groups), so this child is omitted from the group`\n\t\t\t)\n\t\t\tcontinue\n\t\t}\n\t\tchildren.push(tagged)\n\t}\n\tif (children.length === 0) {\n\t\tnotes.note(\n\t\t\t'group.empty',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t'no child of this group produced a call, and addGroup rejects an empty child list, so the group itself is omitted too'\n\t\t)\n\t\treturn null\n\t}\n\n\tif (!hasIdentityChildSpace(shape.element_)) {\n\t\tnotes.note(\n\t\t\t'group.childSpace',\n\t\t\t'flattened',\n\t\t\t'unsupported',\n\t\t\t\"this group scales its contents (its a:chOff/a:chExt differ from its a:off/a:ext); addGroup's child space is always identity, so the children are emitted pre-scaled and resizing the group no longer rescales them\"\n\t\t)\n\t}\n\n\t// The group's own rotation and flips are deliberately NOT emitted here. `absoluteFrame`\n\t// composes them into every child, and the children above were built from it, so the\n\t// transform is already baked in at slide-absolute coordinates. Emitting it on the group\n\t// as well would apply it a second time — measured: a group rotated 30° came back at 60°\n\t// with its children walked off their positions, and a flipped group came back unflipped\n\t// because the double flip cancelled. The group's frame is a bounding box and nothing else.\n\tif (shape.rotation !== 0 || shape.flipH || shape.flipV) {\n\t\tnotes.note(\n\t\t\t'group.transform',\n\t\t\t'flattened',\n\t\t\t'unsupported',\n\t\t\t\"the group's own rotation and flips are baked into its children's coordinates rather than kept on the group, because addGroup would otherwise apply them twice; the shapes render identically but rotating or resetting the group no longer moves them together\"\n\t\t)\n\t}\n\n\treturn {\n\t\tmethod: 'addGroup',\n\t\targs: [children, compact({ ...positionOptions(box), ...identityOptions(shape) }) ?? {}],\n\t\t...nameOf(shape),\n\t}\n}\n\n/** A call's object kind as a note's prose names it: `addImage` is `image`. */\nfunction kindLabel(method: string): string {\n\treturn method.replace(/^add/, '').toLowerCase()\n}\n\n/**\n * Re-tag a call as a `GroupChildProps` entry, or `null` when the content type is one\n * `addGroup` excludes. The tagged form is a single-key object, not a `{ type, args }` pair.\n */\nfunction asGroupChild(call: CallIr): IrValue | null {\n\tconst shared = commonShapeVariant(call)\n\tif (shared) return shared\n\tconst [first, second] = call.args\n\tswitch (call.method) {\n\t\tcase 'addGroup':\n\t\t\treturn { group: compact({ children: first, options: second }) ?? {} }\n\t\tdefault:\n\t\t\t// Charts and tables have no GroupChildProps variant. A connector never arrives here:\n\t\t\t// `groupCall` keeps it as the line shape it paints as.\n\t\t\treturn null\n\t}\n}\n\n/**\n * The three key-tagged variants both union-shaped call sites emit identically: a text box, an\n * auto shape, and an image. `null` when `call.method` is not one of them, which is the signal\n * for the caller to try its own extra arms.\n *\n * Shared rather than duplicated because this is exactly where a fourth common variant would be\n * added to one site and forgotten in the other. What is deliberately *not* shared is either\n * caller's `default`: a group child silently declines a chart, while a layout object reports it\n * as a fidelity loss, and that difference is the point of having two functions.\n */\nfunction commonShapeVariant(call: CallIr): IrValue | null {\n\tconst [first, second] = call.args\n\tswitch (call.method) {\n\t\tcase 'addText':\n\t\t\treturn { text: compact({ text: first, options: second }) ?? {} }\n\t\tcase 'addShape':\n\t\t\treturn { shape: compact({ type: first, options: second }) ?? {} }\n\t\tcase 'addImage':\n\t\t\treturn { image: first ?? {} }\n\t\tdefault:\n\t\t\treturn null\n\t}\n}\n\n/* ===== a layout's own shapes ===== */\n\n/**\n * One shape from a **layout's** shape tree as a `SlideMasterObject` — an entry in the\n * `objects` array of a `defineSlideMaster` call.\n *\n * Everything about the shape itself is decided by {@link shapeCall}, so a rectangle on a\n * layout is transcribed by the same code that transcribes one on a slide and cannot drift\n * from it. Only the *envelope* differs: `objects` is a key-tagged union rather than a method\n * name plus arguments — the same shape `GroupChildProps` takes — which is why this reads as a\n * sibling of {@link asGroupChild}.\n *\n * `notes` must already be a `layoutShapeScope`, so the slide vocabulary this borrows lands\n * under `layout.` and cannot be mistaken for a loss on a slide.\n *\n * Two methods have no variant in the union. `addGroup` never reaches here — the layout walk\n * flattens a group into its children first, since children already carry slide-absolute\n * coordinates. `addTable` genuinely has nowhere to go, and is the one kind this reports as\n * lost.\n */\nexport function masterObject(shape: AnyShape, ctx: MapContext): IrValue | null {\n\t// A connector reaches a layout only as a line shape, so it bypasses `shapeCall`.\n\tif (isConnector(shape)) {\n\t\tconst drawn = connectorLine(\n\t\t\tshape,\n\t\t\tforShape(ctx, shape).notes,\n\t\t\t'this connector is bound to shapes on the layout; it is re-authored as a line shape, which paints the same stroke but no longer follows them'\n\t\t)\n\t\treturn drawn && lineShape(drawn.options)\n\t}\n\n\tconst call = shapeCall(shape, ctx)\n\tif (!call) return null\n\n\tconst shared = commonShapeVariant(call)\n\tif (shared) return shared\n\n\tconst [first, second] = call.args\n\tswitch (call.method) {\n\t\tcase 'addChart': {\n\t\t\t// `addChart(data, options)` carries the chart type inside its options, while a master\n\t\t\t// object names it separately. Lifted back out rather than moved: `addChildDefinition`\n\t\t\t// passes the whole options object on to `addChartDefinition` as well, which is where a\n\t\t\t// chart's `type` is read from in the first place.\n\t\t\tconst options = second !== null && typeof second === 'object' && !Array.isArray(second) && !isAssetRef(second) ? second : null // prettier-ignore\n\t\t\tconst type = options?.['type']\n\t\t\t// Unreachable today - `chartCall` returns `null` for a chart with no type or no data,\n\t\t\t// so this arm never sees one - but `collectObjects` states that a `null` from here is\n\t\t\t// always already noted, and a silent `return null` is the one thing that could break\n\t\t\t// that invariant if `chartCall` ever loosens.\n\t\t\tif (type === undefined || first === undefined) {\n\t\t\t\tforShape(ctx, shape).notes.note(\n\t\t\t\t\t'decoration',\n\t\t\t\t\t'dropped',\n\t\t\t\t\t'unwritable',\n\t\t\t\t\t'a chart on a slide layout that names no type or carries no series has no defineSlideMaster({ objects }) variant, so it is dropped from the layout the output rebuilds'\n\t\t\t\t)\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn { chart: compact({ type, data: first, opts: options }) ?? {} }\n\t\t}\n\t\tdefault:\n\t\t\tforShape(ctx, shape).notes.note(\n\t\t\t\t'decoration',\n\t\t\t\t'dropped',\n\t\t\t\t'unwritable',\n\t\t\t\t`a ${kindLabel(call.method)} on a slide layout has no defineSlideMaster({ objects }) variant — the union covers a chart, an image, a shape and a text box — so it is dropped from the layout the output rebuilds`\n\t\t\t)\n\t\t\treturn null\n\t}\n}\n\n/** What {@link connectorLine} reads off a connector. */\ninterface ConnectorLine {\n\t/** Where the connector's box sits. */\n\tbox: ShapeBox\n\t/** Its stroke, as {@link lineOption} reads it. */\n\tline: Record<string, IrValue> | undefined\n\t/** The options of the `line` shape the connector paints as. */\n\toptions: Record<string, IrValue>\n}\n\n/**\n * A `Connector` as the `line` shape it paints as, or `null` when it produces nothing: it is hidden,\n * or nothing places it. Either way the note has been recorded.\n *\n * A layout reaches a connector only this way. The alternative is dropping every connector a layout\n * carries, and in the fixture corpus that is 18 of the 45 shapes every layout actually draws,\n * because PowerPoint's line tool authors a `p:cxnSp`, so a plain rule under a title is usually a\n * connector rather than a shape. Drawing it as a `line` preset paints the identical stroke, and a\n * shape carries `rotate`, which `addConnector` does not. What that costs is the endpoint binding,\n * which on a layout costs nothing that was working: `a:stCxn`/`a:endCxn` reference shapes in the\n * layout's own tree.\n *\n * `addConnector` reads its endpoints and stroke from the same place, so the frame, the binding note\n * and the stroke are decided once for every way a connector is emitted. The binding note's prose\n * is the caller's, since what the loss means depends on where the connector lands.\n * @param shape - the connector\n * @param notes - the scope bound to this connector\n * @param bindingDetail - the endpoint-binding note's detail, for where this connector lands\n */\nfunction connectorLine(shape: Connector, notes: NoteScope, bindingDetail: string): ConnectorLine | null {\n\tif (shape.hidden) {\n\t\tnoteHidden(notes)\n\t\treturn null\n\t}\n\tconst box = frameOf(shape, notes)\n\tif (!box) return null\n\n\tif (shape.startConnection || shape.endConnection) {\n\t\tnotes.note('connector.binding', 'dropped', 'unsupported', bindingDetail)\n\t}\n\n\tconst line = lineOption(shape, notes)\n\t// No `fill`: a connector's `p:spPr` has no fill that a line geometry could show, and asking\n\t// `fillOption` for one would resolve the `p:style/a:fillRef` a `p:cxnSp` always carries into\n\t// a colour that paints nothing on the source and a filled box on the output.\n\tconst options = compactRequired({\n\t\t...positionOptions(box),\n\t\t...transformOptions(shape),\n\t\tline,\n\t\tshadow: shadowOption(shape, notes),\n\t\tglow: glowOption(shape, notes),\n\t\t...identityOptions(shape),\n\t})\n\treturn { box, line, options }\n}\n\n/**\n * A connector's `line` shape as a key-tagged descriptor, the form a layout object and a group child\n * both take. Through `compact` like the other arms, so every emitted descriptor spells its keys in\n * the same order and the printed script does not read as two different mappers.\n */\nfunction lineShape(options: Record<string, IrValue>): IrValue {\n\treturn { shape: compact({ type: 'line', options }) ?? {} }\n}\n","/**\n * The deck's shared chrome → {@link ChromeIr}: theme colours and fonts, plus one\n * `defineSlideMaster` descriptor per source layout.\n *\n * **Only a standalone output needs any of this,** and it is the part of a deck that survives\n * a conversion worst. A template-anchored output reuses the source package, so its masters,\n * layouts and theme are the originals byte for byte; everything below is the approximation\n * that replaces them when there is no template to inherit from. The notes it records are\n * therefore tier-scoped: real for a standalone script, and suppressed by the template-anchored\n * printer because they do not describe its output.\n *\n * **Two ceilings meet here, and neither moves by working harder on this file:**\n *\n * 1. `a:fmtScheme` is unreachable from *both* directions — no read accessor, and the write\n * path emits a hardcoded Office one. A shape whose look comes from `p:style` is repainted.\n * 2. `p:txStyles` has a write counterpart (`SlideMasterProps.textStyles`) and no reader, so\n * the per-level placeholder defaults are invisible.\n *\n * **A layout's decoration used to be a third, and is not any more.** `SlideLayout.shapes`\n * decodes it, and {@link masterObject} re-tags each shape as an entry in the layout's\n * `defineSlideMaster({ objects })` array — through the *same* mapper the slides use, so a band\n * or a wordmark on a layout is transcribed exactly as one on a slide would be. What is left of\n * the ceiling is narrow and named per shape (`layout.*`): a table has no variant in that\n * union, and a group is flattened into its children because the union has no `group` either.\n * A **master's** own decoration is still lost outright, and structurally so — `defineSlideMaster`\n * creates a *layout* under the one shared master, so a master's shape tree has no counterpart\n * to be written to.\n *\n * **Layout placeholders are deliberately not emitted, and that is a write-path finding rather\n * than a read-path one.** `addPlaceholdersToSlideLayouts` seeds *every* slide with each layout\n * placeholder the slide did not populate, as an empty text shape\n * (`src/gen/define/placeholder.ts`). Since this converter transcribes every source shape as\n * concrete absolute-positioned content and never binds one to a placeholder, reproducing the\n * layout's placeholders would add a ghost shape to every slide for each of them — shapes the\n * source deck does not have. Dropping them costs an editing affordance; emitting them would\n * cost the output's shape tree. It is also what makes the decoration walk below a *filter*\n * rather than a straight transcription of `SlideLayout.shapes`.\n */\nimport type { Presentation } from '../../read/api/presentation.js'\nimport type { SlideLayout, SlideMaster, Theme } from '../../read/api/chrome.js'\nimport { isGroupShape, type AnyShape } from '../../read/api/shapes.js'\nimport { uniqueTitle, type ChromeIr, type IrValue, type MasterIr, type ThemeIr } from '../ir.js'\nimport { layoutShapeScope, type NoteScope } from '../fidelity.js'\nimport { masterObject } from './shape.js'\nimport { forShape, type MapContext } from './context.js'\nimport { hasDecorativeShapes, hasFormatScheme, hasTextStyles, isPlaceholderShape } from './detect.js'\nimport { backgroundIr, MASTER_BACKGROUND } from './background.js'\nimport { compact, literalColor, orUndefined } from './values.js'\nimport { DEFAULT_COLOR_MAP } from '../../ooxml/st-enums.js'\n\n/** Build the chrome IR for a deck. */\nexport function chromeToIr(pres: Presentation, ctx: MapContext): ChromeIr {\n\tconst { notes } = ctx\n\tconst masters = pres.masters()\n\n\tif (masters.length > 1) {\n\t\tnotes.note(\n\t\t\t'master.multiple',\n\t\t\t'flattened',\n\t\t\t'unsupported',\n\t\t\t`this deck has ${masters.length} slide masters; the write API models a deck as one shared master with many layouts, so every layout is rebuilt under a single master and only the first master's theme and colour map survive`\n\t\t)\n\t}\n\n\tconst first = masters[0]\n\tconst theme = first?.theme ?? null\n\trecordMasterLosses(masters, theme, notes)\n\n\treturn { theme: themeToIr(theme), masters: layoutsToIr(masters, ctx) }\n}\n\n/** The theme's colour scheme and font faces, in `ThemeProps` spelling. */\nfunction themeToIr(theme: Theme | null): ThemeIr {\n\tif (!theme) return {}\n\n\tconst scheme = theme.colorScheme\n\tconst colors: Record<string, string> = {}\n\tfor (const [slot, hex] of Object.entries(scheme)) {\n\t\tif (hex !== null) colors[slot] = literalColor(hex)\n\t}\n\n\tconst fonts = theme.fontScheme\n\treturn compact({\n\t\theadFontFace: orUndefined(fonts?.major.latin ?? null),\n\t\tbodyFontFace: orUndefined(fonts?.minor.latin ?? null),\n\t\theadFontFaceEA: orUndefined(fonts?.major.ea ?? null),\n\t\tbodyFontFaceEA: orUndefined(fonts?.minor.ea ?? null),\n\t\theadFontFaceCS: orUndefined(fonts?.major.cs ?? null),\n\t\tbodyFontFaceCS: orUndefined(fonts?.minor.cs ?? null),\n\t\tcolorScheme: Object.keys(colors).length > 0 ? colors : undefined,\n\t}) as ThemeIr\n}\n\n/** The losses that belong to the master/theme tier as a whole rather than to one layout. */\nfunction recordMasterLosses(masters: SlideMaster[], theme: Theme | null, notes: NoteScope): void {\n\tif (theme && hasFormatScheme(theme.element_)) {\n\t\tnotes.note(\n\t\t\t'theme.fmtScheme',\n\t\t\t'approximated',\n\t\t\t'unread',\n\t\t\t\"the theme's format scheme (a:fmtScheme — the three fill, line and effect style lists a shape's p:style indexes into) has no read accessor and no write-API option, so the output carries Office's default; a shape whose fill or outline came from the theme rather than from its own a:ln keeps its colour but not its width, dash or effect\"\n\t\t)\n\t}\n\n\tfor (const master of masters) {\n\t\tconst root = master.part.dom.documentElement\n\t\tif (hasTextStyles(root)) {\n\t\t\tnotes.note(\n\t\t\t\t'master.txStyles',\n\t\t\t\t'dropped',\n\t\t\t\t'unread',\n\t\t\t\t\"the master's per-level text styles (p:txStyles — the default size, face, colour, indent and bullet of each of the nine list levels) have no read accessor, so placeholder text falls back to PowerPoint's built-in defaults; SlideMasterProps.textStyles could author them if they could be seen\"\n\t\t\t)\n\t\t}\n\t\tif (hasDecorativeShapes(root)) {\n\t\t\tnotes.note(\n\t\t\t\t'master.decoration',\n\t\t\t\t'dropped',\n\t\t\t\t'unwritable',\n\t\t\t\t\"this slide master carries shapes that are not placeholders (a logo, a rule, a background graphic); the read model decodes them (SlideMaster.shapes) and a layout's are re-authored, but a master's cannot be — defineSlideMaster creates a layout under the one shared master, so the master's own shape tree has no write-side counterpart to receive them\"\n\t\t\t)\n\t\t}\n\n\t\tconst map = master.colorMap\n\t\tconst remapped = Object.entries(DEFAULT_COLOR_MAP).filter(\n\t\t\t([token, slot]) => map[token as keyof typeof map] !== slot\n\t\t)\n\t\tif (remapped.length > 0) {\n\t\t\tnotes.note(\n\t\t\t\t'master.colorMap',\n\t\t\t\t'dropped',\n\t\t\t\t'unwritable',\n\t\t\t\t`this master remaps ${remapped.map(([token]) => token).join(', ')} to a different theme slot and the write path always emits the identity map, so every scheme colour that passes through as a token resolves to a different hex than it did in the source`\n\t\t\t)\n\t\t}\n\t}\n}\n\n/**\n * One `defineSlideMaster` descriptor per source layout, in the same gallery order\n * `Presentation.layouts()` reports — which is what lets a slide bind by index.\n *\n * Titles are made unique because they are the lookup key `addSlide({ masterTitle })` matches\n * on, and `p:cSld@name` is not unique: a multi-master deck routinely carries several layouts\n * called \"Title and Content\", and two `defineSlideMaster` calls sharing a title would make\n * every slide bind to whichever won.\n */\nfunction layoutsToIr(masters: SlideMaster[], ctx: MapContext): MasterIr[] {\n\tconst { notes, assets } = ctx\n\tconst out: MasterIr[] = []\n\tconst used = new Set<string>()\n\t// Rolled up rather than noted per layout: a 12-layout deck loses the placeholder definitions\n\t// on most of them, and twelve near-identical paragraphs at the top of the emitted script bury\n\t// the per-shape notes underneath that a reader can actually act on.\n\tlet placeholderCount = 0\n\tlet placeholderLayouts = 0\n\n\tconst renamed: string[] = []\n\tconst collided: string[] = []\n\n\tfor (const master of masters) {\n\t\tfor (const layout of master.layouts) {\n\t\t\tconst index = out.length\n\t\t\tconst flattened = flattenAttributeValue(layout.name)\n\t\t\tif (flattened !== layout.name) renamed.push(`${JSON.stringify(layout.name)} → ${JSON.stringify(flattened)}`)\n\t\t\tconst base = flattened || `Layout ${index + 1}`\n\t\t\tconst title = uniqueTitle(base, used)\n\t\t\tif (title !== base) collided.push(`${JSON.stringify(base)} → ${JSON.stringify(title)}`)\n\t\t\tused.add(title)\n\n\t\t\tconst placeholders = layout.placeholders.length\n\t\t\tif (placeholders > 0) {\n\t\t\t\tplaceholderCount += placeholders\n\t\t\t\tplaceholderLayouts++\n\t\t\t}\n\n\t\t\t// The layout's own background if it has one, else the master's — which is what a slide\n\t\t\t// bound to that layout actually shows, and the only tier the write API can set it at.\n\t\t\t// The cast is the one `print/common.ts` makes for the same value: a `BackgroundIr` is\n\t\t\t// exactly the shape the write option takes, and the layout props bag is untyped.\n\t\t\tconst background = backgroundIr(layout.background ?? master.background, notes, assets, MASTER_BACKGROUND) as\n\t\t\t\t| IrValue\n\t\t\t\t| undefined\n\t\t\tconst objects = layoutObjects(layout, ctx)\n\t\t\tout.push({\n\t\t\t\tlayoutIndex: index,\n\t\t\t\tprops: compact({\n\t\t\t\t\ttitle,\n\t\t\t\t\tbackground,\n\t\t\t\t\tobjects: objects.length > 0 ? objects : undefined,\n\t\t\t\t}) as Record<string, IrValue>,\n\t\t\t})\n\t\t}\n\t}\n\n\tif (collided.length > 0) {\n\t\tnotes.note(\n\t\t\t'master.nameCollision',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t`${collided.length} layout name(s) are not unique in the source — normally because the deck has several masters, each with its own \"Title and Content\" — and a layout title here is also the key addSlide({ masterTitle }) binds on, so duplicates cannot both exist. The later ones are suffixed and the slides bound to them follow: ${collided.join('; ')}`\n\t\t)\n\t}\n\tif (renamed.length > 0) {\n\t\tnotes.note(\n\t\t\t'master.name',\n\t\t\t'flattened',\n\t\t\t'unwritable',\n\t\t\t`${renamed.length} layout name(s) contain a line break or tab, which cannot survive as a layout title: the write path emits the name as a literal XML attribute value rather than a character reference, and XML normalises whitespace in an attribute to spaces. Collapsed here so the emitted script says what the output will contain — ${renamed.join('; ')}`\n\t\t)\n\t}\n\tif (placeholderCount > 0) {\n\t\tnotes.note(\n\t\t\t'master.placeholders',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t`the ${placeholderCount} placeholder definition(s) across ${placeholderLayouts} slide layout(s) are not reproduced: the write path seeds every slide with each layout placeholder the slide did not populate, and since every source shape is authored here as concrete content rather than into a placeholder, re-declaring them would add an empty shape to every slide rather than a prompt`\n\t\t)\n\t}\n\n\treturn out\n}\n\n/**\n * A layout's own shapes as the `objects` of its `defineSlideMaster` call — the bands, rules,\n * wordmarks and footer graphics that make a deck recognisable as somebody's template.\n *\n * **Placeholders are filtered out, not mapped.** They are the other half of a layout's tree and\n * the write path already reproduces them from the far side: `addPlaceholdersToSlideLayouts`\n * seeds every slide with each layout placeholder it did not populate, so re-declaring one here\n * would put an empty ghost shape on every slide bound to the layout (see the module header).\n * The test is a DOM predicate rather than `shape.placeholder`, because only `AutoShape` reports\n * one — see {@link isPlaceholderShape}.\n *\n * **A group is flattened into its children rather than dropped.** `SlideMasterObject` has no\n * `group` variant, and unlike the slide-side `addGroup` mapping this loses nothing visual:\n * `absoluteFrame` already composes an enclosing group's offset, rotation, flips *and* its\n * child-space scaling, so each child lands exactly where the group put it. What goes is the\n * grouping itself — one selectable object in PowerPoint becomes several.\n *\n * Notes are recorded through a {@link layoutShapeScope}, so the slide vocabulary the shared\n * mapper speaks lands under `layout.` and stays attributable to the layout tier. Constructs\n * written below are therefore relative to that prefix.\n */\nfunction layoutObjects(layout: SlideLayout, ctx: MapContext): IrValue[] {\n\tconst out: IrValue[] = []\n\t// A layout's own shapes are noted under the `layout.` prefix, so the loss reads as one in\n\t// re-authoring the layout rather than as one on a slide.\n\t// No slide number resolves from a layout's shapes: a slide link written into a layout's\n\t// relationships would resolve under `ppt/slideLayouts/`, so such a link is noted instead.\n\tcollectObjects(layout.shapes, out, { ...ctx, notes: layoutShapeScope(ctx.notes), slideNumberOf: () => null })\n\treturn out\n}\n\n/** {@link layoutObjects}'s walk, recursing through groups. */\nfunction collectObjects(shapes: AnyShape[], out: IrValue[], ctx: MapContext): void {\n\tfor (const shape of shapes) {\n\t\tif (isPlaceholderShape(shape.element_)) continue\n\n\t\tif (isGroupShape(shape)) {\n\t\t\tforShape(ctx, shape).notes.note(\n\t\t\t\t'group',\n\t\t\t\t'flattened',\n\t\t\t\t'unwritable',\n\t\t\t\t\"defineSlideMaster({ objects }) has no group variant, so this group's children are emitted as loose objects; they land in the same places — the group's offset, rotation, flips and child-space scaling are composed into each child's coordinates — but the layout no longer offers them as one selectable object\"\n\t\t\t)\n\t\t\tcollectObjects(shape.shapes, out, ctx)\n\t\t\tcontinue\n\t\t}\n\n\t\t// `null` is always already noted, either by the shared mapper (a hidden shape, a picture\n\t\t// with no bytes) or by `masterObject` itself (a kind with no variant in the union).\n\t\tconst object = masterObject(shape, ctx)\n\t\tif (object !== null) out.push(object)\n\t}\n}\n\n/**\n * Collapse the whitespace an XML attribute value cannot carry.\n *\n * Not a style choice: XML normalises a literal tab, carriage return or line feed inside an\n * attribute value to a space (XML 1.0 §3.3.3), and the write path emits a layout title as a\n * literal rather than as a ` ` character reference. So a PowerPoint layout named across\n * two lines — \"Abschnitts-⏎überschrift\" is a real one, in the German built-in set — comes back\n * with a space either way. Doing it here rather than leaving it to the serializer means the\n * emitted script states the title the output will actually have, and the round trip compares\n * two decks that agree instead of reporting a rename it cannot act on.\n */\nfunction flattenAttributeValue(value: string): string {\n\treturn value.replace(/[\\t\\r\\n]+/g, ' ')\n}\n","/**\n * A slide's show transition (`p:transition`) → the write API's `TransitionProps`.\n *\n * **The whole difficulty is one type mismatch.** `TransitionInfo.type` is an *open string*,\n * because the read model decodes PowerPoint's modern effects (Morph, Vortex, Ripple, …)\n * alongside the base ECMA-376 ones and tells them apart by namespace rather than by name.\n * The write API's `TransitionType` is a closed union of 21 base names. Passing the read\n * model's string straight through would therefore produce a script that does not compile\n * for exactly the decks a converter is most likely to meet — a modern transition is what\n * PowerPoint's own UI offers first. So {@link WRITABLE_TYPES} is the filter, and a name that\n * does not survive it becomes a fidelity note rather than a compile error.\n *\n * **Why `speed` is always emitted.** `spd` is absent from most PowerPoint-authored\n * transitions (its schema default is `fast`) and the read model reports the default rather\n * than the absence, so there is nothing to distinguish \"absent\" from \"explicitly fast\". That\n * is harmless on its own — both read back as `fast`. What is *not* harmless is omitting it\n * when a duration is present: the write path then derives the bucket from `durationMs`\n * (`transitionSpeedForDuration`), and PowerPoint's own pairing does not always agree with\n * that formula — the sound fixture carries `spd=\"slow\"` with `p14:dur=\"2000\"`, which the\n * derivation happens to reproduce, while a 600ms `fast` transition would come back `med`.\n * Emitting the read value verbatim removes the derivation from the path entirely, which is\n * the same discipline the rest of the IR follows: state what was read, never recompute it.\n */\nimport type { Slide } from '../../read/api/slide.js'\nimport type { TransitionInfo } from '../../read/api/transition.js'\nimport { TRANSITION_TYPES } from '../../ooxml/st-enums.js'\nimport type { NoteScope } from '../fidelity.js'\nimport type { TransitionIr, TransitionSoundIr } from '../ir.js'\nimport type { AssetResolver, MapContext } from './context.js'\n\n/**\n * The transitions the write API can author, as a lookup.\n *\n * Built from the tuple the write API's `TransitionType` is derived from and its emitter validates\n * against, so the three cannot disagree. A list kept here by hand would drift out of date the\n * moment the writer gained a name, and the symptom would be a printed script that does not compile\n * or a transition dropped with a note it did not deserve.\n */\nconst WRITABLE_TYPES: ReadonlySet<string> = new Set(TRANSITION_TYPES)\n\n/**\n * `true` when the write API has a name for this transition.\n *\n * The namespace check does no work on PowerPoint's own output and is kept anyway. Every one\n * of the 21 modern effect names in the probed table (`conveyor`, `morph`, `vortex`, …) is\n * distinct from every base name, so today the name lookup alone would reach the same verdict\n * — measured, not assumed. But \"is this a base ECMA-376 transition\" is a question about the\n * *namespace*, and answering it by name would be relying on that disjointness holding for\n * every namespace Microsoft ever adds. The write path emits `p:${type}` unconditionally, so\n * the cost of being wrong is a modern effect silently rewritten as a base one with the same\n * name and no note — a conversion that reports itself as faithful. `script-ir.test.js`\n * authors a `p14:fade` to keep this branch honest, since no fixture can.\n */\nfunction isWritable(info: TransitionInfo): boolean {\n\treturn info.namespace === 'p' && WRITABLE_TYPES.has(info.type)\n}\n\n/**\n * Map a slide's transition, recording a note for anything that does not survive.\n *\n * Returns `undefined` both when the slide has no transition and when it has one this\n * library cannot author — the difference between those two is what the note carries.\n */\nexport function transitionToIr(slide: Slide, ctx: MapContext): TransitionIr | undefined {\n\tconst { notes, assets } = ctx\n\tconst info = slide.transition\n\tif (!info) return undefined\n\n\tif (!isWritable(info)) {\n\t\tnotes.note(\n\t\t\t'slide.transition',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t`this slide's ${info.namespace === 'p' ? '' : `${info.namespace} `}${info.type} transition is not one of the 21 base ECMA-376 transitions the write API can author${\n\t\t\t\tinfo.namespace === 'p' ? '' : \" — it is one of PowerPoint's modern effects, which have no write-API vocabulary\"\n\t\t\t}, so the regenerated slide advances with no effect`\n\t\t)\n\t\treturn undefined\n\t}\n\n\t// Each optional key is spread in only when the source carried it, so an absent attribute\n\t// stays absent rather than becoming an explicit default the source never wrote.\n\tconst sound = soundToIr(slide, info, notes, assets)\n\treturn {\n\t\ttype: info.type,\n\t\tspeed: info.speed,\n\t\t...(info.durationMs === null ? {} : { durationMs: info.durationMs }),\n\t\t// Both are omitted at their OOXML default, so the emitted script says only what the\n\t\t// source said: `advClick` defaults to true and `advTm` to unset.\n\t\t...(info.advanceOnClick ? {} : { advanceOnClick: false }),\n\t\t...(info.advanceAfterMs === null ? {} : { advanceAfterMs: info.advanceAfterMs }),\n\t\t...(Object.keys(info.variant).length > 0 ? { variant: { ...info.variant } } : {}),\n\t\t...(sound ? { sound } : {}),\n\t}\n}\n\n/**\n * The transition's sound (`p:sndAc`), in the two forms OOXML gives it.\n *\n * The stop-previous form is pure structure — no relationship, no media part — so it maps\n * unconditionally. A start sound is an embedded WAV reached through the slide's own\n * relationships, which is the only place in this converter that resolves an `r:embed` by\n * hand: every other media reference arrives already resolved to a partname by the read\n * model's shape accessors, and a transition sound has no shape to hang off.\n */\nfunction soundToIr(\n\tslide: Slide,\n\tinfo: TransitionInfo,\n\tnotes: NoteScope,\n\tassets: AssetResolver\n): TransitionSoundIr | undefined {\n\tconst sound = info.sound\n\tif (!sound) return undefined\n\tif (sound.form === 'stop') return { stopPrevious: true }\n\n\tconst partName = soundPartName(slide, sound.embedRid)\n\tconst asset = partName === null ? null : assets.assetFor(partName)\n\tif (!asset) {\n\t\tnotes.note(\n\t\t\t'slide.transitionSound',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t`this transition's start sound (${sound.embedRid ?? 'no r:embed'}) does not resolve to an audio part in the package, so the regenerated transition is silent`\n\t\t)\n\t\treturn undefined\n\t}\n\n\treturn {\n\t\tdata: asset,\n\t\t...(sound.name === null ? {} : { name: sound.name }),\n\t\t// Omitted at its default, like `advanceOnClick`: `p:stSnd@loop` defaults to false.\n\t\t...(sound.loop ? { loop: true } : {}),\n\t}\n}\n\n/** Resolve `p:snd@r:embed` to the audio part it names, or `null` when it does not resolve. */\nfunction soundPartName(slide: Slide, embedRid: string | null): string | null {\n\tif (!embedRid) return null\n\tconst relationship = slide.relationships.get(embedRid)\n\t// An External audio rel has no partname to read bytes from; `resolveTarget` throws on\n\t// both cases, so they are screened here rather than caught.\n\tif (!relationship || relationship.targetMode === 'External') return null\n\treturn slide.relationships.resolveTarget(embedRid)\n}\n","/**\n * `Presentation` → {@link DeckIr}. The entry point of the read half.\n *\n * Pure in the sense that matters: it reads a loaded package and returns data, touching no\n * filesystem and mutating nothing. Given the same bytes it returns the same IR, so a\n * round-trip check can compare two runs directly.\n *\n * The one judgement made at this level rather than per-shape is {@link SlideSource}. A\n * slide holding a construct the write API cannot express *at all* — a graphic frame with a\n * complete reader and no emitter, which today means an extended chart, a SmartArt diagram,\n * an OLE object or ink — cannot be honestly transcribed, because the output would silently\n * differ from the source. Such a slide is marked `carried` so the printer copies it instead.\n * That decision has to be made here, before any shape is mapped, since it is a property of\n * the slide as a whole.\n */\nimport type { Presentation } from '../../read/api/presentation.js'\nimport type { Slide } from '../../read/api/slide.js'\nimport type { Paragraph } from '../../read/api/text.js'\nimport { isGraphicFrame, isGroupShape, type AnyShape } from '../../read/api/shapes.js'\nimport type { CoreProperties } from '../../read/api/document-properties.js'\nimport { backgroundIr, SLIDE_BACKGROUND } from './background.js'\nimport { NoteCollector, andList, scopeNotes, type NoteScope } from '../fidelity.js'\nimport {\n\tDECK_PROPS,\n\tDECK_PROP_KEYS,\n\ttype AssetIr,\n\ttype AssetRef,\n\ttype BackgroundIr,\n\ttype CallIr,\n\ttype DeckIr,\n\ttype DeckPropKey,\n\ttype DeckPropsIr,\n\ttype SlideIr,\n\ttype SlideLayoutIr,\n} from '../ir.js'\nimport { shapeCall, unwritableFramePayload } from './shape.js'\nimport type { AssetResolver, MapContext } from './context.js'\nimport { chromeToIr } from './chrome.js'\nimport { transitionToIr } from './transition.js'\nimport { compact, inches } from './values.js'\nimport { ABSENT_SLIDE_SIZE_EMU } from '../../ooxml/slide-size.js'\nimport { assetFilenameExtension } from '../../media/content-type.js'\n\n/** An RFC 7230 token without `$`, a quote or a backtick. */\nconst MEDIA_TOKEN = String.raw`[\\w!#%&*+.^|~-]+`\n/** `type/subtype` with optional `; name=value` parameters, each part a {@link MEDIA_TOKEN}. */\nconst MEDIA_TYPE = new RegExp(\n\tString.raw`^${MEDIA_TOKEN}\\/${MEDIA_TOKEN}(?:[ \\t]*;[ \\t]*${MEDIA_TOKEN}=${MEDIA_TOKEN})*$`\n)\n\n/**\n * A part's content type as the IR may carry it.\n *\n * The value is the deck's own `[Content_Types].xml` attribute, and it reaches a printed script\n * inside a `data:` URI. Anything outside the media-type grammar is not a type a renderer could\n * act on anyway, so it becomes `application/octet-stream` rather than text the printer has to\n * be trusted to neutralise.\n */\nfunction assetContentType(contentType: string): string {\n\treturn MEDIA_TYPE.test(contentType) ? contentType : 'application/octet-stream'\n}\n\n/**\n * Collects media as shapes reference it, assigning each part a stable sequential name.\n *\n * Names are assigned in first-reference order rather than derived from the source part\n * name, so the output is deterministic for a given deck and does not leak whatever the\n * source package happened to call its files. A part referenced twice resolves to one asset.\n *\n * Numbering runs per *kind* (`image1.png`, `image2.png`, `audio1.wav`) rather than over one\n * shared counter. Not cosmetics: the asset name becomes a `const` identifier in the emitted\n * script and a filename in its asset directory, and a transition sound bound to `image7`\n * reads as a bug in the generated source every time anyone opens it.\n */\nclass Assets implements AssetResolver {\n\treadonly #byPartName = new Map<string, AssetRef>()\n\treadonly #assets: AssetIr[] = []\n\treadonly #counts = new Map<string, number>()\n\n\tconstructor(private readonly pres: Presentation) {}\n\n\tassetFor(partName: string): AssetRef | null {\n\t\tconst existing = this.#byPartName.get(partName)\n\t\tif (existing) return existing\n\n\t\tconst part = this.pres.opc.part(partName)\n\t\tif (!part) return null\n\n\t\tconst contentType = assetContentType(part.contentType)\n\t\tconst extension = assetFilenameExtension(contentType) ?? partName.split('.').pop() ?? 'bin'\n\t\tconst kind = contentType.startsWith('audio/') ? 'audio' : 'image'\n\t\tconst index = (this.#counts.get(kind) ?? 0) + 1\n\t\tthis.#counts.set(kind, index)\n\t\tconst name = `${kind}${index}.${extension}`\n\t\tconst ref: AssetRef = { $asset: name }\n\t\tthis.#byPartName.set(partName, ref)\n\t\tthis.#assets.push({ name, contentType, bytes: part.serialize() })\n\t\treturn ref\n\t}\n\n\tcontentTypeOf(partName: string): string | null {\n\t\treturn this.pres.opc.part(partName)?.contentType ?? null\n\t}\n\n\tget assets(): AssetIr[] {\n\t\treturn this.#assets\n\t}\n}\n\n/** Convert a loaded deck into its IR. */\nexport function readModelToIr(pres: Presentation): DeckIr {\n\tconst collector = new NoteCollector()\n\tconst assets = new Assets(pres)\n\tconst size = pres.slideSize\n\tconst deckScope = scopeNotes(collector, null)\n\n\tif (!size) {\n\t\tdeckScope.note(\n\t\t\t'deck.slideSize',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t`this deck declares no slide size, so the output uses the ${inches(ABSENT_SLIDE_SIZE_EMU.widthEmu)}in × ${inches(ABSENT_SLIDE_SIZE_EMU.heightEmu)}in PowerPoint opens such a deck at`\n\t\t)\n\t}\n\n\tconst layouts = layoutGallery(pres)\n\t// A run's slide link names its target by part, and the write API names it by number.\n\tconst slideNumbers = new Map(pres.slides.map((slide, index) => [slide.partName, index + 1]))\n\tconst slideNumberOf = (partName: string): number | null => slideNumbers.get(partName) ?? null\n\t// Before the slides, so the chrome's deck-level notes lead the list the way the chrome\n\t// leads the deck. Assets are shared: a layout background image and a slide image that are\n\t// the same part resolve to one asset.\n\tconst chrome = chromeToIr(pres, { notes: deckScope, assets, slideNumberOf })\n\tconst slides = pres.slides.map((slide, index) =>\n\t\tslideToIr(slide, index + 1, collector, { assets, slideNumberOf }, layouts)\n\t)\n\n\treturn {\n\t\tslideSize: size ? { widthEmu: size.widthEmu, heightEmu: size.heightEmu } : { ...ABSENT_SLIDE_SIZE_EMU },\n\t\tprops: deckProps(pres, deckScope),\n\t\tchrome,\n\t\tslides,\n\t\tassets: assets.assets,\n\t\tfidelity: collector.notes,\n\t}\n}\n\n/** A `CoreProperties` key {@link DECK_PROPS} reads. */\ntype CarriedCoreKey = Extract<(typeof DECK_PROPS)[DeckPropKey], { part: 'core' }>['key']\n\n/**\n * The core properties with no write-API setter, each as a note's prose names it.\n *\n * Typed as every `CoreProperties` key {@link DECK_PROPS} does not read, less the three timestamps,\n * which describe the file rather than the deck. A property the read model gains does not compile\n * here until it is placed.\n */\nconst UNCARRIED_CORE_PROPS: Record<\n\tExclude<keyof CoreProperties, CarriedCoreKey | 'created' | 'modified' | 'lastPrinted'>,\n\tstring\n> = {\n\tkeywords: 'keywords',\n\tdescription: 'description',\n\tcategory: 'category',\n\tcontentStatus: 'content status',\n\tlastModifiedBy: 'last-modified-by',\n}\n\n/**\n * Deck properties, reduced to the {@link DECK_PROPS} fields this converter can carry: they have a\n * write-API setter AND the read model reports them. The core fields in\n * {@link UNCARRIED_CORE_PROPS} have no setter. All of them survive anyway in a template-anchored\n * output, since the source deck itself becomes the template; this is only a loss for a standalone\n * one.\n */\nfunction deckProps(pres: Presentation, notes: NoteScope): DeckPropsIr {\n\tconst parts = { core: pres.coreProperties, app: pres.appProperties }\n\tconst uncarried = Object.keys(UNCARRIED_CORE_PROPS) as (keyof typeof UNCARRIED_CORE_PROPS)[]\n\tif (uncarried.some((key) => parts.core[key] !== undefined)) {\n\t\tnotes.note(\n\t\t\t'deck.docProps',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t`only ${andList(DECK_PROP_KEYS)} round-trip; ${andList(Object.values(UNCARRIED_CORE_PROPS))} have no write-API setter`\n\t\t)\n\t}\n\tconst read = (key: DeckPropKey): string | undefined => {\n\t\tconst source = DECK_PROPS[key]\n\t\treturn source.part === 'core' ? parts.core[source.key] : parts.app[source.key]\n\t}\n\treturn compact(Object.fromEntries(DECK_PROP_KEYS.map((key) => [key, read(key)]))) ?? {}\n}\n\n/**\n * The deck's layouts keyed by partname, each resolved to what a printer needs to bind to\n * it: its gallery position and whether its name identifies it on its own.\n *\n * Built once per deck rather than per slide — `layouts()` walks every master's layout list,\n * and the uniqueness question is about the gallery as a whole, so asking it per slide would\n * be both quadratic and unable to see layouts no slide happens to use.\n */\nfunction layoutGallery(pres: Presentation): Map<string, SlideLayoutIr> {\n\tconst handles = pres.layouts()\n\tconst nameCounts = new Map<string, number>()\n\tfor (const handle of handles) nameCounts.set(handle.name, (nameCounts.get(handle.name) ?? 0) + 1)\n\n\treturn new Map(\n\t\thandles.map((handle, index) => [\n\t\t\thandle.partName,\n\t\t\t{ name: handle.name, index, nameIsUnique: (nameCounts.get(handle.name) ?? 0) === 1 },\n\t\t])\n\t)\n}\n\nfunction slideToIr(\n\tslide: Slide,\n\tnumber: number,\n\tcollector: NoteCollector,\n\tdeck: Omit<MapContext, 'notes'>,\n\tlayouts: Map<string, SlideLayoutIr>\n): SlideIr {\n\tconst notes = scopeNotes(collector, number)\n\tconst ctx: MapContext = { ...deck, notes }\n\tconst { assets } = deck\n\tconst layoutPartName = slide.layout?.partName\n\tconst base = {\n\t\tnumber,\n\t\tlayout: (layoutPartName === undefined ? undefined : layouts.get(layoutPartName)) ?? null,\n\t\thidden: slide.hidden,\n\t\t...(slide.name ? { name: slide.name } : {}),\n\t\t...backgroundOf(slide, notes, assets),\n\t\t...notesOf(slide, notes),\n\t}\n\n\tconst transition = transitionToIr(slide, ctx)\n\tconst carried = hasUnwritableContent(slide)\n\tif (carried) {\n\t\tnotes.note(\n\t\t\t'slide.carried',\n\t\t\t'flattened',\n\t\t\t'unwritable',\n\t\t\t'this slide holds a graphic frame the write API cannot author (an extended chart, a SmartArt diagram, an OLE object or ink); a printer that can copy the source slide does so instead of transcribing it, so it renders correctly but the emitted script does not describe its contents. The per-shape note beside this one says which construct forced the copy'\n\t\t)\n\t}\n\n\t// Mapped even for a carried slide: a printer with no source package to copy from prints\n\t// these and loses only the unwritable construct, rather than the whole slide. Each shape\n\t// records its own note, so that loss is declared either way.\n\tconst calls: CallIr[] = []\n\tfor (const shape of slide.shapes) {\n\t\tconst call = shapeCall(shape, ctx)\n\t\tif (call) calls.push(call)\n\t}\n\n\t// Build animations are recorded once per slide rather than per shape, since they live in a\n\t// slide-scoped element with no shape to attribute them to.\n\trecordAnimationLoss(slide, notes)\n\n\treturn {\n\t\t...base,\n\t\t...(transition ? { transition } : {}),\n\t\tsource: carried ? 'carried' : 'authored',\n\t\tcalls,\n\t}\n}\n\n/**\n * `true` when the slide holds something with no write-API expression at all, forcing a\n * carried slide. Descends into groups, since a group can host a graphic frame.\n *\n * Membership comes from {@link unwritableFramePayload}, which `graphicFrameCall` also uses to\n * pick its note — one enumeration, so the two cannot drift apart again. This test named\n * extended charts alone until then, which is why a slide holding SmartArt (or an OLE object,\n * or ink) was transcribed as `authored` and rendered with a hole where the graphic had been.\n */\nfunction hasUnwritableContent(slide: Slide): boolean {\n\tconst check = (shapes: AnyShape[]): boolean =>\n\t\tshapes.some((shape) => {\n\t\t\tif (isGroupShape(shape)) return check(shape.shapes)\n\t\t\treturn isGraphicFrame(shape) && unwritableFramePayload(shape) !== null\n\t\t})\n\treturn check(slide.shapes)\n}\n\n/**\n * A slide's own background, as the write API's `background` option.\n *\n * Only a slide-scoped background is carried: an inherited one comes with the layout, so\n * re-authoring it onto the slide would pin a colour that should keep following the layout.\n */\nfunction backgroundOf(slide: Slide, notes: NoteScope, assets: AssetResolver): { background?: BackgroundIr } {\n\tconst background = slide.background\n\tif (!background || background.source !== 'slide') return {}\n\tconst ir = backgroundIr(background, notes, assets, SLIDE_BACKGROUND)\n\treturn ir ? { background: ir } : {}\n}\n\nfunction notesOf(slide: Slide, notes: NoteScope): { notesText?: string } {\n\tconst text = slide.notesText\n\tif (!text) return {}\n\tconst frame = slide.notesTextFrame\n\tif (frame && frame.paragraphs.some(hasNotesFormatting)) {\n\t\tnotes.note(\n\t\t\t'notes.formatting',\n\t\t\t'flattened',\n\t\t\t'unsupported',\n\t\t\t\"speaker notes carry as plain text; per-run formatting, hyperlinks, bullets and indent levels, and the notes slide's own placeholder geometry, do not\"\n\t\t)\n\t}\n\treturn { notesText: text }\n}\n\n/**\n * `true` when a speaker-notes paragraph states anything plain text cannot carry.\n *\n * `addNotes` takes plain text. The note used to fire for bold and italic only, so underline,\n * strike, colour, size, face, highlight, a hyperlink, a bullet or an indent level went with\n * nothing said. An explicit off (`u=\"none\"`, `strike=\"noStrike\"`, a suppressed bullet) is how plain\n * text reads anyway, so it does not count. Reads accessors only: `runOptions` would record colour\n * notes for text that emits no call.\n */\nfunction hasNotesFormatting(paragraph: Paragraph): boolean {\n\tif (paragraph.level > 0) return true\n\tconst bullet = paragraph.bulletDetail\n\tif (bullet !== null && bullet.kind !== 'none') return true\n\treturn paragraph.runs.some(\n\t\t(run) =>\n\t\t\trun.bold === true ||\n\t\t\trun.italic === true ||\n\t\t\t(run.underline !== null && run.underline !== 'none') ||\n\t\t\t(run.strike !== null && run.strike !== 'noStrike') ||\n\t\t\trun.color !== null ||\n\t\t\trun.schemeColor !== null ||\n\t\t\trun.fontSizePt !== null ||\n\t\t\trun.fontName !== null ||\n\t\t\trun.highlight !== null ||\n\t\t\trun.hyperlink !== null\n\t)\n}\n\n/**\n * Build animations, which live in a slide-scoped `p:timing` element rather than in any\n * shape's subtree.\n *\n * The transition next door used to be recorded here for the same reason and is now mapped\n * instead (`from-read/transition.ts`), which leaves this the one genuinely slide-scoped\n * loss: there is no structural reader for `p:timing` at all, only spid manipulation for the\n * deck-to-deck import path, so a build sequence is invisible to this converter.\n */\nfunction recordAnimationLoss(slide: Slide, notes: NoteScope): void {\n\tif (slide.hasAnimations) {\n\t\tnotes.note(\n\t\t\t'slide.animation',\n\t\t\t'dropped',\n\t\t\t'unread',\n\t\t\t'build animations have no structural reader (p:timing is only manipulated by spid for the deck-to-deck import path), so every shape on this slide lands static'\n\t\t)\n\t}\n}\n","/**\n * {@link IrValue} → TypeScript source text.\n *\n * This module is deliberately the dumbest part of the subsystem. It knows nothing about\n * decks, shapes, or units — only how a value is spelled. Every semantic decision was made\n * upstream in the read half, which is what lets the printed text be checked by comparing\n * IRs rather than by reading source: if this file were allowed to interpret, the same\n * construct could mean two things depending on which half you asked.\n *\n * Two consequences worth stating, because they are easy to erode later:\n *\n * - **Numbers are printed, not reformatted.** The IR already holds geometry either as a\n * `` `${n}emu` `` string (exact) or as a six-decimal inch number (the proven minimum for\n * an EMU-exact round-trip). Rounding here to suppress `0.5000000001`-style noise would\n * turn a cosmetic problem into a real geometry loss, so `printNumber` only refuses\n * values JavaScript cannot spell back.\n * - **Layout is a function of the value alone.** Whether an object prints on one line or\n * several depends only on its rendered width, never on where it came from, so the same\n * deck prints byte-identical text every time.\n */\nimport { isAssetRef, type AssetRef, type IrValue } from '../ir.js'\nimport { InvalidOptionError } from '../../errors.js'\n\n/** Matches `.oxfmtrc.jsonc`: `printWidth: 120`. */\nconst MAX_WIDTH = 120\n\n/**\n * Columns a tab is assumed to occupy when measuring against {@link MAX_WIDTH}. The\n * formatter's default `tabWidth`, since the repo sets `useTabs` but not `tabWidth`.\n */\nconst TAB_COLUMNS = 2\n\n/** A bare object key needs no quotes only if it is a plain identifier. */\nconst IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/\n\n/**\n * Resolves an {@link AssetRef} to the source text that stands in for it — a `const`\n * identifier when assets are written as files, an inline `data:` literal otherwise. The\n * printer takes this as a callback rather than deciding itself, because the choice belongs\n * to the caller's output layout, not to how a value is spelled.\n */\nexport type AssetPrinter = (ref: AssetRef) => string\n\n/**\n * A string literal in the repo's style (`singleQuote: true`).\n *\n * Deck text is arbitrary user content, so every case below is reachable in practice: a\n * quote, a backslash, a hard line break inside a run. `JSON.stringify` would handle those\n * correctly — it is avoided here for the quote style, not for correctness.\n */\nexport function printString(value: string): string {\n\tlet out = \"'\"\n\tfor (const char of value) {\n\t\tswitch (char) {\n\t\t\tcase '\\\\':\n\t\t\t\tout += '\\\\\\\\'\n\t\t\t\tbreak\n\t\t\tcase \"'\":\n\t\t\t\tout += \"\\\\'\"\n\t\t\t\tbreak\n\t\t\tcase '\\n':\n\t\t\t\tout += '\\\\n'\n\t\t\t\tbreak\n\t\t\tcase '\\r':\n\t\t\t\tout += '\\\\r'\n\t\t\t\tbreak\n\t\t\tcase '\\t':\n\t\t\t\tout += '\\\\t'\n\t\t\t\tbreak\n\t\t\tdefault: {\n\t\t\t\tconst code = char.codePointAt(0) ?? 0\n\t\t\t\t// C0/C1 controls have no visible spelling, so a raw one is invisible corruption.\n\t\t\t\t// U+2028/U+2029 have been legal inside a string literal since ES2019 and do not\n\t\t\t\t// strictly need escaping for a modern engine — they are escaped anyway because\n\t\t\t\t// they remain line terminators everywhere *else* in the grammar, and a file that\n\t\t\t\t// depends on that distinction is a poor thing to hand to an unknown toolchain.\n\t\t\t\t// A lone surrogate (half a pair with no other half) has no UTF-8 encoding, so written raw\n\t\t\t\t// it lands in the file as U+FFFD and the script holds a different string from the IR.\n\t\t\t\t// `for…of` walks code points, so a well-formed pair arrives here whole and never matches.\n\t\t\t\t// Everything else rides through, so the script stays readable in the deck's language.\n\t\t\t\tconst escape =\n\t\t\t\t\tcode < 0x20 ||\n\t\t\t\t\t(code >= 0x7f && code <= 0x9f) ||\n\t\t\t\t\tcode === 0x2028 ||\n\t\t\t\t\tcode === 0x2029 ||\n\t\t\t\t\t(code >= 0xd800 && code <= 0xdfff)\n\t\t\t\tout += escape ? '\\\\u' + code.toString(16).padStart(4, '0') : char\n\t\t\t}\n\t\t}\n\t}\n\treturn `${out}'`\n}\n\n/**\n * What ends a `//` comment: CR, LF, and U+2028 and U+2029, which ECMAScript counts as line\n * terminators too. Built from code points because those two, written raw, would end a regex\n * literal just as they end a comment.\n */\nconst LINE_TERMINATORS = new RegExp(`[\\r\\n${String.fromCharCode(0x2028, 0x2029)}]`, 'g')\n\n/**\n * Deck text made safe to sit inside a comment: the `/* … *\\/` banner or a `//` line.\n *\n * A comment is the one place the printer puts deck text with no literal around it, and two\n * things end one early, turning the rest into code: `*\\/` closes a block comment, and a line\n * terminator closes a line comment. `JSON.stringify` escapes CR and LF but leaves U+2028 and\n * U+2029 raw, and ECMAScript counts both as line terminators, so a layout named across a line\n * separator broke the script it was printed into.\n */\nexport function commentText(text: string): string {\n\treturn text.replace(/\\*\\//g, '*\\\\/').replace(LINE_TERMINATORS, ' ')\n}\n\n/**\n * A number literal. `String` gives the shortest text that reads back as the same double,\n * which is exactly the guarantee needed: the printed script must produce the same value the\n * IR held. Non-finite values cannot satisfy that (`NaN` and `Infinity` are identifiers, not\n * literals) and never reach here from a well-formed IR, so they throw rather than emit\n * source that would not run.\n */\nfunction printNumber(value: number): string {\n\tif (!Number.isFinite(value))\n\t\tthrow new InvalidOptionError('script/non-finite-literal', `Cannot print a non-finite number: ${value}`)\n\treturn String(value)\n}\n\n/** An object key, bare when it is a plain identifier and quoted when it is not. */\nfunction printKey(key: string): string {\n\treturn IDENTIFIER.test(key) ? key : printString(key)\n}\n\n/** The value on a single line, however long that line comes out. */\nfunction inline(value: IrValue, asset: AssetPrinter): string {\n\tif (value === null) return 'null'\n\tif (typeof value === 'boolean') return String(value)\n\tif (typeof value === 'number') return printNumber(value)\n\tif (typeof value === 'string') return printString(value)\n\tif (isAssetRef(value)) return asset(value)\n\tif (Array.isArray(value)) return `[${value.map((item) => inline(item, asset)).join(', ')}]`\n\n\tconst keys = Object.keys(value)\n\tif (keys.length === 0) return '{}'\n\treturn `{ ${keys.map((key) => `${printKey(key)}: ${inline(value[key] as IrValue, asset)}`).join(', ')} }`\n}\n\n/**\n * The value as source text, broken across lines only where it would otherwise overflow\n * {@link MAX_WIDTH}.\n *\n * `indentLevel` is the depth the value *starts* at, so a caller that has already written a\n * prefix (`slide1.addText(`) passes the level its closing brace should line up with.\n */\nexport function printValue(value: IrValue, indentLevel: number, asset: AssetPrinter): string {\n\tconst flat = inline(value, asset)\n\tif (indentLevel * TAB_COLUMNS + flat.length <= MAX_WIDTH) return flat\n\n\t// Only containers can be broken up; a single long string or number stays long.\n\tconst pad = '\\t'.repeat(indentLevel)\n\tconst inner = '\\t'.repeat(indentLevel + 1)\n\n\tif (Array.isArray(value)) {\n\t\tif (value.length === 0) return '[]'\n\t\tconst items = value.map((item) => `${inner}${printValue(item, indentLevel + 1, asset)},`)\n\t\treturn `[\\n${items.join('\\n')}\\n${pad}]`\n\t}\n\n\tif (typeof value === 'object' && value !== null && !isAssetRef(value)) {\n\t\tconst keys = Object.keys(value)\n\t\tif (keys.length === 0) return '{}'\n\t\tconst entries = keys.map(\n\t\t\t(key) => `${inner}${printKey(key)}: ${printValue(value[key] as IrValue, indentLevel + 1, asset)},`\n\t\t)\n\t\treturn `{\\n${entries.join('\\n')}\\n${pad}}`\n\t}\n\n\treturn flat\n}\n\n/**\n * A call's argument list, either inline after `prefix` or one argument per line.\n *\n * The decision is made on the *whole* call rather than per argument, so a call either reads\n * as one line or as a list — never as a short first argument followed by a hanging brace,\n * which is what a per-argument rule produces.\n */\nexport function printArguments(prefix: string, args: IrValue[], indentLevel: number, asset: AssetPrinter): string {\n\tconst pad = '\\t'.repeat(indentLevel)\n\tconst flat = `${pad}${prefix}(${args.map((arg) => inline(arg, asset)).join(', ')})`\n\tif (indentLevel * TAB_COLUMNS + flat.length - pad.length <= MAX_WIDTH) return flat\n\n\t// No trailing comma after the final argument: `trailingComma: 'es5'` adds them inside\n\t// objects and arrays but not to an argument list, so one here would be reformatted away.\n\tconst inner = '\\t'.repeat(indentLevel + 1)\n\tconst printed = args.map((arg) => `${inner}${printValue(arg, indentLevel + 1, asset)}`)\n\treturn `${pad}${prefix}(\\n${printed.join(',\\n')}\\n${pad})`\n}\n","/**\n * The parts of printing a script that do not depend on which tier is being printed.\n *\n * Two printers target the same IR — one anchored to the source deck as a template, one\n * standalone — and they differ only in how a deck and its chrome are set up. Everything after\n * that is identical: a slide's statements, how image bytes reach the script, and how the\n * fidelity notes are rendered into the banner. Keeping that here is not tidiness. A slide body\n * printed two slightly different ways would mean the round-trip oracle certifies one tier and\n * only resembles a check on the other, and the drift would be invisible in review.\n */\nimport { asIrValue, type AssetRef, type DeckIr, type IrValue, type SlideIr } from '../ir.js'\nimport { inches } from '../units.js'\nimport { scopeNotes, type FidelityNote, type NoteCollector } from '../fidelity.js'\nimport { commentText, printArguments, printString, printValue, type AssetPrinter } from './literal.js'\nimport { InvalidOptionError } from '../../errors.js'\nimport { bytesToBase64 } from '../../media/base64.js'\n\n/** How image bytes reach the emitted script. */\nexport type AssetMode =\n\t/** Written beside the script and read at run time. Keeps the script readable. */\n\t| 'file'\n\t/** Inlined as `data:` literals. One self-contained file, at roughly 4/3 the byte size. */\n\t| 'inline'\n\nexport interface PrintedScript {\n\t/** The TypeScript module source. */\n\tcode: string\n\t/**\n\t * Image bytes the script expects to find in its asset directory, keyed by filename.\n\t * Empty when the print options asked for `'inline'`, since the bytes are then in\n\t * {@link code}.\n\t */\n\tassets: Map<string, Uint8Array>\n\t/**\n\t * The losses that apply to **this** output: the IR's own notes, minus any this tier\n\t * rescues, plus the ones this tier causes. Reproduced as a comment block at the top of\n\t * {@link code}, so the artifact carries its own caveats.\n\t */\n\tnotes: FidelityNote[]\n}\n\n/** The print options both tiers take. */\nexport interface CommonPrintOptions {\n\t/** Path the emitted script writes to, resolved against the script's own location. @default './output.pptx' */\n\toutputPath?: string\n\t/** Directory the emitted script reads image assets from, when {@link assets} is `'file'`. @default './assets' */\n\tassetDir?: string\n\t/** @default 'file' */\n\tassets?: AssetMode\n\t/**\n\t * Import specifier the emitted script uses; the template-anchored tier also imports its `/read`\n\t * subpath. Defaults to this package's own published name; override it to point a generated\n\t * script at a local build or a fork.\n\t * @default 'pptx-ts'\n\t */\n\tpackageName?: string\n}\n\n/**\n * Default import specifier for an emitted script — this package's *published* name, which is\n * not its directory name. Getting it wrong produces a script that prints and typechecks and\n * then fails at `import`, so it is pinned by a test rather than left to a literal.\n */\nconst PACKAGE_NAME = 'pptx-ts'\n\n/** The print options both tiers share, with their defaults applied. */\ninterface ResolvedPrintOptions {\n\t/** Where the emitted script writes its deck, resolved against the script's own location. */\n\toutputPath: string\n\t/** Where the emitted script reads image assets from, with any trailing slash stripped. */\n\tassetDir: string\n\t/** Whether image bytes are written beside the script or inlined as `data:` literals. */\n\tassetMode: AssetMode\n\t/** The import specifier the emitted script uses. */\n\tpackageName: string\n}\n\n/**\n * Apply the defaults both printers share.\n *\n * `templatePath` is deliberately not here: only the template-anchored tier has one, and that\n * difference is the whole reason there are two printers.\n * @param options - the caller's options, any of which may be absent\n */\nexport function resolvePrintOptions(options: CommonPrintOptions): ResolvedPrintOptions {\n\treturn {\n\t\toutputPath: options.outputPath ?? './output.pptx',\n\t\t// A trailing slash would print `./assets/` and then join another, so it is stripped once\n\t\t// here rather than defended against at each of the places the directory is interpolated.\n\t\tassetDir: (options.assetDir ?? './assets').replace(/\\/$/, ''),\n\t\tassetMode: options.assets ?? 'file',\n\t\tpackageName: options.packageName ?? PACKAGE_NAME,\n\t}\n}\n\n/** Width the header comment's prose wraps at, leaving room for the ` * ` prefix. */\nconst COMMENT_WIDTH = 110\n\n/**\n * A stable JavaScript identifier per asset.\n *\n * Derived from the asset's own name rather than its index, so a reader can match a `const`\n * in the script against a file in the asset directory. The dedupe suffix is defensive: the\n * read half currently names assets `image1.png`, `image2.jpg`, … which cannot collide after\n * the extension is stripped, but nothing in the IR contract promises that.\n */\nexport function assetIdentifiers(ir: DeckIr): Map<string, string> {\n\tconst out = new Map<string, string>()\n\tconst used = new Set<string>()\n\tfor (const asset of ir.assets) {\n\t\tconst raw = asset.name.replace(/\\.[^.]*$/, '').replace(/[^A-Za-z0-9_$]/g, '_')\n\t\t// The SANITISED base seeds the collision candidates too. Re-deriving them from the raw\n\t\t// one made the first candidate for a name starting with a digit `_1image` and the next\n\t\t// `1image_2` — not a legal identifier, so the emitted script would not parse.\n\t\tconst base = /^[A-Za-z_$]/.test(raw) ? raw : `_${raw}`\n\t\tlet identifier = base\n\t\tlet suffix = 2\n\t\twhile (used.has(identifier)) identifier = `${base}_${suffix++}`\n\t\tused.add(identifier)\n\t\tout.set(asset.name, identifier)\n\t}\n\treturn out\n}\n\n/** An {@link AssetPrinter} and the assets it has printed so far. */\nexport interface RecordingAssetPrinter {\n\t/** Resolve an {@link AssetRef} to the `const` identifier standing for its bytes, and record it. */\n\tprint: AssetPrinter\n\t/** The name of every asset {@link print} has resolved. */\n\tprinted: ReadonlySet<string>\n}\n\n/**\n * Resolve an {@link AssetRef} to the `const` identifier standing for its bytes, remembering which\n * assets were printed.\n *\n * `printed`, not `DeckIr.assets`, is what a tier binds and returns. The chrome registers its\n * pictures through the same resolver as the slides, so a layout's background and logo are in\n * `DeckIr.assets`, and so are a carried slide's images. The template-anchored tier prints neither\n * (its template *is* the chrome, and a carried slide is copied), yet it bound every asset with a\n * `readFile`, returned the bytes, counted them in the banner and, in `'inline'` mode, inlined\n * them. So each tier prints its statements first and binds what they referenced.\n */\nexport function assetPrinter(identifiers: Map<string, string>): RecordingAssetPrinter {\n\tconst printed = new Set<string>()\n\tconst print = (ref: AssetRef): string => {\n\t\tconst identifier = identifiers.get(ref.$asset)\n\t\tif (!identifier)\n\t\t\tthrow new InvalidOptionError(\n\t\t\t\t'script/unresolved-asset-reference',\n\t\t\t\t`Asset reference ${ref.$asset} has no entry in DeckIr.assets`\n\t\t\t)\n\t\tprinted.add(ref.$asset)\n\t\treturn identifier\n\t}\n\treturn { print, printed }\n}\n\n/**\n * One `const` per printed asset, each holding a complete `data:` URI.\n *\n * Both modes bind the same *kind* of value — a data URI string — so the call sites are\n * identical and `addImage`'s `data` option is used either way. Only where the bytes come\n * from changes. Rewriting the option key to `path` in file mode would have the printer\n * reshaping an argument, which is precisely the thing that keeps the IR checkable.\n *\n * Bound in `DeckIr.assets` order rather than first-printed order, so the output stays a function\n * of the IR. `printed` comes from {@link assetPrinter}.\n */\nexport function printAssetBindings(\n\tir: DeckIr,\n\tidentifiers: Map<string, string>,\n\tassetDir: string,\n\tmode: AssetMode,\n\tprinted: ReadonlySet<string>,\n\tinlineComment = '// Media bytes, inlined so this script needs no files but its template.'\n): string[] {\n\tconst bound = printedAssets(ir, printed)\n\tif (bound.length === 0) return []\n\n\tconst lines =\n\t\tmode === 'file' ? ['// Media bytes, loaded from the asset directory beside this script.'] : [inlineComment]\n\n\tfor (const asset of bound) {\n\t\tconst identifier = identifiers.get(asset.name)\n\t\tif (!identifier) continue\n\t\tif (mode === 'file') {\n\t\t\t// The prefix is a string literal of its own, never text inside a template literal: the\n\t\t\t// content type comes from the deck, and a `${` in it would be code in the script.\n\t\t\tconst path = printString(`${assetDir}/${asset.name}`)\n\t\t\tconst prefix = printString(`data:${asset.contentType};base64,`)\n\t\t\tlines.push(`const ${identifier} = ${prefix} + (await readFile(here(${path}))).toString('base64')`)\n\t\t} else {\n\t\t\tlines.push(\n\t\t\t\t`const ${identifier} = ${printString(`data:${asset.contentType};base64,${bytesToBase64(asset.bytes)}`)}`\n\t\t\t)\n\t\t}\n\t}\n\treturn lines\n}\n\n/**\n * One slide: a comment, the statement that creates it, then its slide-level properties and\n * its calls in z-order.\n *\n * `comment` and `construction` are the tier's business — one binds a layout by name at append\n * time, the other names a master up front — and everything after them is not.\n */\nexport function printSlide(\n\tslide: SlideIr,\n\tparts: { comment: string; construction: string },\n\tcollector: NoteCollector,\n\tprintAsset: AssetPrinter\n): string[] {\n\tconst notes = scopeNotes(collector, slide.number)\n\tconst identifier = `slide${slide.number}`\n\tconst lines = ['', `// ${commentText(parts.comment)}`, `const ${identifier} = ${parts.construction}`]\n\n\tif (slide.name !== undefined) {\n\t\tnotes.note(\n\t\t\t'slide.name',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t`the slide's own name (p:cSld@name, here ${JSON.stringify(slide.name)}) has no public write-API setter, so the generated slide is unnamed`\n\t\t)\n\t}\n\n\tif (slide.hidden) lines.push(`${identifier}.hidden = true`)\n\tif (slide.background) {\n\t\tlines.push(`${identifier}.background = ${printValue(slide.background as IrValue, 0, printAsset)}`)\n\t}\n\tif (slide.transition) {\n\t\tlines.push(`${identifier}.transition = ${printValue(asIrValue(slide.transition), 0, printAsset)}`)\n\t}\n\tif (slide.notesText !== undefined) {\n\t\tlines.push(printArguments(`${identifier}.addNotes`, [slide.notesText], 0, printAsset))\n\t}\n\n\tfor (const call of slide.calls) {\n\t\t// The source shape name makes a fidelity note navigable: a note carries the same\n\t\t// name, and without it a reader has no way to find the call it refers to.\n\t\tif (call.sourceName) lines.push(`// ${commentText(call.sourceName.replace(/\\s+/g, ' '))}`)\n\t\tlines.push(printArguments(`${identifier}.${call.method}`, call.args, 0, printAsset))\n\t}\n\n\treturn lines\n}\n\n/** The banner comment: `prose` as written, then every loss that applies to this output. */\nexport function header(prose: string[], notes: FidelityNote[]): string {\n\tconst lines = [...prose, '']\n\n\tif (notes.length === 0) {\n\t\tlines.push('FIDELITY: nothing was lost that this converter can detect.')\n\t} else {\n\t\tlines.push(\n\t\t\t`FIDELITY: ${notes.length} declared loss(es). Everything not listed here is expected to`,\n\t\t\t'survive unchanged; a difference that is not in this list is a defect, not a caveat.',\n\t\t\t''\n\t\t)\n\t\tfor (const [scope, group] of groupNotes(notes)) {\n\t\t\tlines.push(`${scope}:`)\n\t\t\tfor (const note of group) {\n\t\t\t\tconst where = note.shapeName ? ` (${note.shapeName})` : ''\n\t\t\t\tlines.push(\n\t\t\t\t\t...wrap(\n\t\t\t\t\t\t`- ${note.construct}${where} [${note.disposition}, ${note.cause}] — ${note.detail}`,\n\t\t\t\t\t\tCOMMENT_WIDTH,\n\t\t\t\t\t\t' '\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Every line through `commentText`: a note's detail quotes slide and layout names, and a `*/`\n\t// in one closed the banner and left the rest of it to be parsed as code.\n\treturn ['/*', ...lines.map((line) => (line ? ` * ${commentText(line)}` : ' *')), ' */'].join('\\n')\n}\n\n/** Notes bucketed by slide, in deck order, so a reader meets them the way they meet the deck. */\nfunction groupNotes(notes: FidelityNote[]): Array<[string, FidelityNote[]]> {\n\tconst deckLevel = notes.filter((note) => note.slideNumber === null)\n\tconst bySlide = new Map<number, FidelityNote[]>()\n\tfor (const note of notes) {\n\t\tif (note.slideNumber === null) continue\n\t\tconst existing = bySlide.get(note.slideNumber)\n\t\tif (existing) existing.push(note)\n\t\telse bySlide.set(note.slideNumber, [note])\n\t}\n\n\tconst out: Array<[string, FidelityNote[]]> = []\n\tif (deckLevel.length > 0) out.push(['Deck', deckLevel])\n\tfor (const number of [...bySlide.keys()].sort((a, b) => a - b)) {\n\t\tout.push([`Slide ${number}`, bySlide.get(number) ?? []])\n\t}\n\treturn out\n}\n\n/** Wrap prose to `width`, indenting every line after the first by `continuation`. */\nfunction wrap(text: string, width: number, continuation: string): string[] {\n\tconst words = text.split(/\\s+/).filter(Boolean)\n\tconst lines: string[] = []\n\tlet current = ''\n\tfor (const word of words) {\n\t\tconst candidate = current ? `${current} ${word}` : `${continuation}${word}`\n\t\tif (current && candidate.length > width) {\n\t\t\tlines.push(current)\n\t\t\tcurrent = `${continuation}${word}`\n\t\t} else {\n\t\t\tcurrent = current ? candidate : word\n\t\t}\n\t}\n\tif (current) lines.push(current)\n\treturn lines\n}\n\n/**\n * Close out a printed script: the accumulated lines as one module source, plus the\n * asset side-car the caller has to write beside it.\n *\n * Both tiers end this way, and the `assetMode` test is the whole reason it is worth\n * naming. In `'inline'` mode the bytes are already in {@link PrintedScript.code} as\n * `data:` literals, so the map must come back **empty** — a tier that returned them\n * anyway would have its caller write every image to disk as well, and the script would\n * ignore the files it was handed.\n * @param {string[]} lines - the script's lines, in order\n * @param {DeckIr} ir - the IR being printed, for its assets\n * @param {AssetMode} assetMode - how image bytes reach the script\n * @param {FidelityNote[]} notes - the losses that apply to this output\n * @param {ReadonlySet<string>} printed - the assets the script's statements reference\n * @returns {PrintedScript} the finished script\n */\nexport function printedScript(\n\tlines: string[],\n\tir: DeckIr,\n\tassetMode: AssetMode,\n\tnotes: FidelityNote[],\n\tprinted: ReadonlySet<string>\n): PrintedScript {\n\treturn {\n\t\tcode: lines.join('\\n'),\n\t\tassets: new Map(\n\t\t\tassetMode === 'file'\n\t\t\t\t? printedAssets(ir, printed).map((asset): [string, Uint8Array] => [asset.name, asset.bytes])\n\t\t\t\t: []\n\t\t),\n\t\tnotes,\n\t}\n}\n\n/** The IR's assets a script printed, in `DeckIr.assets` order. */\nfunction printedAssets(ir: DeckIr, printed: ReadonlySet<string>): DeckIr['assets'] {\n\treturn ir.assets.filter((asset) => printed.has(asset.name))\n}\n\n/**\n * The emitted script's imports and its `here` helper, which every path it reads or writes goes\n * through.\n *\n * Both tiers printed this block line by line and differed only in what they import: the\n * template-anchored one reads and writes files and opens the source deck through the read half,\n * while the standalone one reads files only when it has media to load.\n * @param packageName - the import specifier, from the print options\n * @param imports - the `node:fs/promises` names to import, and whether to import the read half\n */\nexport function printPreamble(packageName: string, imports: { fs: readonly string[]; read: boolean }): string[] {\n\treturn [\n\t\t...(imports.fs.length > 0 ? [`import { ${imports.fs.join(', ')} } from 'node:fs/promises'`] : []),\n\t\t\"import { fileURLToPath } from 'node:url'\",\n\t\t`import TsPptx from ${printString(packageName)}`,\n\t\t...(imports.read ? [`import { Presentation } from ${printString(`${packageName}/read`)}`] : []),\n\t\t'',\n\t\t'/** Resolve a path against this script rather than against the working directory. */',\n\t\t'const here = (name: string): string => fileURLToPath(new URL(name, import.meta.url))',\n\t]\n}\n\n/**\n * The three lines that construct a generator and size it to the source deck.\n *\n * Both tiers print them, and both used to convert the EMU slide size themselves — reaching\n * across the seam into `from-read/values.ts` to do it. `ir.ts` keeps `slideSize` in EMU\n * deliberately, because converting there \"would introduce a rounding decision at the wrong\n * layer\"; the printer is not that layer either, so the conversion lives in `script/units.ts`\n * and the two-line preamble lives here.\n *\n * `appendSlides` compares slide sizes exactly and throws when they differ, so a change to the\n * printed inches fails loudly rather than quietly.\n * @param size - the deck's slide size, in EMU\n * @param indent - the prefix each line takes; the tier-B generator emits them inside a function\n */\nexport function printLayoutSetup(size: { widthEmu: number; heightEmu: number }, indent = ''): string[] {\n\treturn [\n\t\t`${indent}const pptx = new TsPptx()`,\n\t\t`${indent}pptx.defineLayout({ name: 'source', width: ${inches(size.widthEmu)}, height: ${inches(size.heightEmu)} })`,\n\t\t`${indent}pptx.layout = 'source'`,\n\t]\n}\n","/**\n * {@link DeckIr} → a runnable TypeScript module, template-anchored. **Tier B.**\n *\n * **The tier.** The emitted script reuses the *source deck itself* as its template:\n * `Presentation.fromTemplate` strips a package's slides while leaving its masters, layouts,\n * theme, and document properties byte-identical, so the chrome is never regenerated — it is\n * the original. Only the slides are rebuilt, through the public write API, and grafted back\n * with `appendSlides`. That is why this tier's fidelity note list is short: everything the\n * converter cannot see or cannot write is confined to slide content, and the whole of the\n * deck's design survives because nothing ever tried to reproduce it.\n *\n * It also means the plan's \"strip the source slides\" step needs no helper. `fromTemplate`\n * already does exactly that, and does it without pruning shared parts, so the template\n * asset and the source deck are the same file.\n *\n * **Order is not rearranged.** Slides are emitted in source order and every operation\n * appends, so `p:sldIdLst` comes out in the original order without any position arithmetic.\n * Contiguous slides sharing a layout share one generator, because `appendSlides` binds\n * every slide in one call to a single layout — the batching is forced by that signature,\n * not chosen for tidiness.\n *\n * **This module may add fidelity notes.** A loss can belong to the *tier* rather than to\n * the conversion — a slide's `p:cSld@name` is read fine and would survive a byte copy, but\n * has no public write-API setter, so it dies here and nowhere else. {@link PrintedScript}\n * therefore returns the notes that actually apply to *this* output, which is also the set a\n * round-trip check should exclude from its diff.\n *\n * The standalone counterpart is `printStandaloneScript` (Tier A), which prints the same IR\n * with no template at all and pays for it in the note list.\n */\nimport type { DeckIr, SlideIr } from '../ir.js'\nimport {\n\tNoteCollector,\n\tUNWRITABLE_FRAME_CONSTRUCTS,\n\tnoteAppliesTo,\n\tscopeNotes,\n\ttype FidelityNote,\n} from '../fidelity.js'\nimport { commentText, printString, type AssetPrinter } from './literal.js'\nimport {\n\tassetIdentifiers,\n\tassetPrinter,\n\theader,\n\tprintAssetBindings,\n\tprintLayoutSetup,\n\tprintPreamble,\n\tprintSlide,\n\tprintedScript,\n\tresolvePrintOptions,\n\ttype CommonPrintOptions,\n\ttype PrintedScript,\n} from './common.js'\n\nexport type { AssetMode, PrintedScript } from './common.js'\n\nexport interface PrintScriptOptions extends CommonPrintOptions {\n\t/**\n\t * Path the emitted script loads its template from, resolved against the script's own\n\t * location. This is the **source deck unchanged** — `fromTemplate` strips its slides.\n\t * @default './template.pptx'\n\t */\n\ttemplatePath?: string\n}\n\n/** Turn a deck IR into a runnable, template-anchored TypeScript module. */\nexport function printScript(ir: DeckIr, options: PrintScriptOptions = {}): PrintedScript {\n\tconst templatePath = options.templatePath ?? './template.pptx'\n\tconst { outputPath, assetDir, assetMode, packageName } = resolvePrintOptions(options)\n\n\tconst collector = new NoteCollector()\n\tconst assetNames = assetIdentifiers(ir)\n\tconst assets = assetPrinter(assetNames)\n\tconst printAsset = assets.print\n\n\tconst body = printSlides(ir, collector, printAsset)\n\tconst needsSource = ir.slides.some((slide) => slide.source === 'carried')\n\tconst needsFallbackLayout = ir.slides.some((slide) => slide.source === 'authored' && slide.layout === null)\n\n\t// Built last: the tier's own notes are only known once the slides have been walked.\n\t// Each construct's catalogue entry says which tiers it applies to; the chrome's losses, for one,\n\t// are carried by the template rather than lost here.\n\tconst carried = new Set(ir.slides.filter((slide) => slide.source === 'carried').map((slide) => slide.number))\n\tconst notes = [...ir.fidelity, ...collector.notes].filter(\n\t\t(note) => noteAppliesTo(note.construct, 'template') && !transcriptionOfCarried(note, carried)\n\t)\n\n\tconst lines: string[] = [\n\t\theader(\n\t\t\t[\n\t\t\t\t'Generated from a .pptx by ts-pptx/script.',\n\t\t\t\t'',\n\t\t\t\t'Template-anchored: the source deck is reused as the template, so its slide masters,',\n\t\t\t\t'layouts, theme and document properties are the originals, byte for byte. Only the',\n\t\t\t\t'slide content below was rebuilt through the public write API.',\n\t\t\t\t'',\n\t\t\t\t`Expects ${templatePath} (the source deck, unmodified) beside this file${\n\t\t\t\t\t// Counted after the slides were printed: only what they reference ships. The chrome's\n\t\t\t\t\t// pictures stay in the template, and a carried slide is copied with its own.\n\t\t\t\t\tassetMode === 'file' && assets.printed.size > 0\n\t\t\t\t\t\t? `, plus ${assets.printed.size} media file(s) in ${assetDir}`\n\t\t\t\t\t\t: ''\n\t\t\t\t}.`,\n\t\t\t\t`Writes ${outputPath}. Needs an ESM context — it uses top-level await.`,\n\t\t\t],\n\t\t\tnotes\n\t\t),\n\t\t'',\n\t\t...printPreamble(packageName, { fs: ['readFile', 'writeFile'], read: true }),\n\t\t'',\n\t\t'// The source deck is the template: fromTemplate strips its slides and leaves its masters,',\n\t\t'// layouts, theme and document properties exactly as they were.',\n\t\t`const deck = await Presentation.fromTemplate(here(${printString(templatePath)}))`,\n\t]\n\n\tif (needsSource) {\n\t\tlines.push(\n\t\t\t'',\n\t\t\t'// A second, unstripped handle on the same file, for the slides copied verbatim.',\n\t\t\t`const source = await Presentation.load(here(${printString(templatePath)}))`\n\t\t)\n\t}\n\n\tif (needsFallbackLayout) {\n\t\tlines.push(\n\t\t\t'',\n\t\t\t'// Some source slides resolved no layout of their own; they bind to the first one.',\n\t\t\t'const fallbackLayout = deck.layouts()[0]',\n\t\t\t\"if (!fallbackLayout) throw new Error('the template declares no slide layouts to bind to')\"\n\t\t)\n\t}\n\n\tconst assetLines = printAssetBindings(ir, assetNames, assetDir, assetMode, assets.printed)\n\tif (assetLines.length > 0) lines.push('', ...assetLines)\n\n\tlines.push(\n\t\t'',\n\t\t'/**',\n\t\t' * A generator sized to the template. appendSlides compares slide sizes exactly and',\n\t\t' * throws when they differ, so the inches here must round-trip to the source EMU.',\n\t\t' */',\n\t\t'function generator(): TsPptx {',\n\t\t...printLayoutSetup(ir.slideSize, '\\t'),\n\t\t'\\treturn pptx',\n\t\t'}',\n\t\t...body,\n\t\t'',\n\t\t`await writeFile(here(${printString(outputPath)}), await deck.save())`,\n\t\t''\n\t)\n\n\treturn printedScript(lines, ir, assetMode, notes, assets.printed)\n}\n\n/** The notes a slide this tier copies whole still reports: why it was copied, and what forced it. */\nconst CARRIED_SLIDE_CONSTRUCTS: ReadonlySet<string> = new Set([\n\t'slide.carried',\n\t...Object.values(UNWRITABLE_FRAME_CONSTRUCTS),\n])\n\n/**\n * `true` for a note about transcribing a slide this tier copies instead.\n *\n * The IR maps a carried slide's shapes anyway, for the standalone tier, and each records its own\n * losses. `importSlide` copies the slide whole, so here those losses do not happen, and\n * `slide.carried` already excuses every difference on it, so the round trip could not tell.\n */\nfunction transcriptionOfCarried(note: FidelityNote, carried: ReadonlySet<number>): boolean {\n\treturn note.slideNumber !== null && carried.has(note.slideNumber) && !CARRIED_SLIDE_CONSTRUCTS.has(note.construct)\n}\n\n/**\n * The slide statements, batched into generators, preceded by the layout handles they bind to.\n *\n * A batch ends when the layout changes or a carried slide interrupts, because\n * `appendSlides` binds one layout per call and a carried slide is not authored at all.\n *\n * Every layout `const` is hoisted above the first statement rather than emitted where it is\n * first used. `deck.layouts()` is a snapshot of the gallery, and `importSlide` — the call a\n * carried slide prints — grows that gallery with the source slide's own layout and master.\n * Resolving a handle after one has run is therefore resolving against a deck that has already\n * moved; capturing every handle up front is the only ordering that cannot.\n */\nfunction printSlides(ir: DeckIr, collector: NoteCollector, printAsset: AssetPrinter): string[] {\n\tconst declarations: string[] = []\n\tconst lines: string[] = []\n\tlet batch: SlideIr[] = []\n\tlet generatorIndex = 0\n\t// Two non-contiguous batches can share one layout, so its `const` must be emitted once.\n\tconst declaredLayouts = new Set<number>()\n\n\tconst flush = (): void => {\n\t\tif (batch.length === 0) return\n\t\tconst first = batch[0]\n\t\tif (!first) return\n\t\tconst name = `gen${++generatorIndex}`\n\t\tlines.push('', `const ${name} = generator()`)\n\t\tfor (const slide of batch) lines.push(...printAuthoredSlide(slide, name, collector, printAsset))\n\t\tlines.push('', printAppend(name, first, collector, declaredLayouts, declarations))\n\t\tbatch = []\n\t}\n\n\tfor (const slide of ir.slides) {\n\t\tif (slide.source === 'carried') {\n\t\t\tflush()\n\t\t\tlines.push(\n\t\t\t\t'',\n\t\t\t\t`// Slide ${slide.number} — copied from the source deck rather than rebuilt; see the fidelity notes.`,\n\t\t\t\t`deck.importSlide(source, ${slide.number - 1})`\n\t\t\t)\n\t\t\tcontinue\n\t\t}\n\t\t// A batch is one appendSlides call, which binds every slide in it to one layout.\n\t\tconst previous = batch[0]\n\t\tif (previous && previous.layout?.index !== slide.layout?.index) flush()\n\t\tbatch.push(slide)\n\t}\n\tflush()\n\n\treturn declarations.length > 0 ? ['', ...declarations, ...lines] : lines\n}\n\n/**\n * The `appendSlides` call closing a batch, binding by layout name where that is\n * unambiguous and by gallery position where it is not. Any handle it needs is appended to\n * `declarations`, which the caller hoists above every statement.\n *\n * Binding by name is preferred because it survives being re-pointed at a different\n * template and because it is legible. But `appendSlides` *throws* on an ambiguous name\n * rather than picking one, so the positional form resolves the case where the name does not\n * identify one layout: a multi-master deck that repeats layout names.\n *\n * A carried slide used to demote every binding in the script to a position too, because its\n * `importSlide` copied the source layout in under a second name-alike entry. `importSlide`\n * now binds to the chrome the template already holds (`read/api/ops/part-reuse.ts`), and\n * this deck's template *is* the source file, so the gallery no longer grows and the names\n * stay unambiguous.\n */\nfunction printAppend(\n\tgeneratorName: string,\n\tfirst: SlideIr,\n\tcollector: NoteCollector,\n\tdeclared: Set<number>,\n\tdeclarations: string[]\n): string {\n\tconst layout = first.layout\n\tif (!layout) return `await deck.appendSlides(${generatorName}, { layout: fallbackLayout })`\n\tif (layout.nameIsUnique) {\n\t\treturn `await deck.appendSlides(${generatorName}, { layout: ${printString(layout.name)} })`\n\t}\n\n\tscopeNotes(collector, first.number).note(\n\t\t'slide.layout',\n\t\t'approximated',\n\t\t'unsupported',\n\t\t`more than one layout in the source deck is named ${JSON.stringify(layout.name)}, so this slide binds to gallery position ${layout.index} instead; re-pointing the script at a different template will not track the name`\n\t)\n\tconst identifier = `layout${layout.index}`\n\tif (!declared.has(layout.index)) {\n\t\tdeclared.add(layout.index)\n\t\tdeclarations.push(\n\t\t\t`const ${identifier} = deck.layouts()[${layout.index}] // ${commentText(JSON.stringify(layout.name))}`,\n\t\t\t`if (!${identifier}) throw new Error('the template has no layout at position ${layout.index}')`\n\t\t)\n\t}\n\treturn `await deck.appendSlides(${generatorName}, { layout: ${identifier} })`\n}\n\n/** One authored slide, plus the layout-binding note this tier is responsible for. */\nfunction printAuthoredSlide(\n\tslide: SlideIr,\n\tgeneratorName: string,\n\tcollector: NoteCollector,\n\tprintAsset: AssetPrinter\n): string[] {\n\tif (slide.layout === null) {\n\t\tscopeNotes(collector, slide.number).note(\n\t\t\t'slide.layout',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t\"this slide resolves no layout of its own, so it binds to the template's first layout; that governs theme and clrMap resolution, which may differ from the source\"\n\t\t)\n\t}\n\n\t// A tier loss, and a narrow one: a transition's *stop-previous* form needs no relationship\n\t// and rides across fine, while an embedded start sound needs an audio part wired to the\n\t// appended slide. `extractSlides` never runs the registration pass that assigns it a\n\t// relationship id (`registerTransitionSounds` belongs to the package-assembly path), so the\n\t// emitter is handed no sound id and writes no `p:sndAc` at all. That is a silent drop rather\n\t// than a dangling reference — which is the safe failure of the two, and still a loss the\n\t// reader has to be told about. The standalone tier writes a real package and keeps it.\n\tif (slide.transition?.sound?.data !== undefined) {\n\t\tscopeNotes(collector, slide.number).note(\n\t\t\t'slide.transitionSound',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t\"this transition's start sound is dropped: the append path this tier rides does not register a transition's embedded audio part, so the sound does not reach the template. The assignment below still spells it out, and the WAV still ships beside the script, because both describe the source deck faithfully and would take effect the day the append path carries them — but this output is silent. Print the standalone variant to keep the sound\"\n\t\t)\n\t}\n\n\tconst layout = slide.layout === null ? 'no layout' : `layout ${JSON.stringify(slide.layout.name)}`\n\treturn printSlide(\n\t\tslide,\n\t\t{ comment: `Slide ${slide.number} — ${layout}`, construction: `${generatorName}.addSlide()` },\n\t\tcollector,\n\t\tprintAsset\n\t)\n}\n","/**\n * {@link DeckIr} → a runnable TypeScript module that depends on nothing but this package.\n * **Tier A.**\n *\n * **The trade, stated once.** The template-anchored printer (`printScript`) reuses the source\n * `.pptx` and gets the deck's entire design back byte for byte, at the cost of shipping that\n * file alongside the script and of leaving the design uneditable. This one ships a single\n * `.ts` file. Everything the source deck's chrome contained has to be *re-authored* from what\n * the read model exposes, and the read model deliberately exposes the property tiers a slide\n * inherits — colours, fonts, placeholder geometry — not the parts a slide merely sits on top\n * of. So the output is a deck that renders its slides faithfully and wears a different suit.\n *\n * **The ceiling is measured, not estimated, and no amount of printer work moves it.** Two\n * constructs are unreachable from *both* directions: `a:fmtScheme` (nothing reads it, and the\n * write path emits a hardcoded Office one) and `p:txStyles` (no reader, though\n * `SlideMasterProps.textStyles` could author it). A third, `p:clrMap`, is readable and has no\n * setter. Each is a fidelity note here and a `pass` in the other tier, which is the whole\n * reason the other tier shipped first. A **master's** own decoration joins them for a\n * structural reason rather than a reading one: `defineSlideMaster` creates a layout, so there\n * is no master shape tree to write to. A *layout's* decoration used to be on this list and is\n * not any more — it is transcribed into that layout's `objects`.\n *\n * **One structural difference beyond the chrome.** A slide marked `carried` has no source\n * package to be carried from here, so it is transcribed like any other and loses only the\n * construct that made it uncarryable — which each shape has already declared for itself. That\n * is why {@link DeckIr}'s calls are populated even for a carried slide.\n */\nimport { DECK_PROP_KEYS, uniqueTitle, type DeckIr, type IrValue, type MasterIr } from '../ir.js'\nimport { NoteCollector, andList, noteAppliesTo, scopeNotes } from '../fidelity.js'\nimport { printArguments, printString, printValue, type AssetPrinter } from './literal.js'\nimport {\n\tassetIdentifiers,\n\tassetPrinter,\n\theader,\n\tprintAssetBindings,\n\tprintLayoutSetup,\n\tprintPreamble,\n\tprintSlide,\n\tprintedScript,\n\tresolvePrintOptions,\n\ttype CommonPrintOptions,\n\ttype PrintedScript,\n} from './common.js'\n\n/** The standalone printer's options: exactly the ones both tiers share. */\nexport type PrintStandaloneScriptOptions = CommonPrintOptions\n\n/** Turn a deck IR into a runnable TypeScript module that needs no template. */\nexport function printStandaloneScript(ir: DeckIr, options: PrintStandaloneScriptOptions = {}): PrintedScript {\n\tconst { outputPath, assetDir, assetMode, packageName } = resolvePrintOptions(options)\n\n\tconst collector = new NoteCollector()\n\tconst assetNames = assetIdentifiers(ir)\n\tconst assets = assetPrinter(assetNames)\n\tconst printAsset = assets.print\n\n\t// EVERY part that records a note is walked before the header is built: this tier's own notes\n\t// are only known afterwards, and `notes` below is a snapshot of the collector rather than a\n\t// live view. `printDocProps` used to run after that snapshot was taken, so the one note it\n\t// records reached neither the header nor the returned list — it was collected and dropped.\n\tconst masters = printMasters(ir, collector, printAsset)\n\tconst body = printSlides(ir, collector, printAsset)\n\tconst props = printDocProps(ir, collector)\n\t// Printed up front too, for its asset references rather than its notes: the header counts, and\n\t// the bindings declare, only the assets something printed.\n\tconst theme = Object.keys(ir.chrome.theme).length > 0 ? printValue(ir.chrome.theme as IrValue, 0, printAsset) : null\n\tconst notes = [...ir.fidelity, ...collector.notes].filter((note) => noteAppliesTo(note.construct, 'standalone'))\n\n\tconst needsReadFile = assetMode === 'file' && assets.printed.size > 0\n\tconst lines: string[] = [\n\t\theader(\n\t\t\t[\n\t\t\t\t'Generated from a .pptx by ts-pptx/script.',\n\t\t\t\t'',\n\t\t\t\t`Standalone: this script needs nothing but ${packageName}${\n\t\t\t\t\tneedsReadFile ? ` and ${assets.printed.size} media file(s) in ${assetDir}` : ''\n\t\t\t\t}.`,\n\t\t\t\t\"The deck's theme, layouts and slide content are all re-authored through the public write\",\n\t\t\t\t'API, so every one of them is editable here — and the parts of the original design the read',\n\t\t\t\t'model cannot see are gone. They are listed below. For a byte-identical design at the cost',\n\t\t\t\t'of shipping the source deck alongside the script, print the template-anchored variant',\n\t\t\t\t'instead.',\n\t\t\t\t'',\n\t\t\t\t`Writes ${outputPath}. Needs an ESM context — it uses top-level await.`,\n\t\t\t],\n\t\t\tnotes\n\t\t),\n\t\t'',\n\t\t...printPreamble(packageName, { fs: needsReadFile ? ['readFile'] : [], read: false }),\n\t\t'',\n\t\t...printLayoutSetup(ir.slideSize),\n\t]\n\n\tif (theme !== null) {\n\t\tlines.push(\n\t\t\t'',\n\t\t\t\"// The theme's colour scheme and font faces. Its format scheme — the fill, line and effect\",\n\t\t\t'// style lists a shape references through p:style — has no counterpart on either side of the',\n\t\t\t\"// library, so the output carries Office's.\",\n\t\t\t`pptx.theme = ${theme}`\n\t\t)\n\t}\n\n\tif (props.length > 0) lines.push('', ...props)\n\n\tconst assetLines = printAssetBindings(\n\t\tir,\n\t\tassetNames,\n\t\tassetDir,\n\t\tassetMode,\n\t\tassets.printed,\n\t\t'// Media bytes, inlined so this script is a single self-contained file.'\n\t)\n\tif (assetLines.length > 0) lines.push('', ...assetLines)\n\n\tif (masters.length > 0) lines.push('', ...masters)\n\tlines.push(...body, '', `await pptx.writeFile({ fileName: here(${printString(outputPath)}) })`, '')\n\n\treturn printedScript(lines, ir, assetMode, notes, assets.printed)\n}\n\n/**\n * The document properties the write API can set, the ones `DECK_PROPS` in `ir.ts` lists.\n *\n * The rest the read model exposes are the loss `deck.docProps` already declares, and unlike the\n * template-anchored tier, here it is a real one, because nothing else carries them.\n */\nfunction printDocProps(ir: DeckIr, collector: NoteCollector): string[] {\n\tconst entries = Object.entries(ir.props).filter(([, value]) => typeof value === 'string')\n\n\t// A deck built through the write API is stamped with the library's own author, subject,\n\t// title, revision and company in the constructor, and a property cannot be unset — writing\n\t// `''` emits an empty element rather than removing it. So whatever the source left blank\n\t// comes back filled in, which is a change to the deck rather than a formatting detail.\n\t//\n\t// `company` sat outside this list while nothing populated it in the IR: it was\n\t// unconditionally \"missing\", so every standalone script carried a note claiming the source\n\t// deck declared no company — a claim the converter had never checked and one that is false\n\t// for most real decks. Now that `Presentation.appProperties` reads `docProps/app.xml`, the\n\t// key is populated when the source states one and the note is only raised when it does not.\n\tconst stamped = DECK_PROP_KEYS.filter((key) => !(key in ir.props))\n\tif (stamped.length > 0) {\n\t\tscopeNotes(collector, null).note(\n\t\t\t'deck.docPropsDefault',\n\t\t\t'approximated',\n\t\t\t'unwritable',\n\t\t\t`the source deck declares no ${andList(stamped)}, and a deck built through the write API is stamped with the library's own value for each in its constructor with no way to unset it, so the output declares ${stamped.length === 1 ? 'one' : 'these'} the source did not`\n\t\t)\n\t}\n\n\tif (entries.length === 0) return []\n\treturn [\n\t\t'// Document properties. Only these have write-API setters; see the fidelity notes.',\n\t\t...entries.map(([key, value]) => `pptx.${key} = ${printString(value)}`),\n\t]\n}\n\n/**\n * One `defineSlideMaster` per source layout.\n *\n * The naming is the write API's rather than OOXML's: a `defineSlideMaster` call creates a\n * *layout* under the single shared master, which is the right granularity for a source layout.\n * It carries the layout's name, its background, and its decoration — the bands, rules and\n * wordmarks that make the gallery recognisable rather than a list of blank rectangles. What it\n * still cannot carry is the layout's *placeholder definitions*, and that is a write-path\n * consequence rather than a reading one (see `from-read/chrome.ts`). The name earns its place\n * twice over: it is also what `addSlide({ masterTitle })` binds on.\n */\nfunction printMasters(ir: DeckIr, collector: NoteCollector, printAsset: AssetPrinter): string[] {\n\t// A deck written by this library opens its gallery with the layout the constructor seeds, and\n\t// the output's constructor seeds it again. Re-authoring it gave the output two layouts named\n\t// `DEFAULT`, so `addSlide({ masterTitle: 'DEFAULT' })` was ambiguous there; the slides bound to\n\t// it bind to the seed instead, which is the same layout.\n\tconst seeded = ir.chrome.masters.find(isSeedLayout)\n\n\t// Otherwise the extra layout is there whatever is printed below, so the note is recorded before\n\t// the early return. Scoped to that layout's own title rather than deck-wide, because the round\n\t// trip matches a note's `shapeName` against the identity of what differed, and an unscoped note\n\t// would declare *any* extra layout. That title is `DEFAULT` unless a source layout that is not\n\t// the seed already carries it; the reader then makes the second unique the way it made the\n\t// source's titles unique, so the extra one is reported under that spelling.\n\tif (!seeded) {\n\t\tconst sourceTitles = new Set(ir.chrome.masters.map((master) => master.props['title']).filter((t): t is string => typeof t === 'string')) // prettier-ignore\n\t\tscopeNotes(collector, null, uniqueTitle('DEFAULT', sourceTitles)).note(\n\t\t\t'master.default',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t\"the write path seeds every presentation with a blank layout of its own named DEFAULT, and there is no way to remove it, so the output deck's layout gallery carries one extra entry ahead of the source's layouts; nothing binds to it, but it is visible in PowerPoint's layout picker\"\n\t\t)\n\t}\n\tconst authored = ir.chrome.masters.filter((master) => master !== seeded)\n\tif (authored.length === 0) return []\n\treturn [\n\t\t'// One master per source layout, carrying its name, background and decoration. What a',\n\t\t'// layout does not bring across is its placeholder definitions; see the fidelity notes.',\n\t\t...authored.map((master) => printArguments('pptx.defineSlideMaster', [master.props], 0, printAsset)),\n\t]\n}\n\n/**\n * What the layout the write path seeds every presentation with reads back as: blank, titled\n * `DEFAULT`, on the white its master's `p:bgRef` resolves to. `compact` sorts an IR object's keys,\n * so the serialized form is stable.\n */\nconst SEED_LAYOUT_PROPS = JSON.stringify({ background: { color: 'FFFFFF' }, title: 'DEFAULT' })\n\n/**\n * Whether a source layout is the one the output's constructor seeds: first in the gallery, where\n * the seed sits, and identical to it. Anything else is re-authored, even a layout named `DEFAULT`,\n * because binding its slides to the seed would lose what sets it apart.\n */\nfunction isSeedLayout(master: MasterIr): boolean {\n\treturn master.layoutIndex === 0 && JSON.stringify(master.props) === SEED_LAYOUT_PROPS\n}\n\n/** Every slide, in source order, each bound to the master its source layout became. */\nfunction printSlides(ir: DeckIr, collector: NoteCollector, printAsset: AssetPrinter): string[] {\n\tconst byLayout = new Map<number, MasterIr>()\n\tfor (const master of ir.chrome.masters) byLayout.set(master.layoutIndex, master)\n\n\tconst lines: string[] = []\n\tfor (const slide of ir.slides) {\n\t\tconst master = slide.layout === null ? undefined : byLayout.get(slide.layout.index)\n\t\tconst title = typeof master?.props['title'] === 'string' ? master.props['title'] : null\n\n\t\tif (title === null) {\n\t\t\tscopeNotes(collector, slide.number).note(\n\t\t\t\t'slide.layout',\n\t\t\t\t'approximated',\n\t\t\t\t'unsupported',\n\t\t\t\tslide.layout === null\n\t\t\t\t\t? \"this slide resolves no layout of its own, so it binds to the write path's default blank layout\"\n\t\t\t\t\t: `this slide's source layout (gallery position ${slide.layout.index}) produced no master to bind to, so it binds to the write path's default blank layout`\n\t\t\t)\n\t\t}\n\n\t\tlines.push(\n\t\t\t...printSlide(\n\t\t\t\tslide,\n\t\t\t\t{\n\t\t\t\t\tcomment: `Slide ${slide.number} — ${title === null ? 'no master' : `master ${JSON.stringify(title)}`}`,\n\t\t\t\t\tconstruction: title === null ? 'pptx.addSlide()' : `pptx.addSlide({ masterTitle: ${printString(title)} })`,\n\t\t\t\t},\n\t\t\t\tcollector,\n\t\t\t\tprintAsset\n\t\t\t)\n\t\t)\n\t}\n\treturn lines\n}\n","/**\n * A {@link DeckIr} reduced to the form a round-trip diff can compare.\n *\n * The round trip is `source → IR₁ → script → deck → IR₂`. Comparing those two IRs raw\n * produces thousands of differences, almost none of which are losses: the write path\n * spells out defaults that OOXML leaves implicit, and PowerPoint spells out defaults the\n * write path leaves implicit. Both directions are noise, and drowning the real losses in\n * it is the same as not checking at all.\n *\n * **Every rule here must be an equivalence, not a convenience.** A rule that merely makes\n * the report shorter hides a defect permanently and silently — the exact failure mode this\n * subsystem exists to catch. So each one below cites the OOXML default that makes the\n * explicit and the absent spelling mean the same thing, and none of them drops a value that\n * a viewer could render differently. When in doubt the value stays in and the difference is\n * reported: a noisy report is recoverable, a quiet one is not.\n *\n * Canonicalising is deliberately *symmetric* — it runs over both IRs, so it cannot favour\n * the output. A rule that only made sense in one direction would be an exclusion dressed up\n * as a normalisation.\n */\nimport { asIrValue, isAssetRef, type AssetIr, type DeckIr, type IrValue, type SlideIr } from '../ir.js'\nimport { BODY_INSET_DEFAULTS_IN } from '../../ooxml/body-insets.js'\nimport { InvalidOptionError } from '../../errors.js'\n\n/** One write-API call, with the source shape name lifted out as an address rather than data. */\nexport interface CanonicalCall {\n\tmethod: string\n\t/** `p:cNvPr/@name` of the shape this call came from, used to point a difference at it. */\n\tshapeName: string | null\n\t/**\n\t * Every `objectName` appearing anywhere inside {@link args}, which for `addGroup` is the\n\t * group's children.\n\t *\n\t * A fidelity note about a group's child is scoped to that child's name, but the child is\n\t * not a call of its own — it is an argument to the group's. Without this the note and the\n\t * difference it predicted would carry different names and never match, and a declared loss\n\t * would be reported as a defect.\n\t */\n\tcontainedNames: string[]\n\targs: IrValue[]\n}\n\nexport interface CanonicalSlide {\n\tnumber: number\n\thidden: boolean\n\t/**\n\t * The name of the layout this slide binds to, which is the only part of the binding that\n\t * is portable — a gallery *index* shifts whenever the output's gallery differs from the\n\t * source's, which it always does for a standalone output.\n\t *\n\t * Here because the binding is otherwise invisible: a printer that bound every slide to the\n\t * wrong layout, or to none, would produce identical calls and compare clean. The layout\n\t * governs theme and colour-map resolution, so that is not a cosmetic difference.\n\t */\n\tlayoutName: string | null\n\tbackground: IrValue | null\n\tnotesText: string | null\n\t/**\n\t * The show transition, or `null`.\n\t *\n\t * Here for the same reason {@link layoutName} is: a printer that stopped emitting\n\t * transitions altogether would produce identical *calls* and compare clean, so the\n\t * projection has to carry the slide-level properties the write API sets by assignment\n\t * rather than by method. It is compared structurally (key by key), not as one opaque\n\t * value, so a note can declare the loss of a transition's *sound* without also excusing a\n\t * wrong transition *type*.\n\t */\n\ttransition: IrValue | null\n\tcalls: CanonicalCall[]\n}\n\n/**\n * The deck's chrome, reduced the same way its slides are.\n *\n * Included for one reason: without it the diff cannot see the standalone tier's whole job.\n * That tier re-authors the theme and one master per source layout, and a projection that\n * covers only slides would report a printer emitting *neither* as a clean round trip — the\n * same shape of hole mutation testing found in `added` differences, one level up. A\n * template-anchored output compares equal here by construction, which is the claim that tier\n * makes and is worth checking rather than assuming.\n */\nexport interface CanonicalChrome {\n\ttheme: IrValue\n\t/** Each master's `defineSlideMaster` props, in gallery order. */\n\tmasters: IrValue[]\n}\n\nexport interface CanonicalDeck {\n\tslideSize: { widthEmu: number; heightEmu: number }\n\t/** The `docProps` the write API can set. Absent from the projection, a printer that set none would compare clean. */\n\tprops: IrValue\n\tchrome: CanonicalChrome\n\tslides: CanonicalSlide[]\n}\n\n/**\n * Option values that mean exactly what their absence means.\n *\n * Keyed by option name because the IR's argument objects are the write API's own option\n * objects, where a name identifies a construct uniquely — there is no `bold` that means\n * something other than `a:rPr/@b`.\n *\n * Each entry is an OOXML default:\n *\n * - `bold`, `italic` — `a:rPr/@b` / `@i` are `ST_OnOff`, default `false`.\n * - `baseline` — `a:rPr/@baseline` is a percentage, default `0` (no super/subscript).\n * - `breakLine` — not OOXML but the IR's own flat encoding: a run that does not end its\n * paragraph. The final run of a text frame never carries one, so absent and `false` are\n * the same statement.\n * - `wrap` — `a:bodyPr/@wrap` defaults to `square`, which the write API spells `true`.\n * - `rotate` — `a:xfrm/@rot` defaults to `0`.\n * - `flipH`, `flipV` — `a:xfrm/@flipH` / `@flipV` default to `false`.\n * - `transparency` — an alpha of 0% removed, i.e. fully opaque, which is also the default\n * when no `a:alpha` transform is present.\n * - `indentLevel` — `a:p/@lvl` defaults to `0`.\n * - `dashType` — `a:ln`'s dash defaults to `solid` when no `a:prstDash` is present.\n * - `textDirection` — `a:bodyPr/@vert` and `a:tcPr/@vert` both default to `horz`.\n *\n * Line width is deliberately **absent**: `a:ln/@w` defaults to 0 (hairline) while the write\n * path defaults it to 1pt, so those two are not the same line and the difference is real.\n */\nconst IMPLIED_DEFAULTS: Record<string, IrValue> = {\n\tbold: false,\n\titalic: false,\n\tbaseline: 0,\n\tbreakLine: false,\n\twrap: true,\n\trotate: 0,\n\tflipH: false,\n\tflipV: false,\n\ttransparency: 0,\n\tindentLevel: 0,\n\tdashType: 'solid',\n\ttextDirection: 'horz',\n}\n\n/** Reduce a deck IR to the comparable form. */\nexport function canonicalDeckIr(ir: DeckIr): CanonicalDeck {\n\tconst digests = assetDigests(ir.assets)\n\treturn {\n\t\tslideSize: ir.slideSize,\n\t\tprops: canonicalValue(ir.props, digests),\n\t\tchrome: {\n\t\t\ttheme: canonicalValue(ir.chrome.theme as IrValue, digests),\n\t\t\tmasters: ir.chrome.masters.map((master) => canonicalValue(master.props, digests)),\n\t\t},\n\t\tslides: ir.slides.map((slide) => canonicalSlide(slide, digests)),\n\t}\n}\n\nfunction canonicalSlide(slide: SlideIr, digests: Map<string, string>): CanonicalSlide {\n\treturn {\n\t\tnumber: slide.number,\n\t\thidden: slide.hidden,\n\t\tlayoutName: slide.layout?.name ?? null,\n\t\tbackground: slide.background === undefined ? null : canonicalValue(slide.background as IrValue, digests),\n\t\tnotesText: slide.notesText ?? null,\n\t\ttransition: slide.transition === undefined ? null : canonicalValue(asIrValue(slide.transition), digests),\n\t\tcalls: slide.calls.map((call) => {\n\t\t\tconst args = call.args.map((arg) => canonicalValue(arg, digests))\n\t\t\treturn {\n\t\t\t\tmethod: call.method,\n\t\t\t\tshapeName: call.sourceName ?? null,\n\t\t\t\tcontainedNames: [...collectObjectNames(args, new Set())],\n\t\t\t\targs,\n\t\t\t}\n\t\t}),\n\t}\n}\n\n/**\n * Every `objectName` value reachable in `value`, at any depth.\n *\n * Exported for the chrome half of the diff, which needs the same list for the same reason: a\n * layout's decoration is an argument to one `defineSlideMaster` call, so a note scoped to one\n * of those shapes has no call of its own to be matched against.\n */\nexport function collectObjectNames(value: IrValue, out: Set<string>): Set<string> {\n\tif (Array.isArray(value)) {\n\t\tfor (const item of value) collectObjectNames(item, out)\n\t\treturn out\n\t}\n\tif (value === null || typeof value !== 'object') return out\n\tfor (const [key, item] of Object.entries(value)) {\n\t\tif (key === 'objectName' && typeof item === 'string') out.add(item)\n\t\telse collectObjectNames(item as IrValue, out)\n\t}\n\treturn out\n}\n\n/**\n * Recursively drop implied defaults and resolve asset references to a content digest.\n *\n * The digest matters more than it looks: assets are named `image1.png`, `image2.png`, … in\n * the order the walk meets them, and the output deck can meet the same bytes in a different\n * order or under a different extension. Comparing names would report a swap that did not\n * happen and, worse, would *miss* one where two images traded places.\n */\nfunction canonicalValue(value: IrValue, digests: Map<string, string>): IrValue {\n\tif (isAssetRef(value)) {\n\t\tconst digest = digests.get(value.$asset)\n\t\t// An unresolved reference used to fall back to `unknown:<name>`, which is the asset's own\n\t\t// NAME — so if neither side resolved it, both canonicalised to the same string and the round\n\t\t// trip came back clean on bytes it never compared. That is the one case where names carry no\n\t\t// information, which is precisely what the digest exists to avoid. It is already an\n\t\t// `InvalidOptionError` on the print path, so it is an invariant violation rather than a\n\t\t// difference: saying so is louder than a sentinel and cannot be compared equal by accident.\n\t\tif (digest === undefined) {\n\t\t\tthrow new InvalidOptionError(\n\t\t\t\t'script/unresolved-asset-reference',\n\t\t\t\t`Asset reference ${value.$asset} has no entry in DeckIr.assets, so it cannot be compared by content`\n\t\t\t)\n\t\t}\n\t\treturn { $asset: digest }\n\t}\n\tif (Array.isArray(value)) return value.map((item) => canonicalValue(item, digests))\n\tif (value === null || typeof value !== 'object') return value\n\n\t// A run with no characters has no colour anyone can see, and the write path gives every\n\t// run it emits an explicit one. Narrowed to `color` deliberately: a size or a bullet on an\n\t// empty paragraph still affects line height and still draws a glyph, so those stay.\n\tconst blankRun = value['text'] === '' && typeof value['options'] === 'object' && value['options'] !== null\n\n\tconst out: Record<string, IrValue> = {}\n\tfor (const [key, item] of Object.entries(value)) {\n\t\tif (key in IMPLIED_DEFAULTS && item === IMPLIED_DEFAULTS[key]) continue\n\t\tif (key === 'margin' && isDefaultMargin(item)) continue\n\t\tif (blankRun && key === 'options') {\n\t\t\tconst visible = { ...(item as Record<string, IrValue>) }\n\t\t\tdelete visible['color']\n\t\t\tout[key] = canonicalValue(visible, digests)\n\t\t\tcontinue\n\t\t}\n\t\tout[key] = canonicalValue(item, digests)\n\t}\n\treturn out\n}\n\nfunction isDefaultMargin(value: IrValue): boolean {\n\treturn (\n\t\tArray.isArray(value) &&\n\t\tvalue.length === BODY_INSET_DEFAULTS_IN.length &&\n\t\tvalue.every((item, index) => item === BODY_INSET_DEFAULTS_IN[index])\n\t)\n}\n\n/**\n * Content digests keyed by asset name, so the same bytes compare equal under any name.\n *\n * FNV-1a rather than a real hash: this identifies bytes for a comparison both sides of\n * which are in hand, so collision resistance against an adversary is not a property it\n * needs, and the library stays free of `node:crypto` and of the isomorphism problem\n * importing it would create.\n */\nfunction assetDigests(assets: AssetIr[]): Map<string, string> {\n\tconst out = new Map<string, string>()\n\tfor (const asset of assets) {\n\t\tlet hash = 0x811c9dc5\n\t\tfor (const byte of asset.bytes) {\n\t\t\thash ^= byte\n\t\t\thash = Math.imul(hash, 0x01000193) >>> 0\n\t\t}\n\t\tout.set(asset.name, `${asset.bytes.length}:${hash.toString(16)}`)\n\t}\n\treturn out\n}\n","/**\n * ts-pptx: pairing two lists of the same things for comparison.\n *\n * The round trip compares a deck against the deck its script produced, and both the slide\n * calls and the chrome masters have to be paired up before anything can be diffed. Position\n * alone is wrong the moment one item drops out: every later one shifts by one, and the report\n * fills with mismatches that are really one missing shape. So a stable key — a shape's\n * `objectName`, a master's title — aligns what it can, with position as the fallback.\n *\n * Both sides wrote this out, down to two near-identical `nextUnclaimed` closures, and they\n * differed in one respect that matters. `diffChrome`'s own reasoning is recorded there: a\n * mutation that removed layout-title deduplication left two layouts sharing a title and the\n * round trip came back clean, so its key has to identify exactly one item *on both sides*.\n * The call aligner checked the actual side only, and that reasoning was never carried back.\n * This is the both-sides rule, once.\n */\n\n/**\n * Pair `expected` with `actual`, keyed where the key is unambiguous and positional elsewhere.\n *\n * The result holds one entry per pairing, in expected order, then one `[null, item]` for each\n * unclaimed actual item. A `[item, null]` means the item was lost; a `[null, item]` means it\n * was added.\n *\n * @param expected - the source deck's items, in document order\n * @param actual - the round-tripped deck's items, in document order\n * @param keyOf - the alignment key, or `null` for an item that has none\n */\nexport function alignByKey<T>(\n\texpected: readonly T[],\n\tactual: readonly T[],\n\tkeyOf: (item: T) => string | null\n): Array<[T | null, T | null]> {\n\t// A key is usable only where it names exactly one item. Counted on each side separately,\n\t// and required on both: a key that is unique among the expected items but duplicated among\n\t// the actual ones would pair the first of the duplicates and let the second pass unexamined.\n\tconst uniqueBy = (items: readonly T[]): Map<string, T> => {\n\t\tconst counts = new Map<string, number>()\n\t\tfor (const item of items) {\n\t\t\tconst key = keyOf(item)\n\t\t\tif (key !== null) counts.set(key, (counts.get(key) ?? 0) + 1)\n\t\t}\n\t\tconst out = new Map<string, T>()\n\t\tfor (const item of items) {\n\t\t\tconst key = keyOf(item)\n\t\t\tif (key !== null && counts.get(key) === 1) out.set(key, item)\n\t\t}\n\t\treturn out\n\t}\n\n\tconst byKey = uniqueBy(actual)\n\tconst expectedKeys = uniqueBy(expected)\n\tconst claimed = new Set<T>()\n\n\t// Every actual item some expected item will claim BY KEY, reserved before the positional walk\n\t// begins. Without the reservation the walk claims whatever it lands on, including an item a\n\t// later expected entry is going to match by name: with `expected = [<unnamed>, \"A\"]` against\n\t// `actual = [\"A\", <unnamed>]`, the unnamed expected item took `\"A\"` positionally, `\"A\"` then\n\t// found its own match already claimed and fell to the unnamed one, and the report described\n\t// two shapes that each had an exact counterpart as a full set of differences.\n\tconst reserved = new Set<T>()\n\tfor (const before of expected) {\n\t\tconst key = keyOf(before)\n\t\tif (key === null || !expectedKeys.has(key)) continue\n\t\tconst named = byKey.get(key)\n\t\tif (named !== undefined) reserved.add(named)\n\t}\n\n\t// Positional cursor for items no key can align, advanced only past claimed and reserved items\n\t// so a keyed match does not lose its slot to an unkeyed one.\n\tlet cursor = 0\n\tconst nextUnclaimed = (): T | null => {\n\t\twhile (cursor < actual.length) {\n\t\t\tconst candidate = actual[cursor++]\n\t\t\tif (candidate !== undefined && !claimed.has(candidate) && !reserved.has(candidate)) return candidate\n\t\t}\n\t\treturn null\n\t}\n\n\tconst pairs: Array<[T | null, T | null]> = []\n\tfor (const before of expected) {\n\t\tconst key = keyOf(before)\n\t\tconst named = key !== null && expectedKeys.has(key) ? byKey.get(key) : undefined\n\t\tconst after = named !== undefined && !claimed.has(named) ? named : nextUnclaimed()\n\t\tif (after !== null && after !== undefined) claimed.add(after)\n\t\tpairs.push([before, after ?? null])\n\t}\n\tfor (const after of actual) if (!claimed.has(after)) pairs.push([null, after])\n\treturn pairs\n}\n","/**\n * The round-trip oracle: does the deck a printed script builds match the deck it was read\n * from, everywhere the fidelity notes did not say it would not?\n *\n * **Why a projection diff and not byte identity.** The output package is not the input\n * package and never will be — different rel ids, different shape ids, a regenerated shape\n * tree, `dirty=\"0\"` on every run. Comparing bytes would report a total mismatch for every\n * deck and prove nothing. So the comparison happens one level up, on the IR: run the same\n * `readModelToIr` over the source deck and over the deck the script produced, and compare\n * those. Two decks that produce the same IR make the same write-API calls, which is exactly\n * the claim a generated script makes.\n *\n * **What a note is worth here.** A {@link FidelityNote} says a named construct will not\n * survive. That makes it an *exclusion with a signature*: the difference it predicts is\n * allowed, and every other difference is a defect. Without the notes there would be no way\n * to tell a known cost from a regression, and the check could only ever be a snapshot.\n *\n * **Two blind spots, both stated plainly, because a clean report is worth exactly what its\n * limits allow.**\n *\n * 1. *The reader is shared.* Both IRs come from `readModelToIr`, so a construct the read\n * model cannot see is missing from both and compares equal. This check cannot certify\n * anything the read path does not read; `pnpm run read:census` measures that surface, and\n * the two are complementary rather than overlapping.\n * 2. *The converter need not be injective.* Two different source constructs can map to the\n * same call, and then the round trip agrees while the deck has changed. Measured, not\n * hypothetical: the mapper once read an explicit `a:buNone` as the glyph `n`, so a\n * bulletless paragraph gained a bullet — and because the output's real `n` bullet read\n * back through the same wrong mapping, the diff was clean. Mutation testing is what\n * catches that class, and a mutation that survives here is a statement about this\n * check's reach rather than a mistake in it.\n *\n * A clean report means \"nothing the converter can distinguish was lost\", never \"nothing was\n * lost\".\n */\nimport { alignByKey } from './align.js'\nimport { LAYOUT_NOTE_PREFIX, NOTE_CONSTRUCTS, type FidelityNote, type NoteConstructEntry } from '../fidelity.js'\nimport {\n\tcollectObjectNames,\n\ttype CanonicalCall,\n\ttype CanonicalChrome,\n\ttype CanonicalDeck,\n\ttype CanonicalSlide,\n} from './canonical.js'\nimport { DECK_PROP_KEYS, type IrValue } from '../ir.js'\n\n/**\n * Which way a difference points.\n *\n * `lost` and `changed` are the ones the fidelity contract governs — the source said\n * something the output does not, or says differently. `added` is the write path being\n * explicit where the source was implicit, which is *usually* harmless and is reported\n * separately for a reason worth stating: this diff cannot tell whether the value the write\n * path chose is the one the source was inheriting. An `added` `color` is benign if the\n * shape was inheriting that colour and a silent repaint if it was not.\n */\nexport type DifferenceKind = 'lost' | 'added' | 'changed'\n\n/**\n * Options the write path materialises that the source deck left implicit, with the reason\n * each is not judgeable from here.\n *\n * This list exists because `added` differences cannot simply be waved through. Mutation\n * testing settled that: dropping the converter's explicit `valign` left the write path to\n * centre every text body, which showed up as an `added` and nothing failed. So `added` is\n * held to the same standard as the rest — a note must declare it, or its field must appear\n * here with a reason.\n *\n * Every entry names a write-path default whose *correctness* the round trip has no way to\n * assess, because the source's counterpart was inherited and the read model cannot resolve\n * what it was inheriting. That is an honest \"unknown\", not an \"ignore\" — each one names a\n * gap in the reader that could be closed later, and teaching the reader to resolve one turns\n * its entry here into a real comparison.\n */\nconst WRITER_DEFAULTS: Record<string, string> = {\n\t// Keys are dotted option PATHS, matched as a suffix of a difference's own path. A bare key\n\t// still means \"this option wherever it appears\", which is right for the ones below that are\n\t// unambiguous; qualify one the moment the same word names two different things.\n\t// The write path copies the object-level and first-run character properties onto every\n\t// run it emits. The source's bare runs inherited theirs from the list style, which is\n\t// unread, so there is nothing to compare the copied value against.\n\tfontSize: 'runs inherit size from an unread list style; the write path copies the shape size onto each run',\n\toptions: 'a run or cell that carried no options at all in the source now carries the ones below',\n\t// `a:tcBdr` borders come from the table style graph, which `resolvedFill`/`borders` fold\n\t// together rather than separating; the write path spells out an explicit border per edge.\n\tborder:\n\t\t'table cell borders are resolved through the style graph, which the read model cannot separate from the cell’s own',\n\t// The same unknown one level down, for a cell whose border array survives while an individual\n\t// EDGE gains the write path's completed `{ type, color, width }` (`DEF_CELL_BORDER`). Under\n\t// key-only matching these were covered by the bare `type`/`width` entries, which is the accident\n\t// this qualification removes: those are about a fill's kind and an outline's weight, on shapes.\n\t// The colour was covered the same way, by the bare `color` in the run-colour notes.\n\t'border.type':\n\t\t'a table cell border edge the write path completes; the source’s came from the style graph the read model cannot separate',\n\t'border.color':\n\t\t'a table cell border edge the write path completes; the source’s came from the style graph the read model cannot separate',\n\t'border.width':\n\t\t'a table cell border edge the write path completes; the source’s came from the style graph the read model cannot separate',\n\t// `a:ln/@w` defaults to a hairline in OOXML and to 1pt here, and a source outline with no\n\t// explicit width is exactly the theme-`lnRef` case `line.width` already declares unread.\n\t'line.width':\n\t\t'an outline with no explicit width takes the write path’s 1pt default; the source’s came from the unread theme line style',\n\t// A shape with no geometry of its own — an unfilled placeholder — has no preset to name.\n\tshape: 'a shape that inherits its geometry from a layout is emitted as a plain rectangle',\n\t// The image renderer falls back to the image path for `p:cNvPr/@descr` when it is given no alt\n\t// text, and `altText: ''` does not suppress that, so a source picture with no description comes\n\t// back described by its file name. Bare, because array indices are not part of a path and an\n\t// `addImage`'s options sit where every other call's do; no other kind invents a description.\n\taltText: 'a picture with no alt text is described by its image path on the write side',\n\t'fill.type': 'a fill with no explicit kind takes the write path’s solid default',\n\t'line.type': 'an outline with no explicit kind takes the write path’s solid default',\n\t// Chart options the write path always emits; the read side reports only what the chart\n\t// part contains, and these are defaults rather than authored values.\n\tchartColors: 'the write path assigns a series palette; the source’s came from the theme',\n\tdataLabelFormatCode: 'a data label with no explicit number format takes the write path’s default',\n\tshowLeaderLines: 'leader lines are on by default in the write path',\n\t// The five docProps the write path seeds in its constructor ('ts-pptx',\n\t// 'ts-pptx Presentation', '1'). A source deck that declared none of a given property gets\n\t// the library's, and there is no way to unset one — assigning `''` writes an empty element\n\t// rather than removing it. Unlike the entries above, this is a *write*-side candidate, not\n\t// a read-side one: the fix is a way to author a deck with a property genuinely absent.\n\t// Restricted to `added` by construction, so a printer that stopped writing docProps still\n\t// fails: the source's own values become `changed`, which nothing here excuses.\n\t// Path-qualified so they reach `docProps` and nothing else: a bare `title` also excused an\n\t// added chart title and an added layout title in `chrome.masters`.\n\t...Object.fromEntries(\n\t\tDECK_PROP_KEYS.map((key) => [`props.${key}`, `a deck that declares no ${key} gets the write path’s own`])\n\t),\n}\n\nexport interface IrDifference {\n\t/** 1-based source slide. */\n\tslideNumber: number\n\t/** Source shape name, when the difference sits inside a call that has one. */\n\tshapeName: string | null\n\t/**\n\t * Shape names nested inside the same call — a group's children. A note scoped to one of\n\t * these also declares differences reported against the call that carries it.\n\t */\n\tnestedNames: string[]\n\t/** Where in the slide's projection, e.g. `calls[4].args[1].line.width`. */\n\tpath: string\n\t/**\n\t * The option name the difference is about — the last object key on {@link path}, or\n\t * `'*'` when a whole call is present on one side only. This is what a note's `construct`\n\t * is matched against, which is why `construct` has to name a field path rather than\n\t * describe one.\n\t */\n\tfield: string\n\tkind: DifferenceKind\n\t/** The source value, JSON-encoded and truncated for reporting. `'—'` when absent. */\n\texpected: string\n\t/** The output value, likewise. */\n\tactual: string\n\t/** The note that declares this difference, when one does. */\n\tdeclaredBy: FidelityNote | null\n}\n\nexport interface RoundTripReport {\n\tslideCount: number\n\t/** Every difference found, in deck order. */\n\tdifferences: IrDifference[]\n\t/**\n\t * Differences neither a note nor a known write-path default accounts for.\n\t * **These are the defects**, and the number this check gates on.\n\t */\n\tundeclared: IrDifference[]\n\t/** Differences a note declared. The contract working. */\n\tdeclared: IrDifference[]\n\t/** `added` differences: the write path spelling out what the source left implicit. */\n\tadded: IrDifference[]\n\t/**\n\t * Notes that matched no difference.\n\t *\n\t * **Not a defect signal, despite the obvious reading.** Most notes name constructs the\n\t * read model cannot see at all — a bullet's `a:buFont`, a shape's theme `effectRef` —\n\t * so they are absent from *both* IRs and there is nothing for them to match. A note\n\t * here is a candidate for review, not a stale claim.\n\t */\n\tunmatchedNotes: FidelityNote[]\n}\n\n/**\n * Every note construct this table knows how to match, for a test to check against. The\n * `layout.` spellings are not listed — they resolve through {@link isKnownNoteConstruct},\n * which is what a corpus check should use.\n */\nexport function knownNoteConstructs(): string[] {\n\treturn Object.keys(NOTE_CONSTRUCTS).sort()\n}\n\n/**\n * Compare the deck a script was generated from against the deck it produced.\n *\n * `notes` must be the set that actually applies to the printed output — `printScript`'s\n * returned `notes`, not `DeckIr.fidelity`. The two differ in both directions: the printer\n * suppresses notes its tier rescues and adds ones its tier causes, so diffing against the\n * IR's own list would both over- and under-exclude.\n */\nexport function diffDeckIr(expected: CanonicalDeck, actual: CanonicalDeck, notes: FidelityNote[]): RoundTripReport {\n\tconst differences: IrDifference[] = []\n\n\tif (expected.slideSize.widthEmu !== actual.slideSize.widthEmu) {\n\t\tdifferences.push(scalarDifference(0, null, [], 'slideSize.widthEmu', 'widthEmu', expected.slideSize.widthEmu, actual.slideSize.widthEmu)) // prettier-ignore\n\t}\n\tif (expected.slideSize.heightEmu !== actual.slideSize.heightEmu) {\n\t\tdifferences.push(scalarDifference(0, null, [], 'slideSize.heightEmu', 'heightEmu', expected.slideSize.heightEmu, actual.slideSize.heightEmu)) // prettier-ignore\n\t}\n\n\tdiffValue(expected.props, actual.props, 'props', 'props', {\n\t\tslideNumber: 0,\n\t\tshapeName: null,\n\t\tnestedNames: [],\n\t\tout: differences,\n\t})\n\tdiffChrome(expected.chrome, actual.chrome, differences)\n\n\tconst slideCount = Math.max(expected.slides.length, actual.slides.length)\n\tfor (let index = 0; index < slideCount; index++) {\n\t\tconst before = expected.slides[index]\n\t\tconst after = actual.slides[index]\n\t\tconst number = before?.number ?? after?.number ?? index + 1\n\t\tif (!before || !after) {\n\t\t\tdifferences.push({\n\t\t\t\tslideNumber: number,\n\t\t\t\tshapeName: null,\n\t\t\t\tnestedNames: [],\n\t\t\t\tpath: `slides[${index}]`,\n\t\t\t\tfield: '*',\n\t\t\t\tkind: before ? 'lost' : 'added',\n\t\t\t\texpected: before ? 'slide' : '—',\n\t\t\t\tactual: after ? 'slide' : '—',\n\t\t\t\tdeclaredBy: null,\n\t\t\t})\n\t\t\tcontinue\n\t\t}\n\t\tdiffSlide(before, after, differences)\n\t}\n\n\tfor (const difference of differences) difference.declaredBy = declaringNote(difference, notes)\n\tconst matched = new Set(differences.map((difference) => difference.declaredBy).filter(Boolean))\n\tconst accounted = (difference: IrDifference): boolean =>\n\t\tdifference.declaredBy !== null ||\n\t\t(difference.kind === 'added' && Object.keys(WRITER_DEFAULTS).some((spec) => specCovers(spec, difference, 'suffix')))\n\n\treturn {\n\t\tslideCount: Math.max(expected.slides.length, actual.slides.length),\n\t\tdifferences,\n\t\tundeclared: differences.filter((difference) => !accounted(difference)),\n\t\tdeclared: differences.filter((difference) => difference.declaredBy !== null),\n\t\tadded: differences.filter((difference) => difference.kind === 'added'),\n\t\tunmatchedNotes: notes.filter((note) => !matched.has(note)),\n\t}\n}\n\n/**\n * The theme and the layout gallery.\n *\n * Reported at `slideNumber: 0`, the same deck-level bucket the slide size uses, so a\n * deck-scoped note (which carries `slideNumber: null` and matches any slide) can declare one.\n * Masters align by **title**, not by position, for the same reason calls align by shape name:\n * the write path always emits a blank layout of its own at gallery position 0, so positional\n * alignment reports every layout in the deck as renamed and buries the one real difference —\n * that extra layout — under a shift.\n *\n * And, exactly as with shape names, a title is only usable as a key where it is *unique on\n * both sides*. Uniqueness is supposed to be an invariant here — the converter deduplicates\n * titles because a title is also what `addSlide({ masterTitle })` binds on — but keying on it\n * unconditionally makes the check assume the thing it should be testing: a mutation that\n * removed the deduplication left two layouts sharing a title, both expected entries matched\n * the same actual one, and the round trip came back clean. Falling back to position when the\n * key repeats costs nothing when the invariant holds and catches it when it does not.\n */\nfunction diffChrome(expected: CanonicalChrome, actual: CanonicalChrome, out: IrDifference[]): void {\n\tdiffValue(expected.theme, actual.theme, 'chrome.theme', 'theme', {\n\t\tslideNumber: 0,\n\t\tshapeName: null,\n\t\tnestedNames: [],\n\t\tout,\n\t})\n\n\t// A whole master appearing or disappearing is reported *scoped to its title*, using the\n\t// same `shapeName` channel a shape-scoped note uses. Without that, one note declaring the\n\t// blank layout the write path always adds would carry `field: 'master'` and excuse every\n\t// added layout — which is what a mutation that stopped deduplicating layout titles proved.\n\tconst report = (\n\t\tpath: string,\n\t\tkind: DifferenceKind,\n\t\tbefore: IrValue | undefined,\n\t\tafter: IrValue | undefined\n\t): void => {\n\t\tout.push({\n\t\t\tslideNumber: 0,\n\t\t\tshapeName: titleOf(before ?? after ?? null),\n\t\t\tnestedNames: decorationNames(before, after),\n\t\t\tpath,\n\t\t\tfield: 'master',\n\t\t\tkind,\n\t\t\texpected: brief(before),\n\t\t\tactual: brief(after),\n\t\t\tdeclaredBy: null,\n\t\t})\n\t}\n\n\t// Titles align the masters where a title names exactly one on each side; `alignByKey` owns\n\t// that rule, and the call aligner reads the same one.\n\talignByKey(expected.masters, actual.masters, titleOf).forEach(([before, after], index) => {\n\t\tif (before === null) {\n\t\t\treport(`chrome.masters[${index}]`, 'added', undefined, after ?? undefined)\n\t\t\treturn\n\t\t}\n\t\tif (after === null) {\n\t\t\treport(`chrome.masters[${index}]`, 'lost', before, undefined)\n\t\t\treturn\n\t\t}\n\t\t// A layout's decoration rides inside this one value, so a note scoped to one of those\n\t\t// shapes has no call of its own to be matched against — the same problem a group's child\n\t\t// has on a slide, and the same answer.\n\t\tdiffValue(before, after, `chrome.masters[${index}]`, 'master', {\n\t\t\tslideNumber: 0,\n\t\t\tshapeName: null,\n\t\t\tnestedNames: decorationNames(before, after),\n\t\t\tout,\n\t\t})\n\t})\n}\n\n/**\n * The `objectName`s of every decorative shape in a master's props, taking both sides so a\n * shape that dropped out is still named by the source's.\n */\nfunction decorationNames(before: IrValue | undefined, after: IrValue | undefined): string[] {\n\tconst names = new Set<string>()\n\tfor (const master of [before, after]) if (master !== undefined) collectObjectNames(master, names)\n\treturn [...names]\n}\n\n/** A canonical master's `title`, which is its identity across the round trip. */\nfunction titleOf(master: IrValue): string | null {\n\tif (master === null || typeof master !== 'object' || Array.isArray(master)) return null\n\tconst title = (master as Record<string, IrValue>)['title']\n\treturn typeof title === 'string' ? title : null\n}\n\nfunction diffSlide(expected: CanonicalSlide, actual: CanonicalSlide, out: IrDifference[]): void {\n\tconst number = expected.number\n\tconst at = (path: string, field: string, a: IrValue, b: IrValue): void => {\n\t\tif (JSON.stringify(a) !== JSON.stringify(b)) out.push(scalarDifference(number, null, [], path, field, a, b))\n\t}\n\tat('hidden', 'hidden', expected.hidden, actual.hidden)\n\tat('layoutName', 'layoutName', expected.layoutName, actual.layoutName)\n\tat('background', 'background', expected.background, actual.background)\n\tat('notesText', 'notesText', expected.notesText, actual.notesText)\n\t// Structural rather than whole-value, unlike the four above: a transition is a small object\n\t// whose parts are lost independently — the append path drops an embedded sound while\n\t// keeping the effect — and a whole-value compare would force the note that declares the\n\t// sound to carry `field: 'transition'`, which would then excuse a wrong type or duration too.\n\tdiffValue(expected.transition, actual.transition, 'transition', 'transition', {\n\t\tslideNumber: number,\n\t\tshapeName: null,\n\t\tnestedNames: [],\n\t\tout,\n\t})\n\n\tfor (const [before, after] of alignByKey(expected.calls, actual.calls, (call) => call.shapeName)) {\n\t\tconst name = before?.shapeName ?? after?.shapeName ?? null\n\t\t// Union of both sides: a child that dropped out is named only by the source's call.\n\t\tconst nested = [...new Set([...(before?.containedNames ?? []), ...(after?.containedNames ?? [])])]\n\t\tconst path = `calls[${before ? expected.calls.indexOf(before) : actual.calls.indexOf(after as CanonicalCall)}]`\n\t\tif (!before || !after) {\n\t\t\tout.push({\n\t\t\t\tslideNumber: number,\n\t\t\t\tshapeName: name,\n\t\t\t\tnestedNames: nested,\n\t\t\t\tpath,\n\t\t\t\tfield: '*',\n\t\t\t\tkind: before ? 'lost' : 'added',\n\t\t\t\texpected: before ? before.method : '—',\n\t\t\t\tactual: after ? after.method : '—',\n\t\t\t\tdeclaredBy: null,\n\t\t\t})\n\t\t\tcontinue\n\t\t}\n\t\tif (before.method !== after.method) {\n\t\t\tout.push(scalarDifference(number, name, nested, `${path}.method`, 'method', before.method, after.method))\n\t\t}\n\t\tdiffValue(before.args, after.args, `${path}.args`, 'args', {\n\t\t\tslideNumber: number,\n\t\t\tshapeName: name,\n\t\t\tnestedNames: nested,\n\t\t\tout,\n\t\t})\n\t}\n}\n\n/**\n * Where in the deck a difference is being reported, and where the report goes.\n *\n * Four of `diffValue`'s eight positional parameters were this, threaded unchanged through\n * every recursion; only `path` and `field` move as it walks. Bundling them is what makes the\n * recursive calls read as \"same site, deeper path\".\n */\ninterface DiffSite {\n\tslideNumber: number\n\tshapeName: string | null\n\tnestedNames: string[]\n\tout: IrDifference[]\n}\n\nfunction diffValue(expected: IrValue, actual: IrValue, path: string, field: string, site: DiffSite): void {\n\tconst { slideNumber, shapeName, nestedNames, out } = site\n\tif (expected === actual) return\n\tconst kindOf = (value: IrValue): string => (value === null ? 'null' : Array.isArray(value) ? 'array' : typeof value)\n\tif (kindOf(expected) !== kindOf(actual)) {\n\t\tout.push(scalarDifference(slideNumber, shapeName, nestedNames, path, field, expected, actual))\n\t\treturn\n\t}\n\n\tif (Array.isArray(expected) && Array.isArray(actual)) {\n\t\tconst length = Math.max(expected.length, actual.length)\n\t\tfor (let index = 0; index < length; index++) {\n\t\t\tconst before = expected[index]\n\t\t\tconst after = actual[index]\n\t\t\tif (before === undefined || after === undefined) {\n\t\t\t\tout.push({\n\t\t\t\t\tslideNumber,\n\t\t\t\t\tshapeName,\n\t\t\t\t\tnestedNames,\n\t\t\t\t\tpath: `${path}[${index}]`,\n\t\t\t\t\tfield,\n\t\t\t\t\tkind: before === undefined ? 'added' : 'lost',\n\t\t\t\t\texpected: brief(before),\n\t\t\t\t\tactual: brief(after),\n\t\t\t\t\tdeclaredBy: null,\n\t\t\t\t})\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tdiffValue(before, after, `${path}[${index}]`, field, site)\n\t\t}\n\t\treturn\n\t}\n\n\tif (expected !== null && typeof expected === 'object' && actual !== null && typeof actual === 'object') {\n\t\tconst record = expected as Record<string, IrValue>\n\t\tconst other = actual as Record<string, IrValue>\n\t\tfor (const key of new Set([...Object.keys(record), ...Object.keys(other)])) {\n\t\t\tconst before = record[key]\n\t\t\tconst after = other[key]\n\t\t\tif (before === undefined || after === undefined) {\n\t\t\t\tout.push({\n\t\t\t\t\tslideNumber,\n\t\t\t\t\tshapeName,\n\t\t\t\t\tnestedNames,\n\t\t\t\t\tpath: `${path}.${key}`,\n\t\t\t\t\tfield: key,\n\t\t\t\t\tkind: before === undefined ? 'added' : 'lost',\n\t\t\t\t\texpected: brief(before),\n\t\t\t\t\tactual: brief(after),\n\t\t\t\t\tdeclaredBy: null,\n\t\t\t\t})\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tdiffValue(before, after, `${path}.${key}`, key, site)\n\t\t}\n\t\treturn\n\t}\n\n\tout.push(scalarDifference(slideNumber, shapeName, nestedNames, path, field, expected, actual))\n}\n\nfunction scalarDifference(\n\tslideNumber: number,\n\tshapeName: string | null,\n\tnestedNames: string[],\n\tpath: string,\n\tfield: string,\n\texpected: IrValue,\n\tactual: IrValue\n): IrDifference {\n\treturn {\n\t\tslideNumber,\n\t\tshapeName,\n\t\tnestedNames,\n\t\tpath,\n\t\tfield,\n\t\tkind: 'changed',\n\t\texpected: brief(expected),\n\t\tactual: brief(actual),\n\t\tdeclaredBy: null,\n\t}\n}\n\n/**\n * The dotted option path a difference sits at, array indices removed: `calls[4].args[1].line.width`\n * becomes `['calls', 'args', 'line', 'width']`.\n *\n * Both exclusion mechanisms used to match the terminal key alone, at any depth anywhere in the\n * IR — so `type` (written about a fill's solid default) excused an added `bullet.type`, waving\n * through a character bullet that came back as a numbered list; `title` (written about\n * `docProps`) excused an added chart title; and `width` (written about `a:ln/@w`) excused an\n * added table-cell bevel or border width. Matching a suffix keeps every bare key working where\n * it is unambiguous and lets a spec say WHICH `width` it means.\n */\nfunction pathKeys(difference: IrDifference): string[] {\n\tconst keys = difference.path.split('.').map((segment) => segment.replace(/\\[[^\\]]*\\]/g, ''))\n\t// A handful of differences are synthesised rather than walked, and name a `field` the path\n\t// does not end in — a whole master reported at `chrome.masters[11]` with `field: 'master'`.\n\t// Appending it keeps those matchable while leaving every walked difference untouched.\n\treturn keys[keys.length - 1] === difference.field ? keys : [...keys, difference.field]\n}\n\n/**\n * Whether one exclusion spec covers a difference. `'*'` covers everything in the note's scope.\n * Anything else is matched against the difference's own path in one of two modes:\n *\n * - `'suffix'`: the spec is a dotted SUFFIX of the path. Used for a note scoped to a shape, which\n * the shape scoping has already confined to one call, so the spec only has to say which option\n * inside it. Used for {@link WRITER_DEFAULTS} too, whose entries are option names wherever the\n * write path materialises them.\n * - `'root'`: the spec is the dotted path of one node from the root of the diff (`background`,\n * `chrome.masters.title`), and covers that node only. A trailing `.*` extends it to everything\n * beneath the node as well (`transition.sound.*`). Used for a note with no shape, which nothing\n * else confines. Matched as a suffix, a slide or deck note's field names matched inside every\n * call in its scope: `master.background`'s `color` excused every run colour in the deck, and\n * `slide.transitionSound`'s `$asset` excused different image bytes on its slide. Exact by\n * default because `slide.transition` is `transition` and must not cover the sound inside it.\n */\nfunction specCovers(spec: string, difference: IrDifference, anchor: 'suffix' | 'root'): boolean {\n\tif (spec === '*') return true\n\tconst wanted = spec.split('.')\n\tconst keys = pathKeys(difference)\n\tif (anchor === 'root') {\n\t\tconst subtree = wanted[wanted.length - 1] === '*'\n\t\tconst node = subtree ? wanted.slice(0, -1) : wanted\n\t\tif (subtree ? node.length > keys.length : node.length !== keys.length) return false\n\t\treturn node.every((segment, index) => segment === keys[index])\n\t}\n\tif (wanted.length > keys.length) return false\n\treturn wanted.every((segment, index) => segment === keys[keys.length - wanted.length + index])\n}\n\n/**\n * Whether the shape a shape-scoped note names is the one a difference sits on: the call itself, or\n * a group child inside it.\n *\n * A shape with no name of its own is scoped as `''`, and its call carries no name to match, so a\n * note on one covers the unnamed calls on its slide and nothing else. Not a named shape, and not\n * the slide's own keys either, which a `*` note would otherwise excuse. An unnamed group child is\n * not matched through its group: the group's call names no such child.\n */\nfunction coversShape(shapeName: string, difference: IrDifference): boolean {\n\tif (shapeName === '') return difference.shapeName === null && difference.path.startsWith('calls[')\n\treturn shapeName === difference.shapeName || difference.nestedNames.includes(shapeName)\n}\n\n/** The first note that covers this difference, or `null` if none does. */\nfunction declaringNote(difference: IrDifference, notes: FidelityNote[]): FidelityNote | null {\n\tfor (const note of notes) {\n\t\tif (note.slideNumber !== null && note.slideNumber !== difference.slideNumber) continue\n\t\t// A layout-shape note is about the chrome, which the diff reports in the deck-level bucket.\n\t\t// Without this a themed outline on a layout — recorded with no slide number, and named\n\t\t// after a shape whose name repeats between the layout and the slides bound to it — would\n\t\t// excuse the same difference on a *slide*, which is a loss nothing declared.\n\t\tif (note.construct.startsWith(LAYOUT_NOTE_PREFIX) && difference.slideNumber !== 0) continue\n\t\t// A shape-scoped note covers only that shape; a slide- or deck-scoped one covers any, which\n\t\t// is why its fields are anchored at the root of the diff rather than matched as a suffix.\n\t\tif (note.shapeName !== null && !coversShape(note.shapeName, difference)) continue\n\t\tconst fields = noteFields(note.construct)\n\t\tif (!fields) continue\n\t\tconst anchor = note.shapeName === null ? 'root' : 'suffix'\n\t\tif (fields.some((field) => specCovers(field, difference, anchor))) return note\n\t}\n\treturn null\n}\n\n/**\n * The fields a construct is a promise about.\n *\n * A layout-shape construct falls back to its slide counterpart, which is the whole point of\n * borrowing the vocabulary: `layout.line.width` is `line.width` on a layout and covers exactly\n * the same field. Only the two constructs with no slide twin need entries of their own.\n */\nfunction noteFields(construct: string): readonly string[] | undefined {\n\tconst table: Record<string, NoteConstructEntry | undefined> = NOTE_CONSTRUCTS\n\treturn table[construct]?.fields ?? (construct.startsWith(LAYOUT_NOTE_PREFIX) ? table[construct.slice(LAYOUT_NOTE_PREFIX.length)]?.fields : undefined) // prettier-ignore\n}\n\n/**\n * `true` when the coverage table can match this construct — directly or through the\n * layout-shape fallback. The check a corpus test runs over every note both printers emit.\n */\nexport function isKnownNoteConstruct(construct: string): boolean {\n\treturn noteFields(construct) !== undefined\n}\n\nfunction brief(value: IrValue | undefined): string {\n\tif (value === undefined) return '—'\n\tconst text = JSON.stringify(value)\n\treturn text.length > 80 ? `${text.slice(0, 80)}…` : text\n}\n"],"mappings":"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"}
|