@beyondwork/docx-react-component 1.0.128 → 1.0.130

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/dist/api/public-types.cjs +809 -78
  2. package/dist/api/public-types.d.cts +2 -2
  3. package/dist/api/public-types.d.ts +2 -2
  4. package/dist/api/public-types.js +4 -4
  5. package/dist/api/v3.cjs +2059 -402
  6. package/dist/api/v3.d.cts +3 -3
  7. package/dist/api/v3.d.ts +3 -3
  8. package/dist/api/v3.js +13 -13
  9. package/dist/{canonical-document-CXCFCbAz.d.cts → canonical-document-BMtONpgf.d.cts} +6 -0
  10. package/dist/{canonical-document-CXCFCbAz.d.ts → canonical-document-BMtONpgf.d.ts} +6 -0
  11. package/dist/{chunk-MWSBGJQO.js → chunk-35RHOE6I.js} +105 -4
  12. package/dist/{chunk-2QL5DAKF.js → chunk-3YCQM2RV.js} +6 -6
  13. package/dist/{chunk-ESJ2MES5.js → chunk-4YCWECLZ.js} +1 -1
  14. package/dist/{chunk-4EENH4FG.js → chunk-6TBLDBCL.js} +1 -1
  15. package/dist/{chunk-XRACP43Q.js → chunk-7G5GR3VV.js} +469 -32
  16. package/dist/{chunk-CXSYRB37.js → chunk-A3GSNB4G.js} +183 -55
  17. package/dist/{chunk-5DGKFNQT.js → chunk-A66ZVUAT.js} +150 -1
  18. package/dist/{chunk-YIYM4ZAP.js → chunk-CI2TD3T4.js} +1 -1
  19. package/dist/{chunk-TQDQU2E3.js → chunk-DGA7M77X.js} +2 -2
  20. package/dist/{chunk-EB6M3GE6.js → chunk-FM4K4XFJ.js} +100 -97
  21. package/dist/{chunk-D5HYZQTG.js → chunk-HYHCRMR7.js} +1 -1
  22. package/dist/{chunk-6F5QW44A.js → chunk-KNHMXKC6.js} +2 -2
  23. package/dist/{chunk-4YJVRIUB.js → chunk-M7YRJX6V.js} +61 -29
  24. package/dist/{chunk-KFCQYZXR.js → chunk-OVLZQ6FZ.js} +61 -0
  25. package/dist/{chunk-BYSRJ4FE.js → chunk-PHMWH23E.js} +1 -1
  26. package/dist/{chunk-ZDOAUP3V.js → chunk-Q7Y57KOK.js} +2 -2
  27. package/dist/{chunk-LZVBNDGU.js → chunk-QXKQPUOM.js} +3 -3
  28. package/dist/{chunk-CX42VC67.js → chunk-SYQWQ6FE.js} +1 -1
  29. package/dist/{chunk-KV435YXO.js → chunk-T5YYFDZB.js} +1 -1
  30. package/dist/{chunk-YHZHPXDB.js → chunk-THVM6EP5.js} +419 -24
  31. package/dist/{chunk-V6XVZFFH.js → chunk-VRKK2CSZ.js} +111 -90
  32. package/dist/{chunk-OL2UEHRP.js → chunk-WUDSNHWF.js} +1 -1
  33. package/dist/{chunk-LCYYR57Q.js → chunk-WZDKNF37.js} +666 -107
  34. package/dist/{chunk-6EROGFUF.js → chunk-YLL7MF5C.js} +444 -131
  35. package/dist/{chunk-YD2JE54B.js → chunk-ZVC23LKV.js} +1 -1
  36. package/dist/compare.cjs +100 -97
  37. package/dist/compare.d.cts +1 -1
  38. package/dist/compare.d.ts +1 -1
  39. package/dist/compare.js +3 -3
  40. package/dist/core/commands/formatting-commands.d.cts +2 -2
  41. package/dist/core/commands/formatting-commands.d.ts +2 -2
  42. package/dist/core/commands/image-commands.cjs +182 -54
  43. package/dist/core/commands/image-commands.d.cts +2 -2
  44. package/dist/core/commands/image-commands.d.ts +2 -2
  45. package/dist/core/commands/image-commands.js +5 -5
  46. package/dist/core/commands/section-layout-commands.d.cts +2 -2
  47. package/dist/core/commands/section-layout-commands.d.ts +2 -2
  48. package/dist/core/commands/style-commands.d.cts +2 -2
  49. package/dist/core/commands/style-commands.d.ts +2 -2
  50. package/dist/core/commands/table-structure-commands.cjs +182 -54
  51. package/dist/core/commands/table-structure-commands.d.cts +2 -2
  52. package/dist/core/commands/table-structure-commands.d.ts +2 -2
  53. package/dist/core/commands/table-structure-commands.js +4 -4
  54. package/dist/core/commands/text-commands.cjs +182 -54
  55. package/dist/core/commands/text-commands.d.cts +2 -2
  56. package/dist/core/commands/text-commands.d.ts +2 -2
  57. package/dist/core/commands/text-commands.js +5 -5
  58. package/dist/core/selection/mapping.d.cts +2 -2
  59. package/dist/core/selection/mapping.d.ts +2 -2
  60. package/dist/core/state/editor-state.d.cts +2 -2
  61. package/dist/core/state/editor-state.d.ts +2 -2
  62. package/dist/index.cjs +2765 -557
  63. package/dist/index.d.cts +5 -5
  64. package/dist/index.d.ts +5 -5
  65. package/dist/index.js +52 -28
  66. package/dist/io/docx-session.cjs +267 -211
  67. package/dist/io/docx-session.d.cts +4 -4
  68. package/dist/io/docx-session.d.ts +4 -4
  69. package/dist/io/docx-session.js +6 -6
  70. package/dist/legal.cjs +9 -20
  71. package/dist/legal.d.cts +1 -1
  72. package/dist/legal.d.ts +1 -1
  73. package/dist/legal.js +3 -3
  74. package/dist/{loader-19ct2Be0.d.ts → loader-B-aL5HGD.d.ts} +3 -3
  75. package/dist/{loader-CoXQ2wGd.d.cts → loader-DiY_ZgKl.d.cts} +3 -3
  76. package/dist/{measurement-backend-canvas-Q3MJMEYX.js → measurement-backend-canvas-F7ZYDACK.js} +1 -1
  77. package/dist/{public-types-B-CskQen.d.cts → public-types-DyqnxxO9.d.ts} +252 -2
  78. package/dist/{public-types-7KZsNGE2.d.ts → public-types-gvubspUI.d.cts} +252 -2
  79. package/dist/public-types.cjs +809 -78
  80. package/dist/public-types.d.cts +2 -2
  81. package/dist/public-types.d.ts +2 -2
  82. package/dist/public-types.js +4 -4
  83. package/dist/runtime/collab.d.cts +3 -3
  84. package/dist/runtime/collab.d.ts +3 -3
  85. package/dist/runtime/document-runtime.cjs +1887 -313
  86. package/dist/runtime/document-runtime.d.cts +2 -2
  87. package/dist/runtime/document-runtime.d.ts +2 -2
  88. package/dist/runtime/document-runtime.js +17 -17
  89. package/dist/{session-B5015J4v.d.cts → session-BUN6B-Vj.d.cts} +3 -3
  90. package/dist/{session-C2i8-d6v.d.ts → session-CDB0hohT.d.ts} +3 -3
  91. package/dist/session.cjs +267 -211
  92. package/dist/session.d.cts +5 -5
  93. package/dist/session.d.ts +5 -5
  94. package/dist/session.js +7 -7
  95. package/dist/tailwind.cjs +809 -78
  96. package/dist/tailwind.d.cts +2 -2
  97. package/dist/tailwind.d.ts +2 -2
  98. package/dist/tailwind.js +8 -8
  99. package/dist/{types-DNhN0WeN.d.cts → types-C4bz3kDU.d.cts} +2 -2
  100. package/dist/{types-yvrQuGX9.d.ts → types-VWH6CRvG.d.ts} +2 -2
  101. package/dist/ui-tailwind/editor-surface/search-plugin.d.cts +3 -3
  102. package/dist/ui-tailwind/editor-surface/search-plugin.d.ts +3 -3
  103. package/dist/ui-tailwind/editor-surface/search-plugin.js +5 -5
  104. package/dist/ui-tailwind.cjs +809 -78
  105. package/dist/ui-tailwind.d.cts +3 -3
  106. package/dist/ui-tailwind.d.ts +3 -3
  107. package/dist/ui-tailwind.js +8 -8
  108. package/package.json +1 -1
package/dist/tailwind.cjs CHANGED
@@ -31,6 +31,43 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
31
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
32
 
33
33
  // src/runtime/layout/resolved-formatting-state.ts
