@stll/folio-core 0.47.7 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/dist/controller/fontReadiness.js +3 -3
  2. package/dist/controller/hyphenationReadiness.d.ts +19 -0
  3. package/dist/controller/hyphenationReadiness.js +47 -0
  4. package/dist/controller/layoutPipeline.d.ts +3 -0
  5. package/dist/controller/layoutPipeline.js +59 -17
  6. package/dist/display-list/build/buildDisplayList.js +39 -12
  7. package/dist/display-list/build/pageFurniture.d.ts +7 -1
  8. package/dist/display-list/build/pageFurniture.js +21 -8
  9. package/dist/display-list/build/paragraphPrimitives.js +5 -4
  10. package/dist/display-list/build/tablePrimitives.js +10 -6
  11. package/dist/docx/attributeRemainder.js +10 -2
  12. package/dist/docx/blockContentParser.d.ts +2 -0
  13. package/dist/docx/blockContentParser.js +77 -62
  14. package/dist/docx/commentParser.d.ts +2 -1
  15. package/dist/docx/commentParser.js +57 -45
  16. package/dist/docx/containerChildren.d.ts +21 -8
  17. package/dist/docx/containerChildren.js +39 -9
  18. package/dist/docx/documentParser.d.ts +5 -1
  19. package/dist/docx/documentParser.js +8 -5
  20. package/dist/docx/documentSectionFacts.d.ts +22 -0
  21. package/dist/docx/documentSectionFacts.js +43 -0
  22. package/dist/docx/fieldParser.d.ts +8 -1
  23. package/dist/docx/fieldParser.js +47 -3
  24. package/dist/docx/fontTableParser.js +34 -27
  25. package/dist/docx/footnoteParser.d.ts +3 -2
  26. package/dist/docx/footnoteParser.js +15 -12
  27. package/dist/docx/groupDrawingParser.d.ts +2 -1
  28. package/dist/docx/groupDrawingParser.js +3 -6
  29. package/dist/docx/headerFooterParser.d.ts +7 -2
  30. package/dist/docx/headerFooterParser.js +15 -5
  31. package/dist/docx/hyperlinkParser.d.ts +48 -36
  32. package/dist/docx/hyperlinkParser.js +97 -82
  33. package/dist/docx/numberingParser.js +108 -84
  34. package/dist/docx/paragraphParser.d.ts +5 -1
  35. package/dist/docx/paragraphParser.js +381 -362
  36. package/dist/docx/paragraphProperties.js +123 -109
  37. package/dist/docx/paragraphPropertySource.d.ts +6 -1
  38. package/dist/docx/paragraphPropertySource.js +9 -1
  39. package/dist/docx/paragraphTextBoxEnrichment.d.ts +2 -1
  40. package/dist/docx/paragraphTextBoxEnrichment.js +17 -6
  41. package/dist/docx/parser.d.ts +7 -1
  42. package/dist/docx/parser.js +33 -16
  43. package/dist/docx/previewBudget.d.ts +55 -33
  44. package/dist/docx/previewBudget.js +59 -65
  45. package/dist/docx/rezip.js +41 -58
  46. package/dist/docx/runParser.d.ts +4 -1
  47. package/dist/docx/runParser.js +172 -184
  48. package/dist/docx/sdtProperties.js +87 -84
  49. package/dist/docx/sectionParser.js +169 -160
  50. package/dist/docx/serializer/paragraphSerializer.js +42 -38
  51. package/dist/docx/serializer/settingsSerializer.js +19 -1
  52. package/dist/docx/settingsParser.js +8 -0
  53. package/dist/docx/streamingXmlParser.d.ts +6 -2
  54. package/dist/docx/streamingXmlParser.js +12 -7
  55. package/dist/docx/styleParser.js +34 -8
  56. package/dist/docx/tableParser.d.ts +21 -12
  57. package/dist/docx/tableParser.js +518 -441
  58. package/dist/docx/textBoxParser.d.ts +8 -3
  59. package/dist/docx/textBoxParser.js +3 -3
  60. package/dist/docx/verbatimCapture.d.ts +10 -8
  61. package/dist/docx/verbatimCapture.js +45 -2
  62. package/dist/docx/vmlImageParser.d.ts +15 -13
  63. package/dist/docx/vmlImageParser.js +75 -60
  64. package/dist/docx/vmlPreview.d.ts +3 -3
  65. package/dist/docx/vmlPreview.js +3 -4
  66. package/dist/docx/xmlNamespaceContext.d.ts +9 -0
  67. package/dist/docx/xmlNamespaceContext.js +54 -0
  68. package/dist/docx/xmlParser.d.ts +6 -3
  69. package/dist/docx/xmlParser.js +11 -41
  70. package/dist/docx/xmlResourceLimits.d.ts +2 -1
  71. package/dist/docx/xmlResourceLimits.js +4 -1
  72. package/dist/fonts/headlessMeasure.js +0 -0
  73. package/dist/headless-layout.d.ts +11 -2
  74. package/dist/headless-layout.js +153 -107
  75. package/dist/internal/paragraphFormattingSerialization.js +3 -3
  76. package/dist/layout-bridge/convert/endnoteLayout.d.ts +65 -0
  77. package/dist/layout-bridge/convert/endnoteLayout.js +227 -0
  78. package/dist/layout-bridge/convert/footnoteLayout.d.ts +19 -3
  79. package/dist/layout-bridge/convert/footnoteLayout.js +40 -31
  80. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -7
  81. package/dist/layout-bridge/convert/headerFooterLayout.js +5 -20
  82. package/dist/layout-bridge/convert/paragraphMarkFormatting.d.ts +10 -0
  83. package/dist/layout-bridge/convert/paragraphMarkFormatting.js +59 -0
  84. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +29 -1
  85. package/dist/layout-bridge/convert/toFlowBlocks.js +258 -35
  86. package/dist/layout-bridge/engine/hitTest.js +5 -3
  87. package/dist/layout-bridge/engine/selectionRects.js +5 -3
  88. package/dist/layout-engine/anchorLayoutInCellCompatibility.d.ts +10 -0
  89. package/dist/layout-engine/anchorLayoutInCellCompatibility.js +22 -0
  90. package/dist/layout-engine/index.d.ts +2 -2
  91. package/dist/layout-engine/index.js +70 -11
  92. package/dist/layout-engine/justificationCompatibility.d.ts +1 -1
  93. package/dist/layout-engine/justificationCompatibility.js +9 -5
  94. package/dist/layout-engine/keep-together.d.ts +11 -5
  95. package/dist/layout-engine/keep-together.js +39 -16
  96. package/dist/layout-engine/layoutInstrumentation.d.ts +8 -2
  97. package/dist/layout-engine/layoutInstrumentation.js +8 -1
  98. package/dist/layout-engine/measure/advanceComposition.js +4 -7
  99. package/dist/layout-engine/measure/hyphenationDictionaries.d.ts +74 -0
  100. package/dist/layout-engine/measure/hyphenationDictionaries.js +138 -0
  101. package/dist/layout-engine/measure/hyphenationPreload.d.ts +11 -0
  102. package/dist/layout-engine/measure/hyphenationPreload.js +24 -0
  103. package/dist/layout-engine/measure/lineBreakProvider.d.ts +12 -2
  104. package/dist/layout-engine/measure/lineBreakProvider.js +30 -30
  105. package/dist/layout-engine/measure/lineBreaks.d.ts +6 -1
  106. package/dist/layout-engine/measure/lineBreaks.js +10 -3
  107. package/dist/layout-engine/measure/listMarkerWidth.d.ts +9 -6
  108. package/dist/layout-engine/measure/listMarkerWidth.js +20 -22
  109. package/dist/layout-engine/measure/measureBlocks.js +42 -8
  110. package/dist/layout-engine/measure/measureContainer.js +5 -5
  111. package/dist/layout-engine/measure/measureHelpers.d.ts +15 -3
  112. package/dist/layout-engine/measure/measureHelpers.js +21 -5
  113. package/dist/layout-engine/measure/measureParagraph.js +109 -30
  114. package/dist/layout-engine/measure/measureTypes.d.ts +5 -0
  115. package/dist/layout-engine/measure/tabCalculator.d.ts +2 -0
  116. package/dist/layout-engine/measure/tabCalculator.js +2 -1
  117. package/dist/layout-engine/measure/tableCellFloating.d.ts +2 -0
  118. package/dist/layout-engine/measure/tableCellFloating.js +51 -19
  119. package/dist/layout-engine/measure/tableCellGrid.d.ts +28 -3
  120. package/dist/layout-engine/measure/tableCellGrid.js +45 -5
  121. package/dist/layout-engine/measure/tableFragmentBorderGeometry.js +2 -1
  122. package/dist/layout-engine/noteAreaFlow.d.ts +19 -0
  123. package/dist/layout-engine/noteAreaFlow.js +83 -0
  124. package/dist/layout-engine/paginator.d.ts +10 -1
  125. package/dist/layout-engine/paginator.js +13 -1
  126. package/dist/layout-engine/tableRowBreak.js +3 -1
  127. package/dist/layout-engine/types.d.ts +89 -3
  128. package/dist/layout-engine/types.js +96 -1
  129. package/dist/layout-painter/index.d.ts +3 -0
  130. package/dist/layout-painter/renderPage.js +32 -83
  131. package/dist/layout-painter/renderParagraph.d.ts +6 -1
  132. package/dist/layout-painter/renderParagraph.js +34 -22
  133. package/dist/layout-painter/renderTable.js +26 -13
  134. package/dist/prosemirror/attrs/index.d.ts +9 -9
  135. package/dist/prosemirror/attrs/index.js +43 -11
  136. package/dist/prosemirror/conversion/fromProseDoc.js +8 -1
  137. package/dist/prosemirror/conversion/markInterner.d.ts +21 -0
  138. package/dist/prosemirror/conversion/markInterner.js +90 -0
  139. package/dist/prosemirror/conversion/toProseDoc.js +77 -41
  140. package/dist/prosemirror/extensions/core/DocExtension.js +2 -1
  141. package/dist/prosemirror/extensions/core/ParagraphExtension.js +1 -0
  142. package/dist/prosemirror/extensions/marks/markUtils.d.ts +6 -2
  143. package/dist/prosemirror/extensions/marks/markUtils.js +39 -51
  144. package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +2 -1
  145. package/dist/prosemirror/listMarker.d.ts +1 -0
  146. package/dist/prosemirror/listMarker.js +2 -0
  147. package/dist/prosemirror/listRenderingAttrs.d.ts +1 -0
  148. package/dist/prosemirror/listRenderingAttrs.js +3 -0
  149. package/dist/prosemirror/schema/nodes.d.ts +13 -1
  150. package/dist/prosemirror/textBoxHostParagraph.d.ts +13 -0
  151. package/dist/prosemirror/textBoxHostParagraph.js +21 -0
  152. package/dist/prosemirror/validation.js +91 -80
  153. package/dist/utils/createDocument.js +10 -1
  154. package/dist/utils/scriptSegments.d.ts +33 -4
  155. package/dist/utils/scriptSegments.js +39 -6
  156. package/dist/utils/textFormattingMerge.d.ts +17 -3
  157. package/dist/utils/textFormattingMerge.js +18 -12
  158. package/dist/utils/trailingText.d.ts +22 -0
  159. package/dist/utils/trailingText.js +32 -0
  160. package/package.json +2 -2
