pptx-ts 3.7.0 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -269
- package/dist/autopage-odPz7zZO.js +536 -0
- package/dist/autopage-odPz7zZO.js.map +1 -0
- package/dist/binary-string-CKVAYI3M.js +24 -0
- package/dist/binary-string-CKVAYI3M.js.map +1 -0
- package/dist/body-insets-Dw_BeWD_.js +54 -0
- package/dist/body-insets-Dw_BeWD_.js.map +1 -0
- package/dist/browser.d.ts +29 -9
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +41 -14
- package/dist/browser.js.map +1 -1
- package/dist/clip-Bl01BPcN.d.ts +67 -0
- package/dist/clip-Bl01BPcN.d.ts.map +1 -0
- package/dist/diagnostics-D8ot4Ei7.d.ts +244 -0
- package/dist/diagnostics-D8ot4Ei7.d.ts.map +1 -0
- package/dist/embedded-fonts-DarT9aoa.d.ts +20 -0
- package/dist/embedded-fonts-DarT9aoa.d.ts.map +1 -0
- package/dist/entry-compose-DCnvBZz2.d.ts +1046 -0
- package/dist/entry-compose-DCnvBZz2.d.ts.map +1 -0
- package/dist/{enums-CvRYniUA.d.ts → enums-BUKTUB6V.d.ts} +21 -13
- package/dist/{enums-CvRYniUA.d.ts.map → enums-BUKTUB6V.d.ts.map} +1 -1
- package/dist/{errors-Bvln0H-7.js → errors-C4oENPcu.js} +92 -2
- package/dist/errors-C4oENPcu.js.map +1 -0
- package/dist/families.d.ts +260 -0
- package/dist/families.d.ts.map +1 -0
- package/dist/families.js +57 -0
- package/dist/families.js.map +1 -0
- package/dist/{fit-BKs0zxMI.js → fit-Cb7naFj6.js} +249 -167
- package/dist/fit-Cb7naFj6.js.map +1 -0
- package/dist/font-metrics-v5fn7s7e.d.ts +613 -0
- package/dist/font-metrics-v5fn7s7e.d.ts.map +1 -0
- package/dist/grid-DikTjFey.js +187 -0
- package/dist/grid-DikTjFey.js.map +1 -0
- package/dist/{html-dom-B0I0QSbU.js → html-dom-Iuog2wdK.js} +121 -91
- package/dist/html-dom-Iuog2wdK.js.map +1 -0
- package/dist/html.d.ts +6 -6
- package/dist/html.d.ts.map +1 -1
- package/dist/html.js +7 -6
- package/dist/html.js.map +1 -1
- package/dist/image-size-CvN2iCA4.js +1611 -0
- package/dist/image-size-CvN2iCA4.js.map +1 -0
- package/dist/index.d.ts +24 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +31 -11
- package/dist/index.js.map +1 -1
- package/dist/inspect.d.ts +40 -31
- package/dist/inspect.d.ts.map +1 -1
- package/dist/inspect.js +40 -48
- package/dist/inspect.js.map +1 -1
- package/dist/math.d.ts +7 -5
- package/dist/math.d.ts.map +1 -1
- package/dist/math.js +16 -7
- package/dist/math.js.map +1 -1
- package/dist/measure.d.ts +12 -225
- package/dist/measure.d.ts.map +1 -1
- package/dist/measure.js +3 -3
- package/dist/node.d.ts +22 -8
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +27 -7
- package/dist/node.js.map +1 -1
- package/dist/notes-Dh12JAbn.js +3264 -0
- package/dist/notes-Dh12JAbn.js.map +1 -0
- package/dist/options-internal-WqgMf720.js +43 -0
- package/dist/options-internal-WqgMf720.js.map +1 -0
- package/dist/{package-CaOLXSNi.d.ts → package-J49Ck6S2.d.ts} +27 -12
- package/dist/package-J49Ck6S2.d.ts.map +1 -0
- package/dist/playbtn-CUqQdoDf.js +22 -0
- package/dist/playbtn-CUqQdoDf.js.map +1 -0
- package/dist/{slide-ZqAdVvHV.d.ts → pres-C6qgOFAa.d.ts} +1021 -1423
- package/dist/pres-C6qgOFAa.d.ts.map +1 -0
- package/dist/{presentation-DrJtj3-C.js → presentation-DGYlAWhl.js} +3208 -2727
- package/dist/presentation-DGYlAWhl.js.map +1 -0
- package/dist/{presentation-types-CDjScsev.d.ts → presentation-types-8jLQHI4M.d.ts} +1070 -683
- package/dist/presentation-types-8jLQHI4M.d.ts.map +1 -0
- package/dist/read.d.ts +9 -9
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +4 -4
- package/dist/script.d.ts +80 -66
- package/dist/script.d.ts.map +1 -1
- package/dist/script.js +2399 -1139
- package/dist/script.js.map +1 -1
- package/dist/{shapes-BemroU-z.js → shapes-re0KyQk_.js} +2807 -1609
- package/dist/shapes-re0KyQk_.js.map +1 -0
- package/dist/slide-Dx2ZeVZ6.d.ts +1256 -0
- package/dist/slide-Dx2ZeVZ6.d.ts.map +1 -0
- package/dist/slide-size-BalTjFuv.js +88 -0
- package/dist/slide-size-BalTjFuv.js.map +1 -0
- package/dist/{units-internal-Dg95w_YD.js → table-cell-margins-EVg0EwxT.js} +235 -273
- package/dist/table-cell-margins-EVg0EwxT.js.map +1 -0
- package/dist/table-dom-BTDP3lEP.js +21 -0
- package/dist/table-dom-BTDP3lEP.js.map +1 -0
- package/dist/text-anchor-CrYXAfUu.js +176 -0
- package/dist/text-anchor-CrYXAfUu.js.map +1 -0
- package/dist/text-sN64Otf_.js +3980 -0
- package/dist/text-sN64Otf_.js.map +1 -0
- package/dist/transition-speed-kUEWDWTx.js +14 -0
- package/dist/transition-speed-kUEWDWTx.js.map +1 -0
- package/dist/units-internal-XJlf-hOl.js +649 -0
- package/dist/units-internal-XJlf-hOl.js.map +1 -0
- package/dist/zip-C0leZZMj.d.ts +67 -0
- package/dist/zip-C0leZZMj.d.ts.map +1 -0
- package/dist/zip-CKd8ihcf.js +177 -0
- package/dist/zip-CKd8ihcf.js.map +1 -0
- package/dist/zip.d.ts +3 -68
- package/dist/zip.js +3 -163
- package/dist/zoom-DPUHh85d.js +8865 -0
- package/dist/zoom-DPUHh85d.js.map +1 -0
- package/package.json +106 -19
- package/skills/ts-pptx-upstream/SKILL.md +58 -57
- package/dist/autopage-DkjYZUFD.js +0 -423
- package/dist/autopage-DkjYZUFD.js.map +0 -1
- package/dist/diagnostics-DfBdDHre.d.ts +0 -829
- package/dist/diagnostics-DfBdDHre.d.ts.map +0 -1
- package/dist/errors-Bvln0H-7.js.map +0 -1
- package/dist/errors-PflMPWBn.d.ts +0 -182
- package/dist/errors-PflMPWBn.d.ts.map +0 -1
- package/dist/fit-BKs0zxMI.js.map +0 -1
- package/dist/html-dom-B0I0QSbU.js.map +0 -1
- package/dist/namespaces-BVnNu7sg.js +0 -666
- package/dist/namespaces-BVnNu7sg.js.map +0 -1
- package/dist/notes-CJFJaG6M.js +0 -1724
- package/dist/notes-CJFJaG6M.js.map +0 -1
- package/dist/package-CaOLXSNi.d.ts.map +0 -1
- package/dist/pres-BcBR3CSM.d.ts +0 -202
- package/dist/pres-BcBR3CSM.d.ts.map +0 -1
- package/dist/presentation-DrJtj3-C.js.map +0 -1
- package/dist/presentation-types-CDjScsev.d.ts.map +0 -1
- package/dist/shapes-BemroU-z.js.map +0 -1
- package/dist/slide-ZqAdVvHV.d.ts.map +0 -1
- package/dist/text-B8SLEaZx.js +0 -11327
- package/dist/text-B8SLEaZx.js.map +0 -1
- package/dist/units-1kRzYShk.js +0 -231
- package/dist/units-1kRzYShk.js.map +0 -1
- package/dist/units-internal-Dg95w_YD.js.map +0 -1
- package/dist/zip.d.ts.map +0 -1
- package/dist/zip.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostics-DfBdDHre.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":";;;;;;;UAkBiB,sBAAsB;;EAEtC;;;;;EAKA;IAAe;IAAe;;;;;;EAK9B;;EAEA;;;;;;;;;;;;;;;EAeA,aAAa;;;UAIG,uBAAuB;;EAEvC,QAAQ;;;UAIQ,yBAAyB;;EAEzC;;;;;;KAOW,mBAAmB;;;UCjCd,8BAA8B;EAC9C;;EAEA;;UAEgB,0BAA0B;EAC1C,QAAQ,YAAY;;UAEJ,sBAAsB;EACtC,MAAM,aAAa;EACnB,MAAM;EACN,MAAM;EAEN;EACA;EACA;EACA;;;;;;;EAOA;;UAGgB;EAChB,MAAM;;;;;;;;EAQN;EACA;EACA;EACA,OAAO;EACP;EACA;EACA;EACA;;UAEgB;EAChB;EACA,OAAO;EACP;EACA;EACA,gBAAgB;;EAEhB;EACA;EACA;IAAY;IAAW;;;;;;;;;;EASvB;;;;;;;;;EASA;EACA;;EAEA;;UAEgB;EAChB,OAAO;EACP,UAAU;EAEV,OAAO;EAEP,aAAa;EAEb;EAEA;EACA;EACA,YAAY;EAEZ;EACA,QAAQ;EACR;EACA;EACA;EACA,QAAQ;EAER,gBAAgB;EAEhB,OAAO;EAEP,MAAM;EAEN,UAAU;;;;;;;;UAQM;;EAEhB;;EAEA;;EAEA;IAAO;IAAW;IAAW;;;EAE7B;IAAU;IAAW;IAAW;;;EAEhC;IAAM;IAAY;IAAY;;;EAE9B;;EAEA;;;UAGgB;;EAEhB;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;EACA;;;UAGgB;;EAEhB;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;IAAS;IAAW;IAAW;IAAY;;;;UAG3B;EAChB;EACA,OAAO;;EAEP;;EAEA;;UAEgB;EAChB;EACA,UAAU;EACV;EACA,aAAa;EACb,OAAO;EACP,YAAY;EACZ,YAAY;EACZ,aAAa;EACb,YAAY;EACZ,YAAY;EACZ;EACA,oBAAoB;EACpB,eAAe;;;;;;;EAOf,oBAAoB,QAAQ,OAAO;EAEnC,aAAa;;UAEG,4BAA4B,gBAAgB;EAC5D;IACC;IACA;IACA;IACA;;;;;KClOU;WACF,qBAAqB;;;;;;;;;;;;EAY9B,YAAY,KAAK;IAAkB;QAAmB;EACtD,sBAAsB,KAAK,kBAAkB;EAC7C,YAAY,kBAAkB,eAAe,cAAc,OAAO,eAAe;;;;;;;EAOjF,eAAe,mBAAmB,QAAQ;;;;;;;cCnB9B;cACA;cACA;;;;;;cAOA;;;;;;cAOA;;;;;;;cAQA;;;;;;cAOA;;;;;iBAMG,eAAe;;;;;;;;;KAanB;WAA0B;;;;cASzB;KAED;UAEK;;WAEP,QAAQ;;WAER;;WAEA;;WAEA;;WAEA;;WAEA;;iBAGM,YAAY,iBAAiB;iBAK7B,YAAY,iBAAiB;iBAK7B,YAAY,gBAAgB,cAAc;;;;;;iBAW1C,aAAa,iBAAiB,kBAAkB;;;;;;;;;;;;;;;iBAoBhD,WAAW,wBAAwB,kBAAkB;iBAoCrD,YAAY;iBAKZ,YAAY;iBAKZ,YAAY,aAAa;cAiB5B,kBAAkB,SAAS,OAAO,oBAAoB;;;;;;;;;;;;;;;;;;;;;;cCtF9C;;;;;;;;;;;;;UAeZ;MACG,OAAO,gBAAgB;MAgBvB;;;;mBAOM;MACN;;;;UAOH;MACG,OAAO;MAIP;;;;UAOH;MACG,QAAQ;MAIR;;;;;UAQH;MACG,SAAS;MAIT;;;;UAOH;MACG,QAAQ;MAIR;;;;UAOH;MACG,MAAM,OAAO;MAIb,SAAS;;;;UAOZ;MACG,MAAM;MAIN;;UAKH;MACG,cAAc;MAId;;;;;UAQH;MACG,QAAQ;MAIR;;mBAKM;MACN,eAAe;;mBAKT;MACN,UAAU;;mBAKJ;MACN,YAAY;;UAKf;;;;;;;qBAQW,eAAe;MACvB,gBAAgB;cAIf;UAoBJ;UAEA;MACG,cAAc;mBAIR;;mBAGA;;mBAGA;EAEjB,YAAY,SAAS;;;;;;mBAoFJ;;;;;;mBAiBA;;;;;;mBAQA;;;;;mBAMA;;;;;UAaT;;;;;;;;;;;;;;;EAuBR,gBAAa;IAAkB;QAAgD,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6LjF,oBACL,cACA,iBAAiB,aAAa,aAC9B;IAAS;IAAgB;IAAkB;MACzC;;;;;;;;;;;;;;;;;;;;;;;EAmCG,UAAU;IACf;IACA,OAAO,cAAc;IACrB;IACA,QAAQ;MACL;;;;;;;;;;;;;;;;EA6DJ,YAAY,eAAe,aAAa,MAAM,qBAAqB;;;;;;;;;;;EAcnE,aAAa,eAAe,aAAa,MAAM;;;;;;;;;;;;;;;;;;;EAuB/C,YAAY,MAAM,YAAY,MAAM,aAAa;;;;;;;;;EAc3C,QAAQ,QAAQ,iBAAiB,QAAQ;;;;;;EAazC,MAAM,QAAQ,aAAa,iBAAiB,cAAc,OAAO;;;;;;;;;;;;;;;;;EAwBjE,QAAQ,QAAQ,aAAa,QAAQ;;;;;;;EAYrC,UAAU,QAAQ,iBAAiB;;;;;;;EAoBzC,kBAAkB,cAAc,OAAO;;;;;;EAUvC,WAAW,SAAS;;;;;;EA+BpB,SAAS,UAAU,gBAAgB;;;;;;EAsEnC,aAAa,QAAQ;;;;;EAwBrB,kBAAkB,OAAO;;;;;;;;KCp9Bd;;;;;;;KAQA;;KAGA;;;;;;EAKT;EAAmB,MAAM;EAAU,SAAS;;;;;;;;;;;;;;;;;;;;;iBAiH/B,SAAS,OAAO,WAAW,WAAW,YAAY;;;;UC1IjD;;WAEP,MAAM;;WAEN;;;;;WAKA,SAAS,SAAS;;;KAIhB,qBAAqB,YAAY;;;;;;;;;;;;;;;;;;;;;iBAgC7B,qBAAqB,MAAM;;;;;;;;;;;;;;;;iBAuD3B"}
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
//#region src/codes.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* The library's condition vocabulary — one registry covering both surfaces a problem can take.
|
|
4
|
-
*
|
|
5
|
-
* A **code** names a *condition*, in `area/condition` form. The same condition keeps the same code
|
|
6
|
-
* whichever way it reaches the consumer: as a non-fatal {@link Diagnostic} (see `diagnostics.ts`)
|
|
7
|
-
* or as a thrown {@link TsPptxError} (see `errors.ts`). `coord/non-finite` means "a coordinate was
|
|
8
|
-
* `NaN`/`Infinity`" in both directions, and a consumer that special-cases it only has to learn the
|
|
9
|
-
* one string.
|
|
10
|
-
*
|
|
11
|
-
* **A code is API; the message that carries it is not.** Adding a code is back-compatible;
|
|
12
|
-
* removing or renaming one is a breaking change. Every union here is closed, so a new warning or
|
|
13
|
-
* throw site cannot be written without naming its condition in this file — that is the enforcement
|
|
14
|
-
* mechanism for keeping the vocabulary curated rather than accumulated. Reuse an existing code when
|
|
15
|
-
* the condition is genuinely the same, even if the wording differs and even if it is reported from
|
|
16
|
-
* a different entry point.
|
|
17
|
-
*
|
|
18
|
-
* The error codes are grouped by the {@link TsPptxError} subclass that carries them, not by area,
|
|
19
|
-
* because that pairing is type-enforced: `new MediaError('coord/non-finite', …)` does not compile.
|
|
20
|
-
* A condition that can genuinely arrive under two different classes needs two codes, because the
|
|
21
|
-
* class is part of what the consumer branches on.
|
|
22
|
-
*
|
|
23
|
-
* This module is types only — it emits no runtime code, so importing it can never create an import
|
|
24
|
-
* cycle and `diagnostics.ts` keeps the "safe to use from anywhere" property its header claims.
|
|
25
|
-
*/
|
|
26
|
-
/**
|
|
27
|
-
* The stable identifier for a non-fatal condition the library reports and then works around.
|
|
28
|
-
*
|
|
29
|
-
* Codes are shared across entry points where the *condition* is the same even though the message
|
|
30
|
-
* differs — an image whose natural size cannot be measured reports
|
|
31
|
-
* `image/unmeasurable-natural-size` whether it came from `addImage` or from `Picture.setImage`.
|
|
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' | 'chart/point-count-mismatch' | 'chart/point-index-out-of-range' | '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/span-out-of-range' | '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' | 'text/paragraph-margin-out-of-range' | 'text/paragraph-indent-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' | 'diagram/drawing-cache-not-updated' | 'diagram/point-has-no-text-body' | 'inspect/group-transform-missing' | 'inspect/group-transform-degenerate' | 'measure/shrink-unmeasured' | 'measure/resize-unmeasured' | 'measure/heuristic-metrics' | 'measure/uncovered-codepoints' | 'margin/legacy-points' | 'transparency/out-of-range' | 'opacity/out-of-range' | 'line/width-out-of-range' | 'coord/bare-number-is-inches';
|
|
34
|
-
/**
|
|
35
|
-
* Conditions carried by `InvalidOptionError`: the caller passed something the library cannot use.
|
|
36
|
-
*
|
|
37
|
-
* This is the largest group by design — the project's stated policy is to throw rather than coerce
|
|
38
|
-
* (`AGENTS.md` → "Silent coercion of invalid input is a footgun"), so most throws are here.
|
|
39
|
-
*/
|
|
40
|
-
type InvalidOptionErrorCode = 'coord/non-finite' | 'coord/not-positive' | 'coord/negative' | 'coord/invalid-format' | 'geometry/arc-angle-non-finite' | 'chart/missing-type' | 'chart/unknown-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' | 'import/output-index-conflict' | 'import/output-index-out-of-range' | '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' | 'font/collection-index-out-of-range' | 'font/collection-face-not-found' | 'layout/unknown' | 'master/missing-title' | 'math/invalid-latex' | 'zip/unsupported-input' | 'zip/unsupported-output';
|
|
41
|
-
/**
|
|
42
|
-
* Conditions carried by `UnsupportedFeatureError`: the request is well-formed, but this build,
|
|
43
|
-
* runtime, or shape cannot express it. Distinct from `InvalidOptionError` because the caller did
|
|
44
|
-
* nothing wrong — the answer is "not here", not "not like that".
|
|
45
|
-
*/
|
|
46
|
-
type UnsupportedFeatureErrorCode = 'gradient/type-unsupported' | 'group/kind-not-groupable' | 'shape/element-unsupported' | 'shape/fill-unsupported' | 'shape/line-unsupported' | 'shape/shape-properties-unsupported' | 'shape/no-text-frame' | 'math/missing-optional-peer' | 'font/opentype-unavailable' | 'zip/filesystem-unavailable' | 'runtime/file-output-unavailable';
|
|
47
|
-
/**
|
|
48
|
-
* Conditions carried by `PackageReadError`: the bytes handed to the library are not a package it
|
|
49
|
-
* can read, or a part inside one is structurally malformed. Always about *input*, never about
|
|
50
|
-
* something the library is asked to produce.
|
|
51
|
-
*/
|
|
52
|
-
type PackageReadErrorCode = 'zip/not-a-zip-archive' | 'zip/file-read-failed' | 'package/not-an-opc-package' | 'package/content-types-invalid-root' | 'package/content-types-entry-incomplete' | 'package/part-content-type-missing' | 'package/relationships-invalid-root' | 'package/relationship-incomplete' | 'package/relationship-invalid-target-mode' | 'package/duplicate-relationship-id' | 'package/relationship-target-escapes-root' | 'package/relationship-target-missing' | 'package/office-document-relationship-invalid' | 'package/part-missing' | 'package/part-has-no-root' | 'slide/no-shape-tree' | 'shape/no-non-visual-properties' | 'table/cell-has-no-text-body' | 'diagram/parent-edge-cycle';
|
|
53
|
-
/**
|
|
54
|
-
* Conditions carried by `MediaError`: an image, font, or audio/video payload could not be fetched,
|
|
55
|
-
* read, or decoded. Kept separate from `PackageReadError` because the failure is in a *referenced
|
|
56
|
-
* resource*, not in the package structure, and the recovery is usually different (fix the URL or
|
|
57
|
-
* the file, not the deck).
|
|
58
|
-
*/
|
|
59
|
-
type MediaErrorCode = 'media/load-failed' | 'font/fetch-failed' | 'font/read-failed' | 'font/parse-failed' | 'media/fetch-failed' | 'media/read-failed' | 'media/decode-failed' | 'media/svg-preview-failed';
|
|
60
|
-
/**
|
|
61
|
-
* Conditions carried by `InternalError`: an invariant the library maintains itself did not hold.
|
|
62
|
-
* Reaching one is a bug in ts-pptx, not something a consumer can fix by changing their input —
|
|
63
|
-
* which is exactly why it is worth being able to tell apart from the four classes above.
|
|
64
|
-
*/
|
|
65
|
-
type InternalErrorCode = 'layout/default-not-registered' | 'slide/rel-index-out-of-range' | 'slide/part-already-in-deck' | 'import/part-went-missing' | 'chart/type-not-routed' | 'animation/timing-scaffold-failed' | 'oxml/node-has-no-document' | 'oxml/node-has-no-parent';
|
|
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
|
-
*/
|
|
79
|
-
type ErrorCode = InvalidOptionErrorCode | UnsupportedFeatureErrorCode | PackageReadErrorCode | MediaErrorCode | InternalErrorCode;
|
|
80
|
-
/** Every condition the library can report, warned or thrown. */
|
|
81
|
-
type TsPptxCode = DiagnosticCode | ErrorCode;
|
|
82
|
-
//#endregion
|
|
83
|
-
//#region src/errors.d.ts
|
|
84
|
-
/** Extra context accepted by every {@link TsPptxError} constructor. */
|
|
85
|
-
interface TsPptxErrorOptions extends ErrorOptions {
|
|
86
|
-
/**
|
|
87
|
-
* Structured context for the condition, when a site has any to give. Mirrors `Diagnostic.detail`
|
|
88
|
-
* so the same condition looks the same whether it was warned or thrown.
|
|
89
|
-
*/
|
|
90
|
-
readonly detail?: Readonly<Record<string, unknown>>;
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Base class for every error ts-pptx throws.
|
|
94
|
-
*
|
|
95
|
-
* Catch this to catch anything from the library; narrow with `instanceof` on a subclass, or branch
|
|
96
|
-
* on {@link TsPptxError.code}, to react to something specific. It is never thrown directly — every
|
|
97
|
-
* site picks one of the five subclasses.
|
|
98
|
-
*/
|
|
99
|
-
declare class TsPptxError extends Error {
|
|
100
|
-
/** Stable condition identifier — see {@link ErrorCode}. Branch on this, not on the text. */
|
|
101
|
-
readonly code: ErrorCode;
|
|
102
|
-
/** Structured context for the condition, when the throwing site had any to give. */
|
|
103
|
-
readonly detail?: Readonly<Record<string, unknown>>;
|
|
104
|
-
/**
|
|
105
|
-
* @param code - the stable condition identifier
|
|
106
|
-
* @param message - explanation for a human reading a stack trace; not part of the contract
|
|
107
|
-
* @param options - standard `cause`, plus optional structured `detail`
|
|
108
|
-
*/
|
|
109
|
-
constructor(code: ErrorCode, message: string, options?: TsPptxErrorOptions);
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* The caller passed something the library cannot use — a non-finite coordinate, an unknown enum
|
|
113
|
-
* value, a required option left out, a value outside its legal range.
|
|
114
|
-
*
|
|
115
|
-
* This is the error behind the project's throw-rather-than-coerce policy: emitting a degenerate
|
|
116
|
-
* result (a zero-size shape, a silently dropped option) hides the mistake, so the library refuses
|
|
117
|
-
* instead. Reaching one means the calling code needs to change.
|
|
118
|
-
*/
|
|
119
|
-
declare class InvalidOptionError extends TsPptxError {
|
|
120
|
-
readonly code: InvalidOptionErrorCode;
|
|
121
|
-
constructor(code: InvalidOptionErrorCode, message: string, options?: TsPptxErrorOptions);
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* The request is well-formed but cannot be expressed here: an optional peer dependency is not
|
|
125
|
-
* installed, the runtime lacks a capability, or the shape/feature has no OOXML representation the
|
|
126
|
-
* library emits.
|
|
127
|
-
*
|
|
128
|
-
* Distinct from {@link InvalidOptionError} because the caller did nothing wrong — the answer is
|
|
129
|
-
* "not here", not "not like that" — and the fix is usually to install something or pick a different
|
|
130
|
-
* approach rather than to correct a value.
|
|
131
|
-
*/
|
|
132
|
-
declare class UnsupportedFeatureError extends TsPptxError {
|
|
133
|
-
readonly code: UnsupportedFeatureErrorCode;
|
|
134
|
-
constructor(code: UnsupportedFeatureErrorCode, message: string, options?: TsPptxErrorOptions);
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* The bytes handed to the library are not a package it can read, or a part inside one is
|
|
138
|
-
* structurally malformed — a missing `[Content_Types].xml`, a relationship pointing at nothing, a
|
|
139
|
-
* slide part with no root element.
|
|
140
|
-
*
|
|
141
|
-
* Always about *input*. A problem with something the library is being asked to produce is an
|
|
142
|
-
* {@link InvalidOptionError}.
|
|
143
|
-
*/
|
|
144
|
-
declare class PackageReadError extends TsPptxError {
|
|
145
|
-
readonly code: PackageReadErrorCode;
|
|
146
|
-
constructor(code: PackageReadErrorCode, message: string, options?: TsPptxErrorOptions);
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* A referenced image, font, or audio/video resource could not be fetched, read, or decoded.
|
|
150
|
-
*
|
|
151
|
-
* Kept apart from {@link PackageReadError} because the failure is in a resource the deck *points
|
|
152
|
-
* at*, not in the package structure — a broken URL, an unreadable path, a corrupt font file — and
|
|
153
|
-
* a consumer typically retries or substitutes rather than rejecting the deck.
|
|
154
|
-
*/
|
|
155
|
-
declare class MediaError extends TsPptxError {
|
|
156
|
-
readonly code: MediaErrorCode;
|
|
157
|
-
constructor(code: MediaErrorCode, message: string, options?: TsPptxErrorOptions);
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* An invariant the library maintains itself did not hold.
|
|
161
|
-
*
|
|
162
|
-
* No consumer input should be able to produce one, which is the whole reason it is a separate
|
|
163
|
-
* class: seeing it means the bug is in ts-pptx, and the useful response is to file it rather than
|
|
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.
|
|
175
|
-
*/
|
|
176
|
-
declare class InternalError extends TsPptxError {
|
|
177
|
-
readonly code: InternalErrorCode;
|
|
178
|
-
constructor(code: InternalErrorCode, message: string, options?: TsPptxErrorOptions);
|
|
179
|
-
}
|
|
180
|
-
//#endregion
|
|
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 };
|
|
182
|
-
//# sourceMappingURL=errors-PflMPWBn.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"errors-PflMPWBn.d.ts","names":[],"sources":["../src/codes.ts","../src/errors.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAgCY;;;;;;;KAiIA;;;;;;KA8IA;;;;;;KAsBA;;;;;;;KAkCA;;;;;;KAqBA;;;;;;;;;;;;;;KAgCA,YACT,yBACA,8BACA,uBACA,iBACA;;KAGS,aAAa,iBAAiB;;;;UCxXzB,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"}
|
package/dist/fit-BKs0zxMI.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fit-BKs0zxMI.js","names":[],"sources":["../src/measure/font-collection.ts","../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 * Font **collection** (`.ttc` / `.otc`) support for the write-side metrics.\n *\n * A collection is a single file holding several fonts that share their heavy tables.\n * `msgothic.ttc` is three fonts (MS Gothic, MS UI Gothic, MS PGothic) over one 5.5 MB\n * `glyf`; `cambria.ttc` is Cambria plus Cambria Math over one outline set. On Windows\n * that is how most of the East Asian faces ship, and Cambria too, so a measurement API\n * that only reads a bare sfnt cannot measure them at all.\n *\n * `opentype.js` does not read the `ttcf` wrapper (it throws `Unsupported OpenType\n * signature ttcf` from `parseBuffer`, still true in 2.0.0), so this module unwraps one\n * member into a standalone sfnt before handing the bytes over. It parses only the two\n * structures that requires: the table directories and the `name` table.\n *\n * Upstream tracks the gap as opentypejs/opentype.js#379, open since 2019, with #866 an\n * unmerged PR implementing it; check both before rewriting any of this.\n *\n * ## Layout\n *\n * ```text\n * 0 'ttcf' uint16 major, uint16 minor, uint32 numFonts, uint32 dirOffset[numFonts]\n * ... per member: uint32 sfntVersion, uint16 numTables, uint16 searchRange,\n * uint16 entrySelector, uint16 rangeShift, then numTables x 16-byte records\n * { char tag[4], uint32 checksum, uint32 offset, uint32 length }\n * ```\n *\n * The record `offset` is **absolute from the start of the file**, which is the whole\n * trick: two members name the same `glyf` bytes by pointing at them. So a member does\n * not have to be *copied out* to be read on its own; it is enough to give the reader a\n * buffer whose first bytes are that member's directory, leaving every table where it\n * already sits. See {@link extractFontFace}.\n */\n\nimport { InvalidOptionError, MediaError } from '../errors.js'\n\n/** `'ttcf'`, the tag that marks a font collection. */\nconst TTC_TAG = 'ttcf'\n\n/** Bytes in one sfnt table record: tag, checksum, offset, length. */\nconst RECORD_SIZE = 16\n\n/** Bytes in an sfnt table directory header, before the first record. */\nconst DIRECTORY_HEADER_SIZE = 12\n\n/** `name` IDs read for face identity: family, subfamily, full name, PostScript name. */\nconst NAME_FAMILY = 1\nconst NAME_SUBFAMILY = 2\nconst NAME_FULL = 4\nconst NAME_POSTSCRIPT = 6\n\n/** Identity of one font inside a font file, as read from its `name` table. */\nexport interface FontFaceInfo {\n\t/** Position in the file: `0` for a plain TTF/OTF, `0..n-1` inside a collection. */\n\treadonly index: number\n\t/** `name` ID 1, e.g. `'MS PGothic'`. Absent when the table has no readable record. */\n\treadonly family?: string\n\t/** `name` ID 2, e.g. `'Regular'`. */\n\treadonly subfamily?: string\n\t/** `name` ID 4, e.g. `'MS PGothic'`. */\n\treadonly fullName?: string\n\t/** `name` ID 6, e.g. `'MS-PGothic'`. */\n\treadonly postScriptName?: string\n}\n\n/** A parsed sfnt table directory: the member's format tag plus its table records. */\ninterface Directory {\n\treadonly sfntVersion: number\n\treadonly tables: readonly TableRecord[]\n}\n\ninterface TableRecord {\n\t/** Four ASCII characters, e.g. `'glyf'`. */\n\treadonly tag: string\n\treadonly checksum: number\n\t/** Absolute from the start of the file, shared between members of a collection. */\n\treadonly offset: number\n\treadonly length: number\n}\n\nfunction view(data: Uint8Array): DataView {\n\treturn new DataView(data.buffer, data.byteOffset, data.byteLength)\n}\n\n/** Four ASCII bytes at `off` as a string, or `''` when they run past the end. */\nfunction tagAt(data: Uint8Array, off: number): string {\n\tif (off < 0 || off + 4 > data.byteLength) return ''\n\tlet s = ''\n\tfor (let i = 0; i < 4; i++) s += String.fromCharCode(data[off + i] as number)\n\treturn s\n}\n\n/** True when `data` starts with the `ttcf` tag, i.e. holds more than one font. */\nexport function isFontCollection(data: Uint8Array): boolean {\n\treturn tagAt(data, 0) === TTC_TAG\n}\n\n/**\n * Offsets of every member's table directory, in file order. A plain sfnt has exactly\n * one, at 0.\n */\nfunction directoryOffsets(data: Uint8Array): number[] {\n\tif (!isFontCollection(data)) return [0]\n\tconst dv = view(data)\n\tif (data.byteLength < 12) throw new MediaError('font/parse-failed', 'Font collection header is truncated')\n\tconst numFonts = dv.getUint32(8)\n\t// A collection with no members, or one whose offset table cannot fit, is malformed\n\t// rather than merely unsupported: there is nothing to select from.\n\tif (numFonts === 0) throw new MediaError('font/parse-failed', 'Font collection declares 0 fonts')\n\tif (12 + numFonts * 4 > data.byteLength)\n\t\tthrow new MediaError(\n\t\t\t'font/parse-failed',\n\t\t\t`Font collection declares ${numFonts} fonts but the offset table is truncated`\n\t\t)\n\tconst offsets: number[] = []\n\tfor (let i = 0; i < numFonts; i++) offsets.push(dv.getUint32(12 + i * 4))\n\treturn offsets\n}\n\n/** Read the table directory at `dirOff`, materializing every record before any write. */\nfunction readDirectory(data: Uint8Array, dirOff: number): Directory {\n\tconst dv = view(data)\n\tif (dirOff + DIRECTORY_HEADER_SIZE > data.byteLength)\n\t\tthrow new MediaError('font/parse-failed', `Font table directory at ${dirOff} is truncated`)\n\tconst sfntVersion = dv.getUint32(dirOff)\n\tconst numTables = dv.getUint16(dirOff + 4)\n\tif (numTables === 0) throw new MediaError('font/parse-failed', `Font at ${dirOff} declares 0 tables`)\n\tconst end = dirOff + DIRECTORY_HEADER_SIZE + numTables * RECORD_SIZE\n\tif (end > data.byteLength)\n\t\tthrow new MediaError(\n\t\t\t'font/parse-failed',\n\t\t\t`Font at ${dirOff} declares ${numTables} tables but the directory is truncated`\n\t\t)\n\tconst tables: TableRecord[] = []\n\tfor (let i = 0; i < numTables; i++) {\n\t\tconst rec = dirOff + DIRECTORY_HEADER_SIZE + i * RECORD_SIZE\n\t\ttables.push({\n\t\t\ttag: tagAt(data, rec),\n\t\t\tchecksum: dv.getUint32(rec + 4),\n\t\t\toffset: dv.getUint32(rec + 8),\n\t\t\tlength: dv.getUint32(rec + 12),\n\t\t})\n\t}\n\treturn { sfntVersion, tables }\n}\n\n/**\n * Decode one `name` record's string. Windows (platform 3) and Unicode (platform 0)\n * records are UTF-16BE; Macintosh (platform 1) Roman is byte-per-character and\n * coincides with Latin-1 over the ASCII range these names use.\n */\nfunction decodeNameString(data: Uint8Array, off: number, length: number, platformID: number): string {\n\tif (off < 0 || off + length > data.byteLength) return ''\n\tif (platformID === 1) {\n\t\tlet s = ''\n\t\tfor (let i = 0; i < length; i++) s += String.fromCharCode(data[off + i] as number)\n\t\treturn s\n\t}\n\tlet s = ''\n\tfor (let i = 0; i + 1 < length; i += 2)\n\t\ts += String.fromCharCode(((data[off + i] as number) << 8) | (data[off + i + 1] as number))\n\treturn s\n}\n\n/**\n * How much a `name` record is preferred when several carry the same ID. Windows English\n * wins, then any Windows or Unicode record, then Macintosh. The ranking matters because\n * `msgothic.ttc` carries both `'MS Gothic'` (0x409) and the Japanese localized name for\n * the same ID, and a caller selecting by name types the former.\n */\nfunction nameRecordRank(platformID: number, languageID: number): number {\n\tif (platformID === 3) return languageID === 0x409 ? 3 : 2\n\tif (platformID === 0) return 2\n\tif (platformID === 1) return languageID === 0 ? 1 : 0\n\treturn 0\n}\n\n/** Read the wanted IDs out of a `name` table, keeping the best-ranked record for each. */\nfunction readNames(data: Uint8Array, base: number, length: number): Map<number, string> {\n\tconst out = new Map<number, string>()\n\tconst ranks = new Map<number, number>()\n\tif (base + 6 > data.byteLength || base + length > data.byteLength) return out\n\tconst dv = view(data)\n\tconst count = dv.getUint16(base + 2)\n\tconst storage = base + dv.getUint16(base + 4)\n\tfor (let i = 0; i < count; i++) {\n\t\tconst rec = base + 6 + i * 12\n\t\tif (rec + 12 > data.byteLength) break\n\t\tconst nameID = dv.getUint16(rec + 6)\n\t\tif (nameID !== NAME_FAMILY && nameID !== NAME_SUBFAMILY && nameID !== NAME_FULL && nameID !== NAME_POSTSCRIPT)\n\t\t\tcontinue\n\t\tconst platformID = dv.getUint16(rec)\n\t\tconst languageID = dv.getUint16(rec + 4)\n\t\tconst rank = nameRecordRank(platformID, languageID)\n\t\tif (rank <= (ranks.get(nameID) ?? -1)) continue\n\t\tconst text = decodeNameString(data, storage + dv.getUint16(rec + 10), dv.getUint16(rec + 8), platformID)\n\t\tif (!text) continue\n\t\tout.set(nameID, text)\n\t\tranks.set(nameID, rank)\n\t}\n\treturn out\n}\n\n/**\n * The fonts inside `data`, in file order. A plain TTF/OTF yields exactly one entry, so a\n * caller never has to branch on the container format.\n *\n * Identity comes from each member's own `name` table, which is one of the tables a\n * collection does *not* share. A field is absent when the table carries no readable\n * record for it; a font whose `name` table is missing or malformed still yields an entry\n * (with only `index`), because the metrics do not depend on it.\n * @param {Uint8Array} data - the font file's bytes\n * @returns {FontFaceInfo[]} one entry per font, index-ordered\n * @example listFontFaces(readFileSync('C:/Windows/Fonts/msgothic.ttc')).map((f) => f.family)\n */\nexport function listFontFaces(data: Uint8Array): FontFaceInfo[] {\n\treturn directoryOffsets(data).map((dirOff, index) => {\n\t\tconst { tables } = readDirectory(data, dirOff)\n\t\tconst name = tables.find((t) => t.tag === 'name')\n\t\tconst names = name ? readNames(data, name.offset, name.length) : new Map<number, string>()\n\t\tconst family = names.get(NAME_FAMILY)\n\t\tconst subfamily = names.get(NAME_SUBFAMILY)\n\t\tconst fullName = names.get(NAME_FULL)\n\t\tconst postScriptName = names.get(NAME_POSTSCRIPT)\n\t\treturn {\n\t\t\tindex,\n\t\t\t...(family ? { family } : {}),\n\t\t\t...(subfamily ? { subfamily } : {}),\n\t\t\t...(fullName ? { fullName } : {}),\n\t\t\t...(postScriptName ? { postScriptName } : {}),\n\t\t}\n\t})\n}\n\n/** A face's names, lowercased, for case-insensitive selection. */\nfunction selectableNames(face: FontFaceInfo): string[] {\n\treturn [face.family, face.fullName, face.postScriptName]\n\t\t.filter((n): n is string => typeof n === 'string' && n.length > 0)\n\t\t.map((n) => n.toLowerCase())\n}\n\n/** Render the available faces for an error message, e.g. ``0 `MS Gothic`, 1 `MS PGothic` ``. */\nfunction describeFaces(faces: readonly FontFaceInfo[]): string {\n\treturn faces.map((f) => `${f.index} \\`${f.family ?? f.fullName ?? '(unnamed)'}\\``).join(', ')\n}\n\n/**\n * Resolve a `font` selector against the faces in `data`.\n *\n * The selector means the same thing whatever the container: a plain TTF/OTF is a\n * one-entry list, so `{ font: 1 }` or a name that does not match is an error there too\n * rather than being quietly ignored. Silently falling back to the only/first font is the\n * failure mode worth refusing: it measures one face's advances while the caller believes\n * it registered another's, and nothing downstream can tell.\n * @param {Uint8Array} data - the font file's bytes\n * @param {number | string} [font] - 0-based index, or a name matched case-insensitively\n * against the family, full, and PostScript names. Absent selects index 0.\n * @returns {number} the index of the selected font\n */\nexport function resolveFontFace(data: Uint8Array, font?: number | string): number {\n\tif (font === undefined) return 0\n\tconst faces = listFontFaces(data)\n\tif (typeof font === 'number') {\n\t\tif (!Number.isInteger(font) || font < 0 || font >= faces.length)\n\t\t\tthrow new InvalidOptionError(\n\t\t\t\t'font/collection-index-out-of-range',\n\t\t\t\t`Font index ${font} is out of range: the file holds ${faces.length} font(s) (${describeFaces(faces)})`\n\t\t\t)\n\t\treturn font\n\t}\n\tconst wanted = font.toLowerCase()\n\tconst hit = faces.find((f) => selectableNames(f).includes(wanted))\n\tif (!hit)\n\t\tthrow new InvalidOptionError(\n\t\t\t'font/collection-face-not-found',\n\t\t\t`No font named \"${font}\" in this file. It holds: ${describeFaces(faces)}`\n\t\t)\n\treturn hit.index\n}\n\n/**\n * Bytes for one font of `data` as a standalone sfnt, ready for a parser that does not\n * read the `ttcf` wrapper.\n *\n * A plain TTF/OTF at index 0 is returned as-is. For a collection the member's tables are\n * **not copied out**: the file is copied once and the member's directory is written over\n * the prologue at offset 0, so every record keeps the absolute offset it already had and\n * the shared `glyf` is neither duplicated nor moved. The prologue is always large enough\n * to hold that directory, because a well-formed collection places the first table after\n * the `ttcf` header *and* every member's directory, which already includes this one.\n * That is asserted rather than assumed: a file that violates it would otherwise have its\n * first table silently overwritten.\n * @param {Uint8Array} data - the font file's bytes\n * @param {number} index - which font, as resolved by {@link resolveFontFace}\n * @returns {Uint8Array} a buffer whose first bytes are a plain sfnt table directory\n */\nexport function extractFontFace(data: Uint8Array, index: number): Uint8Array {\n\tconst offsets = directoryOffsets(data)\n\tconst dirOff = offsets[index]\n\tif (dirOff === undefined)\n\t\tthrow new InvalidOptionError(\n\t\t\t'font/collection-index-out-of-range',\n\t\t\t`Font index ${index} is out of range: the file holds ${offsets.length} font(s)`\n\t\t)\n\tif (!isFontCollection(data)) return data\n\n\tconst { sfntVersion, tables } = readDirectory(data, dirOff)\n\tconst prologue = DIRECTORY_HEADER_SIZE + tables.length * RECORD_SIZE\n\tconst firstTable = Math.min(...tables.map((t) => t.offset))\n\tif (prologue > firstTable)\n\t\tthrow new MediaError(\n\t\t\t'font/parse-failed',\n\t\t\t`Font ${index} in this collection cannot be unwrapped: its ${tables.length}-table directory needs ${prologue} bytes but the first table starts at ${firstTable}`\n\t\t)\n\n\t// Copy first, then overwrite: `dirOff` frequently sits *inside* the region about to be\n\t// written (member 0 of msgothic.ttc has its directory at 36, and the prologue is 380),\n\t// which is safe only because `readDirectory` already materialized every record.\n\tconst out = new Uint8Array(data)\n\tconst dv = new DataView(out.buffer, out.byteOffset, out.byteLength)\n\tconst entrySelector = Math.floor(Math.log2(tables.length))\n\tconst searchRange = RECORD_SIZE * 2 ** entrySelector\n\tdv.setUint32(0, sfntVersion)\n\tdv.setUint16(4, tables.length)\n\tdv.setUint16(6, searchRange)\n\tdv.setUint16(8, entrySelector)\n\tdv.setUint16(10, tables.length * RECORD_SIZE - searchRange)\n\tlet p = DIRECTORY_HEADER_SIZE\n\tfor (const t of tables) {\n\t\tfor (let i = 0; i < 4; i++) out[p + i] = t.tag.charCodeAt(i) & 0xff\n\t\tdv.setUint32(p + 4, t.checksum)\n\t\tdv.setUint32(p + 8, t.offset)\n\t\tdv.setUint32(p + 12, t.length)\n\t\tp += RECORD_SIZE\n\t}\n\t// `head.checkSumAdjustment` now describes the collection rather than this buffer. No\n\t// consumer here validates it, and recomputing it would mean check-summing the whole\n\t// file to produce a number only a validator reads.\n\treturn out\n}\n","/**\n * 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 `docs/measured-text-fit.md` (\"Font metrics provider\").\n */\n\nimport { MediaError, UnsupportedFeatureError } from '../errors.js'\nimport { extractFontFace, resolveFontFace } from './font-collection.js'\nimport type { FitParagraph, 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/** Options for {@link parseFontMetrics}. */\nexport interface ParseFontMetricsOptions {\n\t/**\n\t * Which font to read out of a file that holds several: a 0-based index, or a name\n\t * matched case-insensitively against the family, full, and PostScript names\n\t * (`listFontFaces` lists them). Omitted selects the first.\n\t *\n\t * Collections (`.ttc`/`.otc`) are why this exists: `msgothic.ttc` is three fonts and\n\t * `cambria.ttc` is two. The selector means the same thing for a plain TTF/OTF, which\n\t * is a one-entry list, so a wrong index or an unmatched name is an error there rather\n\t * than being ignored.\n\t */\n\treadonly font?: number | string\n}\n\n/**\n * Parse a font file into a `FontMetrics`. Lazily imports opentype.js.\n *\n * Reads plain TTF/OTF and **font collections** (`.ttc`/`.otc`); for a collection, pass\n * `font` to say which member, since a collection has no single answer. The underlying\n * parser does not read the `ttcf` wrapper, so the selected member is unwrapped into a\n * standalone sfnt first (see `measure/font-collection.ts`).\n * @param {Uint8Array} data - the font file's bytes\n * @param {ParseFontMetricsOptions} [opts] - which font, for a file holding several\n * @returns {Promise<FontMetrics>} advance widths and cmap coverage for that font\n * @example await parseFontMetrics(bytes) // a plain .ttf\n * @example await parseFontMetrics(ttcBytes, { font: 'MS PGothic' })\n */\nexport async function parseFontMetrics(data: Uint8Array, opts?: ParseFontMetricsOptions): 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\tconst sfnt = extractFontFace(data, resolveFontFace(data, opts?.font))\n\t// opentype.parse needs a standalone ArrayBuffer view of exactly the font bytes.\n\tconst buf = sfnt.buffer.slice(sfnt.byteOffset, sfnt.byteOffset + sfnt.byteLength) as ArrayBuffer\n\ttry {\n\t\treturn new OpentypeFontMetrics(parse(buf))\n\t} catch (ex) {\n\t\t// The parser throws bare `Error`s. Reclassify so a consumer can catch this by the\n\t\t// same taxonomy as every other library failure instead of matching on a message.\n\t\tthrow new MediaError('font/parse-failed', `Unable to parse font file: ${String(ex)}`, { cause: ex })\n\t}\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()}\\0${bold ? 1 : 0}\\0${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()}\\0`\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()}\\0`\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/**\n * Accumulate, per face, the code points `paragraphs` uses that the run's **registered**\n * metrics have no glyph for.\n *\n * This is the one thing the width arithmetic cannot see. PowerPoint substitutes another\n * face per code point and lays the run out in *that* font's advances; the model has no\n * fallback and charges the registered font's `.notdef` advance instead, which is a single\n * flat number unrelated to the glyph that actually paints. Unlike the other approximations\n * here it is **not** conservative in a fixed direction: a `.notdef` wider than the real\n * glyph over-reports (a phantom line — safe), a narrower one under-reports and can drop a\n * line, which is the overflow direction the resize bake has no safety net for. So it is\n * surfaced rather than absorbed — see `docs/measured-text-fit.md` (\"No font fallback\").\n *\n * Runs whose face has no registered metrics at all are skipped: they measure through the\n * cmap-less heuristic, which has no coverage to report, and the caller already flags them\n * as approximated faces.\n * @param paragraphs - the runs to audit, as handed to the layout\n * @param registry - the metrics the layout resolved against\n * @param into - face → uncovered code points, added to in place\n */\nexport function collectUncoveredCodepoints(\n\tparagraphs: FitParagraph[],\n\tregistry: FontMetricsRegistry,\n\tinto: Map<string, Set<number>>\n): void {\n\tfor (const para of paragraphs) {\n\t\tfor (const run of para.runs) {\n\t\t\tconst face = run.fontFace\n\t\t\tif (typeof face !== 'string' || face.length === 0) continue\n\t\t\tconst metrics = registry.get(face, run.bold, run.italic)\n\t\t\tif (!metrics) continue\n\t\t\tlet missing: Set<number> | undefined\n\t\t\t// `for..of` iterates code points, so an astral character is audited whole\n\t\t\t// rather than as two uncovered surrogates.\n\t\t\tfor (const ch of run.text) {\n\t\t\t\tconst cp = ch.codePointAt(0)\n\t\t\t\tif (cp === undefined || metrics.hasCodepoint(cp)) continue\n\t\t\t\tmissing ??= into.get(face) ?? new Set<number>()\n\t\t\t\tmissing.add(cp)\n\t\t\t}\n\t\t\tif (missing) into.set(face, missing)\n\t\t}\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 * A code point that is its own wrap opportunity: a line may break either side of\n * it, with no whitespace involved. Latin words break only at whitespace, but\n * Chinese and Japanese text breaks between any two characters, so treating one\n * long run of them as a single unbreakable \"word\" moves the whole run to the next\n * line, over-reports the laid-out line count, and shrinks text that actually fits.\n *\n * **Hangul is deliberately absent.** UAX #14 makes Hangul breakable between\n * syllables, but PowerPoint does not: Korean is written with spaces between words\n * and the app breaks it like Latin. `autofit-cjk-wrap.pptx` pins that directly —\n * the same box that lays out in 2 lines in Han or Kana takes 3 in Hangul, because\n * the run moves down whole. A Hangul run longer than one line still breaks between\n * syllables, but that is the over-long-token character-wrap fallback in\n * `countLines`, which handles it without a break class. Adding Hangul here would\n * *under*-report the line count for Korean, which is the direction that overflows.\n *\n * Backed by `autofit-cjk-wrap.pptx` (PowerPoint-authored, one case per claim):\n * CJK Unified Ideographs, Hiragana/Katakana, fullwidth Latin, halfwidth Katakana\n * and Plane 2 all break per character; Hangul syllables do not. The remaining\n * ranges are the sibling blocks of the same UAX #14 class ID, generalized from\n * those cases rather than pinned one by one.\n *\n * Known gap: no kinsoku (line-break prohibition) rules. PowerPoint will not start\n * a line with `。` or `、` and hangs them past the right inset instead; this model\n * breaks before them. That is a widest-line difference, not a line-count one, and\n * `docs/measured-text-fit.md` records it.\n */\nexport function isCjkBreakCharacter(ch: string): boolean {\n\tconst cp = ch.codePointAt(0) ?? 0\n\treturn (\n\t\t// U+3000 IDEOGRAPHIC SPACE falls in this first range but never reaches here:\n\t\t// `isWhitespace` claims it first, so it stays a space token.\n\t\t(cp >= 0x2e80 && cp <= 0x303f) || // CJK Radicals / Kangxi / IDC / CJK Symbols and Punctuation\n\t\t(cp >= 0x3040 && cp <= 0x30ff) || // Hiragana / Katakana (fixture)\n\t\t// Bopomofo and Bopomofo Extended sit either side of the Hangul Compatibility\n\t\t// Jamo block excluded below, but they are Chinese phonetic notation, not Korean:\n\t\t// same UAX #14 class as Han, and PowerPoint breaks them the same way.\n\t\t(cp >= 0x3100 && cp <= 0x312f) || // Bopomofo\n\t\t(cp >= 0x3190 && cp <= 0x319f) || // Kanbun\n\t\t(cp >= 0x31a0 && cp <= 0x31ff) || // Bopomofo Extended / CJK Strokes / Katakana Phonetic Extensions\n\t\t(cp >= 0x3200 && cp <= 0x4dbf) || // Enclosed CJK / CJK Compatibility / Ideographs Ext A\n\t\t(cp >= 0x4e00 && cp <= 0x9fff) || // CJK Unified Ideographs (fixture)\n\t\t(cp >= 0xf900 && cp <= 0xfaff) || // CJK Compatibility Ideographs\n\t\t(cp >= 0xfe10 && cp <= 0xfe1f) || // Vertical Forms\n\t\t(cp >= 0xfe30 && cp <= 0xfe4f) || // CJK Compatibility Forms\n\t\t// Halfwidth and Fullwidth Forms, minus U+FFA0..U+FFDF (halfwidth Hangul jamo),\n\t\t// which follows the Hangul rule above. Fullwidth Latin and halfwidth Katakana\n\t\t// are both fixture-backed.\n\t\t(cp >= 0xff00 && cp <= 0xff9f) ||\n\t\t(cp >= 0xffe0 && cp <= 0xffef) ||\n\t\t(cp >= 0x1b000 && cp <= 0x1b16f) || // Kana Supplement / Kana Extended-A / Small Kana Extension\n\t\t(cp >= 0x20000 && cp <= 0x2fffd) || // CJK Ideographs Extension B..F + Compatibility Supplement (fixture)\n\t\t(cp >= 0x30000 && cp <= 0x323af) // CJK Ideographs Extension G, H, I (Plane 3)\n\t)\n}\n\n/**\n * Tokenize one paragraph at a given `fontScalePct`. Words can span run boundaries\n * (a break is only allowed at whitespace, or either side of a per-character\n * breaking code point — see `isCjkBreakCharacter`). Returns `null` if any run's\n * face has no 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 (isCjkBreakCharacter(ch)) {\n\t\t\t\t\tflushWord()\n\t\t\t\t\ttokens.push({ kind: 'word', w, charWidths: [w] })\n\t\t\t\t\tcontinue\n\t\t\t\t}\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 { collectUncoveredCodepoints, 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: the arrays are caller-owned, so they cannot be shared. */\nconst unmeasurable = (): TextMeasurement => ({\n\theightIn: 0,\n\tlineCount: 0,\n\twidestLineIn: 0,\n\tmeasurable: false,\n\tapproximatedFaces: [],\n\tuncoveredCodepoints: [],\n\tfitsBox: () => false,\n\tshrinkScaleFor: () => 100,\n})\n\n/** Flatten a face → uncovered-code-point map into one sorted, deduplicated list. */\nfunction flattenCodepoints(byFace: Map<string, Set<number>>): number[] {\n\tconst all = new Set<number>()\n\tfor (const cps of byFace.values()) for (const cp of cps) all.add(cp)\n\treturn [...all].sort((a, b) => a - b)\n}\n\n/**\n * Render uncovered code points for a warning as `U+XXXX`, capped so one bad run cannot\n * flood the console with a whole unsupported script.\n */\nfunction formatCodepoints(cps: Set<number>): string {\n\tconst all = [...cps].sort((a, b) => a - b)\n\tconst shown = all.slice(0, 8).map((cp) => `U+${cp.toString(16).toUpperCase().padStart(4, '0')}`)\n\treturn all.length > shown.length ? `${shown.join(' ')} +${all.length - shown.length} more` : shown.join(' ')\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`. Code points a *registered* face has no glyph for are reported\n * in `uncoveredCodepoints`, and are the one case where the height may come back short\n * rather than tall — there is no font fallback here, only the font's `.notdef` advance.\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// Coverage is a property of the runs, not of the layout, so it is audited up front —\n\t// which also keeps it out of the resolver that `shrinkScaleFor()` re-enters.\n\tconst uncoveredByFace = new Map<string, Set<number>>()\n\tcollectUncoveredCodepoints(paragraphs, registry, uncoveredByFace)\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\tuncoveredCodepoints: flattenCodepoints(uncoveredByFace),\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), and once if one held code points its registered\n * face has no glyph for, so neither kind of overflow is 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\tconst uncoveredByFace = new Map<string, Set<number>>()\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/** Audit every set of runs the pass is about to measure — see the warning below. */\n\tconst auditCoverage = (paragraphs: FitParagraph[]): void =>\n\t\tcollectUncoveredCodepoints(paragraphs, registry, uncoveredByFace)\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\tauditCoverage(paragraphs)\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\tauditCoverage(paragraphs)\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 (uncoveredByFace.size > 0) {\n\t\tconst perFace = [...uncoveredByFace].map(([face, cps]) => `${face} → ${formatCodepoints(cps)}`).join('; ')\n\t\twarn(\n\t\t\t'measure/uncovered-codepoints',\n\t\t\t`Measured fit charged the .notdef advance for code point(s) the registered face does not cover (${perFace}) — ` +\n\t\t\t\t'PowerPoint renders those from a substituted font, so the measured width can be wrong in EITHER direction. ' +\n\t\t\t\t'Too narrow drops a line and the text overflows the baked size, the one case measured fit does not err safe. ' +\n\t\t\t\t'Register a face that covers them, or set an explicit fontFace on those runs.'\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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"}
|