@shbernal/ts-pptx 4.0.1 → 4.2.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 +147 -114
  2. package/dist/anim-presets-Qbgh8uut.js +55 -0
  3. package/dist/anim-presets-Qbgh8uut.js.map +1 -0
  4. package/dist/{autopage-odPz7zZO.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-Dw_BeWD_.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-CvN2iCA4.js → chart-metadata-CwiTTcJq.js} +634 -537
  15. package/dist/chart-metadata-CwiTTcJq.js.map +1 -0
  16. package/dist/{clip-Bl01BPcN.d.ts → clip-ISfCMtWA.d.ts} +6 -10
  17. package/dist/clip-ISfCMtWA.d.ts.map +1 -0
  18. package/dist/{notes-Dh12JAbn.js → comments-CKIZYRbZ.js} +530 -401
  19. package/dist/comments-CKIZYRbZ.js.map +1 -0
  20. package/dist/{diagnostics-D8ot4Ei7.d.ts → diagnostics-MoA4MBq5.d.ts} +55 -53
  21. package/dist/diagnostics-MoA4MBq5.d.ts.map +1 -0
  22. package/dist/{embedded-fonts-DarT9aoa.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-DCnvBZz2.d.ts → entry-compose-CiakSt-f.d.ts} +62 -81
  25. package/dist/entry-compose-CiakSt-f.d.ts.map +1 -0
  26. package/dist/{errors-C4oENPcu.js → entry-errors-JMthgJ2g.js} +45 -29
  27. package/dist/entry-errors-JMthgJ2g.js.map +1 -0
  28. package/dist/{table-cell-margins-EVg0EwxT.js → enums-BP9wsb9Q.js} +44 -47
  29. package/dist/enums-BP9wsb9Q.js.map +1 -0
  30. package/dist/{enums-BUKTUB6V.d.ts → enums-PcXr3o3J.d.ts} +13 -14
  31. package/dist/{enums-BUKTUB6V.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-Cb7naFj6.js → fit-Bpmzep6O.js} +64 -56
  36. package/dist/fit-Bpmzep6O.js.map +1 -0
  37. package/dist/{font-metrics-v5fn7s7e.d.ts → font-metrics-DTppw4t3.d.ts} +62 -38
  38. package/dist/font-metrics-DTppw4t3.d.ts.map +1 -0
  39. package/dist/{grid-DikTjFey.js → grid-DUIMxjfl.js} +23 -26
  40. package/dist/grid-DUIMxjfl.js.map +1 -0
  41. package/dist/{html-dom-Iuog2wdK.js → html-dom-LZCgntnJ.js} +46 -47
  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 +16 -18
  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-CrYXAfUu.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-J49Ck6S2.d.ts → package-CANBWuSm.d.ts} +9 -13
  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-C6qgOFAa.d.ts → pres-BkEkUAEM.d.ts} +410 -237
  75. package/dist/pres-BkEkUAEM.d.ts.map +1 -0
  76. package/dist/{presentation-DGYlAWhl.js → presentation-4Ggq0_Xa.js} +470 -315
  77. package/dist/presentation-4Ggq0_Xa.js.map +1 -0
  78. package/dist/{presentation-types-8jLQHI4M.d.ts → presentation-types-BgnZR-0a.d.ts} +1119 -468
  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 +2700 -780
  86. package/dist/script.js.map +1 -1
  87. package/dist/{shapes-re0KyQk_.js → shapes-CAPOjU0Q.js} +1564 -491
  88. package/dist/shapes-CAPOjU0Q.js.map +1 -0
  89. package/dist/{slide-Dx2ZeVZ6.d.ts → slide-BmT4kMoO.d.ts} +102 -89
  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-BTDP3lEP.js → table-dom-BYga4FYY.js} +4 -5
  94. package/dist/{table-dom-BTDP3lEP.js.map → table-dom-BYga4FYY.js.map} +1 -1
  95. package/dist/{text-sN64Otf_.js → text-CU08xJGs.js} +393 -344
  96. package/dist/text-CU08xJGs.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-XJlf-hOl.js → units-internal-BR3a4cIi.js} +34 -32
  100. package/dist/units-internal-BR3a4cIi.js.map +1 -0
  101. package/dist/{zip-CKd8ihcf.js → zip-7JTh61LX.js} +8 -10
  102. package/dist/zip-7JTh61LX.js.map +1 -0
  103. package/dist/{zip-C0leZZMj.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-DPUHh85d.js → zoom-CSSeOwM8.js} +1204 -620
  108. package/dist/zoom-CSSeOwM8.js.map +1 -0
  109. package/package.json +27 -28
  110. package/skills/{ts-pptx-upstream → pptx-ts-upstream}/SKILL.md +37 -84
  111. package/dist/autopage-odPz7zZO.js.map +0 -1
  112. package/dist/binary-string-CKVAYI3M.js.map +0 -1
  113. package/dist/body-insets-Dw_BeWD_.js.map +0 -1
  114. package/dist/clip-Bl01BPcN.d.ts.map +0 -1
  115. package/dist/diagnostics-D8ot4Ei7.d.ts.map +0 -1
  116. package/dist/embedded-fonts-DarT9aoa.d.ts.map +0 -1
  117. package/dist/entry-compose-DCnvBZz2.d.ts.map +0 -1
  118. package/dist/errors-C4oENPcu.js.map +0 -1
  119. package/dist/fit-Cb7naFj6.js.map +0 -1
  120. package/dist/font-metrics-v5fn7s7e.d.ts.map +0 -1
  121. package/dist/grid-DikTjFey.js.map +0 -1
  122. package/dist/html-dom-Iuog2wdK.js.map +0 -1
  123. package/dist/image-size-CvN2iCA4.js.map +0 -1
  124. package/dist/notes-Dh12JAbn.js.map +0 -1
  125. package/dist/options-internal-WqgMf720.js.map +0 -1
  126. package/dist/package-J49Ck6S2.d.ts.map +0 -1
  127. package/dist/playbtn-CUqQdoDf.js.map +0 -1
  128. package/dist/pres-C6qgOFAa.d.ts.map +0 -1
  129. package/dist/presentation-DGYlAWhl.js.map +0 -1
  130. package/dist/presentation-types-8jLQHI4M.d.ts.map +0 -1
  131. package/dist/shapes-re0KyQk_.js.map +0 -1
  132. package/dist/slide-Dx2ZeVZ6.d.ts.map +0 -1
  133. package/dist/table-cell-margins-EVg0EwxT.js.map +0 -1
  134. package/dist/text-anchor-CrYXAfUu.js.map +0 -1
  135. package/dist/text-sN64Otf_.js.map +0 -1
  136. package/dist/units-internal-XJlf-hOl.js.map +0 -1
  137. package/dist/zip-C0leZZMj.d.ts.map +0 -1
  138. package/dist/zip-CKd8ihcf.js.map +0 -1
  139. package/dist/zoom-DPUHh85d.js.map +0 -1
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@shbernal/ts-pptx",
3
- "version": "4.0.1",
3
+ "version": "4.2.0",
4
4
  "author": {
5
5
  "name": "shbernal",
6
6
  "url": "https://github.com/shbernal/"
7
7
  },
8
8
  "description": "Create PowerPoint presentations (.pptx) from TypeScript and modern JavaScript",
9
- "homepage": "https://shbernal.github.io/ts-pptx/",
9
+ "homepage": "https://shbernal.github.io/pptx-ts/",
10
10
  "license": "MIT",
11
- "packageManager": "pnpm@12.3.4",
11
+ "packageManager": "pnpm@12.18.0",
12
12
  "type": "module",
13
13
  "engines": {
14
14
  "node": ">=24"
@@ -87,7 +87,7 @@
87
87
  },
88
88
  "peerDependencies": {
89
89
  "mathml2omml": "^0.5.0",
90
- "temml": "^0.13.3"
90
+ "temml": "^0.13.3 || ^0.14.0"
91
91
  },
92
92
  "peerDependenciesMeta": {
93
93
  "mathml2omml": {
@@ -102,44 +102,43 @@
102
102
  },
103
103
  "devDependencies": {
104
104
  "@arethetypeswrong/cli": "^0.18.5",
105
- "@playwright/test": "^1.63.0",
105
+ "@playwright/test": "^1.65.0",
106
106
  "@types/istanbul-lib-coverage": "^2.0.6",
107
107
  "@types/istanbul-lib-report": "^3.0.3",
108
108
  "@types/istanbul-reports": "^3.0.4",
109
- "@types/node": "^26.6.1",
109
+ "@types/node": "^24.19.2",
110
110
  "@types/opentype.js": "^1.3.10",
111
- "@vitest/coverage-v8": "^5.0.1",
112
- "@vue/compiler-sfc": "^3.5.42",
113
- "ast-v8-to-istanbul": "^1.0.6",
114
- "charcheck": "0.4.0",
111
+ "@vitest/coverage-v8": "^5.1.0",
112
+ "@vue/compiler-sfc": "^3.5.45",
113
+ "ast-v8-to-istanbul": "^1.0.8",
114
+ "charcheck": "0.4.1",
115
115
  "esbuild": "^0.28.2",
116
- "happy-dom": "^20.14.5",
116
+ "happy-dom": "^21.0.4",
117
117
  "istanbul-lib-coverage": "^3.2.2",
118
118
  "istanbul-lib-report": "^3.0.1",
119
119
  "istanbul-reports": "^3.2.0",
120
120
  "jszip": "^3.10.2",
121
- "lefthook": "^2.1.14",
121
+ "knip": "^6.45.0",
122
122
  "mathml2omml": "^0.5.0",
123
- "mermaid": "^12.0.0",
124
- "micromark": "^4.0.2",
125
- "ooxml-validate": "^0.0.3",
126
- "oxfmt": "^0.68.0",
127
- "oxlint": "^1.83.0",
128
- "oxlint-tsgolint": "7.0.2001",
129
- "pptx-html": "^0.2.0",
130
- "publint": "^0.3.24",
131
- "temml": "^0.13.5",
132
- "ts-pptx-demos-showcases": "workspace:*",
133
- "tsdown": "^0.23.0",
123
+ "mermaid": "^12.3.0",
124
+ "micromark": "^4.0.3",
125
+ "ooxml-validate": "^0.0.5",
126
+ "oxfmt": "^0.75.0",
127
+ "oxlint": "^1.90.0",
128
+ "oxlint-tsgolint": "7.0.2005",
129
+ "pptx-html": "0.2.2-next.14.g2e560ca",
130
+ "publint": "^0.3.25",
131
+ "temml": "^0.14.0",
132
+ "tsdown": "^0.23.7",
134
133
  "typescript": "^7.0.2",
135
134
  "typescript-6": "npm:typescript@6.0.3",
136
- "vitepress": "^1.6.4",
137
- "vitest": "^5.0.1",
138
- "vue": "^3.5.42"
135
+ "vitepress": "2.0.0-alpha.21",
136
+ "vitest": "^5.1.0",
137
+ "vue": "^3.5.45"
139
138
  },
140
139
  "repository": {
141
140
  "type": "git",
142
- "url": "git+https://github.com/shbernal/ts-pptx.git"
141
+ "url": "git+https://github.com/shbernal/pptx-ts.git"
143
142
  },
144
143
  "keywords": [
145
144
  "pptx",
@@ -152,6 +151,6 @@
152
151
  "html"
153
152
  ],
154
153
  "bugs": {
155
- "url": "https://github.com/shbernal/ts-pptx/issues"
154
+ "url": "https://github.com/shbernal/pptx-ts/issues"
156
155
  }
157
156
  }
@@ -1,9 +1,9 @@
1
1
  ---
2
- name: ts-pptx-upstream
3
- description: Report a ts-pptx (pptx-ts) bug, gap, or wrong output to its GitHub tracker from a project that depends on it. Use when ts-pptx throws an InternalError or an error whose message points at the issue tracker, when it cannot read a .pptx that opens cleanly in PowerPoint, when it writes a deck PowerPoint repairs or renders wrong, when a construct does not survive a round trip, when its types block correct code, or whenever you are about to write a workaround for ts-pptx behaving incorrectly. Filing the bug is the fix; the workaround is the stopgap.
2
+ name: pptx-ts-upstream
3
+ description: Report a pptx-ts bug, gap, or wrong output to its GitHub tracker from a project that depends on it. Use when pptx-ts throws an InternalError or an error whose message points at the issue tracker, when it cannot read a .pptx that opens cleanly in PowerPoint, when it writes a deck PowerPoint repairs or renders wrong, when a construct does not survive a round trip, when its types block correct code, or whenever you are about to write a workaround for pptx-ts behaving incorrectly. Filing the bug is the fix; the workaround is the stopgap.
4
4
  ---
5
5
 
6
- # Reporting a ts-pptx problem upstream
6
+ # Reporting a pptx-ts problem upstream
7
7
 
8
8
  You are in a project that *uses* `pptx-ts`, not the project that builds it.
9
9
  This skill is how a defect you hit here becomes a permanent regression test there.
@@ -17,14 +17,14 @@ builds its own deck.** Everything below is in service of that.
17
17
 
18
18
  ## 1. Decide whether it is actually ours
19
19
 
20
- Every failure ts-pptx raises is a `TsPptxError` in one of five classes, and the class
20
+ Every failure pptx-ts raises is a `PptxTsError` in one of five classes, and the class
21
21
  already answers *whose problem is this*. Catch it and read `err.name` and `err.code`.
22
22
  `code` is a stable `area/condition` string and is API; the message is not, so never
23
23
  branch on its wording.
24
24
 
25
25
  | class | whose bug | report it? |
26
26
  | ------------------------- | ---------------- | ------------------------------------------------------------------- |
27
- | `InternalError` | **ts-pptx** | Always. The library says so itself in the message. |
27
+ | `InternalError` | **pptx-ts** | Always. The library says so itself in the message. |
28
28
  | `PackageReadError` | usually the file | Only if the file opens **cleanly in PowerPoint**. Then it's our gap. |
29
29
  | `MediaError` | usually the asset| Only if the image/font/AV loads fine elsewhere. |
30
30
  | `UnsupportedFeatureError` | nobody's, yet | If PowerPoint can express it, this is a feature request worth filing.|
@@ -32,7 +32,7 @@ branch on its wording.
32
32
 
33
33
  **The supported bar is "the output opens cleanly in Microsoft PowerPoint."** That is
34
34
  the project's own stated standard, and it is the test to apply in both directions: a