34
+ function createLayoutReadyFormattingSnapshot(formatting, runs = /* @__PURE__ */ new Map()) {
35
+ const snapshot = {
36
+ version: 1,
37
+ paragraph: {
38
+ spacingBefore: formatting.spacingBefore,
39
+ spacingAfter: formatting.spacingAfter,
40
+ lineHeight: formatting.lineHeight,
41
+ lineRule: formatting.lineRule,
42
+ indentLeft: formatting.indentLeft,
43
+ indentRight: formatting.indentRight,
44
+ firstLineIndent: formatting.firstLineIndent,
45
+ hangingIndent: formatting.hangingIndent,
46
+ fontSizeHalfPoints: formatting.fontSizeHalfPoints,
47
+ averageCharWidthTwips: formatting.averageCharWidthTwips,
48
+ tabStops: formatting.tabStops.map((tab) => ({ ...tab })),
49
+ defaultTabInterval: formatting.defaultTabInterval,
50
+ keepNext: formatting.keepNext,
51
+ keepLines: formatting.keepLines,
52
+ pageBreakBefore: formatting.pageBreakBefore,
53
+ widowControl: formatting.widowControl,
54
+ contextualSpacing: formatting.contextualSpacing,
55
+ ...formatting.numberingMarkerBox ? { numberingMarkerBox: { ...formatting.numberingMarkerBox } } : {}
56
+ },
57
+ runs: Array.from(runs.entries()).map(([runId, run]) => ({
58
+ runId,
59
+ ...run.fontFamily ? { fontFamily: run.fontFamily } : {},
60
+ ...typeof run.fontSizeHalfPoints === "number" ? { fontSizeHalfPoints: run.fontSizeHalfPoints } : {},
61
+ bold: Boolean(run.bold),
62
+ italic: Boolean(run.italic),
63
+ verticalAlign: run.verticalAlign ?? "baseline"
64
+ })).sort((a, b) => a.runId.localeCompare(b.runId))
65
+ };
66
+ return {
67
+ ...snapshot,
68
+ hash: hashStable(snapshot)
69
+ };
70
+ }
34
71
  function resolveBlockFormatting(block, defaultTabInterval = 720, themeFonts) {
35
72
  if (block.kind !== "paragraph") {
36
73
  return null;
@@ -273,6 +310,29 @@ function buildRunFormattingMap(block) {
273
310
  }
274
311
  return runs;
275
312
  }
313
+ function hashStable(value) {
314
+ return fnv1a(stableStringify(value)).toString(36);
315
+ }
316
+ function stableStringify(value) {
317
+ if (value === null || typeof value !== "object") return JSON.stringify(value);
318
+ if (Array.isArray(value)) {
319
+ return `[${value.map((item) => stableStringify(item)).join(",")}]`;
320
+ }
321
+ if (value instanceof Map) {
322
+ return stableStringify(Array.from(value.entries()));
323
+ }
324
+ const object = value;
325
+ const keys = Object.keys(object).filter((key) => object[key] !== void 0 && typeof object[key] !== "function").sort();
326
+ return `{${keys.map((key) => `${JSON.stringify(key)}:${stableStringify(object[key])}`).join(",")}}`;
327
+ }
328
+ function fnv1a(input) {
329
+ let hash = 2166136261;
330
+ for (let i = 0; i < input.length; i += 1) {
331
+ hash ^= input.charCodeAt(i);
332
+ hash = Math.imul(hash, 16777619);
333
+ }
334
+ return hash >>> 0;
335
+ }
276
336
  var FONT_AVG_CHAR_WIDTH, DEFAULT_FONT_AVG_CHAR_WIDTH, DEFAULT_FONT_SIZE_HALF_POINTS, DEFAULT_LINE_HEIGHT_FACTOR, TWIPS_PER_POINT;
277
337
  var init_resolved_formatting_state = __esm({
278
338
  "src/runtime/layout/resolved-formatting-state.ts"() {
@@ -7348,6 +7408,7 @@ function collectCanonicalLayoutInputs(doc) {
7348
7408
  const blockContexts = collectStoryBlockContexts(doc);
7349
7409
  return {
7350
7410
  stories: collectCanonicalStoryIdentities(doc),
7411
+ layoutIdentities: collectLayoutInputIdentities(doc, blockContexts),
7351
7412
  fieldRegions: collectCanonicalFieldRegionIdentities(doc),
7352
7413
  numbering: collectCanonicalNumberingLayoutInputs(doc, blockContexts),
7353
7414
  tables: collectCanonicalTableLayoutInputs(blockContexts),
@@ -7356,6 +7417,116 @@ function collectCanonicalLayoutInputs(doc) {
7356
7417
  editableTargets: collectEditableTargetRefs(doc)
7357
7418
  };
7358
7419
  }
7420
+ function collectLayoutInputIdentities(doc, contexts = collectStoryBlockContexts(doc)) {
7421
+ const identities = [];
7422
+ const editableTargets = collectEditableTargetRefs(doc);
7423
+ const editableByStoryBlock = new Map(
7424
+ editableTargets.map((target) => [`${target.storyKey}:${target.blockPath}`, target])
7425
+ );
7426
+ for (const context of contexts) {
7427
+ walkBlocks(context.blocks, context.storyKey, context.basePath, {
7428
+ paragraph(paragraph, blockPath) {
7429
+ const styleNumbering = paragraph.numbering === void 0 && paragraph.styleId !== void 0 ? resolveParagraphStyleNumbering(doc, paragraph.styleId) : void 0;
7430
+ const numbering = paragraph.numbering ?? styleNumbering;
7431
+ const editableTargetRef = editableByStoryBlock.get(`${context.storyKey}:${blockPath}`);
7432
+ identities.push(
7433
+ createLayoutInputIdentity({
7434
+ storyKey: context.storyKey,
7435
+ blockPath,
7436
+ block: paragraph,
7437
+ ...editableTargetRef !== void 0 ? { editableTargetRef } : {},
7438
+ ...numbering !== void 0 ? {
7439
+ list: {
7440
+ numberingInstanceId: numbering.numberingInstanceId,
7441
+ level: numbering.level ?? 0,
7442
+ ...paragraph.numbering?.sourceRef !== void 0 ? { markerSourceRef: paragraph.numbering.sourceRef } : {}
7443
+ }
7444
+ } : {}
7445
+ })
7446
+ );
7447
+ },
7448
+ table(table, blockPath) {
7449
+ identities.push(
7450
+ createLayoutInputIdentity({
7451
+ storyKey: context.storyKey,
7452
+ blockPath,
7453
+ block: table,
7454
+ table: { tableBlockPath: blockPath }
7455
+ })
7456
+ );
7457
+ },
7458
+ inline(inline, blockPath, inlinePath) {
7459
+ const objectId = objectIdForInline(inline);
7460
+ if (!objectId) return;
7461
+ const sourceRef = sourceRefForInline(inline);
7462
+ identities.push({
7463
+ storyKey: context.storyKey,
7464
+ blockPath,
7465
+ blockId: `${context.storyKey}:${inlinePath}`,
7466
+ ...sourceRef !== void 0 ? { sourceRef } : {},
7467
+ object: {
7468
+ objectId,
7469
+ ...sourceRef !== void 0 ? { anchorSourceRef: sourceRef } : {}
7470
+ }
7471
+ });
7472
+ }
7473
+ });
7474
+ }
7475
+ return identities;
7476
+ }
7477
+ function createLayoutInputIdentity(input) {
7478
+ const sourceRef = sourceRefForBlock(input.block);
7479
+ const blockId = input.block.type === "paragraph" && input.block.wordExtensionIds?.paraId ? `para:${input.block.wordExtensionIds.paraId}` : sourceRef?.sourceId !== void 0 ? `source:${sourceRef.sourceId}` : `${input.storyKey}:${input.blockPath}`;
7480
+ return {
7481
+ storyKey: input.storyKey,
7482
+ blockPath: input.blockPath,
7483
+ blockId,
7484
+ ...sourceRef !== void 0 ? { sourceRef } : {},
7485
+ ...input.editableTargetRef !== void 0 ? { editableTargetRef: input.editableTargetRef } : {},
7486
+ ...input.table !== void 0 ? { table: input.table } : {},
7487
+ ...input.list !== void 0 ? { list: input.list } : {}
7488
+ };
7489
+ }
7490
+ function sourceRefForBlock(block) {
7491
+ return "sourceRef" in block ? block.sourceRef : void 0;
7492
+ }
7493
+ function sourceRefForInline(inline) {
7494
+ return "sourceRef" in inline ? inline.sourceRef : void 0;
7495
+ }
7496
+ function objectIdForInline(inline) {
7497
+ switch (inline.type) {
7498
+ case "image":
7499
+ return inline.mediaId;
7500
+ case "drawing_frame":
7501
+ return objectIdForDrawingContent(inline.content) ?? inline.sourceRef?.sourceId;
7502
+ case "shape":
7503
+ case "vml_shape":
7504
+ case "wordart":
7505
+ return inline.preserveOnlyObject?.sourceId ?? `raw:${sha256TextHex(inline.rawXml).slice(0, 16)}`;
7506
+ case "chart_preview":
7507
+ case "smartart_preview":
7508
+ return inline.previewMediaId ?? `raw:${sha256TextHex(inline.rawXml).slice(0, 16)}`;
7509
+ case "ole_embed":
7510
+ return inline.relationshipId ?? inline.id ?? inline.sourceRef?.sourceId;
7511
+ case "opaque_inline":
7512
+ return inline.fragmentId;
7513
+ default:
7514
+ return void 0;
7515
+ }
7516
+ }
7517
+ function objectIdForDrawingContent(content) {
7518
+ switch (content.type) {
7519
+ case "picture":
7520
+ return content.mediaId ?? content.packagePartName ?? content.blipRef;
7521
+ case "chart_preview":
7522
+ case "smartart_preview":
7523
+ return content.previewMediaId ?? `raw:${sha256TextHex(content.rawXml).slice(0, 16)}`;
7524
+ case "shape":
7525
+ return content.preserveOnlyObject?.sourceId ?? `raw:${sha256TextHex(content.rawXml).slice(0, 16)}`;
7526
+ case "opaque":
7527
+ return content.preserveOnlyObject?.sourceId ?? `raw:${sha256TextHex(content.rawXml).slice(0, 16)}`;
7528
+ }
7529
+ }
7359
7530
  function collectEditableTargetRefs(doc, cache) {
7360
7531
  const targets = [];
7361
7532
  for (const context of collectStoryBlockContexts(doc)) {
@@ -8925,6 +9096,16 @@ function collectCanonicalNumberingLayoutInputs(doc, contexts = collectStoryBlock
8925
9096
  const instance = doc.numbering.instances[numbering.numberingInstanceId];
8926
9097
  const abstractDefinition = instance?.abstractNumberingId === void 0 ? void 0 : doc.numbering.abstractDefinitions[instance.abstractNumberingId];
8927
9098
  inputs.push({
9099
+ identity: createLayoutInputIdentity({
9100
+ storyKey: context.storyKey,
9101
+ blockPath,
9102
+ block: paragraph,
9103
+ list: {
9104
+ numberingInstanceId: numbering.numberingInstanceId,
9105
+ level: numbering.level ?? 0,
9106
+ ...paragraph.numbering?.sourceRef !== void 0 ? { markerSourceRef: paragraph.numbering.sourceRef } : {}
9107
+ }
9108
+ }),
8928
9109
  numberingKey: `${context.storyKey}:${blockPath}:numbering`,
8929
9110
  storyKey: context.storyKey,
8930
9111
  blockPath,
@@ -9226,6 +9407,12 @@ function projectTableLayoutInput(table, storyKey, blockPath) {
9226
9407
  (row, rowIndex) => projectTableRowLayoutInput(row, tableKey, rowIndex)
9227
9408
  );
9228
9409
  return {
9410
+ identity: createLayoutInputIdentity({
9411
+ storyKey,
9412
+ blockPath,
9413
+ block: table,
9414
+ table: { tableBlockPath: blockPath }
9415
+ }),
9229
9416
  tableKey,
9230
9417
  storyKey,
9231
9418
  blockPath,
@@ -9313,6 +9500,16 @@ function projectDrawingFrameAnchor(node, storyKey, blockPath, inlinePath) {
9313
9500
  const objectKey = `${storyKey}:${inlinePath}`;
9314
9501
  const textBoxBody = projectTextBoxBodyLayoutInput(content, objectKey, sourceRef, `${inlinePath}/txbx`);
9315
9502
  return {
9503
+ identity: {
9504
+ storyKey,
9505
+ blockPath,
9506
+ blockId: objectKey,
9507
+ ...sourceRef !== void 0 ? { sourceRef } : {},
9508
+ object: {
9509
+ objectId: objectKey,
9510
+ ...sourceRef !== void 0 ? { anchorSourceRef: sourceRef } : {}
9511
+ }
9512
+ },
9316
9513
  objectKey,
9317
9514
  storyKey,
9318
9515
  blockPath,
@@ -9434,8 +9631,19 @@ function projectTextBoxRunLayoutInput(inline, paragraphKey, inlineIndex) {
9434
9631
  }
9435
9632
  function projectLegacyImageAnchor(doc, node, storyKey, blockPath, inlinePath) {
9436
9633
  const media = doc.media.items[node.mediaId];
9634
+ const objectKey = `${storyKey}:${inlinePath}`;
9437
9635
  return {
9438
- objectKey: `${storyKey}:${inlinePath}`,
9636
+ identity: {
9637
+ storyKey,
9638
+ blockPath,
9639
+ blockId: objectKey,
9640
+ ...node.sourceRef !== void 0 ? { sourceRef: node.sourceRef } : {},
9641
+ object: {
9642
+ objectId: objectKey,
9643
+ ...node.sourceRef !== void 0 ? { anchorSourceRef: node.sourceRef } : {}
9644
+ }
9645
+ },
9646
+ objectKey,
9439
9647
  storyKey,
9440
9648
  blockPath,
9441
9649
  inlinePath,
@@ -10572,12 +10780,13 @@ function getLevelStartAt(level, levelDefinitions) {
10572
10780
  return levelDefinitions.get(level)?.startAt ?? DEFAULT_NUMBERING_START_AT;
10573
10781
  }
10574
10782
  function getNumberingFormatPosture(format, value) {
10575
- if (!isSupportedNumberingFormat(format)) {
10783
+ const registryEntry = getNumberingFormatRegistryEntry(format);
10784
+ if (!registryEntry || registryEntry.renderSupport === "approximated") {
10576
10785
  return {
10577
10786
  status: "approximated",
10578
10787
  requestedFormat: format,
10579
10788
  renderedFormat: "decimal",
10580
- reason: "unsupported-numbering-format-decimal-fallback"
10789
+ reason: registryEntry?.fallbackReason ?? "unsupported-numbering-format-decimal-fallback"
10581
10790
  };
10582
10791
  }
10583
10792
  if (value !== void 0 && ((format === "upperRoman" || format === "lowerRoman") && (value <= 0 || value >= 4e3) || (format === "cardinalText" || format === "ordinalText") && (!Number.isInteger(value) || value < 1 || value > 999) || (format === "upperLetter" || format === "lowerLetter" || format === "chicago") && value < 1)) {
@@ -10608,56 +10817,148 @@ function renderLevelText(text, counters, levelDefinitions) {
10608
10817
  });
10609
10818
  return rendered.trim().length > 0 ? rendered : null;
10610
10819
  }
10611
- var SUPPORTED_NUMBERING_FORMATS = /* @__PURE__ */ new Set([
10612
- "decimal",
10613
- "decimalZero",
10614
- "upperLetter",
10615
- "lowerLetter",
10616
- "upperRoman",
10617
- "lowerRoman",
10618
- "hex",
10619
- "ordinal",
10620
- "cardinalText",
10621
- "ordinalText",
10622
- "chicago",
10623
- "bullet",
10624
- "none"
10625
- ]);
10626
10820
  function isSupportedNumberingFormat(format) {
10627
- return SUPPORTED_NUMBERING_FORMATS.has(format);
10821
+ return getNumberingFormatRegistryEntry(format)?.renderSupport === "supported";
10822
+ }
10823
+ function getNumberingFormatRegistryEntry(format) {
10824
+ return NUMBERING_FORMAT_REGISTRY.get(format);
10628
10825
  }
10629
10826
  function formatCounter(value, format) {
10630
- switch (format) {
10631
- case "decimal":
10632
- return String(value);
10633
- case "decimalZero":
10634
- return String(value).padStart(2, "0");
10635
- case "upperLetter":
10636
- return toAlphabetic2(value).toUpperCase();
10637
- case "lowerLetter":
10638
- return toAlphabetic2(value).toLowerCase();
10639
- case "upperRoman":
10640
- return toRoman2(value).toUpperCase();
10641
- case "lowerRoman":
10642
- return toRoman2(value).toLowerCase();
10643
- case "hex":
10644
- return value >= 0 ? value.toString(16).toUpperCase() : String(value);
10645
- case "ordinal":
10646
- return toOrdinal2(value);
10647
- case "cardinalText":
10648
- return toCardinalText2(value);
10649
- case "ordinalText":
10650
- return toOrdinalText2(value);
10651
- case "chicago":
10652
- return toChicago2(value);
10653
- case "bullet":
10654
- return "";
10655
- case "none":
10656
- return "";
10657
- default:
10658
- return String(value);
10659
- }
10827
+ return getNumberingFormatRegistryEntry(format)?.render(value) ?? String(value);
10660
10828
  }
10829
+ var exactNumberingFormatEntries = [
10830
+ {
10831
+ format: "decimal",
10832
+ renderSupport: "supported",
10833
+ renderedFormat: "decimal",
10834
+ supportsMutation: true,
10835
+ render: (value) => String(value)
10836
+ },
10837
+ {
10838
+ format: "decimalZero",
10839
+ renderSupport: "supported",
10840
+ renderedFormat: "decimalZero",
10841
+ supportsMutation: true,
10842
+ render: (value) => String(value).padStart(2, "0")
10843
+ },
10844
+ {
10845
+ format: "upperLetter",
10846
+ renderSupport: "supported",
10847
+ renderedFormat: "upperLetter",
10848
+ supportsMutation: true,
10849
+ render: (value) => toAlphabetic2(value).toUpperCase()
10850
+ },
10851
+ {
10852
+ format: "lowerLetter",
10853
+ renderSupport: "supported",
10854
+ renderedFormat: "lowerLetter",
10855
+ supportsMutation: true,
10856
+ render: (value) => toAlphabetic2(value).toLowerCase()
10857
+ },
10858
+ {
10859
+ format: "upperRoman",
10860
+ renderSupport: "supported",
10861
+ renderedFormat: "upperRoman",
10862
+ supportsMutation: true,
10863
+ render: (value) => toRoman2(value).toUpperCase()
10864
+ },
10865
+ {
10866
+ format: "lowerRoman",
10867
+ renderSupport: "supported",
10868
+ renderedFormat: "lowerRoman",
10869
+ supportsMutation: true,
10870
+ render: (value) => toRoman2(value).toLowerCase()
10871
+ },
10872
+ {
10873
+ format: "hex",
10874
+ renderSupport: "supported",
10875
+ renderedFormat: "hex",
10876
+ supportsMutation: true,
10877
+ render: (value) => value >= 0 ? value.toString(16).toUpperCase() : String(value)
10878
+ },
10879
+ {
10880
+ format: "ordinal",
10881
+ renderSupport: "supported",
10882
+ renderedFormat: "ordinal",
10883
+ supportsMutation: true,
10884
+ render: toOrdinal2
10885
+ },
10886
+ {
10887
+ format: "cardinalText",
10888
+ renderSupport: "supported",
10889
+ renderedFormat: "cardinalText",
10890
+ supportsMutation: true,
10891
+ render: toCardinalText2
10892
+ },
10893
+ {
10894
+ format: "ordinalText",
10895
+ renderSupport: "supported",
10896
+ renderedFormat: "ordinalText",
10897
+ supportsMutation: true,
10898
+ render: toOrdinalText2
10899
+ },
10900
+ {
10901
+ format: "chicago",
10902
+ renderSupport: "supported",
10903
+ renderedFormat: "chicago",
10904
+ supportsMutation: true,
10905
+ render: toChicago2
10906
+ },
10907
+ {
10908
+ format: "bullet",
10909
+ renderSupport: "supported",
10910
+ renderedFormat: "bullet",
10911
+ supportsMutation: true,
10912
+ render: () => ""
10913
+ },
10914
+ {
10915
+ format: "none",
10916
+ renderSupport: "supported",
10917
+ renderedFormat: "none",
10918
+ supportsMutation: true,
10919
+ render: () => ""
10920
+ }
10921
+ ];
10922
+ var approximatedDecimalFormats = [
10923
+ "decimalEnclosedCircle",
10924
+ "decimalEnclosedFullstop",
10925
+ "decimalEnclosedParen",
10926
+ "decimalFullWidth",
10927
+ "decimalHalfWidth",
10928
+ "aiueo",
10929
+ "iroha",
10930
+ "ganada",
10931
+ "chosung",
10932
+ "russianLower",
10933
+ "russianUpper",
10934
+ "hebrew1",
10935
+ "hebrew2",
10936
+ "arabicAlpha",
10937
+ "arabicAbjad",
10938
+ "thaiLetters",
10939
+ "thaiNumbers",
10940
+ "hindiLetters",
10941
+ "hindiNumbers",
10942
+ "ideographDigital",
10943
+ "ideographTraditional",
10944
+ "chineseCounting",
10945
+ "japaneseCounting",
10946
+ "japaneseLegal"
10947
+ ];
10948
+ var approximatedNumberingFormatEntries = approximatedDecimalFormats.map((format) => ({
10949
+ format,
10950
+ renderSupport: "approximated",
10951
+ renderedFormat: "decimal",
10952
+ supportsMutation: false,
10953
+ fallbackReason: "unsupported-numbering-format-decimal-fallback",
10954
+ render: (value) => String(value)
10955
+ }));
10956
+ var NUMBERING_FORMAT_REGISTRY = new Map(
10957
+ [...exactNumberingFormatEntries, ...approximatedNumberingFormatEntries].map((entry) => [
10958
+ entry.format,
10959
+ entry
10960
+ ])
10961
+ );
10661
10962
  function toOrdinal2(value) {
10662
10963
  if (value <= 0) return String(value);
10663
10964
  const lastTwo = value % 100;
@@ -11311,12 +11612,36 @@ var DEFAULT_HYPERLINK_COLOR_HEX = "0563C1";
11311
11612
  function resolveHyperlinkRunFormatting(input, catalog, resolver) {
11312
11613
  const augmentedInput = input.characterStyleId === void 0 ? { ...input, characterStyleId: HYPERLINK_CHARACTER_STYLE_ID } : input;
11313
11614
  const cascade = resolveEffectiveRunFormatting(augmentedInput, catalog);
11314
- const resolvedColor = resolveHyperlinkColorHex(cascade, resolver);
11615
+ const resolvedColor = resolveHyperlinkColorHex(
11616
+ stripInheritedColorHexForImplicitHyperlink(input, catalog, cascade),
11617
+ resolver
11618
+ );
11315
11619
  if (resolvedColor && resolvedColor !== cascade.colorHex) {
11316
11620
  return { ...cascade, colorHex: resolvedColor };
11317
11621
  }
11318
11622
  return cascade;
11319
11623
  }
11624
+ function hasDirectNonAutoColor(input) {
11625
+ return Boolean(input.direct?.colorHex && input.direct.colorHex !== "auto");
11626
+ }
11627
+ function characterStyleDeclaresColorHex(styleId, catalog) {
11628
+ if (!catalog) return false;
11629
+ const chain = resolveCharacterStyleChain(styleId, catalog);
11630
+ return chain.some((chainStyleId) => {
11631
+ const colorHex = catalog.characters[chainStyleId]?.runProperties?.colorHex;
11632
+ return Boolean(colorHex && colorHex !== "auto");
11633
+ });
11634
+ }
11635
+ function stripInheritedColorHexForImplicitHyperlink(originalInput, catalog, cascade) {
11636
+ if (originalInput.characterStyleId !== void 0 || hasDirectNonAutoColor(originalInput) || !cascade.colorHex || cascade.colorHex === "auto" || characterStyleDeclaresColorHex(HYPERLINK_CHARACTER_STYLE_ID, catalog)) {
11637
+ return cascade;
11638
+ }
11639
+ const inheritedCascade = resolveEffectiveRunFormatting(originalInput, catalog);
11640
+ if (inheritedCascade.colorHex !== cascade.colorHex) {
11641
+ return cascade;
11642
+ }
11643
+ return { ...cascade, colorHex: void 0 };
11644
+ }
11320
11645
  function resolveHyperlinkColorHex(cascade, resolver) {
11321
11646
  if (cascade.colorHex && cascade.colorHex !== "auto") {
11322
11647
  return cascade.colorHex;
@@ -11548,7 +11873,7 @@ function buildEffectiveLayoutFormatting(input) {
11548
11873
  };
11549
11874
  }
11550
11875
  function createStructuralHash(value) {
11551
- const stable = stableStringify(value);
11876
+ const stable = stableStringify2(value);
11552
11877
  let hash = 2166136261;
11553
11878
  for (let i = 0; i < stable.length; i += 1) {
11554
11879
  hash ^= stable.charCodeAt(i);
@@ -11556,16 +11881,16 @@ function createStructuralHash(value) {
11556
11881
  }
11557
11882
  return `fnv1a32:${(hash >>> 0).toString(16).padStart(8, "0")}`;
11558
11883
  }
11559
- function stableStringify(value) {
11884
+ function stableStringify2(value) {
11560
11885
  if (value === null || typeof value !== "object") {
11561
11886
  return JSON.stringify(value);
11562
11887
  }
11563
11888
  if (Array.isArray(value)) {
11564
- return `[${value.map((entry) => stableStringify(entry)).join(",")}]`;
11889
+ return `[${value.map((entry) => stableStringify2(entry)).join(",")}]`;
11565
11890
  }
11566
11891
  const record = value;
11567
11892
  const keys = Object.keys(record).filter((key) => record[key] !== void 0).sort();
11568
- return `{${keys.map((key) => `${JSON.stringify(key)}:${stableStringify(record[key])}`).join(",")}}`;
11893
+ return `{${keys.map((key) => `${JSON.stringify(key)}:${stableStringify2(record[key])}`).join(",")}}`;
11569
11894
  }
11570
11895
 
11571
11896
  // src/runtime/formatting/formatting-context.ts
@@ -12074,6 +12399,7 @@ function createEditorSurfaceSnapshot(document2, _selection, activeStory = { kind
12074
12399
  ...options.authorColorPalette ? { authorColorPalette: options.authorColorPalette } : {}
12075
12400
  });
12076
12401
  const editableTargetsByBlockPath = options.editableTargetsByBlockPath ?? indexEditableTargetsByBlockPath(document2);
12402
+ const layoutIdentitiesByBlockPath = options.layoutIdentitiesByBlockPath;
12077
12403
  const activeStoryBlockPathBase = getActiveStoryBlockPathBase(document2, activeStory);
12078
12404
  chartModelStore.beginBuildPass(document2);
12079
12405
  const unsupportedNumberingFormatsSeen = options.emitFormattingTelemetry ? /* @__PURE__ */ new Set() : null;
@@ -12097,6 +12423,7 @@ function createEditorSurfaceSnapshot(document2, _selection, activeStory = { kind
12097
12423
  activeStory.kind !== "main",
12098
12424
  !isInViewport,
12099
12425
  editableTargetsByBlockPath,
12426
+ layoutIdentitiesByBlockPath,
12100
12427
  `${activeStoryBlockPathBase}/block[${index}]`
12101
12428
  );
12102
12429
  if (isInViewport) {
@@ -12163,7 +12490,7 @@ function isIndexInAnyRange(index, ranges) {
12163
12490
  }
12164
12491
  return false;
12165
12492
  }
12166
- function createSurfaceBlock(block, document2, cursor, counters, formattingContext, promoteSecondaryStoryTextBoxes, cullBuild = false, editableTargetsByBlockPath = EMPTY_EDITABLE_TARGETS_BY_BLOCK_PATH, blockPath) {
12493
+ function createSurfaceBlock(block, document2, cursor, counters, formattingContext, promoteSecondaryStoryTextBoxes, cullBuild = false, editableTargetsByBlockPath = EMPTY_EDITABLE_TARGETS_BY_BLOCK_PATH, layoutIdentitiesByBlockPath, blockPath) {
12167
12494
  if (block.type === "opaque_block") {
12168
12495
  const fragment = getOpaqueFragment(document2.preservation, block.fragmentId);
12169
12496
  const descriptor = fragment ? describeOpaqueFragment(fragment) : null;
@@ -12200,6 +12527,7 @@ function createSurfaceBlock(block, document2, cursor, counters, formattingContex
12200
12527
  promoteSecondaryStoryTextBoxes,
12201
12528
  cullBuild,
12202
12529
  editableTargetsByBlockPath,
12530
+ layoutIdentitiesByBlockPath,
12203
12531
  blockPath
12204
12532
  );
12205
12533
  }
@@ -12240,6 +12568,7 @@ function createSurfaceBlock(block, document2, cursor, counters, formattingContex
12240
12568
  promoteSecondaryStoryTextBoxes,
12241
12569
  cullBuild,
12242
12570
  editableTargetsByBlockPath,
12571
+ layoutIdentitiesByBlockPath,
12243
12572
  blockPath
12244
12573
  );
12245
12574
  }
@@ -12322,10 +12651,11 @@ function createSurfaceBlock(block, document2, cursor, counters, formattingContex
12322
12651
  cullBuild,
12323
12652
  editableTargetsByBlockPath,
12324
12653
  blockPath,
12325
- blockPath !== void 0 ? editableTargetsByBlockPath.get(blockPath) : void 0
12654
+ blockPath !== void 0 ? editableTargetsByBlockPath.get(blockPath) : void 0,
12655
+ blockPath !== void 0 ? layoutIdentitiesByBlockPath?.get(blockPath) : void 0
12326
12656
  );
12327
12657
  }
12328
- function createTableBlock(tableIndex, table, document2, cursor, counters, formattingContext, promoteSecondaryStoryTextBoxes, cullBuild = false, editableTargetsByBlockPath = EMPTY_EDITABLE_TARGETS_BY_BLOCK_PATH, tablePath) {
12658
+ function createTableBlock(tableIndex, table, document2, cursor, counters, formattingContext, promoteSecondaryStoryTextBoxes, cullBuild = false, editableTargetsByBlockPath = EMPTY_EDITABLE_TARGETS_BY_BLOCK_PATH, layoutIdentitiesByBlockPath, tablePath) {
12329
12659
  const lockedFragmentIds = [];
12330
12660
  let innerCursor = cursor;
12331
12661
  if (cullBuild) {
@@ -12342,6 +12672,7 @@ function createTableBlock(tableIndex, table, document2, cursor, counters, format
12342
12672
  promoteSecondaryStoryTextBoxes,
12343
12673
  true,
12344
12674
  editableTargetsByBlockPath,
12675
+ layoutIdentitiesByBlockPath,
12345
12676
  tablePath !== void 0 ? `${tablePath}/row[${rowIndex}]/cell[${cellIndex}]/block[${childIndex}]` : void 0
12346
12677
  );
12347
12678
  lockedFragmentIds.push(...result.lockedFragmentIds);
@@ -12357,6 +12688,7 @@ function createTableBlock(tableIndex, table, document2, cursor, counters, format
12357
12688
  to: innerCursor,
12358
12689
  styleId: table.styleId,
12359
12690
  ...table.sourceRef !== void 0 ? { sourceRef: table.sourceRef } : {},
12691
+ ...tablePath !== void 0 && layoutIdentitiesByBlockPath?.get(tablePath) !== void 0 ? { layoutIdentity: layoutIdentitiesByBlockPath.get(tablePath) } : {},
12360
12692
  gridColumns: table.gridColumns,
12361
12693
  rows: []
12362
12694
  },
@@ -12394,6 +12726,7 @@ function createTableBlock(tableIndex, table, document2, cursor, counters, format
12394
12726
  promoteSecondaryStoryTextBoxes,
12395
12727
  cullBuild,
12396
12728
  editableTargetsByBlockPath,
12729
+ layoutIdentitiesByBlockPath,
12397
12730
  tablePath !== void 0 ? `${tablePath}/row[${rowIndex}]/cell[${cellIndex}]/block[${childIndex}]` : void 0
12398
12731
  );
12399
12732
  cellContent.push(result.block);
@@ -12482,6 +12815,7 @@ function createTableBlock(tableIndex, table, document2, cursor, counters, format
12482
12815
  to: innerCursor,
12483
12816
  styleId: table.styleId,
12484
12817
  ...table.sourceRef !== void 0 ? { sourceRef: table.sourceRef } : {},
12818
+ ...tablePath !== void 0 && layoutIdentitiesByBlockPath?.get(tablePath) !== void 0 ? { layoutIdentity: layoutIdentitiesByBlockPath.get(tablePath) } : {},
12485
12819
  gridColumns: table.gridColumns,
12486
12820
  ...gridColumnsRelative ? { gridColumnsRelative } : {},
12487
12821
  ...resolvedTable.table?.alignment ? { alignment: resolvedTable.table.alignment } : {},
@@ -12669,7 +13003,7 @@ function resolveCellBorderStyles(borders, tableBorders, position) {
12669
13003
  if (left) result.borderLeft = left;
12670
13004
  return result;
12671
13005
  }
12672
- function createSdtBlock(sdtIndex, block, document2, cursor, counters, formattingContext, promoteSecondaryStoryTextBoxes, cullBuild = false, editableTargetsByBlockPath = EMPTY_EDITABLE_TARGETS_BY_BLOCK_PATH, sdtPath) {
13006
+ function createSdtBlock(sdtIndex, block, document2, cursor, counters, formattingContext, promoteSecondaryStoryTextBoxes, cullBuild = false, editableTargetsByBlockPath = EMPTY_EDITABLE_TARGETS_BY_BLOCK_PATH, layoutIdentitiesByBlockPath, sdtPath) {
12673
13007
  const children = [];
12674
13008
  const lockedFragmentIds = [];
12675
13009
  let innerCursor = cursor;
@@ -12686,6 +13020,7 @@ function createSdtBlock(sdtIndex, block, document2, cursor, counters, formatting
12686
13020
  promoteSecondaryStoryTextBoxes,
12687
13021
  cullBuild,
12688
13022
  editableTargetsByBlockPath,
13023
+ layoutIdentitiesByBlockPath,
12689
13024
  sdtPath !== void 0 ? `${sdtPath}/block[${childIndex}]` : void 0
12690
13025
  );
12691
13026
  children.push(result.block);
@@ -12728,7 +13063,7 @@ function getRecursableSdtBlockedReasonCode(block) {
12728
13063
  ].filter(Boolean).join(" ").toLowerCase();
12729
13064
  return searchText.includes("table of contents") || /\btoc\b/u.test(searchText) ? "workflow_preserve_only" : null;
12730
13065
  }
12731
- function createParagraphBlock(paragraphIndex, paragraph, document2, start, formattingContext, promoteSecondaryStoryTextBoxes, cullBuild = false, editableTargetsByBlockPath = EMPTY_EDITABLE_TARGETS_BY_BLOCK_PATH, blockPath, editableTarget) {
13066
+ function createParagraphBlock(paragraphIndex, paragraph, document2, start, formattingContext, promoteSecondaryStoryTextBoxes, cullBuild = false, editableTargetsByBlockPath = EMPTY_EDITABLE_TARGETS_BY_BLOCK_PATH, blockPath, editableTarget, layoutIdentity) {
12732
13067
  const themeResolver = formattingContext.theme;
12733
13068
  const effectiveNumbering = formattingContext.resolveEffectiveParagraphNumbering(paragraph);
12734
13069
  let resolvedNumbering = null;
@@ -12751,6 +13086,7 @@ function createParagraphBlock(paragraphIndex, paragraph, document2, start, forma
12751
13086
  from: start,
12752
13087
  to: start,
12753
13088
  ...editableTarget !== void 0 ? { editableTarget } : {},
13089
+ ...layoutIdentity !== void 0 ? { layoutIdentity } : {},
12754
13090
  ...paragraph.styleId ? { styleId: paragraph.styleId } : {},
12755
13091
  ...effectiveNumbering ? { numbering: effectiveNumbering } : {},
12756
13092
  ...resolvedNumbering ? {
@@ -16526,6 +16862,14 @@ function paginateSectionBlocksWithSplits(section, blocks, layout, footnotes, mea
16526
16862
  pushPage(block.from);
16527
16863
  continue;
16528
16864
  }
16865
+ if (isStandalonePageBreakParagraph(block)) {
16866
+ if (columnHeight > 0) {
16867
+ pushPage(nextBoundary);
16868
+ } else {
16869
+ pageStart = Math.max(pageStart, Math.min(nextBoundary, section.end));
16870
+ }
16871
+ break;
16872
+ }
16529
16873
  const effectiveNoteHeight = estimateFootnoteReservation(
16530
16874
  block,
16531
16875
  footnotes,
@@ -16700,6 +17044,21 @@ function hasPageBreak(block) {
16700
17044
  }
16701
17045
  return nestedBlocks(block).some(hasPageBreak);
16702
17046
  }
17047
+ function isStandalonePageBreakParagraph(block) {
17048
+ if (block.kind !== "paragraph") return false;
17049
+ let sawPageBreak = false;
17050
+ for (const segment of block.segments) {
17051
+ if (segment.kind === "opaque_inline" && segment.label === "Page break") {
17052
+ sawPageBreak = true;
17053
+ continue;
17054
+ }
17055
+ if (segment.kind === "text" && segment.text.trim().length === 0) {
17056
+ continue;
17057
+ }
17058
+ return false;
17059
+ }
17060
+ return sawPageBreak;
17061
+ }
16703
17062
  function nestedBlocks(block) {
16704
17063
  if (block.kind === "sdt_block") {
16705
17064
  return block.children;
@@ -18161,6 +18520,9 @@ function projectSurfaceBlocksToPageFragments(surface, pages, splits, columnByBlo
18161
18520
  for (let blockIndex = 0; blockIndex < surface.blocks.length; blockIndex += 1) {
18162
18521
  const block = surface.blocks[blockIndex];
18163
18522
  const blockPath = `main/block[${blockIndex}]`;
18523
+ if (isStandalonePageBreakParagraph2(block)) {
18524
+ continue;
18525
+ }
18164
18526
  if (block.kind === "table") {
18165
18527
  const tableSliceList = splits?.tablesByBlockId.get(block.blockId);
18166
18528
  if (tableSliceList && tableSliceList.length > 1) {
@@ -18246,6 +18608,23 @@ function projectSurfaceBlocksToPageFragments(surface, pages, splits, columnByBlo
18246
18608
  }
18247
18609
  return byPage;
18248
18610
  }
18611
+ function isStandalonePageBreakParagraph2(block) {
18612
+ if (block.kind !== "paragraph") {
18613
+ return false;
18614
+ }
18615
+ let sawPageBreak = false;
18616
+ for (const segment of block.segments) {
18617
+ if (segment.kind === "opaque_inline" && segment.label === "Page break") {
18618
+ sawPageBreak = true;
18619
+ continue;
18620
+ }
18621
+ if (segment.kind === "text" && segment.text.trim().length === 0) {
18622
+ continue;
18623
+ }
18624
+ return false;
18625
+ }
18626
+ return sawPageBreak;
18627
+ }
18249
18628
  function projectLineBoxesForPageFragments(pages, fragmentsByPageIndex, fragmentMeasurementsByPageIndex, surface) {
18250
18629
  const byPage = /* @__PURE__ */ new Map();
18251
18630
  const blocksById = surface ? new Map(surface.blocks.map((block) => [block.blockId, block])) : /* @__PURE__ */ new Map();
@@ -18758,13 +19137,11 @@ function buildBookmarkRanges(targets) {
18758
19137
  }
18759
19138
  var EMPTY_NUMBERING_INPUT_INDEX = {
18760
19139
  byNumberingKey: /* @__PURE__ */ new Map(),
18761
- byBlockPath: /* @__PURE__ */ new Map(),
18762
- byParagraphIndex: /* @__PURE__ */ new Map()
19140
+ byBlockPath: /* @__PURE__ */ new Map()
18763
19141
  };
18764
19142
  function buildNumberingInputIndex(numberingInputs) {
18765
19143
  const byNumberingKey = /* @__PURE__ */ new Map();
18766
19144
  const byBlockPath = /* @__PURE__ */ new Map();
18767
- const byParagraph = /* @__PURE__ */ new Map();
18768
19145
  for (const input of numberingInputs) {
18769
19146
  if (!byNumberingKey.has(input.numberingKey)) {
18770
19147
  byNumberingKey.set(input.numberingKey, input);
@@ -18772,11 +19149,8 @@ function buildNumberingInputIndex(numberingInputs) {
18772
19149
  if (!byBlockPath.has(input.blockPath)) {
18773
19150
  byBlockPath.set(input.blockPath, input);
18774
19151
  }
18775
- if (!byParagraph.has(input.paragraphIndex)) {
18776
- byParagraph.set(input.paragraphIndex, input);
18777
- }
18778
19152
  }
18779
- return { byNumberingKey, byBlockPath, byParagraphIndex: byParagraph };
19153
+ return { byNumberingKey, byBlockPath };
18780
19154
  }
18781
19155
  function collectBookmarkRangeLayoutFacts(fragmentId, blockPath, bookmarkRanges) {
18782
19156
  if (!blockPath || !bookmarkRanges || bookmarkRanges.length === 0) return [];
@@ -18896,8 +19270,7 @@ function collectNumberingLayoutFactsForBlock(block, blockPath, numberingIndex, n
18896
19270
  const canonical = lookupNumberingInput(
18897
19271
  numberingIndex,
18898
19272
  numberingKey,
18899
- context.path,
18900
- paragraphIndex
19273
+ context.path
18901
19274
  );
18902
19275
  const target = findNumberingTarget(numberingTargets, context.path);
18903
19276
  const numberingLayoutId = numberingKey ?? [
@@ -18937,7 +19310,7 @@ function findNumberingTarget(numberingTargets, blockPath) {
18937
19310
  if (blockPath === void 0) return void 0;
18938
19311
  return numberingTargets.find((target) => target.blockPath === blockPath);
18939
19312
  }
18940
- function lookupNumberingInput(numberingIndex, numberingKey, blockPath, paragraphIndex) {
19313
+ function lookupNumberingInput(numberingIndex, numberingKey, blockPath) {
18941
19314
  if (!numberingIndex) return void 0;
18942
19315
  if (numberingKey !== void 0) {
18943
19316
  const byKey = numberingIndex.byNumberingKey.get(numberingKey);
@@ -18947,7 +19320,7 @@ function lookupNumberingInput(numberingIndex, numberingKey, blockPath, paragraph
18947
19320
  const byPath = numberingIndex.byBlockPath.get(blockPath);
18948
19321
  if (byPath !== void 0) return byPath;
18949
19322
  }
18950
- return paragraphIndex !== void 0 ? numberingIndex.byParagraphIndex.get(paragraphIndex) : void 0;
19323
+ return void 0;
18951
19324
  }
18952
19325
  function collectNumberingUnavailableReasons(numbering, canonical) {
18953
19326
  const reasons = [];
@@ -19337,12 +19710,330 @@ function createEmpiricalProvider() {
19337
19710
  return createEmpiricalBackend();
19338
19711
  }
19339
19712
 
19713
+ // src/runtime/layout/persistent-layout-measurement-cache.ts
19714
+ init_resolved_formatting_state();
19715
+ var DEFAULT_MAX_ENTRIES = 1e4;
19716
+ var DEFAULT_MAX_ESTIMATED_BYTES = 50 * 1024 * 1024;
19717
+ function createPersistentLayoutMeasurementCache(options = {}) {
19718
+ const maxEntries = Math.max(1, options.maxEntries ?? DEFAULT_MAX_ENTRIES);
19719
+ const maxEstimatedBytes = Math.max(
19720
+ 1024,
19721
+ options.maxEstimatedBytes ?? DEFAULT_MAX_ESTIMATED_BYTES
19722
+ );
19723
+ const entries = /* @__PURE__ */ new Map();
19724
+ const counters = {
19725
+ hits: 0,
19726
+ misses: 0,
19727
+ sets: 0,
19728
+ evictions: 0,
19729
+ clears: 0,
19730
+ estimatedBytes: 0,
19731
+ invalidatedByReason: {}
19732
+ };
19733
+ function evictOldest() {
19734
+ const oldest = entries.keys().next();
19735
+ if (oldest.done) return;
19736
+ const entry = entries.get(oldest.value);
19737
+ if (entry) {
19738
+ counters.estimatedBytes -= entry.estimatedBytes;
19739
+ }
19740
+ entries.delete(oldest.value);
19741
+ counters.evictions += 1;
19742
+ }
19743
+ return {
19744
+ get(key) {
19745
+ const cacheKey = serializeCacheKey(key);
19746
+ const entry = entries.get(cacheKey);
19747
+ if (!entry) {
19748
+ counters.misses += 1;
19749
+ return void 0;
19750
+ }
19751
+ entries.delete(cacheKey);
19752
+ entries.set(cacheKey, entry);
19753
+ counters.hits += 1;
19754
+ return entry.value;
19755
+ },
19756
+ set(key, value) {
19757
+ const cacheKey = serializeCacheKey(key);
19758
+ const previous = entries.get(cacheKey);
19759
+ if (previous) {
19760
+ counters.estimatedBytes -= previous.estimatedBytes;
19761
+ entries.delete(cacheKey);
19762
+ }
19763
+ const estimatedBytes = estimateBytes(key, value);
19764
+ entries.set(cacheKey, { key, value, estimatedBytes });
19765
+ counters.estimatedBytes += estimatedBytes;
19766
+ counters.sets += 1;
19767
+ while (entries.size > maxEntries || counters.estimatedBytes > maxEstimatedBytes) {
19768
+ evictOldest();
19769
+ }
19770
+ },
19771
+ invalidate(reason, predicate) {
19772
+ if (!predicate) {
19773
+ const removed2 = entries.size;
19774
+ counters.estimatedBytes = 0;
19775
+ entries.clear();
19776
+ counters.invalidatedByReason[reason] = (counters.invalidatedByReason[reason] ?? 0) + removed2;
19777
+ return;
19778
+ }
19779
+ let removed = 0;
19780
+ for (const [cacheKey, entry] of entries) {
19781
+ if (!predicate(entry.key)) continue;
19782
+ counters.estimatedBytes -= entry.estimatedBytes;
19783
+ entries.delete(cacheKey);
19784
+ removed += 1;
19785
+ }
19786
+ counters.invalidatedByReason[reason] = (counters.invalidatedByReason[reason] ?? 0) + removed;
19787
+ },
19788
+ clear(reason) {
19789
+ const removed = entries.size;
19790
+ counters.estimatedBytes = 0;
19791
+ entries.clear();
19792
+ counters.clears += 1;
19793
+ counters.invalidatedByReason[reason] = (counters.invalidatedByReason[reason] ?? 0) + removed;
19794
+ },
19795
+ stats() {
19796
+ return {
19797
+ hits: counters.hits,
19798
+ misses: counters.misses,
19799
+ sets: counters.sets,
19800
+ evictions: counters.evictions,
19801
+ clears: counters.clears,
19802
+ size: entries.size,
19803
+ estimatedBytes: Math.max(0, counters.estimatedBytes),
19804
+ invalidatedByReason: { ...counters.invalidatedByReason }
19805
+ };
19806
+ }
19807
+ };
19808
+ }
19809
+ function createCachedLayoutMeasurementProvider(delegate, options = {}) {
19810
+ const cache = options.cache ?? createPersistentLayoutMeasurementCache(options);
19811
+ function emitCounter(type, key) {
19812
+ const telemetryBus = options.telemetryBus;
19813
+ if (!telemetryBus?.isEnabled("layout")) return;
19814
+ telemetryBus.emitLazy("layout", () => ({
19815
+ type,
19816
+ payload: key ? {
19817
+ measurementKind: key.measurementKind,
19818
+ blockId: key.blockId,
19819
+ backendVersion: key.backendVersion
19820
+ } : void 0
19821
+ }));
19822
+ }
19823
+ return {
19824
+ get fidelity() {
19825
+ return delegate.fidelity;
19826
+ },
19827
+ measurementCache: cache,
19828
+ measurementCacheStats() {
19829
+ return cache.stats();
19830
+ },
19831
+ whenReady() {
19832
+ return delegate.whenReady();
19833
+ },
19834
+ measureLineFragments(input) {
19835
+ const key = buildLineFragmentsKey(input, delegate, options);
19836
+ const cached = cache.get(key);
19837
+ if (cached) {
19838
+ emitCounter("pageRender.measurement.hit", key);
19839
+ return cloneMeasuredLineFragments(cached);
19840
+ }
19841
+ emitCounter("pageRender.measurement.miss", key);
19842
+ const measured = delegate.measureLineFragments(input);
19843
+ cache.set(key, cloneMeasuredLineFragments(measured));
19844
+ return measured;
19845
+ },
19846
+ measureInlineObject(input) {
19847
+ const key = buildInlineObjectKey(input, delegate, options);
19848
+ const cached = cache.get(key);
19849
+ if (cached) {
19850
+ emitCounter("pageRender.measurement.hit", key);
19851
+ return { ...cached };
19852
+ }
19853
+ emitCounter("pageRender.measurement.miss", key);
19854
+ const measured = delegate.measureInlineObject(input);
19855
+ cache.set(key, { ...measured });
19856
+ return measured;
19857
+ },
19858
+ measureTableBlock(input) {
19859
+ const key = buildTableBlockKey(input, delegate, options);
19860
+ const cached = cache.get(key);
19861
+ if (cached) {
19862
+ emitCounter("pageRender.measurement.hit", key);
19863
+ return cloneMeasuredTableBlock(cached);
19864
+ }
19865
+ emitCounter("pageRender.measurement.miss", key);
19866
+ const measured = delegate.measureTableBlock(input);
19867
+ cache.set(key, cloneMeasuredTableBlock(measured));
19868
+ return measured;
19869
+ },
19870
+ invalidateCache() {
19871
+ delegate.invalidateCache();
19872
+ cache.clear("provider.invalidateCache");
19873
+ emitCounter("pageRender.measurement.invalidated.provider.invalidateCache");
19874
+ }
19875
+ };
19876
+ }
19877
+ function isCachedLayoutMeasurementProvider(provider) {
19878
+ return typeof provider.measurementCacheStats === "function";
19879
+ }
19880
+ function buildLineFragmentsKey(input, delegate, options) {
19881
+ const block = input.block;
19882
+ const identity = measurementIdentityForBlock(block);
19883
+ return {
19884
+ measurementKind: "line-fragments",
19885
+ blockId: identity.blockId,
19886
+ blockPath: identity.blockPath,
19887
+ contentHash: hashStable2({
19888
+ kind: block.kind,
19889
+ identity: identity.identityHash,
19890
+ segments: block.segments,
19891
+ numbering: block.numbering,
19892
+ numberingPrefix: block.numberingPrefix,
19893
+ numberingSuffix: block.numberingSuffix,
19894
+ resolvedNumbering: block.resolvedNumbering
19895
+ }),
19896
+ formattingHash: createLayoutReadyFormattingSnapshot(
19897
+ input.formatting,
19898
+ input.runs
19899
+ ).hash,
19900
+ constraintsHash: hashStable2({ columnWidth: input.columnWidth }),
19901
+ sectionHash: resolveOptionValue(options.sectionHash, "section:provider-input"),
19902
+ fontEpoch: resolveOptionValue(options.fontEpoch, "font:default"),
19903
+ backendVersion: resolveOptionValue(options.backendVersion, delegate.fidelity),
19904
+ displayModeHash: resolveOptionValue(options.displayModeHash, "display:default")
19905
+ };
19906
+ }
19907
+ function buildInlineObjectKey(input, delegate, options) {
19908
+ return {
19909
+ measurementKind: "inline-object",
19910
+ blockId: "inline-object",
19911
+ blockPath: "inline-object",
19912
+ contentHash: hashStable2({ display: input.display }),
19913
+ formattingHash: "format:none",
19914
+ constraintsHash: hashStable2({
19915
+ widthTwips: input.widthTwips,
19916
+ heightTwips: input.heightTwips
19917
+ }),
19918
+ sectionHash: resolveOptionValue(options.sectionHash, "section:provider-input"),
19919
+ fontEpoch: resolveOptionValue(options.fontEpoch, "font:default"),
19920
+ backendVersion: resolveOptionValue(options.backendVersion, delegate.fidelity),
19921
+ displayModeHash: resolveOptionValue(options.displayModeHash, "display:default")
19922
+ };
19923
+ }
19924
+ function buildTableBlockKey(input, delegate, options) {
19925
+ const block = input.block;
19926
+ const identity = measurementIdentityForBlock(block);
19927
+ return {
19928
+ measurementKind: "table-block",
19929
+ blockId: identity.blockId,
19930
+ blockPath: identity.blockPath,
19931
+ contentHash: hashStable2({
19932
+ kind: block.kind,
19933
+ identity: identity.identityHash,
19934
+ rows: block.rows,
19935
+ gridColumns: block.gridColumns,
19936
+ gridColumnsRelative: block.gridColumnsRelative,
19937
+ tableResolved: block.tableResolved,
19938
+ tblLook: block.tblLook
19939
+ }),
19940
+ formattingHash: hashStable2({
19941
+ styleId: block.styleId,
19942
+ alignment: block.alignment
19943
+ }),
19944
+ constraintsHash: hashStable2({ columnWidth: input.columnWidth }),
19945
+ sectionHash: resolveOptionValue(options.sectionHash, "section:provider-input"),
19946
+ fontEpoch: resolveOptionValue(options.fontEpoch, "font:default"),
19947
+ backendVersion: resolveOptionValue(options.backendVersion, delegate.fidelity),
19948
+ displayModeHash: resolveOptionValue(options.displayModeHash, "display:default")
19949
+ };
19950
+ }
19951
+ function measurementIdentityForBlock(block) {
19952
+ const identity = block.layoutIdentity;
19953
+ if (!identity) {
19954
+ return {
19955
+ blockId: block.blockId,
19956
+ blockPath: blockPathForBlock(block),
19957
+ identityHash: "identity:legacy"
19958
+ };
19959
+ }
19960
+ return {
19961
+ blockId: identity.blockId,
19962
+ blockPath: identity.blockPath,
19963
+ identityHash: hashStable2({
19964
+ storyKey: identity.storyKey,
19965
+ blockId: identity.blockId,
19966
+ blockPath: identity.blockPath,
19967
+ sourceRef: identity.sourceRef,
19968
+ table: identity.table,
19969
+ list: identity.list,
19970
+ field: identity.field,
19971
+ object: identity.object
19972
+ })
19973
+ };
19974
+ }
19975
+ function blockPathForBlock(block) {
19976
+ return `${block.from}:${block.to}`;
19977
+ }
19978
+ function resolveOptionValue(option, fallback) {
19979
+ if (typeof option === "function") return option();
19980
+ return option ?? fallback;
19981
+ }
19982
+ function serializeCacheKey(key) {
19983
+ return stableStringify3(key);
19984
+ }
19985
+ function estimateBytes(key, value) {
19986
+ return stableStringify3(key).length + stableStringify3(value).length;
19987
+ }
19988
+ function cloneMeasuredLineFragments(value) {
19989
+ return {
19990
+ lineCount: value.lineCount,
19991
+ maxLineWidth: value.maxLineWidth,
19992
+ lineHeights: [...value.lineHeights]
19993
+ };
19994
+ }
19995
+ function cloneMeasuredTableBlock(value) {
19996
+ return {
19997
+ totalHeightTwips: value.totalHeightTwips,
19998
+ rowHeights: [...value.rowHeights]
19999
+ };
20000
+ }
20001
+ function hashStable2(value) {
20002
+ return fnv1a2(stableStringify3(value)).toString(36);
20003
+ }
20004
+ function stableStringify3(value) {
20005
+ if (value === null || typeof value !== "object") return JSON.stringify(value);
20006
+ if (Array.isArray(value)) {
20007
+ return `[${value.map((item) => stableStringify3(item)).join(",")}]`;
20008
+ }
20009
+ if (value instanceof Map) {
20010
+ return stableStringify3(Array.from(value.entries()));
20011
+ }
20012
+ const object = value;
20013
+ const keys = Object.keys(object).filter((key) => object[key] !== void 0 && typeof object[key] !== "function").sort();
20014
+ return `{${keys.map((key) => `${JSON.stringify(key)}:${stableStringify3(object[key])}`).join(",")}}`;
20015
+ }
20016
+ function fnv1a2(input) {
20017
+ let hash = 2166136261;
20018
+ for (let i = 0; i < input.length; i += 1) {
20019
+ hash ^= input.charCodeAt(i);
20020
+ hash = Math.imul(hash, 16777619);
20021
+ }
20022
+ return hash >>> 0;
20023
+ }
20024
+
19340
20025
  // src/runtime/layout/layout-engine-version.ts
19341
- var LAYOUT_ENGINE_VERSION = 88;
20026
+ var LAYOUT_ENGINE_VERSION = 93;
19342
20027
 
19343
20028
  // src/runtime/layout/layout-engine-instance.ts
19344
20029
  var FULL_VIEWPORT_WINDOW_KEY = "full";
19345
20030
  var DEFAULT_VIEWPORT_PAGE_WINDOW_BUFFER = 1;
20031
+ function indexLayoutIdentitiesByBlockPath(identities) {
20032
+ return new Map(identities.map((identity) => [identity.blockPath, identity]));
20033
+ }
20034
+ function indexEditableTargetsByBlockPath2(targets) {
20035
+ return new Map(targets.map((target) => [target.blockPath, target]));
20036
+ }
19346
20037
  function normalizeViewportPageWindow(window2) {
19347
20038
  if (!window2) return void 0;
19348
20039
  const buffer = Number.isFinite(window2.bufferPages) ? Math.max(0, Math.floor(window2.bufferPages ?? 0)) : DEFAULT_VIEWPORT_PAGE_WINDOW_BUFFER;
@@ -19538,8 +20229,22 @@ function recordFullRebuildReason(reasonKind) {
19538
20229
  probe.invalidationCounts[totalKey] = (probe.invalidationCounts[totalKey] ?? 0) + 1;
19539
20230
  probe.invalidationCounts[byReasonKey] = (probe.invalidationCounts[byReasonKey] ?? 0) + 1;
19540
20231
  }
20232
+ function wrapMeasurementProvider(provider, measurementCache, telemetryBus) {
20233
+ if (!measurementCache || isCachedLayoutMeasurementProvider(provider)) {
20234
+ return provider;
20235
+ }
20236
+ const cacheOptions = measurementCache === true ? {} : measurementCache;
20237
+ return createCachedLayoutMeasurementProvider(provider, {
20238
+ ...cacheOptions,
20239
+ ...telemetryBus ? { telemetryBus } : {}
20240
+ });
20241
+ }
19541
20242
  function createLayoutEngine(options = {}) {
19542
- let measurementProvider = options.measurementProvider ?? createEmpiricalMeasurementProvider();
20243
+ let measurementProvider = wrapMeasurementProvider(
20244
+ options.measurementProvider ?? createEmpiricalMeasurementProvider(),
20245
+ options.measurementCache,
20246
+ options.telemetryBus
20247
+ );
19543
20248
  const autoUpgradeToCanvas = options.autoUpgradeToCanvasBackend !== false;
19544
20249
  const telemetryBus = options.telemetryBus;
19545
20250
  const dirtyFieldFamilies = /* @__PURE__ */ new Set();
@@ -19639,13 +20344,20 @@ function createLayoutEngine(options = {}) {
19639
20344
  const pageCountBeforeRecompute = previousPageCount;
19640
20345
  const document2 = input.document;
19641
20346
  const viewportWindow = normalizeViewportPageWindow(input.viewportPageWindow);
20347
+ const layoutInputs = collectCanonicalLayoutInputs(document2);
20348
+ const layoutIdentitiesByBlockPath = indexLayoutIdentitiesByBlockPath(
20349
+ layoutInputs.layoutIdentities
20350
+ );
20351
+ const editableTargetsByBlockPath = indexEditableTargetsByBlockPath2(
20352
+ layoutInputs.editableTargets
20353
+ );
19642
20354
  const mainSurface = createEditorSurfaceSnapshot(
19643
20355
  document2,
19644
20356
  createSelectionSnapshot(0, 0),
19645
- MAIN_STORY_TARGET
20357
+ MAIN_STORY_TARGET,
20358
+ { editableTargetsByBlockPath, layoutIdentitiesByBlockPath }
19646
20359
  );
19647
20360
  const sections = buildResolvedSections(document2);
19648
- const layoutInputs = collectCanonicalLayoutInputs(document2);
19649
20361
  const fieldRegions = layoutInputs.fieldRegions;
19650
20362
  const pageStack = buildPageStackWithSplits(
19651
20363
  document2,
@@ -19757,10 +20469,18 @@ function createLayoutEngine(options = {}) {
19757
20469
  const firstDirty = range.firstPageIndex;
19758
20470
  if (firstDirty < 0 || firstDirty >= priorGraph.pages.length) return null;
19759
20471
  const document2 = input.document;
20472
+ const layoutInputs = collectCanonicalLayoutInputs(document2);
20473
+ const layoutIdentitiesByBlockPath = indexLayoutIdentitiesByBlockPath(
20474
+ layoutInputs.layoutIdentities
20475
+ );
20476
+ const editableTargetsByBlockPath = indexEditableTargetsByBlockPath2(
20477
+ layoutInputs.editableTargets
20478
+ );
19760
20479
  const mainSurface = createEditorSurfaceSnapshot(
19761
20480
  document2,
19762
20481
  createSelectionSnapshot(0, 0),
19763
- MAIN_STORY_TARGET
20482
+ MAIN_STORY_TARGET,
20483
+ { editableTargetsByBlockPath, layoutIdentitiesByBlockPath }
19764
20484
  );
19765
20485
  const sections = buildResolvedSections(document2);
19766
20486
  const dirtyPage = priorGraph.pages[firstDirty];
@@ -19789,7 +20509,6 @@ function createLayoutEngine(options = {}) {
19789
20509
  const freshSnapshotsToRebuild = freshSnapshots.slice(0, convergenceIndex);
19790
20510
  const convergedTailStart = convergenceIndex < freshSnapshots.length ? firstDirty + convergenceIndex : void 0;
19791
20511
  const freshStories = resolvePageStories(freshSnapshotsToRebuild);
19792
- const layoutInputs = collectCanonicalLayoutInputs(document2);
19793
20512
  const fieldRegions = layoutInputs.fieldRegions;
19794
20513
  const freshBodyFragmentsByPageIndex = projectSurfaceBlocksToPageFragments(
19795
20514
  mainSurface,
@@ -19921,7 +20640,11 @@ function createLayoutEngine(options = {}) {
19921
20640
  try {
19922
20641
  const mod = await Promise.resolve().then(() => (init_measurement_backend_canvas(), measurement_backend_canvas_exports));
19923
20642
  const canvasProvider = mod.createCanvasBackend();
19924
- measurementProvider = canvasProvider;
20643
+ measurementProvider = wrapMeasurementProvider(
20644
+ canvasProvider,
20645
+ options.measurementCache,
20646
+ telemetryBus
20647
+ );
19925
20648
  cachedKey = null;
19926
20649
  cachedGraph = null;
19927
20650
  cachedFormatting = null;
@@ -20006,7 +20729,11 @@ function createLayoutEngine(options = {}) {
20006
20729
  },
20007
20730
  swapMeasurementProvider(provider) {
20008
20731
  const previousFidelity = measurementProvider.fidelity;
20009
- measurementProvider = provider;
20732
+ measurementProvider = wrapMeasurementProvider(
20733
+ provider,
20734
+ options.measurementCache,
20735
+ telemetryBus
20736
+ );
20010
20737
  if (previousFidelity !== provider.fidelity) {
20011
20738
  cachedKey = null;
20012
20739
  cachedGraph = null;
@@ -20035,6 +20762,10 @@ function createLayoutEngine(options = {}) {
20035
20762
  cachedFormatting = null;
20036
20763
  cachedMapper = null;
20037
20764
  },
20765
+ getMeasurementCacheStats() {
20766
+ if (!isCachedLayoutMeasurementProvider(measurementProvider)) return null;
20767
+ return measurementProvider.measurementCacheStats();
20768
+ },
20038
20769
  /**
20039
20770
  * L7 Phase 2.5 — seed the cached graph from a prerender envelope.
20040
20771
  * Populates both `cachedGraph` and `cachedKey` (keyed on the provided