@stll/folio-core 0.47.7 → 0.49.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 (213) hide show
  1. package/dist/ai-edits/apply.js +565 -121
  2. package/dist/ai-edits/minimal-replacement.d.ts +64 -0
  3. package/dist/ai-edits/minimal-replacement.js +282 -0
  4. package/dist/controller/fontReadiness.js +3 -3
  5. package/dist/controller/hyphenationReadiness.d.ts +19 -0
  6. package/dist/controller/hyphenationReadiness.js +47 -0
  7. package/dist/controller/layoutPipeline.d.ts +3 -0
  8. package/dist/controller/layoutPipeline.js +70 -18
  9. package/dist/display-list/build/buildDisplayList.js +39 -12
  10. package/dist/display-list/build/pageFurniture.d.ts +7 -1
  11. package/dist/display-list/build/pageFurniture.js +21 -8
  12. package/dist/display-list/build/paragraphPrimitives.js +68 -11
  13. package/dist/display-list/build/tablePrimitives.js +10 -6
  14. package/dist/display-list/build/textBoxPrimitives.js +1 -1
  15. package/dist/display-list/build/unsupported.d.ts +2 -2
  16. package/dist/display-list/build/unsupported.js +0 -0
  17. package/dist/display-list/dom/renderDisplayListToDom.js +0 -1
  18. package/dist/docx/attributeRemainder.js +10 -2
  19. package/dist/docx/blockContentParser.d.ts +2 -0
  20. package/dist/docx/blockContentParser.js +79 -64
  21. package/dist/docx/bulletMarkers.d.ts +18 -2
  22. package/dist/docx/bulletMarkers.js +27 -2
  23. package/dist/docx/commentParser.d.ts +2 -1
  24. package/dist/docx/commentParser.js +57 -45
  25. package/dist/docx/containerChildren.d.ts +21 -8
  26. package/dist/docx/containerChildren.js +39 -9
  27. package/dist/docx/documentParser.d.ts +5 -1
  28. package/dist/docx/documentParser.js +8 -5
  29. package/dist/docx/documentSectionFacts.d.ts +22 -0
  30. package/dist/docx/documentSectionFacts.js +43 -0
  31. package/dist/docx/drawingGroupChildren.d.ts +60 -0
  32. package/dist/docx/drawingGroupChildren.js +176 -0
  33. package/dist/docx/drawingUtils.js +3 -0
  34. package/dist/docx/fieldParser.d.ts +8 -1
  35. package/dist/docx/fieldParser.js +47 -3
  36. package/dist/docx/fontTableParser.js +34 -27
  37. package/dist/docx/footnoteParser.d.ts +3 -2
  38. package/dist/docx/footnoteParser.js +15 -12
  39. package/dist/docx/groupDrawingParser.d.ts +9 -2
  40. package/dist/docx/groupDrawingParser.js +125 -37
  41. package/dist/docx/headerFooterParser.d.ts +7 -2
  42. package/dist/docx/headerFooterParser.js +15 -5
  43. package/dist/docx/hyperlinkParser.d.ts +48 -36
  44. package/dist/docx/hyperlinkParser.js +97 -82
  45. package/dist/docx/numberingParser.js +108 -84
  46. package/dist/docx/packageParts.d.ts +45 -1
  47. package/dist/docx/packageParts.js +93 -2
  48. package/dist/docx/paraIdAttribute.d.ts +3 -2
  49. package/dist/docx/paragraphParser.d.ts +5 -1
  50. package/dist/docx/paragraphParser.js +468 -365
  51. package/dist/docx/paragraphProperties.js +123 -109
  52. package/dist/docx/paragraphPropertySource.d.ts +6 -1
  53. package/dist/docx/paragraphPropertySource.js +9 -1
  54. package/dist/docx/paragraphTextBoxEnrichment.d.ts +2 -1
  55. package/dist/docx/paragraphTextBoxEnrichment.js +143 -10
  56. package/dist/docx/parser.d.ts +7 -1
  57. package/dist/docx/parser.js +33 -16
  58. package/dist/docx/previewBudget.d.ts +55 -33
  59. package/dist/docx/previewBudget.js +59 -65
  60. package/dist/docx/rezip.js +41 -58
  61. package/dist/docx/runParser.d.ts +4 -1
  62. package/dist/docx/runParser.js +182 -184
  63. package/dist/docx/sdtProperties.js +87 -84
  64. package/dist/docx/sectionParser.js +169 -160
  65. package/dist/docx/selectiveSaveFlags.d.ts +10 -3
  66. package/dist/docx/selectiveSaveFlags.js +1 -1
  67. package/dist/docx/selectiveXmlPatch.d.ts +56 -34
  68. package/dist/docx/selectiveXmlPatch.js +222 -115
  69. package/dist/docx/serializer/groupTextBoxWriteBack.d.ts +12 -0
  70. package/dist/docx/serializer/groupTextBoxWriteBack.js +101 -0
  71. package/dist/docx/serializer/paragraphSerializer.js +47 -42
  72. package/dist/docx/serializer/runSerializer.d.ts +5 -1
  73. package/dist/docx/serializer/runSerializer.js +4 -3
  74. package/dist/docx/serializer/settingsSerializer.js +19 -1
  75. package/dist/docx/settingsParser.js +8 -0
  76. package/dist/docx/shapeAlternateContent.d.ts +25 -0
  77. package/dist/docx/shapeAlternateContent.js +52 -0
  78. package/dist/docx/streamingXmlParser.d.ts +6 -2
  79. package/dist/docx/streamingXmlParser.js +12 -7
  80. package/dist/docx/styleParser.js +34 -8
  81. package/dist/docx/tableParser.d.ts +21 -12
  82. package/dist/docx/tableParser.js +518 -441
  83. package/dist/docx/textBoxParser.d.ts +18 -5
  84. package/dist/docx/textBoxParser.js +12 -6
  85. package/dist/docx/verbatimCapture.d.ts +10 -8
  86. package/dist/docx/verbatimCapture.js +45 -2
  87. package/dist/docx/vmlImageParser.d.ts +15 -13
  88. package/dist/docx/vmlImageParser.js +75 -60
  89. package/dist/docx/vmlPreview.d.ts +3 -3
  90. package/dist/docx/vmlPreview.js +3 -4
  91. package/dist/docx/xmlNamespaceContext.d.ts +9 -0
  92. package/dist/docx/xmlNamespaceContext.js +54 -0
  93. package/dist/docx/xmlParser.d.ts +6 -3
  94. package/dist/docx/xmlParser.js +11 -41
  95. package/dist/docx/xmlResourceLimits.d.ts +2 -1
  96. package/dist/docx/xmlResourceLimits.js +4 -1
  97. package/dist/fonts/headlessMeasure.js +0 -0
  98. package/dist/headless-layout.d.ts +11 -2
  99. package/dist/headless-layout.js +153 -107
  100. package/dist/internal/headlessRevisionResolution.js +50 -13
  101. package/dist/internal/paragraphFormattingSerialization.js +3 -3
  102. package/dist/layout-bridge/convert/endnoteLayout.d.ts +65 -0
  103. package/dist/layout-bridge/convert/endnoteLayout.js +227 -0
  104. package/dist/layout-bridge/convert/footnoteLayout.d.ts +19 -3
  105. package/dist/layout-bridge/convert/footnoteLayout.js +40 -31
  106. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -7
  107. package/dist/layout-bridge/convert/headerFooterLayout.js +5 -20
  108. package/dist/layout-bridge/convert/paragraphMarkFormatting.d.ts +10 -0
  109. package/dist/layout-bridge/convert/paragraphMarkFormatting.js +59 -0
  110. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +29 -1
  111. package/dist/layout-bridge/convert/toFlowBlocks.js +284 -39
  112. package/dist/layout-bridge/engine/hitTest.js +5 -3
  113. package/dist/layout-bridge/engine/selectionRects.js +5 -3
  114. package/dist/layout-engine/anchorLayoutInCellCompatibility.d.ts +10 -0
  115. package/dist/layout-engine/anchorLayoutInCellCompatibility.js +22 -0
  116. package/dist/layout-engine/index.d.ts +2 -2
  117. package/dist/layout-engine/index.js +102 -14
  118. package/dist/layout-engine/justificationCompatibility.d.ts +1 -1
  119. package/dist/layout-engine/justificationCompatibility.js +9 -5
  120. package/dist/layout-engine/keep-together.d.ts +15 -6
  121. package/dist/layout-engine/keep-together.js +43 -16
  122. package/dist/layout-engine/layoutInstrumentation.d.ts +8 -2
  123. package/dist/layout-engine/layoutInstrumentation.js +8 -1
  124. package/dist/layout-engine/measure/advanceComposition.js +50 -7
  125. package/dist/layout-engine/measure/hyphenationDictionaries.d.ts +74 -0
  126. package/dist/layout-engine/measure/hyphenationDictionaries.js +138 -0
  127. package/dist/layout-engine/measure/hyphenationPreload.d.ts +11 -0
  128. package/dist/layout-engine/measure/hyphenationPreload.js +24 -0
  129. package/dist/layout-engine/measure/lineBreakProvider.d.ts +12 -2
  130. package/dist/layout-engine/measure/lineBreakProvider.js +30 -30
  131. package/dist/layout-engine/measure/lineBreaks.d.ts +6 -1
  132. package/dist/layout-engine/measure/lineBreaks.js +10 -3
  133. package/dist/layout-engine/measure/listMarkerWidth.d.ts +9 -6
  134. package/dist/layout-engine/measure/listMarkerWidth.js +20 -22
  135. package/dist/layout-engine/measure/measureBlocks.js +46 -10
  136. package/dist/layout-engine/measure/measureContainer.js +51 -8
  137. package/dist/layout-engine/measure/measureHelpers.d.ts +15 -3
  138. package/dist/layout-engine/measure/measureHelpers.js +34 -8
  139. package/dist/layout-engine/measure/measureParagraph.js +143 -101
  140. package/dist/layout-engine/measure/measureTypes.d.ts +5 -0
  141. package/dist/layout-engine/measure/smallCapsCasing.d.ts +56 -0
  142. package/dist/layout-engine/measure/smallCapsCasing.js +88 -0
  143. package/dist/layout-engine/measure/tabCalculator.d.ts +2 -0
  144. package/dist/layout-engine/measure/tabCalculator.js +2 -1
  145. package/dist/layout-engine/measure/tableCellFloating.d.ts +2 -0
  146. package/dist/layout-engine/measure/tableCellFloating.js +51 -19
  147. package/dist/layout-engine/measure/tableCellGrid.d.ts +28 -3
  148. package/dist/layout-engine/measure/tableCellGrid.js +45 -5
  149. package/dist/layout-engine/measure/tableFragmentBorderGeometry.js +2 -1
  150. package/dist/layout-engine/noteAreaFlow.d.ts +19 -0
  151. package/dist/layout-engine/noteAreaFlow.js +83 -0
  152. package/dist/layout-engine/paginator.d.ts +12 -1
  153. package/dist/layout-engine/paginator.js +18 -2
  154. package/dist/layout-engine/paragraphSpacing.d.ts +4 -2
  155. package/dist/layout-engine/paragraphSpacing.js +2 -1
  156. package/dist/layout-engine/tableRowBreak.d.ts +8 -1
  157. package/dist/layout-engine/tableRowBreak.js +25 -2
  158. package/dist/layout-engine/types.d.ts +108 -3
  159. package/dist/layout-engine/types.js +96 -1
  160. package/dist/layout-painter/index.d.ts +3 -0
  161. package/dist/layout-painter/renderPage.js +32 -83
  162. package/dist/layout-painter/renderParagraph.d.ts +6 -1
  163. package/dist/layout-painter/renderParagraph.js +75 -26
  164. package/dist/layout-painter/renderTable.js +26 -13
  165. package/dist/layout-painter/renderTextBox.d.ts +12 -2
  166. package/dist/layout-painter/renderTextBox.js +26 -2
  167. package/dist/prosemirror/alternateContentAttrs.d.ts +9 -0
  168. package/dist/prosemirror/alternateContentAttrs.js +35 -0
  169. package/dist/prosemirror/attrs/index.d.ts +9 -9
  170. package/dist/prosemirror/attrs/index.js +133 -11
  171. package/dist/prosemirror/commands/comments.js +51 -41
  172. package/dist/prosemirror/contentControlRevisions.d.ts +43 -0
  173. package/dist/prosemirror/contentControlRevisions.js +84 -0
  174. package/dist/prosemirror/conversion/fromProseDoc.js +54 -23
  175. package/dist/prosemirror/conversion/markInterner.d.ts +21 -0
  176. package/dist/prosemirror/conversion/markInterner.js +90 -0
  177. package/dist/prosemirror/conversion/toProseDoc.js +117 -58
  178. package/dist/prosemirror/extensions/core/DocExtension.js +2 -1
  179. package/dist/prosemirror/extensions/core/ParagraphExtension.js +1 -0
  180. package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.d.ts +7 -7
  181. package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +7 -7
  182. package/dist/prosemirror/extensions/marks/markUtils.d.ts +6 -2
  183. package/dist/prosemirror/extensions/marks/markUtils.js +39 -51
  184. package/dist/prosemirror/extensions/nodes/FieldExtension.js +6 -3
  185. package/dist/prosemirror/extensions/nodes/SdtExtension.js +9 -2
  186. package/dist/prosemirror/extensions/nodes/ShapeExtension.js +1 -0
  187. package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +5 -1
  188. package/dist/prosemirror/listMarker.d.ts +1 -0
  189. package/dist/prosemirror/listMarker.js +4 -2
  190. package/dist/prosemirror/listRenderingAttrs.d.ts +1 -0
  191. package/dist/prosemirror/listRenderingAttrs.js +3 -0
  192. package/dist/prosemirror/paragraphDirection.d.ts +29 -2
  193. package/dist/prosemirror/paragraphDirection.js +21 -2
  194. package/dist/prosemirror/plugins/suggestionMode.js +37 -8
  195. package/dist/prosemirror/rejoinRunCarriers.d.ts +27 -0
  196. package/dist/prosemirror/rejoinRunCarriers.js +66 -0
  197. package/dist/prosemirror/runIdentityAcrossRevisions.d.ts +10 -0
  198. package/dist/prosemirror/runIdentityAcrossRevisions.js +90 -0
  199. package/dist/prosemirror/schema/nodes.d.ts +50 -6
  200. package/dist/prosemirror/textBoxHostParagraph.d.ts +13 -0
  201. package/dist/prosemirror/textBoxHostParagraph.js +21 -0
  202. package/dist/prosemirror/validation.js +91 -80
  203. package/dist/types/content.d.ts +2 -2
  204. package/dist/utils/createDocument.js +10 -1
  205. package/dist/utils/scriptSegments.d.ts +33 -4
  206. package/dist/utils/scriptSegments.js +39 -6
  207. package/dist/utils/textFormattingMerge.d.ts +17 -3
  208. package/dist/utils/textFormattingMerge.js +18 -12
  209. package/dist/utils/trailingText.d.ts +22 -0
  210. package/dist/utils/trailingText.js +32 -0
  211. package/package.json +2 -2
  212. package/dist/layout-engine/justifiedLineFit.d.ts +0 -7
  213. package/dist/layout-engine/justifiedLineFit.js +0 -6
