@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,4 +1,5 @@
1
1
  import { buildFontAlternates, getFontAlternate } from "../fonts/fontAlternates.js";
2
+ import { DEFAULT_FONT_FAMILY } from "../layout-engine/measure/measureHelpers.js";
2
3
  import { expectFontFamilyMarkAttrs, expectParagraphAttrs } from "../prosemirror/attrs/index.js";
3
4
  import { parseFontFamilyList, resolveFontFamily } from "../utils/fontResolver.js";
4
5
  //#region src/controller/fontReadiness.ts
@@ -11,7 +12,6 @@ function documentFontsAreLoaded() {
11
12
  return !fontSet || fontSet.status === "loaded";
12
13
  }
13
14
  const INITIAL_LAYOUT_FONT_TIMEOUT_MS = 2e3;
14
- const DEFAULT_LAYOUT_FONT_FAMILY = "Calibri";
15
15
  const CSS_GENERIC_FONT_FAMILIES = /* @__PURE__ */ new Set([
16
16
  "serif",
17
17
  "sans-serif",
@@ -54,7 +54,7 @@ function collectInitialLayoutFontFamilies(documentModel, pmDoc) {
54
54
  function collectInitialLayoutFontFaces(documentModel, pmDoc) {
55
55
  const faces = /* @__PURE__ */ new Map();
56
56
  const fontAlternates = buildFontAlternates(documentModel?.package.fontTable);
57
- addLayoutFontFamilyFace(faces, DEFAULT_LAYOUT_FONT_FAMILY, REGULAR_LAYOUT_FONT_DESCRIPTOR, fontAlternates);
57
+ addLayoutFontFamilyFace(faces, DEFAULT_FONT_FAMILY, REGULAR_LAYOUT_FONT_DESCRIPTOR, fontAlternates);
58
58
  for (const family of documentModel?.requiredFonts ?? []) addLayoutFontFamilyFace(faces, family, REGULAR_LAYOUT_FONT_DESCRIPTOR, fontAlternates);
59
59
  addLayoutFontFamilyFace(faces, documentModel?.package.theme?.fontScheme?.majorFont?.latin, REGULAR_LAYOUT_FONT_DESCRIPTOR, fontAlternates);
60
60
  addLayoutFontFamilyFace(faces, documentModel?.package.theme?.fontScheme?.minorFont?.latin, REGULAR_LAYOUT_FONT_DESCRIPTOR, fontAlternates);
@@ -75,7 +75,7 @@ function collectProseMirrorFontFaces(faces, node, inheritedTextFormatting, fontA
75
75
  if (node.type.name === "paragraph") addTextFormattingFontFaces(faces, expectParagraphAttrs(node).listMarkerFormatting, fontAlternates);
76
76
  if (node.isText) {
77
77
  const descriptor = layoutDescriptorFromFormattingAndMarks(textFormatting, node.marks);
78
- addLayoutFontFamilyFace(faces, readFontFamilyMarkAttrs(node.marks) ?? textFormatting?.fontFamily ?? DEFAULT_LAYOUT_FONT_FAMILY, descriptor, fontAlternates);
78
+ addLayoutFontFamilyFace(faces, readFontFamilyMarkAttrs(node.marks) ?? textFormatting?.fontFamily ?? "Times New Roman", descriptor, fontAlternates);
79
79
  }
80
80
  node.forEach((child) => {
81
81
  collectProseMirrorFontFaces(faces, child, textFormatting, fontAlternates);
@@ -0,0 +1,19 @@
1
+ import { HyphenationDictionaryError, HyphenationDictionaryId } from "../layout-engine/measure/hyphenationDictionaries.js";
2
+ //#region src/controller/hyphenationReadiness.d.ts
3
+ type HyphenationReadiness = {
4
+ /** Follow up on the dictionaries one layout run lacked. */
5
+ track: (missing: ReadonlySet<HyphenationDictionaryId>) => void;
6
+ /**
7
+ * Ignore loads still pending, as on unmount. A later `track` follows up
8
+ * afresh, so an adapter whose lifecycle re-attaches (React Strict Mode
9
+ * effects) keeps working.
10
+ */
11
+ cancel: () => void;
12
+ };
13
+ type HyphenationReadinessOptions = {
14
+ relayout: () => void;
15
+ onError: (error: HyphenationDictionaryError) => void;
16
+ };
17
+ declare const createHyphenationReadiness: ({ relayout, onError }: HyphenationReadinessOptions) => HyphenationReadiness;
18
+ //#endregion
19
+ export { HyphenationReadiness, HyphenationReadinessOptions, createHyphenationReadiness };
@@ -0,0 +1,47 @@
1
+ import { requestHyphenationDictionary } from "../layout-engine/measure/hyphenationDictionaries.js";
2
+ //#region src/controller/hyphenationReadiness.ts
3
+ /**
4
+ * Per-editor follow-up for hyphenation dictionaries a layout run lacked.
5
+ *
6
+ * Framework-neutral so both adapters share one implementation. The layout
7
+ * pipeline hands {@link HyphenationReadiness.track} the dictionaries its run
8
+ * requested but could not use; this editor then re-runs layout when one loads
9
+ * (the load has already invalidated measured paragraphs) and reports a failed
10
+ * one once. Editors that never asked for a dictionary hear nothing about it,
11
+ * and an editor mounted after a failure still learns of it on its first run.
12
+ */
13
+ const createHyphenationReadiness = ({ relayout, onError }) => {
14
+ let epoch = 0;
15
+ const pending = /* @__PURE__ */ new Set();
16
+ const reported = /* @__PURE__ */ new Set();
17
+ const follow = async (dictionary) => {
18
+ const startedIn = epoch;
19
+ pending.add(dictionary);
20
+ const settled = await requestHyphenationDictionary(dictionary);
21
+ if (startedIn !== epoch) return;
22
+ pending.delete(dictionary);
23
+ switch (settled.status) {
24
+ case "loaded":
25
+ relayout();
26
+ return;
27
+ case "failed":
28
+ if (!reported.has(dictionary)) {
29
+ reported.add(dictionary);
30
+ onError(settled.error);
31
+ }
32
+ return;
33
+ default:
34
+ }
35
+ };
36
+ return {
37
+ track: (missing) => {
38
+ for (const dictionary of missing) if (!pending.has(dictionary)) follow(dictionary);
39
+ },
40
+ cancel: () => {
41
+ epoch += 1;
42
+ pending.clear();
43
+ }
44
+ };
45
+ };
46
+ //#endregion
47
+ export { createHyphenationReadiness };
@@ -3,6 +3,7 @@ import { TemplatePreviewEntry, TemplatePreviewHiddenRange } from "../prosemirror
3
3
  import { ColumnLayout, FlowBlock, FootnoteContent, HeaderFooterContent, Layout, Measure, PageHeaderFooterRefs, PageMargins } from "../layout-engine/types.js";
4
4
  import { LayoutRunReason } from "../layout-engine/layoutInstrumentation.js";
5
5
  import { DirtyRange } from "../paged-layout/incrementalMeasure.js";
6
+ import { HyphenationReadiness } from "./hyphenationReadiness.js";
6
7
  import { ConvertHeaderFooterOptions, HeaderFooterMetrics } from "../layout-bridge/convert/headerFooterLayout.js";
7
8
  import "../layout-engine/index.js";
8
9
  import { FootnoteRenderItem } from "../layout-painter/renderPage.js";
@@ -74,6 +75,8 @@ type LayoutPipelineDeps<THfPMs> = {
74
75
  pageRenderer?: PageRendererName;
75
76
  emptyTemplatePreviewEntries: readonly TemplatePreviewEntry[];
76
77
  emptyTemplatePreviewHidden: readonly TemplatePreviewHiddenRange[];
78
+ /** Follows up on the hyphenation dictionaries a run lacked (relayout or error). */
79
+ hyphenationReadiness: HyphenationReadiness;
77
80
  };
78
81
  declare function runLayoutPipeline<THfPMs>(deps: LayoutPipelineDeps<THfPMs>, state: EditorState, options?: LayoutRunOptions): LayoutOutcome;
79
82
  //#endregion
@@ -9,13 +9,16 @@ import { buildHeaderFooterFieldValues, fieldValuesEqual, resolveFieldValues } fr
9
9
  import { buildSectionPageCounts } from "../fields/sectionPageCounts.js";
10
10
  import { buildSeqValues } from "../fields/seqValues.js";
11
11
  import { buildFontAlternates } from "../fonts/fontAlternates.js";
12
+ import { prepareEndnoteAreas, resolveEndnotePosition, spliceEndnoteAreas, trailingEndnoteIds } from "../layout-bridge/convert/endnoteLayout.js";
12
13
  import { buildFootnoteContentMap, collectEndnoteRefs, collectFootnoteRefs, computeNoteDisplayNumbers, remapNoteMarkerText } from "../layout-bridge/convert/footnoteLayout.js";
13
14
  import { applyTemplatePreviewToBlocks } from "../layout-bridge/convert/templatePreviewFlow.js";
14
15
  import { toFlowBlocks } from "../layout-bridge/convert/toFlowBlocks.js";
15
16
  import { getColumns } from "../layout-bridge/sectionColumns.js";
17
+ import { resolveAnchorLayoutInCellCompatibility } from "../layout-engine/anchorLayoutInCellCompatibility.js";
16
18
  import { layoutDocument } from "../layout-engine/index.js";
17
19
  import { resolveJustificationCompatibility } from "../layout-engine/justificationCompatibility.js";
18
20
  import { recordLayoutComplete, recordLayoutError, recordLayoutPhase, recordLayoutStart } from "../layout-engine/layoutInstrumentation.js";
21
+ import { collectRequestedHyphenationDictionaries } from "../layout-engine/measure/hyphenationDictionaries.js";
19
22
  import { measureBlocks, measureSingleBlockWithoutFloatingZones } from "../layout-engine/measure/measureBlocks.js";
20
23
  import { installCanvasMeasureProvider } from "../layout-engine/measure/measureContainer.js";
21
24
  import { resolveEffectiveParagraphSpacingTree } from "../layout-engine/paragraphSpacing.js";
@@ -100,6 +103,11 @@ function attachAuthoredMarginsToLayoutPages(layout, options) {
100
103
  } : layout;
101
104
  }
102
105
  function runLayoutPipeline(deps, state, options = {}) {
106
+ const { result, missing } = collectRequestedHyphenationDictionaries(() => runLayoutPipelineMeasured(deps, state, options));
107
+ deps.hyphenationReadiness.track(missing);
108
+ return result;
109
+ }
110
+ function runLayoutPipelineMeasured(deps, state, options) {
103
111
  const { contentWidth, columns, pageSize, margins, pageGap, showMarginGuides, marginGuideColor, syncCoordinator, headerContent, footerContent, firstPageHeaderContent, firstPageFooterContent, headerContentRId, footerContentRId, firstPageHeaderContentRId, firstPageFooterContentRId, sectionHeaderFooterRefs, theme: _theme, sectionProperties, document, defaultTabStop, mirrorMargins, styles, layout, hfPMs, painter, pagesContainer, session, renderHfFromContentOrPm, renderHeaderFooterContentByRId, documentFontsAreLoaded, buildFootnoteRenderItems, describeInvalidHighlightMarks, pageRenderer = PAGE_RENDERER.legacy, emptyTemplatePreviewEntries: EMPTY_TEMPLATE_PREVIEW_ENTRIES, emptyTemplatePreviewHidden: EMPTY_TEMPLATE_PREVIEW_HIDDEN } = deps;
104
112
  let outcome = {};
105
113
  let pendingArtifacts;
@@ -131,6 +139,7 @@ function runLayoutPipeline(deps, state, options = {}) {
131
139
  if (justificationCompatibility) flowOpts.justificationCompatibility = justificationCompatibility;
132
140
  const tableIndentCompatibility = resolveTableIndentCompatibility(documentSettings?.compatibilityMode);
133
141
  if (tableIndentCompatibility) flowOpts.tableIndentCompatibility = tableIndentCompatibility;
142
+ if (resolveAnchorLayoutInCellCompatibility(documentSettings?.compatibilityMode)) flowOpts.forceAnchorLayoutInCell = true;
134
143
  if (documentSettings?.autoHyphenation === true) flowOpts.automaticHyphenation = {
135
144
  enabled: true,
136
145
  ...documentSettings.doNotHyphenateCaps !== void 0 ? { doNotHyphenateCaps: documentSettings.doNotHyphenateCaps } : {},
@@ -139,6 +148,9 @@ function runLayoutPipeline(deps, state, options = {}) {
139
148
  };
140
149
  const finalSectionDocumentGridLinePitchTwips = resolveDocumentGridLinePitch(document?.package.document.sections?.at(-1)?.properties.docGrid);
141
150
  if (finalSectionDocumentGridLinePitchTwips !== void 0) flowOpts.finalSectionDocumentGridLinePitchTwips = finalSectionDocumentGridLinePitchTwips;
151
+ const endnotePosition = resolveEndnotePosition(document?.package.settings?.endnotePr?.position, document?.package.document.sections?.at(-1)?.properties);
152
+ const bodyTrailingEndnoteIds = trailingEndnoteIds(document?.package.endnotes, endnotePosition);
153
+ if (bodyTrailingEndnoteIds.size > 0) flowOpts.trailingEndnoteIds = bodyTrailingEndnoteIds;
142
154
  let newBlocks = toFlowBlocks(document === null ? state.doc.type.create({
143
155
  ...state.doc.attrs,
144
156
  _finalSectionStart: sectionProperties?.sectionStart ?? null
@@ -166,7 +178,7 @@ function runLayoutPipeline(deps, state, options = {}) {
166
178
  const footnoteDisplayNumbers = documentFootnotes ? computeNoteDisplayNumbers(documentFootnotes, footnoteRefs.map((ref) => ref.footnoteId)) : void 0;
167
179
  const documentEndnotes = document?.package.endnotes;
168
180
  const endnoteDisplayNumbers = documentEndnotes ? computeNoteDisplayNumbers(documentEndnotes, collectEndnoteRefs(newBlocks).map((ref) => ref.endnoteId)) : void 0;
169
- const endnoteNumberFormat = document?.package.document.sections?.at(-1)?.properties.endnotePr?.numFmt ?? "lowerRoman";
181
+ const endnoteNumberFormat = document?.package.document.sections?.at(-1)?.properties.endnotePr?.numFmt ?? document?.package.settings?.endnotePr?.numFmt ?? "lowerRoman";
170
182
  const endnoteTexts = endnoteDisplayNumbers ? formatEndnoteTexts(endnoteDisplayNumbers, (displayNumber) => formatOoxmlCounter(displayNumber, endnoteNumberFormat)) : void 0;
171
183
  newBlocks = remapNoteMarkerText(newBlocks, {
172
184
  ...footnoteDisplayNumbers ? { footnoteNumbers: footnoteDisplayNumbers } : {},
@@ -302,6 +314,36 @@ function runLayoutPipeline(deps, state, options = {}) {
302
314
  };
303
315
  outcome.measures = newMeasures;
304
316
  recordPhaseDuration("measure-blocks", phaseStartedAt);
317
+ const buildNoteOptions = () => {
318
+ const noteOptions = { measureBlocks };
319
+ if (flowOpts.styles) noteOptions.styles = flowOpts.styles;
320
+ if (flowOpts.defaultSize !== void 0) noteOptions.defaultSize = flowOpts.defaultSize;
321
+ if (_theme !== void 0) noteOptions.theme = _theme;
322
+ noteOptions.fontAlternates = fontAlternates;
323
+ if (defaultTabStop !== void 0) noteOptions.defaultTabStopTwips = defaultTabStop;
324
+ if (flowOpts.lineBreakRules) noteOptions.lineBreakRules = flowOpts.lineBreakRules;
325
+ if (flowOpts.justificationCompatibility) noteOptions.justificationCompatibility = flowOpts.justificationCompatibility;
326
+ if (flowOpts.tableIndentCompatibility) noteOptions.tableIndentCompatibility = flowOpts.tableIndentCompatibility;
327
+ if (flowOpts.automaticHyphenation) noteOptions.automaticHyphenation = flowOpts.automaticHyphenation;
328
+ return noteOptions;
329
+ };
330
+ const endnoteAreas = documentEndnotes && endnoteDisplayNumbers && endnoteTexts ? prepareEndnoteAreas({
331
+ blocks: newBlocks,
332
+ endnotes: documentEndnotes,
333
+ displayNumbers: endnoteDisplayNumbers,
334
+ displayTexts: endnoteTexts,
335
+ position: endnotePosition,
336
+ sections: sectionPropertiesForMargins,
337
+ options: buildNoteOptions()
338
+ }) : void 0;
339
+ const layoutWithNoteAreas = (measures, nextLayoutOpts) => {
340
+ if (endnoteAreas === void 0) return layoutDocument(newBlocks, measures, nextLayoutOpts);
341
+ const flow = spliceEndnoteAreas(newBlocks, measures, endnoteAreas);
342
+ return layoutDocument(flow.blocks, flow.measures, {
343
+ ...nextLayoutOpts,
344
+ noteAreas: endnoteAreas.noteAreas
345
+ });
346
+ };
305
347
  phaseStartedAt = performance.now();
306
348
  let newLayout;
307
349
  let pageFootnoteMap = /* @__PURE__ */ new Map();
@@ -338,29 +380,17 @@ function runLayoutPipeline(deps, state, options = {}) {
338
380
  const layoutOpts = buildLayoutOpts();
339
381
  let layoutOptsUsed = layoutOpts;
340
382
  if (hasFootnotes) {
341
- footnoteContentMap = buildFootnoteContentMap(documentFootnotes, footnoteRefs, contentWidth, (() => {
342
- const footnoteOptions = { measureBlocks };
343
- if (flowOpts.styles) footnoteOptions.styles = flowOpts.styles;
344
- if (flowOpts.defaultSize !== void 0) footnoteOptions.defaultSize = flowOpts.defaultSize;
345
- if (_theme !== void 0) footnoteOptions.theme = _theme;
346
- footnoteOptions.fontAlternates = fontAlternates;
347
- if (defaultTabStop !== void 0) footnoteOptions.defaultTabStopTwips = defaultTabStop;
348
- if (flowOpts.lineBreakRules) footnoteOptions.lineBreakRules = flowOpts.lineBreakRules;
349
- if (flowOpts.justificationCompatibility) footnoteOptions.justificationCompatibility = flowOpts.justificationCompatibility;
350
- if (flowOpts.tableIndentCompatibility) footnoteOptions.tableIndentCompatibility = flowOpts.tableIndentCompatibility;
351
- if (flowOpts.automaticHyphenation) footnoteOptions.automaticHyphenation = flowOpts.automaticHyphenation;
352
- return footnoteOptions;
353
- })());
383
+ footnoteContentMap = buildFootnoteContentMap(documentFootnotes, footnoteRefs, contentWidth, buildNoteOptions());
354
384
  const footnoteHeightById = /* @__PURE__ */ new Map();
355
385
  for (const [id, content] of footnoteContentMap) footnoteHeightById.set(id, content.height + 0);
356
386
  layoutOptsUsed = {
357
387
  ...layoutOpts,
358
388
  footnoteHeightById
359
389
  };
360
- newLayout = layoutDocument(newBlocks, newMeasures, layoutOptsUsed);
390
+ newLayout = layoutWithNoteAreas(newMeasures, layoutOptsUsed);
361
391
  pageFootnoteMap = /* @__PURE__ */ new Map();
362
392
  for (const page of newLayout.pages) if (page.footnoteIds && page.footnoteIds.length > 0) pageFootnoteMap.set(page.number, page.footnoteIds);
363
- } else newLayout = layoutDocument(newBlocks, newMeasures, layoutOpts);
393
+ } else newLayout = layoutWithNoteAreas(newMeasures, layoutOpts);
364
394
  const rebuildFootnotePageMap = () => {
365
395
  pageFootnoteMap = /* @__PURE__ */ new Map();
366
396
  for (const page of newLayout.pages) if (page.footnoteIds && page.footnoteIds.length > 0) pageFootnoteMap.set(page.number, page.footnoteIds);
@@ -376,7 +406,7 @@ function runLayoutPipeline(deps, state, options = {}) {
376
406
  };
377
407
  const relayoutWithCurrentMeasures = (nextLayoutOpts) => {
378
408
  layoutOptsUsed = withFootnoteHeights(nextLayoutOpts);
379
- newLayout = layoutDocument(newBlocks, newMeasures, layoutOptsUsed);
409
+ newLayout = layoutWithNoteAreas(newMeasures, layoutOptsUsed);
380
410
  if (hasFootnotes) rebuildFootnotePageMap();
381
411
  };
382
412
  const stabilizeFieldWidths = () => {
@@ -473,6 +503,18 @@ function runLayoutPipeline(deps, state, options = {}) {
473
503
  measure
474
504
  });
475
505
  }
506
+ for (const area of endnoteAreas?.areas ?? []) for (const [index, block] of area.blocks.entries()) {
507
+ const measure = area.measures[index];
508
+ if (!measure) continue;
509
+ const noteStory = endnoteAreas?.noteStoryByBlockId.get(String(block.id));
510
+ blockLookup.set(String(block.id), {
511
+ block,
512
+ measure,
513
+ ...noteStory === void 0 ? {} : { noteStory }
514
+ });
515
+ }
516
+ const continuationSeparator = endnoteAreas?.noteAreas.continuationSeparator;
517
+ if (continuationSeparator) blockLookup.set(String(continuationSeparator.block.id), continuationSeparator);
476
518
  outcome.blockLookup = blockLookup;
477
519
  const footnotesByPage = hasFootnotes ? buildFootnoteRenderItems(pageFootnoteMap, footnoteContentMap, document) : void 0;
478
520
  const renderOpts = {
@@ -5,7 +5,7 @@ import { collectFloatingImages, pageGeometryOf } from "./floatingImages.js";
5
5
  import { FontTable } from "./fontTable.js";
6
6
  import { paintPageFurniture } from "./furniture.js";
7
7
  import { ImageTable, paintImageFragment } from "./imagePrimitives.js";
8
- import { paintColumnSeparators, paintPageBackground } from "./pageFurniture.js";
8
+ import { paintColumnSeparators, paintFlowedNoteSeparators, paintPageBackground } from "./pageFurniture.js";
9
9
  import { paintParagraphFragment } from "./paragraphPrimitives.js";
10
10
  import { blockRegion, createPageComposer } from "./regions.js";
11
11
  import { paintTableFragment } from "./tablePrimitives.js";
@@ -231,24 +231,51 @@ const buildPage = ({ page, pageIndex, totalPages, blockLookup, pageBackground, b
231
231
  unsupported.report(UNSUPPORTED_CONSTRUCT.missingBlock, pageIndex, `no block lookup entry for ${fragment.kind} fragment ${String(fragment.blockId)}`);
232
232
  continue;
233
233
  }
234
- composer.region(blockRegion({
235
- fragment,
236
- kind: FRAGMENT_REGION_KIND[fragment.kind],
237
- context
238
- }), () => {
239
- paintFragment({
234
+ const paint = (fragmentContext) => {
235
+ composer.region(blockRegion({
240
236
  fragment,
241
- entry,
242
- context,
243
- composer,
244
- prevEntry: entries[index - 1],
245
- nextEntry: entries[index + 1]
237
+ kind: FRAGMENT_REGION_KIND[fragment.kind],
238
+ context: fragmentContext
239
+ }), () => {
240
+ paintFragment({
241
+ fragment,
242
+ entry,
243
+ context: fragmentContext,
244
+ composer,
245
+ prevEntry: entries[index - 1],
246
+ nextEntry: entries[index + 1]
247
+ });
248
+ });
249
+ };
250
+ const noteStory = entry.noteStory;
251
+ if (noteStory === void 0) {
252
+ paint(context);
253
+ continue;
254
+ }
255
+ const story = {
256
+ kind: noteStory.kind,
257
+ id: noteStory.noteId
258
+ };
259
+ composer.region({
260
+ kind: HIT_REGION_KINDS.note,
261
+ rect: {
262
+ xPx: fragment.x,
263
+ yPx: fragment.y,
264
+ widthPx: fragment.width,
265
+ heightPx: fragment.height
266
+ },
267
+ model: { story }
268
+ }, () => {
269
+ paint({
270
+ ...context,
271
+ story
246
272
  });
247
273
  });
248
274
  }
249
275
  });
250
276
  composer.push(frontFloats);
251
277
  composer.push(paintColumnSeparators(page));
278
+ composer.push(paintFlowedNoteSeparators(page));
252
279
  above(composer);
253
280
  return {
254
281
  pageNumber: page.number,
@@ -11,6 +11,12 @@ declare const paintPageBackground: (page: Page, fill: DisplayColor) => DisplayPr
11
11
  * never drew them.
12
12
  */
13
13
  declare const paintColumnSeparators: (page: Page) => readonly DisplayPrimitive[];
14
+ /**
15
+ * The separator rules of a note area laid out in the body flow (endnotes): the
16
+ * paginator records where each `w:separator` / `w:continuationSeparator` mark
17
+ * landed, so like the column rules they are derivable from the `Layout` alone.
18
+ */
19
+ declare const paintFlowedNoteSeparators: (page: Page) => readonly DisplayPrimitive[];
14
20
  type FootnoteAreaPaintOptions = {
15
21
  readonly composer: PageComposer;
16
22
  readonly page: Page;
@@ -32,4 +38,4 @@ type FootnoteAreaPaintOptions = {
32
38
  */
33
39
  declare const paintFootnoteArea: ({ composer, page, context, contentById }: FootnoteAreaPaintOptions) => void;
34
40
  //#endregion
35
- export { FootnoteAreaPaintOptions, paintColumnSeparators, paintFootnoteArea, paintPageBackground };
41
+ export { FootnoteAreaPaintOptions, paintColumnSeparators, paintFlowedNoteSeparators, paintFootnoteArea, paintPageBackground };
@@ -1,4 +1,4 @@
1
- import "../../layout-engine/types.js";
1
+ import { NOTE_SEPARATOR_RULE_THICKNESS, NOTE_SEPARATOR_WIDTH_FRACTION } from "../../layout-engine/types.js";
2
2
  import { calculateFootnoteAreaRenderHeight } from "../../layout-painter/renderPage.js";
3
3
  import { HIT_REGION_KINDS } from "../primitives.js";
4
4
  import { DOC_CANVAS_TEXT } from "./colors.js";
@@ -20,10 +20,8 @@ import { UNSUPPORTED_CONSTRUCT } from "./unsupported.js";
20
20
  */
21
21
  /** `renderPage.ts:2049`: a hairline in the canvas ink colour. */
22
22
  const COLUMN_SEPARATOR_WIDTH_PX = .5;
23
- /** `renderPage.ts:1354-1360`: a 0.5px rule across a third of the column, centred in its 12px slot. */
24
- const FOOTNOTE_RULE_THICKNESS_PX = .5;
25
- const FOOTNOTE_RULE_WIDTH_FRACTION = .33;
26
- const FOOTNOTE_RULE_MARGIN_PX = (12 - FOOTNOTE_RULE_THICKNESS_PX) / 2;
23
+ /** `renderFootnoteArea`: a hairline across a third of the column, centred in its 12px slot. */
24
+ const FOOTNOTE_RULE_MARGIN_PX = (12 - NOTE_SEPARATOR_RULE_THICKNESS) / 2;
27
25
  const paintPageBackground = (page, fill) => ({
28
26
  kind: "rect",
29
27
  rect: {
@@ -63,6 +61,21 @@ const paintColumnSeparators = (page) => {
63
61
  return primitives;
64
62
  };
65
63
  /**
64
+ * The separator rules of a note area laid out in the body flow (endnotes): the
65
+ * paginator records where each `w:separator` / `w:continuationSeparator` mark
66
+ * landed, so like the column rules they are derivable from the `Layout` alone.
67
+ */
68
+ const paintFlowedNoteSeparators = (page) => (page.noteSeparators ?? []).map((rule) => ({
69
+ kind: "rect",
70
+ rect: {
71
+ xPx: rule.x,
72
+ yPx: rule.y,
73
+ widthPx: rule.width,
74
+ heightPx: NOTE_SEPARATOR_RULE_THICKNESS
75
+ },
76
+ fill: DOC_CANVAS_TEXT
77
+ }));
78
+ /**
66
79
  * The footnote band at the foot of the body column: the separator rule, then
67
80
  * one body per note the paginator put on this page.
68
81
  *
@@ -98,8 +111,8 @@ const paintFootnoteArea = ({ composer, page, context, contentById }) => {
98
111
  rect: {
99
112
  xPx: page.margins.left,
100
113
  yPx: areaTopPx + FOOTNOTE_RULE_MARGIN_PX,
101
- widthPx: contentWidthPx * FOOTNOTE_RULE_WIDTH_FRACTION,
102
- heightPx: FOOTNOTE_RULE_THICKNESS_PX
114
+ widthPx: contentWidthPx * NOTE_SEPARATOR_WIDTH_FRACTION,
115
+ heightPx: NOTE_SEPARATOR_RULE_THICKNESS
103
116
  },
104
117
  fill: DOC_CANVAS_TEXT
105
118
  }];
@@ -138,4 +151,4 @@ const paintFootnoteArea = ({ composer, page, context, contentById }) => {
138
151
  }
139
152
  };
140
153
  //#endregion
141
- export { paintColumnSeparators, paintFootnoteArea, paintPageBackground };
154
+ export { paintColumnSeparators, paintFlowedNoteSeparators, paintFootnoteArea, paintPageBackground };
@@ -6,7 +6,7 @@ import { countCompressibleSpaces, toPaintedText } from "../../layout-engine/meas
6
6
  import { isFloatingImageRun } from "../../layout-engine/types.js";
7
7
  import { resolveParagraphBorderHorizontalOutsets } from "../../layout-painter/borderStroke.js";
8
8
  import { getAutomaticTextColorForBackground } from "../../layout-painter/documentColors.js";
9
- import { UNICODE_BIDI_BY_WRAPPER_CONTROL, getLeaderChar, getRenderableTextColor, paragraphHasTrackedChanges, sliceRunsForLine, splitCollapsibleLineEdgeSpaces, splitTextRunsByEastAsia, startsAfterSoftWrap } from "../../layout-painter/renderParagraph.js";
9
+ import { UNICODE_BIDI_BY_WRAPPER_CONTROL, getLeaderChar, getRenderableListMarkerColor, getRenderableTextColor, paragraphHasTrackedChanges, sliceRunsForLine, splitCollapsibleLineEdgeSpaces, splitTextRunsByEastAsia, startsAfterSoftWrap } from "../../layout-painter/renderParagraph.js";
10
10
  import { getHorizontalScaleFactor } from "../../utils/horizontalScale.js";
11
11
  import { resolvePhysicalParagraphInlineLayout } from "../../utils/paragraphInlineLayout.js";
12
12
  import { inlineImageBoundingBox } from "../../utils/rotationBoundingBox.js";
@@ -368,7 +368,7 @@ const emitGlyphRun = ({ sink, context, run, glyphs, style, paintXPx, baselineYPx
368
368
  } else context.unsupported.report(UNSUPPORTED_CONSTRUCT.unresolvedColor, context.pageIndex, `run background ${background}`);
369
369
  }
370
370
  const font = context.fonts.intern({
371
- fontFamily: style.fontFamily ?? "Calibri",
371
+ fontFamily: style.fontFamily ?? "Times New Roman",
372
372
  ...style.alternateFontFamily === void 0 ? {} : { alternateFontFamily: style.alternateFontFamily },
373
373
  ...style.bold === void 0 ? {} : { bold: style.bold },
374
374
  ...style.italic === void 0 ? {} : { italic: style.italic },
@@ -729,6 +729,7 @@ const paintLine = ({ block, line, geometry, context, alignment, isRtl, isFirstLi
729
729
  tabRegions
730
730
  };
731
731
  };
732
+ const parseMarkerColor = (color) => color === void 0 ? void 0 : parseDisplayColor(color);
732
733
  const paintListMarker = ({ sink, block, context, paintXPx, baselineYPx, isRtl }) => {
733
734
  const marker = block.attrs?.listMarker;
734
735
  if (marker === void 0 || marker.length === 0) return;
@@ -742,7 +743,7 @@ const paintListMarker = ({ sink, block, context, paintXPx, baselineYPx, isRtl })
742
743
  collapsed: false
743
744
  });
744
745
  const revision = block.attrs?.listMarkerRevision;
745
- const color = revision ? trackedChangeColor(context.authorColors, revision.author, void 0) : DOC_CANVAS_TEXT;
746
+ const color = revision ? trackedChangeColor(context.authorColors, revision.author, void 0) : parseMarkerColor(getRenderableListMarkerColor(formatting.color)) ?? DOC_CANVAS_TEXT;
746
747
  const font = context.fonts.intern({
747
748
  fontFamily: formatting.fontFamily,
748
749
  ...formatting.alternateFontFamily === void 0 ? {} : { alternateFontFamily: formatting.alternateFontFamily },
@@ -813,7 +814,7 @@ const paintTab = ({ sink, context, runs, index, run, tabContext, layoutXPx, pain
813
814
  collapsed: false
814
815
  });
815
816
  const font = context.fonts.intern({
816
- fontFamily: style.fontFamily ?? "Calibri",
817
+ fontFamily: style.fontFamily ?? "Times New Roman",
817
818
  ...style.bold === void 0 ? {} : { bold: style.bold },
818
819
  ...style.italic === void 0 ? {} : { italic: style.italic },
819
820
  measureStyle: style
@@ -1,5 +1,5 @@
1
1
  import { createTableCellFlowState, placeTableCellBlock } from "../../layout-engine/measure/tableCellFlow.js";
2
- import { buildTableCellGrid, buildTableCellPlacements, getSourceCellAt } from "../../layout-engine/measure/tableCellGrid.js";
2
+ import { buildTableCellGrid, buildTableCellPlacements, getSourceCellAt, getTableCellSpacingInsetsY } from "../../layout-engine/measure/tableCellGrid.js";
3
3
  import { tableFragmentBottomBorders } from "../../layout-engine/measure/tableFragmentBorderGeometry.js";
4
4
  import { resolveTableCellPadding } from "../../layout-engine/types.js";
5
5
  import { cellTextRotationDegrees } from "../../layout-painter/renderTable.js";
@@ -253,8 +253,10 @@ const paintTableBody = ({ composer, block, measure, xPx, yPx, fromRow, toRow, he
253
253
  const placements = buildTableCellPlacements({
254
254
  grid,
255
255
  columnWidths: measure.columnWidths,
256
- bidi: block.bidi === true
256
+ bidi: block.bidi === true,
257
+ cellSpacing: block.cellSpacing
257
258
  });
259
+ const bordersSeparated = (block.cellSpacing ?? 0) > 0;
258
260
  const rowTops = [0];
259
261
  for (const rowMeasure of measure.rows) rowTops.push((rowTops.at(-1) ?? 0) + rowMeasure.height);
260
262
  const paintRow = (rowIndex, rowYPx) => {
@@ -283,7 +285,9 @@ const paintTableBody = ({ composer, block, measure, xPx, yPx, fromRow, toRow, he
283
285
  if (!placement) continue;
284
286
  const rowSpan = Math.max(1, Math.trunc(cell.rowSpan ?? 1));
285
287
  const spanEnd = Math.min(rowTops.length - 1, rowIndex + rowSpan);
286
- const heightPx = spanEnd > rowIndex ? rowTops[spanEnd] - rowTops[rowIndex] : rowMeasure.height;
288
+ const slotHeightPx = spanEnd > rowIndex ? rowTops[spanEnd] - rowTops[rowIndex] : rowMeasure.height;
289
+ const spacing = getTableCellSpacingInsetsY(block.cellSpacing, rowIndex, rowSpan, block.rows.length);
290
+ const heightPx = Math.max(0, slotHeightPx - spacing.top - spacing.bottom);
287
291
  const atLogicalStart = placement.sourceColumn === 0;
288
292
  const atLogicalEnd = placement.sourceColumn + placement.columnSpan >= measure.columnWidths.length;
289
293
  const isFirstColumn = block.bidi === true ? atLogicalEnd : atLogicalStart;
@@ -292,7 +296,7 @@ const paintTableBody = ({ composer, block, measure, xPx, yPx, fromRow, toRow, he
292
296
  const leftCell = getSourceCellAt(grid, rowIndex, leftNeighborColumn);
293
297
  const box = {
294
298
  xPx: xPx + placement.left,
295
- yPx: rowYPx,
299
+ yPx: rowYPx + spacing.top,
296
300
  widthPx: placement.width,
297
301
  heightPx
298
302
  };
@@ -312,9 +316,9 @@ const paintTableBody = ({ composer, block, measure, xPx, yPx, fromRow, toRow, he
312
316
  context,
313
317
  paintTextBox,
314
318
  sides: {
315
- top: rowIndex === fromRow || !hasVisibleBorder(aboveCell?.borders?.bottom),
319
+ top: bordersSeparated || rowIndex === fromRow || !hasVisibleBorder(aboveCell?.borders?.bottom),
316
320
  bottom: true,
317
- left: isFirstColumn || !hasVisibleBorder(leftCell?.borders?.right),
321
+ left: bordersSeparated || isFirstColumn || !hasVisibleBorder(leftCell?.borders?.right),
318
322
  right: true
319
323
  }
320
324
  });
@@ -1,11 +1,19 @@
1
1
  import { modelledAttributeNames } from "./propertyElementAttributes.js";
2
2
  import { OOXML_NAMESPACES } from "./serializer/partNamespaces.js";
3
+ import { XML_NAMESPACE_URI } from "./xmlNamespaceContext.js";
3
4
  import { getLocalName, resolveAttributeNamespaceUri } from "./xmlParser.js";
4
5
  import { TaggedError } from "better-result";
5
6
  import { escapeXmlAttribute } from "@stll/docx-core";
6
7
  //#region src/docx/attributeRemainder.ts
7
- /** Namespace URI to the prefix a rebuilt part binds for it. */
8
- const CANONICAL_PREFIX = new Map(Object.entries(OOXML_NAMESPACES).map(([prefix, { uri }]) => [uri, prefix]));
8
+ /**
9
+ * Namespace URI to the prefix a rebuilt part binds for it.
10
+ *
11
+ * `xml` is reserved rather than declared — {@link OOXML_NAMESPACES} excludes
12
+ * it because a rebuilt part must never write `xmlns:xml` — so it is added
13
+ * here on its own: the remainder still has to spell `xml:space`, `xml:lang`
14
+ * and `xml:id` back, or the attribute is written unprefixed instead of dropped.
15
+ */
16
+ const CANONICAL_PREFIX = new Map([...Object.entries(OOXML_NAMESPACES).map(([prefix, { uri }]) => [uri, prefix]), [XML_NAMESPACE_URI, "xml"]]);
9
17
  const XML_LOCAL_NAME = /^[\p{L}_][\p{L}\p{M}\p{N}._\-\u{00B7}\u{203F}-\u{2040}]*$/u;
10
18
  var InvalidPreservedAttributeError = class extends TaggedError("InvalidPreservedAttributeError") {};
11
19
  /** Whether an attribute remainder can be emitted under a bound canonical name. */
@@ -2,12 +2,14 @@ import { document_d_exports } from "../types/document.js";
2
2
  import { NumberingMap } from "./numberingParser.js";
3
3
  import { ParseContext } from "./parseContext.js";
4
4
  import { XmlElement } from "./xmlParser.js";
5
+ import { PreviewLedger } from "./previewBudget.js";
5
6
  import { StyleMap } from "./styleParser.js";
6
7
  //#region src/docx/blockContentParser.d.ts
7
8
  type ParseBlockContentOptions = {
8
9
  inHeaderFooter?: boolean;
9
10
  rootXmlns?: Record<string, string>;
10
11
  context?: ParseContext | undefined;
12
+ previews?: PreviewLedger;
11
13
  };
12
14
  declare const parseBlockContent: (parent: XmlElement, styles: StyleMap | null, theme: document_d_exports.Theme | null, numbering: NumberingMap | null, rels: document_d_exports.RelationshipMap | null, media: Map<string, document_d_exports.MediaFile> | null, options?: ParseBlockContentOptions) => document_d_exports.BlockContent[];
13
15
  //#endregion