@shbernal/ts-pptx 4.1.0 → 5.0.0

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.
Files changed (139) hide show
  1. package/README.md +11 -11
  2. package/dist/anim-presets-Qbgh8uut.js +55 -0
  3. package/dist/anim-presets-Qbgh8uut.js.map +1 -0
  4. package/dist/{autopage-D4kyVp11.js → autopage-DqZ37VpL.js} +11 -12
  5. package/dist/autopage-DqZ37VpL.js.map +1 -0
  6. package/dist/{binary-string-CKVAYI3M.js → binary-string-Ba8VM3b9.js} +3 -4
  7. package/dist/binary-string-Ba8VM3b9.js.map +1 -0
  8. package/dist/{body-insets-kVHmjGc6.js → body-insets-BDHymJvz.js} +7 -9
  9. package/dist/body-insets-BDHymJvz.js.map +1 -0
  10. package/dist/browser.d.ts +24 -16
  11. package/dist/browser.d.ts.map +1 -1
  12. package/dist/browser.js +19 -19
  13. package/dist/browser.js.map +1 -1
  14. package/dist/{image-size-DwDbakcl.js → chart-metadata-CwiTTcJq.js} +576 -538
  15. package/dist/chart-metadata-CwiTTcJq.js.map +1 -0
  16. package/dist/{clip-DHDlnHUq.d.ts → clip-ISfCMtWA.d.ts} +6 -10
  17. package/dist/clip-ISfCMtWA.d.ts.map +1 -0
  18. package/dist/{notes-BcT571R4.js → comments-CKIZYRbZ.js} +517 -389
  19. package/dist/comments-CKIZYRbZ.js.map +1 -0
  20. package/dist/{diagnostics-DiMmBU8P.d.ts → diagnostics-MoA4MBq5.d.ts} +52 -50
  21. package/dist/diagnostics-MoA4MBq5.d.ts.map +1 -0
  22. package/dist/{embedded-fonts-CI_YGW2d.d.ts → embedded-fonts-U7HIIhPO.d.ts} +4 -6
  23. package/dist/embedded-fonts-U7HIIhPO.d.ts.map +1 -0
  24. package/dist/{entry-compose-6hF9aTmT.d.ts → entry-compose-CiakSt-f.d.ts} +53 -74
  25. package/dist/entry-compose-CiakSt-f.d.ts.map +1 -0
  26. package/dist/{errors-Da2nXCJm.js → entry-errors-JMthgJ2g.js} +41 -25
  27. package/dist/entry-errors-JMthgJ2g.js.map +1 -0
  28. package/dist/{table-cell-margins-PDshga8T.js → enums-BP9wsb9Q.js} +42 -45
  29. package/dist/enums-BP9wsb9Q.js.map +1 -0
  30. package/dist/{enums-DQRpVOLh.d.ts → enums-PcXr3o3J.d.ts} +11 -12
  31. package/dist/{enums-DQRpVOLh.d.ts.map → enums-PcXr3o3J.d.ts.map} +1 -1
  32. package/dist/families.d.ts +24 -26
  33. package/dist/families.d.ts.map +1 -1
  34. package/dist/families.js +3 -4
  35. package/dist/{fit-CcXbg__l.js → fit-Bpmzep6O.js} +60 -52
  36. package/dist/fit-Bpmzep6O.js.map +1 -0
  37. package/dist/{font-metrics-CBGmhLo0.d.ts → font-metrics-DTppw4t3.d.ts} +61 -37
  38. package/dist/font-metrics-DTppw4t3.d.ts.map +1 -0
  39. package/dist/{grid-9B2w5EaY.js → grid-DUIMxjfl.js} +23 -26
  40. package/dist/grid-DUIMxjfl.js.map +1 -0
  41. package/dist/{html-dom-DvJmuHt2.js → html-dom-LZCgntnJ.js} +42 -43
  42. package/dist/html-dom-LZCgntnJ.js.map +1 -0
  43. package/dist/html.d.ts +53 -9
  44. package/dist/html.d.ts.map +1 -1
  45. package/dist/html.js +12 -13
  46. package/dist/html.js.map +1 -1
  47. package/dist/index.d.ts +21 -13
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +15 -15
  50. package/dist/index.js.map +1 -1
  51. package/dist/inspect.d.ts +14 -16
  52. package/dist/inspect.d.ts.map +1 -1
  53. package/dist/inspect.js +18 -19
  54. package/dist/inspect.js.map +1 -1
  55. package/dist/{text-anchor-BgLPbwbL.js → lock-attrs-CSQnFDHP.js} +62 -12
  56. package/dist/lock-attrs-CSQnFDHP.js.map +1 -0
  57. package/dist/math.d.ts +2 -4
  58. package/dist/math.d.ts.map +1 -1
  59. package/dist/math.js +12 -13
  60. package/dist/math.js.map +1 -1
  61. package/dist/measure.d.ts +23 -12
  62. package/dist/measure.d.ts.map +1 -1
  63. package/dist/measure.js +3 -3
  64. package/dist/node.d.ts +21 -13
  65. package/dist/node.d.ts.map +1 -1
  66. package/dist/node.js +12 -12
  67. package/dist/node.js.map +1 -1
  68. package/dist/{options-internal-WqgMf720.js → options-internal-BWgmLPdx.js} +4 -5
  69. package/dist/options-internal-BWgmLPdx.js.map +1 -0
  70. package/dist/{package-KoEgVwII.d.ts → package-CANBWuSm.d.ts} +4 -12
  71. package/dist/package-CANBWuSm.d.ts.map +1 -0
  72. package/dist/{playbtn-CUqQdoDf.js → playbtn-BQZFJir9.js} +4 -5
  73. package/dist/playbtn-BQZFJir9.js.map +1 -0
  74. package/dist/{pres-BA9_lJbY.d.ts → pres-BkEkUAEM.d.ts} +383 -230
  75. package/dist/pres-BkEkUAEM.d.ts.map +1 -0
  76. package/dist/{presentation-Cyl74rq2.js → presentation-4Ggq0_Xa.js} +408 -288
  77. package/dist/presentation-4Ggq0_Xa.js.map +1 -0
  78. package/dist/{presentation-types-B3VQH4Bz.d.ts → presentation-types-BgnZR-0a.d.ts} +1104 -457
  79. package/dist/presentation-types-BgnZR-0a.d.ts.map +1 -0
  80. package/dist/read.d.ts +18 -13
  81. package/dist/read.d.ts.map +1 -1
  82. package/dist/read.js +4 -4
  83. package/dist/script.d.ts +116 -65
  84. package/dist/script.d.ts.map +1 -1
  85. package/dist/script.js +2697 -777
  86. package/dist/script.js.map +1 -1
  87. package/dist/{shapes-BcyFdZpp.js → shapes-CAPOjU0Q.js} +1556 -487
  88. package/dist/shapes-CAPOjU0Q.js.map +1 -0
  89. package/dist/{slide-BqPtyKmb.d.ts → slide-BmT4kMoO.d.ts} +94 -86
  90. package/dist/slide-BmT4kMoO.d.ts.map +1 -0
  91. package/dist/{slide-size-BalTjFuv.js → slide-size-SkScz1ig.js} +2 -3
  92. package/dist/{slide-size-BalTjFuv.js.map → slide-size-SkScz1ig.js.map} +1 -1
  93. package/dist/{table-dom-CVbvUfgh.js → table-dom-BYga4FYY.js} +3 -4
  94. package/dist/{table-dom-CVbvUfgh.js.map → table-dom-BYga4FYY.js.map} +1 -1
  95. package/dist/{text-BvFFMMFQ.js → text-Dz0ArGIp.js} +365 -318
  96. package/dist/text-Dz0ArGIp.js.map +1 -0
  97. package/dist/{transition-speed-kUEWDWTx.js → transition-speed-CNJ0fSpQ.js} +2 -3
  98. package/dist/{transition-speed-kUEWDWTx.js.map → transition-speed-CNJ0fSpQ.js.map} +1 -1
  99. package/dist/{units-internal-DFcUYjh3.js → units-internal-BR3a4cIi.js} +26 -29
  100. package/dist/units-internal-BR3a4cIi.js.map +1 -0
  101. package/dist/{zip-CYZ0F6BV.js → zip-7JTh61LX.js} +8 -10
  102. package/dist/zip-7JTh61LX.js.map +1 -0
  103. package/dist/{zip-CTll_dr0.d.ts → zip-uUjs9Cqx.d.ts} +4 -6
  104. package/dist/zip-uUjs9Cqx.d.ts.map +1 -0
  105. package/dist/zip.d.ts +3 -3
  106. package/dist/zip.js +3 -3
  107. package/dist/{zoom-BoNyOlPm.js → zoom-CSSeOwM8.js} +1153 -583
  108. package/dist/zoom-CSSeOwM8.js.map +1 -0
  109. package/package.json +20 -21
  110. package/skills/{ts-pptx-upstream → pptx-ts-upstream}/SKILL.md +27 -74
  111. package/dist/autopage-D4kyVp11.js.map +0 -1
  112. package/dist/binary-string-CKVAYI3M.js.map +0 -1
  113. package/dist/body-insets-kVHmjGc6.js.map +0 -1
  114. package/dist/clip-DHDlnHUq.d.ts.map +0 -1
  115. package/dist/diagnostics-DiMmBU8P.d.ts.map +0 -1
  116. package/dist/embedded-fonts-CI_YGW2d.d.ts.map +0 -1
  117. package/dist/entry-compose-6hF9aTmT.d.ts.map +0 -1
  118. package/dist/errors-Da2nXCJm.js.map +0 -1
  119. package/dist/fit-CcXbg__l.js.map +0 -1
  120. package/dist/font-metrics-CBGmhLo0.d.ts.map +0 -1
  121. package/dist/grid-9B2w5EaY.js.map +0 -1
  122. package/dist/html-dom-DvJmuHt2.js.map +0 -1
  123. package/dist/image-size-DwDbakcl.js.map +0 -1
  124. package/dist/notes-BcT571R4.js.map +0 -1
  125. package/dist/options-internal-WqgMf720.js.map +0 -1
  126. package/dist/package-KoEgVwII.d.ts.map +0 -1
  127. package/dist/playbtn-CUqQdoDf.js.map +0 -1
  128. package/dist/pres-BA9_lJbY.d.ts.map +0 -1
  129. package/dist/presentation-Cyl74rq2.js.map +0 -1
  130. package/dist/presentation-types-B3VQH4Bz.d.ts.map +0 -1
  131. package/dist/shapes-BcyFdZpp.js.map +0 -1
  132. package/dist/slide-BqPtyKmb.d.ts.map +0 -1
  133. package/dist/table-cell-margins-PDshga8T.js.map +0 -1
  134. package/dist/text-BvFFMMFQ.js.map +0 -1
  135. package/dist/text-anchor-BgLPbwbL.js.map +0 -1
  136. package/dist/units-internal-DFcUYjh3.js.map +0 -1
  137. package/dist/zip-CTll_dr0.d.ts.map +0 -1
  138. package/dist/zip-CYZ0F6BV.js.map +0 -1
  139. package/dist/zoom-BoNyOlPm.js.map +0 -1
@@ -1,13 +1,13 @@
1
- import { i as PackageReadError, l as warn, n as InvalidOptionError, o as UnsupportedFeatureError, t as InternalError } from "./errors-Da2nXCJm.js";
2
- import { X as MIN_SLIDE_MASTER_ID, Y as MAX_SLIDE_ID } from "./units-internal-DFcUYjh3.js";
3
- import { D as emuToInches } from "./table-cell-margins-PDshga8T.js";
4
- import { $t as THEME_CONTENT_TYPE, At as MS_REL, Bt as PRESENTATION_MAIN_CONTENT_TYPE, Dt as MODERN_COMMENT_AUTHORS_REL, E as EMBEDDED_FONT_SLOTS, Gt as SLIDE_CONTENT_TYPE, It as OFFICE_DOCUMENT_REL, Lt as OFFICE_REL, Mt as NOTES_MASTER_REL, Nt as NOTES_SLIDE_CONTENT_TYPE, Ot as MS_MEDIA_REL, Pt as NOTES_SLIDE_REL, Q as THEME_COLOR_SLOTS, Qt as TABLE_STYLES_REL, Rt as PACKAGE_REL, S as COLOR_MAP_TOKENS, Tt as IMAGE_REL, Ut as RELATIONSHIPS_CONTENT_TYPE, Wt as SHARED_PARTS, Xt as SLIDE_REL, Yt as SLIDE_MASTER_REL, Zt as TABLE_STYLES_CONTENT_TYPE, an as OOXML_NS, at as CHARTEX_CONTENT_TYPE, ct as CHART_COLOR_STYLE_REL, dt as CHART_STYLE_CONTENT_TYPE, en as THEME_REL, ft as CHART_STYLE_REL, in as XLSX_CONTENT_TYPE, it as AUDIO_REL, jt as NOTES_MASTER_CONTENT_TYPE, kt as MS_POWERPOINT_CONTENT, lt as CHART_CONTENT_TYPE, mt as COMMENTS_REL, ot as CHARTEX_REL, pn as imageFormatForBytes, qt as SLIDE_LAYOUT_REL, st as CHART_COLOR_STYLE_CONTENT_TYPE, tn as VIDEO_REL, u as boolValue, ut as CHART_REL, vt as CORE_PROPS_REL, wt as HYPERLINK_REL } from "./image-size-DwDbakcl.js";
5
- import { Ct as FONT_DATA_CONTENT_TYPE, Ot as XML_DECL, Rt as encodeXmlAttrValue, St as voidEl, Tt as FONT_REL_TYPE, n as makeXmlNotesMaster, o as makeXmlNotesSlideSkeleton, wt as FONT_DATA_EXTENSION, xt as raw, yt as el } from "./notes-BcT571R4.js";
6
- import { t as pickDefined } from "./options-internal-WqgMf720.js";
7
- import { n as readZip, t as ZipWriter } from "./zip-CYZ0F6BV.js";
8
- import { t as transitionSpeedForDuration } from "./transition-speed-kUEWDWTx.js";
9
- import { $ as placeholderInheritedColor, $t as relsPartNameFor, A as flattenAnimations, At as CSLD_AFTER_BG, B as readColorRef, Bt as SLIDE_AFTER_TRANSITION, Ct as styleRefFill, E as AutoShape, Et as themeElementsOfRoot, Ft as PRESENTATION_AFTER_SLD_ID_LST, G as resolveSlideColorContext, Gt as SPPR_LN_AFTER, H as resolveLayoutColorContext, Ht as SPPR_AFTER_XFRM, It as PRESENTATION_AFTER_SLD_MASTER_ID_LST, J as checkPositiveEmu, Jt as TXBODY_AFTER_BODYPR, K as resolveSlideThemeParts, Kt as SPPR_SCENE3D_AFTER, L as readPatternFill, Lt as RPR_FILL_AFTER, M as pruneSpids, Mt as LN_SLOTS, N as remapSpids, Nt as PRESENTATION_AFTER_EMBEDDED_FONT_LST, O as carryShapeAnimations, Ot as hasFillChoice, P as TextFrame, Pt as PRESENTATION_AFTER_NOTES_MASTER_ID_LST, Q as placeholderInheritedAnchor, Qt as relativePartName, R as readPictureFill, Rt as RUN_AFTER_RPR, St as resolveSchemeToken, T as Picture, Tt as substitutePhClr, U as resolveMasterColorContext, Ut as SPPR_EFFECT_AFTER, Vt as SLIDE_MASTER_AFTER_SLD_LAYOUT_ID_LST, W as resolveNotesColorContext, Wt as SPPR_FILL_AFTER, X as RUN_PROP_NAMES, Xt as partNameExtension, Y as LST_STYLE_LEVELS, Yt as TXBODY_AFTER_LSTSTYLE, Z as lstStyleLevelDefRPr, Zt as partNameToZipPath, _n as parseXml, _t as isA, an as boolAttr, at as slideDefinesProp, bn as serializeXml, bt as replaceColorElement, cn as descendantsByTag, ct as carriedDecorations, dn as getElements, dt as nextDrawingId, en as resolveRelativePartName, et as placeholderInheritedListStyles, fn as getOrAddChild, ft as nthShapeChild, gn as ownerDocumentOf, gt as fmtEntry, hn as numberValue, ht as spTreeOf, in as attr, it as slideDefinesColor, j as hasAnimations, jt as EMBEDDED_FONT_ENTRY_AFTER, k as enumerateSpids, l as wrapShapeElement, ln as firstChild, lt as collectElements, m as resolveTableCellTextStyle, mn as numberAttr, mt as reassignDrawingIds, n as buildShapes, nn as singleRelPart, nt as placeholderInheritedXfrm, on as childElements, ot as cSldName, pn as insertInOrder, pt as nvPrOf, q as checkFiniteEmu, qt as SPPR_SP3D_AFTER, r as findShapeByIdDeep, rn as zipPathToPartName, rt as placeholderOf, sn as createElement, st as cSldOf, t as GroupShape, tn as resolveSingleRel, tt as placeholderInheritedRunProps, u as GraphicFrame, un as firstChildElement, ut as firstShapeChild, vn as removeAttr, vt as parseClrMap, wt as styleRefLine, xn as setAttr, xt as resolveColor, yn as removeChildrenByQName, yt as parseClrScheme, z as readGradientFill, zt as SHAPE_AFTER_SPPR } from "./shapes-BcyFdZpp.js";
10
- //#region src/read/opc/content-types.ts
1
+ import { D as emuToInches } from "./enums-BP9wsb9Q.js";
2
+ import { n as readZip, t as ZipWriter } from "./zip-7JTh61LX.js";
3
+ import { $ as LST_STYLE_LEVELS, $t as TXBODY_AFTER_LSTSTYLE, A as enumerateSpids, At as themeElementsOfRoot, Bt as PRESENTATION_AFTER_SLD_MASTER_ID_LST, Cn as removeChildrenByQName, Ct as parseClrScheme, D as AutoShape, Dt as styleRefFill, E as Picture, Et as resolveSchemeToken, F as remapSpids, Ft as EMBEDDED_FONT_ENTRY_AFTER, Gt as SLIDE_MASTER_AFTER_SLD_LAYOUT_ID_LST, H as readGradientFill, Ht as RUN_AFTER_RPR, I as TextFrame, It as LN_SLOTS, J as resolveNotesColorContext, Jt as SPPR_FILL_AFTER, K as resolveLayoutColorContext, Kt as SPPR_AFTER_XFRM, Lt as PRESENTATION_AFTER_EMBEDDED_FONT_LST, M as hasAnimations, Mt as hasFillChoice, N as pruneSpids, Ot as styleRefLine, P as readBuildEffects, Pt as CSLD_AFTER_BG, Q as checkPositiveEmu, Qt as TXBODY_AFTER_BODYPR, Rt as PRESENTATION_AFTER_NOTES_MASTER_ID_LST, Sn as removeAttr, St as parseClrMap, Tn as setAttr, Tt as resolveColor, U as readPictureFill, Ut as SHAPE_AFTER_SPPR, V as readPatternFill, Vt as RPR_FILL_AFTER, W as readColorRef, Wt as SLIDE_AFTER_TRANSITION, X as resolveSlideThemeParts, Xt as SPPR_SCENE3D_AFTER, Y as resolveSlideColorContext, Yt as SPPR_LN_AFTER, Z as checkFiniteEmu, Zt as SPPR_SP3D_AFTER, _n as insertInOrder, _t as nvPrOf, an as resolveSingleRel, at as placeholderInheritedRunProps, bn as ownerDocumentOf, bt as fmtEntry, cn as attr, ct as slideDefinesColor, dn as createElement, dt as cSldOf, en as partNameExtension, et as RUN_PROP_NAMES, fn as descendantsByTag, ft as carriedDecorations, gn as getOrAddChild, gt as nthShapeChild, hn as getElements, ht as nextDrawingId, in as resolveRelativePartName, it as placeholderInheritedListStyles, j as flattenAnimations, k as carryShapeAnimations, kt as substitutePhClr, l as wrapShapeElement, ln as boolAttr, lt as slideDefinesProp, m as resolveTableCellTextStyle, mn as firstChildElement, mt as firstShapeChild, n as buildShapes, nn as relativePartName, nt as placeholderInheritedAnchor, on as singleRelPart, ot as placeholderInheritedXfrm, pn as firstChild, pt as collectElements, q as resolveMasterColorContext, qt as SPPR_EFFECT_AFTER, r as findShapeByIdDeep, rn as relsPartNameFor, rt as placeholderInheritedColor, sn as zipPathToPartName, st as placeholderOf, t as GroupShape, tn as partNameToZipPath, tt as lstStyleLevelDefRPr, u as GraphicFrame, un as childElements, ut as cSldName, vn as numberAttr, vt as reassignDrawingIds, wn as serializeXml, wt as replaceColorElement, xn as parseXml, xt as isA, yn as numberValue, yt as spTreeOf, zt as PRESENTATION_AFTER_SLD_ID_LST } from "./shapes-CAPOjU0Q.js";
4
+ import { Ft as voidEl, It as XML_DECL, Kt as encodeXmlAttrValue, Mt as el, Pt as raw, a as makeXmlNotesMaster, gt as FONT_REL_TYPE, ht as FONT_DATA_EXTENSION, l as makeXmlNotesSlideSkeleton, mt as FONT_DATA_CONTENT_TYPE, n as makeXmlComments, t as makeXmlCommentAuthors } from "./comments-CKIZYRbZ.js";
5
+ import { a as PackageReadError, n as InternalError, r as InvalidOptionError, s as UnsupportedFeatureError, u as warn } from "./entry-errors-JMthgJ2g.js";
6
+ import { B as NOTES_SLIDE_CONTENT_TYPE, C as COMMENT_AUTHORS_REL, F as MS_MEDIA_REL, G as PACKAGE_REL, I as MS_POWERPOINT_CONTENT, L as MS_REL, M as IMAGE_REL, P as MODERN_COMMENT_AUTHORS_REL, Q as SLIDE_CONTENT_TYPE, Qt as THEME_COLOR_SLOTS, R as NOTES_MASTER_CONTENT_TYPE, S as COMMENT_AUTHORS_CONTENT_TYPE, T as CORE_PROPS_REL, Tt as EMBEDDED_FONT_SLOTS, U as OFFICE_DOCUMENT_REL, V as NOTES_SLIDE_REL, W as OFFICE_REL, X as RELATIONSHIPS_CONTENT_TYPE, Z as SHARED_PARTS, _ as CHART_REL, _n as imageFormatForBytes, at as TABLE_STYLES_REL, b as COMMENTS_CONTENT_TYPE, ct as VIDEO_REL, d as AUDIO_REL, dt as XLSX_CONTENT_TYPE, et as SLIDE_LAYOUT_REL, f as CHARTEX_CONTENT_TYPE, ft as OOXML_NS, g as CHART_CONTENT_TYPE, h as CHART_COLOR_STYLE_REL, it as TABLE_STYLES_CONTENT_TYPE, j as HYPERLINK_REL, m as CHART_COLOR_STYLE_CONTENT_TYPE, nt as SLIDE_MASTER_REL, on as boolValue, ot as THEME_CONTENT_TYPE, p as CHARTEX_REL, q as PRESENTATION_MAIN_CONTENT_TYPE, rt as SLIDE_REL, st as THEME_REL, v as CHART_STYLE_CONTENT_TYPE, x as COMMENTS_REL, xt as COLOR_MAP_TOKENS, y as CHART_STYLE_REL, z as NOTES_MASTER_REL } from "./chart-metadata-CwiTTcJq.js";
7
+ import { X as MIN_SLIDE_MASTER_ID, Y as MAX_SLIDE_ID } from "./units-internal-BR3a4cIi.js";
8
+ import { t as transitionSpeedForDuration } from "./transition-speed-CNJ0fSpQ.js";
9
+ import { t as pickDefined } from "./options-internal-BWgmLPdx.js";
10
+ // src/read/opc/content-types.ts
11
11
  /**
12
12
  * Overlay over `[Content_Types].xml`, used to resolve part content types at
13
13
  * load and to register new ones when parts are added. While clean, the original
@@ -57,7 +57,7 @@ var ContentTypes = class ContentTypes {
57
57
  }
58
58
  /**
59
59
  * Drop the `Override` for `partName` if present (e.g. when a part is removed).
60
- * `Default` rules by extension are left untouched — they may still serve other
60
+ * `Default` rules by extension are left untouched; they may still serve other
61
61
  * parts. Marks the overlay dirty when something was removed.
62
62
  */