@@ -1,8 +1,9 @@
1
1
  import { resolveFloatingTableX } from "../layout-engine/measure/floatingTablePosition.js";
2
2
  import { rectsToFloatingZones } from "../layout-engine/measure/floatingZones.js";
3
+ import { DEFAULT_FONT_FAMILY } from "../layout-engine/measure/measureHelpers.js";
3
4
  import { measureParagraph } from "../layout-engine/measure/measureParagraph.js";
4
5
  import { resolveTableInlineOffset } from "../layout-engine/measure/tableInlinePlacement.js";
5
- import { floatingTextBoxReservesBand, floatingTextBoxWrapsText, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun } from "../layout-engine/types.js";
6
+ import { NOTE_SEPARATOR_RULE_THICKNESS, NOTE_SEPARATOR_WIDTH_FRACTION, floatingTextBoxReservesBand, floatingTextBoxWrapsText, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, stripFlowBlockPmAnchors } from "../layout-engine/types.js";
6
7
  import { cssBorderStyle } from "../utils/borderCss.js";
7
8
  import { resolveFontFamily } from "../utils/fontResolver.js";
8
9
  import { borderToStyle } from "../utils/formatToStyle.js";
@@ -43,7 +44,7 @@ const PAGE_CLASS_NAMES = {
43
44
  };
44
45
  const HEADER_FOOTER_RULE_CLIP_MARGIN = pointsToPixels(1.5);
45
46
  const DEFAULT_MARGIN_GUIDE_COLOR = "#c0c0c0";
46
- const getDefaultPageFontFamily = () => resolveFontFamily("Calibri").cssFallback;
47
+ const getDefaultPageFontFamily = () => resolveFontFamily(DEFAULT_FONT_FAMILY).cssFallback;
47
48
  /**
48
49
  * Apply page styles to an element
49
50
  */
@@ -603,6 +604,25 @@ function calculateFootnoteAreaRenderHeight(footnotes) {
603
604
  }
604
605
  return height;
605
606
  }
