pptx-ts 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +319 -0
  3. package/dist/autopage-DkjYZUFD.js +423 -0
  4. package/dist/autopage-DkjYZUFD.js.map +1 -0
  5. package/dist/browser.d.ts +31 -0
  6. package/dist/browser.d.ts.map +1 -0
  7. package/dist/browser.js +110 -0
  8. package/dist/browser.js.map +1 -0
  9. package/dist/diagnostics-Du_s75MT.d.ts +829 -0
  10. package/dist/diagnostics-Du_s75MT.d.ts.map +1 -0
  11. package/dist/enums-CvRYniUA.d.ts +463 -0
  12. package/dist/enums-CvRYniUA.d.ts.map +1 -0
  13. package/dist/errors-Bvln0H-7.js +112 -0
  14. package/dist/errors-Bvln0H-7.js.map +1 -0
  15. package/dist/errors-PflMPWBn.d.ts +182 -0
  16. package/dist/errors-PflMPWBn.d.ts.map +1 -0
  17. package/dist/fit-BKs0zxMI.js +1356 -0
  18. package/dist/fit-BKs0zxMI.js.map +1 -0
  19. package/dist/html-dom-B0I0QSbU.js +679 -0
  20. package/dist/html-dom-B0I0QSbU.js.map +1 -0
  21. package/dist/html.d.ts +26 -0
  22. package/dist/html.d.ts.map +1 -0
  23. package/dist/html.js +63 -0
  24. package/dist/html.js.map +1 -0
  25. package/dist/index.d.ts +24 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +57 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/inspect.d.ts +197 -0
  30. package/dist/inspect.d.ts.map +1 -0
  31. package/dist/inspect.js +317 -0
  32. package/dist/inspect.js.map +1 -0
  33. package/dist/math.d.ts +37 -0
  34. package/dist/math.d.ts.map +1 -0
  35. package/dist/math.js +203 -0
  36. package/dist/math.js.map +1 -0
  37. package/dist/measure.d.ts +313 -0
  38. package/dist/measure.d.ts.map +1 -0
  39. package/dist/measure.js +3 -0
  40. package/dist/namespaces-BVnNu7sg.js +666 -0
  41. package/dist/namespaces-BVnNu7sg.js.map +1 -0
  42. package/dist/node.d.ts +20 -0
  43. package/dist/node.d.ts.map +1 -0
  44. package/dist/node.js +55 -0
  45. package/dist/node.js.map +1 -0
  46. package/dist/notes-RLCwdlTE.js +1703 -0
  47. package/dist/notes-RLCwdlTE.js.map +1 -0
  48. package/dist/package-CaOLXSNi.d.ts +193 -0
  49. package/dist/package-CaOLXSNi.d.ts.map +1 -0
  50. package/dist/pres-C5__xkDh.d.ts +202 -0
  51. package/dist/pres-C5__xkDh.d.ts.map +1 -0
  52. package/dist/presentation-Cp7vzlAw.js +5427 -0
  53. package/dist/presentation-Cp7vzlAw.js.map +1 -0
  54. package/dist/presentation-types-DP_8jog7.d.ts +4872 -0
  55. package/dist/presentation-types-DP_8jog7.d.ts.map +1 -0
  56. package/dist/read.d.ts +55 -0
  57. package/dist/read.d.ts.map +1 -0
  58. package/dist/read.js +4 -0
  59. package/dist/script.d.ts +581 -0
  60. package/dist/script.d.ts.map +1 -0
  61. package/dist/script.js +3741 -0
  62. package/dist/script.js.map +1 -0
  63. package/dist/shapes-BemroU-z.js +6951 -0
  64. package/dist/shapes-BemroU-z.js.map +1 -0
  65. package/dist/slide-js0QpRV-.d.ts +3873 -0
  66. package/dist/slide-js0QpRV-.d.ts.map +1 -0
  67. package/dist/text-CyetbF6p.js +11278 -0
  68. package/dist/text-CyetbF6p.js.map +1 -0
  69. package/dist/units-1kRzYShk.js +231 -0
  70. package/dist/units-1kRzYShk.js.map +1 -0
  71. package/dist/units-internal-Dg95w_YD.js +753 -0
  72. package/dist/units-internal-Dg95w_YD.js.map +1 -0
  73. package/dist/zip.d.ts +68 -0
  74. package/dist/zip.d.ts.map +1 -0
  75. package/dist/zip.js +163 -0
  76. package/dist/zip.js.map +1 -0
  77. package/package.json +152 -0
  78. package/skills/ts-pptx-upstream/SKILL.md +340 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"math.js","names":[],"sources":["../src/math.ts"],"sourcesContent":["/**\n * `@shbernal/ts-pptx/math` — author display equations in LaTeX or MathML and get\n * OMML for the `math:` option on `addText` (see {@link TextProps.math}).\n *\n * Pipeline: LaTeX --temml--> MathML --mathml2omml--> OMML.\n *\n * Both converters are **optional peer dependencies** (temml is MIT, mathml2omml is\n * LGPL-3.0-or-later); install them to use this subpath:\n *\n * ```sh\n * npm install temml mathml2omml\n * ```\n *\n * This subpath is **Node-only**: it loads the converters synchronously via\n * `node:module`'s `createRequire`, so `latexToOmml()` / `mathmlToOmml()` stay\n * synchronous. Both display and inline (in-sentence) equations are supported: a\n * default `latexToOmml()` returns a centered display `<m:oMathPara>`, while\n * `latexToOmml(tex, { display: false })` (and `mathmlToOmml()`) return the bare\n * `<m:oMath>` form you pass to a text item with `inline: true` to flow it\n * mid-paragraph (see {@link TextProps.inline}).\n *\n * @module\n */\nimport { createRequire } from 'node:module'\nimport { InvalidOptionError, UnsupportedFeatureError } from './errors.js'\n\nconst nodeRequire = createRequire(import.meta.url)\n\n/** Minimal shape of the temml API we depend on. */\ninterface TemmlModule {\n\trenderToString(latex: string, options?: { displayMode?: boolean; throwOnError?: boolean }): string\n}\n/** temml's `ParseError` carries a `position` (character offset into the source). */\ninterface TemmlParseError extends Error {\n\tposition?: number\n}\n\nconst MISSING_DEPS_MESSAGE =\n\t\"@shbernal/ts-pptx/math requires the optional peer dependencies 'temml' and \" +\n\t\"'mathml2omml'. Install them with: npm install temml mathml2omml\"\n\n/** Require an optional peer, remapping a not-found error to the install hint. */\nfunction requirePeer<T>(id: string): T {\n\ttry {\n\t\treturn nodeRequire(id) as T\n\t} catch (err) {\n\t\tif ((err as NodeJS.ErrnoException | undefined)?.code === 'MODULE_NOT_FOUND') {\n\t\t\tthrow new UnsupportedFeatureError('math/missing-optional-peer', MISSING_DEPS_MESSAGE, { cause: err })\n\t\t}\n\t\tthrow err\n\t}\n}\n\nlet temmlModule: TemmlModule | undefined\nlet mml2ommlFn: ((mathml: string) => string) | undefined\n\nfunction loadTemml(): TemmlModule {\n\tif (!temmlModule) {\n\t\tconst mod = requirePeer<TemmlModule | { default: TemmlModule }>('temml')\n\t\ttemmlModule = 'renderToString' in mod ? mod : mod.default\n\t}\n\treturn temmlModule\n}\n\nfunction loadMml2omml(): (mathml: string) => string {\n\tif (!mml2ommlFn) {\n\t\tconst mod = requirePeer<{ mml2omml: (mathml: string) => string }>('mathml2omml')\n\t\tmml2ommlFn = mod.mml2omml\n\t}\n\treturn mml2ommlFn\n}\n\n/**\n * mathml2omml puts namespace declarations on the `<m:oMath>` opening tag: `xmlns:m`\n * (redundant — the `<a14:m>` envelope the `math:` option authors already declares it)\n * and `xmlns:w` (unused in the output it produces). Strip them so the result is a bare\n * `<m:oMath>` that drops into the `math:` option cleanly.\n */\nfunction stripOMathNamespaces(omml: string): string {\n\treturn omml.replace(/^(\\s*<m:oMath)\\b[^>]*>/, '$1>')\n}\n\n/** Centered-display paragraph props, matching what the `math:` emitter/oracle author. */\nconst DISPLAY_PARA_PR = '<m:oMathParaPr><m:jc m:val=\"centerGroup\"/></m:oMathParaPr>'\n\n/**\n * The operator-dictionary subset this module has to carry, keyed by the character temml\n * puts in the `<mo>` of an accent and valued by the combining mark OMML wants in `m:chr`.\n *\n * Two halves of one problem. **Which** `<mover>`s are accents: temml renders every accent\n * command as a bare `<mover>` with no `accent=\"true\"`, which is correct for a browser —\n * MathML renderers derive accent positioning from the operator dictionary, so the attribute\n * is redundant there — but mathml2omml has no dictionary and keys strictly off the\n * attribute, mapping a bare `<mover>` to `<m:limUpp>` (an over-*limit*, with limit spacing)\n * instead of `<m:acc>`. Membership in this table is the dictionary lookup that is otherwise\n * missing. **Which character** to attach: mathml2omml passes the `<mo>` text straight\n * through to `m:chr`, and temml emits the *spacing* modifiers (U+02C6 MODIFIER LETTER\n * CIRCUMFLEX, U+2192 RIGHTWARDS ARROW) while ECMA-376 §22.1.2.20 says an `accPr` character\n * \"should be within the range of (U+0300–U+036F) or (U+20D0–U+20EF)\" — the combining marks,\n * which is also what Word itself writes. Left alone, `\\vec{v}` would hang a full-size arrow\n * over the base instead of an arrow accent.\n *\n * Keyed by character rather than by LaTeX command because that is all that survives into\n * the MathML. Derived by rendering every accent command temml documents and reading back\n * the `<mo>` it produced; the commands each entry serves are named in the comments.\n */\nconst ACCENT_CHARS = new Map<string, string>([\n\t['ˆ', '̂'], // ˆ \\hat, \\^ → COMBINING CIRCUMFLEX ACCENT\n\t['~', '̃'], // ~ \\tilde, \\~ → COMBINING TILDE\n\t['´', '́'], // ´ \\acute → COMBINING ACUTE ACCENT\n\t['ˊ', '́'], // ˊ \\' → COMBINING ACUTE ACCENT\n\t['`', '̀'], // ` \\grave → COMBINING GRAVE ACCENT\n\t['ˋ', '̀'], // ˋ \\` → COMBINING GRAVE ACCENT\n\t['¨', '̈'], // ¨ \\ddot, \\\" → COMBINING DIAERESIS\n\t['˙', '̇'], // ˙ \\dot, \\. → COMBINING DOT ABOVE\n\t['‾', '̄'], // ‾ \\bar → COMBINING MACRON\n\t['ˉ', '̄'], // ˉ \\= → COMBINING MACRON\n\t['˘', '̆'], // ˘ \\breve, \\u → COMBINING BREVE\n\t['ˇ', '̌'], // ˇ \\check, \\v → COMBINING CARON\n\t['˚', '̊'], // ˚ \\mathring, \\r → COMBINING RING ABOVE\n\t['˝', '̋'], // ˝ \\H → COMBINING DOUBLE ACUTE ACCENT\n\t['→', '⃗'], // → \\vec → COMBINING RIGHT ARROW ABOVE\n\t['…', '⃛'], // … \\dddot → COMBINING THREE DOTS ABOVE\n])\n\n/** An `<mover>`'s last child, when that child is an `<mo>`: `[, attributes, text]`. */\nconst TRAILING_MO = /<mo\\b([^>]*)>([^<]*)<\\/mo>\\s*$/\n\n/**\n * Stamp `accent=\"true\"` on the `<mover>`s that are accents, and swap their operator for the\n * combining mark OMML wants. See {@link ACCENT_CHARS} for why both are needed.\n *\n * Scoped as narrowly as the defect. Only `<mo stretchy=\"false\">` qualifies, which is how\n * temml distinguishes a true accent from a *wide* one (`\\widehat`, `\\overrightarrow`) or a\n * group character (`\\overbrace`, `\\overgroup`) — those already reach `m:groupChr`, which is\n * a reasonable rendering, so they are left alone rather than churned. `\\stackrel` is an\n * over-relation whose character comes from the caller, so it stays `m:limUpp` unless the\n * caller happened to stack a diacritic. An `<mover>` that already states `accent` is the\n * author's call and is never rewritten.\n *\n * `<munder>` is deliberately **not** touched. The symmetric-looking fix — stamping\n * `accentunder=\"true\"` — makes mathml2omml emit `<m:acc>`, which is an *over*-accent: it\n * would move `\\utilde`'s tilde above the base. OMML has no under-accent object, so the\n * `m:limLow` an under-accent already produces is the closest thing available.\n *\n * Implemented against the tag text rather than through a DOM. temml's output is\n * machine-generated and well-formed, so pairing `<mover>` with `</mover>` on a stack is\n * exact, and this subpath otherwise carries no XML parser — the read path's is a different\n * dependency and pulling it in here would grow the module for one rewrite.\n */\nfunction markAccentedMovers(mathml: string): string {\n\tconst edits: { at: number; length: number; text: string }[] = []\n\tconst open: number[] = []\n\tconst tags = /<(\\/?)mover\\b[^>]*>/g\n\tfor (let tag = tags.exec(mathml); tag !== null; tag = tags.exec(mathml)) {\n\t\tif (tag[1] === '') {\n\t\t\t// `accent` already stated: the author has answered the question this asks.\n\t\t\topen.push(tag[0].includes('accent=') ? -1 : tag.index)\n\t\t\tcontinue\n\t\t}\n\t\tconst openAt = open.pop()\n\t\tif (openAt === undefined || openAt === -1) continue\n\n\t\tconst openEnd = mathml.indexOf('>', openAt) + 1\n\t\tconst mo = TRAILING_MO.exec(mathml.slice(openEnd, tag.index))\n\t\tif (!mo) continue\n\t\tconst [whole, attrs = '', operator = ''] = mo\n\t\t// `stretchy=\"false\"` is how temml separates a true accent from a wide one\n\t\t// (`\\widehat`) or a group character (`\\overbrace`); those already map well.\n\t\tif (!attrs.includes('stretchy=\"false\"')) continue\n\t\tconst combining = ACCENT_CHARS.get(operator)\n\t\t// A multi-character operator (`\\ddddot` renders as \"….\") has no single `m:chr`, so it\n\t\t// is not in the table and keeps the limit form rather than producing an invalid one.\n\t\tif (combining === undefined) continue\n\n\t\t// Applied right-to-left below, so earlier offsets stay valid.\n\t\tedits.push({\n\t\t\tat: openEnd + mo.index + whole.length - `${operator}</mo>`.length,\n\t\t\tlength: operator.length,\n\t\t\ttext: combining,\n\t\t})\n\t\tedits.push({ at: openAt + '<mover'.length, length: 0, text: ' accent=\"true\"' })\n\t}\n\n\tlet out = mathml\n\tfor (const edit of edits.sort((a, b) => b.at - a.at)) {\n\t\tout = out.slice(0, edit.at) + edit.text + out.slice(edit.at + edit.length)\n\t}\n\treturn out\n}\n\n/**\n * Convert a MathML string to OMML for the `math:` option on `addText`.\n *\n * Canonical output form: a bare `<m:oMath>…</m:oMath>` in the `m:` namespace, with no\n * namespace declarations (the `math:` option's envelope supplies the `m` prefix).\n *\n * @param mathml - a MathML string (e.g. `<math>…</math>`)\n * @returns OMML `<m:oMath>…</m:oMath>`\n */\nexport function mathmlToOmml(mathml: string): string {\n\tconst mml2omml = loadMml2omml()\n\treturn stripOMathNamespaces(mml2omml(mathml).trim())\n}\n\nexport interface LatexToOmmlOptions {\n\t/**\n\t * Display (block) math: render in `displayMode` and wrap the result in\n\t * `<m:oMathPara>` (a centered display-math paragraph). Default `true`. When `false`,\n\t * temml renders in inline mode and the result is a bare `<m:oMath>`.\n\t */\n\tdisplay?: boolean\n}\n\n/**\n * Convert a LaTeX string to OMML for the `math:` option on `addText`.\n *\n * Display math (the default) is returned as a full `<m:oMathPara>` centered display\n * paragraph; with `{ display: false }` a bare `<m:oMath>` is returned (both forms are\n * accepted by the `math:` option). Throws on invalid LaTeX, surfacing temml's parse\n * position.\n *\n * @param latex - a LaTeX math expression, e.g. `x = \\frac{-b \\pm \\sqrt{b^2-4ac}}{2a}`\n * @param opts - see {@link LatexToOmmlOptions}\n * @returns OMML `<m:oMathPara>…</m:oMathPara>` (display) or `<m:oMath>…</m:oMath>` (inline)\n * @throws {Error} if the LaTeX cannot be parsed\n */\nexport function latexToOmml(latex: string, opts: LatexToOmmlOptions = {}): string {\n\tconst display = opts.display ?? true\n\tconst temml = loadTemml()\n\tlet mathml: string\n\ttry {\n\t\tmathml = temml.renderToString(latex, { displayMode: display, throwOnError: true })\n\t} catch (err) {\n\t\tconst pe = err as TemmlParseError\n\t\tconst pos = typeof pe.position === 'number' ? ` (position ${pe.position})` : ''\n\t\tthrow new InvalidOptionError('math/invalid-latex', `Invalid LaTeX${pos}: ${pe.message}`, { cause: err })\n\t}\n\t// Applied here rather than in `mathmlToOmml`, because it compensates for something temml\n\t// does: a caller handing in their own MathML states `accent` themselves, and rewriting it\n\t// under them would be the module second-guessing an attribute the MathML spec gives them.\n\tconst oMath = mathmlToOmml(markAccentedMovers(mathml))\n\treturn display ? `<m:oMathPara>${DISPLAY_PARA_PR}${oMath}</m:oMathPara>` : oMath\n}\n\n// Error taxonomy — see `entry-errors.ts`. Re-exported from every entry so `instanceof`\n// works whichever subpath a consumer imports.\nexport * from './entry-errors.js'\n"],"mappings":"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"}
