@beyondwork/docx-react-component 1.0.129 → 1.0.131

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 (102) hide show
  1. package/dist/api/public-types.cjs +595 -18
  2. package/dist/api/public-types.d.cts +1 -1
  3. package/dist/api/public-types.d.ts +1 -1
  4. package/dist/api/public-types.js +4 -4
  5. package/dist/api/v3.cjs +1164 -332
  6. package/dist/api/v3.d.cts +2 -2
  7. package/dist/api/v3.d.ts +2 -2
  8. package/dist/api/v3.js +13 -13
  9. package/dist/{chunk-OTQIW2TC.js → chunk-35RHOE6I.js} +105 -4
  10. package/dist/{chunk-PGKUJZXV.js → chunk-3YCQM2RV.js} +6 -6
  11. package/dist/{chunk-JJGVE5J7.js → chunk-4YCWECLZ.js} +1 -1
  12. package/dist/{chunk-EZKJXIPH.js → chunk-6TBLDBCL.js} +1 -1
  13. package/dist/{chunk-SKPTKQHF.js → chunk-7G5GR3VV.js} +122 -23
  14. package/dist/{chunk-HUIHBBAQ.js → chunk-A3GSNB4G.js} +17 -6
  15. package/dist/{chunk-5DGKFNQT.js → chunk-A66ZVUAT.js} +150 -1
  16. package/dist/{chunk-YIYM4ZAP.js → chunk-CI2TD3T4.js} +1 -1
  17. package/dist/{chunk-63FYIGCT.js → chunk-DGA7M77X.js} +2 -2
  18. package/dist/{chunk-EB6M3GE6.js → chunk-FM4K4XFJ.js} +100 -97
  19. package/dist/{chunk-VNLDQJ47.js → chunk-HYHCRMR7.js} +1 -1
  20. package/dist/{chunk-DJU2W4E4.js → chunk-KNHMXKC6.js} +2 -2
  21. package/dist/{chunk-Q3QYGKFE.js → chunk-M7YRJX6V.js} +10 -21
  22. package/dist/{chunk-KFCQYZXR.js → chunk-OVLZQ6FZ.js} +61 -0
  23. package/dist/{chunk-W34X3KBR.js → chunk-PHMWH23E.js} +1 -1
  24. package/dist/{chunk-DDN2AIGE.js → chunk-Q7Y57KOK.js} +2 -2
  25. package/dist/{chunk-LJH64PV3.js → chunk-QXKQPUOM.js} +3 -3
  26. package/dist/{chunk-CX42VC67.js → chunk-SYQWQ6FE.js} +1 -1
  27. package/dist/{chunk-5DSHUYSY.js → chunk-T5YYFDZB.js} +1 -1
  28. package/dist/{chunk-RMRTQGW3.js → chunk-THVM6EP5.js} +371 -13
  29. package/dist/{chunk-XMHSGPLN.js → chunk-VRKK2CSZ.js} +111 -90
  30. package/dist/{chunk-OL2UEHRP.js → chunk-WUDSNHWF.js} +1 -1
  31. package/dist/{chunk-XQCAMKIQ.js → chunk-WZDKNF37.js} +250 -106
  32. package/dist/{chunk-PRAZBHNF.js → chunk-YLL7MF5C.js} +15 -15
  33. package/dist/{chunk-YZDZ4FGR.js → chunk-ZVC23LKV.js} +1 -1
  34. package/dist/compare.cjs +100 -97
  35. package/dist/compare.js +3 -3
  36. package/dist/core/commands/formatting-commands.d.cts +1 -1
  37. package/dist/core/commands/formatting-commands.d.ts +1 -1
  38. package/dist/core/commands/image-commands.cjs +16 -5
  39. package/dist/core/commands/image-commands.d.cts +1 -1
  40. package/dist/core/commands/image-commands.d.ts +1 -1
  41. package/dist/core/commands/image-commands.js +5 -5
  42. package/dist/core/commands/section-layout-commands.d.cts +1 -1
  43. package/dist/core/commands/section-layout-commands.d.ts +1 -1
  44. package/dist/core/commands/style-commands.d.cts +1 -1
  45. package/dist/core/commands/style-commands.d.ts +1 -1
  46. package/dist/core/commands/table-structure-commands.cjs +16 -5
  47. package/dist/core/commands/table-structure-commands.d.cts +1 -1
  48. package/dist/core/commands/table-structure-commands.d.ts +1 -1
  49. package/dist/core/commands/table-structure-commands.js +4 -4
  50. package/dist/core/commands/text-commands.cjs +16 -5
  51. package/dist/core/commands/text-commands.d.cts +1 -1
  52. package/dist/core/commands/text-commands.d.ts +1 -1
  53. package/dist/core/commands/text-commands.js +5 -5
  54. package/dist/core/selection/mapping.d.cts +1 -1
  55. package/dist/core/selection/mapping.d.ts +1 -1
  56. package/dist/core/state/editor-state.d.cts +1 -1
  57. package/dist/core/state/editor-state.d.ts +1 -1
  58. package/dist/index.cjs +1280 -347
  59. package/dist/index.d.cts +4 -4
  60. package/dist/index.d.ts +4 -4
  61. package/dist/index.js +24 -24
  62. package/dist/io/docx-session.cjs +216 -203
  63. package/dist/io/docx-session.d.cts +3 -3
  64. package/dist/io/docx-session.d.ts +3 -3
  65. package/dist/io/docx-session.js +6 -6
  66. package/dist/legal.cjs +9 -20
  67. package/dist/legal.js +3 -3
  68. package/dist/{loader-4qsw4eIU.d.ts → loader-B-aL5HGD.d.ts} +2 -2
  69. package/dist/{loader-B8TKhmQi.d.cts → loader-DiY_ZgKl.d.cts} +2 -2
  70. package/dist/{measurement-backend-canvas-Q3MJMEYX.js → measurement-backend-canvas-F7ZYDACK.js} +1 -1
  71. package/dist/{public-types-p9b8rfy8.d.ts → public-types-DyqnxxO9.d.ts} +124 -1
  72. package/dist/{public-types-B5CRoR6f.d.cts → public-types-gvubspUI.d.cts} +124 -1
  73. package/dist/public-types.cjs +595 -18
  74. package/dist/public-types.d.cts +1 -1
  75. package/dist/public-types.d.ts +1 -1
  76. package/dist/public-types.js +4 -4
  77. package/dist/runtime/collab.d.cts +2 -2
  78. package/dist/runtime/collab.d.ts +2 -2
  79. package/dist/runtime/document-runtime.cjs +908 -129
  80. package/dist/runtime/document-runtime.d.cts +1 -1
  81. package/dist/runtime/document-runtime.d.ts +1 -1
  82. package/dist/runtime/document-runtime.js +17 -17
  83. package/dist/{session-BnGIjaex.d.cts → session-BUN6B-Vj.d.cts} +2 -2
  84. package/dist/{session-vEYKf-w3.d.ts → session-CDB0hohT.d.ts} +2 -2
  85. package/dist/session.cjs +216 -203
  86. package/dist/session.d.cts +4 -4
  87. package/dist/session.d.ts +4 -4
  88. package/dist/session.js +7 -7
  89. package/dist/tailwind.cjs +595 -18
  90. package/dist/tailwind.d.cts +1 -1
  91. package/dist/tailwind.d.ts +1 -1
  92. package/dist/tailwind.js +8 -8
  93. package/dist/{types-BLuvZ6cQ.d.cts → types-C4bz3kDU.d.cts} +1 -1
  94. package/dist/{types-Dutlyj0T.d.ts → types-VWH6CRvG.d.ts} +1 -1
  95. package/dist/ui-tailwind/editor-surface/search-plugin.d.cts +2 -2
  96. package/dist/ui-tailwind/editor-surface/search-plugin.d.ts +2 -2
  97. package/dist/ui-tailwind/editor-surface/search-plugin.js +5 -5
  98. package/dist/ui-tailwind.cjs +595 -18
  99. package/dist/ui-tailwind.d.cts +2 -2
  100. package/dist/ui-tailwind.d.ts +2 -2
  101. package/dist/ui-tailwind.js +8 -8
  102. package/package.json +4 -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,