63
63
  removeOverride(partName) {
@@ -78,10 +78,9 @@ var ContentTypes = class ContentTypes {
78
78
  return lines.join("");
79
79
  }
80
80
  };
81
- //#endregion
82
- //#region src/read/opc/part.ts
81
+ // src/read/opc/part.ts
83
82
  const textDecoder$1 = new TextDecoder("utf-8");
84
- const textEncoder$4 = new TextEncoder();
83
+ const textEncoder$5 = new TextEncoder();
85
84
  const XML_DECLARATION_RE = /^\uFEFF?<\?xml[^>]*\?>\s*/;
86
85
  /**
87
86
  * One OPC part. Holds the original bytes from the zip for its whole life;
@@ -147,11 +146,10 @@ var Part = class {
147
146
  if (!this.#dirty) return this.#bytes;
148
147
  let xml = serializeXml(this.dom);
149
148
  if (!xml.startsWith("<?xml")) xml = (XML_DECLARATION_RE.exec(textDecoder$1.decode(this.#bytes))?.[0] ?? "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\r\n") + xml;
150
- return textEncoder$4.encode(xml);
149
+ return textEncoder$5.encode(xml);
151
150
  }
152
151
  };
153
- //#endregion
154
- //#region src/read/opc/relationships.ts
152
+ // src/read/opc/relationships.ts
155
153
  /**
156
154
  * Overlay over one `.rels` part, keyed by relationship id. While clean, the
157
155
  * `.rels` bytes pass through verbatim on save (byte-identical); once `add()`
@@ -302,17 +300,16 @@ var Relationships = class Relationships {
302
300
  return lines.join("");
303
301
  }
304
302
  };
305
- //#endregion
306
- //#region src/read/opc/package.ts
303
+ // src/read/opc/package.ts
307
304
  const CONTENT_TYPES_ZIP_PATH = "[Content_Types].xml";
308
305
  const textDecoder = new TextDecoder("utf-8");
309
- const textEncoder$3 = new TextEncoder();
306
+ const textEncoder$4 = new TextEncoder();
310
307
  /**
311
308
  * An OPC package loaded from `.pptx` bytes.
312
309
  *
313
310
  * Fidelity contract: parts that are never mutated (`Part.markDirty()`) are
314
311
  * written back byte-identically by `save()`. Whole-zip byte-identity is not
315
- * promised — zip metadata and compression may differ — but part bodies, the
312
+ * promised (zip metadata and compression may differ), but part bodies, the
316
313
  * part-name set, and part order are preserved.
317
314
  */