607
+ /** A note separator rule: the canvas ink colour, `NOTE_SEPARATOR_RULE_THICKNESS` high. */
608
+ function applyNoteSeparatorRuleStyles(element, width) {
609
+ element.style.width = `${width}px`;
610
+ element.style.height = `${NOTE_SEPARATOR_RULE_THICKNESS}px`;
611
+ element.style.backgroundColor = "var(--doc-canvas-text, #000)";
612
+ }
613
+ /** The separator rules of a note area that flows with the body (endnotes). */
614
+ function renderFlowedNoteSeparators(page, contentEl, doc) {
615
+ for (const rule of page.noteSeparators ?? []) {
616
+ const ruleEl = doc.createElement("div");
617
+ ruleEl.className = "layout-note-separator";
618
+ applyNoteSeparatorRuleStyles(ruleEl, rule.width);
619
+ ruleEl.style.position = "absolute";
620
+ ruleEl.style.left = `${rule.x - page.margins.left}px`;
621
+ ruleEl.style.top = `${rule.y - page.margins.top}px`;
622
+ ruleEl.style.pointerEvents = "none";
623
+ contentEl.append(ruleEl);
624
+ }
625
+ }
606
626
  /**
607
627
  * Render the footnote area at the bottom of a page.
608
628
  * Includes a separator line (33% width) and footnote entries.
@@ -612,11 +632,8 @@ function renderFootnoteArea(footnotes, contentWidth, doc, context) {
612
632
  container.className = "layout-footnote-area";
613
633
  container.style.width = `${contentWidth}px`;
614
634
  const separator = doc.createElement("div");
615
- const separatorRuleHeight = .5;
616
- const separatorMargin = (12 - separatorRuleHeight) / 2;
617
- separator.style.width = "33%";
618
- separator.style.height = `${separatorRuleHeight}px`;
619
- separator.style.backgroundColor = "var(--doc-canvas-text, #000)";
635
+ const separatorMargin = (12 - NOTE_SEPARATOR_RULE_THICKNESS) / 2;
636
+ applyNoteSeparatorRuleStyles(separator, contentWidth * NOTE_SEPARATOR_WIDTH_FRACTION);
620
637
  separator.style.marginTop = `${separatorMargin}px`;
621
638
  separator.style.marginBottom = `${separatorMargin}px`;
622
639
  container.append(separator);
@@ -674,7 +691,7 @@ function renderFootnoteContent(footnote, contentWidth, doc, context) {
674
691
  return wrapper;
675
692
  }
676
693
  function renderFootnoteBlock(block, measure, contentWidth, y, context, doc) {
677
- const renderBlock = stripFootnotePmAnchors(block);
694
+ const renderBlock = stripFlowBlockPmAnchors(block);
678
695
  if (renderBlock.kind === "paragraph" && measure.kind === "paragraph") {
679
696
  const element = renderParagraphFragment({
680
697
  kind: "paragraph",
@@ -732,81 +749,6 @@ function renderFootnoteBlock(block, measure, contentWidth, y, context, doc) {
732
749
  }
733
750
  return null;
734
751
  }
735
- function stripFootnotePmAnchors(block) {
736
- switch (block.kind) {
737
- case "paragraph": return stripFootnoteParagraphPmAnchors(block);
738
- case "table": return stripFootnoteTablePmAnchors(block);
739
- case "image": {
740
- const { pmStart: _pmStart, pmEnd: _pmEnd, ...image } = block;
741
- return image;
742
- }
743
- case "textBox": {
744
- const { pmStart: _pmStart, pmEnd: _pmEnd, ...textBox } = block;
745
- return {
746
- ...textBox,
747
- content: textBox.content.map((contentBlock) => contentBlock.kind === "table" ? stripFootnoteTablePmAnchors(contentBlock) : stripFootnoteParagraphPmAnchors(contentBlock))
748
- };
749
- }
750
- case "pageBreak":
751
- case "columnBreak": {
752
- const { pmStart: _pmStart, pmEnd: _pmEnd, ...breakBlock } = block;
753
- return breakBlock;
754
- }
755
- case "sectionBreak": return block;
756
- default: return block;
757
- }
758
- }
759
- function stripFootnoteTablePmAnchors(block) {
760
- const { pmStart: _pmStart, pmEnd: _pmEnd, ...table } = block;
761
- return {
762
- ...table,
763
- rows: table.rows.map(stripFootnoteTableRowPmAnchors)
764
- };
765
- }
766
- function stripFootnoteTableRowPmAnchors(row) {
767
- return {
768
- ...row,
769
- cells: row.cells.map(stripFootnoteTableCellPmAnchors)
770
- };
771
- }
772
- function stripFootnoteTableCellPmAnchors(cell) {
773
- return {
774
- ...cell,
775
- blocks: cell.blocks.map(stripFootnotePmAnchors)
776
- };
777
- }
778
- function stripFootnoteParagraphPmAnchors(block) {
779
- const { pmStart: _pmStart, pmEnd: _pmEnd, ...paragraph } = block;
780
- return {
781
- ...paragraph,
782
- runs: paragraph.runs.map(stripFootnoteRunPmAnchors)
783
- };
784
- }
785
- function stripFootnoteRunPmAnchors(run) {
786
- switch (run.kind) {
787
- case "text": {
788
- const { pmStart: _pmStart, pmEnd: _pmEnd, ...textRun } = run;
789
- return textRun;
790
- }
791
- case "tab": {
792
- const { pmStart: _pmStart, pmEnd: _pmEnd, ...tabRun } = run;
793
- return tabRun;
794
- }
795
- case "image": {
796
- const { pmStart: _pmStart, pmEnd: _pmEnd, ...imageRun } = run;
797
- return imageRun;
798
- }
799
- case "lineBreak": {
800
- const { pmStart: _pmStart, pmEnd: _pmEnd, ...lineBreakRun } = run;
801
- return lineBreakRun;
802
- }
803
- case "field": {
804
- const { pmStart: _pmStart, pmEnd: _pmEnd, ...fieldRun } = run;
805
- return fieldRun;
806
- }
807
- default: return run;
808
- }
809
- }
810
752
  function positionFootnoteBlock(element, top, width, height) {
811
753
  element.style.position = "absolute";
812
754
  element.style.left = "0";
@@ -1040,6 +982,11 @@ function renderPage(page, context, options = {}) {
1040
982
  left: page.margins.left,
1041
983
  top: page.margins.top
1042
984
  });
985
+ const noteStory = options.blockLookup?.get(String(fragment.blockId))?.noteStory;
986
+ if (noteStory) {
987
+ fragmentEl.dataset["noteKind"] = noteStory.kind;
988
+ fragmentEl.dataset["noteId"] = String(noteStory.noteId);
989
+ }
1043
990
  contentEl.append(fragmentEl);
1044
991
  }
1045
992
  if (frontFloatingImages.length > 0) {
@@ -1064,6 +1011,7 @@ function renderPage(page, context, options = {}) {
1064
1011
  contentEl.append(line);
1065
1012
  }
1066
1013
  }
1014
+ renderFlowedNoteSeparators(page, contentEl, doc);
1067
1015
  if (options.footnoteArea && options.footnoteArea.length > 0) {
1068
1016
  const fnAreaEl = renderFootnoteArea(options.footnoteArea, contentWidth, doc, context);
1069
1017
  fnAreaEl.style.position = "absolute";
@@ -1425,6 +1373,7 @@ function runContentKey(run) {
1425
1373
  if (run.forceComplexScript !== void 0) parts.push(`cs-force:${run.forceComplexScript}`);
1426
1374
  if (run.eastAsiaFontFamily) parts.push(`ea:${run.eastAsiaFontFamily}`);
1427
1375
  if (run.eastAsiaAlternateFontFamily) parts.push(`ea-alt:${run.eastAsiaAlternateFontFamily}`);
1376
+ if (run.eastAsiaHint !== void 0) parts.push(`ea-hint:${run.eastAsiaHint}`);
1428
1377
  if (run.fontSize !== void 0) parts.push(`fs:${run.fontSize}`);
1429
1378
  if (run.letterSpacing !== void 0) parts.push(`ls:${run.letterSpacing}`);
1430
1379
  if (run.superscript) parts.push("sup");
@@ -30,6 +30,11 @@ type RenderParagraphOptions = {
30
30
  renderedInlineImageKeys?: Set<string>;
31
31
  };
32
32
  declare function getRenderableTextColor(run: TextRun | TabRun): string | undefined;
33
+ /**
34
+ * The colour a list marker paints in, or undefined for the canvas text colour.
35
+ * Black and `auto` fall back to the canvas colour, as they do for runs.
36
+ */
37
+ declare function getRenderableListMarkerColor(color: string | undefined): string | undefined;
33
38
  /**
34
39
  * How CSS spells each bidirectional wrapper: an override switches the
35
40
  * bidirectional algorithm off for its content, an embedding opens a level and
@@ -147,4 +152,4 @@ declare const paragraphHasTrackedChanges: (block: ParagraphBlock) => boolean;
147
152
  */