@@ -11665,7 +11873,7 @@ function buildEffectiveLayoutFormatting(input) {
11665
11873
  };
11666
11874
  }
11667
11875
  function createStructuralHash(value) {
11668
- const stable = stableStringify(value);
11876
+ const stable = stableStringify2(value);
11669
11877
  let hash = 2166136261;
11670
11878
  for (let i = 0; i < stable.length; i += 1) {
11671
11879
  hash ^= stable.charCodeAt(i);
@@ -11673,16 +11881,16 @@ function createStructuralHash(value) {
11673
11881
  }
11674
11882
  return `fnv1a32:${(hash >>> 0).toString(16).padStart(8, "0")}`;
11675
11883
  }
11676
- function stableStringify(value) {
11884
+ function stableStringify2(value) {
11677
11885
  if (value === null || typeof value !== "object") {
11678
11886
  return JSON.stringify(value);
11679
11887
  }
11680
11888
  if (Array.isArray(value)) {
11681
- return `[${value.map((entry) => stableStringify(entry)).join(",")}]`;
11889
+ return `[${value.map((entry) => stableStringify2(entry)).join(",")}]`;
11682
11890
  }
11683
11891
  const record = value;
11684
11892
  const keys = Object.keys(record).filter((key) => record[key] !== void 0).sort();
11685
- return `{${keys.map((key) => `${JSON.stringify(key)}:${stableStringify(record[key])}`).join(",")}}`;
11893
+ return `{${keys.map((key) => `${JSON.stringify(key)}:${stableStringify2(record[key])}`).join(",")}}`;
11686
11894
  }
11687
11895
 
11688
11896
  // src/runtime/formatting/formatting-context.ts
@@ -12191,6 +12399,7 @@ function createEditorSurfaceSnapshot(document2, _selection, activeStory = { kind
12191
12399
  ...options.authorColorPalette ? { authorColorPalette: options.authorColorPalette } : {}
12192
12400
  });
12193
12401
  const editableTargetsByBlockPath = options.editableTargetsByBlockPath ?? indexEditableTargetsByBlockPath(document2);
12402
+ const layoutIdentitiesByBlockPath = options.layoutIdentitiesByBlockPath;
12194
12403
  const activeStoryBlockPathBase = getActiveStoryBlockPathBase(document2, activeStory);
12195
12404
  chartModelStore.beginBuildPass(document2);
12196
12405
  const unsupportedNumberingFormatsSeen = options.emitFormattingTelemetry ? /* @__PURE__ */ new Set() : null;
@@ -12214,6 +12423,7 @@ function createEditorSurfaceSnapshot(document2, _selection, activeStory = { kind
12214
12423
  activeStory.kind !== "main",
12215
12424
  !isInViewport,
12216
12425
  editableTargetsByBlockPath,
12426
+ layoutIdentitiesByBlockPath,
12217
12427
  `${activeStoryBlockPathBase}/block[${index}]`
12218
12428
  );
12219
12429
  if (isInViewport) {
@@ -12280,7 +12490,7 @@ function isIndexInAnyRange(index, ranges) {
12280
12490
  }
12281
12491
  return false;
12282
12492
  }
12283
- 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) {
12284
12494
  if (block.type === "opaque_block") {
12285
12495
  const fragment = getOpaqueFragment(document2.preservation, block.fragmentId);
12286
12496
  const descriptor = fragment ? describeOpaqueFragment(fragment) : null;
@@ -12317,6 +12527,7 @@ function createSurfaceBlock(block, document2, cursor, counters, formattingContex
12317
12527
  promoteSecondaryStoryTextBoxes,
12318
12528
  cullBuild,
12319
12529
  editableTargetsByBlockPath,
12530
+ layoutIdentitiesByBlockPath,
12320
12531
  blockPath
12321
12532
  );
12322
12533
  }
@@ -12357,6 +12568,7 @@ function createSurfaceBlock(block, document2, cursor, counters, formattingContex
12357
12568
  promoteSecondaryStoryTextBoxes,
12358
12569
  cullBuild,
12359
12570
  editableTargetsByBlockPath,
12571
+ layoutIdentitiesByBlockPath,
12360
12572
  blockPath
12361
12573
  );
12362
12574
  }
@@ -12439,10 +12651,11 @@ function createSurfaceBlock(block, document2, cursor, counters, formattingContex
12439
12651
  cullBuild,
12440
12652
  editableTargetsByBlockPath,
12441
12653
  blockPath,
12442
- 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
12443
12656
  );
12444
12657
  }
12445
- 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) {
12446
12659
  const lockedFragmentIds = [];
12447
12660
  let innerCursor = cursor;
12448
12661
  if (cullBuild) {
@@ -12459,6 +12672,7 @@ function createTableBlock(tableIndex, table, document2, cursor, counters, format
12459
12672
  promoteSecondaryStoryTextBoxes,
12460
12673
  true,
12461
12674
  editableTargetsByBlockPath,
12675
+ layoutIdentitiesByBlockPath,
12462
12676
  tablePath !== void 0 ? `${tablePath}/row[${rowIndex}]/cell[${cellIndex}]/block[${childIndex}]` : void 0
12463
12677
  );
12464
12678
  lockedFragmentIds.push(...result.lockedFragmentIds);
@@ -12474,6 +12688,7 @@ function createTableBlock(tableIndex, table, document2, cursor, counters, format
12474
12688
  to: innerCursor,
12475
12689
  styleId: table.styleId,
12476
12690
  ...table.sourceRef !== void 0 ? { sourceRef: table.sourceRef } : {},
12691
+ ...tablePath !== void 0 && layoutIdentitiesByBlockPath?.get(tablePath) !== void 0 ? { layoutIdentity: layoutIdentitiesByBlockPath.get(tablePath) } : {},
12477
12692
  gridColumns: table.gridColumns,
12478
12693
  rows: []
12479
12694
  },
@@ -12511,6 +12726,7 @@ function createTableBlock(tableIndex, table, document2, cursor, counters, format
12511
12726
  promoteSecondaryStoryTextBoxes,
12512
12727
  cullBuild,
12513
12728
  editableTargetsByBlockPath,
12729
+ layoutIdentitiesByBlockPath,
12514
12730
  tablePath !== void 0 ? `${tablePath}/row[${rowIndex}]/cell[${cellIndex}]/block[${childIndex}]` : void 0
12515
12731
  );
12516
12732
  cellContent.push(result.block);
@@ -12599,6 +12815,7 @@ function createTableBlock(tableIndex, table, document2, cursor, counters, format
12599
12815
  to: innerCursor,
12600
12816
  styleId: table.styleId,
12601
12817
  ...table.sourceRef !== void 0 ? { sourceRef: table.sourceRef } : {},
12818
+ ...tablePath !== void 0 && layoutIdentitiesByBlockPath?.get(tablePath) !== void 0 ? { layoutIdentity: layoutIdentitiesByBlockPath.get(tablePath) } : {},
12602
12819
  gridColumns: table.gridColumns,
12603
12820
  ...gridColumnsRelative ? { gridColumnsRelative } : {},
12604
12821
  ...resolvedTable.table?.alignment ? { alignment: resolvedTable.table.alignment } : {},
@@ -12786,7 +13003,7 @@ function resolveCellBorderStyles(borders, tableBorders, position) {
12786
13003
  if (left) result.borderLeft = left;
12787
13004
  return result;
12788
13005
  }
12789
- 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) {
12790
13007
  const children = [];
12791
13008
  const lockedFragmentIds = [];
12792
13009
  let innerCursor = cursor;
@@ -12803,6 +13020,7 @@ function createSdtBlock(sdtIndex, block, document2, cursor, counters, formatting
12803
13020
  promoteSecondaryStoryTextBoxes,
12804
13021
  cullBuild,
12805
13022
  editableTargetsByBlockPath,
13023
+ layoutIdentitiesByBlockPath,
12806
13024
  sdtPath !== void 0 ? `${sdtPath}/block[${childIndex}]` : void 0
12807
13025
  );
12808
13026
  children.push(result.block);
@@ -12845,7 +13063,7 @@ function getRecursableSdtBlockedReasonCode(block) {
12845
13063
  ].filter(Boolean).join(" ").toLowerCase();
12846
13064
  return searchText.includes("table of contents") || /\btoc\b/u.test(searchText) ? "workflow_preserve_only" : null;
12847
13065
  }
12848
- 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) {
12849
13067
  const themeResolver = formattingContext.theme;
12850
13068
  const effectiveNumbering = formattingContext.resolveEffectiveParagraphNumbering(paragraph);
12851
13069
  let resolvedNumbering = null;
@@ -12868,6 +13086,7 @@ function createParagraphBlock(paragraphIndex, paragraph, document2, start, forma
12868
13086
  from: start,
12869
13087
  to: start,
12870
13088
  ...editableTarget !== void 0 ? { editableTarget } : {},
13089
+ ...layoutIdentity !== void 0 ? { layoutIdentity } : {},
12871
13090
  ...paragraph.styleId ? { styleId: paragraph.styleId } : {},
12872
13091
  ...effectiveNumbering ? { numbering: effectiveNumbering } : {},
12873
13092
  ...resolvedNumbering ? {
@@ -19491,12 +19710,330 @@ function createEmpiricalProvider() {
19491
19710
  return createEmpiricalBackend();
19492
19711
  }
19493
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
+
19494
20025
  // src/runtime/layout/layout-engine-version.ts
19495
- var LAYOUT_ENGINE_VERSION = 89;
20026
+ var LAYOUT_ENGINE_VERSION = 93;
19496
20027
 
19497
20028
  // src/runtime/layout/layout-engine-instance.ts
19498
20029
  var FULL_VIEWPORT_WINDOW_KEY = "full";
19499
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
+ }
19500
20037
  function normalizeViewportPageWindow(window2) {
19501
20038
  if (!window2) return void 0;
19502
20039
  const buffer = Number.isFinite(window2.bufferPages) ? Math.max(0, Math.floor(window2.bufferPages ?? 0)) : DEFAULT_VIEWPORT_PAGE_WINDOW_BUFFER;
@@ -19692,8 +20229,22 @@ function recordFullRebuildReason(reasonKind) {
19692
20229
  probe.invalidationCounts[totalKey] = (probe.invalidationCounts[totalKey] ?? 0) + 1;
19693
20230
  probe.invalidationCounts[byReasonKey] = (probe.invalidationCounts[byReasonKey] ?? 0) + 1;
19694
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
+ }
19695
20242
  function createLayoutEngine(options = {}) {
19696
- let measurementProvider = options.measurementProvider ?? createEmpiricalMeasurementProvider();
20243
+ let measurementProvider = wrapMeasurementProvider(
20244
+ options.measurementProvider ?? createEmpiricalMeasurementProvider(),
20245
+ options.measurementCache,
20246
+ options.telemetryBus
20247
+ );
19697
20248
  const autoUpgradeToCanvas = options.autoUpgradeToCanvasBackend !== false;
19698
20249
  const telemetryBus = options.telemetryBus;
19699
20250
  const dirtyFieldFamilies = /* @__PURE__ */ new Set();
@@ -19793,13 +20344,20 @@ function createLayoutEngine(options = {}) {
19793
20344
  const pageCountBeforeRecompute = previousPageCount;
19794
20345
  const document2 = input.document;
19795
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
+ );
19796
20354
  const mainSurface = createEditorSurfaceSnapshot(
19797
20355
  document2,
19798
20356
  createSelectionSnapshot(0, 0),
19799
- MAIN_STORY_TARGET
20357
+ MAIN_STORY_TARGET,
20358
+ { editableTargetsByBlockPath, layoutIdentitiesByBlockPath }
19800
20359
  );
19801
20360
  const sections = buildResolvedSections(document2);
19802
- const layoutInputs = collectCanonicalLayoutInputs(document2);
19803
20361
  const fieldRegions = layoutInputs.fieldRegions;
19804
20362
  const pageStack = buildPageStackWithSplits(
19805
20363
  document2,
@@ -19911,10 +20469,18 @@ function createLayoutEngine(options = {}) {
19911
20469
  const firstDirty = range.firstPageIndex;
19912
20470
  if (firstDirty < 0 || firstDirty >= priorGraph.pages.length) return null;
19913
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
+ );
19914
20479
  const mainSurface = createEditorSurfaceSnapshot(
19915
20480
  document2,
19916
20481
  createSelectionSnapshot(0, 0),
19917
- MAIN_STORY_TARGET
20482
+ MAIN_STORY_TARGET,
20483
+ { editableTargetsByBlockPath, layoutIdentitiesByBlockPath }
19918
20484
  );
19919
20485
  const sections = buildResolvedSections(document2);
19920
20486
  const dirtyPage = priorGraph.pages[firstDirty];
@@ -19943,7 +20509,6 @@ function createLayoutEngine(options = {}) {
19943
20509
  const freshSnapshotsToRebuild = freshSnapshots.slice(0, convergenceIndex);
19944
20510
  const convergedTailStart = convergenceIndex < freshSnapshots.length ? firstDirty + convergenceIndex : void 0;
19945
20511
  const freshStories = resolvePageStories(freshSnapshotsToRebuild);
19946
- const layoutInputs = collectCanonicalLayoutInputs(document2);
19947
20512
  const fieldRegions = layoutInputs.fieldRegions;
19948
20513
  const freshBodyFragmentsByPageIndex = projectSurfaceBlocksToPageFragments(
19949
20514
  mainSurface,
@@ -20075,7 +20640,11 @@ function createLayoutEngine(options = {}) {
20075
20640
  try {
20076
20641
  const mod = await Promise.resolve().then(() => (init_measurement_backend_canvas(), measurement_backend_canvas_exports));
20077
20642
  const canvasProvider = mod.createCanvasBackend();
20078
- measurementProvider = canvasProvider;
20643
+ measurementProvider = wrapMeasurementProvider(
20644
+ canvasProvider,
20645
+ options.measurementCache,
20646
+ telemetryBus
20647
+ );
20079
20648
  cachedKey = null;
20080
20649
  cachedGraph = null;
20081
20650
  cachedFormatting = null;
@@ -20160,7 +20729,11 @@ function createLayoutEngine(options = {}) {
20160
20729
  },
20161
20730
  swapMeasurementProvider(provider) {
20162
20731
  const previousFidelity = measurementProvider.fidelity;
20163
- measurementProvider = provider;
20732
+ measurementProvider = wrapMeasurementProvider(
20733
+ provider,
20734
+ options.measurementCache,
20735
+ telemetryBus
20736
+ );
20164
20737
  if (previousFidelity !== provider.fidelity) {
20165
20738
  cachedKey = null;
20166
20739
  cachedGraph = null;
@@ -20189,6 +20762,10 @@ function createLayoutEngine(options = {}) {
20189
20762
  cachedFormatting = null;
20190
20763
  cachedMapper = null;
20191
20764
  },
20765
+ getMeasurementCacheStats() {
20766
+ if (!isCachedLayoutMeasurementProvider(measurementProvider)) return null;
20767
+ return measurementProvider.measurementCacheStats();
20768
+ },
20192
20769
  /**
20193
20770
  * L7 Phase 2.5 — seed the cached graph from a prerender envelope.
20194
20771
  * Populates both `cachedGraph` and `cachedKey` (keyed on the provided