@@ -81,6 +81,7 @@ type XmlPackageBudget = {
81
81
  attributes: number;
82
82
  };
83
83
  declare const createXmlPackageBudget: () => XmlPackageBudget;
84
+ declare const exceedsUtf8ByteLimit: (value: string, maxBytes: number) => boolean;
84
85
  type XmlResourceScanOptions = {
85
86
  xml: string;
86
87
  limits?: XmlResourceLimits;
@@ -104,4 +105,4 @@ type XmlResourceScanResult = {
104
105
  */
105
106
  declare const assertXmlResourceLimits: ({ xml, limits, partPath, budget }: XmlResourceScanOptions) => XmlResourceScanResult;
106
107
  //#endregion
107
- export { FOLIO_XML_RESOURCE_LIMITS, XmlPackageBudget, XmlResourceLimitError, XmlResourceLimits, XmlResourceScanOptions, XmlResourceScanResult, assertXmlResourceLimits, createXmlPackageBudget };
108
+ export { FOLIO_XML_RESOURCE_LIMITS, XmlPackageBudget, XmlResourceLimitError, XmlResourceLimits, XmlResourceScanOptions, XmlResourceScanResult, assertXmlResourceLimits, createXmlPackageBudget, exceedsUtf8ByteLimit };
@@ -55,7 +55,10 @@ const createXmlPackageBudget = () => ({
55
55
  elements: 0,
56
56
  attributes: 0
57
57
  });
58
+ /** No UTF-16 code unit encodes to more than three UTF-8 bytes; a pair encodes to four. */
59
+ const MAX_UTF8_BYTES_PER_CODE_UNIT = 3;
58
60
  const exceedsUtf8ByteLimit = (value, maxBytes) => {
61
+ if (value.length * MAX_UTF8_BYTES_PER_CODE_UNIT <= maxBytes) return false;
59
62
  let bytes = 0;
60
63
  for (let index = 0; index < value.length; index += 1) {
61
64
  const codeUnit = value.charCodeAt(index);
@@ -186,4 +189,4 @@ const assertXmlResourceLimits = ({ xml, limits = FOLIO_XML_RESOURCE_LIMITS, part
186
189
  };
187
190
  };
188
191
  //#endregion
189
- export { FOLIO_XML_RESOURCE_LIMITS, XmlResourceLimitError, assertXmlResourceLimits, createXmlPackageBudget };
192
+ export { FOLIO_XML_RESOURCE_LIMITS, XmlResourceLimitError, assertXmlResourceLimits, createXmlPackageBudget, exceedsUtf8ByteLimit };
Binary file
@@ -17,9 +17,13 @@ import { Result } from "better-result";
17
17
  * names.
18
18
  */
19
19
  type DocumentPaintFeatures = DocumentFeatures;
20
- /** A story this entry does not paginate, named so a caller can see the hole. */
20
+ /**
21
+ * A story this entry does not paginate, named so a caller can see the hole.
22
+ * Every story is laid out now, so `story` admits none; a story that stops
23
+ * being laid out widens it again, and {@link UNPAGINATED_STORIES} must name it.
24
+ */
21
25
  type HeadlessLayoutGap = {
22
- readonly story: "endnote";
26
+ readonly story: never;
23
27
  readonly detail: string;
24
28
  };
25
29
  declare const HeadlessLayoutError_base: import("better-result").TaggedErrorClass<"HeadlessLayoutError">;
@@ -70,6 +74,11 @@ type HeadlessLayoutResult = {
70
74
  readonly embeddedFonts: readonly EmbeddedFont[];
71
75
  readonly unsupported: readonly HeadlessLayoutGap[];
72
76
  };
77
+ /**
78
+ * Parse and paginate a package. Fails rather than defaulting when no
79
+ * measurement backend is installed: a layout measured by the wrong provider
80
+ * is wrong in a way no downstream check catches.
81
+ */
73
82
  declare const layoutDocxHeadless: (input: DocxInput, options?: HeadlessLayoutOptions) => Promise<Result<HeadlessLayoutResult, HeadlessLayoutError>>;
74
83
  //#endregion
75
84
  export { DocumentPaintFeatures, HeadlessLayoutError, HeadlessLayoutGap, HeadlessLayoutOptions, HeadlessLayoutResult, layoutDocxHeadless };
@@ -6,11 +6,14 @@ import { parseDocx } from "./docx/parser.js";
6
6
  import { buildHeaderFooterFieldValues } from "./fields/resolveFieldValues.js";
7
7
  import { extractEmbeddedFonts } from "./fonts/embeddedFonts.js";
8
8
  import { buildFontAlternates } from "./fonts/fontAlternates.js";
9
+ import { prepareEndnoteAreas, resolveEndnotePosition, spliceEndnoteAreas, trailingEndnoteIds } from "./layout-bridge/convert/endnoteLayout.js";
9
10
  import { buildFootnoteContentMap, collectEndnoteRefs, collectFootnoteRefs, computeNoteDisplayNumbers, remapNoteMarkerText } from "./layout-bridge/convert/footnoteLayout.js";
10
11
  import { convertHeaderFooterToContent } from "./layout-bridge/convert/headerFooterLayout.js";
11
12
  import { toFlowBlocks } from "./layout-bridge/convert/toFlowBlocks.js";
12
13
  import { resolveSectionHeaderFooterRefs } from "./layout-engine/headerFooterRefs.js";
13
14
  import { layoutDocument } from "./layout-engine/index.js";
15
+ import { collectRequestedHyphenationDictionaries } from "./layout-engine/measure/hyphenationDictionaries.js";
16
+ import { preloadHyphenationDictionaries } from "./layout-engine/measure/hyphenationPreload.js";
14
17
  import { measureBlocks } from "./layout-engine/measure/measureBlocks.js";
15
18
  import { getMeasureProvider } from "./layout-engine/measure/measureProvider.js";
16
19
  import "./layout-engine/types.js";
@@ -34,14 +37,14 @@ import { createHash } from "node:crypto";
34
37
  *
35
38
  * ## The other stories
36
39
  *
37
- * Headers, footers and footnotes are separate OOXML stories that the editor
38
- * lays out as their own ProseMirror views, but neither conversion needs a view:
39
- * `convertHeaderFooterToContent` and `buildFootnoteContentMap` run the same
40
- * `toFlowBlocks → measureBlocks` chain the body runs. This entry therefore lays
41
- * them out too and returns them as {@link HeadlessLayoutResult.furniture}, so
42
- * an export paints the pages the editor paints rather than bare bodies.
43
- * Endnotes remain unpaginated and say so through
44
- * {@link HeadlessLayoutResult.unsupported}.
40
+ * Headers, footers and notes are separate OOXML stories that the editor
41
+ * lays out as their own ProseMirror views, but no conversion needs a view:
42
+ * `convertHeaderFooterToContent`, `buildFootnoteContentMap` and
43
+ * `prepareEndnoteAreas` run the same `toFlowBlocks → measureBlocks` chain the
44
+ * body runs. This entry therefore lays them out too: headers, footers and
45
+ * footnotes come back as {@link HeadlessLayoutResult.furniture}, and endnotes
46
+ * paginate with the body, so an export paints the pages the editor paints
47
+ * rather than bare bodies.
45
48
  *
46
49
  * What this entry still does not do is push the body down for a header taller
47
50
  * than its margin: the editor's margin clearing lives in the controller, and a
@@ -67,21 +70,9 @@ var HeadlessLayoutError = class extends TaggedError("HeadlessLayoutError") {};
67
70
  * than content that vanishes without a report, and a story that starts being
68
71
  * laid out cannot keep a stale entry, because removing it narrows the union.
69
72
  *
70
- * Endnotes are the only one left. They are collected at the end of the
71
- * document rather than reserved per page, so nothing in `Layout` and nothing in
72
- * the painter's render options places them yet; laying them out is a
73
- * pagination feature, not a conversion this entry could call.
73
+ * None is left: endnotes, the last, paginate with the body.
74
74
  */
75
- const UNPAGINATED_STORIES = { endnote: {
76
- story: "endnote",
77
- detail: "Endnotes are their own story and are not paginated with the body."
78
- } };
79
- const hasStory = (document, story) => {
80
- switch (story) {
81
- case "endnote": return (document.package.endnotes?.length ?? 0) > 0;
82
- default: return false;
83
- }
84
- };
75
+ const UNPAGINATED_STORIES = {};
85
76
  const readPaintFeatures = (document) => ({
86
77
  pageBorders: (document.package.document.sections ?? []).some((section) => Object.values(section.properties.pageBorders ?? {}).some((border) => border !== void 0)),
87
78
  watermark: getDocumentWatermark(document) !== void 0
@@ -178,26 +169,36 @@ const NONCE_LENGTH = 12;
178
169
  /** Whether `fontTable.xml` declares any embedded face at all. */
179
170
  const declaresEmbeddedFonts = (document) => (document.package.fontTable?.fonts ?? []).some((font) => font.embedRegular !== void 0 || font.embedBold !== void 0 || font.embedItalic !== void 0 || font.embedBoldItalic !== void 0);
180
171
  /**
181
- * Parse and paginate a package. Fails rather than defaulting when no
182
- * measurement backend is installed: a layout measured by the wrong provider
183
- * is wrong in a way no downstream check catches.
184
- */
185
- /**
186
- * Whether any text in the package needs shaping.
172
+ * Whether `test` holds for any record in the package's content model.
187
173
  *
188
174
  * Every story a page paints, body, headers, footers and notes alike, is built
189
175
  * from the same content model, so one walk over the package answers for all of
190
- * them. The answer decides whether the shaper is fetched at all: a document in
191
- * Latin, Cyrillic or Greek must not pay for an artifact it has no use for.
176
+ * them. Headers and footers are keyed by relationship id in `Map`s, which
177
+ * `Object.entries` sees as empty, so the walk descends into map values too.
192
178
  */
193
- const packageNeedsShaping = (value) => {
194
- if (Array.isArray(value)) return value.some(packageNeedsShaping);
179
+ const somePackageRecord = (value, test) => {
180
+ if (Array.isArray(value) || value instanceof Map) {
181
+ for (const child of value.values()) if (somePackageRecord(child, test)) return true;
182
+ return false;
183
+ }
195
184
  if (typeof value !== "object" || value === null) return false;
196
185
  const entries = Object.entries(value);
197
- const text = entries.find(([key]) => key === "text")?.[1];
198
- if (entries.find(([key]) => key === "type")?.[1] === "text" && typeof text === "string" && needsShaping(text)) return true;
199
- return entries.some(([, child]) => packageNeedsShaping(child));
186
+ return test(entries) || entries.some(([, child]) => somePackageRecord(child, test));
200
187
  };
188
+ /**
189
+ * Whether any text in the package needs shaping. The answer decides whether
190
+ * the shaper is fetched at all: a document in Latin, Cyrillic or Greek must not
191
+ * pay for an artifact it has no use for.
192
+ */
193
+ const packageNeedsShaping = (value) => somePackageRecord(value, (entries) => {
194
+ const text = entries.find(([key]) => key === "text")?.[1];
195
+ return entries.find(([key]) => key === "type")?.[1] === "text" && typeof text === "string" && needsShaping(text);
196
+ });
197
+ /**
198
+ * Parse and paginate a package. Fails rather than defaulting when no
199
+ * measurement backend is installed: a layout measured by the wrong provider
200
+ * is wrong in a way no downstream check catches.
201
+ */
201
202
  const layoutDocxHeadless = async (input, options = {}) => {
202
203
  const providerCheck = Result.try(() => getMeasureProvider().getFontMetrics({ fontSize: 11 }));
203
204
  if (providerCheck.isErr()) return Result.err(new HeadlessLayoutError({
@@ -245,32 +246,49 @@ const layoutDocxHeadless = async (input, options = {}) => {
245
246
  const margins = getMargins(firstSection);
246
247
  const contentWidth = pageSize.w - margins.left - margins.right;
247
248
  const pageContentHeight = pageSize.h - margins.top - margins.bottom;
249
+ const endnotePosition = resolveEndnotePosition(document.package.settings?.endnotePr?.position, finalSection);
248
250
  const flowOptions = buildFlowOptions(document, pageContentHeight);
251
+ const bodyTrailingEndnoteIds = trailingEndnoteIds(document.package.endnotes, endnotePosition);
252
+ if (bodyTrailingEndnoteIds.size > 0) flowOptions.trailingEndnoteIds = bodyTrailingEndnoteIds;
249
253
  const storyOptions = buildStoryOptions(flowOptions);
250
- const laidOut = Result.try(() => {
251
- const authored = toFlowBlocks(projected.value, flowOptions);
252
- const footnotes = document.package.footnotes ?? [];
253
- const endnotes = document.package.endnotes ?? [];
254
- const footnoteRefs = collectFootnoteRefs(authored);
255
- const footnoteNumbers = computeNoteDisplayNumbers(footnotes, footnoteRefs.map((ref) => ref.footnoteId));
256
- const endnoteNumbers = computeNoteDisplayNumbers(endnotes, collectEndnoteRefs(authored).map((ref) => ref.endnoteId));
257
- const endnoteNumberFormat = finalSection?.endnotePr?.numFmt ?? "lowerRoman";
258
- const blocks = remapNoteMarkerText(authored, {
259
- footnoteNumbers,
260
- endnoteTexts: formatEndnoteTexts(endnoteNumbers, (displayNumber) => formatOoxmlCounter(displayNumber, endnoteNumberFormat))
261
- });
262
- const measures = measureBlocks(blocks, contentWidth);
263
- const footnoteContentById = footnoteRefs.length === 0 ? void 0 : buildFootnoteContentMap(footnotes, footnoteRefs, contentWidth, {
264
- ...storyOptions,
265
- measureBlocks
266
- });
267
- const footnoteHeightById = /* @__PURE__ */ new Map();
268
- for (const [id, content] of footnoteContentById ?? []) footnoteHeightById.set(id, content.height + 0);
269
- const sectionHeaderFooterRefs = resolveSectionHeaderFooterRefs(document);
270
- const finalPageSize = getPageSize(finalSection);
271
- const finalMargins = getMargins(finalSection);
272
- return {
273
- layout: layoutDocument(blocks, measures, {
254
+ const layOut = () => {
255
+ const laidOut = Result.try(() => {
256
+ const authored = toFlowBlocks(projected.value, flowOptions);
257
+ const footnotes = document.package.footnotes ?? [];
258
+ const endnotes = document.package.endnotes ?? [];
259
+ const footnoteRefs = collectFootnoteRefs(authored);
260
+ const footnoteNumbers = computeNoteDisplayNumbers(footnotes, footnoteRefs.map((ref) => ref.footnoteId));
261
+ const endnoteNumbers = computeNoteDisplayNumbers(endnotes, collectEndnoteRefs(authored).map((ref) => ref.endnoteId));
262
+ const endnoteNumberFormat = finalSection?.endnotePr?.numFmt ?? document.package.settings?.endnotePr?.numFmt ?? "lowerRoman";
263
+ const endnoteTexts = formatEndnoteTexts(endnoteNumbers, (displayNumber) => formatOoxmlCounter(displayNumber, endnoteNumberFormat));
264
+ const blocks = remapNoteMarkerText(authored, {
265
+ footnoteNumbers,
266
+ endnoteTexts
267
+ });
268
+ const measures = measureBlocks(blocks, contentWidth);
269
+ const footnoteContentById = footnoteRefs.length === 0 ? void 0 : buildFootnoteContentMap(footnotes, footnoteRefs, contentWidth, {
270
+ ...storyOptions,
271
+ measureBlocks
272
+ });
273
+ const footnoteHeightById = /* @__PURE__ */ new Map();
274
+ for (const [id, content] of footnoteContentById ?? []) footnoteHeightById.set(id, content.height + 0);
275
+ const endnoteAreas = prepareEndnoteAreas({
276
+ blocks,
277
+ endnotes,
278
+ displayNumbers: endnoteNumbers,
279
+ displayTexts: endnoteTexts,
280
+ position: endnotePosition,
281
+ sections: sections.map(({ properties }) => properties),
282
+ options: {
283
+ ...storyOptions,
284
+ measureBlocks
285
+ }
286
+ });
287
+ const flow = spliceEndnoteAreas(blocks, measures, endnoteAreas);
288
+ const sectionHeaderFooterRefs = resolveSectionHeaderFooterRefs(document);
289
+ const finalPageSize = getPageSize(finalSection);
290
+ const finalMargins = getMargins(finalSection);
291
+ const layoutOptions = {
274
292
  pageSize,
275
293
  margins,
276
294
  pageNumbering: getPageNumbering(firstSection),
@@ -283,51 +301,79 @@ const layoutDocxHeadless = async (input, options = {}) => {
283
301
  evenAndOddHeaders: document.package.settings?.evenAndOddHeaders === true,
284
302
  mirrorMargins: readsMirrorMargins(document.package.settings),
285
303
  ...footnoteHeightById.size === 0 ? {} : { footnoteHeightById },
286
- ...sectionHeaderFooterRefs === void 0 ? {} : { sectionHeaderFooterRefs }
287
- }),
288
- blockLookup: buildBlockLookup(blocks, measures),
289
- footnoteContentById
290
- };
291
- });
292
- if (laidOut.isErr()) return Result.err(new HeadlessLayoutError({
293
- message: "The document could not be paginated.",
294
- cause: laidOut.error
295
- }));
296
- const { layout, blockLookup, footnoteContentById } = laidOut.value;
297
- const stories = Result.try(() => {
298
- const pageCount = layout.pages.length;
299
- const now = options.now ?? /* @__PURE__ */ new Date();
300
- const shared = {
301
- contentWidth,
302
- storyOptions,
303
- pageCount,
304
- now
305
- };
306
- return {
307
- headerContentByRId: convertStories({
308
- ...shared,
309
- parts: document.package.headers,
310
- metrics: {
311
- section: "header",
312
- pageSize,
313
- margins
314
- }
315
- }),
316
- footerContentByRId: convertStories({
317
- ...shared,
318
- parts: document.package.footers,
319
- metrics: {
320
- section: "footer",
321
- pageSize,
322
- margins
323
- }
324
- })
325
- };
326
- });
327
- if (stories.isErr()) return Result.err(new HeadlessLayoutError({
328
- message: "The header and footer stories could not be laid out.",
329
- cause: stories.error
330
- }));
304
+ ...sectionHeaderFooterRefs === void 0 ? {} : { sectionHeaderFooterRefs },
305
+ ...endnoteAreas === void 0 ? {} : { noteAreas: endnoteAreas.noteAreas }
306
+ };
307
+ const blockLookup = buildBlockLookup(flow.blocks, flow.measures);
308
+ for (const [blockId, noteStory] of endnoteAreas?.noteStoryByBlockId ?? []) {
309
+ const entry = blockLookup.get(blockId);
310
+ if (entry !== void 0) entry.noteStory = noteStory;
311
+ }
312
+ const continuationSeparator = endnoteAreas?.noteAreas.continuationSeparator;
313
+ if (continuationSeparator !== void 0) blockLookup.set(String(continuationSeparator.block.id), continuationSeparator);
314
+ return {
315
+ layout: layoutDocument(flow.blocks, flow.measures, layoutOptions),
316
+ blockLookup,
317
+ footnoteContentById
318
+ };
319
+ });
320
+ if (laidOut.isErr()) return Result.err(new HeadlessLayoutError({
321
+ message: "The document could not be paginated.",
322
+ cause: laidOut.error
323
+ }));
324
+ const { layout, blockLookup, footnoteContentById } = laidOut.value;
325
+ const stories = Result.try(() => {
326
+ const pageCount = layout.pages.length;
327
+ const now = options.now ?? /* @__PURE__ */ new Date();
328
+ const shared = {
329
+ contentWidth,
330
+ storyOptions,
331
+ pageCount,
332
+ now
333
+ };
334
+ return {
335
+ headerContentByRId: convertStories({
336
+ ...shared,
337
+ parts: document.package.headers,
338
+ metrics: {
339
+ section: "header",
340
+ pageSize,
341
+ margins
342
+ }
343
+ }),
344
+ footerContentByRId: convertStories({
345
+ ...shared,
346
+ parts: document.package.footers,
347
+ metrics: {
348
+ section: "footer",
349
+ pageSize,
350
+ margins
351
+ }
352
+ })
353
+ };
354
+ });
355
+ if (stories.isErr()) return Result.err(new HeadlessLayoutError({
356
+ message: "The header and footer stories could not be laid out.",
357
+ cause: stories.error
358
+ }));
359
+ return Result.ok({
360
+ layout,
361
+ blockLookup,
362
+ footnoteContentById,
363
+ ...stories.value
364
+ });
365
+ };
366
+ let pass = collectRequestedHyphenationDictionaries(layOut);
367
+ if (pass.missing.size > 0) {
368
+ const loaded = await preloadHyphenationDictionaries(pass.missing);
369
+ if (loaded.isErr()) return Result.err(new HeadlessLayoutError({
370
+ message: "A hyphenation dictionary could not be loaded, and this document needs one.",
371
+ cause: loaded.error
372
+ }));
373
+ pass = collectRequestedHyphenationDictionaries(layOut);
374
+ }
375
+ if (pass.result.isErr()) return Result.err(pass.result.error);
376
+ const { layout, blockLookup, footnoteContentById, headerContentByRId, footerContentByRId } = pass.result.value;
331
377
  const embeddedFonts = declaresEmbeddedFonts(document) ? await Result.tryPromise({
332
378
  try: async () => {
333
379
  const source = await toArrayBuffer(input);
@@ -356,13 +402,13 @@ const layoutDocxHeadless = async (input, options = {}) => {
356
402
  ...watermark === void 0 ? {} : { watermark },
357
403
  watermarkByHeaderRId: watermarksByHeader,
358
404
  ...watermarkImageSrc === void 0 ? {} : { watermarkImageSrc },
359
- headerContentByRId: stories.value.headerContentByRId,
360
- footerContentByRId: stories.value.footerContentByRId,
405
+ headerContentByRId,
406
+ footerContentByRId,
361
407
  titlePg: firstSection?.titlePg === true,
362
408
  ...footnoteContentById === void 0 ? {} : { footnoteContentById }
363
409
  },
364
410
  embeddedFonts: embeddedFonts.value,
365
- unsupported: Object.values(UNPAGINATED_STORIES).filter((gap) => hasStory(document, gap.story))
411
+ unsupported: Object.values(UNPAGINATED_STORIES)
366
412
  });
367
413
  };
368
414
  //#endregion
@@ -1,6 +1,8 @@
1
1
  import { recreateProseNodeWithParagraphPropertySource } from "../docx/paragraphPropertySource.js";
2
2
  import { expectRunPropertyChangeMarkAttrs } from "../prosemirror/attrs/index.js";
3
+ import { resolutionRemovesControl, withoutResolvedEnclosures } from "../prosemirror/contentControlRevisions.js";
3
4
  import "../prosemirror/extensions/nodes/SdtExtension.js";
5
+ import { continuedRunMarks } from "../prosemirror/rejoinRunCarriers.js";
4
6
  import { RUN_FORMATTING_MARK_NAMES } from "../prosemirror/runFormattingMarkNames.js";
5
7
  import { reconstructRejectedRunFormattingMarks } from "../prosemirror/runPropertyChangeResolution.js";
6
8
  import { paragraphRunStyleContext } from "../prosemirror/runStyleFormatting.js";
@@ -75,8 +77,26 @@ const resolveInlineNode = ({ node, context, paragraphScope }) => {
75
77
  if (context.keepType) marks = marks.filter((mark) => mark.type !== context.keepType);
76
78
  return marksEqual(marks, node.marks) ? node : node.mark(marks);
77
79
  };
80
+ /**
81
+ * The pieces a revision split off its run, one run again: the headless half of
82
+ * `rejoinRunsAt`, over the children of one inline container.
83
+ */
84
+ const rejoinResolvedRuns = ({ children, resolvedBoundaries, paragraphScope, context }) => {
85
+ for (const index of [...resolvedBoundaries].toSorted((left, right) => left - right)) {
86
+ const left = children[index - 1];
87
+ const right = children[index];
88
+ if (!left || !right) continue;
89
+ const marks = continuedRunMarks({
90
+ left,
91
+ right,
92
+ context: () => resolveParagraphRunStyleScope(paragraphScope, context.styleResolver),
93
+ styleResolver: context.styleResolver
94
+ });
95
+ if (marks !== null) children[index] = right.mark(marks);
96
+ }
97
+ };
78
98
  const resolveInlineContent = ({ node, position, context, inheritedParagraphScope }) => {
79
- const paragraphScope = node.type.name === "paragraph" && context.mode === "reject" ? { paragraph: node } : inheritedParagraphScope;
99
+ const paragraphScope = node.type.name === "paragraph" ? { paragraph: node } : inheritedParagraphScope;
80
100
  const replacementRangeStart = context.replacementRanges.length;
81
101
  let resolvedNode = node;
82
102
  if (node.isInline) {
@@ -96,7 +116,21 @@ const resolveInlineContent = ({ node, position, context, inheritedParagraphScope
96
116
  resolvedNode = resolved;
97
117
  if (resolvedNode.isLeaf) return resolvedNode;
98
118
  }
119
+ if (resolutionRemovesControl({
120
+ control: resolvedNode,
121
+ removeType: context.removeType,
122
+ resolves: () => true
123
+ })) {
124
+ context.replacementRanges.push({
125
+ from: position,
126
+ to: position + node.nodeSize,
127
+ newSize: 0
128
+ });
129
+ return null;
130
+ }
99
131
  const children = [];
132
+ /** Indices into `children` where resolved content began or ended. */
133
+ const resolvedBoundaries = /* @__PURE__ */ new Set();
100
134
  const contentStart = resolvedNode.type.name === "doc" ? 0 : position + 1;
101
135
  let contentChanged = false;
102
136
  resolvedNode.forEach((child, offset) => {
@@ -106,20 +140,23 @@ const resolveInlineContent = ({ node, position, context, inheritedParagraphScope
106
140
  context,
107
141
  ...paragraphScope !== void 0 ? { inheritedParagraphScope: paragraphScope } : {}
108
142
  });
143
+ if (resolved !== child) {
144
+ contentChanged = true;
145
+ resolvedBoundaries.add(children.length);
146
+ }
109
147
  if (resolved) {
110
148
  children.push(resolved);
111
- contentChanged ||= resolved !== child;
112
- } else contentChanged = true;
149
+ if (resolved !== child) resolvedBoundaries.add(children.length);
150
+ }
151
+ });
152
+ const resolvedAttrs = resolvedNode.type.name === "sdt" ? withoutResolvedEnclosures(resolvedNode, () => true) ?? resolvedNode.attrs : resolvedNode.attrs;
153
+ if (!contentChanged && resolvedAttrs === resolvedNode.attrs) return resolvedNode;
154
+ if (contentChanged && resolvedNode.inlineContent) rejoinResolvedRuns({
155
+ children,
156
+ resolvedBoundaries,
157
+ paragraphScope,
158
+ context
113
159
  });
114
- if (!contentChanged) return resolvedNode;
115
- if (children.length === 0 && node.childCount > 0 && resolvedNode.type.name === "sdt") {
116
- context.replacementRanges.splice(replacementRangeStart, context.replacementRanges.length - replacementRangeStart, {
117
- from: position,
118
- to: position + node.nodeSize,
119
- newSize: 0
120
- });
121
- return null;
122
- }
123
160
  let resolvedContent = Fragment.fromArray(children);
124
161
  if (!resolvedNode.type.validContent(resolvedContent)) {
125
162
  const fitted = resolvedNode.type.createAndFill(resolvedNode.attrs, resolvedContent, resolvedNode.marks);
@@ -143,7 +180,7 @@ const resolveInlineContent = ({ node, position, context, inheritedParagraphScope
143
180
  from: position,
144
181
  to: position + resolvedNode.nodeSize
145
182
  });
146
- return rebuildNode(node, resolvedNode.attrs, resolvedContent, resolvedNode.marks);
183
+ return rebuildNode(node, resolvedAttrs, resolvedContent, resolvedNode.marks);
147
184
  };
148
185
  const coalesceReplacementRanges = (replacementRanges) => {
149
186
  const coalesced = [];
@@ -3,7 +3,7 @@ import { serializeBorder } from "../docx/serializer/borderSerializer.js";
3
3
  import { serializeShading, serializeTextFormatting } from "../docx/serializer/textFormattingSerializer.js";
4
4
  import { intAttr } from "../docx/serializer/xmlUtils.js";
5
5
  import { TRANSITIONAL_NAME_BY_STRICT_NAME } from "../docx/strictNames.gen.js";
6
- import { sanitizeCapturedXmlElement } from "../docx/verbatimCapture.js";
6
+ import { createCapturedXmlSanitizer } from "../docx/verbatimCapture.js";
7
7
  import { NAMESPACES, OOXML_NAMESPACE_SCOPE } from "../docx/xmlParser.js";
8
8
  import { escapeXmlAttribute, serializeOnOffElement } from "@stll/docx-core";
9
9
  import { outlineLevelStatedValue, paragraphNumberingSlots, sameEffectiveParagraphNumbering } from "@stll/docx-core/model";
@@ -86,12 +86,12 @@ const serializeNumbering = ({ numPr, numberingChangeXml, numberingInsertionXml }
86
86
  const NUMBERING_CHANGE_ROOT_NAME = /* @__PURE__ */ new Set(["numberingChange"]);
87
87
  const NUMBERING_INSERTION_ROOT_NAME = /* @__PURE__ */ new Set(["ins"]);
88
88
  const WORDPROCESSINGML_NAMESPACE = /* @__PURE__ */ new Set([NAMESPACES.w]);
89
- const replayableNumberingChangeXml = (numberingChangeXml) => sanitizeCapturedXmlElement(numberingChangeXml, {
89
+ const replayableNumberingChangeXml = createCapturedXmlSanitizer({
90
90
  allowedLocalNames: NUMBERING_CHANGE_ROOT_NAME,
91
91
  allowedNamespaceUris: WORDPROCESSINGML_NAMESPACE,
92
92
  inheritedNamespaceScope: OOXML_NAMESPACE_SCOPE
93
93
  });
94
- const replayableNumberingInsertionXml = (numberingInsertionXml) => sanitizeCapturedXmlElement(numberingInsertionXml, {
94
+ const replayableNumberingInsertionXml = createCapturedXmlSanitizer({
95
95
  allowedLocalNames: NUMBERING_INSERTION_ROOT_NAME,
96
96
  allowedNamespaceUris: WORDPROCESSINGML_NAMESPACE,
97
97
  inheritedNamespaceScope: OOXML_NAMESPACE_SCOPE
@@ -0,0 +1,65 @@
1
+ import { document_d_exports } from "../../types/document.js";
2
+ import { FlowBlock, Measure, NoteAreaLayout } from "../../layout-engine/types.js";
3
+ import { ConvertFootnoteOptions, MeasureBlocksFn } from "./footnoteLayout.js";
4
+ import { NoteStoryKey } from "../../types/editor-story.js";
5
+ //#region src/layout-bridge/convert/endnoteLayout.d.ts
6
+ /** One endnote area and the body position it follows. */
7
+ type EndnoteArea = {
8
+ /**
9
+ * The body `sectionBreak` block the area precedes, counted from zero; `null`
10
+ * places it after the last body block.
11
+ */
12
+ beforeSectionBreak: number | null;
13
+ blocks: FlowBlock[];
14
+ measures: Measure[];
15
+ };
16
+ type PreparedEndnoteAreas = {
17
+ areas: readonly EndnoteArea[];
18
+ noteAreas: NoteAreaLayout;
19
+ /** The endnote each area content block belongs to, by block id. */
20
+ noteStoryByBlockId: ReadonlyMap<string, NoteStoryKey>;
21
+ };
22
+ type PrepareEndnoteAreasInput = {
23
+ /** The body's top-level flow blocks, markers already renumbered. */
24
+ blocks: readonly FlowBlock[];
25
+ endnotes: readonly document_d_exports.Endnote[] | undefined;
26
+ /** Endnote `w:id` → reference-order number, as the body markers show it. */
27
+ displayNumbers: ReadonlyMap<number, number>;
28
+ /** Endnote `w:id` → the formatted number the body marker shows. */
29
+ displayTexts: ReadonlyMap<number, string>;
30
+ position: document_d_exports.EndnotePosition;
31
+ /**
32
+ * Section properties by section index: `w:noEndnote`, and the column width
33
+ * an area wraps to in the section it follows.
34
+ */
35
+ sections: readonly (document_d_exports.SectionProperties | undefined)[];
36
+ options: ConvertFootnoteOptions & {
37
+ measureBlocks: MeasureBlocksFn;
38
+ };
39
+ };
40
+ /**
41
+ * Convert and measure every referenced endnote into the areas `w:pos` asks
42
+ * for. `undefined` when no reference names a note, so a document without
43
+ * endnotes lays out exactly as it did before.
44
+ */
45
+ declare function prepareEndnoteAreas(input: PrepareEndnoteAreasInput): PreparedEndnoteAreas | undefined;
46
+ /**
47
+ * The body blocks with each endnote area in place: before the section break
48
+ * that ends the section it follows, or after the last body block.
49
+ */
50
+ declare function spliceEndnoteAreas(blocks: FlowBlock[], measures: Measure[], prepared: PreparedEndnoteAreas | undefined): {
51
+ blocks: FlowBlock[];
52
+ measures: Measure[];
53
+ };
54
+ /**
55
+ * The endnotes a `docEnd` area collects after the body's last block, for
56
+ * `toFlowBlocks`' `trailingEndnoteIds`. Empty for `sectEnd`, whose final area
57
+ * depends on where the references fall.
58
+ */
59
+ declare function trailingEndnoteIds(endnotes: readonly document_d_exports.Endnote[] | undefined, position: document_d_exports.EndnotePosition): ReadonlySet<number>;
60
+ /** `w:pos` for the document: the settings value, else the final section's. */
61
+ declare function resolveEndnotePosition(settingsPosition: document_d_exports.EndnotePosition | undefined, finalSection: document_d_exports.SectionProperties | undefined): document_d_exports.EndnotePosition;
62
+ /** The first column's width in a section: what an endnote area there wraps to. */
63
+ declare function endnoteAreaWidth(section: document_d_exports.SectionProperties | undefined): number;
64
+ //#endregion
65
+ export { PrepareEndnoteAreasInput, PreparedEndnoteAreas, endnoteAreaWidth, prepareEndnoteAreas, resolveEndnotePosition, spliceEndnoteAreas, trailingEndnoteIds };