318
315
  var OpcPackage = class OpcPackage {
@@ -407,7 +404,7 @@ var OpcPackage = class OpcPackage {
407
404
  * later `save()` neither re-emits it nor flushes a stale `.rels` for it. A relationship set
408
405
  * belongs to its part: one left behind would come back as the relationships of the next part
409
406
  * added under the same name. Low-level: it does not touch references *to* this part
410
- * (dangling rels are the caller's concern) nor cascade to parts this one referenced — see
407
+ * (dangling rels are the caller's concern) nor cascade to parts this one referenced; see
411
408
  * {@link Presentation.removeSlide} for the slide-aware variant that unwires the presentation
412
409
  * and prunes orphans.
413
410
  */
@@ -481,21 +478,20 @@ var OpcPackage = class OpcPackage {
481
478
  for (const relationships of this.#relationshipsCache.values()) {
482
479
  if (!relationships.isDirty) continue;
483
480
  const relsPartName = relsPartNameFor(relationships.sourcePartName);
484
- const bytes = textEncoder$3.encode(relationships.serialize());
481
+ const bytes = textEncoder$4.encode(relationships.serialize());
485
482
  this.#parts.set(relsPartName, new Part(relsPartName, RELATIONSHIPS_CONTENT_TYPE, bytes));
486
483
  this.#partsByContentType = null;
487
484
  }
488
485
  }
489
486
  };
490
- //#endregion
491
- //#region src/read/api/slide-background.ts
487
+ // src/read/api/slide-background.ts
492
488
  /**
493
489
  * Read a slide's effective background (`p:cSld/p:bg`), decoded into a typed union.
494
490
  *
495
491
  * A background lives on the slide itself, or is inherited from its slideLayout,
496
- * else its slideMaster — the {@link SlideBackground.source} field records which.
492
+ * else its slideMaster; the {@link SlideBackground.source} field records which.
497
493
  * The writer authors solid-colour, gradient, pattern and image backgrounds (all FAITHFUL);
498
- * theme-indexed (`p:bgRef`) backgrounds are read-only for imported decks — surface
494
+ * theme-indexed (`p:bgRef`) backgrounds are read-only for imported decks. Surface
499
495
  * them so a codegen pass can carry the part rather than fake it. A
500
496
  * `themeRef` additionally resolves its `idx` through the slide theme's `fmtScheme`
501
497
  * to a concrete {@link BackgroundFill} in `resolvedFill`, so a consumer can ask what
@@ -538,13 +534,13 @@ function decodeBackgroundFill(container, ctx, rels) {
538
534
  /**
539
535
  * Resolve a `p:bgRef`'s `idx` into the concrete {@link BackgroundFill} it renders
540
536
  * as, through the slide theme's `fmtScheme`. A `p:bgRef` is a
541
- * `CT_StyleMatrixReference` — the same shape as a shape's `a:fillRef` — so
537
+ * `CT_StyleMatrixReference` (the same shape as a shape's `a:fillRef`), so
542
538
  * {@link styleRefFill} builds the indexed `bgFillStyleLst`/`fillStyleLst` entry with
543
539
  * its `phClr` substituted by the bgRef's colour, and the resulting fill element is
544
540
  * decoded like a `p:bgPr`. `null` when the theme has no `fmtScheme`, the entry is
545
541
  * absent, or the colour cannot be resolved.
546
542
  *
547
- * `themeRels` — not the owning slide/layout/master's rels — is what an `a:blipFill`
543
+ * `themeRels`, not the owning slide/layout/master's rels, is what an `a:blipFill`
548
544
  * entry's `r:embed` resolves against: the fill element is lifted out of the *theme*
549
545
  * part, so its relationship id is scoped to that part. Several stock Office themes
550
546
  * (Ion, Facet, …) put a picture in the third `bgFillStyleLst` slot, so a deck using
@@ -585,14 +581,13 @@ function readSlideBackground(bg, source, ctx, rels, themeRels) {
585
581
  source
586
582
  };
587
583
  }
588
- //#endregion
589
- //#region src/read/api/ops/part-index.ts
584
+ // src/read/api/ops/part-index.ts
590
585
  /**
591
586
  * Walking a deck's master/layout spine by partname.
592
587
  *
593
588
  * The `p:sldMasterIdLst` / `p:sldLayoutIdLst` entries hold relationship ids, not partnames, so
594
589
  * every traversal has to resolve through the owning part's relationships. These are the
595
- * source-side reads that do it — used against a *foreign* presentation as often as against this
590
+ * source-side reads that do it, used against a *foreign* presentation as often as against this
596
591
  * one, which is why they take the deck rather than living on it.
597
592
  */
598
593
  /**
@@ -632,8 +627,7 @@ function idListTargets(lst, qname, resolve) {
632
627
  }
633
628
  return out;
634
629
  }
635
- //#endregion
636
- //#region src/read/api/chrome.ts
630
+ // src/read/api/chrome.ts
637
631
  /** Read `<a:latin>`/`<a:ea>`/`<a:cs>` typefaces of a theme font family; empty string ⇒ `null`. */
638
632
  function readThemeFontFace(font) {
639
633
  const face = (child) => {
@@ -727,7 +721,7 @@ function placeholderShapes(spTree) {
727
721
  return getElements(spTree, "p:sp").filter((sp) => placeholderOf(sp) !== null);
728
722
  }
729
723
  /**
730
- * One placeholder shape (`p:sp` with a `p:ph`) of a slide master or slide layout —
724
+ * One placeholder shape (`p:sp` with a `p:ph`) of a slide master or slide layout:
731
725
  * the definition a slide's placeholder of the same `type`/`idx` inherits geometry
732
726
  * and text style from. Geometry getters read the placeholder's *own* `a:xfrm`,
733
727
  * which a master/layout placeholder carries explicitly (so it round-trips, unlike a
@@ -753,7 +747,7 @@ var Placeholder = class {
753
747
  * `xfrm()` + `emuFrom`; and,
754
748
  * the one that showed, the text frame was built with **no** inheritance context, so
755
749
  * `Run.resolvedSizePt`, `resolvedFontFace`, `resolvedColor` and `resolvedBold` resolved
756
- * through `SlideMaster.shapes` and came back `null` through `SlideMaster.placeholders` —
750
+ * through `SlideMaster.shapes` and came back `null` through `SlideMaster.placeholders`:
757
751
  * two views of one element disagreeing about the same run.
758
752
  */
759
753
  shape;
@@ -821,7 +815,7 @@ var Placeholder = class {
821
815
  }
822
816
  };
823
817
  /**
824
- * The shared body of a slide master and a slide layout — the two template tiers a slide
818
+ * The shared body of a slide master and a slide layout, the two template tiers a slide
825
819
  * inherits from.
826
820
  *
827
821
  * Both are an OPC part holding a `p:cSld` with a shape tree and a resolvable theme context, and
@@ -839,7 +833,7 @@ var Placeholder = class {
839
833
  *
840
834
  * `Slide` deliberately does not extend this. It is a shape host too, but it is constructed from
841
835
  * a `Presentation` rather than an `OpcPackage`, reaches its relationships through that, and
842
- * reports an unnamed slide as `null` where a template tier reports `''` — three differences in
836
+ * reports an unnamed slide as `null` where a template tier reports `''`. That is three differences in
843
837
  * the same handful of members, which is more contortion than the sharing is worth.
844
838
  */
845
839
  var TemplatePart = class {
@@ -864,7 +858,7 @@ var TemplatePart = class {
864
858
  return (cSld && attr(cSld, "name")) ?? "";
865
859
  }
866
860
  /**
867
- * Every shape in this tier's `p:cSld/p:spTree`, in document order — the same `AnyShape`
861
+ * Every shape in this tier's `p:cSld/p:spTree`, in document order: the same `AnyShape`
868
862
  * union `Slide.shapes` returns, so shape-walking code applies unchanged.
869
863
  *
870
864
  * {@link placeholders} is the filtered view of the same tree.
@@ -934,7 +928,7 @@ var SlideMaster = class extends TemplatePart {
934
928
  }
935
929
  /**
936
930
  * The master's *own* background (`p:cSld/p:bg`), decoded, or `null` when it defines
937
- * none. Scoped to the master's own element — a slide's *effective* background,
931
+ * none. Scoped to the master's own element. A slide's *effective* background,
938
932
  * resolved through the slide → layout → master chain, is `Slide.background`.
939
933
  */
940
934
  get background() {
@@ -943,21 +937,21 @@ var SlideMaster = class extends TemplatePart {
943
937
  const themePart = this.relTarget(THEME_REL);
944
938
  return readSlideBackground(bg, "master", this.themeContext(), this.relationships, themePart ? this.opc.relationshipsFor(themePart.partName) : null);
945
939
  }
946
- /** A master's context is its own `p:clrMap` plus its theme — no walk beyond this part. */
940
+ /** A master's context is its own `p:clrMap` plus its theme; no walk beyond this part. */
947
941
  resolveThemeContext() {
948
942
  return resolveMasterColorContext(this.opc, this.partName);
949
943
  }
950
944
  };
951
945
  /**
952
- * A deck's slide layout (`slideLayoutN.xml`) as a modeled object — the gallery entry
946
+ * A deck's slide layout (`slideLayoutN.xml`) as a modeled object: the gallery entry
953
947
  * a slide binds to. Exposes its {@link name}, its {@link type} (import-only; the
954
948
  * writer authors none), its {@link master} (and, through it, the {@link theme}), its
955
949
  * `shapes` and the `placeholders` subset of them, and its own {@link background}.
956
950
  * Reachable from `Slide.layout` and {@link SlideMaster.layouts}.
957
951
  *
958
952
  * The write API authors non-placeholder shapes into a layout: every
959
- * `defineSlideMaster({ objects })` member that is not a `placeholder` — a `rect`, a
960
- * `line`, an `image`, a `chart`, a `text` box — lands in this tier's tree.
953
+ * `defineSlideMaster({ objects })` member that is not a `placeholder` (a `rect`, a
954
+ * `line`, an `image`, a `chart`, a `text` box) lands in this tier's tree.
961
955
  */
962
956
  var SlideLayout = class extends TemplatePart {
963
957
  /**
@@ -972,7 +966,7 @@ var SlideLayout = class extends TemplatePart {
972
966
  /**
973
967
  * Whether this layout draws the master's non-placeholder shapes
974
968
  * (`p:sldLayout/@showMasterSp`). `xsd:boolean` defaulting to `true`, so an absent
975
- * attribute means shown — the layout-tier counterpart of `Slide.showMasterSp`,
969
+ * attribute means shown. This is the layout-tier counterpart of `Slide.showMasterSp`,
976
970
  * and the one PowerPoint actually writes on a section-divider or full-bleed
977
971
  * layout. A renderer resolving what to paint under a slide's own shapes has to
978
972
  * consult both: the slide's flag, then its layout's.
@@ -992,7 +986,7 @@ var SlideLayout = class extends TemplatePart {
992
986
  }
993
987
  /**
994
988
  * The layout's *own* background (`p:cSld/p:bg`), decoded, or `null` when it defines
995
- * none. A layout usually authors one — an explicit fill (`p:bgPr`) or a
989
+ * none. A layout usually authors one: an explicit fill (`p:bgPr`) or a
996
990
  * theme-indexed reference (`p:bgRef`). The slide's *effective* background is
997
991
  * `Slide.background`.
998
992
  */
@@ -1007,8 +1001,7 @@ var SlideLayout = class extends TemplatePart {
1007
1001
  return resolveLayoutColorContext(this.opc, this.partName);
1008
1002
  }
1009
1003
  };
1010
- //#endregion
1011
- //#region src/read/api/notes.ts
1004
+ // src/read/api/notes.ts
1012
1005
  /**
1013
1006
  * One placeholder shape (`p:sp`) of a notes slide. A notes slide holds a fixed set:
1014
1007
  * the slide thumbnail (`type="sldImg"`), the notes body (`type="body"`), and the
@@ -1016,8 +1009,8 @@ var SlideLayout = class extends TemplatePart {
1016
1009
  * `a:xfrm` and are `null` when it inherits geometry from the notesMaster (the case
1017
1010
  * on an authored deck, whose `sldImg`/`sldNum` carry an empty `p:spPr`).
1018
1011
  *
1019
- * A notes placeholder IS a {@link Placeholder} — identity, geometry and the escape hatch are
1020
- * the same twelve members read off the same `p:sp`, down to `p:ph` being found the same way —
1012
+ * A notes placeholder IS a {@link Placeholder}. Identity, geometry and the escape hatch are
1013
+ * the same twelve members read off the same `p:sp`, down to `p:ph` being found the same way,
1021
1014
  * so it extends one rather than repeating it. Two things are its own: the flattened
1022
1015
  * {@link text} convenience, and a {@link textFrame} that threads the notesMaster inheritance
1023
1016
  * context onto the body frame.
@@ -1029,7 +1022,7 @@ var NotesPlaceholder = class extends Placeholder {
1029
1022
  * runs round-trip a slide's authored notes; the `sldNum` placeholder's frame
1030
1023
  * holds the slide-number `a:fld`, whose value surfaces through `TextFrame.text`.
1031
1024
  *
1032
- * Overrides {@link Placeholder.textFrame} for the inheritance context alone — see below.
1025
+ * Overrides {@link Placeholder.textFrame} for the inheritance context alone (see below).
1033
1026
  */
1034
1027
  get textFrame() {
1035
1028
  const txBody = firstChild(this.sp, "p:txBody");
@@ -1055,7 +1048,7 @@ var NotesPlaceholder = class extends Placeholder {
1055
1048
  }
1056
1049
  };
1057
1050
  /**
1058
- * A slide's speaker-notes slide (`notesSlideN.xml`) as a modeled object — the deep
1051
+ * A slide's speaker-notes slide (`notesSlideN.xml`) as a modeled object: the deep
1059
1052
  * companion to {@link Slide.notesText}. Exposes the notes
1060
1053
  * shape tree as {@link NotesPlaceholder}s ({@link body}/{@link slideImage}/
1061
1054
  * {@link slideNumber}) plus the body {@link textFrame} the older getters flatten.
@@ -1075,7 +1068,7 @@ var NotesSlide = class {
1075
1068
  get partName() {
1076
1069
  return this.part.partName;
1077
1070
  }
1078
- /** The notes part's own relationships — a notes hyperlink resolves through these. */
1071
+ /** The notes part's own relationships; a notes hyperlink resolves through these. */
1079
1072
  get relationships() {
1080
1073
  return this.opc.relationshipsFor(this.partName);
1081
1074
  }
@@ -1083,7 +1076,7 @@ var NotesSlide = class {
1083
1076
  * The notes shape tree as full shapes, in document order.
1084
1077
  *
1085
1078
  * A notes slide holds nothing but its three placeholders, so {@link placeholders} is the
1086
- * view to read. This one exists because a notes slide is a {@link ShapeHost} — which is
1079
+ * view to read. This one exists because a notes slide is a {@link ShapeHost}, which is
1087
1080
  * what lets a {@link NotesPlaceholder} be the same {@link AutoShape} view of its `p:sp`
1088
1081
  * that a master or layout placeholder is, rather than a second reading of one.
1089
1082
  */
@@ -1135,8 +1128,7 @@ var NotesSlide = class {
1135
1128
  return spTreeOf(this.part.dom.documentElement);
1136
1129
  }
1137
1130
  };
1138
- //#endregion
1139
- //#region src/read/api/ops/deck-target.ts
1131
+ // src/read/api/ops/deck-target.ts
1140
1132
  /**
1141
1133
  * `ppt/_rels/presentation.xml.rels` -- the deck's own relationship part.
1142
1134
  *
@@ -1151,8 +1143,7 @@ var NotesSlide = class {
1151
1143
  function presentationRels(dest) {
1152
1144
  return dest.opc.relationshipsFor(dest.presentationPart.partName);
1153
1145
  }
1154
- //#endregion
1155
- //#region src/read/api/ops/master-registry.ts
1146
+ // src/read/api/ops/master-registry.ts
1156
1147
  /**
1157
1148
  * Slide-master bookkeeping in `presentation.xml` and in a master's own
1158
1149
  * `p:sldLayoutIdLst`: registering a master so renderers treat it as active,
@@ -1189,7 +1180,7 @@ function registerMaster(dest, masterPartName) {
1189
1180
  /**
1190
1181
  * Move the `p:sldMasterId` entries for `masterPartNames` to the front of
1191
1182
  * `p:sldMasterIdLst`, preserving their existing relative order, so the first of
1192
- * them becomes the deck's `Designs(1)` — the theme PowerPoint's Design tab shows.
1183
+ * them becomes the deck's `Designs(1)`, the theme PowerPoint's Design tab shows.
1193
1184
  * Reorders the id list only; relationships, ids, and all other parts are left as
1194
1185
  * they are. A no-op when the named masters already lead (idempotent re-call).
1195
1186
  */
@@ -1219,7 +1210,7 @@ function promoteMasters(dest, masterPartNames) {
1219
1210
  * unique across the WHOLE presentation, not just within their own list. A duplicate
1220
1211
  * anywhere in this space makes PowerPoint report the file as corrupt on open
1221
1212
  * ("found a problem with content" / 0x80070570), even though LibreOffice silently
1222
- * tolerates it — so an imported master AND each of its layouts must take an id past
1213
+ * tolerates it. So an imported master AND each of its layouts must take an id past
1223
1214
  * the max of both the master-id list and every layout-id list. Recomputed per
1224
1215
  * allocation so ids appended earlier in the same import are counted.
1225
1216
  *
@@ -1275,20 +1266,19 @@ function addLayoutToMaster(dest, masterPartName, layoutPartName) {
1275
1266
  lst.appendChild(entry);
1276
1267
  masterPart.markDirty();
1277
1268
  }
1278
- //#endregion
1279
- //#region src/read/api/ops/copy-traversal.ts
1269
+ // src/read/api/ops/copy-traversal.ts
1280
1270
  /**
1281
1271
  * What a copy traversal does with one relationship: skip it, carry it as an external link, or
1282
1272
  * follow it into the part it names.
1283
1273
  *
1284
1274
  * Notes pull in a notesMaster and its own theme, which an imported page does not need, so the
1285
- * notes relationship is never followed — `carryNotes` picks it up afterwards for the pages
1275
+ * notes relationship is never followed; `carryNotes` picks it up afterwards for the pages
1286
1276
  * that asked. A master's relationships to its layouts are skipped so the copy stays lean:
1287
1277
  * copied layouts re-link themselves, and skipping the list is also what keeps one edited
1288
1278
  * layout from disqualifying every other layout that shares its master.
1289
1279
  *
1290
- * Each caller still owns its own extra arms — a copy's overrides and its jump-link rule, the reuse
1291
- * check's byte comparison — which is why this answers only the part they share.
1280
+ * Each caller still owns its own extra arms (a copy's overrides and its jump-link rule, the reuse
1281
+ * check's byte comparison), which is why this answers only the part they share.
1292
1282
  * @param part - the part the relationship belongs to
1293
1283
  * @param rel - the relationship being considered
1294
1284
  */
@@ -1297,13 +1287,12 @@ function copyTraversalStep(part, rel) {
1297
1287
  if (part.contentType === "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml" && rel.type === "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout") return "skip";
1298
1288
  return rel.targetMode === "External" ? "external" : "recurse";
1299
1289
  }
1300
- //#endregion
1301
- //#region src/read/api/ops/page-owned.ts
1290
+ // src/read/api/ops/page-owned.ts
1302
1291
  /**
1303
1292
  * What a page copy may share with the page it was copied from, and what it must own.
1304
1293
  *
1305
- * Duplicating a page — `cloneSlide`, `importSlide` of the same page twice,
1306
- * `importSlides` naming it twice — copies the page part and then has to decide,
1294
+ * Duplicating a page (`cloneSlide`, `importSlide` of the same page twice,
1295
+ * `importSlides` naming it twice) copies the page part and then has to decide,
1307
1296
  * for every part hanging off it, whether the copy points at the same part or gets
1308
1297
  * one of its own. Sharing is the cheap answer and is right for most of the graph:
1309
1298
  * a layout, a master, a theme, an image are deck-wide assets PowerPoint itself
@@ -1312,7 +1301,7 @@ function copyTraversalStep(part, rel) {
1312
1301
  * It is not right for the parts a page *owns*. A chart and its embedded workbook,
1313
1302
  * a SmartArt diagram's five parts, an OLE embedding, a notes slide: PowerPoint
1314
1303
  * treats each as belonging to exactly one page, and a package where two slides
1315
- * resolve to one of them is one it refuses to open at all — the "the file or
1304
+ * resolve to one of them is one it refuses to open at all: the "the file or
1316
1305
  * directory is corrupted and unreadable" (`0x80070570`) dialog, with the whole
1317
1306
  * deck rejected rather than the duplicate page. The schema validator accepts such
1318
1307
  * a package: nothing in ECMA-376 says a chart part has one referrer, so this rule
@@ -1342,14 +1331,13 @@ function copyTraversalStep(part, rel) {
1342
1331
  const SHARED_BY_PAGE_COPIES = new Set(SHARED_PARTS.map((kind) => kind.relType));
1343
1332
  /**
1344
1333
  * Whether a page copy may point at this relationship's target rather than taking
1345
- * a copy of it. Everything not listed is owned by the page and copied — see the
1334
+ * a copy of it. Everything not listed is owned by the page and copied; see the
1346
1335
  * module comment for why that is the safe default.
1347
1336
  */
1348
1337
  function isSharedByPageCopies(relType) {
1349
1338
  return SHARED_BY_PAGE_COPIES.has(relType);
1350
1339
  }
1351
- //#endregion
1352
- //#region src/read/api/ops/part-reuse.ts
1340
+ // src/read/api/ops/part-reuse.ts
1353
1341
  /**
1354
1342
  * Whether the destination already holds `sourcePartName`'s subgraph, part for part and
1355
1343
  * byte for byte, in a state an imported slide can bind to.
@@ -1430,8 +1418,7 @@ function bytesEqual(a, b) {
1430
1418
  for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
1431
1419
  return true;
1432
1420
  }
1433
- //#endregion
1434
- //#region src/read/api/ops/part-copy.ts
1421
+ // src/read/api/ops/part-copy.ts
1435
1422
  /** Open an ownership scope for one page copy. */
1436
1423
  function newOwnedScope() {
1437
1424
  return /* @__PURE__ */ new Map();
@@ -1445,7 +1432,7 @@ function copyTarget(ctx) {
1445
1432
  * it would throw, found before anything in the destination moves.
1446
1433
  *
1447
1434
  * This is what lets a refused import leave the deck byte-identical. The copy changes the deck as it
1448
- * goes — parts added, a master registered in `presentation.xml`, a layout linked into its master —
1435
+ * goes (parts added, a master registered in `presentation.xml`, a layout linked into its master),
1449
1436
  * so a failure it met halfway would leave all of that behind. An import therefore runs the same
1450
1437
  * traversal twice: first with a plan in its context, which throws what the copy would and writes
1451
1438
  * nothing, then for real. The dry run used to be a separate walk of the source, transcribed from the
@@ -1456,8 +1443,8 @@ function copyTarget(ctx) {
1456
1443
  * A plan stands in for the destination package as a {@link CopyTarget}. It hands out the partnames
1457
1444
  * the copy will be given, keeps its own copy of each source's registry so a part it planned is found
1458
1445
  * again as the copy would find it, and remembers the notes master it would install in a deck that has
1459
- * none. Destination bookkeeping that adds no part — registering a master, linking a layout into it —
1460
- * is not recorded.
1446
+ * none. Destination bookkeeping that adds no part, such as registering a master or linking a layout
1447
+ * into it, is not recorded.
1461
1448
  */
1462
1449
  var CopyPlan = class {
1463
1450
  api;
@@ -1551,7 +1538,7 @@ var CopyPlan = class {
1551
1538
  * registry idempotence is right for a theme, master, layout or image, where a
1552
1539
  * second copy is waste; applied to the slide it made a repeated import of the
1553
1540
  * same source page return the first copy's partname, and the caller then wired a
1554
- * second `p:sldId` to a part that already had one — a package PowerPoint refuses
1541
+ * second `p:sldId` to a part that already had one: a package PowerPoint refuses
1555
1542
  * to open (0x80070570), with nothing in the read model to show for it. So the
1556
1543
  * page goes into the selection plan `copyPart` already honours for a batch, which
1557
1544
  * re-materializes exactly the named pages and leaves the dedup of their
@@ -1574,7 +1561,7 @@ function copySlidePart(ctx, sourcePartName) {
1574
1561
  * per source package via the copy registry. Relationship ids are preserved so
1575
1562
  * the copied part body's `r:id`/`r:embed` references stay valid; targets are
1576
1563
  * rewritten to the freshly-allocated partnames. Notes relationships are
1577
- * dropped. A copied `slideMaster` does not drag in all its sibling layouts —
1564
+ * dropped. A copied `slideMaster` does not drag in all its sibling layouts;
1578
1565
  * each imported `slideLayout` wires itself into the master instead (see
1579
1566
  * {@link linkLayoutIntoMaster}).
1580
1567
  *
@@ -1584,13 +1571,13 @@ function copySlidePart(ctx, sourcePartName) {
1584
1571
  * a `slide → slide` link may not leave the selection is enforced as each link is
1585
1572
  * followed (see {@link rebuildRels}). Imports run this traversal as a
1586
1573
  * {@link CopyPlan} first, which throws that and every other failure the copy
1587
- * could meet — so once copying starts there is nothing left to throw, and a
1574
+ * could meet, so once copying starts there is nothing left to throw, and a
1588
1575
  * rejected batch never leaves a half-copied deck behind.
1589
1576
  *
1590
1577
  * Idempotence stops at the page's own parts. Reaching a page opens an
1591
1578
  * {@link OwnedScope}, and everything under it that {@link isSharedByPageCopies}
1592
- * does not clear for sharing — a chart, a diagram, an OLE embedding, each with
1593
- * its own subtree — is copied into that scope instead of the registry, so the
1579
+ * does not clear for sharing (a chart, a diagram, an OLE embedding, each with
1580
+ * its own subtree) is copied into that scope instead of the registry, so the
1594
1581
  * next copy of the page gets parts of its own. Pass `owned` to open the scope
1595
1582
  * from outside, as the rebinding import paths do for the page they build
1596
1583
  * themselves.
@@ -1698,7 +1685,7 @@ function rebuildRels(ctx, options) {
1698
1685
  * The page's shared targets are carried as the source wrote them. Each owned one is repointed at a
1699
1686
  * fresh copy, and the subtree under it is copied the same way, so a chart's workbook and
1700
1687
  * user-shapes drawing come along while the image inside that drawing stays shared. A relationship
1701
- * *back* to the source page — a notes slide names the slide it annotates — is repointed at the
1688
+ * *back* to the source page (a notes slide names the slide it annotates) is repointed at the
1702
1689
  * clone, which is what makes the copied notes belong to it.
1703
1690
  *
1704
1691
  * Unlike an import, a clone keeps its page's notes, and nothing here consults the copy registry or
@@ -1773,19 +1760,18 @@ function linkLayoutIntoMaster(ctx, layoutSourceRels, layoutPartName) {
1773
1760
  if (!masterPartName) return;
1774
1761
  addLayoutToMaster(ctx.dest, masterPartName, layoutPartName);
1775
1762
  }
1776
- //#endregion
1777
- //#region src/read/api/ops/notes-master.ts
1763
+ // src/read/api/ops/notes-master.ts
1778
1764
  /**
1779
1765
  * Carrying speaker notes and the deck's single notes master across an import or an append.
1780
1766
  *
1781
1767
  * A `notesSlide` is not self-contained: it back-references the slide it annotates and forward-
1782
1768
  * references the deck's notes master. `CT_NotesMasterIdList` allows at most one master per
1783
- * presentation, so a deck that already has one keeps it — the destination's notes styling wins —
1769
+ * presentation, so a deck that already has one keeps it (the destination's notes styling wins),
1784
1770
  * and a source master is copied only into a deck that has none. That single rule is why both the
1785
1771
  * `Presentation`-to-`Presentation` path and the generator-XML path funnel through
1786
1772
  * `registerNotesMaster`: they differ only in how the *part* comes into being.
1787
1773
  */
1788
- const textEncoder$2 = new TextEncoder();
1774
+ const textEncoder$3 = new TextEncoder();
1789
1775
  /**
1790
1776
  * Carry the source slide's speaker notes onto the just-imported slide (the
1791
1777
  * `importNotes` option). The slide copy itself dropped the `notesSlide` rel, so
@@ -1793,7 +1779,7 @@ const textEncoder$2 = new TextEncoder();
1793
1779
  * `slide → notesSlide` rel on the new slide, and rebuilds the copied notesSlide's
1794
1780
  * own relationships:
1795
1781
  *
1796
- * - its `slide` back-rel is repointed at the new slide (`newSlidePartName`) — the
1782
+ * - its `slide` back-rel is repointed at the new slide (`newSlidePartName`); the
1797
1783
  * source slide is *not* copied (that would be circular);
1798
1784
  * - its `notesMaster` rel is resolved through {@link ensureNotesMaster}, which
1799
1785
  * reuses this deck's notesMaster when it has one and copies the source's only
@@ -1842,7 +1828,7 @@ function carryNotes(dest, source, ctx, sourceSlidePartName, newSlidePartName) {
1842
1828
  */
1843
1829
  function addNotesSlidePart(dest, xml, slidePartName, notesMasterPartName) {
1844
1830
  const notesPartName = dest.opc.reservePartNameLike("/ppt/notesSlides/notesSlide1.xml");
1845
- dest.opc.addPart(notesPartName, NOTES_SLIDE_CONTENT_TYPE, textEncoder$2.encode(xml));
1831
+ dest.opc.addPart(notesPartName, NOTES_SLIDE_CONTENT_TYPE, textEncoder$3.encode(xml));
1846
1832
  const notesRels = dest.opc.relationshipsFor(notesPartName);
1847
1833
  if (notesMasterPartName) notesRels.addWithId("rId1", NOTES_MASTER_REL, relativePartName(notesPartName, notesMasterPartName));
1848
1834
  notesRels.addWithId("rId2", SLIDE_REL, relativePartName(notesPartName, slidePartName));
@@ -1880,8 +1866,8 @@ function presentationRoot(dest) {
1880
1866
  * allows. Returns the partname, so callers can use it as a rel target.
1881
1867
  *
1882
1868
  * Split out of {@link ensureNotesMaster} because the two ways a notesMaster arrives
1883
- * — copied from another `Presentation`, or authored by a generator and injected by
1884
- * {@link Presentation.appendSlides} — differ only in how the *part* is created, not in how it is
1869
+ * (copied from another `Presentation`, or authored by a generator and injected by
1870
+ * {@link Presentation.appendSlides}) differ only in how the *part* is created, not in how it is
1885
1871
  * registered.
1886
1872
  */
1887
1873
  function registerNotesMaster(dest, notesMasterPartName) {
@@ -1925,7 +1911,7 @@ function installNotesMaster(dest, masterBytes, themeBytes, themeContentType = TH
1925
1911
  * theme its `.rels` requires (the normal write path emits that as `theme2.xml`).
1926
1912
  */
1927
1913
  function ensureNotesMasterFromXml(dest, master) {
1928
- return existingNotesMaster(dest) ?? installNotesMaster(dest, textEncoder$2.encode(master.xml), textEncoder$2.encode(master.themeXml));
1914
+ return existingNotesMaster(dest) ?? installNotesMaster(dest, textEncoder$3.encode(master.xml), textEncoder$3.encode(master.themeXml));
1929
1915
  }
1930
1916
  /**
1931
1917
  * Resolve the notesMaster a *newly authored* notes slide should bind to
@@ -1945,7 +1931,7 @@ function ensureNotesMasterFromXml(dest, master) {
1945
1931
  * arrangement PowerPoint writes (`theme1.xml` for the master, `theme2.xml` for the
1946
1932
  * notes master).
1947
1933
  *
1948
- * Throws when the deck has no theme to clone — a package that malformed cannot be
1934
+ * Throws when the deck has no theme to clone: a package that malformed cannot be
1949
1935
  * given a valid notesMaster, and silently emitting one without a resolvable theme
1950
1936
  * is what PowerPoint reports as a repair prompt rather than a bad edit.
1951
1937
  * @param {Presentation} dest - the deck being authored onto
@@ -1958,10 +1944,9 @@ function ensureNotesMasterForAuthoring(dest, slidePartName) {
1958
1944
  const themePartName = resolveSlideThemeParts(dest.opc, slidePartName).themePartName;
1959
1945
  const themePart = themePartName ? dest.opc.part(themePartName) : void 0;
1960
1946
  if (!themePart) throw new PackageReadError("package/part-missing", `addNotes: no theme reachable from ${slidePartName} to bind a new notes master to`);
1961
- return installNotesMaster(dest, textEncoder$2.encode(makeXmlNotesMaster()), themePart.serialize(), themePart.contentType);
1947
+ return installNotesMaster(dest, textEncoder$3.encode(makeXmlNotesMaster()), themePart.serialize(), themePart.contentType);
1962
1948
  }
1963
- //#endregion
1964
- //#region src/read/api/ops/notes-author.ts
1949
+ // src/read/api/ops/notes-author.ts
1965
1950
  /**
1966
1951
  * Authoring speaker notes onto a slide of a *loaded* deck ({@link Slide.addNotes}).
1967
1952
  *
@@ -1974,7 +1959,7 @@ function ensureNotesMasterForAuthoring(dest, slidePartName) {
1974
1959
  * placeholder frame comes from {@link makeXmlNotesSlideSkeleton}, and the body
1975
1960
  * paragraphs carry the same elements and attributes the write path emits for a plain
1976
1961
  * `pptx.addSlide().addNotes(text)`. `test/read/add-notes.test.ts` asserts that
1977
- * equivalence, so the two cannot drift apart unnoticed — the same guarantee
1962
+ * equivalence, so the two cannot drift apart unnoticed: the same guarantee
1978
1963
  * `src/ooxml/` gives the constants both halves share.
1979
1964
  *
1980
1965
  * The one difference is empty-element *spelling*: the write path emits `a:rPr` as an
@@ -2009,7 +1994,7 @@ function notesParagraphsXml(text) {
2009
1994
  /**
2010
1995
  * Replace a notes body's paragraphs with `text`, in the body's own document.
2011
1996
  *
2012
- * The path taken when the slide *already* has a notes part — an imported one, or one
1997
+ * The path taken when the slide *already* has a notes part: an imported one, or one
2013
1998
  * an earlier `addNotes` wrote. Only the `a:p` children are replaced, so the part's
2014
1999
  * geometry, its `a:bodyPr`/`a:lstStyle`, and its other two placeholders survive. The
2015
2000
  * body's hyperlink relationships are deliberately *not* pruned: a caller replacing
@@ -2051,7 +2036,7 @@ function notesBodyTxBody(root) {
2051
2036
  * When the slide already has a notes part, only the body paragraphs are rewritten
2052
2037
  * (see {@link replaceNotesParagraphs}). When it has none, the part is built and
2053
2038
  * wired: `slide → notesSlide`, and on the new part the two relationships a notes
2054
- * slide always carries — `notesMaster` as rId1 and a `slide` back-reference as rId2,
2039
+ * slide always carries: `notesMaster` as rId1 and a `slide` back-reference as rId2,
2055
2040
  * the ids and order the write path reserves.
2056
2041
  *
2057
2042
  * The notes master is resolved through {@link ensureNotesMasterForAuthoring}: this
@@ -2081,8 +2066,7 @@ function authorNotes(slide, text) {
2081
2066
  slide.relationships.add(NOTES_SLIDE_REL, relativePartName(slide.partName, partName));
2082
2067
  return partName;
2083
2068
  }
2084
- //#endregion
2085
- //#region src/read/api/comments.ts
2069
+ // src/read/api/comments.ts
2086
2070
  /** The slide → modern-comments-part relationship type (2018 schema). Only this module reads one. */
2087
2071
  const MODERN_COMMENTS_REL_TYPE = MS_REL + "2018/10/relationships/comments";
2088
2072
  /** Content type of the modern per-slide comments part (`ppt/comments/modernComment_*.xml`). */
@@ -2203,8 +2187,7 @@ function commentSchema(opc) {
2203
2187
  if (opc.partsByContentType("application/vnd.openxmlformats-officedocument.presentationml.comments+xml").length > 0) return "legacy";
2204
2188
  return "none";
2205
2189
  }
2206
- //#endregion
2207
- //#region src/read/api/tags.ts
2190
+ // src/read/api/tags.ts
2208
2191
  /** The owner → tags-part relationship type. Only this module follows one. */
2209
2192
  const TAGS_REL_TYPE = OFFICE_REL + "tags";
2210
2193
  /**
@@ -2227,8 +2210,7 @@ function readTagsForPart(opc, ownerPartName) {
2227
2210
  }
2228
2211
  return out;
2229
2212
  }
2230
- //#endregion
2231
- //#region src/read/api/transition.ts
2213
+ // src/read/api/transition.ts
2232
2214
  /**
2233
2215
  * Typed read/edit model for a slide's `p:transition` (slide-show transition).
2234
2216
  *
@@ -2239,7 +2221,7 @@ function readTagsForPart(opc, ownerPartName) {
2239
2221
  * when the duration matches a coarse `spd` speed bucket; and
2240
2222
  * - **wrapped** `<mc:AlternateContent>` carrying a `<mc:Choice Requires="p14">`
2241
2223
  * whose `p:transition` adds the precise `p14:dur` (milliseconds), plus a base
2242
- * `<mc:Fallback>` without it — emitted for an off-bucket exact duration.
2224
+ * `<mc:Fallback>` without it. This form is emitted for an off-bucket exact duration.
2243
2225
  *
2244
2226
  * The getter prefers the `p14` Choice (so `durationMs` is recovered); the setter
2245
2227
  * emits the `mc:AlternateContent` form when `durationMs` is set and the bare form
@@ -2254,7 +2236,6 @@ function typeElement(transition) {
2254
2236
  }
2255
2237
  /** Namespace prefix for a URI, defaulting to `p` for the base presentationml namespace. */
2256
2238
  function prefixFor(uri) {
2257
- if (!uri) return "p";
2258
2239
  for (const [prefix, ns] of Object.entries(OOXML_NS)) if (ns === uri) return prefix;
2259
2240
  return "p";
2260
2241
  }
@@ -2417,8 +2398,7 @@ function removeTransition(root) {
2417
2398
  const found = findTransition(root);
2418
2399
  if (found) root.removeChild(found.outer);
2419
2400
  }
2420
- //#endregion
2421
- //#region src/read/api/slide-build.ts
2401
+ // src/read/api/slide-build.ts
2422
2402
  /**
2423
2403
  * Create `qname` in the parent's document and append it.
2424
2404
  *
@@ -2488,8 +2468,7 @@ function buildPicture(doc, spec) {
2488
2468
  appendSpPr(pic, spec);
2489
2469
  return pic;
2490
2470
  }
2491
- //#endregion
2492
- //#region src/read/api/slide.ts
2471
+ // src/read/api/slide.ts
2493
2472
  /** Recognize a common raster format from its leading bytes, through the shared registry. */
2494
2473
  function sniffImageType(bytes) {
2495
2474
  const format = imageFormatForBytes(bytes);
@@ -2546,8 +2525,8 @@ var Slide = class {
2546
2525
  * `fmtScheme` + `fontScheme`, plus the layout/master roots), walked once from
2547
2526
  * slide → layout → master → theme and cached on this proxy. Backs the read-model
2548
2527
  * resolved getters ({@link Shape.resolvedFill}, `Run.resolvedColor`,
2549
- * `Run.resolvedSizePt`, `Run.resolvedFontFace`) so a `schemeClr` token — including
2550
- * one delivered through a shape's `p:style` `fillRef`/`lnRef` — resolves to a
2528
+ * `Run.resolvedSizePt`, `Run.resolvedFontFace`) so a `schemeClr` token (including
2529
+ * one delivered through a shape's `p:style` `fillRef`/`lnRef`) resolves to a
2551
2530
  * literal hex, and a placeholder run's inherited size/typeface (a `+mj-*`/`+mn-*`
2552
2531
  * font token included) resolves to a literal value. The maps/roots are empty when
2553
2532
  * the theme chain is incomplete, in which case tokens simply stay unresolved.
@@ -2597,7 +2576,7 @@ var Slide = class {
2597
2576
  /**
2598
2577
  * Whether this slide draws the master's non-placeholder shapes
2599
2578
  * (`p:sld/@showMasterSp`). `xsd:boolean` defaulting to `true`, so an absent
2600
- * attribute means shown — the same shape as {@link hidden}.
2579
+ * attribute means shown, the same shape as {@link hidden}.
2601
2580
  *
2602
2581
  * This is the switch that decides whether {@link SlideMaster.shapes} belongs on
2603
2582
  * *this* slide. A slide the author gave a full-bleed image or a section divider
@@ -2624,7 +2603,7 @@ var Slide = class {
2624
2603
  * Set or clear the slide's show transition. Assigning `null` removes it.
2625
2604
  * Writing a transition with `durationMs` emits the `mc:AlternateContent` form
2626
2605
  * (a `p14` Choice carrying `p14:dur` plus a base `mc:Fallback`); otherwise the
2627
- * bare `<p:transition>` is written. The node is inserted at its schema slot —
2606
+ * bare `<p:transition>` is written. The node is inserted at its schema slot,
2628
2607
  * after `p:clrMapOvr`, before `p:timing`/`p:extLst`. Marks the slide part dirty.
2629
2608
  *
2630
2609
  * The new transition is built from the current one before that is removed: it keeps the sound
@@ -2650,6 +2629,15 @@ var Slide = class {
2650
2629
  return root ? hasAnimations(root) : false;
2651
2630
  }
2652
2631
  /**
2632
+ * The slide's build effects: every time node in its `p:timing` with a `presetClass`, in document
2633
+ * order, with the sequence it plays in, its preset, trigger, duration, step delay and target shape
2634
+ * id. `[]` when the slide has no timing. Read-only: see {@link BuildEffect}.
2635
+ */
2636
+ get animations() {
2637
+ const root = this.part.dom.documentElement;
2638
+ return root ? readBuildEffects(root) : [];
2639
+ }
2640
+ /**
2653
2641
  * @internal The sorted, de-duplicated set of shape ids (`spid`) referenced by
2654
2642
  * the slide's animations (`<p:spTgt spid>` and `<p:bldP spid>`). Exposed for the
2655
2643
  * import paths' spid-coherence checks.
@@ -2679,14 +2667,14 @@ var Slide = class {
2679
2667
  /**
2680
2668
  * Flatten the slide's build animations: remove the `<p:timing>` block so the
2681
2669
  * slide renders and edits as its final static state, with every shape shown at
2682
- * once. Gated like {@link hasAnimations} — a `<p:timing>` that is purely a media
2670
+ * once. Gated like {@link hasAnimations}: a `<p:timing>` that is purely a media
2683
2671
  * loop (no `<p:bldP>` or `presetID`) is preserved so media playback survives.
2684
2672
  * Marks the slide part dirty and returns `true` only when a timing block was
2685
2673
  * removed.
2686
2674
  *
2687
2675
  * This removes click-through staging only; it does not delete shapes. If a slide
2688
2676
  * animated alternating states over the same region, the flattened render shows
2689
- * them all at once — keep that distinct from removing staged/duplicate shapes.
2677
+ * them all at once. Keep that distinct from removing staged/duplicate shapes.
2690
2678
  */
2691
2679
  flattenAnimations() {
2692
2680
  const root = this.part.dom.documentElement;
@@ -2702,7 +2690,7 @@ var Slide = class {
2702
2690
  return spTree ? buildShapes(spTree, this) : [];
2703
2691
  }
2704
2692
  /**
2705
- * All text on the slide, flattened in document order — the read-model
2693
+ * All text on the slide, flattened in document order: the read-model
2706
2694
  * counterpart to {@link TextFrame.text} one level up. Every text-bearing shape
2707
2695
  * contributes its text, recursing into groups ({@link GroupShape}) and reading
2708
2696
  * table cells ({@link GraphicFrame.table}) and SmartArt node text
@@ -2745,12 +2733,12 @@ var Slide = class {
2745
2733
  return blocks.join("\n");
2746
2734
  }
2747
2735
  /**
2748
- * The slide's speaker-note text — the companion to {@link text} for the notes
2736
+ * The slide's speaker-note text, the companion to {@link text} for the notes
2749
2737
  * that {@link text} deliberately excludes. Delegates to {@link notesSlide}: finds
2750
2738
  * the notes body placeholder (`p:ph` `type="body"`) and flattens its text frame
2751
2739
  * the same way {@link TextFrame.text} does (paragraphs joined by `\n`).
2752
2740
  *
2753
- * Returns `null` when the slide has **no notes slide part at all** — distinct
2741
+ * Returns `null` when the slide has **no notes slide part at all**, distinct
2754
2742
  * from `''`, which means a notes slide exists but its body is empty (PowerPoint
2755
2743
  * often attaches an empty notes slide to every slide). Only the body placeholder
2756
2744
  * is read; the slide-thumbnail (`sldImg`) and slide-number (`sldNum`)
@@ -2761,14 +2749,14 @@ var Slide = class {
2761
2749
  return notes ? notes.text : null;
2762
2750
  }
2763
2751
  /**
2764
- * The slide's speaker-note body as a navigable {@link TextFrame} — the rich
2752
+ * The slide's speaker-note body as a navigable {@link TextFrame}: the rich
2765
2753
  * companion to {@link notesText}, which flattens the same body to a plain string.
2766
2754
  * Walk `paragraphs → runs` to recover per-run formatting (bold/italic/underline,
2767
2755
  * colour, size, face) and any notes hyperlink that {@link notesText} discards.
2768
2756
  *
2769
2757
  * `null` when the slide has **no notes slide part** (the same boundary
2770
2758
  * {@link notesText} returns `null` at), and also when a notes part exists but
2771
- * carries no body-placeholder text frame — there is then no frame to hand back
2759
+ * carries no body-placeholder text frame; there is then no frame to hand back
2772
2760
  * (whereas {@link notesText} reports `''` for that empty-body case). Convenience
2773
2761
  * for `notesSlide.textFrame`; see {@link notesSlide} for the whole modeled notes
2774
2762
  * slide (its `sldImg`/`sldNum` placeholders and their geometry).
@@ -2780,9 +2768,9 @@ var Slide = class {
2780
2768
  * The slide's speaker-notes slide (`notesSlideN.xml`) as a modeled
2781
2769
  * {@link NotesSlide}, or `null` when the slide has no notes slide part. Beyond the
2782
2770
  * body text {@link notesText}/{@link notesTextFrame} surface, this exposes the
2783
- * notes slide's three placeholders — the slide thumbnail (`slideImage`), the notes
2784
- * body, and the slide-number field (`slideNumber`) — each with its geometry and
2785
- * (where present) a navigable text frame.
2771
+ * notes slide's three placeholders, each with its geometry and (where present) a
2772
+ * navigable text frame: the slide thumbnail (`slideImage`), the notes body, and the
2773
+ * slide-number field (`slideNumber`).
2786
2774
  *
2787
2775
  * The writer authors all three placeholders but leaves `sldImg`/`sldNum` with an
2788
2776
  * empty `p:spPr`, so on an authored deck their geometry reads `null` while an
@@ -2838,7 +2826,7 @@ var Slide = class {
2838
2826
  * carries its body text, `created` timestamp, marker position (EMU), its author
2839
2827
  * resolved through the deck-wide {@link Presentation.modernCommentAuthors}
2840
2828
  * registry (`@authorId` GUID → name/initials), and its reply thread nested under
2841
- * `replies`. Read-only — the writer authors the legacy schema; see
2829
+ * `replies`. Read-only: the writer authors the legacy schema; see
2842
2830
  * {@link Presentation.commentSchema} to tell which schema a deck uses.
2843
2831
  */
2844
2832
  get modernComments() {
@@ -2847,7 +2835,7 @@ var Slide = class {
2847
2835
  /**
2848
2836
  * The slide's programmatic tags (`p:custDataLst/p:tags` on the slide part,
2849
2837
  * resolved to `ppt/tags/tagN.xml`) as `{ name, val }` string pairs, `[]` when it
2850
- * has none. Host/add-in metadata with no visible rendering and no writer —
2838
+ * has none. Host/add-in metadata with no visible rendering and no writer:
2851
2839
  * read-only, preserved byte-for-byte on round-trip. Deck-level tags are
2852
2840
  * {@link Presentation.tags}.
2853
2841
  */
@@ -2857,7 +2845,7 @@ var Slide = class {
2857
2845
  /**
2858
2846
  * The slide's effective background (`p:cSld/p:bg`), decoded into a typed
2859
2847
  * {@link SlideBackground}. Resolved through the inheritance chain: the slide's
2860
- * own `p:bg` wins; failing that the slideLayout's, then the slideMaster's — the
2848
+ * own `p:bg` wins; failing that the slideLayout's, then the slideMaster's. The
2861
2849
  * result's `source` records which supplied it. `null` when nothing in the chain
2862
2850
  * defines a background.
2863
2851
  *
@@ -2903,7 +2891,7 @@ var Slide = class {
2903
2891
  * `slide.slideNumber`, or added to a master defined with `slideNumber`; its geometry and run formatting
2904
2892
  * read off the returned {@link AutoShape} the same as any placeholder.
2905
2893
  *
2906
- * Scoped to the slide's *own* shape tree — a slide number inherited purely from
2894
+ * Scoped to the slide's *own* shape tree: a slide number inherited purely from
2907
2895
  * the master's `p:hf`/placeholder (with no shape on the slide) is a master-level
2908
2896
  * concern this getter does not resolve.
2909
2897
  */
@@ -2920,7 +2908,7 @@ var Slide = class {
2920
2908
  }
2921
2909
  /**
2922
2910
  * The first shape *anywhere* in the slide's shape tree with the given drawing id
2923
- * (`p:cNvPr/@id`), descending into groups — unlike {@link shapeById}, which scans
2911
+ * (`p:cNvPr/@id`), descending into groups, unlike {@link shapeById}, which scans
2924
2912
  * only top-level shapes. Walked pre-order (a group is visited before its children),
2925
2913
  * matching how the writer allocates ids. `undefined` when no shape carries that id.
2926
2914
  *
@@ -2939,8 +2927,9 @@ var Slide = class {
2939
2927
  /**
2940
2928
  * The first placeholder of the given type (`p:ph/@type`, e.g. `title`,
2941
2929
  * `ctrTitle`, `subTitle`, `body`), optionally narrowed by `idx`. Returns
2942
- * `undefined` when none match. Only `p:sp` shapes can be placeholders, so the
2943
- * result is an {@link AutoShape}.
2930
+ * `undefined` when none match. Only {@link AutoShape}s are searched: a filled
2931
+ * picture, table or chart placeholder is not found here, though its own
2932
+ * `placeholder` getter still reads it.
2944
2933
  */
2945
2934
  placeholder(type, idx) {
2946
2935
  return this.shapes.find((shape) => {
@@ -3020,7 +3009,7 @@ var Slide = class {
3020
3009
  * afterwards through {@link notesTextFrame}.
3021
3010
  *
3022
3011
  * The counterpart to the read side's `notesText`/`notesTextFrame`/`notesSlide`
3023
- * getters, and the way to annotate a slide that has **no notes part at all** —
3012
+ * getters, and the way to annotate a slide that has **no notes part at all**:
3024
3013
  * the state an `importSlide` without `{ importNotes: true }` leaves behind, and
3025
3014
  * the one a `notesTextFrame` edit cannot reach because there is no frame to
3026
3015
  * hand back. Calling it on a slide that already has notes replaces the body
@@ -3075,8 +3064,7 @@ var Slide = class {
3075
3064
  return spTreeOf(this.part.dom.documentElement);
3076
3065
  }
3077
3066
  };
3078
- //#endregion
3079
- //#region src/read/api/document-properties.ts
3067
+ // src/read/api/document-properties.ts
3080
3068
  /** `dc:title`-style core-property fields, keyed by output field → element qname. */
3081
3069
  const CORE_FIELDS = [
3082
3070
  ["title", "dc:title"],
@@ -3146,7 +3134,7 @@ function readExtendedProperties(opc) {
3146
3134
  * number; real types (`r4`/`r8`/`decimal`) → number; `bool` → boolean;
3147
3135
  * `filetime`/`date` → the **raw string** (see {@link CoreProperties} on
3148
3136
  * timestamps). Any unrecognized `vt:` element falls back to its text content as a
3149
- * string — lossy but never throws.
3137
+ * string, which is lossy but never throws.
3150
3138
  */
3151
3139
  function decodeValue(vt) {
3152
3140
  const text = vt.textContent ?? "";
@@ -3203,13 +3191,12 @@ function readCustomProperties(opc) {
3203
3191
  }
3204
3192
  return out;
3205
3193
  }
3206
- //#endregion
3207
- //#region src/read/api/ops/embedded-fonts.ts
3194
+ // src/read/api/ops/embedded-fonts.ts
3208
3195
  /**
3209
3196
  * Merging embedded font faces into a deck's `p:embeddedFontLst`.
3210
3197
  *
3211
- * Fonts arrive two ways — copied out of another `Presentation`, or handed over as raw bytes by a
3212
- * generator during an append — and the two differ only in how the binary part comes into being.
3198
+ * Fonts arrive two ways (copied out of another `Presentation`, or handed over as raw bytes by a
3199
+ * generator during an append), and the two differ only in how the binary part comes into being.
3213
3200
  * That difference is confined to a per-face thunk, so both paths share one merge core: entries
3214
3201
  * join by typeface, faces de-dupe by slot, and the thunk runs only for a face actually being
3215
3202
  * added, so a face the deck already embeds never mints an orphan part.
@@ -3271,7 +3258,7 @@ function readEmbeddedFontEntries(deck) {
3271
3258
  * every face this deck would copy names a part that is actually there.
3272
3259
  *
3273
3260
  * Every import that carries fonts calls it before it changes anything, because the carry runs
3274
- * last — after the page or the masters are already in the deck — and a face it cannot copy would
3261
+ * last (after the page or the masters are already in the deck), and a face it cannot copy would
3275
3262
  * throw with parts added and no way back. A face whose `r:id` names no relationship and a face
3276
3263
  * whose relationship names no part are the same failure to a caller, the face's binary is not in
3277
3264
  * the package, so both are `package/part-missing`.
@@ -3354,7 +3341,7 @@ function carryGeneratedEmbeddedFonts(dest, fonts) {
3354
3341
  }
3355
3342
  /**
3356
3343
  * Merge normalized {@link IncomingEmbeddedFont} entries into this deck's
3357
- * `p:embeddedFontLst` — the shared core of {@link carryEmbeddedFonts} (import-side)
3344
+ * `p:embeddedFontLst`: the shared core of {@link carryEmbeddedFonts} (import-side)
3358
3345
  * and {@link carryGeneratedEmbeddedFonts} (append-side). Entries merge by `typeface`,
3359
3346
  * faces de-dupe by slot (a face this deck already embeds is left as is). For each newly
3360
3347
  * added face the `fntdata` Default is ensured, the binary part is created via the face's
@@ -3404,8 +3391,126 @@ function mergeEmbeddedFontEntries(dest, entries) {
3404
3391
  presPart.markDirty();
3405
3392
  }
3406
3393
  }
3407
- //#endregion
3408
- //#region src/read/api/ops/slide-size.ts
3394
+ // src/read/api/ops/comments.ts
3395
+ /**
3396
+ * Carrying legacy review comments onto a deck: a comments part per slide, and the deck-wide
3397
+ * author registry (`ppt/commentAuthors.xml`) every comment names its author in by `@authorId`.
3398
+ * `appendSlides` builds the comments part from a generator's comments; `importSlide` and
3399
+ * `importSlides` copy the source's part with the page and then renumber it here.
3400
+ *
3401
+ * The registry is the part that makes this more than a copy. The destination may already have
3402
+ * one, with its own ids and its own per-author numbering, so an incoming comment's author is
3403
+ * looked up there by name and initials (the key the writer resolves authors by) and its `idx`
3404
+ * continues that author's `lastIdx`. An author the destination does not have is added under the
3405
+ * next free id.
3406
+ */
3407
+ const textEncoder$2 = new TextEncoder();
3408
+ /** The deck's comment-author registry part, created and related from the presentation when it has none. */
3409
+ function commentAuthorsPart(dest) {
3410
+ const existing = singleRelPart(dest.opc, dest.presentationPart.partName, COMMENT_AUTHORS_REL);
3411
+ if (existing) return existing;
3412
+ const partName = dest.opc.reservePartNameLike("/ppt/commentAuthors.xml");
3413
+ const part = dest.opc.addPart(partName, COMMENT_AUTHORS_CONTENT_TYPE, textEncoder$2.encode(makeXmlCommentAuthors([])));
3414
+ presentationRels(dest).add(COMMENT_AUTHORS_REL, relativePartName(dest.presentationPart.partName, partName));
3415
+ return part;
3416
+ }
3417
+ /**
3418
+ * The deck's author registry, open for registering authors: each call to `register` finds or adds
3419
+ * the author by name and initials, takes that author's next `idx`, and marks the part dirty.
3420
+ */
3421
+ function authorRegistry(dest) {
3422
+ const part = commentAuthorsPart(dest);
3423
+ const root = part.dom.documentElement;
3424
+ if (!root) throw new PackageReadError("package/part-has-no-root", `${part.partName} has no document element to register comment authors in`);
3425
+ const authors = getElements(root, "p:cmAuthor");
3426
+ return (name, initials) => {
3427
+ let author = authors.find((a) => attr(a, "name") === name && attr(a, "initials") === initials);
3428
+ if (!author) {
3429
+ const id = Math.max(-1, ...authors.map((a) => numberValue(attr(a, "id")) ?? -1)) + 1;
3430
+ author = createElement(part.dom, "p:cmAuthor");
3431
+ setAttr(author, "id", String(id));
3432
+ setAttr(author, "name", name);
3433
+ setAttr(author, "initials", initials);
3434
+ setAttr(author, "lastIdx", "0");
3435
+ setAttr(author, "clrIdx", String(id));
3436
+ root.appendChild(author);
3437
+ authors.push(author);
3438
+ }
3439
+ const idx = (numberValue(attr(author, "lastIdx")) ?? 0) + 1;
3440
+ setAttr(author, "lastIdx", String(idx));
3441
+ part.markDirty();
3442
+ return {
3443
+ authorId: numberValue(attr(author, "id")) ?? 0,
3444
+ idx
3445
+ };
3446
+ };
3447
+ }
3448
+ /**
3449
+ * Add a comments part holding `comments`, registering each author in the deck's
3450
+ * `commentAuthors.xml`. The slide's own relationship *to* the part is left to the caller, as
3451
+ * `addNotesSlidePart` leaves the notes one, because the append path adds it after every id
3452
+ * the slide body names.
3453
+ * @param dest - the deck the part is added to
3454
+ * @param comments - the slide's comments, in order
3455
+ * @returns the comments part's name
3456
+ */
3457
+ function addCommentsPart(dest, comments) {
3458
+ const register = authorRegistry(dest);
3459
+ const meta = new Map(comments.map((comment) => [comment, register(comment.author, comment.initials)]));
3460
+ const partName = dest.opc.reservePartNameLike("/ppt/comments/comment1.xml");
3461
+ dest.opc.addPart(partName, COMMENTS_CONTENT_TYPE, textEncoder$2.encode(makeXmlComments(comments, meta)));
3462
+ return partName;
3463
+ }
3464
+ /**
3465
+ * Renumber the comments part a page copy brought from `source` against this deck's registry
3466
+ * (#235). The copy keeps each `@authorId` and `@idx` as the source numbered them, which on this
3467
+ * deck names no author, or the wrong one. Each comment's author is resolved in the source's
3468
+ * registry and registered in this deck's, and the comment takes the id and the next `idx` it gets
3469
+ * there. A comment whose author the source itself does not register is left as it is.
3470
+ *
3471
+ * Runs once per page copy, after the copy: a comments part is owned by its page (see
3472
+ * `page-owned.ts`), so every copy has a part of its own to renumber.
3473
+ * @param dest - the deck the page was copied into
3474
+ * @param source - the deck it was copied from
3475
+ * @param slidePartName - the copied page in `dest`
3476
+ */
3477
+ function carryCommentAuthors(dest, source, slidePartName) {
3478
+ const part = singleRelPart(dest.opc, slidePartName, COMMENTS_REL);
3479
+ const root = part?.dom.documentElement;
3480
+ if (!part || !root) return;
3481
+ const comments = getElements(root, "p:cm");
3482
+ if (comments.length === 0) return;
3483
+ const sourceAuthors = new Map(readCommentAuthors(source.opc, source.presentationPart.partName).map((a) => [a.id, a]));
3484
+ const register = authorRegistry(dest);
3485
+ const renumber = (cm) => {
3486
+ const author = sourceAuthors.get(numberValue(attr(cm, "authorId")));
3487
+ if (!author) return;
3488
+ const { authorId, idx } = register(author.name, author.initials);
3489
+ setAttr(cm, "authorId", String(authorId));
3490
+ setAttr(cm, "idx", String(idx));
3491
+ };
3492
+ comments.forEach(renumber);
3493
+ part.markDirty();
3494
+ }
3495
+ /**
3496
+ * Reset every author's `lastIdx` in the deck's registry to 0, for a deck with no comments left
3497
+ * (#244). `fromTemplate` strips the template's slides, and their comments with them, but the
3498
+ * registry keeps counting from the comments it removed, so the next comment would be numbered
3499
+ * after one the deck no longer has. `lastIdx` is the author's highest used index (ECMA-376
3500
+ * §19.4.2), and in an empty deck that is none. The authors themselves stay, with their ids and
3501
+ * colours, so a comment re-authored under the same name lands on the same entry.
3502
+ * @param dest - the deck whose slides were all removed
3503
+ */
3504
+ function resetCommentAuthorIndexes(dest) {
3505
+ const part = singleRelPart(dest.opc, dest.presentationPart.partName, COMMENT_AUTHORS_REL);
3506
+ const root = part?.dom.documentElement;
3507
+ if (!part || !root) return;
3508
+ const authors = getElements(root, "p:cmAuthor").filter((author) => attr(author, "lastIdx") !== "0");
3509
+ if (authors.length === 0) return;
3510
+ for (const author of authors) setAttr(author, "lastIdx", "0");
3511
+ part.markDirty();
3512
+ }
3513
+ // src/read/api/ops/slide-size.ts
3409
3514
  /**
3410
3515
  * pptx-ts: slide-size preconditions for the import surface
3411
3516
  *
@@ -3417,9 +3522,9 @@ function mergeEmbeddedFontEntries(dest, entries) {
3417
3522
  * except `importSlide`, and only when a rescale had been asked for.
3418
3523
  *
3419
3524
  * The two conditions are separated here, and the codes now mean what their names say:
3420
- * - `import/slide-size-unknown` — a deck does not declare `p:sldSz`, so there is no size to
3525
+ * - `import/slide-size-unknown`: a deck does not declare `p:sldSz`, so there is no size to
3421
3526
  * compare and no rescale to compute. Nothing the caller passes can make it comparable.
3422
- * - `import/slide-size-mismatch` — both sizes are known and they differ. This one *is*
3527
+ * - `import/slide-size-mismatch`: both sizes are known and they differ. This one *is*
3423
3528
  * answerable, which is why each caller supplies the escape hatch it offers.
3424
3529
  */
3425
3530
  /** A size as the error messages print it. */
@@ -3430,7 +3535,7 @@ function fmt(size) {
3430
3535
  * Both decks' sizes, or a throw when either deck does not declare one.
3431
3536
  *
3432
3537
  * Returned rather than asserted because every caller that needs both sizes known needs the
3433
- * values too — to compute a rescale — and TypeScript cannot narrow two parameters from one
3538
+ * values too, to compute a rescale, and TypeScript cannot narrow two parameters from one
3434
3539
  * assertion signature.
3435
3540
  *
3436
3541
  * @param target - this deck's slide size
@@ -3455,19 +3560,18 @@ function requireEqualSlideSize(target, incoming, api, hint = "") {
3455
3560
  if (known.widthEmu === source.widthEmu && known.heightEmu === source.heightEmu) return;
3456
3561
  throw new InvalidOptionError("import/slide-size-mismatch", `${api} requires equal slide sizes${hint ? ` (${hint})` : ""}; target is ${fmt(target)}, source is ${fmt(incoming)}`);
3457
3562
  }
3458
- /** Whether both sizes are known and equal — the question a caller with a rescale asks first. */
3563
+ /** Whether both sizes are known and equal: the question a caller with a rescale asks first. */
3459
3564
  function slideSizesMatch(target, incoming) {
3460
3565
  return !!target && !!incoming && target.widthEmu === incoming.widthEmu && target.heightEmu === incoming.heightEmu;
3461
3566
  }
3462
- //#endregion
3463
- //#region src/read/api/ops/append-slides.ts
3567
+ // src/read/api/ops/append-slides.ts
3464
3568
  /**
3465
3569
  * pptx-ts: the body of {@link Presentation.appendSlides}
3466
3570
  *
3467
3571
  * The hybrid "generate onto an existing deck" path: a slide producer authors slides, they are
3468
- * spliced into this package under fresh partnames, and every dependency each one carries —
3469
- * images, embedded and online media, hyperlinks, speaker notes, charts, intra-batch slide links
3470
- * — is wired into its `.rels`.
3572
+ * spliced into this package under fresh partnames, and every dependency each one carries
3573
+ * (images, embedded and online media, hyperlinks, speaker notes, review comments, charts,
3574
+ * intra-batch slide links) is wired into its `.rels`.
3471
3575
  *
3472
3576
  * Here rather than on the class for the reason `presentation.ts` states about the four import
3473
3577
  * bodies: the *contract* is the doc comment a caller reads and stays on the public method, while
@@ -3480,12 +3584,12 @@ function slideSizesMatch(target, incoming) {
3480
3584
  */
3481
3585
  const textEncoder$1 = new TextEncoder();
3482
3586
  /**
3483
- * Resolve `options.layout` — a layout *name* or a {@link LayoutHandle} — against this deck's
3484
- * gallery, with no silent fallback: an unusable value is one of three named errors rather than a
3587
+ * Resolve `options.layout` (a layout *name* or a {@link LayoutHandle}) against this deck's
3588
+ * gallery, with no silent fallback: an unusable value is one of four named errors rather than a
3485
3589
  * default layout, because a slide bound to the wrong layout is a deck that looks authored.
3486
3590
  *
3487
3591
  * Split out because it is the part of the append most likely to be wanted by a second caller, and
3488
- * because it is the only place `layout/ambiguous-name`, `layout/not-found` and
3592
+ * because it is the only place `layout/missing`, `layout/ambiguous-name`, `layout/not-found` and
3489
3593
  * `layout/foreign-handle` are raised.
3490
3594
  *
3491
3595
  * @param deck - the destination deck, whose `layouts()` gallery is searched
@@ -3494,6 +3598,8 @@ const textEncoder$1 = new TextEncoder();
3494
3598
  */
3495
3599
  function resolveLayoutTarget(deck, layout, api = "appendSlides") {
3496
3600
  const gallery = deck.layouts();
3601
+ const names = () => gallery.map((l) => JSON.stringify(l.name)).join(", ") || "(none)";
3602
+ if (layout == null) throw new InvalidOptionError("layout/missing", `${api}: options.layout is required, a layout name or a LayoutHandle from layouts(); available: ${names()}`);
3497
3603
  if (typeof layout !== "string") {
3498
3604
  if (!gallery.some((l) => l.partName === layout.partName)) throw new InvalidOptionError("layout/foreign-handle", `${api}: layout ${layout.partName} does not belong to this presentation`);
3499
3605
  return layout;
@@ -3501,10 +3607,7 @@ function resolveLayoutTarget(deck, layout, api = "appendSlides") {
3501
3607
  const matches = gallery.filter((l) => l.name === layout);
3502
3608
  if (matches.length > 1) throw new InvalidOptionError("layout/ambiguous-name", `${api}: layout name ${JSON.stringify(layout)} is ambiguous (${matches.length} layouts share it); pass a LayoutHandle from layouts() instead`);
3503
3609
  const [only] = matches;
3504
- if (!only) {
3505
- const names = gallery.map((l) => JSON.stringify(l.name)).join(", ");
3506
- throw new InvalidOptionError("layout/not-found", `${api}: no layout named ${JSON.stringify(layout)}; available: ${names || "(none)"}`);
3507
- }
3610
+ if (!only) throw new InvalidOptionError("layout/not-found", `${api}: no layout named ${JSON.stringify(layout)}; available: ${names()}`);
3508
3611
  return only;
3509
3612
  }
3510
3613
  /** Image parts behind the slide body's `image` rels, each keeping the id the body was built with. */
@@ -3536,8 +3639,20 @@ function wireAvMedia(deck, rels, partName, slide) {
3536
3639
  }
3537
3640
  }
3538
3641
  /**
3539
- * Online (external-link) video: two External rels share the link Target — the ECMA video rel and
3540
- * the MS-2007 media rel — with no media binary part and no content-type entry. The poster image is
3642
+ * A transition's start sound: one audio part behind the `audio` rel the body's `p:snd r:embed`
3643
+ * names. Registered as a Default extension entry, as {@link wireAvMedia} does.
3644
+ */
3645
+ function wireTransitionSound(deck, rels, partName, slide) {
3646
+ const sound = slide.transitionSound;
3647
+ if (!sound) return;
3648
+ const mediaPartName = deck.opc.reserveMediaPartName(sound.extn, "media");
3649
+ deck.opc.contentTypes.ensureDefault(sound.extn, sound.contentType);
3650
+ deck.opc.addPart(mediaPartName, sound.contentType, sound.bytes);
3651
+ rels.addWithId(`rId${sound.rId}`, AUDIO_REL, relativePartName(partName, mediaPartName));
3652
+ }
3653
+ /**
3654
+ * Online (external-link) video: two External rels share the link Target (the ECMA video rel and
3655
+ * the MS-2007 media rel), with no media binary part and no content-type entry. The poster image is
3541
3656
  * wired by {@link wireMedia}, which runs first.
3542
3657
  */
3543
3658
  function wireOnlineMedia(rels, slide) {
@@ -3552,7 +3667,7 @@ function wireHyperlinks(rels, slide) {
3552
3667
  }
3553
3668
  /**
3554
3669
  * Speaker notes. The notes part carries its own rel namespace, independent of the slide's:
3555
- * rId1 = notesMaster, rId2 = the slide it annotates, hyperlinks from rId3 — the order the
3670
+ * rId1 = notesMaster, rId2 = the slide it annotates, hyperlinks from rId3. That is the order the
3556
3671
  * generator's body was serialized against, so these are added by explicit id rather than left to
3557
3672
  * auto-numbering.
3558
3673
  *
@@ -3560,12 +3675,13 @@ function wireHyperlinks(rels, slide) {
3560
3675
  * so {@link wireAutoIdRels} adds it once every id the body does name is claimed.
3561
3676
  * @returns the notes part's name, or `null` when the slide has no notes
3562
3677
  */
3563
- function wireNotes(deck, partName, slide, sourceNotesMaster) {
3678
+ function wireNotes(deck, partName, slide, sourceNotesMaster, partBySourceNumber, index) {
3564
3679
  if (!slide.notes) return null;
3565
3680
  const notesMasterPartName = sourceNotesMaster ? ensureNotesMasterFromXml(deck, sourceNotesMaster) : null;
3566
3681
  const notesPartName = addNotesSlidePart(deck, slide.notes.xml, partName, notesMasterPartName);
3567
3682
  const notesRels = deck.opc.relationshipsFor(notesPartName);
3568
3683
  for (const h of slide.notes.hyperlinks) notesRels.addWithId(`rId${h.rId}`, HYPERLINK_REL, h.target, "External");
3684
+ wireSlideLinks(notesRels, notesPartName, slide.notes.slideLinks ?? [], partBySourceNumber, index);
3569
3685
  return notesPartName;
3570
3686
  }
3571
3687
  /**
@@ -3575,7 +3691,7 @@ function wireNotes(deck, partName, slide, sourceNotesMaster) {
3575
3691
  *
3576
3692
  * A chartEx chart differs in every other coordinate: the `chartEx{N}.xml` name family, the MS
3577
3693
  * chartex content type, the MS `chartEx` rel off the slide, and two mandatory sidecars at
3578
- * rId2/rId3 — without which PowerPoint reports the deck as corrupt (schema-valid but unopenable).
3694
+ * rId2/rId3, without which PowerPoint reports the deck as corrupt (schema-valid but unopenable).
3579
3695
  * `c.chartEx` carries both sidecar bodies; the generator built them, so nothing here reaches into
3580
3696
  * the emitters.
3581
3697
  */
@@ -3589,6 +3705,11 @@ function wireCharts(deck, rels, partName, slide) {
3589
3705
  deck.opc.addPart(embeddingPartName, XLSX_CONTENT_TYPE, c.embeddingBytes);
3590
3706
  const chartRels = deck.opc.relationshipsFor(chartPartName);
3591
3707
  chartRels.addWithId("rId1", PACKAGE_REL, relativePartName(chartPartName, embeddingPartName));
3708
+ for (const picture of c.pictures ?? []) {
3709
+ const mediaPartName = deck.opc.reserveMediaPartName(picture.extn);
3710
+ deck.opc.addPart(mediaPartName, picture.contentType, picture.bytes);
3711
+ chartRels.addWithId(`rId${picture.rId}`, IMAGE_REL, relativePartName(chartPartName, mediaPartName));
3712
+ }
3592
3713
  if (c.chartEx) {
3593
3714
  const colorsPartName = deck.opc.reservePartNameLike("/ppt/charts/colors1.xml");
3594
3715
  deck.opc.addPart(colorsPartName, CHART_COLOR_STYLE_CONTENT_TYPE, textEncoder$1.encode(c.chartEx.colorsXml));
@@ -3601,12 +3722,12 @@ function wireCharts(deck, rels, partName, slide) {
3601
3722
  }
3602
3723
  }
3603
3724
  /**
3604
- * Intra-batch slide-to-slide links: a `slide:N` in the source is repointed at the Nth appended
3605
- * slide's new partname, which is why pass 1 places every slide before any of this runs. A link out
3725
+ * Intra-batch slide-to-slide links, from a slide or from its notes: a `slide:N` in the source is
3726
+ * repointed at the Nth appended slide's new partname, which is why pass 1 places every slide before any of this runs. A link out
3606
3727
  * of the batch was refused before pass 1 by {@link requireLinksInBatch}.
3607
3728
  */
3608
- function wireSlideLinks(rels, partName, slide, partBySourceNumber, index) {
3609
- for (const link of slide.slideLinks) {
3729
+ function wireSlideLinks(rels, partName, links, partBySourceNumber, index) {
3730
+ for (const link of links) {
3610
3731
  const targetPartName = partBySourceNumber.get(link.sourceSlideNumber);
3611
3732
  if (!targetPartName) throw new InternalError("import/slide-link-not-placed", `appendSlides: slide ${index} links to source slide ${link.sourceSlideNumber}, which was checked against the batch but has no appended slide`);
3612
3733
  rels.addWithId(`rId${link.rId}`, SLIDE_REL, relativePartName(partName, targetPartName));
@@ -3619,12 +3740,13 @@ function wireSlideLinks(rels, partName, slide, partBySourceNumber, index) {
3619
3740
  */
3620
3741
  function requireLinksInBatch(slides) {
3621
3742
  slides.forEach((slide, index) => {
3622
- for (const link of slide.slideLinks) if (link.sourceSlideNumber > slides.length) throw new InvalidOptionError("import/unresolved-slide-link", `appendSlides: slide ${index} links to source slide ${link.sourceSlideNumber}, which is not among the appended slides`);
3743
+ for (const link of [...slide.slideLinks, ...slide.notes?.slideLinks ?? []]) if (link.sourceSlideNumber > slides.length) throw new InvalidOptionError("import/unresolved-slide-link", `appendSlides: slide ${index} links to source slide ${link.sourceSlideNumber}, which is not among the appended slides`);
3623
3744
  });
3624
3745
  }
3625
3746
  /**
3626
- * The first of pass 2's two phases: every rel the slide body names by id — media, embedded and
3627
- * online media, hyperlinks, charts, slide links — each added with the rId the generator wrote.
3747
+ * The first of pass 2's two phases: every rel the slide body names by id (media, embedded and
3748
+ * online media, a transition sound, hyperlinks, charts, slide links), each added with the rId the
3749
+ * generator wrote.
3628
3750
  * Also creates the notes part, whose own rels are fixed ids too.
3629
3751
  *
3630
3752
  * A new rel the body references by id belongs here, and nowhere after {@link wireAutoIdRels}.
@@ -3634,24 +3756,26 @@ function wireFixedIdRels(deck, rels, placed, sourceNotesMaster, partBySourceNumb
3634
3756
  const { slide, partName } = placed;
3635
3757
  wireMedia(deck, rels, partName, slide);
3636
3758
  wireAvMedia(deck, rels, partName, slide);
3759
+ wireTransitionSound(deck, rels, partName, slide);
3637
3760
  wireOnlineMedia(rels, slide);
3638
3761
  wireHyperlinks(rels, slide);
3639
- const notesPartName = wireNotes(deck, partName, slide, sourceNotesMaster);
3762
+ const notesPartName = wireNotes(deck, partName, slide, sourceNotesMaster, partBySourceNumber, index);
3640
3763
  wireCharts(deck, rels, partName, slide);
3641
- wireSlideLinks(rels, partName, slide, partBySourceNumber, index);
3764
+ wireSlideLinks(rels, partName, slide.slideLinks, partBySourceNumber, index);
3642
3765
  return notesPartName;
3643
3766
  }
3644
3767
  /**
3645
- * The second phase: the rels the slide body names by no id — its notes and its layout — numbered
3646
- * by `add()`, which takes one past the highest id present.
3768
+ * The second phase: the rels the slide body names by no id (its notes, its comments and its
3769
+ * layout), numbered by `add()`, which takes one past the highest id present.
3647
3770
  *
3648
3771
  * Strictly after {@link wireFixedIdRels}. The generator numbers a slide's rels from rId1, so an
3649
3772
  * auto id taken before a fixed one is claimed is routinely that fixed one: the notes rel used to
3650
3773
  * be added in the middle of the first phase, and a slide carrying notes and a chart or a slide
3651
3774
  * link threw `relationship/duplicate-id`.
3652
3775
  */
3653
- function wireAutoIdRels(rels, partName, notesPartName, layoutPartName) {
3776
+ function wireAutoIdRels(rels, partName, notesPartName, commentsPartName, layoutPartName) {
3654
3777
  if (notesPartName) rels.add(NOTES_SLIDE_REL, relativePartName(partName, notesPartName));
3778
+ if (commentsPartName) rels.add(COMMENTS_REL, relativePartName(partName, commentsPartName));
3655
3779
  rels.add(SLIDE_LAYOUT_REL, relativePartName(partName, layoutPartName));
3656
3780
  }
3657
3781
  /**
@@ -3659,7 +3783,7 @@ function wireAutoIdRels(rels, partName, notesPartName, layoutPartName) {
3659
3783
  * {@link Presentation.appendSlides}.
3660
3784
  */
3661
3785
  async function appendSlides(deck, source, options) {
3662
- const target = resolveLayoutTarget(deck, options.layout);
3786
+ const target = resolveLayoutTarget(deck, options?.layout);
3663
3787
  const extracted = await source.extractSlides(pickDefined(options, ["onMediaError"]));
3664
3788
  requireEqualSlideSize(deck.slideSize, {
3665
3789
  widthEmu: extracted.widthEmu,
@@ -3683,15 +3807,16 @@ async function appendSlides(deck, source, options) {
3683
3807
  placed.forEach((placedSlide, i) => {
3684
3808
  const rels = deck.opc.relationshipsFor(placedSlide.partName);
3685
3809
  const notesPartName = wireFixedIdRels(deck, rels, placedSlide, extracted.notesMaster, partBySourceNumber, i);
3686
- wireAutoIdRels(rels, placedSlide.partName, notesPartName, target.partName);
3810
+ const comments = placedSlide.slide.comments;
3811
+ const commentsPartName = comments?.length ? addCommentsPart(deck, comments) : null;
3812
+ wireAutoIdRels(rels, placedSlide.partName, notesPartName, commentsPartName, target.partName);
3687
3813
  const at = options.at === void 0 ? void 0 : options.at + i;
3688
3814
  added.push(deck.insertSlidePart(placedSlide.part, at));
3689
3815
  });
3690
3816
  carryGeneratedEmbeddedFonts(deck, extracted.embeddedFonts || []);
3691
3817
  return added;
3692
3818
  }
3693
- //#endregion
3694
- //#region src/read/api/ops/prune.ts
3819
+ // src/read/api/ops/prune.ts
3695
3820
  /**
3696
3821
  * Content types that are shared deck chrome, not owned by any one slide: the `deck` rows of
3697
3822
  * {@link SHARED_PARTS}, reached through the presentation → master → layout → theme graph or named
@@ -3823,8 +3948,7 @@ function isReferenced(pres, partName) {
3823
3948
  function relationshipOwners(pres) {
3824
3949
  return [...[...pres.opc.parts.keys()].filter((partName) => !partName.endsWith(".rels")), "/"];
3825
3950
  }
3826
- //#endregion
3827
- //#region src/read/api/ops/import-memo.ts
3951
+ // src/read/api/ops/import-memo.ts
3828
3952
  var ImportMemo = class {
3829
3953
  #registries = /* @__PURE__ */ new Map();
3830
3954
  #rescaled = /* @__PURE__ */ new Map();
@@ -3848,14 +3972,13 @@ var ImportMemo = class {
3848
3972
  for (const partName of gone) this.#rescaled.delete(partName);
3849
3973
  }
3850
3974
  };
3851
- //#endregion
3852
- //#region src/read/api/ops/flatten.ts
3975
+ // src/read/api/ops/flatten.ts
3853
3976
  /**
3854
3977
  * Baking a slide's theme dependencies into the slide itself, for `Presentation.importSlide` /
3855
3978
  * `importShape`.
3856
3979
  *
3857
3980
  * A slide imported into another deck is rebound to the *destination* master, so everything it
3858
- * resolved symbolically against its own theme silently re-resolves against a different one — its
3981
+ * resolved symbolically against its own theme silently re-resolves against a different one: its
3859
3982
  * scheme colours change, its style-matrix fills change, its placeholders snap to different
3860
3983
  * geometry and type sizes. The `theme: 'preserve'` mode exists to stop that: each pass here
3861
3984
  * resolves a dependency against the **source** theme (via `read/oxml/theme.ts` and
@@ -3864,25 +3987,25 @@ var ImportMemo = class {
3864
3987
  *
3865
3988
  * What gets flattened, and why each one matters:
3866
3989
  *
3867
- * 1. **`a:schemeClr` tokens** — rewritten to the literal `a:srgbClr` the source `clrMap` +
3990
+ * 1. **`a:schemeClr` tokens**: rewritten to the literal `a:srgbClr` the source `clrMap` +
3868
3991
  * `clrScheme` produce. Child transforms (`lumMod`/`shade`/`alpha`/…) are carried through
3869
3992
  * untouched, so tints and shades render identically; only the *base* reference is swapped,
3870
3993
  * never the transform math.
3871
- * 2. **Style-matrix refs** — a shape's `p:style` (`lnRef`/`fillRef`/`effectRef`) indexes the
3994
+ * 2. **Style-matrix refs**: a shape's `p:style` (`lnRef`/`fillRef`/`effectRef`) indexes the
3872
3995
  * theme `fmtScheme`; the indexed entry is resolved into an explicit `spPr` fill/line/effect
3873
3996
  * (with its `phClr` substituted) and the ref neutralized so it cannot re-resolve. The
3874
- * `fontRef` is deliberately left intact so its font can re-bind to the destination theme —
3875
- * the "normalize fonts on attach" bonus.
3876
- * 3. **Placeholder-inherited run colour, size and weight** — a run that sets none of its own
3997
+ * `fontRef` is deliberately left intact so its font can re-bind to the destination theme
3998
+ * (the "normalize fonts on attach" bonus).
3999
+ * 3. **Placeholder-inherited run colour, size and weight**: a run that sets none of its own
3877
4000
  * takes them from the source placeholder → layout → master text-style chain. Rebinding
3878
4001
  * replaces that chain, so each is resolved from the source styles and written onto the run.
3879
- * Typeface (`a:latin`) is deliberately *not* baked — it re-binds along with `fontRef`.
4002
+ * Typeface (`a:latin`) is deliberately *not* baked; it re-binds along with `fontRef`.
3880
4003
  * A shape that is not a placeholder takes the same properties from the presentation's
3881
4004
  * `p:defaultTextStyle` instead, which the rebind swaps for the destination's, so those
3882
4005
  * are baked from the source one. A table cell's text takes its size from the master's
3883
4006
  * `p:otherStyle`, and its weight too where the table style states none, so those are
3884
4007
  * baked from the source master.
3885
- * 4. **Placeholder-inherited geometry** — a placeholder with no own `a:xfrm` takes position and
4008
+ * 4. **Placeholder-inherited geometry**: a placeholder with no own `a:xfrm` takes position and
3886
4009
  * size from the matching source layout/master placeholder; without baking it, a title snaps
3887
4010
  * to the destination default and often clips off-canvas.
3888
4011
  *
@@ -3925,7 +4048,7 @@ function flattenSlide(slideRoot, ctx) {
3925
4048
  resolveSchemeColors(slideRoot, ctx);
3926
4049
  }
3927
4050
  /**
3928
- * Flatten a single lifted shape's theme dependencies in place — the shape-scoped
4051
+ * Flatten a single lifted shape's theme dependencies in place: the shape-scoped
3929
4052
  * subset of {@link flattenSlide} used by `Presentation.importShape` `preserve`
3930
4053
  * mode. It runs every pass that resolves a *shape's* theme references against the
3931
4054
  * source theme (style-matrix refs, placeholder-inherited geometry/colour/size/
@@ -3946,7 +4069,7 @@ function flattenSlide(slideRoot, ctx) {
3946
4069
  *
3947
4070
  * `shapeRoot` must be an element whose *descendants* include the lifted shape
3948
4071
  * (the passes match via `getElementsByTagNameNS`, which excludes the root element
3949
- * itself) — the caller wraps the imported `p:sp`/`p:pic`/`p:graphicFrame`/`p:grpSp`
4072
+ * itself), so the caller wraps the imported `p:sp`/`p:pic`/`p:graphicFrame`/`p:grpSp`
3950
4073
  * in a throwaway container before calling. The caller marks the part dirty.
3951
4074
  */
3952
4075
  function flattenShape(shapeRoot, ctx) {
@@ -3963,7 +4086,7 @@ function flattenShape(shapeRoot, ctx) {
3963
4086
  }
3964
4087
  /**
3965
4088
  * Restyle a rebound slide in place (the `theme: 'restyle'` mode): the exact
3966
- * inverse of {@link flattenSlide}. It bakes *nothing* — leaving every
4089
+ * inverse of {@link flattenSlide}. It bakes *nothing*: leaving every
3967
4090
  * `a:schemeClr`/style-matrix ref and `p:bg` `bgRef` symbolic is the whole point,
3968
4091
  * so they re-resolve against the *destination* master's `clrMap` + theme once the
3969
4092
  * slide is rebound. The single mutation is dropping the slide's own colour-map
@@ -3986,14 +4109,14 @@ function restyleSlide(slideRoot) {
3986
4109
  * destination theme; a literal matching no slot (the common case) is left exactly
3987
4110
  * as authored. Transform children (`lumMod`/`shade`/`alpha`/…) are carried across.
3988
4111
  *
3989
- * Plain `restyle` cannot re-brand a literal — it carries no theme reference. This
4112
+ * Plain `restyle` cannot re-brand a literal, since it carries no theme reference. This
3990
4113
  * re-introduces one by matching the literal's RGB against the slots the *source*
3991
4114
  * theme defined, emitting the scheme token that routes through the source `clrMap`
3992
4115
  * (so a literal equal to the source `accent1` slot becomes `schemeClr accent1`,
3993
4116
  * which the destination `clrMap`/theme then re-resolve). Slots are matched in
3994
4117
  * `clrScheme` order, so the first slot defining a given RGB wins when several share
3995
4118
  * it. Opt-in because it deliberately reinterprets authored literals as theme
3996
- * colours — visual QA territory, the same caveat as the rest of `restyle`.
4119
+ * colours: visual QA territory, the same caveat as the rest of `restyle`.
3997
4120
  */
3998
4121
  function remapLiteralColors(slideRoot, ctx) {
3999
4122
  const slotByHex = reverseClrScheme(ctx.clrScheme);
@@ -4082,7 +4205,7 @@ function resolvePlaceholderRunColors(slideRoot, ctx) {
4082
4205
  * `resolve` is asked once per *list level* per shape and memoized, because walking the
4083
4206
  * layout/master style chain is the expensive half and every paragraph at the same level gets
4084
4207
  * the same answer. `write` then runs per run, and owns the decision to skip a run the slide
4085
- * already fixes — the two passes ask that question differently (one colour check versus three
4208
+ * already fixes. The two passes ask that question differently (one colour check versus three
4086
4209
  * independent property checks), so it stays on their side of the boundary rather than becoming
4087
4210
  * a predicate parameter only one caller could use.
4088
4211
  *
@@ -4177,7 +4300,7 @@ function resolvePlaceholderGeometry(slideRoot, ctx) {
4177
4300
  * We resolve the effective anchor from the source chain and write it explicitly.
4178
4301
  * Shapes whose `a:bodyPr` already fixes `@anchor`, and placeholders with no
4179
4302
  * resolvable inherited anchor, are left untouched. Other `a:bodyPr` knobs (insets,
4180
- * autofit) are left as authored — they have sane defaults a plain shape keeps.
4303
+ * autofit) are left as authored; they have sane defaults a plain shape keeps.
4181
4304
  */
4182
4305
  function resolvePlaceholderBodyPr(shapeRoot, ctx) {
4183
4306
  forEachPlaceholderTextBody(shapeRoot, ctx, (txBody, type, idx) => {
@@ -4190,21 +4313,20 @@ function resolvePlaceholderBodyPr(shapeRoot, ctx) {
4190
4313
  }
4191
4314
  /**
4192
4315
  * Bake the placeholder-inherited list style onto a lifted shape's text body (the
4193
- * {@link flattenShape} placeholder-demotion path). A placeholder's per-level
4194
- * *paragraph* formatting — indent (`marL`/`indent`), bullets (`a:buChar`/
4195
- * `a:buAutoNum`/`a:buNone`), alignment, and the level `a:defRPr` — is inherited
4196
- * from the source layout/master placeholder `a:lstStyle` and the master
4197
- * `p:txStyles` category style. Run colour/size are baked onto each run by the
4198
- * sibling passes, but paragraph-level defaults live here; once
4199
- * {@link demotePlaceholders} strips the `p:ph` the shape stops inheriting them, so
4200
- * bullets and indents would vanish. We materialize the effective list style onto
4201
- * the shape's `p:txBody/a:lstStyle`.
4316
+ * {@link flattenShape} placeholder-demotion path). A placeholder inherits its per-level
4317
+ * *paragraph* formatting from the source layout/master placeholder `a:lstStyle` and
4318
+ * the master `p:txStyles` category style: indent (`marL`/`indent`), bullets
4319
+ * (`a:buChar`/`a:buAutoNum`/`a:buNone`), alignment, and the level `a:defRPr`. Run
4320
+ * colour/size are baked onto each run by the sibling passes, but paragraph-level
4321
+ * defaults live here; once {@link demotePlaceholders} strips the `p:ph` the shape
4322
+ * stops inheriting them, so bullets and indents would vanish. We materialize the
4323
+ * effective list style onto the shape's `p:txBody/a:lstStyle`.
4202
4324
  *
4203
4325
  * Resolution is per *level*, most specific tier wins whole: the slide's own level
4204
4326
  * (if it defines one) is kept verbatim, else the first source tier that defines it
4205
4327
  * (layout placeholder, then master placeholder, then master category style) is
4206
4328
  * cloned. This is a whole-element overlay, not the per-attribute merge PowerPoint
4207
- * does — but explicit paragraph `a:pPr` on the slide's own runs travels with the
4329
+ * does, but explicit paragraph `a:pPr` on the slide's own runs travels with the
4208
4330
  * shape and still wins, so this only supplies defaults for the inherited case
4209
4331
  * (paragraphs that set no `a:pPr` of their own). Scheme colours in the cloned
4210
4332
  * levels are resolved by the later `resolveSchemeColors` pass.
@@ -4231,7 +4353,7 @@ function resolvePlaceholderListStyle(shapeRoot, ctx) {
4231
4353
  * Strip the `p:ph` marker from every placeholder shape in a lifted subtree so it
4232
4354
  * becomes a self-contained ordinary shape (the {@link flattenShape} path only). By
4233
4355
  * the time this runs, the shape's inherited geometry, colour, run size, anchor, and
4234
- * list style are all baked explicitly, so it no longer needs — and must not keep —
4356
+ * list style are all baked explicitly, so it no longer needs (and must not keep)
4235
4357
  * its placeholder identity: a surviving `p:ph` would re-resolve against the *host*
4236
4358
  * deck's layout/master placeholder of the same type/idx (wrong inheritance, or a
4237
4359
  * fallback when the host has none) and could collide with the host slide's own
@@ -4249,7 +4371,7 @@ function demotePlaceholders(shapeRoot) {
4249
4371
  * {@link resolvePlaceholderRunColors}: for each placeholder run that sets no
4250
4372
  * `sz`/`b`/`i` of its own (nor at paragraph/text-body level on the *slide*),
4251
4373
  * resolve the value it would inherit from the source `slideLayout`/`slideMaster`
4252
- * text styles — per paragraph list level — and write it explicitly onto the run's
4374
+ * text styles, per paragraph list level, and write it explicitly onto the run's
4253
4375
  * `a:rPr`. Each property resolves independently up the chain. Typeface (`a:latin`)
4254
4376
  * is left to re-bind to the destination theme, as the colour pass does for the `fontRef`.
4255
4377
  */
@@ -4483,15 +4605,14 @@ function neutralizeRef(ref) {
4483
4605
  setAttr(ref, "idx", "0");
4484
4606
  for (const child of childElements(ref)) ref.removeChild(child);
4485
4607
  }
4486
- //#endregion
4487
- //#region src/read/api/ops/carried-rels.ts
4608
+ // src/read/api/ops/carried-rels.ts
4488
4609
  /**
4489
4610
  * Relationship rewriting for content carried between packages.
4490
4611
  *
4491
4612
  * When a shape or decoration is deep-copied out of a source deck, every relationship
4492
4613
  * reference it carries (`r:embed` on a picture fill, `r:id` on a chart frame, `r:link` on a
4493
4614
  * linked image, …) still names an id in the *source* part's relationship list. Left alone
4494
- * those ids either dangle or — worse — silently resolve to whatever the destination part
4615
+ * those ids either dangle or, worse, silently resolve to whatever the destination part
4495
4616
  * happens to have under the same id. This rewrites each one to a fresh relationship on the
4496
4617
  * destination part, copying the referenced part into the destination package on first sight.
4497
4618
  *
@@ -4551,8 +4672,7 @@ function carryRel(ctx, sourceRels, id, destPartName, destRels, relIdMap, owned)
4551
4672
  if (!ownsIt) relIdMap.set(key, newId);
4552
4673
  return newId;
4553
4674
  }
4554
- //#endregion
4555
- //#region src/read/api/ops/flatten-context.ts
4675
+ // src/read/api/ops/flatten-context.ts
4556
4676
  /**
4557
4677
  * The background the slide effectively inherits from its source subgraph: the layout's
4558
4678
  * `p:bg`, else the master's. Returns `null` when the slide carries its own `p:bg` (it stays
@@ -4585,8 +4705,7 @@ function sourceFlattenContext(sourceOpc, slidePartName) {
4585
4705
  tableStyles: sourceOpc.partsByContentType("application/vnd.openxmlformats-officedocument.presentationml.tableStyles+xml")[0]?.dom.documentElement ?? null
4586
4706
  };
4587
4707
  }
4588
- //#endregion
4589
- //#region src/read/api/ops/table-styles.ts
4708
+ // src/read/api/ops/table-styles.ts
4590
4709
  const TABLE_STYLES_DEFAULT_GUID = "{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}";
4591
4710
  const textEncoder = new TextEncoder();
4592
4711
  /**
@@ -4595,7 +4714,7 @@ const textEncoder = new TextEncoder();
4595
4714
  * table resolves its `@tableStyleId` against the *destination* `tableStyles` and
4596
4715
  * silently falls back when that id is absent; the source `<a:tblStyle>` is itself
4597
4716
  * symbolic (scheme colours), so copying it verbatim under the **same** id lets the
4598
- * table keep its structure while re-branding to this deck's theme — no table-XML
4717
+ * table keep its structure while re-branding to this deck's theme, with no table-XML
4599
4718
  * rewrite needed. Idempotent: an id this deck already defines is left as-is, and a
4600
4719
  * referenced id with no source definition is skipped. Creates and wires a
4601
4720
  * `tableStyles.xml` part if this deck has none.
@@ -4622,7 +4741,7 @@ function copySourceTableStyles(dest, sourceOpc, slideRoot) {
4622
4741
  }
4623
4742
  /**
4624
4743
  * Append each source `<a:tblStyle>` this deck does not already define, keyed by
4625
- * `styleId` — the shared core of {@link copySourceTableStyles} (which offers only
4744
+ * `styleId`: the shared core of {@link copySourceTableStyles} (which offers only
4626
4745
  * the styles a restyled slide references) and {@link carryTableStyles} (which
4627
4746
  * offers the source's whole list). Destination-wins per id: a style this deck
4628
4747
  * already defines is left untouched, so a re-call adds nothing. Returns whether
@@ -4644,14 +4763,14 @@ function addTableStyles(destList, styles) {
4644
4763
  * Copy the source deck's **whole** `tableStyles.xml` into this deck: every
4645
4764
  * `<a:tblStyle>` it defines, plus its `a:tblStyleLst@def` (the default table
4646
4765
  * style). Presentation-level, so a separate traversal from the master/layout copy
4647
- * chain — and whole-deck, since `tableStyles.xml` does not record which style
4766
+ * chain, and whole-deck, since `tableStyles.xml` does not record which style
4648
4767
  * belongs to which master. See `ImportSlideMastersOptions.tableStyles`.
4649
4768
  *
4650
4769
  * Styles union by `styleId` (destination-wins per id, via {@link addTableStyles}),
4651
4770
  * but `def` is **source-wins**: a caller asking for the source's table styling
4652
4771
  * wants its default too, and the destination's `def` is typically a generator stub
4653
4772
  * rather than a deliberate choice. Carrying the styles without the `def` would be
4654
- * the worse half-measure — the standard default GUID is one most templates also
4773
+ * the worse half-measure: the standard default GUID is one most templates also
4655
4774
  * define, so a new table would silently resolve to the wrong style rather than
4656
4775
  * visibly to none. Idempotent: a re-call re-adds nothing and re-sets `def` to the
4657
4776
  * same value.
@@ -4688,26 +4807,25 @@ function ensureTableStylesPart(dest) {
4688
4807
  dest.opc.relationshipsFor(dest.presentationPart.partName).add(TABLE_STYLES_REL, relativePartName(dest.presentationPart.partName, partName));
4689
4808
  return part;
4690
4809
  }
4691
- //#endregion
4692
- //#region src/read/api/ops/import-slide.ts
4810
+ // src/read/api/ops/import-slide.ts
4693
4811
  /**
4694
4812
  * The three ways a slide can be brought across from another deck.
4695
4813
  *
4696
4814
  * {@link Presentation.importSlide} picks one by `options.theme`, and the difference between
4697
4815
  * them is entirely about what happens to the slide's *look*:
4698
4816
  *
4699
- * - **`copy`** — not here. It copies the source theme subgraph wholesale via `copyPart`, so
4817
+ * - **`copy`**: not here. It copies the source theme subgraph wholesale via `copyPart`, so
4700
4818
  * the slide keeps its look by keeping its own theme; nothing needs rewriting.
4701
- * - **`preserve`** ({@link importSlidePreserve}) — rebind to this deck's master, then bake
4819
+ * - **`preserve`** ({@link importSlidePreserve}): rebind to this deck's master, then bake
4702
4820
  * the source theme into the slide XML. The slide looks the same as it did; it just no
4703
4821
  * longer depends on the theme it came from.
4704
- * - **`restyle`** ({@link importSlideRestyle}) — rebind and bake *nothing*, so the slide's
4822
+ * - **`restyle`** ({@link importSlideRestyle}): rebind and bake *nothing*, so the slide's
4705
4823
  * symbolic theme references re-resolve against the destination theme and it re-brands.
4706
4824
  *
4707
4825
  * The two share {@link importSlideRebind} and are exact inverses on top of it: preserve
4708
4826
  * resolves every reference it can, restyle resolves none. Any baking added to the shared
4709
4827
  * rebind would break restyle by pinning the slide to its source look, which is why the
4710
- * rebind carries no theme handling of its own — not even the inherited background.
4828
+ * rebind carries no theme handling of its own, not even the inherited background.
4711
4829
  *
4712
4830
  * These were private methods on `Presentation`, where they made the read model's own surface
4713
4831
  * (open a deck, walk slides, read shapes) hard to see: the import machinery was roughly two
@@ -4738,17 +4856,17 @@ function importSlidePreserve(dest, ctx, source, sourceSlide, carryGraphics) {
4738
4856
  }
4739
4857
  /**
4740
4858
  * Import a slide in `restyle` mode: rebind it to this deck's master/layout and then
4741
- * {@link restyleSlide} it — drop its colour map override but bake *nothing*, so its symbolic
4859
+ * {@link restyleSlide} it: drop its colour map override but bake *nothing*, so its symbolic
4742
4860
  * theme references re-resolve against the destination theme and the slide re-brands.
4743
4861
  *
4744
4862
  * The deliberate inverse of `preserve`: no flatten, no inherited-background bake, no
4745
- * placeholder colour/size/geometry bake — every one of those would pin the slide to its
4863
+ * placeholder colour/size/geometry bake. Every one of those would pin the slide to its
4746
4864
  * source look, the opposite of re-branding. Carried decorations are left symbolic too, so
4747
4865
  * they re-brand along with the slide.
4748
4866
  *
4749
4867
  * With `remapLiterals` it additionally force-remaps the slide's source-theme literal colours
4750
- * back to symbolic scheme colours and copies any referenced source table style into this deck
4751
- * — the two things plain `restyle` cannot re-brand.
4868
+ * back to symbolic scheme colours and copies any referenced source table style into this deck:
4869
+ * the two things plain `restyle` cannot re-brand.
4752
4870
  * @param {Presentation} dest - the destination deck
4753
4871
  * @param {ImportContext} ctx - the open import out of the source package
4754
4872
  * @param {Presentation} source - the source deck
@@ -4774,11 +4892,11 @@ function importSlideRestyle(dest, ctx, source, sourceSlide, carryGraphics, remap
4774
4892
  /**
4775
4893
  * The rebind shared by `preserve` and `restyle`: copy the slide bytes into a fresh part,
4776
4894
  * rebuild its relationships (drop notes, repoint the `slideLayout` rel at this deck's
4777
- * existing layout, copy every other internal target — media/charts — and pass externals
4895
+ * existing layout, copy every other internal target (media/charts), and pass externals
4778
4896
  * through), and optionally bake the source master/layout decorations onto the slide. Returns
4779
4897
  * the new part, its name, and its live root element for the caller's mode-specific pass.
4780
4898
  *
4781
- * This carries *no* theme baking of its own — not even the inherited background.
4899
+ * This carries *no* theme baking of its own, not even the inherited background.
4782
4900
  * `preserve` adds that via {@link flattenSlide}'s context; `restyle` must not, so the
4783
4901
  * background stays symbolic and re-brands.
4784
4902
  * @param {Presentation} dest - the destination deck
@@ -4839,8 +4957,8 @@ function rebind(dest, ctx, source, sourceSlide, carryGraphics) {
4839
4957
  /**
4840
4958
  * Bake the source `slideLayout`/`slideMaster` shape-tree decorations onto the imported slide
4841
4959
  * (the `carryMasterGraphics` path). Every shape on those trees *except* placeholders is
4842
- * deep-copied into the slide's `p:spTree` ahead of its own content — master decorations
4843
- * first, then layout, then the slide's shapes — so document (z-)order keeps the master
4960
+ * deep-copied into the slide's `p:spTree` ahead of its own content (master decorations
4961
+ * first, then layout, then the slide's shapes), so document (z-)order keeps the master
4844
4962
  * furthest back. Each decoration's media and other relationship targets are copied into this
4845
4963
  * package and its `r:embed`/`r:id`/… references rewritten to fresh slide-local ids. The
4846
4964
  * injected shapes are left for the caller's {@link flattenSlide} pass to resolve any theme
@@ -4893,8 +5011,7 @@ function destinationLayoutPartName(dest) {
4893
5011
  if (!layoutPartName) throw new InvalidOptionError("import/destination-missing-layout", "importSlide with theme 'preserve' or 'restyle' requires a slide layout in the destination deck");
4894
5012
  return layoutPartName;
4895
5013
  }
4896
- //#endregion
4897
- //#region src/read/api/ops/rescale.ts
5014
+ // src/read/api/ops/rescale.ts
4898
5015
  /** Build the EMU transform mapping source-canvas coordinates onto the target canvas (see {@link ImportSlideOptions.rescale}). */
4899
5016
  function computeRescale(source, target, mode) {
4900
5017
  if (mode === "stretch") return {
@@ -4913,7 +5030,7 @@ function computeRescale(source, target, mode) {
4913
5030
  }
4914
5031
  /**
4915
5032
  * Rescale every top-level transform on a `p:spTree`: shapes/pictures/connectors
4916
- * (`p:spPr/a:xfrm`), groups (`p:grpSpPr/a:xfrm` — only the group's own off/ext, so
5033
+ * (`p:spPr/a:xfrm`), groups (`p:grpSpPr/a:xfrm`, only the group's own off/ext, so
4917
5034
  * its children remap via the unchanged `chOff`/`chExt` rather than being recursed
4918
5035
  * into), and graphic frames (`p:graphicFrame/p:xfrm`, plus any inner table grid).
4919
5036
  * Placeholders that inherit geometry carry no `a:xfrm` and are left to inherit from
@@ -4962,8 +5079,8 @@ function rescaleXfrm(xfrm, t) {
4962
5079
  }
4963
5080
  }
4964
5081
  /**
4965
- * Scale a graphic-frame table's intrinsic dimensions — column widths by `sx`, row
4966
- * heights by `sy` — so the table resizes with the slide (PowerPoint derives table
5082
+ * Scale a graphic-frame table's intrinsic dimensions (column widths by `sx`, row
5083
+ * heights by `sy`) so the table resizes with the slide (PowerPoint derives table
4967
5084
  * geometry from the grid, not the frame `a:ext`). No-op for non-table frames.
4968
5085
  */
4969
5086
  function rescaleTableGrid(graphicFrame, t) {
@@ -4981,8 +5098,7 @@ function rescaleTableGrid(graphicFrame, t) {
4981
5098
  if (h !== null) setAttr(tr, "h", String(Math.max(0, Math.round(h * t.sy))));
4982
5099
  }
4983
5100
  }
4984
- //#endregion
4985
- //#region src/read/api/ops/rescale-import.ts
5101
+ // src/read/api/ops/rescale-import.ts
4986
5102
  /**
4987
5103
  * Rescaling an imported slide's geometry onto the destination canvas.
4988
5104
  *
@@ -4999,8 +5115,8 @@ function rescaleTableGrid(graphicFrame, t) {
4999
5115
  * graphicFrame transform and table grid on the slide; in `copy` mode also
5000
5116
  * rescales the imported layout and master shape trees (resolved via the
5001
5117
  * slide → layout → master rel chain) so inherited placeholder/background geometry
5002
- * stays aligned. `preserve`/`restyle` rebind to this deck's own master/layout —
5003
- * already the destination size — so only the slide is touched. Geometry only:
5118
+ * stays aligned. `preserve`/`restyle` rebind to this deck's own master/layout,
5119
+ * already the destination size, so only the slide is touched. Geometry only:
5004
5120
  * font sizes and line widths are left as authored.
5005
5121
  */
5006
5122
  function rescaleImportedGeometry(dest, rescaledParts, slidePartName, theme, source, target, mode) {
@@ -5052,8 +5168,7 @@ function rescalePartGeometry(dest, rescaledParts, partName, transform, mode) {
5052
5168
  rescaleSpTree(spTree, transform);
5053
5169
  part.markDirty();
5054
5170
  }
5055
- //#endregion
5056
- //#region src/read/api/presentation-imports.ts
5171
+ // src/read/api/presentation-imports.ts
5057
5172
  /** Body of {@link Presentation.importSlide}, whose doc comment carries the contract. */
5058
5173
  function importSlide(deck, source, index, options = {}) {
5059
5174
  const sourceSlide = source.slides[index];
@@ -5071,6 +5186,7 @@ function importSlide(deck, source, index, options = {}) {
5071
5186
  const newPart = deck.opc.part(newPartName);
5072
5187
  if (!newPart) throw new InternalError("import/part-went-missing", `Imported slide part went missing: ${newPartName}`);
5073
5188
  if (sizesDiffer && options.rescale && target && incoming) rescaleImportedGeometry(deck, deck.rescaledParts, newPartName, options.theme, incoming, target, options.rescale === true ? "fit" : options.rescale);
5189
+ carryCommentAuthors(deck, source, newPartName);
5074
5190
  const slide = deck.insertSlidePart(newPart, options.at);
5075
5191
  if (options.importNotes) carryNotes(deck, source, importCtx, sourceSlide.partName, newPartName);
5076
5192
  if (options.embedFonts) carryEmbeddedFonts(deck, source, importCtx);
@@ -5125,6 +5241,7 @@ function importSlides(deck, requests) {
5125
5241
  destPart
5126
5242
  };
5127
5243
  });
5244
+ for (const request of planned) carryCommentAuthors(deck, request.source, request.destPartName);
5128
5245
  for (const request of planned) {
5129
5246
  const mode = rescaleBySource.get(request.source.opc);
5130
5247
  if (!mode) continue;
@@ -5318,14 +5435,13 @@ function importShapes(deck, target, source, shapeIndices, options = {}) {
5318
5435
  }
5319
5436
  return result;
5320
5437
  }
5321
- //#endregion
5322
- //#region src/read/api/presentation.ts
5438
+ // src/read/api/presentation.ts
5323
5439
  /**
5324
5440
  * Read-model entry point: `Presentation` wraps an `OpcPackage` and exposes a
5325
5441
  * navigable, typed view of the deck (slides → shapes → text), backed by the
5326
5442
  * live DOM so the same nodes can later be mutated.
5327
5443
  *
5328
- * The class holds the model and the deck-level plumbing every operation needs — the part
5444
+ * The class holds the model and the deck-level plumbing every operation needs: the part
5329
5445
  * index, the slide list, the copy registry that lets repeated imports from one source share
5330
5446
  * what they already copied, and the `p:sldIdLst` wiring. The operations themselves live in
5331
5447
  * `ops/`, one job per module, taking this deck as an argument. The slide-import machinery
@@ -5335,11 +5451,11 @@ function importShapes(deck, target, source, shapeIndices, options = {}) {
5335
5451
  * The four import entry points went the same way, and {@link appendSlides} after them: their
5336
5452
  * contracts stay here as the doc comments a caller reads, and their bodies live in
5337
5453
  * `presentation-imports.ts` and `ops/append-slides.ts`. Those bodies are the one thing in this
5338
- * directory that is not independent of this class — they reach back for {@link importContext},
5454
+ * directory that is not independent of this class. They reach back for {@link importContext},
5339
5455
  * {@link insertSlidePart} and {@link rescaledParts}, which {@link cloneSlide} reads too and so
5340
5456
  * could not travel with them. Those three are `@internal` for that and nothing else.
5341
5457
  */
5342
- /** Content type of the main part in a `.potx` template package — flipped to {@link PRESENTATION_MAIN_CONTENT_TYPE} by {@link Presentation.fromTemplate}. */
5458
+ /** Content type of the main part in a `.potx` template package, flipped to {@link PRESENTATION_MAIN_CONTENT_TYPE} by {@link Presentation.fromTemplate}. */
5343
5459
  const PRESENTATION_TEMPLATE_MAIN_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.presentationml.template.main+xml";
5344
5460
  var Presentation = class Presentation {
5345
5461
  opc;
@@ -5393,6 +5509,7 @@ var Presentation = class Presentation {
5393
5509
  if (mainPart.contentType === PRESENTATION_TEMPLATE_MAIN_CONTENT_TYPE) pres.opc.contentTypes.ensureRegistered(mainPart.partName, PRESENTATION_MAIN_CONTENT_TYPE);
5394
5510
  }
5395
5511
  while (pres.slides.length > 0) pres.removeSlide(0);
5512
+ resetCommentAuthorIndexes(pres);
5396
5513
  return pres;
5397
5514
  }
5398
5515
  /** The main presentation part (`/ppt/presentation.xml`), resolved via the package `officeDocument` relationship. */
@@ -5444,7 +5561,7 @@ var Presentation = class Presentation {
5444
5561
  /**
5445
5562
  * The deck's embedded font families (`p:embeddedFontLst` in `presentation.xml`),
5446
5563
  * `[]` when it embeds none. Each entry names the typeface and resolves every
5447
- * embedded face's `r:id` to the absolute partname of its `.fntdata` binary — the
5564
+ * embedded face's `r:id` to the absolute partname of its `.fntdata` binary: the
5448
5565
  * read counterpart to the write-side `pptx.embedFont` / `importSlide({ embedFonts })`
5449
5566
  * carry. An entry whose `p:font` has no `@typeface`, or a face whose `r:id` is
5450
5567
  * missing or dangling, is skipped (faithful degradation, no throw). Read-only.
@@ -5474,7 +5591,7 @@ var Presentation = class Presentation {
5474
5591
  * `ppt/authors.xml`), `[]` when the deck carries no modern comments. Unlike the
5475
5592
  * legacy {@link commentAuthors}, each entry is keyed by a GUID `id` (plus
5476
5593
  * `userId`/`providerId`); each slide's {@link Slide.modernComments} resolves its
5477
- * `@authorId` against this list. Read-only — the writer emits legacy comments.
5594
+ * `@authorId` against this list. Read-only: the writer emits legacy comments.
5478
5595
  */
5479
5596
  get modernCommentAuthors() {
5480
5597
  return readModernCommentAuthors(this.opc, this.presentationPart.partName);
@@ -5504,7 +5621,7 @@ var Presentation = class Presentation {
5504
5621
  * The deck's extended document properties (`docProps/app.xml`): the producing
5505
5622
  * application and its version, the company, and the flat `TitlesOfParts` vector.
5506
5623
  * `{}` when the deck carries no extended-properties part. The read counterpart of
5507
- * the write-side `pptx.company` setter — the only one of the four this library
5624
+ * the write-side `pptx.company` setter, the only one of the four this library
5508
5625
  * writes from a caller's value; the other three it states about itself.
5509
5626
  *
5510
5627
  * A deliberate subset of the part: see {@link ExtendedProperties} for why the
@@ -5526,7 +5643,7 @@ var Presentation = class Presentation {
5526
5643
  * The deck-level programmatic tags (`p:custDataLst/p:tags` on `presentation.xml`,
5527
5644
  * resolved to `ppt/tags/tagN.xml`) as `{ name, val }` string pairs, `[]` when the
5528
5645
  * deck carries none. These are add-in/host metadata with no visible rendering and
5529
- * no writer — read-only, preserved byte-for-byte on round-trip. Per-slide tags are
5646
+ * no writer. They are read-only, preserved byte-for-byte on round-trip. Per-slide tags are
5530
5647
  * {@link Slide.tags}.
5531
5648
  */
5532
5649
  get tags() {
@@ -5545,7 +5662,7 @@ var Presentation = class Presentation {
5545
5662
  * charts, SmartArt diagrams and OLE embeddings, each with the subtree under it
5546
5663
  * (a chart's embedded workbook comes along; the image inside its user-shapes
5547
5664
  * drawing stays shared). PowerPoint refuses to open a deck where two slides
5548
- * resolve to one chart or diagram, so this is not tidiness — see
5665
+ * resolve to one chart or diagram, so this is not tidiness; see
5549
5666
  * `page-owned.ts` for the rule and the evidence behind it.
5550
5667
  */
5551
5668
  cloneSlide(index, options = {}) {
@@ -5563,7 +5680,7 @@ var Presentation = class Presentation {
5563
5680
  * `p:sldId` entry and the presentation→slide relationship are dropped, the slide
5564
5681
  * part and its `.rels` are deleted, and any part the slide *privately* owned
5565
5682
  * (its notes slide, slide-only media, charts/embeddings) that no remaining part
5566
- * references is pruned too — recursively. Shared deck chrome (layout, master,
5683
+ * references is pruned too, recursively. Shared deck chrome (layout, master,
5567
5684
  * theme, …) is never pruned, so the deck stays renderable; removing every slide
5568
5685
  * leaves a valid master/layout-only package (a template shell). The slide also
5569
5686
  * leaves every custom show and section it was in, which stay even when that
@@ -5603,9 +5720,9 @@ var Presentation = class Presentation {
5603
5720
  * Append a copy of `source.slides[index]` to this presentation and return it.
5604
5721
  *
5605
5722
  * Unlike {@link cloneSlide} (same-deck duplicate), this copies a slide across
5606
- * a package boundary: it brings the connected sub-graph the slide depends on —
5607
- * its `slideLayout` → `slideMaster` → `theme`, plus any media, charts, and
5608
- * embeddings — into this package under fresh partnames, rewriting every
5723
+ * a package boundary: it brings the connected sub-graph the slide depends on
5724
+ * (its `slideLayout` → `slideMaster` → `theme`, plus any media, charts, and
5725
+ * embeddings) into this package under fresh partnames, rewriting every
5609
5726
  * partname, relationship id, and content-type registration so the result is a
5610
5727
  * self-consistent OPC package. Parts of this (target) package that are not
5611
5728
  * touched stay byte-identical, matching `cloneSlide`'s fidelity contract.
@@ -5613,7 +5730,7 @@ var Presentation = class Presentation {
5613
5730
  * Only the layout(s) actually used by imported slides are copied; the imported
5614
5731
  * master's `p:sldLayoutIdLst` is pruned to exactly those, mirroring how
5615
5732
  * PowerPoint's "Reuse Slides" brings a slide across. Parts shared by repeated
5616
- * imports from the same source deck are copied once and reused — every part
5733
+ * imports from the same source deck are copied once and reused: every part
5617
5734
  * except the page itself. Importing the same source slide twice yields two
5618
5735
  * independent copies over one shared layout/master/theme, which is what lets a
5619
5736
  * deck show one page twice (verbatim, then edited).
@@ -5622,7 +5739,7 @@ var Presentation = class Presentation {
5622
5739
  * into the slide XML and the slide is bound to this deck's existing
5623
5740
  * master/layout; with `{ theme: 'restyle' }` the slide is bound to this deck's
5624
5741
  * master/layout with its theme references left symbolic, so it re-brands to the
5625
- * destination palette — see {@link ImportSlideOptions}.
5742
+ * destination palette. See {@link ImportSlideOptions}.
5626
5743
  *
5627
5744
  * By default the source slide size must equal this presentation's. Pass
5628
5745
  * `{ rescale: 'fit' | 'stretch' }` to rescale the imported geometry onto this
@@ -5641,7 +5758,7 @@ var Presentation = class Presentation {
5641
5758
  * Import selected pages from one or more loaded source presentations as one
5642
5759
  * batch. Each imported page lands at its `outputIndex` in the complete
5643
5760
  * destination slide list after the batch, and the returned array is parallel
5644
- * to `requests` — `result[i]` is the page `requests[i]` asked for, whatever
5761
+ * to `requests`: `result[i]` is the page `requests[i]` asked for, whatever
5645
5762
  * order the output positions were given in.
5646
5763
  *
5647
5764
  * Everything is checked before a single byte of this deck moves: every request
@@ -5654,13 +5771,13 @@ var Presentation = class Presentation {
5654
5771
  * The batch also decides what a `slide → slide` link means: an internal link
5655
5772
  * on a selected page must target another **selected** page (or one this deck
5656
5773
  * already contains via an earlier import from that source), and is rewritten
5657
- * to the fresh partname — importing page 3 of 10 does not drag pages 1–2
5774
+ * to the fresh partname. Importing page 3 of 10 does not drag pages 1–2
5658
5775
  * across as dependencies, and never strands the link. This mirrors
5659
5776
  * `appendSlides`' `import/unresolved-slide-link`, which the write side already
5660
5777
  * enforces for generator decks.
5661
5778
  *
5662
5779
  * One request is one output page, so naming the same source page in several
5663
- * requests is how you ask for several independent copies of it — the page part
5780
+ * requests is how you ask for several independent copies of it; the page part
5664
5781
  * is the one thing an import never shares, exactly as in {@link importSlide}.
5665
5782
  * Everything under it (layout, master, theme, media) is still copied once and
5666
5783
  * shared. Where such a page is the target of a `slide → slide` link, the link
@@ -5671,7 +5788,7 @@ var Presentation = class Presentation {
5671
5788
  * Speaker notes travel per request: `{ importNotes: true }` carries that page's
5672
5789
  * `notesSlide` part across, wired to the new page and bound to a single
5673
5790
  * `notesMaster` under the same 0..1 rule {@link importSlide} and
5674
- * {@link appendSlides} follow — the destination's own master wins when it has
5791
+ * {@link appendSlides} follow: the destination's own master wins when it has
5675
5792
  * one. Notes are part of the up-front dry run too, so a batch that would fail
5676
5793
  * carrying them is refused with the deck still byte-identical. A page named in
5677
5794
  * several requests gets its own copy of its notes each time, as of everything
@@ -5698,9 +5815,9 @@ var Presentation = class Presentation {
5698
5815
  }
5699
5816
  /**
5700
5817
  * Graft slide master(s) from another open package into this one and return what
5701
- * was copied. Unlike {@link importSlide} — which brings a master across only as
5818
+ * was copied. Unlike {@link importSlide}, which brings a master across only as
5702
5819
  * the dependency of an imported *slide* and prunes it to the one layout that
5703
- * slide uses — this copies a master together with its **whole** layout family
5820
+ * slide uses, this copies a master together with its **whole** layout family
5704
5821
  * and attaches it to no slide: the master and its layouts land in this deck's
5705
5822
  * layout gallery (PowerPoint's *Insert ▸ New Slide* / *Layout* picker) without
5706
5823
  * changing any existing slide.
@@ -5732,7 +5849,7 @@ var Presentation = class Presentation {
5732
5849
  }
5733
5850
  /**
5734
5851
  * The deck's slide masters, in `p:sldMasterIdLst` order, as modeled
5735
- * {@link SlideMaster}s — the typed read model over the shared chrome (each
5852
+ * {@link SlideMaster}s: the typed read model over the shared chrome (each
5736
5853
  * master's colour map, theme, placeholders, and the layouts built on it). Walk
5737
5854
  * `pres.masters()[i].layouts` for the rich layout model, or use {@link layouts}
5738
5855
  * for the flat {@link LayoutHandle} gallery {@link appendSlides} binds to.
@@ -5742,7 +5859,7 @@ var Presentation = class Presentation {
5742
5859
  return slideMasterPartNames(this).map((partName) => this.opc.part(partName)).filter((part) => part !== void 0).map((part) => new SlideMaster(this.opc, part));
5743
5860
  }
5744
5861
  /**
5745
- * The deck's slide layouts, in master then layout order — the gallery a new
5862
+ * The deck's slide layouts, in master then layout order: the gallery a new
5746
5863
  * slide can bind to. Each {@link LayoutHandle} addresses one layout for
5747
5864
  * {@link appendSlides}; the `name` is its `p:cSld@name`. Read-only enumeration:
5748
5865
  * it copies nothing and leaves the package byte-identical.
@@ -5765,12 +5882,12 @@ var Presentation = class Presentation {
5765
5882
  /**
5766
5883
  * Append generator-produced slides onto this deck, binding each to an existing
5767
5884
  * layout, and return the new {@link Slide}s. This is the hybrid
5768
- * "generate-onto-existing" path: the deck's masters, layouts, theme — and every
5769
- * other untouched part — stay **byte-identical** (only `presentation.xml`, its
5885
+ * "generate-onto-existing" path: the deck's masters, layouts, theme, and every
5886
+ * other untouched part stay **byte-identical** (only `presentation.xml`, its
5770
5887
  * `.rels`, `[Content_Types].xml`, and the freshly-added slide/media parts
5771
5888
  * change), because the existing chrome is never regenerated.
5772
5889
  *
5773
- * `source` is any slide producer (a `TsPptx` instance); its authored slides
5890
+ * `source` is any slide producer (a `PptxTs` instance); its authored slides
5774
5891
  * are serialized via {@link SlideSource.extractSlides} and spliced in under
5775
5892
  * fresh partnames, with each slide's `slideLayout` relationship pointed at the
5776
5893
  * layout named by `options.layout` and its image/hyperlink relationships rebuilt
@@ -5780,13 +5897,13 @@ var Presentation = class Presentation {
5780
5897
  * Charts and internal slide-to-slide hyperlinks are carried across: chart parts
5781
5898
  * (chart XML + `.rels` + embedded workbook) are injected under fresh names, and a
5782
5899
  * `slide:N` link is repointed at the Nth appended slide's new partname. A chartEx
5783
- * (Office 2016 — waterfall, funnel, treemap, ...) chart carries too, as its own
5900
+ * (Office 2016: waterfall, funnel, treemap, ...) chart carries too, as its own
5784
5901
  * `chartEx{N}.xml` part behind the MS chartEx rel, with the style and color-style
5785
5902
  * sidecars PowerPoint requires alongside it.
5786
5903
  *
5787
5904
  * The generator's presentation-level embedded fonts (`pptx.embedFont`) are also
5788
5905
  * carried into this deck and merged into its `p:embeddedFontLst`, de-duped by
5789
- * typeface + face slot — so author-side embedded fonts survive the append onto a
5906
+ * typeface + face slot, so author-side embedded fonts survive the append onto a
5790
5907
  * template that may itself already embed fonts.
5791
5908
  *
5792
5909
  * Embedded audio/video is carried too: the media part backs the ECMA audio/video rel
@@ -5797,24 +5914,28 @@ var Presentation = class Presentation {
5797
5914
  * Speaker notes ride across too: a slide authored with `addNotes` gets a `notesSlide`
5798
5915
  * part wired back to it, with its hyperlink rels preserved. A notes slide must bind to
5799
5916
  * a notes master, and a template commonly has none, so the generator's is installed
5800
- * (with the theme its `.rels` needs) — but only when this deck has none of its own, so
5917
+ * (with the theme its `.rels` needs), but only when this deck has none of its own, so
5801
5918
  * an existing notes master and its styling always win.
5802
5919
  *
5920
+ * Review comments (`addComment`) ride across as a comments part per slide. Their
5921
+ * authors merge into this deck's `commentAuthors.xml` by name and initials: an author
5922
+ * the deck already has keeps its id and continues its numbering, and a new one is added.
5923
+ *
5803
5924
  * Limitations:
5804
5925
  * - An internal link to a source slide outside the appended batch throws (its
5805
5926
  * target has no counterpart in the destination).
5806
5927
  * - Appended slides are concrete absolute-positioned content with no placeholder
5807
5928
  * inheritance from the bound layout; the binding governs theme/`clrMap`
5808
5929
  * resolution and the "based on" link, not placeholder geometry. Author with
5809
- * concrete colours — any `schemeClr` re-resolves against the destination theme.
5930
+ * concrete colours: any `schemeClr` re-resolves against the destination theme.
5810
5931
  * - Source and destination slide sizes must match (no geometry rescale).
5811
5932
  */
5812
5933
  async appendSlides(source, options) {
5813
5934
  return appendSlides(this, source, options);
5814
5935
  }
5815
5936
  /**
5816
- * Copy one shape — an autoshape, picture, table/chart graphic frame, connector,
5817
- * or group — from `source.shapes[shapeIndex]` onto `target`, returning the new
5937
+ * Copy one shape (an autoshape, picture, table/chart graphic frame, connector,
5938
+ * or group) from `source.shapes[shapeIndex]` onto `target`, returning the new
5818
5939
  * {@link Shape}. `target` must be a slide of *this* presentation; `source` may
5819
5940
  * belong to any open presentation.
5820
5941
  *
@@ -5825,7 +5946,7 @@ var Presentation = class Presentation {
5825
5946
  * so they cannot collide with the host. With `theme: 'preserve'` (default) the
5826
5947
  * shape's theme references are baked to literals against the *source* theme so it
5827
5948
  * renders the same on a foreign host; `restyle` leaves them symbolic to re-brand;
5828
- * `copy` brings the XML across untouched — see {@link ImportShapeOptions}.
5949
+ * `copy` brings the XML across untouched. See {@link ImportShapeOptions}.
5829
5950
  *
5830
5951
  * Differing slide sizes need `{ rescale }` (see {@link ImportShapeOptions.rescale});
5831
5952
  * a lifted `preserve` placeholder is baked self-contained and demoted to a plain
@@ -5857,7 +5978,7 @@ var Presentation = class Presentation {
5857
5978
  }
5858
5979
  /**
5859
5980
  * @internal The parts whose geometry a rescale has already rewritten, and in which mode.
5860
- * Exposed for `presentation-imports.ts` as a live map the callee adds to — the memo is what
5981
+ * Exposed for `presentation-imports.ts` as a live map the callee adds to. The memo is what
5861
5982
  * makes a layout or master shared across repeated imports from one source scale exactly
5862
5983
  * once, so like the copy registry it has to outlive the call that fills it.
5863
5984
  */
@@ -5867,7 +5988,7 @@ var Presentation = class Presentation {
5867
5988
  /**
5868
5989
  * @internal Open an import out of `source`: this deck as the destination, paired with
5869
5990
  * the copy registry for that package (created on first use). The registry is held on
5870
- * the class rather than in the context because it must outlive any one call — that is
5991
+ * the class rather than in the context because it must outlive any one call: that is
5871
5992
  * what makes a second import from the same source reuse the layout, master, theme, and
5872
5993
  * media it already copied instead of duplicating them, and it is why the import bodies
5873
5994
  * in `presentation-imports.ts` call back here rather than carrying it with them.
@@ -5914,7 +6035,7 @@ var Presentation = class Presentation {
5914
6035
  * A slide id one past the highest existing, but at least ST_SlideId's minimum.
5915
6036
  *
5916
6037
  * The module named and enforced that minimum and not the maximum, so a deck near the ceiling
5917
- * got an out-of-range `p:sldId/@id` written with no diagnostic — the package then needs
6038
+ * got an out-of-range `p:sldId/@id` written with no diagnostic. The package then needs
5918
6039
  * repair, for a reason nothing reported. Past the ceiling there is no "next" id to hand out,
5919
6040
  * so the allocation falls back to the lowest id in range that the deck is not already using;
5920
6041
  * a deck holding every one of the two billion has no legal answer and says so.
@@ -5937,7 +6058,6 @@ var Presentation = class Presentation {
5937
6058
  return this.opc.save();
5938
6059
  }
5939
6060
  };
5940
- //#endregion
5941
6061
  export { Slide as a, NotesSlide as c, SlideMaster as d, Theme as f, ContentTypes as g, Part as h, readExtendedProperties as i, Placeholder as l, Relationships as m, readCoreProperties as n, readTagsForPart as o, OpcPackage as p, readCustomProperties as r, NotesPlaceholder as s, Presentation as t, SlideLayout as u };
5942
6062
 
5943
- //# sourceMappingURL=presentation-Cyl74rq2.js.map
6063
+ //# sourceMappingURL=presentation-4Ggq0_Xa.js.map