148
153
  declare function renderParagraphFragment(fragment: ParagraphFragment, block: ParagraphBlock, measure: ParagraphMeasure, context: RenderContext, options?: RenderParagraphOptions): HTMLElement;
149
154
  //#endregion
150
- export { PARAGRAPH_CLASS_NAMES, RenderParagraphOptions, UNICODE_BIDI_BY_WRAPPER_CONTROL, getLeaderChar, getRenderableTextColor, paragraphHasTrackedChanges, renderLine, renderParagraphFragment, sliceRunsForLine, splitCollapsibleLineEdgeSpaces, splitTextRunsByEastAsia, startsAfterSoftWrap };
155
+ export { PARAGRAPH_CLASS_NAMES, RenderParagraphOptions, UNICODE_BIDI_BY_WRAPPER_CONTROL, getLeaderChar, getRenderableListMarkerColor, getRenderableTextColor, paragraphHasTrackedChanges, renderLine, renderParagraphFragment, sliceRunsForLine, splitCollapsibleLineEdgeSpaces, splitTextRunsByEastAsia, startsAfterSoftWrap };
@@ -4,7 +4,7 @@ import { evaluateFieldInstruction } from "../fields/evaluateField.js";
4
4
  import { applyComplexScriptFormatting, hasComplexScriptFormatting, resolveComplexScriptFormatting } from "../layout-engine/measure/complexScriptFormatting.js";
5
5
  import { getHyperlinkInstanceIndex } from "../layout-engine/measure/hyperlinkInstance.js";
6
6
  import { getListMarkerInlineWidth, getListMarkerVisualOffset, resolveListMarkerFont } from "../layout-engine/measure/listMarkerWidth.js";
7
- import { DOCX_SCRIPT_FONT_SCALE } from "../layout-engine/measure/measureHelpers.js";
7
+ import { DEFAULT_FONT_FAMILY, docxScriptFontSize } from "../layout-engine/measure/measureHelpers.js";
8
8
  import { calculateTabWidth } from "../layout-engine/measure/tabCalculator.js";
9
9
  import { FONT_KERNING_MODE, countCompressibleSpaces, getFontKerningMode, getRunFontKerningMode, toPaintedText } from "../layout-engine/measure/textMeasurementPolicy.js";
10
10
  import { isFloatingImageRun } from "../layout-engine/types.js";
@@ -17,7 +17,8 @@ import { getHorizontalScaleFactor } from "../utils/horizontalScale.js";
17
17
  import { resolvePhysicalParagraphInlineLayout } from "../utils/paragraphInlineLayout.js";
18
18
  import { inlineImageBoundingBox, parseRotationDegrees, rotatedBoundingBox } from "../utils/rotationBoundingBox.js";
19
19
  import { sanitizeImageSrc } from "../utils/sanitizeImageSrc.js";
20
- import { SCRIPT_CLASS, hasCjk, hasComplexScript, segmentByScript } from "../utils/scriptSegments.js";
20
+ import { SCRIPT_CLASS, eastAsiaHintApplies, hasComplexScript, hasEastAsiaSlotText, segmentByScript } from "../utils/scriptSegments.js";
21
+ import { trailingSpaceStart } from "../utils/trailingText.js";
21
22
  import { anchorTargetAttrs, sanitizeExternalUrl } from "../utils/urlSecurity.js";
22
23
  import { borderStrokeToCss, resolveParagraphBorderHorizontalOutsets } from "./borderStroke.js";
23
24
  import { planCursiveJoiners, withCursiveJoiners } from "./cursiveJoiners.js";
@@ -146,6 +147,14 @@ function getRenderableTextColor(run) {
146
147
  if (!shouldRenderTextColor(textColor, run.highlight, run.textColorSource)) return;
147
148
  return textColor.trim();
148
149
  }
