@shbernal/ts-pptx 2.0.0 → 3.1.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.
- package/README.md +31 -2
- package/dist/{autopage-tmfjRzL4.js → autopage-QQyfRtoK.js} +4 -5
- package/dist/{autopage-tmfjRzL4.js.map → autopage-QQyfRtoK.js.map} +1 -1
- package/dist/browser.d.ts +14 -6
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +14 -6
- package/dist/browser.js.map +1 -1
- package/dist/{diagnostics-CQ0JWc9m.d.ts → diagnostics-PMINsVP6.d.ts} +97 -8
- package/dist/diagnostics-PMINsVP6.d.ts.map +1 -0
- package/dist/{enums-D3aF4QGb.d.ts → enums-CoXnxiCI.d.ts} +6 -5
- package/dist/{enums-D3aF4QGb.d.ts.map → enums-CoXnxiCI.d.ts.map} +1 -1
- package/dist/{errors-B22h8Qd0.d.ts → errors-BeUEkNWL.d.ts} +26 -4
- package/dist/errors-BeUEkNWL.d.ts.map +1 -0
- package/dist/{errors-DGE9zh3U.js → errors-Bvln0H-7.js} +21 -2
- package/dist/errors-Bvln0H-7.js.map +1 -0
- package/dist/{fit-BSWY0AYt.js → fit-DhMbQG5O.js} +0 -0
- package/dist/fit-DhMbQG5O.js.map +1 -0
- package/dist/{html-dom-BQLUntho.js → html-dom-DajBuobe.js} +20 -6
- package/dist/html-dom-DajBuobe.js.map +1 -0
- package/dist/html.d.ts +3 -3
- package/dist/html.d.ts.map +1 -1
- package/dist/html.js +7 -4
- package/dist/html.js.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/inspect.d.ts +1 -1
- package/dist/inspect.js +4 -4
- package/dist/inspect.js.map +1 -1
- package/dist/math.d.ts +1 -1
- package/dist/math.d.ts.map +1 -1
- package/dist/math.js +98 -2
- package/dist/math.js.map +1 -1
- package/dist/measure.d.ts +3 -3
- package/dist/measure.js +2 -2
- package/dist/node.d.ts +14 -6
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +13 -5
- package/dist/node.js.map +1 -1
- package/dist/package-CaOLXSNi.d.ts.map +1 -1
- package/dist/{pres-GU-jjBEx.d.ts → pres-BgvxhQ_m.d.ts} +3 -3
- package/dist/{pres-GU-jjBEx.d.ts.map → pres-BgvxhQ_m.d.ts.map} +1 -1
- package/dist/{presentation-MJe9WDi4.js → presentation-BP1B8PCF.js} +863 -343
- package/dist/presentation-BP1B8PCF.js.map +1 -0
- package/dist/{presentation-CVaTZw1V.d.ts → presentation-DyIRDKkp.d.ts} +742 -595
- package/dist/presentation-DyIRDKkp.d.ts.map +1 -0
- package/dist/{presentation-types-BVw0EknS.d.ts → presentation-types-Dj4riuDs.d.ts} +2 -2
- package/dist/{presentation-types-BVw0EknS.d.ts.map → presentation-types-Dj4riuDs.d.ts.map} +1 -1
- package/dist/read.d.ts +5 -5
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +3 -3
- package/dist/script.d.ts +2 -2
- package/dist/script.d.ts.map +1 -1
- package/dist/script.js +0 -0
- package/dist/script.js.map +1 -1
- package/dist/{shapes-CaOgR0i1.js → shapes-DMThLsZN.js} +689 -1032
- package/dist/shapes-DMThLsZN.js.map +1 -0
- package/dist/{slide-BBlElWr9.d.ts → slide-BRAtT8Dl.d.ts} +197 -22
- package/dist/slide-BRAtT8Dl.d.ts.map +1 -0
- package/dist/{image-size-C8uYE8GJ.js → st-enums-evQG2A7Z.js} +233 -2
- package/dist/st-enums-evQG2A7Z.js.map +1 -0
- package/dist/{text-B1ZrPEeK.js → text-B6PbMFih.js} +725 -319
- package/dist/text-B6PbMFih.js.map +1 -0
- package/dist/{units-B-JUKwCS.js → units-C7QM1KgH.js} +2 -2
- package/dist/{units-B-JUKwCS.js.map → units-C7QM1KgH.js.map} +1 -1
- package/dist/{units-internal-7JcMfYti.js → units-internal-CR8s8YQa.js} +4 -3
- package/dist/units-internal-CR8s8YQa.js.map +1 -0
- package/dist/zip.d.ts +2 -2
- package/dist/zip.js +1 -1
- package/dist/zip.js.map +1 -1
- package/package.json +40 -29
- package/skills/ts-pptx-upstream/SKILL.md +247 -0
- package/dist/diagnostics-CQ0JWc9m.d.ts.map +0 -1
- package/dist/errors-B22h8Qd0.d.ts.map +0 -1
- package/dist/errors-DGE9zh3U.js.map +0 -1
- package/dist/fit-BSWY0AYt.js.map +0 -1
- package/dist/html-dom-BQLUntho.js.map +0 -1
- package/dist/image-size-C8uYE8GJ.js.map +0 -1
- package/dist/presentation-CVaTZw1V.d.ts.map +0 -1
- package/dist/presentation-MJe9WDi4.js.map +0 -1
- package/dist/shapes-CaOgR0i1.js.map +0 -1
- package/dist/slide-BBlElWr9.d.ts.map +0 -1
- package/dist/text-B1ZrPEeK.js.map +0 -1
- package/dist/units-internal-7JcMfYti.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics-PMINsVP6.d.ts","names":[],"sources":["../src/types/zoom.ts","../src/types/internal.ts","../src/runtime/types.ts","../src/units.ts","../src/presentation.ts","../src/clip.ts","../src/diagnostics.ts"],"mappings":"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"}
|
|
@@ -266,7 +266,7 @@ type SHAPE_NAME = 'accentBorderCallout1' | 'accentBorderCallout2' | 'accentBorde
|
|
|
266
266
|
* `ShapeType` name. They are still legal geometries PowerPoint renders, so the
|
|
267
267
|
* preset-validation set must accept them.
|
|
268
268
|
*/
|
|
269
|
-
declare const EXTRA_SHAPE_PRESETS: readonly [
|
|
269
|
+
declare const EXTRA_SHAPE_PRESETS: readonly ['straightConnector1', 'bentConnector2', 'bentConnector3', 'bentConnector4', 'bentConnector5', 'curvedConnector2', 'curvedConnector3', 'curvedConnector4', 'curvedConnector5'];
|
|
270
270
|
/**
|
|
271
271
|
* Connector preset geometries (`straightConnector1` / `bentConnector{2-5}` /
|
|
272
272
|
* `curvedConnector{2-5}`) that `addShape` can serialize but that are not surfaced
|
|
@@ -306,6 +306,7 @@ declare enum SlideObjectType {
|
|
|
306
306
|
hyperlink = "hyperlink",
|
|
307
307
|
image = "image",
|
|
308
308
|
media = "media",
|
|
309
|
+
model3d = "model3d",
|
|
309
310
|
oleObject = "oleObject",
|
|
310
311
|
online = "online",
|
|
311
312
|
placeholder = "placeholder",
|
|
@@ -321,9 +322,9 @@ declare enum SlideObjectType {
|
|
|
321
322
|
* (`bentConnector{3,4,5}` / `curvedConnector{3,4,5}`) — see `connectorPresetFor`.
|
|
322
323
|
*/
|
|
323
324
|
declare const CONNECTOR_PRESETS: {
|
|
324
|
-
readonly straight:
|
|
325
|
-
readonly elbow:
|
|
326
|
-
readonly curved:
|
|
325
|
+
readonly straight: 'straightConnector1';
|
|
326
|
+
readonly elbow: 'bentConnector';
|
|
327
|
+
readonly curved: 'curvedConnector';
|
|
327
328
|
};
|
|
328
329
|
/**
|
|
329
330
|
* Resolve the concrete connector preset geometry name for a `type` + bend count.
|
|
@@ -449,4 +450,4 @@ declare enum TableStyle {
|
|
|
449
450
|
}
|
|
450
451
|
//#endregion
|
|
451
452
|
export { isChartExType as C, connectorPresetFor as S, TextAnchor as _, CONNECTOR_PRESETS as a, ZIP_OUTPUT_TYPE as b, OutputType as c, SCHEME_COLORS as d, SHAPE_NAME as f, TableStyle as g, SlideObjectType as h, CHART_NAME as i, PLACEHOLDER_TYPE as l, ShapeType as m, AlignV as n, CONNECTOR_PRESET_NAME as o, SchemeColor as p, BulletType as r, ChartType as s, AlignH as t, PlaceholderType as u, VALID_SHAPE_PRESETS as v, asChartType as x, WRITE_OUTPUT_TYPE as y };
|
|
452
|
-
//# sourceMappingURL=enums-
|
|
453
|
+
//# sourceMappingURL=enums-CoXnxiCI.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enums-
|
|
1
|
+
{"version":3,"file":"enums-CoXnxiCI.d.ts","names":[],"sources":["../src/enums.ts"],"mappings":";;;;;;;;;;KAUY,qBAAqB;KACrB,oBAAoB;;;;;;KAMpB,gBAAgB;;;;;KAKhB,mBAAmB;aAEnB;EACX;EACA;EACA;;aAIW;EACX;EACA;EACA;EACA;EACA;EACA;;aAEW;EACX;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;aAEW;EACX;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;aAEW;EACX;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;aAEW;EACX;EACA;EACA;EACA;;aAEW;EACX;EACA;EACA;;KAGW,8iGAoLT;;;;;;cAOG;;;;;;;;;KAoBM,gCAAgC;;;;;;;;;cAU/B,qBAAqB;;;;;;;;iBAYlB,YAAY,MAAM,aAAa;;;;;;iBA4B/B,cAAc;aAIlB;EACX;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;;;;;cAQY;WACF;WACH;WACC;;;;;;;;;;;iBAYO,mBAAmB,uCAAuC,gBAAgB;aAI9E;EACX;EACA;EACA;EACA;EACA;EACA;;;;;;KAMW,sBAAsB;;;;;aAMtB;EACX;EACA;EACA;EACA;;;;;;;;;;;;aAaW;EAEX;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;;EAEA;;EAEA;;EAEA"}
|
|
@@ -30,14 +30,14 @@
|
|
|
30
30
|
* differs — an image whose natural size cannot be measured reports
|
|
31
31
|
* `image/unmeasurable-natural-size` whether it came from `addImage` or from `Picture.setImage`.
|
|
32
32
|
*/
|
|
33
|
-
type DiagnosticCode = 'object-name/empty' | 'object-name/control-characters' | 'object-name/too-long' | 'object-name/duplicate' | 'animation/target-index-out-of-range' | 'animation/target-not-found' | 'animation/target-missing' | 'chart/invalid-axis-time-unit' | 'chart/non-finite-value' | 'chart/error-bars-missing-values' | 'chart/axis-type-conflict' | 'chart/invalid-metadata' | 'chart/invalid-metadata-key' | 'chart/invalid-metadata-value' | 'chart/option-out-of-range' | 'chart/invalid-subtotal-index' | 'chart/symbol-size-out-of-range' | 'chart/invalid-grid-line-size' | 'chart/invalid-grid-line-style' | 'chart/invalid-grid-line-cap' | 'chart/layout-out-of-range' | 'chart/stock-series-count' | 'comment/missing-author' | 'comment/missing-text' | 'connector/bends-ignored-for-straight' | 'connector/adj-out-of-range' | 'connector/unresolved-binding' | 'group/unsupported-child' | 'group/unrecognized-child' | 'group/no-children' | 'group/partial-frame' | 'image-fill/missing-source' | 'image-fill/missing-base64-header' | 'image-fill/svg-unsupported' | 'image-fill/unresolved-media' | 'image/crop-and-sizing-conflict' | 'image/unmeasurable-natural-size' | 'table/invalid-border' | 'table/invalid-outer-border' | 'table/invalid-horz-overflow' | 'table/invalid-cell3d' | 'table/col-width-count-mismatch' | 'table/autopage-height-too-small' | 'text/invalid-columns' | 'text/invalid-column-spacing' | 'text/invalid-fit-percentage' | 'text/char-spacing-out-of-range' | 'text/line-spacing-out-of-range' | 'font/size-out-of-range' | 'bullet/size-out-of-range' | 'bullet/image-missing-base64-header' | 'bullet/image-embed-failed' | 'bullet/invalid-character-code' | 'zoom/missing-target' | 'zoom/unresolved-target' | 'zoom/missing-section-title' | 'zoom/section-not-found' | 'zoom/section-empty' | 'zoom/no-sections-to-summarize' | 'color/not-a-string' | 'color/invalid-value' | 'shadow/invalid-type' | 'shadow/angle-out-of-range' | 'shadow/transparency-out-of-range' | 'shadow/color-has-hash' | 'geometry/invalid-shape-adjust' | 'geometry/shape-adjust-overridden' | 'geometry/arc-node-point-ignored' | 'geometry/invalid-guide' | 'geometry/unknown-guide-operation' | 'geometry/invalid-connection-site' | 'border/unknown-key' | 'border/invalid-dash-type' | 'object-lock/unsupported-on-shape' | 'media/load-failed' | 'theme/invalid-color-override' | 'master/invalid-text-style-font-size' | 'master/too-many-text-style-levels' | 'notes/hyperlink-slide-unsupported' | 'html/image-missing-source' | 'section/missing-argument' | 'section/missing-title' | 'section/duplicate-title' | 'slide/section-not-found' | 'layout/invalid-definition' | 'inspect/group-transform-missing' | 'inspect/group-transform-degenerate' | 'measure/shrink-unmeasured' | 'measure/resize-unmeasured' | 'measure/heuristic-metrics' | 'margin/legacy-points' | 'transparency/out-of-range' | 'opacity/out-of-range' | 'line/width-out-of-range' | 'coord/bare-number-is-inches';
|
|
33
|
+
type DiagnosticCode = 'object-name/empty' | 'object-name/control-characters' | 'object-name/too-long' | 'object-name/duplicate' | 'animation/target-index-out-of-range' | 'animation/target-not-found' | 'animation/target-missing' | 'chart/invalid-axis-time-unit' | 'chart/non-finite-value' | 'chart/error-bars-missing-values' | 'chart/axis-type-conflict' | 'chart/invalid-metadata' | 'chart/invalid-metadata-key' | 'chart/invalid-metadata-value' | 'chart/option-out-of-range' | 'chart/invalid-subtotal-index' | 'chart/symbol-size-out-of-range' | 'chart/invalid-grid-line-size' | 'chart/invalid-grid-line-style' | 'chart/invalid-grid-line-cap' | 'chart/layout-out-of-range' | 'chart/stock-series-count' | 'comment/missing-author' | 'comment/missing-text' | 'connector/bends-ignored-for-straight' | 'connector/adj-out-of-range' | 'connector/unresolved-binding' | 'group/unsupported-child' | 'group/unrecognized-child' | 'group/no-children' | 'group/partial-frame' | 'image-fill/missing-source' | 'image-fill/missing-base64-header' | 'image-fill/svg-unsupported' | 'image-fill/unresolved-media' | 'image/crop-and-sizing-conflict' | 'image/unmeasurable-natural-size' | 'table/invalid-border' | 'table/invalid-outer-border' | 'table/invalid-horz-overflow' | 'table/invalid-cell3d' | 'table/col-width-count-mismatch' | 'table/autopage-height-too-small' | 'text/invalid-columns' | 'text/invalid-column-spacing' | 'text/invalid-fit-percentage' | 'text/char-spacing-out-of-range' | 'text/line-spacing-out-of-range' | 'font/size-out-of-range' | 'bullet/size-out-of-range' | 'bullet/image-missing-base64-header' | 'bullet/image-embed-failed' | 'bullet/invalid-character-code' | 'zoom/missing-target' | 'zoom/unresolved-target' | 'zoom/missing-section-title' | 'zoom/section-not-found' | 'zoom/section-empty' | 'zoom/no-sections-to-summarize' | 'color/not-a-string' | 'color/invalid-value' | 'shadow/invalid-type' | 'shadow/angle-out-of-range' | 'shadow/transparency-out-of-range' | 'shadow/color-has-hash' | 'geometry/invalid-shape-adjust' | 'geometry/shape-adjust-overridden' | 'geometry/arc-node-point-ignored' | 'geometry/invalid-guide' | 'geometry/unknown-guide-operation' | 'geometry/invalid-connection-site' | 'border/unknown-key' | 'border/invalid-dash-type' | 'object-lock/unsupported-on-shape' | 'media/load-failed' | 'model3d/preview-missing' | 'theme/invalid-color-override' | 'master/invalid-text-style-font-size' | 'master/too-many-text-style-levels' | 'notes/hyperlink-slide-unsupported' | 'html/image-missing-source' | 'section/missing-argument' | 'section/missing-title' | 'section/duplicate-title' | 'slide/section-not-found' | 'layout/invalid-definition' | 'inspect/group-transform-missing' | 'inspect/group-transform-degenerate' | 'measure/shrink-unmeasured' | 'measure/resize-unmeasured' | 'measure/heuristic-metrics' | 'margin/legacy-points' | 'transparency/out-of-range' | 'opacity/out-of-range' | 'line/width-out-of-range' | 'coord/bare-number-is-inches';
|
|
34
34
|
/**
|
|
35
35
|
* Conditions carried by `InvalidOptionError`: the caller passed something the library cannot use.
|
|
36
36
|
*
|
|
37
37
|
* This is the largest group by design — the project's stated policy is to throw rather than coerce
|
|
38
38
|
* (`AGENTS.md` → "Silent coercion of invalid input is a footgun"), so most throws are here.
|
|
39
39
|
*/
|
|
40
|
-
type InvalidOptionErrorCode = 'coord/non-finite' | 'coord/not-positive' | 'coord/negative' | 'coord/invalid-format' | 'geometry/arc-angle-non-finite' | 'chart/missing-type' | 'chart/secondary-axis-unused' | 'chart/axis-count-mismatch' | 'shape/missing-type' | 'shape/unknown-preset' | 'connector/missing-endpoints' | 'connector/invalid-type' | 'connector/invalid-bends' | 'connector/adj-count-mismatch' | 'connector/adj-non-finite' | 'connector/invalid-binding-name' | 'connector/invalid-connection-site' | 'line/invalid-cap' | 'group/missing-object-names' | 'group/invalid-object-name' | 'group/duplicate-object-name' | 'group/unresolved-object-name' | 'group/ambiguous-object-name' | 'gradient/angle-non-finite' | 'gradient/too-few-stops' | 'gradient/stop-position-non-finite' | 'gradient/stop-position-out-of-range' | 'gradient/rotate-with-shape-not-boolean' | 'gradient/scaled-not-boolean' | 'pattern-fill/missing-pattern' | 'image/missing-source' | 'image/path-not-a-string' | 'image/data-not-a-string' | 'image/missing-base64-header' | 'image/crop-window-overflows' | 'image/crop-inset-out-of-range' | 'image/crop-insets-exceed-extent' | 'media/missing-source' | 'media/missing-base64-header' | 'media/cover-missing-base64-header' | 'media/online-missing-link' | 'ole/missing-source' | 'table/rows-not-an-array' | 'table/rows-not-nested' | 'table/invalid-cell-anchor' | 'table/invalid-cell-vert' | 'table/invalid-cell-overflow' | 'table/invalid-cell-margin' | 'table/invalid-cell-border' | 'table/row-index-out-of-range' | 'table/column-index-out-of-range' | 'table/merge-range-invalid' | 'hyperlink/not-an-object' | 'hyperlink/missing-target' | 'html/no-document' | 'html/table-not-found' | 'html/table-has-no-cells' | 'color/invalid-hex' | 'slide/index-out-of-range' | 'slide/foreign-target' | 'shape/index-out-of-range' | 'layout/ambiguous-name' | 'layout/not-found' | 'layout/foreign-handle' | 'import/slide-size-mismatch' | 'import/slide-size-unknown' | 'import/unresolved-slide-link' | 'import/destination-missing-master' | 'import/destination-missing-layout' | 'image/undeterminable-extension' | 'image/undeterminable-type' | 'image/missing-content-type' | 'image/fit-needs-extent' | 'font/size-not-positive' | 'script/unresolved-asset-reference' | 'script/non-finite-literal' | 'package/duplicate-part-name' | 'part/not-xml' | 'relationship/duplicate-id' | 'relationship/not-found' | 'relationship/external-has-no-partname' | 'oxml/unknown-namespace-prefix' | 'oxml/invalid-qname' | 'font/missing-typeface' | 'font/invalid-style-slot' | 'font/invalid-base64' | 'font/missing-source' | 'layout/unknown' | 'master/missing-title' | 'math/invalid-latex' | 'zip/unsupported-input' | 'zip/unsupported-output';
|
|
40
|
+
type InvalidOptionErrorCode = 'coord/non-finite' | 'coord/not-positive' | 'coord/negative' | 'coord/invalid-format' | 'geometry/arc-angle-non-finite' | 'chart/missing-type' | 'chart/secondary-axis-unused' | 'chart/axis-count-mismatch' | 'shape/missing-type' | 'shape/unknown-preset' | 'connector/missing-endpoints' | 'connector/invalid-type' | 'connector/invalid-bends' | 'connector/adj-count-mismatch' | 'connector/adj-non-finite' | 'connector/invalid-binding-name' | 'connector/invalid-connection-site' | 'line/invalid-cap' | 'group/missing-object-names' | 'group/invalid-object-name' | 'group/duplicate-object-name' | 'group/unresolved-object-name' | 'group/ambiguous-object-name' | 'gradient/angle-non-finite' | 'gradient/too-few-stops' | 'gradient/stop-position-non-finite' | 'gradient/stop-position-out-of-range' | 'gradient/rotate-with-shape-not-boolean' | 'gradient/scaled-not-boolean' | 'pattern-fill/missing-pattern' | 'image/missing-source' | 'image/path-not-a-string' | 'image/data-not-a-string' | 'image/missing-base64-header' | 'image/crop-window-overflows' | 'image/crop-inset-out-of-range' | 'image/crop-insets-exceed-extent' | 'media/missing-source' | 'media/missing-base64-header' | 'media/cover-missing-base64-header' | 'media/online-missing-link' | 'ole/missing-source' | 'model3d/missing-source' | 'model3d/invalid-camera' | 'model3d/invalid-fov' | 'model3d/invalid-scale' | 'table/rows-not-an-array' | 'table/rows-not-nested' | 'table/invalid-cell-anchor' | 'table/invalid-cell-vert' | 'table/invalid-cell-overflow' | 'table/invalid-cell-margin' | 'table/invalid-cell-border' | 'table/row-index-out-of-range' | 'table/column-index-out-of-range' | 'table/merge-range-invalid' | 'hyperlink/not-an-object' | 'hyperlink/missing-target' | 'html/no-document' | 'html/table-not-found' | 'html/table-has-no-cells' | 'color/invalid-hex' | 'slide/index-out-of-range' | 'slide/foreign-target' | 'shape/index-out-of-range' | 'layout/ambiguous-name' | 'layout/not-found' | 'layout/foreign-handle' | 'import/slide-size-mismatch' | 'import/slide-size-unknown' | 'import/unresolved-slide-link' | 'import/destination-missing-master' | 'import/destination-missing-layout' | 'image/undeterminable-extension' | 'image/undeterminable-type' | 'image/missing-content-type' | 'image/fit-needs-extent' | 'font/size-not-positive' | 'script/unresolved-asset-reference' | 'script/non-finite-literal' | 'package/duplicate-part-name' | 'part/not-xml' | 'relationship/duplicate-id' | 'relationship/not-found' | 'relationship/external-has-no-partname' | 'oxml/unknown-namespace-prefix' | 'oxml/invalid-qname' | 'font/missing-typeface' | 'font/invalid-style-slot' | 'font/invalid-base64' | 'font/missing-source' | 'layout/unknown' | 'master/missing-title' | 'math/invalid-latex' | 'zip/unsupported-input' | 'zip/unsupported-output';
|
|
41
41
|
/**
|
|
42
42
|
* Conditions carried by `UnsupportedFeatureError`: the request is well-formed, but this build,
|
|
43
43
|
* runtime, or shape cannot express it. Distinct from `InvalidOptionError` because the caller did
|
|
@@ -63,7 +63,19 @@ type MediaErrorCode = 'media/load-failed' | 'font/fetch-failed' | 'font/read-fai
|
|
|
63
63
|
* which is exactly why it is worth being able to tell apart from the four classes above.
|
|
64
64
|
*/
|
|
65
65
|
type InternalErrorCode = 'layout/default-not-registered' | 'slide/rel-index-out-of-range' | 'import/part-went-missing' | 'animation/timing-scaffold-failed' | 'oxml/node-has-no-document' | 'oxml/node-has-no-parent';
|
|
66
|
-
/**
|
|
66
|
+
/**
|
|
67
|
+
* Every condition the library can throw. See {@link TsPptxCode} for the whole vocabulary.
|
|
68
|
+
*
|
|
69
|
+
* **Which of these is worth reporting upstream.** An `InternalErrorCode` always is, and the error
|
|
70
|
+
* carrying it says so at runtime. A `PackageReadErrorCode` on a file that opens cleanly in
|
|
71
|
+
* PowerPoint, a `MediaErrorCode` on an asset every other tool loads, and an
|
|
72
|
+
* `UnsupportedFeatureErrorCode` for something PowerPoint can plainly express are all gaps on our
|
|
73
|
+
* side rather than bad input — the project's supported bar is "the output opens cleanly in
|
|
74
|
+
* Microsoft PowerPoint", and it reads in both directions. An `InvalidOptionErrorCode` is worth
|
|
75
|
+
* reporting only if the deck it refused is one PowerPoint can express.
|
|
76
|
+
*
|
|
77
|
+
* `npx skills add shbernal/ts-pptx` installs the skill that walks through filing one.
|
|
78
|
+
*/
|
|
67
79
|
type ErrorCode = InvalidOptionErrorCode | UnsupportedFeatureErrorCode | PackageReadErrorCode | MediaErrorCode | InternalErrorCode;
|
|
68
80
|
/** Every condition the library can report, warned or thrown. */
|
|
69
81
|
type TsPptxCode = DiagnosticCode | ErrorCode;
|
|
@@ -150,6 +162,16 @@ declare class MediaError extends TsPptxError {
|
|
|
150
162
|
* No consumer input should be able to produce one, which is the whole reason it is a separate
|
|
151
163
|
* class: seeing it means the bug is in ts-pptx, and the useful response is to file it rather than
|
|
152
164
|
* to keep adjusting the input.
|
|
165
|
+
*
|
|
166
|
+
* It is the one class in the taxonomy that extends its own message, appending `REPORT_NOTICE`
|
|
167
|
+
* below the invariant that broke. The constructor is where that lives so a throw site added later
|
|
168
|
+
* inherits it — the alternative, a notice pasted at each of the sites, is one every future site can
|
|
169
|
+
* forget. Every other class leaves `message` exactly as given: a malformed package is the routine
|
|
170
|
+
* outcome for a library that reads untrusted files, and a "report this" banner on each corrupt
|
|
171
|
+
* input would train callers to ignore the one banner that always means something.
|
|
172
|
+
*
|
|
173
|
+
* This does not make the message API — see the class doc on {@link TsPptxError}. Branch on
|
|
174
|
+
* `instanceof` or on {@link InternalError.code}, never on the text.
|
|
153
175
|
*/
|
|
154
176
|
declare class InternalError extends TsPptxError {
|
|
155
177
|
readonly code: InternalErrorCode;
|
|
@@ -157,4 +179,4 @@ declare class InternalError extends TsPptxError {
|
|
|
157
179
|
}
|
|
158
180
|
//#endregion
|
|
159
181
|
export { TsPptxError as a, DiagnosticCode as c, InvalidOptionErrorCode as d, MediaErrorCode as f, UnsupportedFeatureErrorCode as h, PackageReadError as i, ErrorCode as l, TsPptxCode as m, InvalidOptionError as n, TsPptxErrorOptions as o, PackageReadErrorCode as p, MediaError as r, UnsupportedFeatureError as s, InternalError as t, InternalErrorCode as u };
|
|
160
|
-
//# sourceMappingURL=errors-
|
|
182
|
+
//# sourceMappingURL=errors-BeUEkNWL.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors-BeUEkNWL.d.ts","names":[],"sources":["../src/codes.ts","../src/errors.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAgCY;;;;;;;KAwHA;;;;;;KAsIA;;;;;;KAsBA;;;;;;;KA8BA;;;;;;KAiBA;;;;;;;;;;;;;;KAuBA,YACT,yBACA,8BACA,uBACA,iBACA;;KAGS,aAAa,iBAAiB;;;;UCtVzB,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"}
|
|
@@ -76,18 +76,37 @@ var MediaError = class extends TsPptxError {
|
|
|
76
76
|
}
|
|
77
77
|
};
|
|
78
78
|
/**
|
|
79
|
+
* Where a report of an `InternalError` should go. Appended to the message rather than left to the
|
|
80
|
+
* docs, because a stack trace is the only artefact of the failure that reaches whoever (or
|
|
81
|
+
* whatever) is debugging it — a pointer anywhere else is a pointer they have to already be looking
|
|
82
|
+
* for. Most code that calls this library is written by an agent in a repository that is not this
|
|
83
|
+
* one, and an agent that hits a library defect routes around it silently unless something in front
|
|
84
|
+
* of it says the report is worth making.
|
|
85
|
+
*/
|
|
86
|
+
const REPORT_NOTICE = "This is a bug in ts-pptx, not in your deck or your code. Please report it:\nhttps://github.com/shbernal/ts-pptx/issues/new?template=agent-report.yml";
|
|
87
|
+
/**
|
|
79
88
|
* An invariant the library maintains itself did not hold.
|
|
80
89
|
*
|
|
81
90
|
* No consumer input should be able to produce one, which is the whole reason it is a separate
|
|
82
91
|
* class: seeing it means the bug is in ts-pptx, and the useful response is to file it rather than
|
|
83
92
|
* to keep adjusting the input.
|
|
93
|
+
*
|
|
94
|
+
* It is the one class in the taxonomy that extends its own message, appending `REPORT_NOTICE`
|
|
95
|
+
* below the invariant that broke. The constructor is where that lives so a throw site added later
|
|
96
|
+
* inherits it — the alternative, a notice pasted at each of the sites, is one every future site can
|
|
97
|
+
* forget. Every other class leaves `message` exactly as given: a malformed package is the routine
|
|
98
|
+
* outcome for a library that reads untrusted files, and a "report this" banner on each corrupt
|
|
99
|
+
* input would train callers to ignore the one banner that always means something.
|
|
100
|
+
*
|
|
101
|
+
* This does not make the message API — see the class doc on {@link TsPptxError}. Branch on
|
|
102
|
+
* `instanceof` or on {@link InternalError.code}, never on the text.
|
|
84
103
|
*/
|
|
85
104
|
var InternalError = class extends TsPptxError {
|
|
86
105
|
constructor(code, message, options) {
|
|
87
|
-
super(code, message
|
|
106
|
+
super(code, `${message}\n\n${REPORT_NOTICE}`, options);
|
|
88
107
|
}
|
|
89
108
|
};
|
|
90
109
|
//#endregion
|
|
91
110
|
export { TsPptxError as a, PackageReadError as i, InvalidOptionError as n, UnsupportedFeatureError as o, MediaError as r, InternalError as t };
|
|
92
111
|
|
|
93
|
-
//# sourceMappingURL=errors-
|
|
112
|
+
//# sourceMappingURL=errors-Bvln0H-7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors-Bvln0H-7.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\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.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":";;;;;;;;AA2DA,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"}
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fit-DhMbQG5O.js","names":[],"sources":["../src/measure/font-metrics.ts","../src/measure/text-fit.ts","../src/measure/paragraphs.ts","../src/measure/table-fit.ts","../src/measure/fit.ts"],"sourcesContent":["/**\n * PptxGenJS: Write-side font metrics\n *\n * Provides per-glyph advance widths for measured text fit (see `text-fit.ts`).\n * The library has no write-side font registration otherwise; consumers register\n * a face's font file via `pptx.registerFontMetrics(...)` and the measured-fit\n * pass uses these advances to compute a baked `fontScale` for `fit: 'shrink'`.\n *\n * Width is summed from **raw `hmtx` advances with no kerning/shaping** (GPOS/GSUB\n * are deliberately ignored): kerning almost always narrows a line, so raw advances\n * over-estimate width — the conservative direction (shrink a touch too much, never\n * overflow). See `PLAN-measured-text-fit.md` §1.\n */\n\nimport { UnsupportedFeatureError } from '../errors.js'\nimport type { MetricsResolver } from './text-fit.js'\n\n/** Per-(face,bold,italic) advance-width source backed by a parsed font file. */\nexport interface FontMetrics {\n\t/** Font design units per em (advances are in these units). */\n\treadonly unitsPerEm: number\n\t/**\n\t * Advance width of `text` at `sizePt`, in points. Sums raw glyph advances\n\t * (no kerning) and adds `charSpacingPt` after every character, matching how\n\t * PowerPoint widens runs with character spacing.\n\t */\n\tadvanceWidthPt: (text: string, sizePt: number, charSpacingPt?: number) => number\n\t/**\n\t * True if this face's cmap maps code point `cp` to a real glyph (not the\n\t * `.notdef` fallback). Use it to flag source code points the face cannot\n\t * render. Authoritative only for file-backed metrics; the unregistered-font\n\t * heuristic has no cmap and reports every code point as covered.\n\t */\n\thasCodepoint: (cp: number) => boolean\n}\n\n/** Minimal slice of an opentype.js `Font` that `OpentypeFontMetrics` relies on. */\ninterface OpentypeFontLike {\n\tunitsPerEm: number\n\tcharToGlyph: (ch: string) => { advanceWidth?: number } | undefined\n\thasChar: (ch: string) => boolean\n}\n\nclass OpentypeFontMetrics implements FontMetrics {\n\tprivate readonly font: OpentypeFontLike\n\tconstructor(font: OpentypeFontLike) {\n\t\tthis.font = font\n\t}\n\n\tget unitsPerEm(): number {\n\t\treturn this.font.unitsPerEm\n\t}\n\n\tadvanceWidthPt(text: string, sizePt: number, charSpacingPt = 0): number {\n\t\tif (!text) return 0\n\t\t// Sum raw per-glyph `hmtx` advances via cmap (charToGlyph) — deliberately\n\t\t// NOT getAdvanceWidth(), which runs GPOS/GSUB shaping (kerning narrows lines,\n\t\t// and some lookups even throw). Raw advances over-estimate width, the\n\t\t// conservative direction. `for..of` iterates code points (astral-safe).\n\t\tconst scale = sizePt / this.font.unitsPerEm\n\t\tlet width = 0\n\t\tlet count = 0\n\t\tfor (const ch of text) {\n\t\t\tconst glyph = this.font.charToGlyph(ch)\n\t\t\twidth += (glyph?.advanceWidth ?? 0) * scale\n\t\t\tcount++\n\t\t}\n\t\tif (charSpacingPt) width += charSpacingPt * count\n\t\treturn width\n\t}\n\n\thasCodepoint(cp: number): boolean {\n\t\t// opentype's charToGlyph() falls back to .notdef for uncovered code points,\n\t\t// so it can't answer coverage; hasChar() keys on the cmap (glyph index > 0).\n\t\treturn this.font.hasChar(String.fromCodePoint(cp))\n\t}\n}\n\nconst HEURISTIC_UNITS_PER_EM = 1000\n\n/**\n * Advance width of an ASCII/Unicode code point as a fraction of em, for the\n * unregistered-font fallback. Values are biased to **over-estimate** a typical\n * proportional Latin face: over-estimating width is the conservative direction for\n * both solvers (shrink a touch too much / grow a touch too tall, never overflow).\n * Non-Latin code points are treated as full-em (safe for CJK, which is otherwise\n * out of scope; slightly over-wide for accented Latin, which is harmless).\n */\nfunction heuristicCharRatio(ch: string): number {\n\tconst cp = ch.codePointAt(0) ?? 0\n\tif (cp > 0x2e7f) return 1.0 // CJK / full-width and beyond\n\tif (cp > 0xff) return 0.62 // Latin-Extended / accented / misc symbols\n\tif (ch === ' ' || ch === '\\t') return 0.3\n\tif (\"ijl.,'`!|:;\".includes(ch)) return 0.3\n\tif ('ftr()[]{}/\\\\I'.includes(ch)) return 0.4\n\tif (ch === 'm' || ch === 'w') return 0.9\n\tif (ch === 'M' || ch === 'W') return 0.98\n\tif (ch === '@' || ch === '%') return 1.0\n\tif (ch >= 'A' && ch <= 'Z') return 0.72\n\treturn 0.58 // lowercase, digits, default punctuation\n}\n\nclass HeuristicFontMetrics implements FontMetrics {\n\treadonly unitsPerEm = HEURISTIC_UNITS_PER_EM\n\tadvanceWidthPt(text: string, sizePt: number, charSpacingPt = 0): number {\n\t\tif (!text) return 0\n\t\tlet width = 0\n\t\tlet count = 0\n\t\tfor (const ch of text) {\n\t\t\twidth += heuristicCharRatio(ch) * sizePt\n\t\t\tcount++\n\t\t}\n\t\tif (charSpacingPt) width += charSpacingPt * count\n\t\treturn width\n\t}\n\n\thasCodepoint(): boolean {\n\t\treturn true // no cmap to consult; never fabricate a 'missing' glyph\n\t}\n}\n\nlet heuristicSingleton: FontMetrics | undefined\n\n/**\n * Shared, font-independent `FontMetrics` used when a named face has no registered\n * metrics but the deck has opted into measured fit (some other face is registered).\n * Approximate but conservative — see {@link heuristicCharRatio}. A deck with no\n * registered metrics at all does not engage measured fit, so this never fires there.\n */\nexport function getHeuristicFontMetrics(): FontMetrics {\n\tif (!heuristicSingleton) heuristicSingleton = new HeuristicFontMetrics()\n\treturn heuristicSingleton\n}\n\n/** Parse a font file (TTF/OTF) into a `FontMetrics`. Lazily imports opentype.js. */\nexport async function parseFontMetrics(data: Uint8Array): Promise<FontMetrics> {\n\t// Dynamic import keeps opentype.js off the critical/browser path until a\n\t// consumer actually registers metrics.\n\tconst mod = (await import('opentype.js')) as unknown as {\n\t\tparse?: (buf: ArrayBuffer) => OpentypeFontLike\n\t\tdefault?: { parse: (buf: ArrayBuffer) => OpentypeFontLike }\n\t}\n\tconst parse = mod.parse ?? mod.default?.parse\n\tif (typeof parse !== 'function')\n\t\tthrow new UnsupportedFeatureError('font/opentype-unavailable', 'opentype.js: parse() not found in module exports')\n\t// opentype.parse needs a standalone ArrayBuffer view of exactly the font bytes.\n\tconst buf = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength) as ArrayBuffer\n\treturn new OpentypeFontMetrics(parse(buf))\n}\n\n/**\n * Registry of `FontMetrics` keyed by `(face, bold, italic)`. Variant advances\n * differ, so bold/italic are stored separately; lookup falls back to the regular\n * variant (then any registered variant of the face) so a deck that only registers\n * the regular weight still measures bold runs approximately rather than not at all.\n */\nexport class FontMetricsRegistry {\n\tprivate readonly map = new Map<string, FontMetrics>()\n\n\tprivate key(face: string, bold: boolean, italic: boolean): string {\n\t\treturn `${face.toLowerCase()}\u0000${bold ? 1 : 0}\u0000${italic ? 1 : 0}`\n\t}\n\n\tset(face: string, metrics: FontMetrics, opts?: { bold?: boolean; italic?: boolean }): void {\n\t\tthis.map.set(this.key(face, !!opts?.bold, !!opts?.italic), metrics)\n\t}\n\n\t/** True if any variant of `face` has registered metrics. */\n\thasFace(face: string): boolean {\n\t\tconst prefix = `${face.toLowerCase()}\u0000`\n\t\tfor (const k of this.map.keys()) if (k.startsWith(prefix)) return true\n\t\treturn false\n\t}\n\n\t/**\n\t * Coverage of code point `cp` for `face`, read from the registered font's cmap:\n\t * `true`/`false` when a variant of `face` is registered (see {@link get} for the\n\t * exact→regular→any-variant fallback), or `undefined` when the face has **no**\n\t * registered metrics — \"unknown\", deliberately distinct from a `false`\n\t * \"registered but not covered\". A coverage audit must not treat an unregistered\n\t * face as fully covered, so callers get `undefined` here rather than the per-face\n\t * {@link FontMetrics.hasCodepoint} boolean (which, for the heuristic fallback,\n\t * always reports covered). Register the face via {@link parseFontMetrics} +\n\t * {@link set} first.\n\t */\n\thasCodepoint(\n\t\tface: string | undefined | null,\n\t\tcp: number,\n\t\topts?: { bold?: boolean; italic?: boolean }\n\t): boolean | undefined {\n\t\treturn this.get(face, opts?.bold, opts?.italic)?.hasCodepoint(cp)\n\t}\n\n\t/** Resolve metrics for a run, falling back from exact variant → regular → any variant. */\n\tget(face: string | undefined | null, bold = false, italic = false): FontMetrics | undefined {\n\t\t// A run with no explicit face inherits the theme font, which we cannot resolve\n\t\t// reliably here — treat as unregistered so measured fit degrades gracefully.\n\t\tif (typeof face !== 'string' || face.length === 0) return undefined\n\t\tconst exact = this.map.get(this.key(face, bold, italic))\n\t\tif (exact) return exact\n\t\tconst regular = this.map.get(this.key(face, false, false))\n\t\tif (regular) return regular\n\t\tconst prefix = `${face.toLowerCase()}\u0000`\n\t\tfor (const [k, v] of this.map) if (k.startsWith(prefix)) return v\n\t\treturn undefined\n\t}\n\n\tget size(): number {\n\t\treturn this.map.size\n\t}\n}\n\n/**\n * A {@link MetricsResolver} backed by a registry: exact metrics for a registered face, otherwise\n * the shared heuristic fallback (with `onHeuristic` told which face it stood in for). A run with\n * no `fontFace` at all resolves to `undefined`, which the callers treat as unmeasurable.\n */\nexport function makeRegistryResolver(\n\tregistry: FontMetricsRegistry,\n\tonHeuristic?: (face: string) => void\n): MetricsResolver {\n\treturn (run) => {\n\t\tconst exact = registry.get(run.fontFace, run.bold, run.italic)\n\t\tif (exact) return exact\n\t\tif (typeof run.fontFace === 'string' && run.fontFace.length > 0) {\n\t\t\tonHeuristic?.(run.fontFace)\n\t\t\treturn getHeuristicFontMetrics()\n\t\t}\n\t\treturn undefined\n\t}\n}\n","/**\n * ts-pptx: Measured text fit (line-break simulator + shrink solver)\n *\n * Computes a baked `fontScale` for `fit: 'shrink'` so overflowing text renders\n * pre-shrunk in headless renderers (and on plain file-open) without a manual\n * edit/resize. See `docs/measured-text-fit.md`.\n *\n * Calibration: every constant here is pinned against PowerPoint-authored fixtures\n * (`test/read/fixtures/autofit-calibration.json`). The model errs **conservative**\n * — it over-estimates width (raw advances, no kerning) and uses the calibrated\n * line pitch — so the computed `fontScale` is ≤ PowerPoint's and the text never\n * overflows in either PowerPoint or LibreOffice.\n */\n\nimport type { FontMetrics } from './font-metrics.js'\n\n/**\n * PowerPoint single-spacing line pitch as a multiple of font size.\n *\n * Calibrated from `autofit-calibration.json` (Deck 1, `autofit-line-metrics`):\n * the per-line `cy` delta is a **font-independent** 1.2117× at 12/18/32 pt across\n * {Aptos, Aptos SemiBold, Calibri, Tahoma, Arial}, and PowerPoint vs LibreOffice\n * agree to ≤ 0.041 pt. See `test/read/fixtures/README.md` → \"Findings\" #1–#2.\n */\nexport const SINGLE_LINE_PITCH = 1.2117\n\n/** PowerPoint's `fontScale` search grid: discrete 2.5% steps (Findings #3). */\nexport const FONT_SCALE_STEP_PCT = 2.5\n\n/** Floor for the shrink search (see `docs/measured-text-fit.md` → Solvers). */\nexport const MIN_FONT_SCALE_PCT = 25\n\n/**\n * Conservative safety factors applied by the shrink solver (not by the pure\n * `measureHeightPt`). Raw `hmtx` advances summed without shaping still pack a line\n * a little tighter than PowerPoint, which lays text out at a device DPI and rounds\n * each glyph advance up — so PowerPoint wraps marginally earlier and its fitted\n * box is marginally taller. Inflating measured width and height by these factors\n * makes the computed `fontScale` ≤ PowerPoint's across the calibration oracle\n * (`test/read/autofit-calibration-oracle.test.js`: 0 violations over the Aptos\n * cases). They err on the side of shrinking slightly too much, never overflowing.\n */\nexport const WIDTH_SAFETY_FACTOR = 1.03\nexport const HEIGHT_SAFETY_FACTOR = 1.04\n\n/** One text run with the inputs measurement needs. */\nexport interface FitRun {\n\ttext: string\n\tsizePt: number\n\tbold?: boolean\n\titalic?: boolean\n\tfontFace?: string\n\t/** Character spacing in points (PowerPoint `spc`/1200). */\n\tcharSpacingPt?: number\n}\n\n/** One paragraph: its runs plus vertical-rhythm options. */\nexport interface FitParagraph {\n\truns: FitRun[]\n\t/** Line spacing as a percent of single (100 = single). Ignored if `lineSpacingPts` set. */\n\tlineSpacingPct?: number\n\t/** Exact line spacing in points (overrides `lineSpacingPct`). */\n\tlineSpacingPts?: number\n\tspaceBeforePts?: number\n\tspaceAfterPts?: number\n}\n\n/** Inner box (shape minus insets) the text must fit, in points. */\nexport interface FitBox {\n\tinnerWidthPt: number\n\tinnerHeightPt: number\n\t/**\n\t * `false` when the frame does not wrap (`wrap:false` / `wrap=\"none\"`): text lays\n\t * out as one line per paragraph (no width-wrapping), and the shrink solver must\n\t * additionally keep the widest line within `innerWidthPt`. A too-wide line\n\t * overflows HORIZONTALLY — `normAutofit`'s vertical shrink never catches it, so\n\t * without this check a non-wrapping line is never shrunk and spills out of the box\n\t * in PowerPoint. Defaults to wrapping (`true`), so table cells and `measureText`\n\t * are unaffected.\n\t */\n\twrap?: boolean\n}\n\n/** Resolve the metrics for a run, or `undefined` if the face is not registered. */\nexport type MetricsResolver = (run: FitRun) => FontMetrics | undefined\n\nexport interface ShrinkResult {\n\tfontScalePct: number\n\tlnSpcReductionPct: number\n}\n\nexport type ShrinkOutcome =\n\t| { kind: 'fits' } // already fits at 100% — no shrink needed\n\t| { kind: 'unmeasurable' } // a run's face has no registered metrics — caller degrades\n\t| { kind: 'shrink'; result: ShrinkResult }\n\ninterface WordToken {\n\tkind: 'word'\n\tw: number\n\tcharWidths: number[]\n}\ntype Token = WordToken | { kind: 'space'; w: number } | { kind: 'newline'; w: 0 }\n\nconst isWhitespace = (ch: string): boolean => ch === ' ' || ch === '\\t' || ch === ' ' || /\\s/.test(ch)\n\n/**\n * Tokenize one paragraph at a given `fontScalePct`. Words can span run boundaries\n * (a break is only allowed at whitespace). Returns `null` if any run's face has no\n * registered metrics (the paragraph cannot be measured).\n */\nfunction tokenizeParagraph(\n\tpara: FitParagraph,\n\tresolve: MetricsResolver,\n\tfontScalePct: number,\n\twidthSafety: number\n): Token[] | null {\n\tconst tokens: Token[] = []\n\tlet curWord: WordToken | null = null\n\tconst flushWord = (): void => {\n\t\tif (curWord) {\n\t\t\ttokens.push(curWord)\n\t\t\tcurWord = null\n\t\t}\n\t}\n\tfor (const run of para.runs) {\n\t\tconst metrics = resolve(run)\n\t\tif (!metrics) return null\n\t\tconst scaledSize = run.sizePt * (fontScalePct / 100)\n\t\tconst charSpacingPt = run.charSpacingPt ?? 0\n\t\tfor (const ch of run.text ?? '') {\n\t\t\tif (ch === '\\n') {\n\t\t\t\tflushWord()\n\t\t\t\ttokens.push({ kind: 'newline', w: 0 })\n\t\t\t} else if (isWhitespace(ch)) {\n\t\t\t\tflushWord()\n\t\t\t\t// Tabs are approximated as a single space-width gap (documented P1 gap).\n\t\t\t\tconst w = metrics.advanceWidthPt(ch === '\\t' ? ' ' : ch, scaledSize, charSpacingPt) * widthSafety\n\t\t\t\ttokens.push({ kind: 'space', w })\n\t\t\t} else {\n\t\t\t\tconst w = metrics.advanceWidthPt(ch, scaledSize, charSpacingPt) * widthSafety\n\t\t\t\tif (!curWord) curWord = { kind: 'word', w: 0, charWidths: [] }\n\t\t\t\tcurWord.w += w\n\t\t\t\tcurWord.charWidths.push(w)\n\t\t\t}\n\t\t}\n\t}\n\tflushWord()\n\treturn tokens\n}\n\n/** Greedy `wrap=square` line layout for a tokenized paragraph. */\ninterface LineLayout {\n\tlines: number\n\t/** Width (points) of the widest laid-out line — for natural/widest-line measurement. */\n\tmaxLineWidthPt: number\n}\n\n/**\n * Greedy `wrap=square` line layout: the wrapped line count plus the widest\n * laid-out line width. `maxLineWidthPt` tracks the running line width and records\n * it whenever a line completes (a wrap or the final line), so callers can measure\n * the actual text extent, not just the box width. Trailing whitespace counts\n * toward width (Findings #7), which slightly over-reports — the conservative\n * direction, consistent with the wrap model erring wide.\n */\nfunction countLines(tokens: Token[], innerWidthPt: number): LineLayout {\n\tlet lines = 1\n\tlet lineW = 0\n\tlet maxLineWidthPt = 0\n\tconst finishLine = (): void => {\n\t\tif (lineW > maxLineWidthPt) maxLineWidthPt = lineW\n\t}\n\tfor (const tok of tokens) {\n\t\tif (tok.kind === 'newline') {\n\t\t\tfinishLine()\n\t\t\tlines++\n\t\t\tlineW = 0\n\t\t} else if (tok.kind === 'space') {\n\t\t\t// Trailing whitespace counts toward line width (Findings #7); if it\n\t\t\t// overflows, the line wraps and the space is consumed at the break.\n\t\t\tif (lineW + tok.w > innerWidthPt && lineW > 0) {\n\t\t\t\tfinishLine()\n\t\t\t\tlines++\n\t\t\t\tlineW = 0\n\t\t\t} else {\n\t\t\t\tlineW += tok.w\n\t\t\t}\n\t\t} else if (tok.w <= innerWidthPt) {\n\t\t\tif (lineW + tok.w > innerWidthPt && lineW > 0) {\n\t\t\t\tfinishLine()\n\t\t\t\tlines++\n\t\t\t\tlineW = tok.w\n\t\t\t} else {\n\t\t\t\tlineW += tok.w\n\t\t\t}\n\t\t} else {\n\t\t\t// Over-long unbreakable word → character-wrap (Findings #7).\n\t\t\tif (lineW > 0) {\n\t\t\t\tfinishLine()\n\t\t\t\tlines++\n\t\t\t\tlineW = 0\n\t\t\t}\n\t\t\tfor (const cw of tok.charWidths) {\n\t\t\t\tif (lineW + cw > innerWidthPt && lineW > 0) {\n\t\t\t\t\tfinishLine()\n\t\t\t\t\tlines++\n\t\t\t\t\tlineW = cw\n\t\t\t\t} else {\n\t\t\t\t\tlineW += cw\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfinishLine()\n\treturn { lines, maxLineWidthPt }\n}\n\n/** Max run size in a paragraph (line height follows the tallest run — Findings #7). */\nfunction maxRunSizePt(para: FitParagraph): number {\n\tlet max = 0\n\tfor (const run of para.runs) if (run.sizePt > max) max = run.sizePt\n\treturn max\n}\n\n/** Laid-out result of {@link measureLayout}: total height (points) + wrapped line count. */\nexport interface LayoutResult {\n\theightPt: number\n\tlineCount: number\n\t/**\n\t * Width (points) of the widest laid-out line across all paragraphs. Useful for\n\t * tightening a box to the actual text extent or measuring a natural (single-line)\n\t * width. Carries the same `widthSafety` inflation as the wrap decision, so a box\n\t * set to this width will not re-wrap. Conservative (slightly wide).\n\t */\n\twidestLineWidthPt: number\n}\n\n/**\n * Lay out `paragraphs` at a given scale/reduction and return the total height\n * (points) and wrapped line count, or `null` if any paragraph is unmeasurable.\n * Errs tall (conservative): includes space-before/after and the calibrated line\n * pitch. The single source of truth for both {@link measureHeightPt} (the solvers)\n * and the public layout-time measure API.\n */\nexport function measureLayout(\n\tparagraphs: FitParagraph[],\n\tinnerWidthPt: number,\n\tresolve: MetricsResolver,\n\tfontScalePct: number,\n\tlnSpcReductionPct: number,\n\twidthSafety = 1\n): LayoutResult | null {\n\tif (innerWidthPt <= 0) return null\n\tlet total = 0\n\tlet lineCount = 0\n\tlet widestLineWidthPt = 0\n\tfor (const para of paragraphs) {\n\t\tconst tokens = tokenizeParagraph(para, resolve, fontScalePct, widthSafety)\n\t\tif (tokens === null) return null\n\t\tconst { lines, maxLineWidthPt } = countLines(tokens, innerWidthPt)\n\t\tlineCount += lines\n\t\tif (maxLineWidthPt > widestLineWidthPt) widestLineWidthPt = maxLineWidthPt\n\t\tconst scaledMax = maxRunSizePt(para) * (fontScalePct / 100)\n\t\tlet lineHeight =\n\t\t\tpara.lineSpacingPts != null && para.lineSpacingPts > 0\n\t\t\t\t? para.lineSpacingPts\n\t\t\t\t: SINGLE_LINE_PITCH * scaledMax * ((para.lineSpacingPct ?? 100) / 100)\n\t\tlineHeight *= 1 - lnSpcReductionPct / 100\n\t\ttotal += lines * lineHeight + (para.spaceBeforePts ?? 0) + (para.spaceAfterPts ?? 0)\n\t}\n\treturn { heightPt: total, lineCount, widestLineWidthPt }\n}\n\n/**\n * Total laid-out height (points) at a given scale/reduction, or `null` if any\n * paragraph is unmeasurable. Thin wrapper over {@link measureLayout}.\n */\nexport function measureHeightPt(\n\tparagraphs: FitParagraph[],\n\tinnerWidthPt: number,\n\tresolve: MetricsResolver,\n\tfontScalePct: number,\n\tlnSpcReductionPct: number,\n\twidthSafety = 1\n): number | null {\n\tconst result = measureLayout(paragraphs, innerWidthPt, resolve, fontScalePct, lnSpcReductionPct, widthSafety)\n\treturn result === null ? null : result.heightPt\n}\n\n/**\n * Largest `fontScale` (on PowerPoint's 2.5% grid) at which the text fits the box.\n * Width and height both re-measured per scale. Conservative: because the model\n * over-estimates, the returned scale is ≤ PowerPoint's and the text never overflows.\n *\n * `lnSpcReduction` is left at 0 in P1 — dropping `fontScale` alone is provably\n * conservative (PowerPoint trades line-spacing reduction to keep the font *larger*,\n * so a reduction-free fit is always ≤ PowerPoint's scale). The calibration data for\n * the reduction ramp (Findings #4) is recorded for a future refinement.\n */\nexport type ResizeOutcome =\n\t| { kind: 'unmeasurable' } // a run's face has no registered metrics — caller degrades\n\t| { kind: 'resize'; neededInnerHeightPt: number }\n\n/**\n * Inner height (points) the text needs at full size — the value to bake into the\n * shape's `a:ext/@cy` for `fit: 'resize'` (`spAutoFit`). Unlike shrink, resize has\n * **no safety net**: an under-estimate overflows (there is no text scaling\n * fallback), so this errs **tall** — width is inflated (earlier wrap ⇒ more lines)\n * and the laid-out height by the calibrated height factor, so the computed `cy` is\n * ≥ PowerPoint's and ≥ the LibreOffice-rendered height across the resize oracle.\n */\n/**\n * Width used for wrap layout: the inner box width when wrapping, or unbounded for a\n * non-wrapping frame (`wrap:false`) so each paragraph lays out as a single line. A\n * non-wrapping frame's width constraint is enforced separately, against the widest\n * laid-out line — see {@link solveShrink}.\n */\nfunction layoutWidthPt(box: FitBox): number {\n\treturn box.wrap === false ? Infinity : box.innerWidthPt\n}\n\nexport function solveResize(paragraphs: FitParagraph[], box: FitBox, resolve: MetricsResolver): ResizeOutcome {\n\tconst h = measureHeightPt(paragraphs, layoutWidthPt(box), resolve, 100, 0, WIDTH_SAFETY_FACTOR)\n\tif (h === null) return { kind: 'unmeasurable' }\n\treturn { kind: 'resize', neededInnerHeightPt: h * HEIGHT_SAFETY_FACTOR }\n}\n\nexport function solveShrink(paragraphs: FitParagraph[], box: FitBox, resolve: MetricsResolver): ShrinkOutcome {\n\tconst width = layoutWidthPt(box)\n\tconst noWrap = box.wrap === false\n\t// Inflate measured width (earlier wrap) and height by the calibrated safety\n\t// factors so the fit threshold is conservative against PowerPoint. For a\n\t// non-wrapping frame the single line always fits the box HEIGHT, so height alone\n\t// never triggers a shrink: also require the widest (unwrapped) line to fit the box\n\t// WIDTH. `widestLineWidthPt` already carries the WIDTH_SAFETY_FACTOR inflation, so\n\t// comparing it straight to `innerWidthPt` stays on the conservative (shrink-more) side.\n\tconst fits = (scale: number): boolean | null => {\n\t\tconst layout = measureLayout(paragraphs, width, resolve, scale, 0, WIDTH_SAFETY_FACTOR)\n\t\tif (layout === null) return null\n\t\tif (layout.heightPt * HEIGHT_SAFETY_FACTOR > box.innerHeightPt) return false\n\t\tif (noWrap && layout.widestLineWidthPt > box.innerWidthPt) return false\n\t\treturn true\n\t}\n\n\tconst at100 = fits(100)\n\tif (at100 === null) return { kind: 'unmeasurable' }\n\tif (at100) return { kind: 'fits' }\n\n\tfor (let scale = 100 - FONT_SCALE_STEP_PCT; scale >= MIN_FONT_SCALE_PCT; scale -= FONT_SCALE_STEP_PCT) {\n\t\tif (fits(scale)) return { kind: 'shrink', result: { fontScalePct: scale, lnSpcReductionPct: 0 } }\n\t}\n\t// Even at the floor it overflows our conservative model — bake the floor as best effort.\n\treturn { kind: 'shrink', result: { fontScalePct: MIN_FONT_SCALE_PCT, lnSpcReductionPct: 0 } }\n}\n","/**\n * ts-pptx: turning a slide text object into the simulator's inputs\n *\n * The lower half of the measured-fit pass: normalize a text object's runs into `FitParagraph`s,\n * resolve its body insets and box, and work out how a height change is shared between `off.y` and\n * `ext.cy` for a given anchor. Everything here is about *reading* an authored object; the solving\n * and the rewriting live in the siblings (`table-fit.ts`, `fit.ts`).\n */\n\nimport { DEF_FONT_SIZE } from '../constants-internal.js'\nimport { EMU_PER_POINT } from '../units.js'\nimport { getSmartParseNumber, marginToEmu } from '../units-internal.js'\nimport type { FitBox, FitParagraph, FitRun } from './text-fit.js'\nimport { TextAnchor } from '../enums.js'\nimport type { ObjectOptions, TextProps, TextPropsOptions } from '../types/index.js'\nimport type { SlideObject, PresSlideInternal } from '../types/internal.js'\n\n// PowerPoint's default text-frame insets (EMU): l/r = 0.1in, t/b = 0.05in.\nconst DEF_INS_LR_EMU = 91440\nconst DEF_INS_TB_EMU = 45720\n\nconst CRLF_RE = /\\r*\\n/g\n\nexport type RunOpts = TextPropsOptions & ObjectOptions\n\n/** Normalize `slideObj.text` (string | TextProps | TextProps[]) to a run list. */\nexport function normalizeRuns(obj: SlideObject): TextProps[] {\n\tconst opts = obj.options ?? {}\n\tconst text = obj.text as unknown\n\tif (text == null) return []\n\tif (typeof text === 'string' || typeof text === 'number') return [{ text: String(text), options: opts }]\n\tif (!Array.isArray(text) && typeof text === 'object' && 'text' in text) {\n\t\tconst t = text as TextProps\n\t\treturn [{ text: t.text, options: t.options ?? opts }]\n\t}\n\tif (Array.isArray(text)) return (text as TextProps[]).map((t) => ({ text: t.text, options: t.options ?? opts }))\n\treturn []\n}\n\n/** Build a measurable `FitParagraph[]` from a text object, or null if not measurable. */\nexport function extractParagraphs(obj: SlideObject): FitParagraph[] | null {\n\tconst opts = (obj.options ?? {}) as RunOpts\n\tconst runs = normalizeRuns(obj)\n\tif (runs.length === 0) return null\n\treturn buildFitParagraphs(runs, opts)\n}\n\n/**\n * Convert a run list (+ box-level default options) into a measurable\n * `FitParagraph[]`, or null if empty. The single converter shared by the\n * export-time pass ({@link extractParagraphs}) and the public layout-time\n * `measureText` API, so a layout-time prediction and the baked export never drift.\n */\nexport function buildFitParagraphs(runs: TextProps[], opts: RunOpts): FitParagraph[] | null {\n\tif (runs.length === 0) return null\n\n\t// Expand \"\\n\" inside a run into separate pieces, flagging the paragraph break\n\t// after each (mirrors `gen/slide/objects/table.ts` STEP 4). `breakLine` ends a paragraph too.\n\tinterface Piece {\n\t\ttext: string\n\t\toptions: RunOpts\n\t\tbreakAfter: boolean\n\t}\n\tconst pieces: Piece[] = []\n\tfor (const run of runs) {\n\t\tconst ro = (run.options ?? opts) as RunOpts\n\t\tconst raw = String(run.text ?? '').replace(CRLF_RE, '\\n')\n\t\tif (raw.includes('\\n')) {\n\t\t\tconst lines = raw.split('\\n')\n\t\t\tlines.forEach((line, i) => {\n\t\t\t\tconst isLast = i === lines.length - 1\n\t\t\t\tpieces.push({ text: line, options: ro, breakAfter: isLast ? !!ro.breakLine : true })\n\t\t\t})\n\t\t} else {\n\t\t\tpieces.push({ text: raw, options: ro, breakAfter: !!ro.breakLine })\n\t\t}\n\t}\n\n\tconst toRun = (p: Piece): FitRun => {\n\t\tconst ro = p.options\n\t\tconst sizePt = Number(ro.fontSize ?? opts.fontSize ?? DEF_FONT_SIZE)\n\t\treturn {\n\t\t\ttext: p.text,\n\t\t\tsizePt: Number.isFinite(sizePt) && sizePt > 0 ? sizePt : DEF_FONT_SIZE,\n\t\t\tbold: !!(ro.bold ?? opts.bold),\n\t\t\titalic: !!(ro.italic ?? opts.italic),\n\t\t\tfontFace: ro.fontFace ?? opts.fontFace,\n\t\t\tcharSpacingPt: (ro.charSpacing ?? opts.charSpacing) || undefined,\n\t\t}\n\t}\n\tconst toPara = (runsForPara: FitRun[], paraOpts: RunOpts): FitParagraph => {\n\t\tconst lineSpacing = paraOpts.lineSpacing ?? opts.lineSpacing\n\t\tconst lineSpacingMultiple = paraOpts.lineSpacingMultiple ?? opts.lineSpacingMultiple\n\t\treturn {\n\t\t\truns: runsForPara,\n\t\t\tlineSpacingPts: typeof lineSpacing === 'number' && lineSpacing > 0 ? lineSpacing : undefined,\n\t\t\tlineSpacingPct:\n\t\t\t\ttypeof lineSpacingMultiple === 'number' && lineSpacingMultiple > 0 ? lineSpacingMultiple * 100 : 100,\n\t\t\tspaceBeforePts: Number(paraOpts.paraSpaceBefore ?? opts.paraSpaceBefore ?? 0) || 0,\n\t\t\tspaceAfterPts: Number(paraOpts.paraSpaceAfter ?? opts.paraSpaceAfter ?? 0) || 0,\n\t\t}\n\t}\n\n\tconst paras: FitParagraph[] = []\n\tlet cur: FitRun[] = []\n\tlet curParaOpts: RunOpts = opts\n\tfor (const piece of pieces) {\n\t\tcur.push(toRun(piece))\n\t\tcurParaOpts = piece.options\n\t\tif (piece.breakAfter) {\n\t\t\tparas.push(toPara(cur, curParaOpts))\n\t\t\tcur = []\n\t\t}\n\t}\n\tif (cur.length > 0) paras.push(toPara(cur, curParaOpts))\n\treturn paras.length > 0 ? paras : null\n}\n\ninterface InsetsEmu {\n\tlIns: number\n\trIns: number\n\ttIns: number\n\tbIns: number\n}\n\n/** Resolve text-frame insets (EMU): explicit `_bodyProp` (from `inset`) → `margin` → PowerPoint defaults. */\nexport function resolveInsetsEmu(opts: RunOpts): InsetsEmu {\n\tconst bp = opts._bodyProp ?? {}\n\tconst margin = opts.margin\n\tlet lIns = bp.lIns\n\tlet rIns = bp.rIns\n\tlet tIns = bp.tIns\n\tlet bIns = bp.bIns\n\tif (lIns == null && rIns == null && tIns == null && bIns == null && margin != null) {\n\t\tif (Array.isArray(margin)) {\n\t\t\ttIns = marginToEmu(margin[0] ?? 0)\n\t\t\trIns = marginToEmu(margin[1] ?? 0)\n\t\t\tbIns = marginToEmu(margin[2] ?? 0)\n\t\t\tlIns = marginToEmu(margin[3] ?? 0)\n\t\t} else if (typeof margin === 'number') {\n\t\t\tlIns = rIns = tIns = bIns = marginToEmu(margin)\n\t\t}\n\t}\n\treturn {\n\t\tlIns: lIns ?? DEF_INS_LR_EMU,\n\t\trIns: rIns ?? DEF_INS_LR_EMU,\n\t\ttIns: tIns ?? DEF_INS_TB_EMU,\n\t\tbIns: bIns ?? DEF_INS_TB_EMU,\n\t}\n}\n\n/**\n * Resolve the inner box (shape minus insets) in points; null if degenerate.\n *\n * Reads the object's own `opts.w/h` with no ancestor walk — correct only because a group keeps an\n * identity child coordinate space (`chOff/chExt == off/ext`, see the `gen/slide/object.ts` group renderer and\n * `docs/groups.md`), so a group never scales its children and a grouped text box's authored w/h is its\n * true rendered size. `applyMeasuredFit` reaches here for grouped text via its explicit group descent\n * (`measureObject`). If `addGroup` ever authored a scaled group (non-identity `chExt`), this would need\n * the same ancestor-scale composition `Shape.absoluteFrame` performs on the read path.\n */\nexport function computeBox(obj: SlideObject, presLayout: PresSlideInternal['_presLayout']): FitBox | null {\n\tconst opts = (obj.options ?? {}) as RunOpts\n\tconst wEmu = getSmartParseNumber(opts.w, 'X', presLayout)\n\tconst hEmu = getSmartParseNumber(opts.h, 'Y', presLayout)\n\tif (!(wEmu > 0) || !(hEmu > 0)) return null\n\n\tconst { lIns, rIns, tIns, bIns } = resolveInsetsEmu(opts)\n\n\t// wrap=none lays text out one line per paragraph (no width-wrapping, handled by\n\t// the solver via the wrap flag), but the box width is still a real constraint:\n\t// solveShrink enforces it against the widest line so an over-wide non-wrapping\n\t// line shrinks to fit horizontally instead of spilling out of the box.\n\tconst wrap = (opts._bodyProp ?? {}).wrap !== false\n\tconst innerWidthPt = (wEmu - lIns - rIns) / EMU_PER_POINT\n\tconst innerHeightPt = (hEmu - tIns - bIns) / EMU_PER_POINT\n\tif (!(innerHeightPt > 0)) return null\n\tif (!(innerWidthPt > 0)) return null\n\treturn { innerWidthPt, innerHeightPt, wrap }\n}\n\n/** Vertical-anchor share of a height change that moves the box top up (`off.y` shift). */\nexport function anchorTopShareOfDelta(opts: RunOpts): number {\n\t// `_bodyProp.anchor` is the resolved valign ('t' | 'ctr' | 'b'); default 'ctr'.\n\tconst anchor = (opts._bodyProp ?? {}).anchor\n\tif (anchor === TextAnchor.t) return 0 // grow downward — top fixed\n\tif (anchor === TextAnchor.b) return 1 // grow upward — bottom fixed\n\treturn 0.5 // centered growth (default)\n}\n\n// --- Table cells -----------------------------------------------------------\n// PowerPoint has no text-autofit for table cells (`a:tcPr` carries no autofit and\n// the app ignores `normAutofit` inside a cell — rows auto-grow instead). So a cell's\n// `fit:'shrink'` is honored by baking a *reduced literal font size* onto its runs,\n// which both PowerPoint and LibreOffice render identically with no edit/resize.\n\n/** Text/format options that a cell inherits from the table when it sets none itself (mirrors `gen/slide/objects/table.ts`). */\n","/**\n * ts-pptx: measuring a table's row heights and cell fits\n *\n * A table is measured cell by cell against its resolved grid: each cell inherits the table's text\n * options where it sets none, gets its own margins resolved to EMU insets, and is laid out inside\n * the column span it actually occupies. A merged region is measured once, at its origin, across\n * the columns it covers — which is what `walkTableGrid` exists to hand out.\n */\n\nimport { DEF_CELL_MARGIN_IN, DEF_FONT_SIZE, LINEH_MODIFIER } from '../constants-internal.js'\nimport { EMU_PER_POINT, emuToInches } from '../units.js'\nimport { getSmartParseNumber, inch2Emu, marginToEmu, resolveTableColWidthsEmu } from '../units-internal.js'\nimport { measureLayout, WIDTH_SAFETY_FACTOR, HEIGHT_SAFETY_FACTOR } from './text-fit.js'\nimport { makeRegistryResolver, type FontMetricsRegistry } from './font-metrics.js'\nimport { extractParagraphs, type RunOpts } from './paragraphs.js'\nimport type {\n\tMargin,\n\tPresLayout,\n\tTableCell,\n\tTableCellLayout,\n\tTableCellProps,\n\tTableLayoutResult,\n\tTableProps,\n} from '../types/index.js'\nimport type { SlideObject } from '../types/internal.js'\n\nconst CELL_INHERIT_KEYS = [\n\t'fontFace',\n\t'fontSize',\n\t'bold',\n\t'italic',\n\t'charSpacing',\n\t'align',\n\t'lineSpacing',\n\t'lineSpacingMultiple',\n\t'valign',\n\t'margin',\n] as const\n\n/** Effective cell options: the cell's own values, with table-level values filled in where unset. */\nexport function effectiveCellOpts(cellOpts: TableCellProps, tableOpts: RunOpts): RunOpts {\n\tconst merged = { ...cellOpts } as RunOpts\n\tfor (const k of CELL_INHERIT_KEYS) {\n\t\tif (merged[k] === undefined && tableOpts[k] !== undefined) (merged as Record<string, unknown>)[k] = tableOpts[k]\n\t}\n\treturn merged\n}\n\ninterface CellInsetsEmu {\n\tmarL: number\n\tmarR: number\n\tmarT: number\n\tmarB: number\n}\n\n/** Resolve a cell's margins to EMU insets, mirroring `gen/slide/objects/table.ts` (array is `[T,R,B,L]`, inches; see `marginToEmu`). */\nexport function resolveCellInsetsEmu(margin: Margin | undefined): CellInsetsEmu {\n\tlet m: Margin = margin === 0 || margin ? margin : DEF_CELL_MARGIN_IN\n\tif (typeof m === 'number') m = [m, m, m, m]\n\tif (!Array.isArray(m) || m.length !== 4 || m.some((v) => typeof v !== 'number' || !isFinite(v)))\n\t\tm = DEF_CELL_MARGIN_IN\n\tconst arr = m\n\treturn {\n\t\tmarT: marginToEmu(arr[0]),\n\t\tmarR: marginToEmu(arr[1]),\n\t\tmarB: marginToEmu(arr[2]),\n\t\tmarL: marginToEmu(arr[3]),\n\t}\n}\n\n/**\n * Bake a reduced font size onto a cell's runs by factor `f` (< 1). Clones every\n * options object before mutating: a plain-string cell shares the table's `opt`\n * object (`gen/define/`), so in-place mutation would corrupt every other such cell.\n */\nexport function scaleCellFontSizes(cell: TableCell, eff: RunOpts, f: number): void {\n\tconst shrink = (sizePt: number): number => Math.floor(sizePt * f * 10) / 10 // floor: stay on the conservative (smaller) side\n\tconst baseSize = Number(eff.fontSize ?? DEF_FONT_SIZE)\n\tcell.options = { ...cell.options, fontSize: shrink(baseSize) }\n\tif (Array.isArray(cell.text)) {\n\t\tcell.text = cell.text.map((run) =>\n\t\t\trun && typeof run === 'object' && typeof run.options?.fontSize === 'number'\n\t\t\t\t? { ...run, options: { ...run.options, fontSize: shrink(run.options.fontSize) } }\n\t\t\t\t: run\n\t\t)\n\t}\n}\n\n/** Grid column count of a table (sums the first row's colspans), mirroring `gen/slide/objects/table.ts`. */\nexport function tableColCount(rows: TableCell[][]): number {\n\tconst first = rows[0]\n\treturn first ? first.reduce((n, c) => n + (Number(c?.options?.colspan) || 1), 0) : 0\n}\n\n/** A placed (non-merged origin) cell yielded by {@link walkTableGrid}. */\ninterface GridPlacement {\n\tcell: TableCell\n\t/** Zero-based grid row of the cell's top-left origin. */\n\trow: number\n\t/** Zero-based grid column of the cell's top-left origin. */\n\tcol: number\n\t/** Rows spanned, clamped to the available rows. */\n\trowSpan: number\n\t/** Columns spanned, clamped to the grid width. */\n\tcolSpan: number\n}\n\n/**\n * Walk a table's cell grid in row-major order, resolving each authored cell to its\n * grid origin (`row`/`col`) and clamped colspan/rowspan. Tracks rowspan occupancy so\n * a cell never lands beneath one spanned from above (grid build). This is\n * the single traversal shared by the measured-fit shrink pass and\n * {@link computeTableLayout}, so cell placement cannot drift between them.\n */\nexport function* walkTableGrid(rows: TableCell[][], numCols: number): Generator<GridPlacement> {\n\t// occupied[c] = rows still covered by a rowspan started above (incl. current row).\n\tconst occupied = new Array<number>(numCols).fill(0)\n\tfor (let r = 0; r < rows.length; r++) {\n\t\tconst row = rows[r]\n\t\tif (!row) continue\n\t\tlet col = 0\n\t\tfor (const cell of row) {\n\t\t\twhile (col < numCols && (occupied[col] ?? 0) > 0) col++\n\t\t\tif (col >= numCols) break\n\t\t\tconst colspan = Math.max(1, Number(cell?.options?.colspan) || 1)\n\t\t\tconst rowspan = Math.min(Math.max(1, Number(cell?.options?.rowspan) || 1), rows.length - r)\n\t\t\tconst colStart = col\n\t\t\tconst colEnd = Math.min(colStart + colspan, numCols)\n\t\t\tfor (let c = colStart; c < colEnd; c++) occupied[c] = rowspan\n\t\t\tcol = colEnd\n\t\t\tyield { cell, row: r, col: colStart, rowSpan: rowspan, colSpan: colEnd - colStart }\n\t\t}\n\t\tfor (let c = 0; c < numCols; c++) {\n\t\t\tconst cur = occupied[c] ?? 0\n\t\t\tif (cur > 0) occupied[c] = cur - 1\n\t\t}\n\t}\n}\n\n/**\n * Compute per-cell geometry (inches) for a table laid out at `opts.x`/`y`/`w` — the\n * engine behind `pptx.tableLayout()`. Column widths come from the same\n * {@link resolveTableColWidthsEmu} the writer uses, so cell x/width are exact. Row\n * heights are exact when pinned by `rowH` (array or scalar) or table `h`; otherwise\n * each auto-height row is estimated with the same conservative (tall) text model as\n * {@link measureText} and flagged `heightExact: false`. Single-slide only —\n * `autoPage` paging across slides is not modeled. Rowspan cells do not drive a row's\n * estimated height (mirrors `gen/table/autopage.ts`, which exempts them from line-height growth).\n */\nexport function computeTableLayout(\n\trows: TableCell[][],\n\topts: TableProps,\n\tpresLayout: PresLayout,\n\tregistry: FontMetricsRegistry\n): TableLayoutResult {\n\tconst empty: TableLayoutResult = { cells: [], widthIn: 0, heightIn: 0, heightExact: true }\n\tif (!rows || rows.length === 0 || !rows[0]) return empty\n\tconst numRows = rows.length\n\tconst numCols = tableColCount(rows)\n\tif (!(numCols > 0)) return empty\n\t// Reuse TableProps as a bag of inheritable text props; only CELL_INHERIT_KEYS are\n\t// read from it. Route through `unknown` because TableProps.columns (per-column cell\n\t// styling, TableCellProps[]) collides by name with TextPropsOptions.columns (text\n\t// column count, number) — the two never overlap here since `columns` isn't inherited.\n\tconst o = opts as unknown as RunOpts\n\n\tconst tableXEmu = opts.x != null ? getSmartParseNumber(opts.x, 'X', presLayout) : 0\n\tconst tableYEmu = opts.y != null ? getSmartParseNumber(opts.y, 'Y', presLayout) : 0\n\tconst cxEmu =\n\t\topts.w != null ? getSmartParseNumber(opts.w, 'X', presLayout) : getSmartParseNumber('75%', 'X', presLayout)\n\tconst colWidthsEmu = resolveTableColWidthsEmu(opts.colW, cxEmu, numCols)\n\n\t// Prefix-sum column x offsets (length numCols+1): colXEmu[c] = left edge of column c.\n\tconst colXEmu = new Array<number>(numCols + 1).fill(0)\n\tfor (let c = 0; c < numCols; c++) colXEmu[c + 1] = (colXEmu[c] ?? 0) + (colWidthsEmu[c] ?? 0)\n\n\tconst tableHeightEmu = opts.h != null ? getSmartParseNumber(opts.h, 'Y', presLayout) : 0\n\t// Explicit row height (EMU) or null when the row is auto-height. An array `rowH`\n\t// slot that is missing/NaN falls back to an even split of table `h` if one is set.\n\tconst explicitRowHEmu = (r: number): number | null => {\n\t\tif (Array.isArray(opts.rowH)) {\n\t\t\tconst v = opts.rowH[r]\n\t\t\tif (typeof v === 'number' && isFinite(v)) return inch2Emu(v)\n\t\t\treturn tableHeightEmu > 0 ? Math.round(tableHeightEmu / numRows) : null\n\t\t}\n\t\tif (opts.rowH != null && !isNaN(Number(opts.rowH))) return inch2Emu(Number(opts.rowH))\n\t\tif (tableHeightEmu > 0) return Math.round(tableHeightEmu / numRows)\n\t\treturn null\n\t}\n\tconst resolve = makeRegistryResolver(registry)\n\tconst defLineEmu = inch2Emu((DEF_FONT_SIZE * LINEH_MODIFIER) / 100)\n\n\t// Estimate a cell's content height (EMU) at its authored size, conservative/tall,\n\t// with a one-line floor. Mirrors measureText's inflated wrap + height safety.\n\tconst estimateContentHeightEmu = (cell: TableCell, eff: RunOpts, innerWidthPt: number): number => {\n\t\tconst fontSizePt = Number(eff.fontSize ?? DEF_FONT_SIZE) || DEF_FONT_SIZE\n\t\tconst oneLineEmu = inch2Emu((fontSizePt * LINEH_MODIFIER) / 100)\n\t\tif (!(innerWidthPt > 0)) return oneLineEmu\n\t\tconst paragraphs = extractParagraphs({ text: cell.text, options: eff } as unknown as SlideObject)\n\t\tif (!paragraphs) return oneLineEmu\n\t\tconst layout = measureLayout(paragraphs, innerWidthPt, resolve, 100, 0, WIDTH_SAFETY_FACTOR)\n\t\tif (layout === null) return oneLineEmu\n\t\treturn Math.max(Math.round(layout.heightPt * HEIGHT_SAFETY_FACTOR * EMU_PER_POINT), oneLineEmu)\n\t}\n\n\t// PASS 1: place every origin cell and resolve each row's height.\n\tinterface Placed {\n\t\tp: GridPlacement\n\t\tcolStart: number\n\t\tcolEnd: number\n\t}\n\tconst placed: Placed[] = []\n\tconst rowHeightsEmu = new Array<number>(numRows).fill(0)\n\tconst rowExact = new Array<boolean>(numRows).fill(false)\n\tfor (let r = 0; r < numRows; r++) {\n\t\tconst ex = explicitRowHEmu(r)\n\t\tif (ex != null) {\n\t\t\trowHeightsEmu[r] = ex\n\t\t\trowExact[r] = true\n\t\t}\n\t}\n\n\tfor (const p of walkTableGrid(rows, numCols)) {\n\t\tconst colStart = p.col\n\t\tconst colEnd = p.col + p.colSpan\n\t\tplaced.push({ p, colStart, colEnd })\n\n\t\t// Only single-row, auto-height cells drive a row's estimated height.\n\t\tif (p.rowSpan === 1 && !rowExact[p.row]) {\n\t\t\tlet widthEmu = 0\n\t\t\tfor (let c = colStart; c < colEnd; c++) widthEmu += colWidthsEmu[c] ?? 0\n\t\t\tconst eff = effectiveCellOpts(p.cell?.options ?? {}, o)\n\t\t\tconst ins = resolveCellInsetsEmu(eff.margin)\n\t\t\tconst innerWidthPt = (widthEmu - ins.marL - ins.marR) / EMU_PER_POINT\n\t\t\tconst contentEmu = estimateContentHeightEmu(p.cell, eff, innerWidthPt) + ins.marT + ins.marB\n\t\t\tif (contentEmu > (rowHeightsEmu[p.row] ?? 0)) rowHeightsEmu[p.row] = contentEmu\n\t\t}\n\t}\n\n\t// A row touched only by rowspans (no single-row cell, no explicit height) still\n\t// needs a non-zero height: give it one default line.\n\tfor (let r = 0; r < numRows; r++) if ((rowHeightsEmu[r] ?? 0) <= 0) rowHeightsEmu[r] = defLineEmu\n\n\t// Prefix-sum row y offsets.\n\tconst rowYEmu = new Array<number>(numRows + 1).fill(0)\n\tfor (let r = 0; r < numRows; r++) rowYEmu[r + 1] = (rowYEmu[r] ?? 0) + (rowHeightsEmu[r] ?? 0)\n\n\t// PASS 2: emit one rect per origin cell.\n\tconst cells: TableCellLayout[] = placed.map(({ p, colStart, colEnd }) => {\n\t\tconst rowEnd = p.row + p.rowSpan\n\t\tlet heightExact = true\n\t\tfor (let rr = p.row; rr < rowEnd; rr++) if (!rowExact[rr]) heightExact = false\n\t\treturn {\n\t\t\trow: p.row,\n\t\t\tcol: p.col,\n\t\t\trowSpan: p.rowSpan,\n\t\t\tcolSpan: p.colSpan,\n\t\t\txIn: emuToInches(tableXEmu + (colXEmu[colStart] ?? 0)),\n\t\t\tyIn: emuToInches(tableYEmu + (rowYEmu[p.row] ?? 0)),\n\t\t\twIn: emuToInches((colXEmu[colEnd] ?? 0) - (colXEmu[colStart] ?? 0)),\n\t\t\thIn: emuToInches((rowYEmu[rowEnd] ?? 0) - (rowYEmu[p.row] ?? 0)),\n\t\t\theightExact,\n\t\t}\n\t})\n\n\treturn {\n\t\tcells,\n\t\twidthIn: emuToInches(colXEmu[numCols] ?? 0),\n\t\theightIn: emuToInches(rowYEmu[numRows] ?? 0),\n\t\theightExact: rowExact.every(Boolean),\n\t}\n}\n\n/**\n * Build the `MetricsResolver` both the export pass and `measureText` use, so they\n * agree run-for-run: exact registered metrics → conservative heuristic for any\n * **named** face without exact metrics → `undefined` only for an unnamed\n * (theme-default) face that cannot be guessed. `onHeuristic` is called with each\n * named face that fell back to the heuristic (for the export pass's warn-once).\n */\n","/**\n * ts-pptx: Measured-fit serialization pass\n *\n * Bridges slide text objects to the line-break simulator / shrink solver\n * (`text-fit.ts`). Runs during async export, BEFORE the `gen/` emitter builds the body:\n * for each text box with `fit: 'shrink'` and a registered font, it computes the\n * `fontScale` PowerPoint would have baked and rewrites `options.fit` to the\n * explicit object form (`{ type:'shrink', fontScale }`) so `genXmlNormAutofit`\n * emits `<a:normAutofit fontScale=…/>`. Without metrics it leaves the bare flag\n * untouched (current behavior) and warns once. See `docs/measured-text-fit.md`.\n */\n\nimport { SlideObjectType } from '../enums.js'\nimport { EMU_PER_POINT, POINTS_PER_INCH } from '../units.js'\nimport { getSmartParseNumber, inch2Emu, resolveTableColWidthsEmu } from '../units-internal.js'\nimport { warn } from '../diagnostics.js'\nimport { makeRegistryResolver, type FontMetricsRegistry } from './font-metrics.js'\nimport {\n\tsolveShrink,\n\tsolveResize,\n\tmeasureLayout,\n\tWIDTH_SAFETY_FACTOR,\n\tHEIGHT_SAFETY_FACTOR,\n\ttype FitBox,\n\ttype FitParagraph,\n} from './text-fit.js'\nimport {\n\tanchorTopShareOfDelta,\n\tbuildFitParagraphs,\n\tcomputeBox,\n\textractParagraphs,\n\tresolveInsetsEmu,\n\ttype RunOpts,\n} from './paragraphs.js'\nimport {\n\teffectiveCellOpts,\n\tresolveCellInsetsEmu,\n\tscaleCellFontSizes,\n\ttableColCount,\n\twalkTableGrid,\n} from './table-fit.js'\nimport type { MeasureTextOptions, TextMeasurement, TextProps } from '../types/index.js'\nimport type { SlideObject, PresSlideInternal } from '../types/internal.js'\n\n/** Map the public {@link MeasureTextOptions} onto the internal run-option shape. */\nfunction measureOptsToRunOpts(opts: MeasureTextOptions): RunOpts {\n\treturn {\n\t\tfontSize: opts.fontSize,\n\t\tfontFace: opts.fontFace,\n\t\tbold: opts.bold,\n\t\titalic: opts.italic,\n\t\tcharSpacing: opts.charSpacing,\n\t\tlineSpacing: opts.lineSpacing,\n\t\tlineSpacingMultiple: opts.lineSpacingMultiple,\n\t\tparaSpaceBefore: opts.paraSpaceBefore,\n\t\tparaSpaceAfter: opts.paraSpaceAfter,\n\t}\n}\n\n/** A fresh result each call: `approximatedFaces` is caller-owned, so it cannot be shared. */\nconst unmeasurable = (): TextMeasurement => ({\n\theightIn: 0,\n\tlineCount: 0,\n\twidestLineIn: 0,\n\tmeasurable: false,\n\tapproximatedFaces: [],\n\tfitsBox: () => false,\n\tshrinkScaleFor: () => 100,\n})\n\n/**\n * Layout-time text measurement against registered metrics — the public engine\n * behind `pptx.measureText()`. Uses the **same** calibrated wrap model, resolver\n * semantics, and conservative safety factors as the export-time bake\n * ({@link applyMeasuredFit} / {@link solveResize} / {@link solveShrink}), so a\n * layout-time prediction matches the value the export would bake **for any deck\n * that opted into measured fit (i.e. registered at least one face)**.\n *\n * With an **empty** registry the two intentionally diverge: {@link applyMeasuredFit}\n * treats \"no metrics\" as \"not opted in\" and bakes nothing, while this returns\n * heuristic numbers so the API is useful with zero setup. Check\n * `approximatedFaces` if that distinction matters.\n *\n * Synchronous: assumes metrics are pre-registered (lookup is sync). A named face\n * with no exact metrics silently uses the conservative heuristic (same as export)\n * and is reported in `approximatedFaces`; an unnamed theme-default face returns\n * `measurable: false`.\n */\nexport function measureText(\n\tregistry: FontMetricsRegistry,\n\ttext: string | TextProps[],\n\topts: MeasureTextOptions\n): TextMeasurement {\n\tconst runs: TextProps[] =\n\t\ttypeof text === 'string' || typeof text === 'number' ? [{ text: String(text) }] : Array.isArray(text) ? text : []\n\tconst paragraphs = buildFitParagraphs(runs, measureOptsToRunOpts(opts))\n\tif (!paragraphs) return unmeasurable()\n\n\tconst inset = opts.insetIn ?? 0\n\tconst innerWidthPt = (opts.wIn - 2 * inset) * POINTS_PER_INCH\n\tconst heuristicFaces = new Set<string>()\n\tconst resolve = makeRegistryResolver(registry, (face) => heuristicFaces.add(face))\n\n\t// Conservative (tall) layout at full size, mirroring solveResize: inflate width\n\t// (earlier wrap) by WIDTH_SAFETY and the height by HEIGHT_SAFETY. The resolver runs\n\t// during layout, so `heuristicFaces` is only populated once this returns.\n\tconst layout = measureLayout(paragraphs, innerWidthPt, resolve, 100, 0, WIDTH_SAFETY_FACTOR)\n\tif (layout === null) return unmeasurable()\n\tconst heightPt = layout.heightPt * HEIGHT_SAFETY_FACTOR\n\tconst heightIn = heightPt / POINTS_PER_INCH\n\n\treturn {\n\t\theightIn,\n\t\tlineCount: layout.lineCount,\n\t\twidestLineIn: layout.widestLineWidthPt / POINTS_PER_INCH,\n\t\tmeasurable: true,\n\t\t// Snapshot: shrinkScaleFor() re-enters the same resolver, so the live set must not leak.\n\t\tapproximatedFaces: [...heuristicFaces],\n\t\t// Mirrors solveShrink's fit check at scale 100 (height already inflated).\n\t\tfitsBox: (hIn: number) => heightPt <= hIn * POINTS_PER_INCH,\n\t\tshrinkScaleFor: (hIn: number) => {\n\t\t\tconst box: FitBox = { innerWidthPt, innerHeightPt: hIn * POINTS_PER_INCH }\n\t\t\tconst outcome = solveShrink(paragraphs, box, resolve)\n\t\t\tif (outcome.kind === 'shrink') return outcome.result.fontScalePct\n\t\t\treturn 100 // 'fits' (or, defensively, 'unmeasurable') → no shrink\n\t\t},\n\t}\n}\n\n/**\n * Apply measured fit across every slide. For each text box that opts in via\n * `fit:'shrink'` or `fit:'resize'` and whose font has registered metrics, this\n * bakes the computed result before the sync XML pass reads it:\n * - `'shrink'` → rewrites `options.fit` to the object form so `<a:normAutofit\n * fontScale=…/>` is emitted (text renders pre-shrunk).\n * - `'resize'` → rewrites `options.h` (and `options.y` per vertical anchor) so the\n * shape's `a:ext/@cy` is the height the text needs; the `<a:spAutoFit/>` marker is\n * left in place (the renderer draws the baked `cy`).\n *\n * Safe to call with an empty registry (no-op). Warns once if any opted-in box could\n * not be measured (missing metrics) so overflow is not silently ignored.\n */\nexport function applyMeasuredFit(slides: PresSlideInternal[], registry: FontMetricsRegistry): void {\n\tif (registry.size === 0) return\n\n\t// A deck that registered *some* metrics has opted into measured fit, so a named\n\t// face we have no exact metrics for falls back to the conservative heuristic rather\n\t// than degrading to the bare flag — overflow still self-corrects, just less precisely.\n\t// An unnamed (theme-default) face stays unmeasurable: we cannot guess which face it is.\n\tconst heuristicFaces = new Set<string>()\n\tconst resolve = makeRegistryResolver(registry, (face) => heuristicFaces.add(face))\n\tconst unmeasuredShrink = new Set<string>()\n\tconst unmeasuredResize = new Set<string>()\n\n\tconst collectUnmeasured = (paragraphs: FitParagraph[], into: Set<string>): void => {\n\t\tfor (const para of paragraphs)\n\t\t\tfor (const run of para.runs) if (!resolve(run)) into.add(run.fontFace ?? '(theme default)')\n\t}\n\n\t/**\n\t * Bake measured shrink into a table's cells. Walks the cell grid (accounting for\n\t * colspan/rowspan) to size each cell's box from its column widths and row heights,\n\t * then lowers the run font sizes of any `fit:'shrink'` cell that overflows. Cells\n\t * in auto-height rows (no fixed `rowH`/table `h`) are skipped — the row grows instead.\n\t */\n\tconst measureTableCells = (tableObj: SlideObject, layout: PresSlideInternal['_presLayout']): void => {\n\t\tconst rows = tableObj.arrTabRows\n\t\tif (!rows || rows.length === 0 || !rows[0]) return\n\t\tconst tableOpts = (tableObj.options ?? {}) as RunOpts\n\t\tconst numRows = rows.length\n\t\tconst numCols = tableColCount(rows)\n\t\tif (!(numCols > 0)) return\n\n\t\tconst cxEmu =\n\t\t\ttableOpts.w != null ? getSmartParseNumber(tableOpts.w, 'X', layout) : getSmartParseNumber('75%', 'X', layout)\n\t\tconst colWidthsEmu = resolveTableColWidthsEmu(tableOpts.colW, cxEmu, numCols)\n\t\tconst tableHeightEmu =\n\t\t\ttableOpts.h != null\n\t\t\t\t? getSmartParseNumber(tableOpts.h, 'Y', layout)\n\t\t\t\t: typeof tableOpts.cy === 'number'\n\t\t\t\t\t? tableOpts.cy\n\t\t\t\t\t: 0\n\t\tconst rowHeightEmu = (rIdx: number): number => {\n\t\t\tif (Array.isArray(tableOpts.rowH) && tableOpts.rowH[rIdx]) return inch2Emu(Number(tableOpts.rowH[rIdx]))\n\t\t\tif (tableOpts.rowH != null && !Array.isArray(tableOpts.rowH) && !isNaN(Number(tableOpts.rowH)))\n\t\t\t\treturn inch2Emu(Number(tableOpts.rowH))\n\t\t\tif (tableHeightEmu > 0) return Math.round(tableHeightEmu / numRows)\n\t\t\treturn 0 // auto-height row → grows to fit, no shrink\n\t\t}\n\n\t\tfor (const { cell, row: r, col: colStart, colSpan, rowSpan } of walkTableGrid(rows, numCols)) {\n\t\t\tconst colEnd = colStart + colSpan\n\t\t\tconst cellOpts = cell?.options ?? {}\n\t\t\tconst fit = cellOpts.fit ?? (tableOpts.fit === 'shrink' ? 'shrink' : undefined)\n\t\t\tif (fit !== 'shrink') continue\n\n\t\t\tlet widthEmu = 0\n\t\t\tfor (let c = colStart; c < colEnd; c++) widthEmu += colWidthsEmu[c] ?? 0\n\t\t\tlet heightEmu = 0\n\t\t\tlet autoHeight = false\n\t\t\tfor (let rr = r; rr < r + rowSpan; rr++) {\n\t\t\t\tconst h = rowHeightEmu(rr)\n\t\t\t\tif (h <= 0) {\n\t\t\t\t\tautoHeight = true\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\theightEmu += h\n\t\t\t}\n\t\t\tif (autoHeight) continue\n\n\t\t\tconst eff = effectiveCellOpts(cellOpts, tableOpts)\n\t\t\tconst ins = resolveCellInsetsEmu(eff.margin)\n\t\t\tconst innerWidthPt = (widthEmu - ins.marL - ins.marR) / EMU_PER_POINT\n\t\t\tconst innerHeightPt = (heightEmu - ins.marT - ins.marB) / EMU_PER_POINT\n\t\t\tif (!(innerWidthPt > 0) || !(innerHeightPt > 0)) continue\n\n\t\t\tconst paragraphs = extractParagraphs({ text: cell.text, options: eff } as unknown as SlideObject)\n\t\t\tif (!paragraphs) continue\n\t\t\tconst box: FitBox = { innerWidthPt, innerHeightPt }\n\t\t\tconst outcome = solveShrink(paragraphs, box, resolve)\n\t\t\tif (outcome.kind === 'shrink') {\n\t\t\t\tconst f = outcome.result.fontScalePct / 100\n\t\t\t\tif (f < 1) scaleCellFontSizes(cell, eff, f)\n\t\t\t} else if (outcome.kind === 'unmeasurable') {\n\t\t\t\tcollectUnmeasured(paragraphs, unmeasuredShrink)\n\t\t\t}\n\t\t\t// 'fits' → leave the authored size; the text already fits.\n\t\t}\n\t}\n\n\tconst measureObject = (obj: SlideObject, layout: PresSlideInternal['_presLayout']): void => {\n\t\t// Groups keep their children outside slide._slideObjects. Descend through every\n\t\t// nesting level so grouping remains a visual/editability operation and does not\n\t\t// disable the export-time fit pass for contained text.\n\t\tif (obj._type === SlideObjectType.group) {\n\t\t\tfor (const child of obj._groupObjects ?? []) measureObject(child, layout)\n\t\t\treturn\n\t\t}\n\t\tif (obj._type === SlideObjectType.table) {\n\t\t\tmeasureTableCells(obj, layout)\n\t\t\treturn\n\t\t}\n\t\tif (obj._type !== SlideObjectType.text) return\n\t\t// Only the bare string forms opt into measurement; an explicit object form is\n\t\t// already baked by the caller, and 'none' is a no-op.\n\t\tconst options = obj.options\n\t\tif (!options) return\n\t\tconst fit = options.fit\n\t\tif (fit !== 'shrink' && fit !== 'resize') return\n\n\t\tconst paragraphs = extractParagraphs(obj)\n\t\tif (!paragraphs) return\n\t\tconst box = computeBox(obj, layout)\n\t\tif (!box) return\n\n\t\tif (fit === 'shrink') {\n\t\t\tconst outcome = solveShrink(paragraphs, box, resolve)\n\t\t\tif (outcome.kind === 'shrink') {\n\t\t\t\tconst { fontScalePct, lnSpcReductionPct } = outcome.result\n\t\t\t\toptions.fit = {\n\t\t\t\t\ttype: 'shrink',\n\t\t\t\t\tfontScale: fontScalePct,\n\t\t\t\t\tlnSpcReduction: lnSpcReductionPct || undefined,\n\t\t\t\t}\n\t\t\t} else if (outcome.kind === 'unmeasurable') {\n\t\t\t\tcollectUnmeasured(paragraphs, unmeasuredShrink)\n\t\t\t}\n\t\t\t// 'fits' → leave the bare flag; the text already fits, so no scale is needed.\n\t\t} else {\n\t\t\tconst outcome = solveResize(paragraphs, box, resolve)\n\t\t\tif (outcome.kind === 'resize') {\n\t\t\t\tconst opts = obj.options as RunOpts\n\t\t\t\tconst { tIns, bIns } = resolveInsetsEmu(opts)\n\t\t\t\tconst oldHeightEmu = getSmartParseNumber(opts.h, 'Y', layout)\n\t\t\t\tconst newHeightEmu = Math.round(outcome.neededInnerHeightPt * EMU_PER_POINT) + tIns + bIns\n\t\t\t\t// Shift the box origin so growth/shrink honors the vertical anchor; `off.y`\n\t\t\t\t// moves up by the anchor's share of the height delta (0 / half / full for t / ctr / b).\n\t\t\t\tconst oldYEmu = getSmartParseNumber(opts.y, 'Y', layout)\n\t\t\t\tconst shiftEmu = Math.round((newHeightEmu - oldHeightEmu) * anchorTopShareOfDelta(opts))\n\t\t\t\topts.h = `${newHeightEmu}emu`\n\t\t\t\tif (shiftEmu !== 0) opts.y = `${oldYEmu - shiftEmu}emu`\n\t\t\t} else {\n\t\t\t\tcollectUnmeasured(paragraphs, unmeasuredResize)\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const slide of slides) {\n\t\tfor (const obj of slide._slideObjects ?? []) measureObject(obj, slide._presLayout)\n\t}\n\n\tif (unmeasuredShrink.size > 0) {\n\t\twarn(\n\t\t\t'measure/shrink-unmeasured',\n\t\t\t`fit:'shrink' could not be measured for font(s) [${[...unmeasuredShrink].join(', ')}] — ` +\n\t\t\t\t'no registered metrics. Emitting bare <a:normAutofit/> (text will not pre-shrink in headless renders). ' +\n\t\t\t\t'Call pptx.registerFontMetrics(face, fontFilePathOrBytes) to enable measured fit.'\n\t\t)\n\t}\n\tif (unmeasuredResize.size > 0) {\n\t\twarn(\n\t\t\t'measure/resize-unmeasured',\n\t\t\t`fit:'resize' could not be measured for font(s) [${[...unmeasuredResize].join(', ')}] — ` +\n\t\t\t\t'no registered metrics. Emitting bare <a:spAutoFit/> with the authored height (box will not auto-grow in headless renders). ' +\n\t\t\t\t'Call pptx.registerFontMetrics(face, fontFilePathOrBytes) to enable measured fit.'\n\t\t)\n\t}\n\tif (heuristicFaces.size > 0) {\n\t\twarn(\n\t\t\t'measure/heuristic-metrics',\n\t\t\t`Note: measured fit used a conservative average-advance estimate for font(s) [${[...heuristicFaces].join(', ')}] — ` +\n\t\t\t\t'no exact metrics registered. Fit is approximate (may shrink/grow more than necessary). ' +\n\t\t\t\t'Call pptx.registerFontMetrics(face, fontFilePathOrBytes) for an exact fit.'\n\t\t)\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { n as warn } from "./diagnostics-DYQC7xLV.js";
|
|
2
|
-
import { n as InvalidOptionError } from "./errors-
|
|
3
|
-
import { r as EMU_PER_INCH } from "./units-
|
|
4
|
-
import { i as inch2Emu } from "./units-internal-
|
|
5
|
-
import { t as getSlidesForTableRows } from "./autopage-
|
|
2
|
+
import { n as InvalidOptionError } from "./errors-Bvln0H-7.js";
|
|
3
|
+
import { r as EMU_PER_INCH } from "./units-C7QM1KgH.js";
|
|
4
|
+
import { i as inch2Emu } from "./units-internal-CR8s8YQa.js";
|
|
5
|
+
import { t as getSlidesForTableRows } from "./autopage-QQyfRtoK.js";
|
|
6
6
|
//#region src/gen/table/html-dom.ts
|
|
7
7
|
/**
|
|
8
8
|
* Stand-in for `getComputedStyle` on a document that has no view — a document produced by
|
|
@@ -207,7 +207,7 @@ function parseCssWidthBasis(values) {
|
|
|
207
207
|
return basis;
|
|
208
208
|
}
|
|
209
209
|
/**
|
|
210
|
-
* Choose which vector the proportional column math runs on,
|
|
210
|
+
* Choose which vector the proportional column math runs on, falling back as bases run out.
|
|
211
211
|
*
|
|
212
212
|
* `offsetWidth` is the ideal basis — it is the width the table actually rendered at — but it
|
|
213
213
|
* requires a layout engine, and reports `0` for every cell both in a hidden table and on any
|
|
@@ -220,6 +220,20 @@ function parseCssWidthBasis(values) {
|
|
|
220
220
|
*
|
|
221
221
|
* Only the basis changes; `data-pptx-width` / `data-pptx-min-width` overrides still apply
|
|
222
222
|
* downstream via {@link resolveHtmlColWidth} and still win outright.
|
|
223
|
+
*
|
|
224
|
+
* **The first two bases do not measure the same box, and the docs used to imply they did.**
|
|
225
|
+
* `offsetWidth` is the border box; a computed `width` is the content box. Padding alone
|
|
226
|
+
* separates them — `test/browser/harness/table.html` is built so it does, giving 1:1 measured
|
|
227
|
+
* against 2:1 from CSS on one table — so choosing arm 2 over arm 1 can change a table's column
|
|
228
|
+
* *proportions*, not just their precision. That is why the fixture discriminates at all, and why
|
|
229
|
+
* "degrades to computed CSS" was the wrong word for it everywhere it appeared.
|
|
230
|
+
*
|
|
231
|
+
* Left as-is rather than reconciled. Normalizing arm 2 to the border box would need the computed
|
|
232
|
+
* padding and border widths, which the DOMs that reach arm 2 need not resolve either (a `%`
|
|
233
|
+
* padding computes to nothing usable without layout), so it would converge the two only
|
|
234
|
+
* sometimes — and it would collapse the one discriminator the browser lane has, turning
|
|
235
|
+
* `table-widths.spec.mjs` back into a test that passes whether or not the measured arm ran.
|
|
236
|
+
* A caller who needs both runtimes to agree on a column states it with `data-pptx-width`.
|
|
223
237
|
* @param {readonly number[]} measured - per-column `offsetWidth`
|
|
224
238
|
* @param {readonly number[]} cssWidths - per-column CSS width basis (`[]` when unusable)
|
|
225
239
|
* @returns {number[]} the basis vector to run the proportional calc on
|
|
@@ -663,4 +677,4 @@ function genTableToSlides(pptx, target, options = {}) {
|
|
|
663
677
|
//#endregion
|
|
664
678
|
export { genTableToSlides as t };
|
|
665
679
|
|
|
666
|
-
//# sourceMappingURL=html-dom-
|
|
680
|
+
//# sourceMappingURL=html-dom-DajBuobe.js.map
|