@@ -0,0 +1,313 @@
1
+ import { Qt as MeasureTextOptions, dn as TextPropsOptions, i as ObjectOptions, ln as TextMeasurement, tn as OverflowBoxOptions, un as TextProps } from "./slide-js0QpRV-.js";
2
+ import { a as TsPptxError, d as InvalidOptionErrorCode, f as MediaErrorCode, h as UnsupportedFeatureErrorCode, i as PackageReadError, l as ErrorCode, m as TsPptxCode, n as InvalidOptionError, o as TsPptxErrorOptions, p as PackageReadErrorCode, r as MediaError, s as UnsupportedFeatureError, t as InternalError, u as InternalErrorCode } from "./errors-PflMPWBn.js";
3
+ //#region src/measure/font-metrics.d.ts
4
+ /** Per-(face,bold,italic) advance-width source backed by a parsed font file. */
5
+ interface FontMetrics {
6
+ /** Font design units per em (advances are in these units). */
7
+ readonly unitsPerEm: number;
8
+ /**
9
+ * Advance width of `text` at `sizePt`, in points. Sums raw glyph advances
10
+ * (no kerning) and adds `charSpacingPt` after every character, matching how
11
+ * PowerPoint widens runs with character spacing.
12
+ */
13
+ advanceWidthPt: (text: string, sizePt: number, charSpacingPt?: number) => number;
14
+ /**
15
+ * True if this face's cmap maps code point `cp` to a real glyph (not the
16
+ * `.notdef` fallback). Use it to flag source code points the face cannot
17
+ * render. Authoritative only for file-backed metrics; the unregistered-font
18
+ * heuristic has no cmap and reports every code point as covered.
19
+ */
20
+ hasCodepoint: (cp: number) => boolean;
21
+ }
22
+ /**
23
+ * Shared, font-independent `FontMetrics` used when a named face has no registered
24
+ * metrics but the deck has opted into measured fit (some other face is registered).
25
+ * Approximate but conservative — see {@link heuristicCharRatio}. A deck with no
26
+ * registered metrics at all does not engage measured fit, so this never fires there.
27
+ */
28
+ declare function getHeuristicFontMetrics(): FontMetrics;
29
+ /** Options for {@link parseFontMetrics}. */
30
+ interface ParseFontMetricsOptions {
31
+ /**
32
+ * Which font to read out of a file that holds several: a 0-based index, or a name
33
+ * matched case-insensitively against the family, full, and PostScript names
34
+ * (`listFontFaces` lists them). Omitted selects the first.
35
+ *
36
+ * Collections (`.ttc`/`.otc`) are why this exists: `msgothic.ttc` is three fonts and
37
+ * `cambria.ttc` is two. The selector means the same thing for a plain TTF/OTF, which
38
+ * is a one-entry list, so a wrong index or an unmatched name is an error there rather
39
+ * than being ignored.
40
+ */
41
+ readonly font?: number | string;
42
+ }
43
+ /**
44
+ * Parse a font file into a `FontMetrics`. Lazily imports opentype.js.
45
+ *
46
+ * Reads plain TTF/OTF and **font collections** (`.ttc`/`.otc`); for a collection, pass
47
+ * `font` to say which member, since a collection has no single answer. The underlying
48
+ * parser does not read the `ttcf` wrapper, so the selected member is unwrapped into a
49
+ * standalone sfnt first (see `measure/font-collection.ts`).
50
+ * @param {Uint8Array} data - the font file's bytes
51
+ * @param {ParseFontMetricsOptions} [opts] - which font, for a file holding several
52
+ * @returns {Promise<FontMetrics>} advance widths and cmap coverage for that font
53
+ * @example await parseFontMetrics(bytes) // a plain .ttf
54
+ * @example await parseFontMetrics(ttcBytes, { font: 'MS PGothic' })
55
+ */
56
+ declare function parseFontMetrics(data: Uint8Array, opts?: ParseFontMetricsOptions): Promise<FontMetrics>;
57
+ /**
58
+ * Registry of `FontMetrics` keyed by `(face, bold, italic)`. Variant advances
59
+ * differ, so bold/italic are stored separately; lookup falls back to the regular
60
+ * variant (then any registered variant of the face) so a deck that only registers
61
+ * the regular weight still measures bold runs approximately rather than not at all.
62
+ */
63
+ declare class FontMetricsRegistry {
64
+ private readonly map;
65
+ private key;
66
+ set(face: string, metrics: FontMetrics, opts?: {
67
+ bold?: boolean;
68
+ italic?: boolean;
69
+ }): void;
70
+ /** True if any variant of `face` has registered metrics. */
71
+ hasFace(face: string): boolean;
72
+ /**
73
+ * Coverage of code point `cp` for `face`, read from the registered font's cmap:
74
+ * `true`/`false` when a variant of `face` is registered (see {@link get} for the
75
+ * exact→regular→any-variant fallback), or `undefined` when the face has **no**
76
+ * registered metrics — "unknown", deliberately distinct from a `false`
77
+ * "registered but not covered". A coverage audit must not treat an unregistered
78
+ * face as fully covered, so callers get `undefined` here rather than the per-face
79
+ * {@link FontMetrics.hasCodepoint} boolean (which, for the heuristic fallback,
80
+ * always reports covered). Register the face via {@link parseFontMetrics} +
81
+ * {@link set} first.
82
+ */
83
+ hasCodepoint(face: string | undefined | null, cp: number, opts?: {
84
+ bold?: boolean;
85
+ italic?: boolean;
86
+ }): boolean | undefined;
87
+ /** Resolve metrics for a run, falling back from exact variant → regular → any variant. */
88
+ get(face: string | undefined | null, bold?: boolean, italic?: boolean): FontMetrics | undefined;
89
+ get size(): number;
90
+ }
91
+ /**
92
+ * A {@link MetricsResolver} backed by a registry: exact metrics for a registered face, otherwise
93
+ * the shared heuristic fallback (with `onHeuristic` told which face it stood in for). A run with
94
+ * no `fontFace` at all resolves to `undefined`, which the callers treat as unmeasurable.
95
+ */
96
+ declare function makeRegistryResolver(registry: FontMetricsRegistry, onHeuristic?: (face: string) => void): MetricsResolver;
97
+ //#endregion
98
+ //#region src/measure/text-fit.d.ts
99
+ /**
100
+ * PowerPoint single-spacing line pitch as a multiple of font size.
101
+ *
102
+ * Calibrated from `autofit-calibration.json` (Deck 1, `autofit-line-metrics`):
103
+ * the per-line `cy` delta is a **font-independent** 1.2117× at 12/18/32 pt across
104
+ * {Aptos, Aptos SemiBold, Calibri, Tahoma, Arial}, and PowerPoint vs LibreOffice
105
+ * agree to ≤ 0.041 pt. See `test/read/fixtures/README.md` → "Findings" #1–#2.
106
+ */
107
+ declare const SINGLE_LINE_PITCH = 1.2117;
108
+ /** PowerPoint's `fontScale` search grid: discrete 2.5% steps (Findings #3). */
109
+ declare const FONT_SCALE_STEP_PCT = 2.5;
110
+ /** Floor for the shrink search (see `docs/measured-text-fit.md` → Solvers). */
111
+ declare const MIN_FONT_SCALE_PCT = 25;
112
+ /**
113
+ * Conservative safety factors applied by the shrink solver (not by the pure
114
+ * `measureHeightPt`). Raw `hmtx` advances summed without shaping still pack a line
115
+ * a little tighter than PowerPoint, which lays text out at a device DPI and rounds
116
+ * each glyph advance up — so PowerPoint wraps marginally earlier and its fitted
117
+ * box is marginally taller. Inflating measured width and height by these factors
118
+ * makes the computed `fontScale` ≤ PowerPoint's across the calibration oracle
119
+ * (`test/read/autofit-calibration-oracle.test.js`: 0 violations over the Aptos
120
+ * cases). They err on the side of shrinking slightly too much, never overflowing.
121
+ */
122
+ declare const WIDTH_SAFETY_FACTOR = 1.03;
123
+ declare const HEIGHT_SAFETY_FACTOR = 1.04;
124
+ /** One text run with the inputs measurement needs. */
125
+ interface FitRun {
126
+ text: string;
127
+ sizePt: number;
128
+ bold?: boolean;
129
+ italic?: boolean;
130
+ fontFace?: string;
131
+ /** Character spacing in points (PowerPoint `spc`/1200). */
132
+ charSpacingPt?: number;
133
+ }
134
+ /** One paragraph: its runs plus vertical-rhythm options. */
135
+ interface FitParagraph {
136
+ runs: FitRun[];
137
+ /** Line spacing as a percent of single (100 = single). Ignored if `lineSpacingPts` set. */
138
+ lineSpacingPct?: number;
139
+ /** Exact line spacing in points (overrides `lineSpacingPct`). */
140
+ lineSpacingPts?: number;
141
+ spaceBeforePts?: number;
142
+ spaceAfterPts?: number;
143
+ }
144
+ /** Inner box (shape minus insets) the text must fit, in points. */
145
+ interface FitBox {
146
+ innerWidthPt: number;
147
+ innerHeightPt: number;
148
+ /**
149
+ * `false` when the frame does not wrap (`wrap:false` / `wrap="none"`): text lays
150
+ * out as one line per paragraph (no width-wrapping), and the shrink solver must
151
+ * additionally keep the widest line within `innerWidthPt`. A too-wide line
152
+ * overflows HORIZONTALLY — `normAutofit`'s vertical shrink never catches it, so
153
+ * without this check a non-wrapping line is never shrunk and spills out of the box
154
+ * in PowerPoint. Defaults to wrapping (`true`), so table cells and `measureText`
155
+ * are unaffected.
156
+ */
157
+ wrap?: boolean;
158
+ }
159
+ /** Resolve the metrics for a run, or `undefined` if the face is not registered. */
160
+ type MetricsResolver = (run: FitRun) => FontMetrics | undefined;
161
+ interface ShrinkResult {
162
+ fontScalePct: number;
163
+ lnSpcReductionPct: number;
164
+ }
165
+ type ShrinkOutcome = {
166
+ kind: 'fits';
167
+ } | {
168
+ kind: 'unmeasurable';
169
+ } | {
170
+ kind: 'shrink';
171
+ result: ShrinkResult;
172
+ };
173
+ /** Laid-out result of {@link measureLayout}: total height (points) + wrapped line count. */
174
+ interface LayoutResult {
175
+ heightPt: number;
176
+ lineCount: number;
177
+ /**
178
+ * Width (points) of the widest laid-out line across all paragraphs. Useful for
179
+ * tightening a box to the actual text extent or measuring a natural (single-line)
180
+ * width. Carries the same `widthSafety` inflation as the wrap decision, so a box
181
+ * set to this width will not re-wrap. Conservative (slightly wide).
182
+ */
183
+ widestLineWidthPt: number;
184
+ }
185
+ /**
186
+ * Lay out `paragraphs` at a given scale/reduction and return the total height
187
+ * (points) and wrapped line count, or `null` if any paragraph is unmeasurable.
188
+ * Errs tall (conservative): includes space-before/after and the calibrated line
189
+ * pitch. The single source of truth for both {@link measureHeightPt} (the solvers)
190
+ * and the public layout-time measure API.
191
+ */
192
+ declare function measureLayout(paragraphs: FitParagraph[], innerWidthPt: number, resolve: MetricsResolver, fontScalePct: number, lnSpcReductionPct: number, widthSafety?: number): LayoutResult | null;
193
+ /**
194
+ * Total laid-out height (points) at a given scale/reduction, or `null` if any
195
+ * paragraph is unmeasurable. Thin wrapper over {@link measureLayout}.
196
+ */
197
+ declare function measureHeightPt(paragraphs: FitParagraph[], innerWidthPt: number, resolve: MetricsResolver, fontScalePct: number, lnSpcReductionPct: number, widthSafety?: number): number | null;
198
+ /**
199
+ * Largest `fontScale` (on PowerPoint's 2.5% grid) at which the text fits the box.
200
+ * Width and height both re-measured per scale. Conservative: because the model
201
+ * over-estimates, the returned scale is ≤ PowerPoint's and the text never overflows.
202
+ *
203
+ * `lnSpcReduction` is left at 0 in P1 — dropping `fontScale` alone is provably
204
+ * conservative (PowerPoint trades line-spacing reduction to keep the font *larger*,
205
+ * so a reduction-free fit is always ≤ PowerPoint's scale). The calibration data for
206
+ * the reduction ramp (Findings #4) is recorded for a future refinement.
207
+ */
208
+ type ResizeOutcome = {
209
+ kind: 'unmeasurable';
210
+ } | {
211
+ kind: 'resize';
212
+ neededInnerHeightPt: number;
213
+ };
214
+ declare function solveResize(paragraphs: FitParagraph[], box: FitBox, resolve: MetricsResolver): ResizeOutcome;
215
+ declare function solveShrink(paragraphs: FitParagraph[], box: FitBox, resolve: MetricsResolver): ShrinkOutcome;
216
+ //#endregion
217
+ //#region src/measure/font-collection.d.ts
218
+ /**
219
+ * Font **collection** (`.ttc` / `.otc`) support for the write-side metrics.
220
+ *
221
+ * A collection is a single file holding several fonts that share their heavy tables.
222
+ * `msgothic.ttc` is three fonts (MS Gothic, MS UI Gothic, MS PGothic) over one 5.5 MB
223
+ * `glyf`; `cambria.ttc` is Cambria plus Cambria Math over one outline set. On Windows
224
+ * that is how most of the East Asian faces ship, and Cambria too, so a measurement API
225
+ * that only reads a bare sfnt cannot measure them at all.
226
+ *
227
+ * `opentype.js` does not read the `ttcf` wrapper (it throws `Unsupported OpenType
228
+ * signature ttcf` from `parseBuffer`, still true in 2.0.0), so this module unwraps one
229
+ * member into a standalone sfnt before handing the bytes over. It parses only the two
230
+ * structures that requires: the table directories and the `name` table.
231
+ *
232
+ * Upstream tracks the gap as opentypejs/opentype.js#379, open since 2019, with #866 an
233
+ * unmerged PR implementing it; check both before rewriting any of this.
234
+ *
235
+ * ## Layout
236
+ *
237
+ * ```text
238
+ * 0 'ttcf' uint16 major, uint16 minor, uint32 numFonts, uint32 dirOffset[numFonts]
239
+ * ... per member: uint32 sfntVersion, uint16 numTables, uint16 searchRange,
240
+ * uint16 entrySelector, uint16 rangeShift, then numTables x 16-byte records
241
+ * { char tag[4], uint32 checksum, uint32 offset, uint32 length }
242
+ * ```
243
+ *
244
+ * The record `offset` is **absolute from the start of the file**, which is the whole
245
+ * trick: two members name the same `glyf` bytes by pointing at them. So a member does
246
+ * not have to be *copied out* to be read on its own; it is enough to give the reader a
247
+ * buffer whose first bytes are that member's directory, leaving every table where it
248
+ * already sits. See {@link extractFontFace}.
249
+ */
250
+ /** Identity of one font inside a font file, as read from its `name` table. */
251
+ interface FontFaceInfo {
252
+ /** Position in the file: `0` for a plain TTF/OTF, `0..n-1` inside a collection. */
253
+ readonly index: number;
254
+ /** `name` ID 1, e.g. `'MS PGothic'`. Absent when the table has no readable record. */
255
+ readonly family?: string;
256
+ /** `name` ID 2, e.g. `'Regular'`. */
257
+ readonly subfamily?: string;
258
+ /** `name` ID 4, e.g. `'MS PGothic'`. */
259
+ readonly fullName?: string;
260
+ /** `name` ID 6, e.g. `'MS-PGothic'`. */
261
+ readonly postScriptName?: string;
262
+ }
263
+ /** True when `data` starts with the `ttcf` tag, i.e. holds more than one font. */
264
+ declare function isFontCollection(data: Uint8Array): boolean;
265
+ /**
266
+ * The fonts inside `data`, in file order. A plain TTF/OTF yields exactly one entry, so a
267
+ * caller never has to branch on the container format.
268
+ *
269
+ * Identity comes from each member's own `name` table, which is one of the tables a
270
+ * collection does *not* share. A field is absent when the table carries no readable
271
+ * record for it; a font whose `name` table is missing or malformed still yields an entry
272
+ * (with only `index`), because the metrics do not depend on it.
273
+ * @param {Uint8Array} data - the font file's bytes
274
+ * @returns {FontFaceInfo[]} one entry per font, index-ordered
275
+ * @example listFontFaces(readFileSync('C:/Windows/Fonts/msgothic.ttc')).map((f) => f.family)
276
+ */
277
+ declare function listFontFaces(data: Uint8Array): FontFaceInfo[];
278
+ //#endregion
279
+ //#region src/measure/fit.d.ts
280
+ /**
281
+ * Layout-time text measurement against registered metrics — the public engine
282
+ * behind `pptx.measureText()`. Uses the **same** calibrated wrap model, resolver
283
+ * semantics, and conservative safety factors as the export-time bake
284
+ * ({@link applyMeasuredFit} / {@link solveResize} / {@link solveShrink}), so a
285
+ * layout-time prediction matches the value the export would bake **for any deck
286
+ * that opted into measured fit (i.e. registered at least one face)**.
287
+ *
288
+ * With an **empty** registry the two intentionally diverge: {@link applyMeasuredFit}
289
+ * treats "no metrics" as "not opted in" and bakes nothing, while this returns
290
+ * heuristic numbers so the API is useful with zero setup. Check
291
+ * `approximatedFaces` if that distinction matters.
292
+ *
293
+ * Synchronous: assumes metrics are pre-registered (lookup is sync). A named face
294
+ * with no exact metrics silently uses the conservative heuristic (same as export)
295
+ * and is reported in `approximatedFaces`; an unnamed theme-default face returns
296
+ * `measurable: false`. Code points a *registered* face has no glyph for are reported
297
+ * in `uncoveredCodepoints`, and are the one case where the height may come back short
298
+ * rather than tall — there is no font fallback here, only the font's `.notdef` advance.
299
+ */
300
+ declare function measureText(registry: FontMetricsRegistry, text: string | TextProps[], opts: MeasureTextOptions): TextMeasurement;
301
+ //#endregion
302
+ //#region src/measure/paragraphs.d.ts
303
+ type RunOpts = TextPropsOptions & ObjectOptions;
304
+ /**
305
+ * Convert a run list (+ box-level default options) into a measurable
306
+ * `FitParagraph[]`, or null if empty. The single converter shared by the
307
+ * export-time pass ({@link extractParagraphs}) and the public layout-time
308
+ * `measureText` API, so a layout-time prediction and the baked export never drift.
309
+ */
310
+ declare function buildFitParagraphs(runs: TextProps[], opts: RunOpts): FitParagraph[] | null;
311
+ //#endregion
312
+ export { type ErrorCode, FONT_SCALE_STEP_PCT, type FitBox, type FitParagraph, type FitRun, type FontFaceInfo, type FontMetrics, FontMetricsRegistry, HEIGHT_SAFETY_FACTOR, InternalError, type InternalErrorCode, InvalidOptionError, type InvalidOptionErrorCode, type LayoutResult, MIN_FONT_SCALE_PCT, type MeasureTextOptions, MediaError, type MediaErrorCode, type MetricsResolver, type OverflowBoxOptions, PackageReadError, type PackageReadErrorCode, type ParseFontMetricsOptions, type ResizeOutcome, SINGLE_LINE_PITCH, type ShrinkOutcome, type ShrinkResult, type TextMeasurement, type TsPptxCode, TsPptxError, type TsPptxErrorOptions, UnsupportedFeatureError, type UnsupportedFeatureErrorCode, WIDTH_SAFETY_FACTOR, buildFitParagraphs, getHeuristicFontMetrics, isFontCollection, listFontFaces, makeRegistryResolver, measureHeightPt, measureLayout, measureText, parseFontMetrics, solveResize, solveShrink };
313
+ //# sourceMappingURL=measure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"measure.d.ts","names":[],"sources":["../src/measure/font-metrics.ts","../src/measure/text-fit.ts","../src/measure/font-collection.ts","../src/measure/fit.ts","../src/measure/paragraphs.ts"],"mappings":";;;;UAmBiB;;WAEP;;;;;;EAMT,iBAAiB,cAAc,gBAAgB;;;;;;;EAO/C,eAAe;;;;;;;;iBAgGA,2BAA2B;;UAM1B;;;;;;;;;;;WAWP;;;;;;;;;;;;;;;iBAgBY,iBAAiB,MAAM,YAAY,OAAO,0BAA0B,QAAQ;;;;;;;cA4BrF;mBACK;UAET;EAIR,IAAI,cAAc,SAAS,aAAa;IAAS;IAAgB;;;EAKjE,QAAQ;;;;;;;;;;;;EAiBR,aACC,iCACA,YACA;IAAS;IAAgB;;;EAM1B,IAAI,iCAAiC,gBAAc,mBAAiB;MAahE;;;;;;;iBAUW,qBACf,UAAU,qBACV,eAAe,wBACb;;;;;;;;;;;cCvOU;;cAGA;;cAGA;;;;;;;;;;;cAYA;cACA;;UAGI;EAChB;EACA;EACA;EACA;EACA;;EAEA;;;UAIgB;EAChB,MAAM;;EAEN;;EAEA;EACA;EACA;;;UAIgB;EAChB;EACA;;;;;;;;;;EAUA;;;KAIW,mBAAmB,KAAK,WAAW;UAE9B;EAChB;EACA;;KAGW;EACP;;EACA;;EACA;EAAgB,QAAQ;;;UAiMZ;EAChB;EACA;;;;;;;EAOA;;;;;;;;;iBAUe,cACf,YAAY,gBACZ,sBACA,SAAS,iBACT,sBACA,2BACA,uBACE;;;;;iBA0Ba,gBACf,YAAY,gBACZ,sBACA,SAAS,iBACT,sBACA,2BACA;;;;;;;;;;;KAgBW;EACP;;EACA;EAAgB;;iBAoBL,YAAY,YAAY,gBAAgB,KAAK,QAAQ,SAAS,kBAAkB;iBAMhF,YAAY,YAAY,gBAAgB,KAAK,QAAQ,SAAS,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UClV/E;;WAEP;;WAEA;;WAEA;;WAEA;;WAEA;;;iBA+BM,iBAAiB,MAAM;;;;;;;;;;;;;iBA0HvB,cAAc,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;iBC1GjC,YACf,UAAU,qBACV,eAAe,aACf,MAAM,qBACJ;;;KCzFS,UAAU,mBAAmB;;;;;;;iBA8BzB,mBAAmB,MAAM,aAAa,MAAM,UAAU"}
@@ -0,0 +1,3 @@
1
+ import { a as TsPptxError, i as PackageReadError, n as InvalidOptionError, o as UnsupportedFeatureError, r as MediaError, t as InternalError } from "./errors-Bvln0H-7.js";
2
+ import { _ as parseFontMetrics, a as FONT_SCALE_STEP_PCT, c as SINGLE_LINE_PITCH, d as measureLayout, f as solveResize, g as makeRegistryResolver, h as getHeuristicFontMetrics, i as buildFitParagraphs, l as WIDTH_SAFETY_FACTOR, m as FontMetricsRegistry, n as measureText, o as HEIGHT_SAFETY_FACTOR, p as solveShrink, s as MIN_FONT_SCALE_PCT, u as measureHeightPt, v as isFontCollection, y as listFontFaces } from "./fit-BKs0zxMI.js";
3
+ export { FONT_SCALE_STEP_PCT, FontMetricsRegistry, HEIGHT_SAFETY_FACTOR, InternalError, InvalidOptionError, MIN_FONT_SCALE_PCT, MediaError, PackageReadError, SINGLE_LINE_PITCH, TsPptxError, UnsupportedFeatureError, WIDTH_SAFETY_FACTOR, buildFitParagraphs, getHeuristicFontMetrics, isFontCollection, listFontFaces, makeRegistryResolver, measureHeightPt, measureLayout, measureText, parseFontMetrics, solveResize, solveShrink };