35
- file PowerPoint opens but ts-pptx rejects is our gap, and a file ts-pptx writes that
35
+ file PowerPoint opens but pptx-ts rejects is our gap, and a file pptx-ts writes that
36
36
  PowerPoint repairs is our bug.
37
37
 
38
38
  Not every defect throws. These are ours too, and are worth reporting:
@@ -42,7 +42,7 @@ Not every defect throws. These are ours too, and are worth reporting:
42
42
  - A **round trip that loses a construct**: read a deck, write it back, something is
43
43
  gone or changed. If the loss surfaced as a conversion fidelity note, the note has
44
44
  already classified it for you. See below.
45
- - The **read side cannot see what the write side authors**: ts-pptx emits the property
45
+ - The **read side cannot see what the write side authors**: pptx-ts emits the property
46
46
  but has no accessor to read it back. This is the strongest case a gap can make, and
47
47
  it has its own form (see step 5).
48
48
  - A `Diagnostic` that fires when it should not, does not fire when it should, or
@@ -79,13 +79,13 @@ before spending effort on a reproduction:
79
79
  *rendered* page (real `offsetWidth` after layout, the resolved cascade). Converting
80
80
  an HTML `<table>` is *not* in this category.
81
81
  - Third-party office-suite interop quirks that appear only after the file has been
82
- round-tripped through another application, when the package ts-pptx wrote is itself
82
+ round-tripped through another application, when the package pptx-ts wrote is itself
83
83
  valid OOXML.
84
84
 
85
85
  Issues and pull requests in those two areas are still welcome; just say so in the
86
86
  report so nobody triages it as a regression.
87
87
 
88
- Also: ts-pptx is **ESM, Node-first**. Reports about `require()`, a CJS build, or an
88
+ Also: pptx-ts is **ESM, Node-first**. Reports about `require()`, a CJS build, or an
89
89
  IIFE/global browser bundle will be closed. Those are deliberately not supported.
90
90
 
91
91
  ## 2. Collect the facts
@@ -115,10 +115,10 @@ anonymously, never its name, its deck or client names, or a path from its tree.
115
115
  Instead, write a self-contained script that *constructs* its input and fails:
116
116
 
117
117
  ```ts
118
- import TsPptx from 'pptx-ts'
118
+ import PptxTs from 'pptx-ts'
119
119
 
120
120
  // build the smallest deck that shows the problem
121
- const pptx = new TsPptx()
121
+ const pptx = new PptxTs()
122
122
  const slide = pptx.addSlide()
123
123
  slide.addText('x', { x: 1, y: 1, w: 8, h: 1 /* the option that triggers it */ })
124
124
 
@@ -169,7 +169,7 @@ command, and you were going to need it anyway once the fix shipped.
169
169
  Then the tracker:
170
170
 
171
171
  ```bash