150
+ /**
151
+ * The colour a list marker paints in, or undefined for the canvas text colour.
152
+ * Black and `auto` fall back to the canvas colour, as they do for runs.
153
+ */
154
+ function getRenderableListMarkerColor(color) {
155
+ if (!color || isAutomaticTextColor(color) || isDefaultBlackTextColor(color)) return;
156
+ return color.trim();
157
+ }
149
158
  function getHyperlinkTextColor(run, inheritedColor) {
150
159
  const textColor = run.color?.trim();
151
160
  if (textColor && !isAutomaticTextColor(textColor) && run.textColorSource === "direct") return textColor;
@@ -155,8 +164,7 @@ function fontSizePtToPx(fontSizePt) {
155
164
  return fontSizePt * 96 / 72;
156
165
  }
157
166
  function getRaisedRunFontSize(run) {
158
- if (run.fontSize) return `${fontSizePtToPx(run.fontSize) * DOCX_SCRIPT_FONT_SCALE}px`;
159
- return `${DOCX_SCRIPT_FONT_SCALE}em`;
167
+ return `${fontSizePtToPx(docxScriptFontSize(run.fontSize || 11))}px`;
160
168
  }
161
169
  function applyHorizontalScaleTransform(element, horizontalScale) {
162
170
  const horizontalScaleFactor = getHorizontalScaleFactor(horizontalScale);
@@ -717,7 +725,7 @@ function renderFieldRun(run, doc, { context, visualSpaceContractionPx }) {
717
725
  const horizontalScaleFactor = getHorizontalScaleFactor(resolvedRun.horizontalScale);
718
726
  applyHorizontalScaleTransform(wrapper, resolvedRun.horizontalScale);
719
727
  const { pmStart: _pmStart, pmEnd: _pmEnd, horizontalScale: _horizontalScale, ...segmentBase } = resolvedRun;
720
- for (const segment of segmentByScript(text)) {
728
+ for (const segment of segmentByScript(text, eastAsiaHintApplies(resolvedRun))) {
721
729
  const segmentRun = formatTextRunForScript({
722
730
  ...segmentBase,
723
731
  text: segment.text
@@ -864,7 +872,7 @@ const formatTextRunForScript = (run, script) => {
864
872
  */
865
873
  const needsPerScriptSpans = (run) => {
866
874
  if (run.letterSpacing) return false;
867
- if (run.eastAsiaFontFamily !== void 0 && hasCjk(run.text)) return true;
875
+ if (run.eastAsiaFontFamily !== void 0 && hasEastAsiaSlotText(run.text, eastAsiaHintApplies(run))) return true;
868
876
  return hasComplexScriptFormatting(run) && hasComplexScript(run.text);
869
877
  };
870
878
  /**
@@ -888,7 +896,7 @@ function splitTextRunsByEastAsia(runs) {
888
896
  continue;
889
897
  }
890
898
  let offset = 0;
891
- for (const segment of segmentByScript(run.text)) {
899
+ for (const segment of segmentByScript(run.text, eastAsiaHintApplies(run))) {
892
900
  result.push(formatTextRunForScript({
893
901
  ...run,
894
902
  text: segment.text,
@@ -933,13 +941,13 @@ const splitCollapsibleLineEdgeSpaces = (sourceRuns, collapseLeading) => {
933
941
  const run = runs[index];
934
942
  if (!run || !isTextRun(run)) break;
935
943
  if (run.text.length === 0) continue;
936
- const trailingSpaces = / +$/u.exec(run.text);
937
- if (!trailingSpaces || paintsLineEdgeSpaces(run)) break;
938
- if (trailingSpaces.index === 0) {
944
+ const spacesStart = trailingSpaceStart(run.text);
945
+ if (spacesStart === run.text.length || paintsLineEdgeSpaces(run)) break;
946
+ if (spacesStart === 0) {
939
947
  collapsedTrailingRuns.add(run);
940
948
  continue;
941
949
  }
942
- const [leading, trailing] = splitTextRunAt(run, trailingSpaces.index);
950
+ const [leading, trailing] = splitTextRunAt(run, spacesStart);
943
951
  runs.splice(index, 1, leading, trailing);
944
952
  collapsedTrailingRuns.add(trailing);
945
953
  break;
@@ -1005,6 +1013,7 @@ function runMeasureStyle(run) {
1005
1013
  ...run.alternateFontFamily !== void 0 ? { alternateFontFamily: run.alternateFontFamily } : {},
1006
1014
  ...run.eastAsiaFontFamily !== void 0 ? { eastAsiaFontFamily: run.eastAsiaFontFamily } : {},
1007
1015
  ...run.eastAsiaAlternateFontFamily !== void 0 ? { eastAsiaAlternateFontFamily: run.eastAsiaAlternateFontFamily } : {},
1016
+ ...eastAsiaHintApplies(run) ? { eastAsiaHint: true } : {},
1008
1017
  ...run.complexScriptFontFamily !== void 0 ? { complexScriptFontFamily: run.complexScriptFontFamily } : {},
1009
1018
  ...run.complexScriptAlternateFontFamily !== void 0 ? { complexScriptAlternateFontFamily: run.complexScriptAlternateFontFamily } : {},
1010
1019
  ...run.complexScriptFontSize !== void 0 ? { complexScriptFontSize: run.complexScriptFontSize } : {},
@@ -1028,10 +1037,10 @@ function measureFollowingContentWidth(runs, tabRunIndex, measureText, context) {
1028
1037
  if (isTabRun(run) || isLineBreakRun(run)) break;
1029
1038
  if (isTextRun(run)) {
1030
1039
  const text = run.allCaps ? run.text.toLocaleUpperCase() : run.text;
1031
- width += measureText(text, run.fontSize ?? 11, run.fontFamily ?? "Calibri", runMeasureStyle(run)) * getHorizontalScaleFactor(run.horizontalScale);
1040
+ width += measureText(text, run.fontSize ?? 11, run.fontFamily ?? "Times New Roman", runMeasureStyle(run)) * getHorizontalScaleFactor(run.horizontalScale);
1032
1041
  } else if (isFieldRun(run)) {
1033
1042
  const fieldText = resolveFieldText(run, context);
1034
- width += measureText(run.allCaps ? fieldText.toLocaleUpperCase() : fieldText, run.fontSize ?? 11, run.fontFamily ?? "Calibri", runMeasureStyle(run)) * getHorizontalScaleFactor(run.horizontalScale);
1043
+ width += measureText(run.allCaps ? fieldText.toLocaleUpperCase() : fieldText, run.fontSize ?? 11, run.fontFamily ?? "Times New Roman", runMeasureStyle(run)) * getHorizontalScaleFactor(run.horizontalScale);
1035
1044
  } else if (isImageRun(run) && !isFloatingImageRun(run)) width += inlineImageBoundingBox(run).width || 0;
1036
1045
  else if (isMathRun(run)) width += measureText(run.plainText, run.fontSize ?? 11, run.fontFamily ?? "Cambria Math", runMeasureStyle(run)) * getHorizontalScaleFactor(run.horizontalScale);
1037
1046
  }
@@ -1061,7 +1070,7 @@ function measureDecimalPrefixWidth(runs, tabRunIndex, decimalIndex, measureText,
1061
1070
  const take = Math.min(runText.length, decimalIndex - consumed);
1062
1071
  if (take > 0) {
1063
1072
  const horizontalScaleFactor = getHorizontalScaleFactor(run.horizontalScale);
1064
- width += measureText(runText.slice(0, take), run.fontSize ?? 11, run.fontFamily ?? "Calibri", runMeasureStyle(run)) * horizontalScaleFactor;
1073
+ width += measureText(runText.slice(0, take), run.fontSize ?? 11, run.fontFamily ?? "Times New Roman", runMeasureStyle(run)) * horizontalScaleFactor;
1065
1074
  }
1066
1075
  consumed += runText.length;
1067
1076
  }
@@ -1113,7 +1122,7 @@ function applyLetterSpacingToMeasuredWidth(width, text, letterSpacing) {
1113
1122
  }
1114
1123
  function createTextMeasurer(doc) {
1115
1124
  const ctx = doc.createElement("canvas").getContext("2d");
1116
- return (text, fontSize = 11, fontFamily = "Calibri", style = {}) => {
1125
+ return (text, fontSize = 11, fontFamily = DEFAULT_FONT_FAMILY, style = {}) => {
1117
1126
  if (!ctx) return applyLetterSpacingToMeasuredWidth(text.length * 7, text, style.letterSpacing);
1118
1127
  ctx.fontKerning = getFontKerningMode(style);
1119
1128
  const fontString = (family, size, bold, italic, alternateFamily) => {
@@ -1131,9 +1140,9 @@ function createTextMeasurer(doc) {
1131
1140
  ctx.font = complexFont;
1132
1141
  return applyLetterSpacingToMeasuredWidth(ctx.measureText(text).width, text, style.letterSpacing);
1133
1142
  }
1134
- if (!style.letterSpacing && (style.eastAsiaFontFamily && hasCjk(text) || hasComplexScriptFormatting(style) && hasComplexScript(text))) {
1143
+ if (!style.letterSpacing && (style.eastAsiaFontFamily && hasEastAsiaSlotText(text, style.eastAsiaHint) || hasComplexScriptFormatting(style) && hasComplexScript(text))) {
1135
1144
  let segmentedWidth = 0;
1136
- for (const segment of segmentByScript(text)) {
1145
+ for (const segment of segmentByScript(text, style.eastAsiaHint)) {
1137
1146
  if (segment.script === SCRIPT_CLASS.eastAsia && style.eastAsiaFontFamily) ctx.font = fontString(style.eastAsiaFontFamily, fontSize, style.bold, style.italic, style.eastAsiaAlternateFontFamily);
1138
1147
  else if (segment.script === SCRIPT_CLASS.complex) ctx.font = complexFont;
1139
1148
  else ctx.font = baseFont;
@@ -1189,7 +1198,7 @@ function renderLine(block, line, alignment, doc, options) {
1189
1198
  if (collapsedLeadingSpaceRuns.has(run)) runEl.dataset["collapsedLeadingSpaces"] = "true";
1190
1199
  if (collapsedTrailingSpaceRuns.has(run)) runEl.dataset["collapsedTrailingSpaces"] = "true";
1191
1200
  if (isCollapsedLineEdgeSpaceRun(run)) {
1192
- const spaceAdvance = (collapsedSpaceMeasureText?.(" ", run.fontSize || 11, run.fontFamily || "Calibri", runMeasureStyle(run)) ?? 0) * getHorizontalScaleFactor(run.horizontalScale);
1201
+ const spaceAdvance = (collapsedSpaceMeasureText?.(" ", run.fontSize || 11, run.fontFamily || "Times New Roman", runMeasureStyle(run)) ?? 0) * getHorizontalScaleFactor(run.horizontalScale);
1193
1202
  runEl.dataset["collapsedSpaceAdvance"] = String(spaceAdvance);
1194
1203
  runEl.style.fontSize = "0";
1195
1204
  runEl.style.letterSpacing = "0";
@@ -1340,7 +1349,8 @@ function renderLine(block, line, alignment, doc, options) {
1340
1349
  }
1341
1350
  let tabWidth = tabResult.width;
1342
1351
  const landsOnLeftIndent = tabResult.alignment === "start" && tabLeftIndentPx > 0 && Math.abs(currentX + tabWidth - tabLeftIndentPx) <= RIGHT_EDGE_EPSILON_PX;
1343
- if (!preservesAuthoredEndStop && !landsOnLeftIndent && lineRightEdgeX !== void 0 && canClampTabToRightEdge(tabResult.alignment, i > 0, runsForLine.slice(0, i).some(isTabRun), options?.isLastLine === true) && currentX + tabWidth + followingWidthForCheck > lineRightEdgeX) tabWidth = Math.max(1, lineRightEdgeX - currentX - followingWidthForCheck);
1352
+ const followingContentEndsOnLine = options?.isLastLine === true || runsForLine.slice(i + 1).some((next) => isTabRun(next) || isLineBreakRun(next));
1353
+ if (!(preservesAuthoredEndStop || activeContentRightEdge !== void 0 && tabResult.explicit === true && followingContentEndsOnLine && authoredEndpoint <= activeContentRightEdge + RIGHT_EDGE_EPSILON_PX) && !landsOnLeftIndent && lineRightEdgeX !== void 0 && canClampTabToRightEdge(tabResult.alignment, i > 0, runsForLine.slice(0, i).some(isTabRun), options?.isLastLine === true) && currentX + tabWidth + followingWidthForCheck > lineRightEdgeX) tabWidth = Math.max(1, lineRightEdgeX - currentX - followingWidthForCheck);
1344
1354
  const tabEl = renderTabRun(run, doc, tabWidth, tabResult.leader);
1345
1355
  lineEl.append(tabEl);
1346
1356
  currentX += tabWidth;
@@ -1350,7 +1360,7 @@ function renderLine(block, line, alignment, doc, options) {
1350
1360
  if (isCollapsedLineEdgeSpaceRun(run)) continue;
1351
1361
  if (!measureText) continue;
1352
1362
  const fontSize = run.fontSize || 11;
1353
- const fontFamily = run.fontFamily || "Calibri";
1363
+ const fontFamily = run.fontFamily || "Times New Roman";
1354
1364
  const measuredWidth = measureText(run.allCaps ? run.text.toLocaleUpperCase() : run.text, fontSize, fontFamily, runMeasureStyle(run));
1355
1365
  const runContractionPx = runVisualSpaceContraction({
1356
1366
  text: run.text,
@@ -1383,7 +1393,7 @@ function renderLine(block, line, alignment, doc, options) {
1383
1393
  if (!measureText) continue;
1384
1394
  const fieldText = resolveFieldText(run, options.context);
1385
1395
  const fontSize = run.fontSize || 11;
1386
- const fontFamily = run.fontFamily || "Calibri";
1396
+ const fontFamily = run.fontFamily || "Times New Roman";
1387
1397
  const measuredWidth = measureText(run.allCaps ? fieldText.toLocaleUpperCase() : fieldText, fontSize, fontFamily, runMeasureStyle(run));
1388
1398
  const runContractionPx = runVisualSpaceContraction({
1389
1399
  text: fieldText,
@@ -1628,6 +1638,8 @@ function renderListMarker({ marker, inlineWidth, visualOffset, doc, formatting,
1628
1638
  if (formatting.bold !== void 0) span.style.fontWeight = formatting.bold ? "700" : "normal";
1629
1639
  if (formatting.italic !== void 0) span.style.fontStyle = formatting.italic ? "italic" : "normal";
1630
1640
  if (formatting.rtl !== void 0) span.dir = formatting.rtl ? "rtl" : "ltr";
1641
+ const markerColor = revision ? void 0 : getRenderableListMarkerColor(formatting.color);
1642
+ if (markerColor) setAuthoredTextColor(span.style, markerColor);
1631
1643
  span.style.textAlign = physicalStart;
1632
1644
  span.style.textAlignLast = physicalStart;
1633
1645
  span.style.boxSizing = "border-box";
@@ -1673,4 +1685,4 @@ function renderListMarker({ marker, inlineWidth, visualOffset, doc, formatting,
1673
1685
  return span;
1674
1686
  }
1675
1687
  //#endregion
1676
- export { PARAGRAPH_CLASS_NAMES, UNICODE_BIDI_BY_WRAPPER_CONTROL, getLeaderChar, getRenderableTextColor, paragraphHasTrackedChanges, renderLine, renderParagraphFragment, sliceRunsForLine, splitCollapsibleLineEdgeSpaces, splitTextRunsByEastAsia, startsAfterSoftWrap };
1688
+ export { PARAGRAPH_CLASS_NAMES, UNICODE_BIDI_BY_WRAPPER_CONTROL, getLeaderChar, getRenderableListMarkerColor, getRenderableTextColor, paragraphHasTrackedChanges, renderLine, renderParagraphFragment, sliceRunsForLine, splitCollapsibleLineEdgeSpaces, splitTextRunsByEastAsia, startsAfterSoftWrap };
@@ -1,7 +1,7 @@
1
1
  import { measureParagraph } from "../layout-engine/measure/measureParagraph.js";
2
2
  import { buildTableCellFloatingZones, getTableCellContentWidth, getTableCellFloatingImages } from "../layout-engine/measure/tableCellFloating.js";
3
3
  import { createTableCellFlowState, finishTableCellFlow, placeTableCellBlock } from "../layout-engine/measure/tableCellFlow.js";
4
- import { buildTableCellGrid, buildTableCellPlacements, getSourceCellAt } from "../layout-engine/measure/tableCellGrid.js";
4
+ import { buildTableCellGrid, buildTableCellPlacements, getSourceCellAt, getTableCellSpacingInsetsY } from "../layout-engine/measure/tableCellGrid.js";
5
5
  import { tableFragmentBottomBorders } from "../layout-engine/measure/tableFragmentBorderGeometry.js";
6
6
  import { resolveTableInlineOffset, resolveTableInlinePlacement } from "../layout-engine/measure/tableInlinePlacement.js";
7
7
  import { isFloatingImageRun, isFloatingTextBoxBlock, resolveTableCellPadding, tableColumnsArePinned } from "../layout-engine/types.js";
@@ -293,7 +293,8 @@ function renderNestedTable(block, measure, context, doc, frameWidth = context.co
293
293
  const cellPlacements = buildTableCellPlacements({
294
294
  grid: cellGrid,
295
295
  columnWidths: measure.columnWidths,
296
- bidi: block.bidi === true
296
+ bidi: block.bidi === true,
297
+ cellSpacing: block.cellSpacing
297
298
  });
298
299
  let y = 0;
299
300
  for (let rowIndex = 0; rowIndex < block.rows.length; rowIndex++) {
@@ -318,6 +319,7 @@ function renderNestedTable(block, measure, context, doc, frameWidth = context.co
318
319
  columnsPinned,
319
320
  cellGrid,
320
321
  cellPlacements,
322
+ cellSpacing: block.cellSpacing,
321
323
  inlineOffset: resolveTableInlineOffset({
322
324
  table: block,
323
325
  rowJustification: row.justification,
@@ -375,12 +377,12 @@ function renderCellDiagonalBorder({ border, direction, cellWidth, cellHeight, do
375
377
  }
376
378
  return line;
377
379
  }
378
- function renderTableCell({ cell, cellMeasure, x, width, rowHeight, borderFlags, columnsPinned, context, doc, contentClip, pageContentPosition }) {
380
+ function renderTableCell({ cell, cellMeasure, x, y = 0, width, rowHeight, borderFlags, columnsPinned, context, doc, contentClip, pageContentPosition }) {
379
381
  const cellEl = doc.createElement("div");
380
382
  cellEl.className = TABLE_CLASS_NAMES.cell;
381
383
  cellEl.style.position = "absolute";
382
384
  cellEl.style.left = `${x}px`;
383
- cellEl.style.top = "0";
385
+ cellEl.style.top = `${y}px`;
384
386
  cellEl.style.width = `${width}px`;
385
387
  cellEl.style.height = `${rowHeight}px`;
386
388
  cellEl.style.overflow = "hidden";
@@ -499,7 +501,8 @@ const continuationRowBottomBorderOffsets = (fragment, block, measure, cellGrid)
499
501
  snapAfterRow
500
502
  });
501
503
  };
502
- function renderTableRow({ row, rowMeasure, rowIndex, y, columnWidths, totalRows, context, doc, rowYPositions, isFirstRowInFragment, bidi = false, columnsPinned = false, cellGrid, cellPlacements, contentClip, pageContentPosition, inlineOffset = 0, bottomBorderOffset = 0 }) {
504
+ function renderTableRow({ row, rowMeasure, rowIndex, y, columnWidths, totalRows, context, doc, rowYPositions, isFirstRowInFragment, bidi = false, columnsPinned = false, cellGrid, cellPlacements, cellSpacing, contentClip, pageContentPosition, inlineOffset = 0, bottomBorderOffset = 0 }) {
505
+ const bordersSeparated = (cellSpacing ?? 0) > 0;
503
506
  const rowEl = doc.createElement("div");
504
507
  rowEl.className = TABLE_CLASS_NAMES.row;
505
508
  rowEl.style.position = "absolute";
@@ -530,15 +533,22 @@ function renderTableRow({ row, rowMeasure, rowIndex, y, columnWidths, totalRows,
530
533
  const isLastCol = bidi ? atLogicalStart : atLogicalEnd;
531
534
  const aboveCell = getSourceCellAt(cellGrid, rowIndex - 1, columnIndex);
532
535
  const leftCell = getSourceCellAt(cellGrid, rowIndex, bidi ? columnIndex + colSpan : columnIndex - 1);
533
- const drawTop = isFirstRow || !hasVisibleBorder(aboveCell?.borders?.bottom);
534
- const drawLeft = isFirstCol || !hasVisibleBorder(leftCell?.borders?.right);
536
+ const drawTop = bordersSeparated || isFirstRow || !hasVisibleBorder(aboveCell?.borders?.bottom);
537
+ const drawLeft = bordersSeparated || isFirstCol || !hasVisibleBorder(leftCell?.borders?.right);
538
+ const spacing = getTableCellSpacingInsetsY(cellSpacing, rowIndex, rowSpan, totalRows);
539
+ const boxHeight = Math.max(0, cellHeight - spacing.top - spacing.bottom);
540
+ const boxClip = contentClip ? {
541
+ top: contentClip.top - spacing.top,
542
+ bottom: contentClip.bottom - spacing.top
543
+ } : void 0;
535
544
  const paintBottomBorderSeparately = bottomBorderOffset > 0 && hasVisibleBorder(cell.borders?.bottom);
536
545
  const cellEl = renderTableCell({
537
546
  cell,
538
547
  cellMeasure,
539
548
  x: cellLeft,
549
+ y: spacing.top,
540
550
  width,
541
- rowHeight: cellHeight,
551
+ rowHeight: boxHeight,
542
552
  borderFlags: {
543
553
  drawTop,
544
554
  drawBottom: !paintBottomBorderSeparately,
@@ -549,11 +559,11 @@ function renderTableRow({ row, rowMeasure, rowIndex, y, columnWidths, totalRows,
549
559
  columnsPinned,
550
560
  context,
551
561
  doc,
552
- ...contentClip ? { contentClip } : {},
562
+ ...boxClip ? { contentClip: boxClip } : {},
553
563
  ...pageContentPosition ? { pageContentPosition: {
554
564
  geometry: pageContentPosition.geometry,
555
565
  x: pageContentPosition.x + inlineOffset + cellLeft,
556
- y: pageContentPosition.y
566
+ y: pageContentPosition.y + spacing.top
557
567
  } } : {}
558
568
  });
559
569
  cellEl.dataset["cellIndex"] = String(cellIndex);
@@ -565,9 +575,9 @@ function renderTableRow({ row, rowMeasure, rowIndex, y, columnWidths, totalRows,
565
575
  bottomBorderEl.className = CELL_BOTTOM_BORDER_CLASS;
566
576
  bottomBorderEl.style.position = "absolute";
567
577
  bottomBorderEl.style.left = `${cellLeft}px`;
568
- bottomBorderEl.style.top = "0";
578
+ bottomBorderEl.style.top = `${spacing.top}px`;
569
579
  bottomBorderEl.style.width = `${width}px`;
570
- bottomBorderEl.style.height = `${cellHeight + bottomBorderOffset}px`;
580
+ bottomBorderEl.style.height = `${boxHeight + bottomBorderOffset}px`;
571
581
  bottomBorderEl.style.boxSizing = "border-box";
572
582
  bottomBorderEl.style.pointerEvents = "none";
573
583
  bottomBorderEl.style.zIndex = "1";
@@ -637,7 +647,8 @@ function renderTableFragment(fragment, block, measure, context, options = {}) {
637
647
  const cellPlacements = buildTableCellPlacements({
638
648
  grid: cellGrid,
639
649
  columnWidths: measure.columnWidths,
640
- bidi: block.bidi === true
650
+ bidi: block.bidi === true,
651
+ cellSpacing: block.cellSpacing
641
652
  });
642
653
  const contentRowBottomBorderOffsets = continuationRowBottomBorderOffsets(fragment, block, measure, cellGrid);
643
654
  const headerRowCount = fragment.headerRowCount ?? 0;
@@ -665,6 +676,7 @@ function renderTableFragment(fragment, block, measure, context, options = {}) {
665
676
  columnsPinned,
666
677
  cellGrid,
667
678
  cellPlacements,
679
+ cellSpacing: block.cellSpacing,
668
680
  ...tablePageContentPosition ? { pageContentPosition: {
669
681
  ...tablePageContentPosition,
670
682
  y: tablePageContentPosition.y + y
@@ -718,6 +730,7 @@ function renderTableFragment(fragment, block, measure, context, options = {}) {
718
730
  columnsPinned,
719
731
  cellGrid,
720
732
  cellPlacements,
733
+ cellSpacing: block.cellSpacing,
721
734
  bottomBorderOffset: contentRowBottomBorderOffsets[rowIndex - fragment.fromRow] ?? 0,
722
735
  ...contentClip ? { contentClip } : {},
723
736
  ...tablePageContentPosition ? { pageContentPosition: {
@@ -4,18 +4,18 @@ import "../schema/index.js";
4
4
  import { Mark, Node } from "prosemirror-model";
5
5
  //#region src/prosemirror/attrs/index.d.ts
6
6
  type ProseMirrorAttrIssue = {
7
- path: string;
8
- message: string;
7
+ readonly path: string;
8
+ readonly message: string;
9
9
  };
10
10
  type ReadProseMirrorAttrsResult<T> = {
11
11
  ok: true;
12
12
  value: T;
13
13
  } | {
14
14
  ok: false;
15
- issues: ProseMirrorAttrIssue[];
15
+ issues: readonly ProseMirrorAttrIssue[];
16
16
  };
17
- declare const readParagraphAttrs: (node: Node) => ReadProseMirrorAttrsResult<ParagraphAttrs>;
18
- declare const expectParagraphAttrs: (node: Node) => ParagraphAttrs;
17
+ declare const readParagraphAttrs: (node: Node) => ReadProseMirrorAttrsResult<Readonly<ParagraphAttrs>>;
18
+ declare const expectParagraphAttrs: (node: Node) => Readonly<ParagraphAttrs>;
19
19
  declare const readHardBreakAttrs: (node: Node) => ReadProseMirrorAttrsResult<HardBreakAttrs>;
20
20
  declare const expectHardBreakAttrs: (node: Node) => HardBreakAttrs;
21
21
  declare const readPageBreakRunAttrs: (node: Node) => ReadProseMirrorAttrsResult<PageBreakRunAttrs>;
@@ -28,10 +28,10 @@ declare const readPreservedXmlAttrs: (node: Node) => ReadProseMirrorAttrsResult<
28
28
  declare const expectPreservedXmlAttrs: (node: Node) => PreservedXmlAttrs;
29
29
  declare const readPreservedBlockAttrs: (node: Node) => ReadProseMirrorAttrsResult<PreservedBlockAttrs>;
30
30
  declare const expectPreservedBlockAttrs: (node: Node) => PreservedBlockAttrs;
31
- declare const readTableAttrs: (node: Node) => ReadProseMirrorAttrsResult<TableAttrs>;
32
- declare const expectTableAttrs: (node: Node) => TableAttrs;
33
- declare const readTableRowAttrs: (node: Node) => ReadProseMirrorAttrsResult<TableRowAttrs>;
34
- declare const expectTableRowAttrs: (node: Node) => TableRowAttrs;
31
+ declare const readTableAttrs: (node: Node) => ReadProseMirrorAttrsResult<Readonly<TableAttrs>>;
32
+ declare const expectTableAttrs: (node: Node) => Readonly<TableAttrs>;
33
+ declare const readTableRowAttrs: (node: Node) => ReadProseMirrorAttrsResult<Readonly<TableRowAttrs>>;
34
+ declare const expectTableRowAttrs: (node: Node) => Readonly<TableRowAttrs>;
35
35
  declare const readTableCellAttrs: (node: Node) => ReadProseMirrorAttrsResult<TableCellAttrs>;
36
36
  declare const expectTableCellAttrs: (node: Node) => TableCellAttrs;
37
37
  declare const readImageAttrs: (node: Node) => ReadProseMirrorAttrsResult<ImageAttrs>;