172
- gh issue list --repo shbernal/ts-pptx --state all --limit 20 --search "<distinctive phrase>"
172
+ gh issue list --repo shbernal/pptx-ts --state all --limit 20 --search "<distinctive phrase>"
173
173
  ```
174
174
 
175
175
  Search the error `code` (`table/invalid-border`, `oxml/node-has-no-document`), the
@@ -192,71 +192,30 @@ file from this project is attached. When you cannot manage a self-contained repr
192
192
  the answer is a thinner report, the prose description from step 3. Not a question, and
193
193
  not an attachment.
194
194
 
195
- Three forms; pick by what you are reporting:
195
+ Two forms; pick by what you are reporting:
196
196
 
197
- | form | for |
198
- | ------------------ | ------------------------------------------------------------------------- |
199
- | `agent-report.yml` | you hit this while using the library in another project. Start here. |
200
- | `bug.yml` | wrong output, a repair prompt, a regression, a fidelity limit |
201
- | `api-gap.yml` | the OOXML carries it but no accessor reaches it |
197
+ | form | for |
198
+ | ------------- | ------------------------------------------------------------------------------------------ |
199
+ | `bug.yml` | a thrown error, wrong output, a repair prompt, a regression, wrong types, a fidelity limit |
200
+ | `api-gap.yml` | the OOXML carries it but no accessor reaches it |
202
201
 
203
- If none fits, file a blank issue rather than bending one of them. Blank issues are
202
+ If neither fits, file a blank issue rather than bending one of them. Blank issues are
204
203
  enabled deliberately.
205
204
 
206
- `gh` defaults to the *current* repository, which here is the consumer's, not ts-pptx's.
207
- Always pass `--repo shbernal/ts-pptx` explicitly, or you will file the bug into the wrong
208
- tracker.
205
+ File through whatever you have: a GitHub MCP server, `gh`, or `curl` against the REST API
206
+ with `GITHUB_TOKEN`. Whichever it is, target `shbernal/pptx-ts` explicitly. `gh` and most
207
+ tools default to the *current* repository, which here is the consumer's. Do not send
208
+ labels: the API drops them for anyone without push access, and triage applies them.
209
209
 
210
- ```bash
211
- gh issue create --repo shbernal/ts-pptx \
212
- --title "<InternalError|reads|writes|round-trip|types>: <one specific symptom>" \
213
- --label agent-reported \
214
- --body-file <a path your repo ignores>/ts-pptx-report.md
215
- ```
216
-
217
- Write the body somewhere the consumer's own `.gitignore` already covers: its scratch or
218
- temp directory, whatever that repo calls it. A report file committed by accident is a
219
- second copy of the reproduction living in someone else's history.
220
-
221
- The web form (`agent-report.yml`) is what the error message links to; `gh` does not apply
222
- issue forms, so mirror its sections in the body file so both routes land the same shape:
223
-
224
- ````markdown
225
- ### ts-pptx version
226
- <x.y.z>
227
-
228
- ### Node.js version
229
- <vXX.Y.Z>
230
-
231
- ### Operating system
232
- <Windows 11 x64 / macOS 15 arm64 / Ubuntu 24.04 x64>
233
-
234
- ### PowerPoint version
235
- <only if the report depends on how PowerPoint renders or repairs the file>
236
-
237
- ### Error class and code
238
- <InternalError / oxml/node-has-no-document> (or: nothing threw, the output is wrong)
239
-
240
- ### What happened
241
- <observed>
210
+ None of those routes applies a form, so write the body with the form's headings
211
+ (`### Severity`, `### What happens`, `### Minimal reproduction`, and the rest of
212
+ [`bug.yml`](https://github.com/shbernal/pptx-ts/blob/main/.github/ISSUE_TEMPLATE/bug.yml)),
213
+ and answer `### AI involvement` with `Filed by an AI agent`. If you stage the body in a
214
+ file, put it somewhere the consumer's `.gitignore` already covers, so the reproduction does
215
+ not end up in someone else's history.
242
216
 
243
- ### What should have happened
244
- <expected, and why you believe that: an ECMA-376 clause, what PowerPoint itself does
245
- with the same input, or what the docs promise>
246
-
247
- ### Minimal reproduction
248
- ```js
249
- <the script from step 3>
250
- ```
251
-
252
- ### Error output
253
- ```
254
- <verbatim message, detail, and stack>
255
- ```
256
-
257
- ### Attached file
258
- <none / synthesized, and how it was generated>
259
- ````
217
+ With no way to authenticate, give the user the report and
218
+ <https://github.com/shbernal/pptx-ts/issues/new?template=bug.yml> to paste it into.
260
219
 
261
220
  Tell the user the issue number and URL once it exists. After the fact, as a result, not
262
221
  as a request. They should be able to read what you filed and close it if they disagree.
@@ -272,7 +231,7 @@ which means re-reading the issue and re-deriving the reproduction someone alread
272
231
  Write the comment so that verifying the fix is running one line:
273
232
 
274
233
  ```ts
275
- // Workaround for ts-pptx#<N>: https://github.com/shbernal/ts-pptx/issues/<N>
234
+ // Workaround for pptx-ts#<N>: https://github.com/shbernal/pptx-ts/issues/<N>
276
235
  //
277
236
  // <what the library does instead, as an observable: the XML it emits, the value the
278
237
  // accessor returns, the option it ignores.>
@@ -281,8 +240,8 @@ Write the comment so that verifying the fix is running one line:
281
240
  // part containing the right element> holds, and write <the code this becomes> instead.
282
241
  ```
283
242
 
284
- Keep `ts-pptx#` in that literal spelling wherever you mark one. It is the token that
285
- makes `rg 'ts-pptx#'` list every stopgap in the project at once, and step 7 is exactly
243
+ Keep `pptx-ts#` in that literal spelling wherever you mark one. It is the token that
244
+ makes `rg 'pptx-ts#'` list every stopgap in the project at once, and step 7 is exactly
286
245
  the moment someone needs that list.
287
246
 
288
247
  ## 7. When the fix ships, delete the workaround
@@ -294,13 +253,13 @@ fix.
294
253
 
295
254
  ```bash
296
255
  npm view pptx-ts version # what is out
297
- gh issue list --repo shbernal/ts-pptx --state closed --limit 30
298
- rg 'ts-pptx#' # every stopgap here
256
+ gh issue list --repo shbernal/pptx-ts --state closed --limit 30
257
+ rg 'pptx-ts#' # every stopgap here
299
258
  ```
300
259
 
301
260
  **A closed issue is not a released fix.** A fix can sit merged and unreleased for weeks,
302
261
  so check the published version, never the issue state. The repository's
303
- [`CHANGELOG.md`](https://github.com/shbernal/ts-pptx/blob/master/CHANGELOG.md) and the
262
+ [`CHANGELOG.md`](https://github.com/shbernal/pptx-ts/blob/main/CHANGELOG.md) and the
304
263
  GitHub release notes name the issue numbers each version closes. Bump the pin, reinstall,
305
264
  and refresh the installed skill in the same commit. Then, per stopgap:
306
265
 
@@ -319,12 +278,6 @@ and refresh the installed skill in the same commit. Then, per stopgap:
319
278
  say the fix works; a consumer's say it works *where it was found*, which is the thing
320
279
  they cannot write themselves.
321
280
 
322
- ## If `gh` is unavailable
323
-
324
- Print the assembled report and this URL, and ask the user to paste it in:
325
-
326
- <https://github.com/shbernal/ts-pptx/issues/new?template=agent-report.yml>
327
-
328
281
  ## Keeping this skill current
329
282
 
330
283
  This file ships inside the package, so the copy in `node_modules` always matches the
@@ -332,7 +285,7 @@ installed version. The copy in an agent directory is a *copy*, and a version bum
332
285
  not move it. Refresh it in the same commit as the bump, which is step 7's commit:
333
286
 
334
287
  ```bash
335
- npx skills update ts-pptx-upstream
288
+ npx skills update pptx-ts-upstream
336
289
  ```
337
290
 
338
291
  If that reports nothing to do but the skill is not loading, the runtime link is missing
@@ -1 +0,0 @@
1
- {"version":3,"file":"autopage-odPz7zZO.js","names":[],"sources":["../src/gen/table/autopage.ts"],"sourcesContent":["/**\n * ts-pptx: Table auto-paging core\n *\n * The DOM-independent heart of table generation: given rows that overflow a slide,\n * split them across as many slides as needed, measuring wrapped text to compute line\n * counts and row heights. `getSlidesForTableRows` is the in-memory core (fully\n * Node-testable); `parseTextToLines` is its private cell-wrapping helper.\n */\n\nimport { SlideObjectType } from '../../enums.js'\nimport { DEF_FONT_SIZE, DEF_SLIDE_MARGIN_IN } from '../../constants-internal.js'\nimport type { PresLayout, TableRowSlide, TableCellProps } from '../../types/index.js'\nimport type {\n\tSlideLayoutInternal,\n\tTableCellInternal,\n\tTableRowInternal,\n\tTableToSlidesPropsInternal,\n} from '../../types/internal.js'\nimport {\n\tautoPageLineHeightEmu,\n\tgetSmartParseNumber,\n\tinch2Emu,\n\tmarginToEmu,\n\tpinnedRowHeightInches,\n\tresolveCellMarginsInches,\n\tresolveSlideMarginsInches,\n\tresolveTableColWidthsEmu,\n\tusableTableWidthEmu,\n} from '../../units-internal.js'\nimport { warn } from '../../diagnostics.js'\nimport { type GridPlacement, tableColCount, walkTableGrid } from './grid.js'\nimport { resolveSpan, withCheckedSpans } from './spans.js'\nimport { EMU_PER_INCH, POINTS_PER_INCH } from '../../units.js'\n\ntype AutoPageCell = TableCellInternal & {\n\t_lineHeight: number\n\t_lines: TableCellInternal[][]\n\toptions: TableCellProps\n\ttext: TableCellInternal[]\n}\n\n/**\n * A cell for the pager's working grid, carrying the source cell's options only when it has some.\n *\n * Every one of these used to be an inline `{ …, options: cell.options }`, which put an `options`\n * key holding `undefined` on a cell whose source had none. Readers cannot see the difference —\n * they all go through `cell.options?.…` — but a `TableCellProps` bag *is* spread in\n * `gen/define/table.ts` (`{ ...colDef, ...headerRow, ...cell.options }`), where the two states\n * are not the same thing. So the model keeps one spelling of absent.\n * @param text - the cell's content, a string or the run list the pager is accumulating\n * @param options - the source cell's options, if it had any\n */\nfunction workingCell(text: string | TableCellInternal[], options: TableCellProps | undefined): TableCellInternal {\n\treturn options === undefined\n\t\t? { _type: SlideObjectType.tablecell, text }\n\t\t: { _type: SlideObjectType.tablecell, text, options }\n}\n\n// ===== Cell text wrapping =====\n\n/**\n * Break cell text into lines based upon table column width (e.g.: Magic Happens Here(tm))\n *\n * `charWeight` arrives as an argument rather than being read off `cell.options` because the\n * caller used to *stamp* it there: the table's weight was written onto the caller's own cell\n * options bag, or `delete`d from it when the table stated none. That mutated caller input --\n * which the chart path has a dedicated guard against -- and it made the option's precedence\n * differ by call site: the row-height probe read the cell's own value while the main loop had\n * just overwritten it with the table's. Both callers now resolve it the same way, and the more\n * specific statement wins, as it does everywhere else in this codebase.\n *\n * `fontSizePt` arrives resolved for the same reason. This read `cell.options.fontSize` or the\n * library default and never the table's `fontSize`, while the row's line height and the emitted\n * `sz` both used the table's. A table of 24pt text was wrapped as if it were 12pt, so the pager\n * counted about half the lines and rows ran off the bottom of each page.\n * @param {TableCellInternal} cell - table cell\n * @param {number} colWidth - table column width (inches)\n * @param {number} fontSizePt - resolved font size: the cell's, else the table's, else the default\n * @param {number} charWeight - resolved `autoPageCharWeight`: the cell's, else the table's, else 0\n * @param {boolean} [verbose] - dump the four wrapping stages; carries `addTable({ verbose })`\n * down, which is the only stage of the pager that flag did not reach\n * @return {TableRowInternal[]} - cell's text objects grouped into lines\n */\nfunction parseTextToLines(\n\tcell: TableCellInternal,\n\tcolWidth: number,\n\tfontSizePt: number,\n\tcharWeight: number,\n\tverbose?: boolean\n): TableCellInternal[][] {\n\t// FYI: CPL = Width / (font-size / font-constant)\n\t// FYI: CHAR:2.3, colWidth:10, fontSize:12 => CPL=138, (actual chars per line in PPT)=145 [14.5 CPI]\n\t// FYI: CHAR:2.3, colWidth:7 , fontSize:12 => CPL= 97, (actual chars per line in PPT)=100 [14.3 CPI]\n\t// FYI: CHAR:2.3, colWidth:9 , fontSize:16 => CPL= 96, (actual chars per line in PPT)=84 [ 9.3 CPI]\n\tconst FOCO = 2.3 + charWeight // Character Constant\n\t// `colWidth` is inches, so the column's width in points is `colWidth * 72`. This used to be\n\t// spelled `(colWidth / EMU_PER_POINT) * EMU_PER_INCH`, which is the same 72 with two EMU\n\t// constants that cancel -- except that the detour through EMU is not exact in binary floating\n\t// point, and `Math.floor` takes the hit. Over the 200,000 widths from 0.001in to 200in the two\n\t// forms disagree on 51, always by one point low: 6.625in is exactly 477 points, and the old\n\t// form floored 476.9999... to 476.\n\tconst CPL = Math.floor(colWidth * POINTS_PER_INCH) / (fontSizePt / FOCO) // Chars-Per-Line\n\n\t// The number the four dumps below exist to explain: every wrap decision in step 4 is\n\t// `strCurrLine.length + word.length > CPL`, so a wrap that looks wrong is almost always\n\t// a CPL that is wrong, and CPL is not recoverable from the lines themselves.\n\tif (verbose) console.log(`[0/4] colWidth=${colWidth}in fontSize=${fontSizePt} FOCO=${FOCO} CPL=${CPL}`)\n\n\tconst parsedLines: TableCellInternal[][] = []\n\tlet inputCells: TableCellInternal[] = []\n\tconst inputLines1: TableCellInternal[][] = []\n\tconst inputLines2: TableCellInternal[][] = []\n\n\t/**\n\t * EX INPUTS: `cell.text`\n\t * - string....: \"Account Name Column\"\n\t * - object....: { text:\"Account Name Column\" }\n\t * - object[]..: [{ text:\"Account Name\", options:{ bold:true } }, { text:\" Column\" }]\n\t * - object[]..: [{ text:\"Account Name\", options:{ breakLine:true } }, { text:\"Input\" }]\n\t */\n\n\t/**\n\t * EX OUTPUTS:\n\t * - string....: [{ text:\"Account Name Column\" }]\n\t * - object....: [{ text:\"Account Name Column\" }]\n\t * - object[]..: [{ text:\"Account Name\", options:{ breakLine:true } }, { text:\"Input\" }]\n\t * - object[]..: [{ text:\"Account Name\", options:{ breakLine:true } }, { text:\"Input\" }]\n\t */\n\n\t// STEP 1: Ensure inputCells is an array of TableCells\n\tif (cell.text && cell.text.toString().trim().length === 0) {\n\t\t// Allow a single space/whitespace as cell text (user-requested feature)\n\t\tinputCells.push({ _type: SlideObjectType.tablecell, text: ' ' })\n\t} else if (typeof cell.text === 'number' || typeof cell.text === 'string') {\n\t\tinputCells.push({ _type: SlideObjectType.tablecell, text: (cell.text || '').toString().trim() })\n\t} else if (Array.isArray(cell.text)) {\n\t\tinputCells = cell.text\n\t}\n\tif (verbose) {\n\t\tconsole.log('[1/4] inputCells')\n\t\tinputCells.forEach((cell, idx) => console.log(`[1/4] [${idx + 1}] cell: ${JSON.stringify(cell)}`))\n\t}\n\n\t// STEP 2: Group table cells into lines based on \"\\n\" or `breakLine` prop\n\t/**\n\t * - EX: `[{ text:\"Input Output\" }, { text:\"Extra\" }]` == 1 line\n\t * - EX: `[{ text:\"Input\" }, { text:\"Output\", options:{ breakLine:true } }]` == 1 line\n\t * - EX: `[{ text:\"Input\\nOutput\" }]` == 2 lines\n\t * - EX: `[{ text:\"Input\", options:{ breakLine:true } }, { text:\"Output\" }]` == 2 lines\n\t */\n\tlet newLine: TableCellInternal[] = []\n\tinputCells.forEach((cell) => {\n\t\tif (typeof cell.text !== 'string') return\n\n\t\tif (cell.text.includes('\\n')) {\n\t\t\t// Each non-last \\n-split part ends with a forced paragraph break; the last\n\t\t\t// part accumulates in newLine so subsequent runs stay on the same paragraph.\n\t\t\tconst parts = cell.text.split('\\n')\n\t\t\tparts.forEach((part, partIdx) => {\n\t\t\t\tconst isLastPart = partIdx === parts.length - 1\n\t\t\t\tif (isLastPart) {\n\t\t\t\t\tnewLine.push(workingCell(part, cell.options))\n\t\t\t\t} else {\n\t\t\t\t\tnewLine.push({\n\t\t\t\t\t\t_type: SlideObjectType.tablecell,\n\t\t\t\t\t\ttext: part,\n\t\t\t\t\t\toptions: { ...cell.options, breakLine: true },\n\t\t\t\t\t})\n\t\t\t\t\tinputLines1.push(newLine)\n\t\t\t\t\tnewLine = []\n\t\t\t\t}\n\t\t\t})\n\t\t} else {\n\t\t\tnewLine.push(workingCell(cell.text.trim(), cell.options))\n\t\t}\n\n\t\tif (cell.options?.breakLine) {\n\t\t\tif (verbose) console.log(`inputCells: new line > ${JSON.stringify(newLine)}`)\n\t\t\tinputLines1.push(newLine)\n\t\t\tnewLine = []\n\t\t}\n\t})\n\t// Flush remaining buffer after all cells are processed\n\tif (newLine.length > 0) {\n\t\tinputLines1.push(newLine)\n\t\tnewLine = []\n\t}\n\tif (verbose) {\n\t\tconsole.log(`[2/4] inputLines1 (${inputLines1.length})`)\n\t\tinputLines1.forEach((line, idx) => console.log(`[2/4] [${idx + 1}] line: ${JSON.stringify(line)}`))\n\t}\n\n\t// STEP 3: Tokenize every text object into words. All runs of one logical paragraph\n\t// are flattened into a single token list so step 4 tracks column position across\n\t// styled-run boundaries (fixes independent-reset bug for rich-text cells).\n\tinputLines1.forEach((line) => {\n\t\tconst lineTokens: TableCellInternal[] = []\n\t\tline.forEach((cell) => {\n\t\t\tconst cellTextStr = String(cell.text) // force convert to string (compiled JS is better with this than a cast)\n\t\t\tconst lineWords = cellTextStr.split(' ')\n\n\t\t\tlineWords.forEach((word, idx) => {\n\t\t\t\tconst cellProps = { ...cell.options }\n\t\t\t\t// IMPORTANT: Handle `breakLine` prop - we cannot apply to each word - only apply to very last word!\n\t\t\t\tif (cellProps?.breakLine) cellProps.breakLine = idx + 1 === lineWords.length\n\t\t\t\tlineTokens.push({\n\t\t\t\t\t_type: SlideObjectType.tablecell,\n\t\t\t\t\ttext: word + (idx + 1 < lineWords.length ? ' ' : ''),\n\t\t\t\t\toptions: cellProps,\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\t\tinputLines2.push(lineTokens)\n\t})\n\tif (verbose) {\n\t\tconsole.log(`[3/4] inputLines2 (${inputLines2.length})`)\n\t\tinputLines2.forEach((line) => console.log(`[3/4] line: ${JSON.stringify(line)}`))\n\t}\n\n\t// STEP 4: Group cells/words into lines based upon space consumed by word letters\n\tinputLines2.forEach((line) => {\n\t\tlet lineCells: TableCellInternal[] = []\n\t\tlet strCurrLine = ''\n\n\t\tline.forEach((word) => {\n\t\t\tconst wordText = String(word.text || '')\n\t\t\t// A: create new line when horizontal space is exhausted.\n\t\t\t// `lineCells.length > 0` is the same guard the flush below carries, and for the same\n\t\t\t// reason: on the first word `strCurrLine` is `''`, so a word wider than the column on\n\t\t\t// its own fires this branch with nothing buffered and used to push an EMPTY line. The\n\t\t\t// cell's text survived -- the pager concatenates lines back together -- but its height\n\t\t\t// did not, because `_lines.length` is what prices the row. Twelve single-word rows in a\n\t\t\t// 0.4in column paged onto two slides when the word was long and one when it was short.\n\t\t\t// The word still overflows its column: nothing here breaks inside a word, which is the\n\t\t\t// stated behaviour rather than a gap (`docs/contributing/design/tables.md`). A hard\n\t\t\t// break would have to land at the `CPL` estimate, which is not where the renderer wraps,\n\t\t\t// and would then have to keep `_lines.length` and the emitted text in step -- the exact\n\t\t\t// pairing the phantom-line bug above got wrong.\n\t\t\tif (strCurrLine.length + wordText.length > CPL) {\n\t\t\t\tif (lineCells.length > 0) parsedLines.push(lineCells)\n\t\t\t\tlineCells = []\n\t\t\t\tstrCurrLine = ''\n\t\t\t}\n\n\t\t\t// B: add current word to line cells\n\t\t\tlineCells.push(word)\n\n\t\t\t// C: add current word to `strCurrLine` which we use to keep track of line's char length\n\t\t\tstrCurrLine += wordText\n\t\t})\n\n\t\t// Flush buffer: Only create a line when there's text to avoid empty row\n\t\tif (lineCells.length > 0) parsedLines.push(lineCells)\n\t})\n\tif (verbose) {\n\t\tconsole.log(`[4/4] parsedLines (${parsedLines.length})`)\n\t\tparsedLines.forEach((line, idx) => console.log(`[4/4] [Line ${idx + 1}]:\\n${JSON.stringify(line)}`))\n\t\tconsole.log('...............................................\\n\\n')\n\t}\n\n\t// Done:\n\treturn parsedLines\n}\n\n/**\n * The font size in points one auto-paged cell is measured at: the cell's own `fontSize`,\n * else the table's, else the library default. Pass `null` for the cell to ask the same\n * question of the table alone.\n */\nfunction resolveCellFontSize(\n\tcellOpts: TableCellProps | undefined | null,\n\ttableOpts: TableToSlidesPropsInternal\n): number {\n\tconst size = cellOpts?.fontSize ?? tableOpts.fontSize\n\treturn typeof size === 'number' ? size : DEF_FONT_SIZE\n}\n\n/**\n * The `autoPageCharWeight` a cell wraps at: its own, else the table's, else none.\n *\n * The sibling of {@link resolveCellFontSize}, and named for the same reason -- the two call\n * sites of {@link parseTextToLines} had resolved this one differently. The row-height probe\n * read the cell's own value; the main loop stamped the table's over it first, and `delete`d the\n * cell's when the table stated none, so a weight set on a cell alone was accepted and dropped.\n * The precedence here is the one every other paired option in this codebase uses.\n * @param cellOpts - the cell's own options, if any\n * @param tableOpts - the table's options\n */\nfunction resolveCellCharWeight(\n\tcellOpts: TableCellProps | undefined | null,\n\ttableOpts: TableToSlidesPropsInternal\n): number {\n\tconst weight = cellOpts?.autoPageCharWeight ?? tableOpts.autoPageCharWeight\n\treturn typeof weight === 'number' ? weight : 0\n}\n\n// ===== Auto-page engine =====\n// The in-memory core (fully Node-testable). Internally signposted by the\n// `// STEP 1..7` markers below: margins → column count → widths → the main\n// row-iteration/overflow loop (STEP 6) → final-slide flush (STEP 7).\n\n/**\n * The largest top and bottom cell margin in one row, in EMU.\n *\n * A cell's own `margin` wins over the table's when it states one, and a stated `0` counts as\n * stating one. Both sites that read this gated on truthiness and on `Array.isArray`, so a cell\n * asking for `margin: [0, …]` fell through to the table's margin instead of taking its own, and\n * a scalar `margin: 0.2` was not seen at all -- while the emitter broadcasts a scalar to four\n * sides. `resolveCellMarginsInches` is the resolver the emitter itself reads.\n * @param row - the row's cells\n * @param tableProps - the table's options, for the fallback margin\n * @returns the row's top and bottom margin allowance in EMU\n */\nfunction rowMarginsEmu(\n\trow: TableRowInternal,\n\ttableProps: TableToSlidesPropsInternal\n): { topEmu: number; btmEmu: number } {\n\tlet topEmu = 0\n\tlet btmEmu = 0\n\trow.forEach((cell) => {\n\t\tconst stated = cell?.options?.margin ?? tableProps.margin\n\t\tif (stated === undefined || stated === null) return\n\t\tconst [top, , btm] = resolveCellMarginsInches(stated)\n\t\tif (marginToEmu(top) > topEmu) topEmu = marginToEmu(top)\n\t\tif (marginToEmu(btm) > btmEmu) btmEmu = marginToEmu(btm)\n\t})\n\treturn { topEmu, btmEmu }\n}\n\n/** One row, measured: each cell's wrapped lines and what the row costs a page. */\ninterface MeasuredRow {\n\t/** One working cell per source cell, in row order, carrying its lines and its line height. */\n\tcells: AutoPageCell[]\n\t/** The row's tallest top margin plus its tallest bottom margin, in EMU. */\n\tmarginsEmu: number\n\t/** The tallest line height among the cells that do not span rows, in EMU. */\n\tlineHeightEmu: number\n\t/** The whole row: its margins plus its tallest cell's line count at `lineHeightEmu`. */\n\theightEmu: number\n}\n\n/**\n * Takes an array of table rows and breaks into an array of slides, which contain the calculated amount of table rows that fit on that slide\n * @param {TableCellInternal[][]} tableRows - table rows\n * @param {TableToSlidesPropsInternal} tableProps - table2slides properties\n * @param {PresLayout} presLayout - presentation layout\n * @param {SlideLayoutInternal} masterSlide - master slide\n * @return {TableRowSlide[]} array of table rows\n */\nexport function getSlidesForTableRows(\n\trows: TableCellInternal[][] = [],\n\ttableProps: TableToSlidesPropsInternal = {},\n\tpresLayout: PresLayout,\n\tmasterSlide?: SlideLayoutInternal | null\n): TableRowSlide[] {\n\t// `MAX_TABLE_SPAN` guards the two allocations a span decides, and its own module says it\n\t// covers both paths -- but `tableToSlides` reaches this function directly, without the\n\t// definer that applies the check, and its own `gridSpan` has no ceiling. So a\n\t// `colspan=\"4000000000\"` in a source table reached the column walk and the per-column depth\n\t// array, which is the allocation that takes the host process down with no exception to catch.\n\t// Checking here rather than at the call site keeps the one entry point guarded whoever calls\n\t// it; a grid whose spans are all fine is passed through by identity.\n\tconst tableRows = withCheckedSpans(rows)\n\tlet arrInchMargins = DEF_SLIDE_MARGIN_IN\n\tlet emuSlideTabW: number\n\tlet colWidthsIn: number[] = []\n\tlet emuSlideTabH = EMU_PER_INCH * 1\n\tlet emuTabCurrH = 0\n\tlet numCols = 0\n\tlet warnedNoTabH = false\n\tconst tableRowSlides: TableRowSlide[] = []\n\tconst tablePropX = getSmartParseNumber(tableProps.x, 'X', presLayout)\n\tconst tablePropY = getSmartParseNumber(tableProps.y, 'Y', presLayout)\n\tconst tablePropW = getSmartParseNumber(tableProps.w, 'X', presLayout)\n\tconst tablePropH = getSmartParseNumber(tableProps.h, 'Y', presLayout)\n\tlet tableCalcW: number = tablePropW\n\n\t/**\n\t * Where this page's table starts, in EMU from the top of the slide.\n\t *\n\t * There used to be three rules for two cases. The first page and \"every page after it\"\n\t * were handled together, then a block gated on `tableRowSlides.length > 1` overrode the\n\t * result -- so despite its own comment it began on the THIRD page, and its first arm\n\t * recomputed exactly what had just been computed. Page 2 therefore got a different usable\n\t * height from pages 3 and up: with `y` above the top margin and an explicit `h`, a\n\t * 60-row table paged 9 / 7 / 9 / 9 / 9 / 9 / 8, which is the same \"pages disagree about\n\t * how many identical rows fit\" symptom the margin-reset note in `calcSlideTabH` records.\n\t *\n\t * It is a function rather than two expressions because the too-small-height fallback in\n\t * `calcSlideTabH` had spelled the continuation arm its own way and drifted the same way\n\t * twice over: `autoPageSlideStartY || margin` discarded an explicit `0` that the main rule\n\t * honoured, and the `Math.min` clause below was missing outright. Two readings of one rule\n\t * is what the paragraph above is about; there is now one.\n\t */\n\tfunction startYEmu(): number {\n\t\t// A stated `y: 0` is the top edge of the slide, not a missing `y`: tested for truthiness, it\n\t\t// was budgeted from the top margin while `addTable` placed the page at 0.\n\t\tconst statedY = tableProps.y !== undefined && tableProps.y !== null\n\t\tif (tableRowSlides.length === 0) return statedY ? tablePropY : inch2Emu(arrInchMargins[0])\n\t\tif (typeof tableProps.autoPageSlideStartY === 'number') return inch2Emu(tableProps.autoPageSlideStartY)\n\t\t// RULE: after the first page the table starts at the top margin rather than at its\n\t\t// own `y` -- unless `y` is ABOVE the margin, in which case paging must not push the\n\t\t// table down and lose the space. Whichever is higher on the slide wins.\n\t\treturn inch2Emu(statedY ? Math.min(tablePropY / EMU_PER_INCH, arrInchMargins[0]) : arrInchMargins[0])\n\t}\n\n\tfunction calcSlideTabH(): void {\n\t\tconst emuStartY = startYEmu()\n\t\temuSlideTabH = (tablePropH || presLayout.height) - emuStartY - inch2Emu(arrInchMargins[2])\n\t\t// EXPLICIT-H FIX: an explicit `h` is the table's height (an extent), not a bottom\n\t\t// coordinate, so -- unlike `presLayout.height` -- the start-Y must not be subtracted from\n\t\t// it. Otherwise a table that begins mid-slide gets a tiny page while the pages that do\n\t\t// clamp to `h` render normally. Applied on every page: the floor used to reach the first\n\t\t// page and pages three and up, leaving page two as the one that could shrink below `h`.\n\t\tif (tablePropH && emuSlideTabH < tablePropH) emuSlideTabH = tablePropH\n\n\t\t// GUARD: a non-positive height, or one too small to fit even a single line of the base font,\n\t\t// means no row ever fits. That previously emitted degenerate empty overflow pages (rows:[]),\n\t\t// which made the recursive addTable throw \"Array expected\", or — with `h` smaller than one\n\t\t// line — placed one row per slide forever. Ignore the unusable height, fall back to the full\n\t\t// slide area between margins, and warn once rather than emit a broken table.\n\t\tconst emuBaseLineH = autoPageLineHeightEmu(\n\t\t\tresolveCellFontSize(null, tableProps),\n\t\t\ttableProps.autoPageLineWeight || 0\n\t\t)\n\t\tif (emuSlideTabH < emuBaseLineH) {\n\t\t\tconst fallbackH = presLayout.height - startYEmu() - inch2Emu(arrInchMargins[2])\n\t\t\tif (!warnedNoTabH) {\n\t\t\t\twarn(\n\t\t\t\t\t'table/autopage-height-too-small',\n\t\t\t\t\t'addTable/autoPage: the table height (`h`) leaves no room to paginate; ignoring it and using the slide height. Increase `h` or decrease `y`.'\n\t\t\t\t)\n\t\t\t\twarnedNoTabH = true\n\t\t\t}\n\t\t\temuSlideTabH = fallbackH > 0 ? fallbackH : presLayout.height\n\t\t}\n\t}\n\n\tif (tableProps.verbose) {\n\t\tconsole.log('[[VERBOSE MODE]]')\n\t\tconsole.log('|-- TABLE PROPS --------------------------------------------------------|')\n\t\tconsole.log(`| presLayout.width ................................ = ${(presLayout.width / EMU_PER_INCH).toFixed(1)}`)\n\t\tconsole.log(\n\t\t\t`| presLayout.height ............................... = ${(presLayout.height / EMU_PER_INCH).toFixed(1)}`\n\t\t)\n\t\tconsole.log(\n\t\t\t`| tableProps.x .................................... = ${typeof tableProps.x === 'number' ? (tableProps.x / EMU_PER_INCH).toFixed(1) : tableProps.x}`\n\t\t)\n\t\tconsole.log(\n\t\t\t`| tableProps.y .................................... = ${typeof tableProps.y === 'number' ? (tableProps.y / EMU_PER_INCH).toFixed(1) : tableProps.y}`\n\t\t)\n\t\tconsole.log(\n\t\t\t`| tableProps.w .................................... = ${typeof tableProps.w === 'number' ? (tableProps.w / EMU_PER_INCH).toFixed(1) : tableProps.w}`\n\t\t)\n\t\tconsole.log(\n\t\t\t`| tableProps.h .................................... = ${typeof tableProps.h === 'number' ? (tableProps.h / EMU_PER_INCH).toFixed(1) : tableProps.h}`\n\t\t)\n\t\tconsole.log(\n\t\t\t`| tableProps.slideMargin .......................... = ${tableProps.slideMargin ? String(tableProps.slideMargin) : ''}`\n\t\t)\n\t\tconsole.log(`| tableProps.margin ............................... = ${String(tableProps.margin)}`)\n\t\tconsole.log(`| tableProps.colW ................................. = ${String(tableProps.colW)}`)\n\t\tconsole.log(`| tableProps.autoPageSlideStartY .................. = ${tableProps.autoPageSlideStartY}`)\n\t\tconsole.log(`| tableProps.autoPageCharWeight ................... = ${tableProps.autoPageCharWeight}`)\n\t\tconsole.log('|-- CALCULATIONS -------------------------------------------------------|')\n\t\tconsole.log(`| tablePropX ...................................... = ${tablePropX / EMU_PER_INCH}`)\n\t\tconsole.log(`| tablePropY ...................................... = ${tablePropY / EMU_PER_INCH}`)\n\t\tconsole.log(`| tablePropW ...................................... = ${tablePropW / EMU_PER_INCH}`)\n\t\tconsole.log(`| tablePropH ...................................... = ${tablePropH / EMU_PER_INCH}`)\n\t\tconsole.log(`| tableCalcW ...................................... = ${tableCalcW / EMU_PER_INCH}`)\n\t}\n\n\t// STEP 1: Calculate margins\n\t{\n\t\t// The caller's value goes through unaltered, including an absent one: `resolveSlideMarginsInches`\n\t\t// owns all three tiers, and defaulting to `DEF_SLIDE_MARGIN_IN[0]` here handed it a stated\n\t\t// caller margin that no caller had stated, which suppressed the master's own `margin`.\n\t\tarrInchMargins = resolveSlideMarginsInches(masterSlide?._margin, tableProps.slideMargin)\n\n\t\tif (tableProps.verbose)\n\t\t\tconsole.log(`| arrInchMargins .................................. = [${arrInchMargins.join(', ')}]`)\n\t}\n\n\t// STEP 2: Calculate number of columns\n\t{\n\t\tnumCols = tableColCount(tableRows)\n\t\tif (tableProps.verbose) console.log(`| numCols ......................................... = ${numCols}`)\n\t}\n\n\t// Where every cell actually lands. The pager asks the grid two questions -- which columns a\n\t// cell spans, so its text is wrapped against the right width, and whether a rowspan opened\n\t// on an earlier row is still open here, so a page break does not split a merged group -- and\n\t// it used to answer both with its own occupancy array, once forwards through the row and\n\t// once again after it. `walkTableGrid` is the traversal the measured-fit pass and the\n\t// emitter's own grid build follow, so the widths this pager wraps against are the widths the\n\t// cells are finally given.\n\tconst placements: GridPlacement[][] = tableRows.map(() => [])\n\t/**\n\t * How many of each row's grid columns are held by a rowspan opened ABOVE it, accumulated as\n\t * the placements arrive rather than searched for afterwards.\n\t *\n\t * The question used to be answered by scanning every placement in the table, once per row,\n\t * which is quadratic in a table of any width. Two columns of short text and no spans at all:\n\t * 1000 rows took 55ms, 2000 took 115ms, 4000 took 333ms and 8000 took 1036ms. The same four\n\t * now take 24ms, 19ms, 40ms and 83ms -- so it was pure overhead, paid in full by the long\n\t * report table that is the whole reason this code exists.\n\t *\n\t * Filling forward instead is bounded by the placement's own `rowSpan`, so the total work is\n\t * the sum of all rowspans. That is safe to expand without a further check because\n\t * `walkTableGrid` has already clamped each `rowSpan` to `rows.length - r`: a span cannot\n\t * reach past the last row however large the caller wrote it, so the sum is bounded by the\n\t * grid rather than by anything the caller states.\n\t *\n\t * The fill starts at `row + 1`. A `rowSpan` of 1 must contribute nothing -- starting at\n\t * `row` would have every ordinary row counting itself as covered, and the\n\t * `coveredFromAbove(iRow) === numCols` reader below would then fire on all of them.\n\t */\n\tconst coveredCols: number[] = Array.from({ length: tableRows.length }, () => 0)\n\tfor (const placement of walkTableGrid(tableRows, numCols)) {\n\t\tplacements[placement.row]?.push(placement)\n\t\tconst last = Math.min(placement.row + placement.rowSpan, coveredCols.length)\n\t\tfor (let r = placement.row + 1; r < last; r++) coveredCols[r] = (coveredCols[r] ?? 0) + placement.colSpan\n\t}\n\t/** How many of `iRow`'s grid columns are held by a rowspan opened above it. */\n\tconst coveredFromAbove = (iRow: number): number => coveredCols[iRow] ?? 0\n\t/** Whether a rowspan opened above `iRow` is still covering it. */\n\tconst spannedFromAbove = (iRow: number): boolean => coveredFromAbove(iRow) > 0\n\n\t// STEP 3: Calculate width using tableProps.colW if possible. Only an array reaches here:\n\t// `addTableDefinition` turns a single `colW` into `w` before paging, and `tableToSlides` always\n\t// passes one width per column.\n\tif (!tablePropW && Array.isArray(tableProps.colW)) {\n\t\t// The `0` seed is what `colW: []` needs: an empty array is truthy, so it reached an\n\t\t// unseeded `reduce` and threw a raw `TypeError` — a failure this library did not raise as\n\t\t// a `TsPptxError`. Seeded, it totals `0`, which falls through to `usableTableWidthEmu`\n\t\t// exactly where `colW: undefined` lands. That is the reading intended: an empty array is a\n\t\t// caller stating no columns, not a table of width zero.\n\t\ttableCalcW = tableProps.colW.reduce((p, n) => p + n, 0) * EMU_PER_INCH\n\t\tif (tableProps.verbose)\n\t\t\tconsole.log(`| tableCalcW ...................................... = ${tableCalcW / EMU_PER_INCH}`)\n\t}\n\n\t// STEP 4: Calculate usable width now that total usable space is known (`emuSlideTabW`)\n\t{\n\t\temuSlideTabW = tableCalcW || usableTableWidthEmu(presLayout, tablePropX, arrInchMargins)\n\t\tif (tableProps.verbose)\n\t\t\tconsole.log(`| emuSlideTabW .................................... = ${(emuSlideTabW / EMU_PER_INCH).toFixed(1)}`)\n\t}\n\n\t// STEP 5: Resolve the column grid. `resolveTableColWidthsEmu` is the same resolver the\n\t// table emitter and the measured-fit pass read, so the widths this pager wraps text\n\t// against are the widths the emitted `<a:gridCol>`s carry. It also normalizes the array\n\t// to `numCols`: a short `colW` used to leave the trailing columns measuring against a\n\t// zero width. Inches, because that is the unit each paged table's `colW` takes; the grid\n\t// rides out on every `TableRowSlide` rather than being written back onto the caller's bag.\n\tcolWidthsIn = resolveTableColWidthsEmu(tableProps.colW, emuSlideTabW, numCols).map(\n\t\t(emu: number) => emu / EMU_PER_INCH\n\t)\n\n\t// Resolve a row's explicit height (inches) from the original `rowH` *array*, keyed by original\n\t// row index. A single-number `rowH` is left to propagate via table options (it applies uniformly,\n\t// so it needs no per-row remapping); only the array form is index-sensitive after pagination.\n\t// Whether a slot pins its row is `pinnedRowHeightInches`, the same rule the writer applies to\n\t// the array this builds — a `0` accepted here and rejected there is how the two readings drift.\n\tconst resolveRowH = (origRowIdx: number): number | undefined =>\n\t\tArray.isArray(tableProps.rowH) ? (pinnedRowHeightInches(tableProps.rowH[origRowIdx]) ?? undefined) : undefined\n\n\t/**\n\t * Wrap each of row `iRow`'s cells against the grid columns it covers, and price the row.\n\t *\n\t * The one row measure. The repeated header rows used to be priced by a second copy of it with its\n\t * own column cursor, which ignored the columns a rowspan holds -- the fault `walkTableGrid`\n\t * fixed for the main loop -- and skipped the line-height exemption for a cell that spans rows,\n\t * so a header row inside a rowspan was measured against the wrong columns.\n\t * @param iRow - the row's index in `tableRows`\n\t * @param verbose - dump the wrapping stages, as `addTable({ verbose })` asks\n\t */\n\tfunction measureRow(iRow: number, verbose?: boolean): MeasuredRow {\n\t\tconst row = tableRows[iRow] ?? []\n\t\tconst { topEmu, btmEmu } = rowMarginsEmu(row, tableProps)\n\t\t// Cells are keyed to grid columns, not to their position in the row: a colspan earlier in\n\t\t// the row shifts every later cell, and a rowspan opened above skips columns entirely.\n\t\t// Measuring a cell against `colW[iCell]` wrapped its text to another column's width.\n\t\tconst rowPlacements = placements[iRow] ?? []\n\t\tconst cells = row.map((cell, iCell): AutoPageCell => {\n\t\t\t// A row longer than the grid runs off the end of it: those cells are placed nowhere\n\t\t\t// and measure against no column, which is what the cursor did by clamping.\n\t\t\tconst placed = rowPlacements[iCell]\n\t\t\tconst colStart = placed ? placed.col : numCols\n\t\t\tconst cellColspan = placed ? placed.colSpan : resolveSpan(cell.options?.colspan, 'colspan')\n\t\t\t// A spanning cell is as wide as the columns it covers; the seed keeps a row longer than\n\t\t\t// the grid from throwing on an empty slice.\n\t\t\tconst totalColW = colWidthsIn.slice(colStart, colStart + cellColspan).reduce((prev, curr) => prev + curr, 0)\n\t\t\tconst fontSizePt = resolveCellFontSize(cell.options, tableProps)\n\t\t\treturn {\n\t\t\t\t_type: SlideObjectType.tablecell,\n\t\t\t\t_lines: parseTextToLines(cell, totalColW, fontSizePt, resolveCellCharWeight(cell.options, tableProps), verbose),\n\t\t\t\t// A cell that spans rows adds no line height to this one (or a page could break where\n\t\t\t\t// nothing needed it to). The grid's clamped span decides, not the option: `rowspan: 1`\n\t\t\t\t// is a valid \"no span\" that `withCheckedSpans` passes through, and testing the option\n\t\t\t\t// priced every such row at its margins alone.\n\t\t\t\t_lineHeight:\n\t\t\t\t\tplaced && placed.rowSpan > 1 ? 0 : autoPageLineHeightEmu(fontSizePt, tableProps.autoPageLineWeight || 0),\n\t\t\t\ttext: [],\n\t\t\t\toptions: cell.options || {},\n\t\t\t}\n\t\t})\n\t\tconst lineHeightEmu = cells.reduce((max, cell) => Math.max(max, cell._lineHeight), 0)\n\t\tconst maxLines = cells.reduce((max, cell) => Math.max(max, cell._lines.length), 0)\n\t\tconst marginsEmu = topEmu + btmEmu\n\t\treturn { cells, marginsEmu, lineHeightEmu, heightEmu: marginsEmu + maxLines * lineHeightEmu }\n\t}\n\n\t// What the repeated header rows cost a continuation page. Computed once: the rows and the\n\t// grid are the same on every page, so re-measuring per page would only be slower. Both callers\n\t// pass the header rows as the leading rows of `tableRows`, so each is measured at its own index,\n\t// against the grid placements the body rows use.\n\tconst repeatHeaderRows =\n\t\ttableProps.autoPageRepeatHeader && tableProps._arrObjTabHeadRows ? tableProps._arrObjTabHeadRows : []\n\tconst repeatHeaderHeightsEmu = repeatHeaderRows.map((_row, headIdx) => measureRow(headIdx).heightEmu)\n\n\t/**\n\t * The last row of the rowspan group that row `iRow` opens: the furthest row any of its spans\n\t * reaches, extended by every span a covered row opens in turn. `walkTableGrid` has clamped each\n\t * span to the table, so the walk ends inside it.\n\t * @param iRow - the row that opens the group\n\t */\n\tfunction rowSpanGroupEnd(iRow: number): number {\n\t\tlet end = iRow\n\t\tfor (let r = iRow; r <= end; r++) {\n\t\t\tfor (const placement of placements[r] ?? []) end = Math.max(end, r + placement.rowSpan - 1)\n\t\t}\n\t\treturn end\n\t}\n\n\t// STEP 6: **MAIN** Iterate over rows, add table content, create new slides as rows overflow\n\tlet newTableRowSlide: TableRowSlide = {\n\t\trows: [] as TableRowInternal[],\n\t\trowH: [] as Array<number | undefined>,\n\t\tcolW: colWidthsIn,\n\t\ty: startYEmu() / EMU_PER_INCH,\n\t}\n\t/** Rows placed on the working page other than its repeated header rows. */\n\tlet bodyRowsOnPage = 0\n\tlet warnedTallRowSpan = false\n\n\t/**\n\t * Close the working page and open the next: push the page when it has rows, re-derive the page\n\t * height, charge `chargedEmu` to the new page, then repeat the header rows onto it.\n\t * @param chargedEmu - what the new page already owes before its header rows: the margins of a\n\t * row that is starting over here, or nothing\n\t */\n\tfunction startNewPage(chargedEmu: number): void {\n\t\t// Never push an empty page: a row that does not fit yet has no content here, and an empty\n\t\t// `rows` slide crashes the recursive addTable.\n\t\tif (newTableRowSlide.rows.length > 0) tableRowSlides.push(newTableRowSlide)\n\t\t// Decided after the push: the page just closed is what makes this one a continuation.\n\t\tnewTableRowSlide = {\n\t\t\trows: [],\n\t\t\trowH: [] as Array<number | undefined>,\n\t\t\tcolW: colWidthsIn,\n\t\t\ty: startYEmu() / EMU_PER_INCH,\n\t\t}\n\t\tbodyRowsOnPage = 0\n\t\t// The page height depends on which page this is, so it is re-derived for the new one.\n\t\tcalcSlideTabH()\n\t\t// ORDER IS LOAD-BEARING. The charge used to be added and then wiped by the reset, so the first\n\t\t// row of every continuation slide was the only row in the table that paid no margin. That let\n\t\t// a continuation slide accept one row more than it had room for, and the extra row hung off\n\t\t// the bottom of the slide (upstream gitbrent/PptxGenJS#1200). The symptom is easy to miss\n\t\t// because the pager is *self*-consistent per slide: it only shows up as the first slide and\n\t\t// the continuation slides disagreeing about how many identical rows fit the identical space,\n\t\t// which is what test/regression/table/table-autopage-continuation-budget.test.js pins.\n\t\temuTabCurrH = chargedEmu\n\t\tif (tableProps.verbose)\n\t\t\tconsole.log(\n\t\t\t\t`| SLIDE [${tableRowSlides.length}]: emuSlideTabH ...... = ${(emuSlideTabH / EMU_PER_INCH).toFixed(1)} `\n\t\t\t)\n\t\trepeatHeaderRows.forEach((headRow, headIdx) => {\n\t\t\tnewTableRowSlide.rows.push([...headRow])\n\t\t\t// Repeated header rows are the original leading rows, so carry their configured height.\n\t\t\tnewTableRowSlide.rowH?.push(resolveRowH(headIdx))\n\t\t\temuTabCurrH += repeatHeaderHeightsEmu[headIdx] ?? 0\n\t\t})\n\t}\n\n\ttableRows.forEach((row, iRow) => {\n\t\t// A: Row variables — detect active rowspan at the start of this row so we can\n\t\t// suppress page breaks that would split a rowspan group across slides.\n\t\tconst hasActiveRowSpan = spannedFromAbove(iRow)\n\t\t// B: Create new row in data model\n\t\tlet currTableRow: TableRowInternal = []\n\t\trow.forEach((cell) => currTableRow.push(workingCell([], cell.options)))\n\n\t\t// C: Calc usable vertical space/table height. Set default value first, adjust below when necessary.\n\t\tcalcSlideTabH()\n\t\tif (tableProps.verbose && iRow === 0)\n\t\t\tconsole.log(\n\t\t\t\t`| SLIDE [${tableRowSlides.length}]: emuSlideTabH ...... = ${(emuSlideTabH / EMU_PER_INCH).toFixed(1)} `\n\t\t\t)\n\n\t\t// C-2: A row that opens a rowspan is kept with the rows the span covers. Breaking a page\n\t\t// partway through it left the partial row as the page's last row still carrying `rowSpan`,\n\t\t// so the emitter wrote a `rowSpan=\"2\"` with no row under it -- the state PowerPoint reports\n\t\t// as corrupt. The whole group is priced before any of its lines is taken: when it does not\n\t\t// fit under rows already on the page, the page breaks before it, and a group taller than a\n\t\t// page is emitted whole on a page of its own.\n\t\tconst startsRowSpan = !hasActiveRowSpan && (placements[iRow] ?? []).some((placement) => placement.rowSpan > 1)\n\t\tif (startsRowSpan) {\n\t\t\tlet groupHeightEmu = 0\n\t\t\tfor (let r = iRow; r <= rowSpanGroupEnd(iRow); r++) groupHeightEmu += measureRow(r).heightEmu\n\t\t\tif (bodyRowsOnPage > 0 && emuTabCurrH + groupHeightEmu > emuSlideTabH) startNewPage(0)\n\t\t\tif (emuTabCurrH + groupHeightEmu > emuSlideTabH && !warnedTallRowSpan) {\n\t\t\t\twarn(\n\t\t\t\t\t'table/autopage-rowspan-too-tall',\n\t\t\t\t\t'addTable/autoPage: a group of rows joined by a rowspan is taller than a page; it is kept on one page and runs past its bottom. Reduce the span or the text in it.'\n\t\t\t\t)\n\t\t\t\twarnedTallRowSpan = true\n\t\t\t}\n\t\t}\n\t\tconst keepRowTogether = hasActiveRowSpan || startsRowSpan\n\n\t\t// D: --==[[ BUILD DATA SET ]]==-- (split each cell's text into lines, set its line height)\n\t\tconst {\n\t\t\tcells: rowCellLines,\n\t\t\tmarginsEmu: rowMarginsTotalEmu,\n\t\t\tlineHeightEmu: emuLineMaxH,\n\t\t} = measureRow(iRow, tableProps.verbose)\n\t\temuTabCurrH += rowMarginsTotalEmu // Start row height with margins\n\n\t\t/** E: --==[[ PAGE DATA SET ]]==--\n\t\t * Add text one-line-a-time to this row's cells until: lines are exhausted OR table height limit is hit\n\t\t *\n\t\t * Design:\n\t\t * - Building cells L-to-R/loop style wont work as one could be 100 lines and another 1 line\n\t\t * - Therefore, build the whole row, one-line-at-a-time, across each table columns\n\t\t * - Then, when the vertical size limit is hit is by any of the cells, make a new slide and continue adding any remaining lines\n\t\t *\n\t\t * Implementation:\n\t\t * - `rowCellLines` is an array of cells, one for each column in the table, with each cell containing an array of lines\n\t\t *\n\t\t * Sample Data:\n\t\t * - `rowCellLines` ..: [ TableCellInternal, TableCellInternal, TableCellInternal ]\n\t\t * - `TableCellInternal` .....: { _type: 'tablecell', _lines: TableCellInternal[], _lineHeight: 10 }\n\t\t * - `_lines` ........: [ {_type: 'tablecell', text: 'cell-1,line-1', options: {…}}, {_type: 'tablecell', text: 'cell-1,line-2', options: {…}} }\n\t\t * - `_lines` is TableCellInternal[] (the 1-N words in the line)\n\t\t * {\n\t\t * _lines: [{ text:'cell-1,line-1' }, { text:'cell-1,line-2' }], // TOTAL-CELL-HEIGHT = 2\n\t\t * _lines: [{ text:'cell-2,line-1' }, { text:'cell-2,line-2' }], // TOTAL-CELL-HEIGHT = 2\n\t\t * _lines: [{ text:'cell-3,line-1' }, { text:'cell-3,line-2' }, { text:'cell-3,line-3' }, { text:'cell-3,line-4' }], // TOTAL-CELL-HEIGHT = 4\n\t\t * }\n\t\t *\n\t\t * Example: 2 rows, with the firstrow overflowing onto a new slide\n\t\t * SLIDE 1:\n\t\t * |--------|--------|--------|--------|\n\t\t * | line-1 | line-1 | line-1 | line-1 |\n\t\t * | | | line-2 | |\n\t\t * | | | line-3 | |\n\t\t * |--------|--------|--------|--------|\n\t\t *\n\t\t * SLIDE 2:\n\t\t * |--------|--------|--------|--------|\n\t\t * | | | line-4 | |\n\t\t * |--------|--------|--------|--------|\n\t\t * | line-1 | line-1 | line-1 | line-1 |\n\t\t * |--------|--------|--------|--------|\n\t\t */\n\t\tif (tableProps.verbose) console.log(`\\n| SLIDE [${tableRowSlides.length}]: ROW [${iRow}]: START...`)\n\t\tlet currCellIdx = 0\n\t\tlet isDone = false\n\t\twhile (!isDone) {\n\t\t\tconst srcCell = rowCellLines[currCellIdx]\n\t\t\tif (!srcCell) break\n\t\t\tlet tgtCell = currTableRow[currCellIdx] // NOTE: may be redefined below (a new row may be created, thus changing this value)\n\n\t\t\t// 2: create a new slide if there is insufficient room for the current row,\n\t\t\t// but never break inside a rowspan group — keep spanned rows together.\n\t\t\tif (emuTabCurrH + emuLineMaxH > emuSlideTabH && !keepRowTogether) {\n\t\t\t\tif (tableProps.verbose) {\n\t\t\t\t\tconsole.log('\\n|-----------------------------------------------------------------------|')\n\t\t\t\t\t// prettier-ignore\n\t\t\t\t\tconsole.log(`|-- NEW SLIDE CREATED (currTabH+currLineH > maxH) => ${(emuTabCurrH / EMU_PER_INCH).toFixed(2)} + ${(srcCell._lineHeight / EMU_PER_INCH).toFixed(2)} > ${emuSlideTabH / EMU_PER_INCH}`)\n\t\t\t\t\tconsole.log('|-----------------------------------------------------------------------|\\n\\n')\n\t\t\t\t}\n\n\t\t\t\t// A: add current row slide or it will be lost (only if it has rows and text)\n\t\t\t\tif (\n\t\t\t\t\tcurrTableRow.length > 0 &&\n\t\t\t\t\tcurrTableRow.map((cell) => (Array.isArray(cell.text) ? cell.text.length : 0)).reduce((p, n) => p + n) > 0\n\t\t\t\t) {\n\t\t\t\t\tnewTableRowSlide.rows.push(currTableRow)\n\t\t\t\t\tnewTableRowSlide.rowH?.push(resolveRowH(iRow))\n\t\t\t\t}\n\n\t\t\t\t// B: open the next page. The row is starting over there, so it owes its cell margins\n\t\t\t\t// again.\n\t\t\t\tstartNewPage(rowMarginsTotalEmu)\n\n\t\t\t\t// C: reset working/curr row\n\t\t\t\tcurrTableRow = []\n\t\t\t\trow.forEach((cell) => currTableRow.push(workingCell([], cell.options)))\n\n\t\t\t\ttgtCell = currTableRow[currCellIdx]\n\t\t\t}\n\n\t\t\t// 3: set array of words that comprise this line\n\t\t\tconst currLine = srcCell._lines.shift()\n\n\t\t\t// 4: create new line by adding all words from curr line (or add empty if there are no words to avoid \"needs repair\" issue triggered when cells have null content)\n\t\t\tif (tgtCell && Array.isArray(tgtCell.text)) {\n\t\t\t\tif (currLine) tgtCell.text = tgtCell.text.concat(currLine)\n\t\t\t\telse if (tgtCell.text.length === 0)\n\t\t\t\t\ttgtCell.text = tgtCell.text.concat({ _type: SlideObjectType.tablecell, text: '' })\n\t\t\t\t// IMPORTANT: ^^^ add empty if there are no words to avoid \"needs repair\" issue triggered when cells have null content\n\t\t\t}\n\n\t\t\t// 5: increase table height by the curr line height (if we're on the last column)\n\t\t\tif (currCellIdx === rowCellLines.length - 1) emuTabCurrH += emuLineMaxH\n\n\t\t\t// 6: advance column/cell index (or circle back to first one to continue adding lines)\n\t\t\tcurrCellIdx = currCellIdx < rowCellLines.length - 1 ? currCellIdx + 1 : 0\n\n\t\t\t// 7: WIP: done?\n\t\t\tconst brent = rowCellLines.map((cell) => cell._lines.length).reduce((prev, next) => prev + next)\n\t\t\tif (brent === 0) isDone = true\n\t\t}\n\n\t\t// F: Flush/capture row buffer before it resets at the top of this loop.\n\t\t//\n\t\t// A row that states no cells is kept only when every one of its grid columns is held by a\n\t\t// rowspan from above. That is a real row -- a source row states only the cells it *starts*,\n\t\t// so one entirely covered from above states none at all, which is what `<tr></tr>` between\n\t\t// two spanned rows means -- and the emitter fills it with `vMerge` continuations. Dropping\n\t\t// it moved every later row up one while the emitter went on synthesizing that grid row's\n\t\t// continuations, so they landed in the next row's `<a:tr>`: a 2-column table came out with\n\t\t// a 4-cell row.\n\t\t//\n\t\t// An empty row NOT covered that way is a different thing and is still dropped: nothing\n\t\t// would fill it, and a `<a:tr>` carrying fewer `<a:tc>` than the grid has columns is the\n\t\t// malformation PowerPoint offers to repair.\n\t\tif (currTableRow.length > 0 || (row.length === 0 && coveredFromAbove(iRow) === numCols)) {\n\t\t\tnewTableRowSlide.rows.push(currTableRow)\n\t\t\tnewTableRowSlide.rowH?.push(resolveRowH(iRow))\n\t\t\tbodyRowsOnPage++\n\t\t}\n\n\t\tif (tableProps.verbose) {\n\t\t\tconsole.log(\n\t\t\t\t`- SLIDE [${tableRowSlides.length}]: ROW [${iRow}]: ...COMPLETE ...... emuTabCurrH = ${(emuTabCurrH / EMU_PER_INCH).toFixed(2)} ( emuSlideTabH = ${(\n\t\t\t\t\temuSlideTabH / EMU_PER_INCH\n\t\t\t\t).toFixed(2)} )`\n\t\t\t)\n\t\t}\n\t})\n\n\t// STEP 7: Flush buffer / add final slide (skip an empty trailing buffer; always keep at least\n\t// one slide so a non-empty table is never reduced to zero pages)\n\tif (newTableRowSlide.rows.length > 0 || tableRowSlides.length === 0) tableRowSlides.push(newTableRowSlide)\n\n\tif (tableProps.verbose) {\n\t\tconsole.log('\\n|================================================|')\n\t\tconsole.log(`| FINAL: tableRowSlides.length = ${tableRowSlides.length}`)\n\t\ttableRowSlides.forEach((slide) => console.log(slide))\n\t\tconsole.log('|================================================|\\n\\n')\n\t}\n\n\t// LAST:\n\treturn tableRowSlides\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"binary-string-CKVAYI3M.js","names":[],"sources":["../src/media/binary-string.ts"],"sourcesContent":["/**\n * Raw bytes as a latin1 binary string, one character per byte: what `btoa` takes, and what the\n * `zip` entry's `binarystring` output returns as it is.\n *\n * A module of its own, importing nothing, for the reason `ooxml/pptx-content-type.ts` states: the\n * `zip` entry needs this one function, and imported from `base64.ts` it brought that module's other\n * exports along and pushed the entry past its size budget.\n *\n * Chunked because `String.fromCharCode(...spread)` blows the argument-count limit on a payload\n * of any real size — a multi-megabyte video rel would throw rather than encode.\n * @param {Uint8Array} bytes - the payload\n * @returns {string} one character per byte\n */\nexport function bytesToBinaryString(bytes: Uint8Array): string {\n\tconst CHUNK = 0x8000\n\tlet binary = ''\n\tfor (let i = 0; i < bytes.length; i += CHUNK) binary += String.fromCharCode(...bytes.subarray(i, i + CHUNK))\n\treturn binary\n}\n"],"mappings":";;;;;;;;;;;;;;AAaA,SAAgB,oBAAoB,OAA2B;CAC9D,MAAM,QAAQ;CACd,IAAI,SAAS;CACb,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,OAAO,UAAU,OAAO,aAAa,GAAG,MAAM,SAAS,GAAG,IAAI,KAAK,CAAC;CAC3G,OAAO;AACR"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"body-insets-Dw_BeWD_.js","names":[],"sources":["../src/ooxml/body-insets.ts"],"sourcesContent":["/**\n * PowerPoint's default `a:bodyPr` text insets.\n *\n * ECMA-376 §21.1.2.1.1 states them in prose; the XSD leaves `lIns`/`tIns`/`rIns`/`bIns`\n * optional with no schema default, so a reader that wants to know what an omitted side is\n * inset by has to carry the numbers itself. Four places did, in three units and two orders:\n * the script mapper as a points record, the round-trip canonicaliser as an inches tuple in\n * `[top, right, bottom, left]`, `inspect.ts` as two inch scalars, and the measured-fit\n * solver as two EMU scalars — that last one deciding the inner box every `autoFit` is\n * computed against, so a correction here would have left every fit decision on the old\n * numbers.\n *\n * The canonicaliser's tuple in particular has to be exactly `pointsToInches` of the mapper's\n * record, or `isDefaultMargin` stops matching and every text frame that spells its insets\n * reports four spurious differences. Nothing linked them; this module is the link.\n *\n * It is a fact about the schema, so — like `st-enums.ts` — it belongs to neither `gen/` nor\n * `read/` nor `script/`.\n */\n\nimport { EMU_PER_POINT, POINTS_PER_INCH } from './emu.js'\n\n/** The four default insets in points: 7.2pt (0.1in) left and right, 3.6pt (0.05in) top and bottom. */\nexport const BODY_INSET_DEFAULTS_PT = { left: 7.2, right: 7.2, top: 3.6, bottom: 3.6 } as const\n\n/**\n * The same four in inches, in the write API's `margin` order — `[top, right, bottom, left]`.\n *\n * Derived rather than transcribed, so it cannot drift from {@link BODY_INSET_DEFAULTS_PT}.\n */\nexport const BODY_INSET_DEFAULTS_IN: readonly number[] = [\n\tBODY_INSET_DEFAULTS_PT.top / POINTS_PER_INCH,\n\tBODY_INSET_DEFAULTS_PT.right / POINTS_PER_INCH,\n\tBODY_INSET_DEFAULTS_PT.bottom / POINTS_PER_INCH,\n\tBODY_INSET_DEFAULTS_PT.left / POINTS_PER_INCH,\n]\n\n/**\n * The same four in EMU, which is the unit the measured-fit solver works in.\n *\n * Derived rather than transcribed, for the same reason {@link BODY_INSET_DEFAULTS_IN} is.\n */\nexport const BODY_INSET_DEFAULTS_EMU = {\n\tleft: BODY_INSET_DEFAULTS_PT.left * EMU_PER_POINT,\n\tright: BODY_INSET_DEFAULTS_PT.right * EMU_PER_POINT,\n\ttop: BODY_INSET_DEFAULTS_PT.top * EMU_PER_POINT,\n\tbottom: BODY_INSET_DEFAULTS_PT.bottom * EMU_PER_POINT,\n} as const\n\n/**\n * A table cell's default text insets in EMU. They happen to equal {@link BODY_INSET_DEFAULTS_EMU}.\n * Declared in `table-cell-margins.ts`, which imports nothing, so the write path's inch defaults can\n * derive from it without bringing this module along.\n */\nexport { TABLE_CELL_MARGIN_DEFAULTS_EMU } from './table-cell-margins.js'\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAuBA,MAAa,yBAAyB;CAAE,MAAM;CAAK,OAAO;CAAK,KAAK;CAAK,QAAQ;AAAI;;;;;;AAOrF,MAAa,yBAA4C;CACxD,uBAAuB,MAAA;CACvB,uBAAuB,QAAA;CACvB,uBAAuB,SAAA;CACvB,uBAAuB,OAAA;AACxB;;;;;;AAOA,MAAa,0BAA0B;CACtC,MAAM,uBAAuB,OAAO;CACpC,OAAO,uBAAuB,QAAQ;CACtC,KAAK,uBAAuB,MAAM;CAClC,QAAQ,uBAAuB,SAAS;AACzC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"clip-Bl01BPcN.d.ts","names":[],"sources":["../src/ooxml/emu.ts","../src/clip.ts"],"mappings":";;;;;;;;;;;cAUa;;cAEA;;cAEA;;;;;;;KCgBD;;;;;;;KAQA;;KAGA;;;;;;EAKT;EAAmB,MAAM;EAAU,SAAS;;;;;;;;;;;;;;;;;;;;;;;;iBAyH/B,SAAS,OAAO,WAAW,WAAW,YAAY"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"diagnostics-D8ot4Ei7.d.ts","names":[],"sources":["../src/codes.ts","../src/errors.ts","../src/diagnostics.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAgCY;;;;;;;KA8KA;;;;;;KAwKA;;;;;;KAwBA;;;;;;;KAkCA;;;;;;KAwBA;;;;;;;;;;;;;;KAiEA,YACT,yBACA,8BACA,uBACA,iBACA;;KAGS,aAAa,iBAAiB;;;;UCrezB,2BAA2B;;;;;WAKlC,SAAS,SAAS;;;;;;;;;cAUf,oBAAoB;;WAEvB,MAAM;;WAGN,SAAS,SAAS;;;;;;EAO3B,YAAY,MAAM,WAAW,iBAAiB,UAAU;;;;;;;;;;cAmB5C,2BAA2B;WACtB,MAAM;EACvB,YAAY,MAAM,wBAAwB,iBAAiB,UAAU;;;;;;;;;;;cAczD,gCAAgC;WAC3B,MAAM;EACvB,YAAY,MAAM,6BAA6B,iBAAiB,UAAU;;;;;;;;;;cAa9D,yBAAyB;WACpB,MAAM;EACvB,YAAY,MAAM,sBAAsB,iBAAiB,UAAU;;;;;;;;;cAYvD,mBAAmB;WACd,MAAM;EACvB,YAAY,MAAM,gBAAgB,iBAAiB,UAAU;;;;;;;;;;;;;;;;;;;cAkCjD,sBAAsB;WACjB,MAAM;EACvB,YAAY,MAAM,mBAAmB,iBAAiB,UAAU;;;;;UCzJhD;;WAEP,MAAM;;WAEN;;;;;;;;;;;WAWA,SAAS,SAAS;;;KAIhB,qBAAqB,YAAY;;;;;;;;;;;;;;;;;;;;;;;iBAkC7B,qBAAqB,MAAM;;;;;;;;;;;;;;;;;iBAwD3B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"embedded-fonts-DarT9aoa.d.ts","names":[],"sources":["../src/embedded-fonts.ts"],"mappings":";;KAyCY,2BAA2B;;UAGtB;EAChB,MAAM;EACN,QAAQ;;;UAIQ;;EAEhB;EACA;EACA;EACA;EACA,OAAO"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"entry-compose-DCnvBZz2.d.ts","names":[],"sources":["../src/runtime/types.ts","../src/units.ts","../src/gen/oxml/el.ts","../src/gen/slide/objects/shared.ts","../src/gen/opc/content-types.ts","../src/package/parts/shared.ts","../src/slide.ts","../src/families/shared.ts","../src/presentation.ts","../src/gen/slide/objects/text.ts","../src/gen/slide/objects/image.ts","../src/families/core.ts","../src/entry-compose.ts"],"mappings":";;;;;;;;;KAIY;WACF,qBAAqB;;;;;;;;;;;;EAY9B,YAAY,KAAK;IAAkB;QAAmB;;;;;;;;;EAStD,sBAAsB,KAAK,kBAAkB,QAAQ;EACrD,YAAY,kBAAkB,eAAe,cAAc,OAAO,eAAe;;;;;;;EAOjF,eAAe,mBAAmB,QAAQ;;;;;;;;;cClB9B;;;;;;cAOA;;;;;;;cAQA;;;;;;cAOA;;;;;iBAMG,eAAe;;;;;;;;;KAanB;WAA0B;;;;cASzB;;;;;cAMA;;cAGA;KAED;UAEK;;WAEP,QAAQ;;WAER;;WAEA;;WAEA;;WAEA;;WAEA;;iBAGM,YAAY,iBAAiB;iBAK7B,YAAY,iBAAiB;iBAK7B,YAAY,gBAAgB,cAAc;;;;;;;;;;;;;iBAkB1C,aAAa,iBAAiB,kBAAkB;;;;;;;;;;;;;;;iBAoBhD,WAAW,wBAAwB,kBAAkB;iBAoCrD,YAAY;;;;;;;;;;;;;;;;;;;;iBAwBZ,YAAY;;;;;;;;;iBAaZ,YAAY,aAAa;cAiB5B,kBAAkB,SAAS,OAAO,oBAAoB;;;;KC7LvD,WAAW;;;;;;;;;;;;;;;;;;;;;UCDN;;EAEhB,KAAK;;;;;;;;;EASL;;;;;;;;EAQA,UAAU,YAAY;;EAEtB,OAAO,oBAAoB,sBAAsB;;EAEjD;IAAS;IAAW;IAAW;IAAY;;;EAE3C,aAAa;;EAEb,eAAe;;;;;;EAMf,UAAU;;;;;;;;;;;KAYC,qBACT,gBAAgB,QAChB,gBAAgB,YAChB,gBAAgB,QAChB,gBAAgB,QAChB,gBAAgB,UAChB,gBAAgB,YAChB,gBAAgB,cAChB,gBAAgB,QAChB,gBAAgB,OAChB,gBAAgB;;KAGP,kBAAkB,KAAK;;;;;;;;;;;;;;;;;KAkBvB,gBAAgB,QAAQ,OAAO,oBAAoB;;;;UCtE9C;WACP;WACA;;;;;;;UAQO;WACP;WACA;WACA;;;;;KC/BE,aAAa,oBAAoB,sBAAsB;;;;;;;;UASlD;;;;;;;WAOP;;WAEA,QAAQ;;WAER,eAAe;;;UAIR;;WAEP,iBAAiB,OAAO,mBAAmB,qBAAqB,KAAK;;WAErE,eAAe,MAAM,2BAA2B,KAAK;;;;;;WAMrD,kBAAkB,QAAQ,YAAY,KAAK,cAAc;;;;;;UAOlD;WACP,YAAY,MAAM,8BAA8B;WAChD,gBAAgB,MAAM,8BAA8B;WACpD,YAAY,OAAO,mBAAmB,wBAAwB;WAC9D,aAAa,QAAQ,qBAAqB,yBAAyB;WACnE,YAAY,MAAM,8BAA8B;;;;cCRrC;;mBACH;EAEV,WAAW,QAAQ,+BAA+B;EAClD,WAAW,qBAAqB;EAChC,mBAAmB;EACnB;EACA,aAAa;EACb,OAAO;EACP,YAAY;EACZ,YAAY;EACZ;EACA;EACA,cAAc;EACd;EACA,mBAAmB;EACnB,eAAe;EACf,WAAW;EACX,qBAAqB;EACrB,aAAa;;;;;;WAOJ,eAAe;;;;;;;;EAShB,cAAc;EACd,UAAU;EACV,YAAY;EACZ,cAAc;EACd,UAAU;EACV,UAAU;EACV,UAAU;EACV,YAAY;EACZ,UAAU;EACV,cAAc;EACd,gBAAgB;EAChB,UAAU;EACV,cAAc;EACd,gBAAgB;EAChB,UAAU;EACV,SAAS;EACT,cAAc;EAE7B,YAAY;IACX,WAAW,QAAQ,+BAA+B;IAClD,WAAW,qBAAqB;IAChC,oBAAoB;IACpB,YAAY;IACZ,cAAc,OAAO;IACrB;IACA;IACA;IACA,cAAc;IACd,SAAS;IACT,cAAc;;;;;;;;;;UAwDP;MACG,WAAW,OAAO;MASlB,cAAc;;;;;UAQjB;MACG,MAAM,OAAO;MAIb,SAAS;;;;UAOZ;MACG,OAAO;MAIP;;;;;UAUH;MACG,WAAW,OAAO;MAIlB,cAAc;;;;MAOd,YAAY,OAAO;MAMnB,eAAe;;;;;;;;;;MAaf,sBAAsB;;;;;;;;;MAYtB,oBAAoB;;MAOpB;;MAKA;;;;;;;;KC5OA;;KAkBA;;;;;;KAwBP,OAAO,UAAU,sBAAsB,OAAO,iBAAiB,MAAM,WAAW,MAAM;;;;;;;;;;KAW/E,kBAAkB,KAAK,QAAQ,kCAAkC,OAAO;EACnF,YACC,OAAO,cACP,MAAM,kBAAkB,cACxB,OAAO;IAAc,OAAO;;;;;;;UA6Bb;WACP,MAAM;WACN,aAAa;;;;;;;;;UAUN;EAChB,eACC,KAAK,2BACL,eAAe,aACf,MAAM,uBACF;EACL,gBAAgB,KAAK,2BAA2B,eAAe,aAAa,MAAM;EAClF,eAAe,KAAK,2BAA2B,MAAM,YAAY,MAAM,eAAe;EACtF,iBAAiB,KAAK,2BAA2B,eAAe,SAAS;;;;;;;KAgB9D;;KAqBP,gBAAgB,UAAU,sBAAsB,QAAQ,mBAAmB,OAAO,aAAa;;;;;;;KAQxF,kBACV,KAAK,uBAAuB,QAAQ,mBAAmB,OAAO,gBAAgB;;;;;;;;;UAW/D;WACP,UAAU,OAAO,sBAAsB;;;UAIhC;;WAEP,MAAM;;WAEN,UAAU;;WAEV,WAAW;;WAEX,YAAY;;WAEZ,QAAQ;;WAER,sBAAsB;;WAEtB,UAAU;;;;;;KAgER,wBAAwB,KAAK,YAAW,KAAK,8BAA8B,YAAY,YAAY,SACxG,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;cCrKE;;;;;;;;;;;;;;UAeZ;MACG,OAAO,gBAAgB;MAgBvB;;;;mBAOM;MACN;;;;UAeH;MACG,OAAO;MAIP;;;;UAOH;MACG,QAAQ;MAIR;;;;;UAQH;MACG,SAAS;MAIT;;;;UAOH;MACG,QAAQ;MAIR;;;;UAOH;MACG,MAAM,OAAO;MAIb,SAAS;;;;UAOZ;MACG,MAAM;MAIN;;;;;UAQH;MACG,cAAc;MASd;;;;;UAQH;MACG,QAAQ;MAIR;;mBAKM;;mBAGA;MACN,UAAU;;mBAKJ;MACN,YAAY;;UAKf;;;;;;;qBAQW,eAAe;MACvB,gBAAgB;cAIf;UAoBJ;UAiBA;MACG,cAAc;mBAIR;;mBAaA;;mBAGA;EAEjB,YAAY,SAAS,gBAAgB,mBAAmB;;;;;;mBA6DvC;;;;;;mBAoBA;;;;;;mBAQA;;;;;mBAMA;;;;;UAaT;;;;;;;;;;;;;;;EAyBR,gBAAa;IAAkB;QAAgD,QAAQ;;;;;;;;;YAsB7E,aAAa,gBAAgB,qBACtC,QAAQ,IACN,wBAAwB,YAAY,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuCrD,oBACL,cACA,iBAAiB,aAAa,aAC9B;IAAS;IAAgB;IAAkB;MACzC;;;;;;;;;;;;;;;;;;;;;;;;EAmCG,UAAU;IACf;IACA,OAAO,cAAc;IACrB;IACA,QAAQ;MACL;;;;;;;;;;;;;;;;EAoDJ,YAAY,eAAe,aAAa,MAAM,qBAAqB;;;;;;;;;;;EAcnE,aAAa,eAAe,aAAa,MAAM;;;;;;;;;;;;;;;;;;;EAsB/C,YAAY,MAAM,YAAY,MAAM,aAAa;;;;;;;;;EAc3C,QAAQ,QAAQ,iBAAiB,QAAQ;;;;;;EAYzC,MAAM,QAAQ,aAAa,iBAAiB,cAAc,OAAO;;;;;;;;;;;;;;;;;EAuBjE,QAAQ,QAAQ,aAAa,QAAQ;;;;;;;EAYrC,UAAU,QAAQ,iBAAiB;;;;;;;EAqBzC,kBAAkB,cAAc,OAAO;;;;;;EAUvC,WAAW,SAAS;;;;;;EA6CpB,SAAS,UAAU,gBAAgB;;;;;;EAqFnC,aAAa,QAAQ;;;;;EAgDrB,kBAAkB,OAAO;;;;;;;iBCz7BV,iBAAiB,KAAK;;;;;;iBCEtB,kBAAkB,KAAK;;;;;;;;;;;;;;;;cCL1B;;;mBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KCSR,oBAAoB,MAAM,qBAAqB,GAAG,8BAA6B,SAAS,cAAa;;KAGrG,QAAQ,GAAG,KAAK,eAAc,YAAY,qBAAoB,MAAM,MAAM;;;;;;;;UASrE,iBAAiB;EAC1B;KACE,MAAM,iBAAiB,SAAS;MAAc,MAAM;QAAe;KACnE,QAAQ,cAAc,UAAU,YAAY;;;;KAKnC,eAAe,oBAAoB,qBAAqB,cAC7D,oBAAoB,QAAQ;EAAc;gBAChD;;KAIW,sBAAsB,oBAAoB,qBAAqB,cACpE,oBAAoB,QAAQ;EAAc;kCAC1C;;;;;;;;;KAWK,cAAc,UAAU,qBAAqB,KAAK,OAAO,wBACnE,KAAK,IAAI,gBAAgB,4BACvB,iBAAiB,cAAc,IAAI,KACnC,QAAQ,MAAM,IAAI,cAAc;;KAI/B,+BACH,WAAW,wBAAwB,wBAAwB,YAAY,oBAAoB;;;;;KAOjF,qBAAqB,UAAU,mBAAmB,gBAAgB,uBAAuB,KACpG,qCACmB,uBAEnB,KAAK,2BAA2B;EAAO,WAAW,UAAU,kBAAkB,cAAc;;;UAG5E,eAAe,oBAAoB;;EAEnD,MAAM;;;KAIK,SAAS,oBAAoB,qBAAqB,qBAC7D,0BAA0B,4BAA4B,MACtD,iCAAiC,4BAA4B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"errors-C4oENPcu.js","names":[],"sources":["../src/diagnostics.ts","../src/errors.ts"],"sourcesContent":["/**\n * Central sink for library diagnostics.\n *\n * Every user-facing warning is routed through {@link warn} / {@link warnOnce} rather than calling\n * `console.warn` directly, so there is one place to apply a consistent prefix and one place a\n * consumer can take over — see {@link setDiagnosticHandler}. This module has no *runtime* imports\n * so it can be used from anywhere without risking an import cycle; `codes.ts` is types only and is\n * erased at compile time, so it does not cost that property.\n *\n * **A diagnostic's `code` is API; its `message` is not.** The code is a stable identifier a\n * consumer may branch on (`if (d.code === 'chart/non-finite-value')`); the wording behind it is\n * free to improve in any release. The vocabulary lives in `codes.ts` and is shared with the thrown\n * surface (`errors.ts`), so a condition that can both warn and throw reads the same either way.\n */\n\nimport type { DiagnosticCode } from './codes.js'\n\nexport type { DiagnosticCode }\n\n/** One diagnostic emitted by the library. */\nexport interface Diagnostic {\n\t/** Stable condition identifier — see {@link DiagnosticCode}. Branch on this, not on the text. */\n\treadonly code: DiagnosticCode\n\t/** Human-readable explanation. Free to change in any release; do not parse it. */\n\treadonly message: string\n\t/**\n\t * Structured context for the condition, when a site has any to give.\n\t *\n\t * Every rejection of an `ST_` enum value populates it: `checkEnumOrWarn` (`ooxml/check-enum.ts`)\n\t * carries `received` — the value the caller passed — and `valid`, the whole legal list, plus\n\t * whatever the call site adds. That reaches a handler for a line dash type, a table cell's 3-D\n\t * preset and a table's horizontal overflow, among others. Nothing else populates it yet, so a\n\t * handler must still treat the field as optional and must not assume a particular key is there\n\t * for a given code.\n\t */\n\treadonly detail?: Readonly<Record<string, unknown>>\n}\n\n/** Receives every {@link Diagnostic} the library emits. See {@link setDiagnosticHandler}. */\nexport type DiagnosticHandler = (diagnostic: Diagnostic) => void\n\n/** Prefix stamped on every warning so consumers can attribute console noise to this library. */\nconst WARN_PREFIX = 'ts-pptx'\n\n/** The default handler: one `console.warn` line per diagnostic, prefixed. */\nconst consoleHandler: DiagnosticHandler = (diagnostic) => {\n\tconsole.warn(`${WARN_PREFIX}: ${diagnostic.message}`)\n}\n\nlet handler: DiagnosticHandler = consoleHandler\n\n/**\n * Route every library diagnostic to `handler`, or pass `null` to restore the default\n * (one prefixed `console.warn` per diagnostic).\n *\n * This is process-global rather than per-presentation, deliberately: the emitting code is a tree\n * of free functions in `gen/**` with no presentation in scope, and threading a handler through\n * every signature would be a far larger and worse change than the problem warrants. The practical\n * consequence is that a process building several decks concurrently cannot attribute a diagnostic\n * to one of them. If that matters, correlate on `code`, or build the decks one at a time with the\n * handler set around each build: a handler set around concurrent builds sees all of their\n * diagnostics.\n *\n * A throwing handler propagates out of whatever library call emitted the diagnostic, which is the\n * supported way to make a specific condition fatal:\n *\n * ```ts\n * setDiagnosticHandler((d) => {\n * if (d.code === 'coord/bare-number-is-inches') throw new Error(d.message)\n * })\n * ```\n * @param next - the receiver, or `null` to restore the console default\n */\nexport function setDiagnosticHandler(next: DiagnosticHandler | null): void {\n\thandler = next ?? consoleHandler\n}\n\n/**\n * Emit a library diagnostic.\n * @param code - the stable condition identifier ({@link DiagnosticCode})\n * @param message - explanation, without a `ts-pptx:` prefix (the default handler adds one)\n * @param detail - optional structured context\n */\nexport function warn(code: DiagnosticCode, message: string, detail?: Readonly<Record<string, unknown>>): void {\n\thandler(detail === undefined ? { code, message } : { code, message, detail })\n}\n\n// Track diagnostics already emitted so a recurring condition (e.g. the same out-of-range fontSize\n// on every cell of a table) is reported once instead of flooding the handler. Keyed on code AND\n// message, so a *different* offending value under the same code still reports.\nconst seen = new Set<string>()\n\n/**\n * Emit a library diagnostic at most once per distinct code+message.\n *\n * \"Once\" is **process-global**, the same scope {@link setDiagnosticHandler} has and for the\n * same reason: the emitting code is a tree of free functions in `gen/**` with no presentation\n * in scope. The consequence is different, though, and worth stating on its own — a process that\n * builds several decks does not get a second report of a condition an earlier deck already\n * tripped, so the second deck's diagnostics are incomplete rather than merely unattributed.\n * {@link resetDiagnosticState} is how a host that cares gets each build a clean slate.\n *\n * @param code - the stable condition identifier ({@link DiagnosticCode})\n * @param message - explanation (see {@link warn})\n * @param detail - optional structured context\n */\nexport function warnOnce(code: DiagnosticCode, message: string, detail?: Readonly<Record<string, unknown>>): void {\n\tconst key = `${code}\\0${message}`\n\tif (seen.has(key)) return\n\tseen.add(key)\n\twarn(code, message, detail)\n}\n\n/**\n * Clear the `warnOnce` dedupe set, so a condition already reported reports again. (`warnOnce` is\n * internal and carries no page of its own, so it is named rather than linked.)\n *\n * Call it between builds in a host that builds more than one deck per process and wants each\n * build's diagnostics complete. Without it, deck two is silent about anything deck one already\n * warned for, which reads as \"no problems found\" rather than as \"already mentioned\".\n *\n * It also bounds the set. Most `warnOnce` messages interpolate the offending value, so a server\n * building decks from user input accumulates one entry per distinct bad value with no way to\n * release them.\n *\n * This does not touch the handler — {@link setDiagnosticHandler} owns that, and the two are\n * reset independently on purpose: a host usually installs its handler once and wants it to\n * survive.\n */\nexport function resetDiagnosticState(): void {\n\tseen.clear()\n}\n","/**\n * The library's error taxonomy.\n *\n * Every failure ts-pptx raises is a {@link TsPptxError} carrying a stable {@link ErrorCode}, so a\n * consumer can tell *\"you passed a bad coordinate\"* from *\"this font file is corrupt\"* from\n * *\"these bytes are not a package\"* without matching on message substrings. The classes are a\n * deliberately flat, coarse bucket — five of them — and the code carries the specificity. Do not\n * add a class per throw site; add a code.\n *\n * **The class and the code are API. The message is not.** Branch on `instanceof` and on `code`;\n * the wording behind them is free to improve in any release. Every error remains an\n * `instanceof Error`, so existing `catch` blocks keep working.\n *\n * Which class to reach for:\n *\n * | class | the failure is | who fixes it |\n * |---|---|---|\n * | {@link InvalidOptionError} | the caller passed something unusable | the caller's code |\n * | {@link UnsupportedFeatureError} | a well-formed request this build/runtime/shape cannot express | the caller's expectations, or the environment |\n * | {@link PackageReadError} | the input bytes are not a readable package | the input file |\n * | {@link MediaError} | a referenced image/font/AV resource would not load or decode | the resource |\n * | {@link InternalError} | an invariant of the library itself did not hold | ts-pptx (file a bug) |\n *\n * **Which of these is worth reporting upstream.** `InternalError` always is, and says so at\n * runtime. The middle three are worth reporting when the environment disagrees with us:\n * a `PackageReadError` on a file that opens cleanly in PowerPoint, a `MediaError` on an asset every\n * other tool loads, an `UnsupportedFeatureError` for something PowerPoint can plainly express.\n * `InvalidOptionError` is worth reporting only if the deck it refused is one PowerPoint can\n * express. See `skills/ts-pptx-upstream` for how to file one.\n *\n * @see `docs/errors-and-warnings.md` for the consumer-facing contract.\n * @see `codes.ts` for the code vocabulary, which is shared with the diagnostic (warning) surface.\n */\n\nimport type {\n\tErrorCode,\n\tInternalErrorCode,\n\tInvalidOptionErrorCode,\n\tMediaErrorCode,\n\tPackageReadErrorCode,\n\tUnsupportedFeatureErrorCode,\n} from './codes.js'\n\n/** Extra context accepted by every {@link TsPptxError} constructor. */\nexport interface TsPptxErrorOptions extends ErrorOptions {\n\t/**\n\t * Structured context for the condition, when a site has any to give. Mirrors `Diagnostic.detail`\n\t * so the same condition looks the same whether it was warned or thrown.\n\t */\n\treadonly detail?: Readonly<Record<string, unknown>>\n}\n\n/**\n * Base class for every error ts-pptx throws.\n *\n * Catch this to catch anything from the library; narrow with `instanceof` on a subclass, or branch\n * on {@link TsPptxError.code}, to react to something specific. It is never thrown directly — every\n * site picks one of the five subclasses.\n */\nexport class TsPptxError extends Error {\n\t/** Stable condition identifier — see {@link ErrorCode}. Branch on this, not on the text. */\n\treadonly code: ErrorCode\n\n\t/** Structured context for the condition, when the throwing site had any to give. */\n\treadonly detail?: Readonly<Record<string, unknown>>\n\n\t/**\n\t * @param code - the stable condition identifier\n\t * @param message - explanation for a human reading a stack trace; not part of the contract\n\t * @param options - standard `cause`, plus optional structured `detail`\n\t */\n\tconstructor(code: ErrorCode, message: string, options?: TsPptxErrorOptions) {\n\t\tsuper(message, options)\n\t\t// `name` drives how a stack trace and `console.log` label the error, and the default from\n\t\t// `Error` would say \"Error\" for every subclass. Derive it from the constructor so a subclass\n\t\t// never has to remember to set it.\n\t\tthis.name = new.target.name\n\t\tthis.code = code\n\t\tif (options?.detail !== undefined) this.detail = options.detail\n\t}\n}\n\n/**\n * The caller passed something the library cannot use — a non-finite coordinate, an unknown enum\n * value, a required option left out, a value outside its legal range.\n *\n * This is the error behind the project's throw-rather-than-coerce policy: emitting a degenerate\n * result (a zero-size shape, a silently dropped option) hides the mistake, so the library refuses\n * instead. Reaching one means the calling code needs to change.\n */\nexport class InvalidOptionError extends TsPptxError {\n\tdeclare readonly code: InvalidOptionErrorCode\n\tconstructor(code: InvalidOptionErrorCode, message: string, options?: TsPptxErrorOptions) {\n\t\tsuper(code, message, options)\n\t}\n}\n\n/**\n * The request is well-formed but cannot be expressed here: an optional peer dependency is not\n * installed, the runtime lacks a capability, or the shape/feature has no OOXML representation the\n * library emits.\n *\n * Distinct from {@link InvalidOptionError} because the caller did nothing wrong — the answer is\n * \"not here\", not \"not like that\" — and the fix is usually to install something or pick a different\n * approach rather than to correct a value.\n */\nexport class UnsupportedFeatureError extends TsPptxError {\n\tdeclare readonly code: UnsupportedFeatureErrorCode\n\tconstructor(code: UnsupportedFeatureErrorCode, message: string, options?: TsPptxErrorOptions) {\n\t\tsuper(code, message, options)\n\t}\n}\n\n/**\n * The bytes handed to the library are not a package it can read, or a part inside one is\n * structurally malformed — a missing `[Content_Types].xml`, a relationship pointing at nothing, a\n * slide part with no root element.\n *\n * Always about *input*. A problem with something the library is being asked to produce is an\n * {@link InvalidOptionError}.\n */\nexport class PackageReadError extends TsPptxError {\n\tdeclare readonly code: PackageReadErrorCode\n\tconstructor(code: PackageReadErrorCode, message: string, options?: TsPptxErrorOptions) {\n\t\tsuper(code, message, options)\n\t}\n}\n\n/**\n * A referenced image, font, or audio/video resource could not be fetched, read, or decoded.\n *\n * Kept apart from {@link PackageReadError} because the failure is in a resource the deck *points\n * at*, not in the package structure — a broken URL, an unreadable path, a corrupt font file — and\n * a consumer typically retries or substitutes rather than rejecting the deck.\n */\nexport class MediaError extends TsPptxError {\n\tdeclare readonly code: MediaErrorCode\n\tconstructor(code: MediaErrorCode, message: string, options?: TsPptxErrorOptions) {\n\t\tsuper(code, message, options)\n\t}\n}\n\n/**\n * Where a report of an `InternalError` should go. Appended to the message rather than left to the\n * docs, because a stack trace is the only artefact of the failure that reaches whoever (or\n * whatever) is debugging it — a pointer anywhere else is a pointer they have to already be looking\n * for. Most code that calls this library is written by an agent in a repository that is not this\n * one, and an agent that hits a library defect routes around it silently unless something in front\n * of it says the report is worth making.\n */\nconst REPORT_NOTICE =\n\t'This is a bug in ts-pptx, not in your deck or your code. Please report it:\\n' +\n\t'https://github.com/shbernal/ts-pptx/issues/new?template=agent-report.yml'\n\n/**\n * An invariant the library maintains itself did not hold.\n *\n * No consumer input should be able to produce one, which is the whole reason it is a separate\n * class: seeing it means the bug is in ts-pptx, and the useful response is to file it rather than\n * to keep adjusting the input.\n *\n * It is the one class in the taxonomy that extends its own message, appending `REPORT_NOTICE`\n * below the invariant that broke. The constructor is where that lives so a throw site added later\n * inherits it — the alternative, a notice pasted at each of the sites, is one every future site can\n * forget. Every other class leaves `message` exactly as given: a malformed package is the routine\n * outcome for a library that reads untrusted files, and a \"report this\" banner on each corrupt\n * input would train callers to ignore the one banner that always means something.\n *\n * This does not make the message API — see the class doc on {@link TsPptxError}. Branch on\n * `instanceof` or on {@link InternalError.code}, never on the text.\n */\nexport class InternalError extends TsPptxError {\n\tdeclare readonly code: InternalErrorCode\n\tconstructor(code: InternalErrorCode, message: string, options?: TsPptxErrorOptions) {\n\t\tsuper(code, `${message}\\n\\n${REPORT_NOTICE}`, options)\n\t}\n}\n"],"mappings":";;AA0CA,MAAM,cAAc;;AAGpB,MAAM,kBAAqC,eAAe;CACzD,QAAQ,KAAK,GAAG,YAAY,IAAI,WAAW,SAAS;AACrD;AAEA,IAAI,UAA6B;;;;;;;;;;;;;;;;;;;;;;;AAwBjC,SAAgB,qBAAqB,MAAsC;CAC1E,UAAU,QAAQ;AACnB;;;;;;;AAQA,SAAgB,KAAK,MAAsB,SAAiB,QAAkD;CAC7G,QAAQ,WAAW,KAAA,IAAY;EAAE;EAAM;CAAQ,IAAI;EAAE;EAAM;EAAS;CAAO,CAAC;AAC7E;AAKA,MAAM,uBAAO,IAAI,IAAY;;;;;;;;;;;;;;;AAgB7B,SAAgB,SAAS,MAAsB,SAAiB,QAAkD;CACjH,MAAM,MAAM,GAAG,KAAK,IAAI;CACxB,IAAI,KAAK,IAAI,GAAG,GAAG;CACnB,KAAK,IAAI,GAAG;CACZ,KAAK,MAAM,SAAS,MAAM;AAC3B;;;;;;;;;;;;;;;;;AAkBA,SAAgB,uBAA6B;CAC5C,KAAK,MAAM;AACZ;;;;;;;;;;ACxEA,IAAa,cAAb,cAAiC,MAAM;;CAEtC;;CAGA;;;;;;CAOA,YAAY,MAAiB,SAAiB,SAA8B;EAC3E,MAAM,SAAS,OAAO;EAItB,KAAK,OAAO,WAAW;EACvB,KAAK,OAAO;EACZ,IAAI,SAAS,WAAW,KAAA,GAAW,KAAK,SAAS,QAAQ;CAC1D;AACD;;;;;;;;;AAUA,IAAa,qBAAb,cAAwC,YAAY;CAEnD,YAAY,MAA8B,SAAiB,SAA8B;EACxF,MAAM,MAAM,SAAS,OAAO;CAC7B;AACD;;;;;;;;;;AAWA,IAAa,0BAAb,cAA6C,YAAY;CAExD,YAAY,MAAmC,SAAiB,SAA8B;EAC7F,MAAM,MAAM,SAAS,OAAO;CAC7B;AACD;;;;;;;;;AAUA,IAAa,mBAAb,cAAsC,YAAY;CAEjD,YAAY,MAA4B,SAAiB,SAA8B;EACtF,MAAM,MAAM,SAAS,OAAO;CAC7B;AACD;;;;;;;;AASA,IAAa,aAAb,cAAgC,YAAY;CAE3C,YAAY,MAAsB,SAAiB,SAA8B;EAChF,MAAM,MAAM,SAAS,OAAO;CAC7B;AACD;;;;;;;;;AAUA,MAAM,gBACL;;;;;;;;;;;;;;;;;;AAoBD,IAAa,gBAAb,cAAmC,YAAY;CAE9C,YAAY,MAAyB,SAAiB,SAA8B;EACnF,MAAM,MAAM,GAAG,QAAQ,MAAM,iBAAiB,OAAO;CACtD;AACD"}