@stll/folio-core 0.47.6 → 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 (163) hide show
  1. package/dist/ai-edits/word-diff.d.ts +25 -6
  2. package/dist/ai-edits/word-diff.js +210 -38
  3. package/dist/controller/fontReadiness.js +3 -3
  4. package/dist/controller/hyphenationReadiness.d.ts +19 -0
  5. package/dist/controller/hyphenationReadiness.js +47 -0
  6. package/dist/controller/layoutPipeline.d.ts +3 -0
  7. package/dist/controller/layoutPipeline.js +59 -17
  8. package/dist/display-list/build/buildDisplayList.js +39 -12
  9. package/dist/display-list/build/pageFurniture.d.ts +7 -1
  10. package/dist/display-list/build/pageFurniture.js +21 -8
  11. package/dist/display-list/build/paragraphPrimitives.js +5 -4
  12. package/dist/display-list/build/tablePrimitives.js +10 -6
  13. package/dist/docx/attributeRemainder.js +10 -2
  14. package/dist/docx/blockContentParser.d.ts +2 -0
  15. package/dist/docx/blockContentParser.js +77 -62
  16. package/dist/docx/commentParser.d.ts +2 -1
  17. package/dist/docx/commentParser.js +57 -45
  18. package/dist/docx/containerChildren.d.ts +21 -8
  19. package/dist/docx/containerChildren.js +39 -9
  20. package/dist/docx/documentParser.d.ts +5 -1
  21. package/dist/docx/documentParser.js +8 -5
  22. package/dist/docx/documentSectionFacts.d.ts +22 -0
  23. package/dist/docx/documentSectionFacts.js +43 -0
  24. package/dist/docx/fieldParser.d.ts +8 -1
  25. package/dist/docx/fieldParser.js +47 -3
  26. package/dist/docx/fontTableParser.js +34 -27
  27. package/dist/docx/footnoteParser.d.ts +3 -2
  28. package/dist/docx/footnoteParser.js +15 -12
  29. package/dist/docx/groupDrawingParser.d.ts +2 -1
  30. package/dist/docx/groupDrawingParser.js +3 -6
  31. package/dist/docx/headerFooterParser.d.ts +7 -2
  32. package/dist/docx/headerFooterParser.js +15 -5
  33. package/dist/docx/hyperlinkParser.d.ts +48 -36
  34. package/dist/docx/hyperlinkParser.js +97 -82
  35. package/dist/docx/numberingParser.js +108 -84
  36. package/dist/docx/paragraphParser.d.ts +5 -1
  37. package/dist/docx/paragraphParser.js +381 -362
  38. package/dist/docx/paragraphProperties.js +123 -109
  39. package/dist/docx/paragraphPropertySource.d.ts +6 -1
  40. package/dist/docx/paragraphPropertySource.js +9 -1
  41. package/dist/docx/paragraphTextBoxEnrichment.d.ts +2 -1
  42. package/dist/docx/paragraphTextBoxEnrichment.js +17 -6
  43. package/dist/docx/parser.d.ts +7 -1
  44. package/dist/docx/parser.js +33 -16
  45. package/dist/docx/previewBudget.d.ts +55 -33
  46. package/dist/docx/previewBudget.js +59 -65
  47. package/dist/docx/relsParser.js +9 -1
  48. package/dist/docx/rezip.js +41 -58
  49. package/dist/docx/runParser.d.ts +4 -1
  50. package/dist/docx/runParser.js +172 -184
  51. package/dist/docx/sdtProperties.js +87 -84
  52. package/dist/docx/sectionParser.js +169 -160
  53. package/dist/docx/serializer/paragraphSerializer.js +42 -38
  54. package/dist/docx/serializer/settingsSerializer.js +19 -1
  55. package/dist/docx/settingsParser.js +8 -0
  56. package/dist/docx/streamingXmlParser.d.ts +6 -2
  57. package/dist/docx/streamingXmlParser.js +12 -7
  58. package/dist/docx/styleParser.js +34 -8
  59. package/dist/docx/tableParser.d.ts +21 -12
  60. package/dist/docx/tableParser.js +518 -441
  61. package/dist/docx/textBoxParser.d.ts +8 -3
  62. package/dist/docx/textBoxParser.js +3 -3
  63. package/dist/docx/verbatimCapture.d.ts +10 -8
  64. package/dist/docx/verbatimCapture.js +45 -2
  65. package/dist/docx/vmlImageParser.d.ts +15 -13
  66. package/dist/docx/vmlImageParser.js +75 -60
  67. package/dist/docx/vmlPreview.d.ts +3 -3
  68. package/dist/docx/vmlPreview.js +3 -4
  69. package/dist/docx/xmlNamespaceContext.d.ts +9 -0
  70. package/dist/docx/xmlNamespaceContext.js +54 -0
  71. package/dist/docx/xmlParser.d.ts +6 -3
  72. package/dist/docx/xmlParser.js +11 -41
  73. package/dist/docx/xmlResourceLimits.d.ts +2 -1
  74. package/dist/docx/xmlResourceLimits.js +4 -1
  75. package/dist/fonts/headlessMeasure.js +0 -0
  76. package/dist/headless-layout.d.ts +11 -2
  77. package/dist/headless-layout.js +153 -107
  78. package/dist/internal/paragraphFormattingSerialization.js +3 -3
  79. package/dist/layout-bridge/convert/endnoteLayout.d.ts +65 -0
  80. package/dist/layout-bridge/convert/endnoteLayout.js +227 -0
  81. package/dist/layout-bridge/convert/footnoteLayout.d.ts +19 -3
  82. package/dist/layout-bridge/convert/footnoteLayout.js +40 -31
  83. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -7
  84. package/dist/layout-bridge/convert/headerFooterLayout.js +5 -20
  85. package/dist/layout-bridge/convert/paragraphMarkFormatting.d.ts +10 -0
  86. package/dist/layout-bridge/convert/paragraphMarkFormatting.js +59 -0
  87. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +29 -1
  88. package/dist/layout-bridge/convert/toFlowBlocks.js +258 -35
  89. package/dist/layout-bridge/engine/hitTest.js +5 -3
  90. package/dist/layout-bridge/engine/selectionRects.js +5 -3
  91. package/dist/layout-engine/anchorLayoutInCellCompatibility.d.ts +10 -0
  92. package/dist/layout-engine/anchorLayoutInCellCompatibility.js +22 -0
  93. package/dist/layout-engine/index.d.ts +2 -2
  94. package/dist/layout-engine/index.js +70 -11
  95. package/dist/layout-engine/justificationCompatibility.d.ts +1 -1
  96. package/dist/layout-engine/justificationCompatibility.js +9 -5
  97. package/dist/layout-engine/keep-together.d.ts +11 -5
  98. package/dist/layout-engine/keep-together.js +39 -16
  99. package/dist/layout-engine/layoutInstrumentation.d.ts +8 -2
  100. package/dist/layout-engine/layoutInstrumentation.js +8 -1
  101. package/dist/layout-engine/measure/advanceComposition.js +4 -7
  102. package/dist/layout-engine/measure/hyphenationDictionaries.d.ts +74 -0
  103. package/dist/layout-engine/measure/hyphenationDictionaries.js +138 -0
  104. package/dist/layout-engine/measure/hyphenationPreload.d.ts +11 -0
  105. package/dist/layout-engine/measure/hyphenationPreload.js +24 -0
  106. package/dist/layout-engine/measure/lineBreakProvider.d.ts +12 -2
  107. package/dist/layout-engine/measure/lineBreakProvider.js +30 -30
  108. package/dist/layout-engine/measure/lineBreaks.d.ts +6 -1
  109. package/dist/layout-engine/measure/lineBreaks.js +10 -3
  110. package/dist/layout-engine/measure/listMarkerWidth.d.ts +9 -6
  111. package/dist/layout-engine/measure/listMarkerWidth.js +20 -22
  112. package/dist/layout-engine/measure/measureBlocks.js +42 -8
  113. package/dist/layout-engine/measure/measureContainer.js +5 -5
  114. package/dist/layout-engine/measure/measureHelpers.d.ts +15 -3
  115. package/dist/layout-engine/measure/measureHelpers.js +21 -5
  116. package/dist/layout-engine/measure/measureParagraph.js +109 -30
  117. package/dist/layout-engine/measure/measureTypes.d.ts +5 -0
  118. package/dist/layout-engine/measure/tabCalculator.d.ts +2 -0
  119. package/dist/layout-engine/measure/tabCalculator.js +2 -1
  120. package/dist/layout-engine/measure/tableCellFloating.d.ts +2 -0
  121. package/dist/layout-engine/measure/tableCellFloating.js +51 -19
  122. package/dist/layout-engine/measure/tableCellGrid.d.ts +28 -3
  123. package/dist/layout-engine/measure/tableCellGrid.js +45 -5
  124. package/dist/layout-engine/measure/tableFragmentBorderGeometry.js +2 -1
  125. package/dist/layout-engine/noteAreaFlow.d.ts +19 -0
  126. package/dist/layout-engine/noteAreaFlow.js +83 -0
  127. package/dist/layout-engine/paginator.d.ts +10 -1
  128. package/dist/layout-engine/paginator.js +13 -1
  129. package/dist/layout-engine/tableRowBreak.js +3 -1
  130. package/dist/layout-engine/types.d.ts +89 -3
  131. package/dist/layout-engine/types.js +96 -1
  132. package/dist/layout-painter/index.d.ts +3 -0
  133. package/dist/layout-painter/renderPage.js +32 -83
  134. package/dist/layout-painter/renderParagraph.d.ts +6 -1
  135. package/dist/layout-painter/renderParagraph.js +34 -22
  136. package/dist/layout-painter/renderTable.js +26 -13
  137. package/dist/prosemirror/attrs/index.d.ts +9 -9
  138. package/dist/prosemirror/attrs/index.js +43 -11
  139. package/dist/prosemirror/conversion/fromProseDoc.js +8 -1
  140. package/dist/prosemirror/conversion/markInterner.d.ts +21 -0
  141. package/dist/prosemirror/conversion/markInterner.js +90 -0
  142. package/dist/prosemirror/conversion/toProseDoc.js +77 -41
  143. package/dist/prosemirror/extensions/core/DocExtension.js +2 -1
  144. package/dist/prosemirror/extensions/core/ParagraphExtension.js +1 -0
  145. package/dist/prosemirror/extensions/marks/markUtils.d.ts +6 -2
  146. package/dist/prosemirror/extensions/marks/markUtils.js +39 -51
  147. package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +2 -1
  148. package/dist/prosemirror/listMarker.d.ts +1 -0
  149. package/dist/prosemirror/listMarker.js +2 -0
  150. package/dist/prosemirror/listRenderingAttrs.d.ts +1 -0
  151. package/dist/prosemirror/listRenderingAttrs.js +3 -0
  152. package/dist/prosemirror/schema/nodes.d.ts +13 -1
  153. package/dist/prosemirror/textBoxHostParagraph.d.ts +13 -0
  154. package/dist/prosemirror/textBoxHostParagraph.js +21 -0
  155. package/dist/prosemirror/validation.js +91 -80
  156. package/dist/utils/createDocument.js +10 -1
  157. package/dist/utils/scriptSegments.d.ts +33 -4
  158. package/dist/utils/scriptSegments.js +39 -6
  159. package/dist/utils/textFormattingMerge.d.ts +17 -3
  160. package/dist/utils/textFormattingMerge.js +18 -12
  161. package/dist/utils/trailingText.d.ts +22 -0
  162. package/dist/utils/trailingText.js +32 -0
  163. package/package.json +2 -2
@@ -1,6 +1,7 @@
1
1
  import { blockPlainText } from "./blockPlainText.js";
2
2
  import { parseEndnoteProperties, parseFootnoteProperties } from "./notePropertiesParser.js";
3
3
  import { parseParagraph } from "./paragraphParser.js";
4
+ import { standalonePreviewLedger } from "./previewBudget.js";
4
5
  import { captureSdtSiblingMarkers, parseSdtProperties } from "./sdtProperties.js";
5
6
  import { parseTable } from "./tableParser.js";
6
7
  import { findChildren, findWordprocessingChild, getAttributes, getChildElements, getLocalName, parseXml } from "./xmlParser.js";
@@ -27,13 +28,13 @@ function parseNoteId(element) {
27
28
  const parsed = Number.parseInt(id, 10);
28
29
  return Number.isNaN(parsed) ? 0 : parsed;
29
30
  }
30
- function parseNoteBlockContent(element, styles, theme, numbering, rels, media) {
31
+ function parseNoteBlockContent(element, styles, theme, numbering, rels, media, previews) {
31
32
  const blocks = [];
32
33
  for (const child of getChildElements(element)) {
33
34
  const localName = getLocalName(child.name ?? "");
34
- if (localName === "p") blocks.push(parseParagraph(child, styles, theme, numbering, rels));
35
+ if (localName === "p") blocks.push(parseParagraph(child, styles, theme, numbering, rels, media, { previews }));
35
36
  else if (localName === "tbl") {
36
- const table = parseTable(child, styles, theme, numbering, rels, media);
37
+ const table = parseTable(child, styles, theme, numbering, rels, media, { previews });
37
38
  if (table) blocks.push(table);
38
39
  } else if (localName === "sdt") {
39
40
  const sdtPr = findWordprocessingChild(child, "sdtPr");
@@ -46,7 +47,7 @@ function parseNoteBlockContent(element, styles, theme, numbering, rels, media) {
46
47
  blocks.push({
47
48
  type: "blockSdt",
48
49
  properties,
49
- content: sdtContent ? parseNoteBlockContent(sdtContent, styles, theme, numbering, rels, media) : []
50
+ content: sdtContent ? parseNoteBlockContent(sdtContent, styles, theme, numbering, rels, media, previews) : []
50
51
  });
51
52
  }
52
53
  }
@@ -55,12 +56,12 @@ function parseNoteBlockContent(element, styles, theme, numbering, rels, media) {
55
56
  /**
56
57
  * Parse a single footnote element (w:footnote)
57
58
  */
58
- function parseFootnote(element, styles, theme, numbering, rels, media) {
59
+ function parseFootnote(element, styles, theme, numbering, rels, media, previews) {
59
60
  return {
60
61
  type: "footnote",
61
62
  id: parseNoteId(element),
62
63
  noteType: parseNoteType(getNoteAttribute(element, "type")),
63
- content: parseNoteBlockContent(element, styles, theme, numbering, rels, media)
64
+ content: parseNoteBlockContent(element, styles, theme, numbering, rels, media, previews)
64
65
  };
65
66
  }
66
67
  /**
@@ -74,7 +75,7 @@ function parseFootnote(element, styles, theme, numbering, rels, media) {
74
75
  * @param media - Media files for images
75
76
  * @returns FootnoteMap with all footnotes
76
77
  */
77
- function parseFootnotes(footnotesXml, styles = null, theme = null, numbering = null, rels = null, media = null, context) {
78
+ function parseFootnotes(footnotesXml, styles = null, theme = null, numbering = null, rels = null, media = null, context, previews = standalonePreviewLedger()) {
78
79
  const byId = /* @__PURE__ */ new Map();
79
80
  const footnotes = [];
80
81
  if (!footnotesXml) return createFootnoteMap(byId, footnotes);
@@ -82,13 +83,14 @@ function parseFootnotes(footnotesXml, styles = null, theme = null, numbering = n
82
83
  if (!rootElement) return createFootnoteMap(byId, footnotes);
83
84
  const footnoteElements = findChildren(rootElement, "w", "footnote");
84
85
  for (const fnEl of footnoteElements) {
85
- const footnote = parseFootnote(fnEl, styles, theme, numbering, rels, media);
86
+ const footnote = parseFootnote(fnEl, styles, theme, numbering, rels, media, previews);
86
87
  if (byId.has(footnote.id)) {
87
88
  context?.warn({
88
89
  code: PARSE_WARNING_CODES.duplicateNoteId,
89
90
  element: "w:footnote",
90
91
  at: `w:id ${String(footnote.id)}`
91
92
  });
93
+ previews.release(footnote);
92
94
  continue;
93
95
  }
94
96
  byId.set(footnote.id, footnote);
@@ -123,12 +125,12 @@ function createFootnoteMap(byId, footnotes) {
123
125
  /**
124
126
  * Parse a single endnote element (w:endnote)
125
127
  */
126
- function parseEndnote(element, styles, theme, numbering, rels, media) {
128
+ function parseEndnote(element, styles, theme, numbering, rels, media, previews) {
127
129
  return {
128
130
  type: "endnote",
129
131
  id: parseNoteId(element),
130
132
  noteType: parseNoteType(getNoteAttribute(element, "type")),
131
- content: parseNoteBlockContent(element, styles, theme, numbering, rels, media)
133
+ content: parseNoteBlockContent(element, styles, theme, numbering, rels, media, previews)
132
134
  };
133
135
  }
134
136
  /**
@@ -142,7 +144,7 @@ function parseEndnote(element, styles, theme, numbering, rels, media) {
142
144
  * @param media - Media files for images
143
145
  * @returns EndnoteMap with all endnotes
144
146
  */
145
- function parseEndnotes(endnotesXml, styles = null, theme = null, numbering = null, rels = null, media = null, context) {
147
+ function parseEndnotes(endnotesXml, styles = null, theme = null, numbering = null, rels = null, media = null, context, previews = standalonePreviewLedger()) {
146
148
  const byId = /* @__PURE__ */ new Map();
147
149
  const endnotes = [];
148
150
  if (!endnotesXml) return createEndnoteMap(byId, endnotes);
@@ -150,13 +152,14 @@ function parseEndnotes(endnotesXml, styles = null, theme = null, numbering = nul
150
152
  if (!rootElement) return createEndnoteMap(byId, endnotes);
151
153
  const endnoteElements = findChildren(rootElement, "w", "endnote");
152
154
  for (const enEl of endnoteElements) {
153
- const endnote = parseEndnote(enEl, styles, theme, numbering, rels, media);
155
+ const endnote = parseEndnote(enEl, styles, theme, numbering, rels, media, previews);
154
156
  if (byId.has(endnote.id)) {
155
157
  context?.warn({
156
158
  code: PARSE_WARNING_CODES.duplicateNoteId,
157
159
  element: "w:endnote",
158
160
  at: `w:id ${String(endnote.id)}`
159
161
  });
162
+ previews.release(endnote);
160
163
  continue;
161
164
  }
162
165
  byId.set(endnote.id, endnote);
@@ -1,5 +1,6 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
2
  import { XmlElement } from "./xmlParser.js";
3
+ import { PreviewLedger } from "./previewBudget.js";
3
4
  //#region src/docx/groupDrawingParser.d.ts
4
5
  /**
5
6
  * Whether a `w:drawing` carries a WordprocessingGroup payload. A group this
@@ -8,6 +9,6 @@ import { XmlElement } from "./xmlParser.js";
8
9
  */
9
10
  declare const isGroupDrawing: (drawing: XmlElement) => boolean;
10
11
  /** Parse a WordprocessingGroup drawing into a safe SVG-backed image preview. */
11
- declare const parseGroupDrawing: (drawing: XmlElement, rels?: document_d_exports.RelationshipMap, media?: Map<string, document_d_exports.MediaFile>) => document_d_exports.Image | null;
12
+ declare const parseGroupDrawing: (drawing: XmlElement, previews: PreviewLedger, rels?: document_d_exports.RelationshipMap, media?: Map<string, document_d_exports.MediaFile>) => document_d_exports.Image | null;
12
13
  //#endregion
13
14
  export { isGroupDrawing, parseGroupDrawing };
@@ -1,6 +1,5 @@
1
1
  import { emuToPixels } from "../utils/units.js";
2
2
  import { parseImage, resolveImageData } from "./imageParser.js";
3
- import { PREVIEW_KINDS } from "./previewBudget.js";
4
3
  import { findAllDeep, findChildByLocalName, findChildrenByLocalName, getAttribute, getChildElements, getLocalName, getTextContent, parseNumericAttribute } from "./xmlParser.js";
5
4
  import { escapeXmlAttribute, escapeXmlText } from "@stll/docx-core";
6
5
  //#region src/docx/groupDrawingParser.ts
@@ -176,17 +175,15 @@ const groupElement = (drawing) => {
176
175
  */
177
176
  const isGroupDrawing = (drawing) => groupElement(drawing) !== null;
178
177
  /** Parse a WordprocessingGroup drawing into a safe SVG-backed image preview. */
179
- const parseGroupDrawing = (drawing, rels, media) => {
178
+ const parseGroupDrawing = (drawing, previews, rels, media) => {
180
179
  const group = groupElement(drawing);
181
180
  if (!group) return null;
182
181
  const image = parseImage(drawing, void 0, void 0);
183
182
  if (!image || image.size.width <= 0 || image.size.height <= 0) return null;
184
183
  const svg = createSvg(group, image.size.width, image.size.height, rels, media);
185
184
  if (!svg || svg.length > MAX_SVG_CHARACTERS) return null;
186
- image.src = `${PREVIEW_KINDS.wpGroup.srcPrefix}${encodeURIComponent(svg)}`;
187
- image.mimeType = PREVIEW_KINDS.wpGroup.mimeType;
188
- image.filename = PREVIEW_KINDS.wpGroup.filename;
189
- return image;
185
+ const { rId: _rId, src: _src, mimeType: _mimeType, filename: _filename, ...frame } = image;
186
+ return previews.svgImage("wpGroup", svg, frame);
190
187
  };
191
188
  //#endregion
192
189
  export { isGroupDrawing, parseGroupDrawing };
@@ -1,5 +1,6 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
2
  import { NumberingMap } from "./numberingParser.js";
3
+ import { PreviewLedger } from "./previewBudget.js";
3
4
  import { StyleMap } from "./styleParser.js";
4
5
  import { parseFooterReference, parseFooterReferences, parseHeaderReference, parseHeaderReferences } from "./headerFooterRefParser.js";
5
6
  //#region src/docx/headerFooterParser.d.ts
@@ -28,9 +29,11 @@ type HeaderFooterMap = {
28
29
  * @param numbering - Parsed numbering definitions for lists
29
30
  * @param rels - Relationships for resolving hyperlinks/images
30
31
  * @param media - Media files for images
32
+ * @param previews - The ledger of the package this part belongs to; a part
33
+ * read on its own charges its previews to no package
31
34
  * @returns HeaderFooter object
32
35
  */
33
- declare function parseHeader(headerXml: string, hdrFtrType?: document_d_exports.HeaderFooterType, 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): document_d_exports.HeaderFooter;
36
+ declare function parseHeader(headerXml: string, hdrFtrType?: document_d_exports.HeaderFooterType, 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, previews?: PreviewLedger): document_d_exports.HeaderFooter;
34
37
  /**
35
38
  * Parse a footer XML file (word/footer*.xml)
36
39
  *
@@ -41,9 +44,11 @@ declare function parseHeader(headerXml: string, hdrFtrType?: document_d_exports.
41
44
  * @param numbering - Parsed numbering definitions for lists
42
45
  * @param rels - Relationships for resolving hyperlinks/images
43
46
  * @param media - Media files for images
47
+ * @param previews - The ledger of the package this part belongs to; a part
48
+ * read on its own charges its previews to no package
44
49
  * @returns HeaderFooter object
45
50
  */
46
- declare function parseFooter(footerXml: string, hdrFtrType?: document_d_exports.HeaderFooterType, 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): document_d_exports.HeaderFooter;
51
+ declare function parseFooter(footerXml: string, hdrFtrType?: document_d_exports.HeaderFooterType, 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, previews?: PreviewLedger): document_d_exports.HeaderFooter;
47
52
  /**
48
53
  * Generic function to parse either header or footer
49
54
  *
@@ -3,6 +3,7 @@ import { blockPlainText } from "./blockPlainText.js";
3
3
  import { parseFooterReference, parseFooterReferences, parseHeaderReference, parseHeaderReferences } from "./headerFooterRefParser.js";
4
4
  import { assignHeaderFooterVerbatimXml } from "./headerFooterVerbatim.js";
5
5
  import { cloneParagraphWithPropertySource } from "./paragraphPropertySource.js";
6
+ import { standalonePreviewLedger } from "./previewBudget.js";
6
7
  import { parseWatermark } from "./watermarkParser.js";
7
8
  import { collectXmlnsDeclarations, parseXml } from "./xmlParser.js";
8
9
  //#region src/docx/headerFooterParser.ts
@@ -16,9 +17,11 @@ import { collectXmlnsDeclarations, parseXml } from "./xmlParser.js";
16
17
  * @param numbering - Parsed numbering definitions for lists
17
18
  * @param rels - Relationships for resolving hyperlinks/images
18
19
  * @param media - Media files for images
20
+ * @param previews - The ledger of the package this part belongs to; a part
21
+ * read on its own charges its previews to no package
19
22
  * @returns HeaderFooter object
20
23
  */
21
- function parseHeader(headerXml, hdrFtrType = "default", styles = null, theme = null, numbering = null, rels = null, media = null) {
24
+ function parseHeader(headerXml, hdrFtrType = "default", styles = null, theme = null, numbering = null, rels = null, media = null, previews = standalonePreviewLedger()) {
22
25
  const result = {
23
26
  type: "header",
24
27
  hdrFtrType,
@@ -35,11 +38,15 @@ function parseHeader(headerXml, hdrFtrType = "default", styles = null, theme = n
35
38
  }
36
39
  result.content = parseBlockContent(rootElement, styles, theme, numbering, rels, media, {
37
40
  inHeaderFooter: true,
38
- rootXmlns: collectXmlnsDeclarations(rootElement)
41
+ rootXmlns: collectXmlnsDeclarations(rootElement),
42
+ previews
39
43
  });
40
44
  if (watermarkResult) {
41
45
  const host = result.content.at(watermarkResult.blockIndex);
42
- if (host?.type === "paragraph") result.content[watermarkResult.blockIndex] = cloneParagraphWithPropertySource(host, { content: [] });
46
+ if (host?.type === "paragraph") {
47
+ previews.release(host.content);
48
+ result.content[watermarkResult.blockIndex] = cloneParagraphWithPropertySource(host, { content: [] });
49
+ }
43
50
  }
44
51
  assignHeaderFooterVerbatimXml(result, headerXml);
45
52
  return result;
@@ -54,9 +61,11 @@ function parseHeader(headerXml, hdrFtrType = "default", styles = null, theme = n
54
61
  * @param numbering - Parsed numbering definitions for lists
55
62
  * @param rels - Relationships for resolving hyperlinks/images
56
63
  * @param media - Media files for images
64
+ * @param previews - The ledger of the package this part belongs to; a part
65
+ * read on its own charges its previews to no package
57
66
  * @returns HeaderFooter object
58
67
  */
59
- function parseFooter(footerXml, hdrFtrType = "default", styles = null, theme = null, numbering = null, rels = null, media = null) {
68
+ function parseFooter(footerXml, hdrFtrType = "default", styles = null, theme = null, numbering = null, rels = null, media = null, previews = standalonePreviewLedger()) {
60
69
  const result = {
61
70
  type: "footer",
62
71
  hdrFtrType,
@@ -67,7 +76,8 @@ function parseFooter(footerXml, hdrFtrType = "default", styles = null, theme = n
67
76
  if (!rootElement) return result;
68
77
  result.content = parseBlockContent(rootElement, styles, theme, numbering, rels, media, {
69
78
  inHeaderFooter: true,
70
- rootXmlns: collectXmlnsDeclarations(rootElement)
79
+ rootXmlns: collectXmlnsDeclarations(rootElement),
80
+ previews
71
81
  });
72
82
  assignHeaderFooterVerbatimXml(result, footerXml);
73
83
  return result;
@@ -1,6 +1,8 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
2
  import { XmlElement } from "./xmlParser.js";
3
+ import { PreviewLedger } from "./previewBudget.js";
3
4
  import { StyleMap } from "./styleParser.js";
5
+ import { ChildReader } from "./containerChildren.js";
4
6
  //#region src/docx/hyperlinkParser.d.ts
5
7
  /**
6
8
  * Parse a hyperlink element (w:hyperlink)
@@ -13,10 +15,19 @@ import { StyleMap } from "./styleParser.js";
13
15
  * @param styles - Style map for resolving run styles
14
16
  * @param theme - Theme for resolving colors/fonts
15
17
  * @param media - Media files map for image data
18
+ * @param previews - The ledger of the package this link belongs to; a link
19
+ * read on its own charges its previews to no package
16
20
  * @returns Parsed Hyperlink object
17
21
  */
18
- declare function parseHyperlink(node: XmlElement, rels: document_d_exports.RelationshipMap | null, styles?: StyleMap | null, theme?: document_d_exports.Theme | null, media?: Map<string, document_d_exports.MediaFile> | null, rootXmlns?: Record<string, string>): document_d_exports.Hyperlink;
19
- /** What {@link hyperlinkChildHandlers} needs to read one child of a link. */
22
+ declare function parseHyperlink(node: XmlElement, rels: document_d_exports.RelationshipMap | null, styles?: StyleMap | null, theme?: document_d_exports.Theme | null, media?: Map<string, document_d_exports.MediaFile> | null, rootXmlns?: Record<string, string>, previews?: PreviewLedger): document_d_exports.Hyperlink;
23
+ /**
24
+ * A `w:hyperlink`'s own attributes as a link with no children yet.
25
+ *
26
+ * The paragraph parser's revision-segmenting walk reads the children itself,
27
+ * so it takes the shell rather than a link whose children it would discard.
28
+ */
29
+ declare function parseHyperlinkShell(node: XmlElement, rels: document_d_exports.RelationshipMap | null): document_d_exports.Hyperlink;
30
+ /** What {@link HYPERLINK_CHILD_HANDLERS} needs to read one child of a link. */
20
31
  type HyperlinkChildContext = {
21
32
  /** Where a parsed or captured child lands, in source order. */
22
33
  push: (child: document_d_exports.Hyperlink["children"][number]) => void;
@@ -24,6 +35,7 @@ type HyperlinkChildContext = {
24
35
  theme: document_d_exports.Theme | null;
25
36
  rels: document_d_exports.RelationshipMap | null;
26
37
  media: Map<string, document_d_exports.MediaFile> | null;
38
+ previews: PreviewLedger;
27
39
  inScopeXmlns: Record<string, string>;
28
40
  };
29
41
  /**
@@ -43,39 +55,39 @@ type HyperlinkChildContext = {
43
55
  * recognising is recognised by all of them rather than by whichever list
44
56
  * somebody remembered to update.
45
57
  */
46
- declare const hyperlinkChildHandlers: (context: HyperlinkChildContext) => {
47
- r: (child: XmlElement) => void;
48
- bookmarkStart: (child: XmlElement) => void;
49
- bookmarkEnd: (child: XmlElement) => void;
50
- bdo: (child: XmlElement) => void;
51
- dir: (child: XmlElement) => void;
52
- customXml: (child: XmlElement) => void;
53
- smartTag: (child: XmlElement) => void;
54
- del: "capture";
55
- ins: "capture";
56
- moveFrom: "capture";
57
- moveTo: "capture";
58
- commentRangeEnd: "capture";
59
- commentRangeStart: "capture";
60
- customXmlDelRangeEnd: "capture";
61
- customXmlDelRangeStart: "capture";
62
- customXmlInsRangeEnd: "capture";
63
- customXmlInsRangeStart: "capture";
64
- customXmlMoveFromRangeEnd: "capture";
65
- customXmlMoveFromRangeStart: "capture";
66
- customXmlMoveToRangeEnd: "capture";
67
- customXmlMoveToRangeStart: "capture";
68
- fldSimple: (child: XmlElement) => void;
69
- hyperlink: (child: XmlElement) => void;
70
- moveFromRangeEnd: "capture";
71
- moveFromRangeStart: "capture";
72
- moveToRangeEnd: "capture";
73
- moveToRangeStart: "capture";
74
- permEnd: "capture";
75
- permStart: "capture";
76
- proofErr: "capture";
77
- sdt: "capture";
78
- subDoc: "capture";
58
+ declare const HYPERLINK_CHILD_HANDLERS: {
59
+ readonly r: (child: XmlElement, { push, styles, theme, rels, media, previews, inScopeXmlns }: HyperlinkChildContext) => void;
60
+ readonly bookmarkStart: (child: XmlElement, { push }: HyperlinkChildContext) => void;
61
+ readonly bookmarkEnd: (child: XmlElement, { push }: HyperlinkChildContext) => void;
62
+ readonly bdo: ChildReader<HyperlinkChildContext>;
63
+ readonly dir: ChildReader<HyperlinkChildContext>;
64
+ readonly customXml: ChildReader<HyperlinkChildContext>;
65
+ readonly smartTag: ChildReader<HyperlinkChildContext>;
66
+ readonly del: "capture";
67
+ readonly ins: "capture";
68
+ readonly moveFrom: "capture";
69
+ readonly moveTo: "capture";
70
+ readonly commentRangeEnd: "capture";
71
+ readonly commentRangeStart: "capture";
72
+ readonly customXmlDelRangeEnd: "capture";
73
+ readonly customXmlDelRangeStart: "capture";
74
+ readonly customXmlInsRangeEnd: "capture";
75
+ readonly customXmlInsRangeStart: "capture";
76
+ readonly customXmlMoveFromRangeEnd: "capture";
77
+ readonly customXmlMoveFromRangeStart: "capture";
78
+ readonly customXmlMoveToRangeEnd: "capture";
79
+ readonly customXmlMoveToRangeStart: "capture";
80
+ readonly fldSimple: (child: XmlElement, { push }: HyperlinkChildContext) => void;
81
+ readonly hyperlink: (child: XmlElement, { push }: HyperlinkChildContext) => void;
82
+ readonly moveFromRangeEnd: "capture";
83
+ readonly moveFromRangeStart: "capture";
84
+ readonly moveToRangeEnd: "capture";
85
+ readonly moveToRangeStart: "capture";
86
+ readonly permEnd: "capture";
87
+ readonly permStart: "capture";
88
+ readonly proofErr: "capture";
89
+ readonly sdt: "capture";
90
+ readonly subDoc: "capture";
79
91
  };
80
92
  /**
81
93
  * Get the display text of a hyperlink
@@ -169,4 +181,4 @@ declare function createExternalHyperlink(url: string, children: document_d_expor
169
181
  target?: string;
170
182
  }): document_d_exports.Hyperlink;
171
183
  //#endregion
172
- export { HyperlinkChildContext, createExternalHyperlink, createInternalHyperlink, getHyperlinkRuns, getHyperlinkText, getHyperlinkUrl, hasContent, hyperlinkChildHandlers, isExternalLink, isInternalLink, parseHyperlink, resolveHyperlinkUrl };
184
+ export { HYPERLINK_CHILD_HANDLERS, HyperlinkChildContext, createExternalHyperlink, createInternalHyperlink, getHyperlinkRuns, getHyperlinkText, getHyperlinkUrl, hasContent, isExternalLink, isInternalLink, parseHyperlink, parseHyperlinkShell, resolveHyperlinkUrl };
@@ -1,7 +1,8 @@
1
1
  import { sanitizeExternalUrl } from "../utils/urlSecurity.js";
2
- import { CAPTURE, dispatchChildren, ownedElsewhere, withPreservedChildren } from "./containerChildren.js";
2
+ import { CAPTURE, dispatchChildrenWithContext, ownedElsewhere, withPreservedChildren } from "./containerChildren.js";
3
3
  import { inlineWrapperOf } from "./inlineWrapperParser.js";
4
4
  import { preserveInlineChild, preservedInlineCapture } from "./preservedRunContent.js";
5
+ import { standalonePreviewLedger } from "./previewBudget.js";
5
6
  import { RELATIONSHIP_TYPES, resolveRelationshipIdOfType } from "./relsParser.js";
6
7
  import { parseRun } from "./runParser.js";
7
8
  import { runHoldsPayload } from "./runPayload.js";
@@ -44,9 +45,40 @@ function parseBookmarkEnd(node) {
44
45
  * @param styles - Style map for resolving run styles
45
46
  * @param theme - Theme for resolving colors/fonts
46
47
  * @param media - Media files map for image data
48
+ * @param previews - The ledger of the package this link belongs to; a link
49
+ * read on its own charges its previews to no package
47
50
  * @returns Parsed Hyperlink object
48
51
  */
49
- function parseHyperlink(node, rels, styles = null, theme = null, media = null, rootXmlns = {}) {
52
+ function parseHyperlink(node, rels, styles = null, theme = null, media = null, rootXmlns = {}, previews = standalonePreviewLedger()) {
53
+ const hyperlink = parseHyperlinkShell(node, rels);
54
+ const inScopeXmlns = mergeXmlnsDeclarations(rootXmlns, node);
55
+ const children = [];
56
+ hyperlink.children = withPreservedChildren(children, dispatchChildrenWithContext({
57
+ element: node,
58
+ container: "w:hyperlink",
59
+ capturePosition: () => children.length,
60
+ handlers: HYPERLINK_CHILD_HANDLERS,
61
+ context: {
62
+ push: (child) => {
63
+ children.push(child);
64
+ },
65
+ styles,
66
+ theme,
67
+ rels,
68
+ media,
69
+ previews,
70
+ inScopeXmlns
71
+ }
72
+ }), preservedInlineCapture);
73
+ return hyperlink;
74
+ }
75
+ /**
76
+ * A `w:hyperlink`'s own attributes as a link with no children yet.
77
+ *
78
+ * The paragraph parser's revision-segmenting walk reads the children itself,
79
+ * so it takes the shell rather than a link whose children it would discard.
80
+ */
81
+ function parseHyperlinkShell(node, rels) {
50
82
  const hyperlink = {
51
83
  type: "hyperlink",
52
84
  children: []
@@ -72,25 +104,12 @@ function parseHyperlink(node, rels, styles = null, theme = null, media = null, r
72
104
  if (history !== void 0) hyperlink.history = history;
73
105
  const docLocation = getAttribute(node, "w", "docLocation");
74
106
  if (docLocation) hyperlink.docLocation = docLocation;
75
- const inScopeXmlns = mergeXmlnsDeclarations(rootXmlns, node);
76
- const children = [];
77
- hyperlink.children = withPreservedChildren(children, dispatchChildren({
78
- element: node,
79
- container: "w:hyperlink",
80
- capturePosition: () => children.length,
81
- handlers: hyperlinkChildHandlers({
82
- push: (child) => {
83
- children.push(child);
84
- },
85
- styles,
86
- theme,
87
- rels,
88
- media,
89
- inScopeXmlns
90
- })
91
- }), preservedInlineCapture);
92
107
  return hyperlink;
93
108
  }
109
+ /** A transparent wrapper the link holds, read as the wrapper it is. */
110
+ const linkedInlineWrapper = (element) => (child, context) => {
111
+ context.push(parseLinkedInlineWrapper(element, child, context));
112
+ };
94
113
  /**
95
114
  * What a `w:hyperlink` does with every child its content model declares.
96
115
  *
@@ -108,56 +127,50 @@ function parseHyperlink(node, rels, styles = null, theme = null, media = null, r
108
127
  * recognising is recognised by all of them rather than by whichever list
109
128
  * somebody remembered to update.
110
129
  */
111
- const hyperlinkChildHandlers = (context) => {
112
- const { push, styles, theme, rels, media, inScopeXmlns } = context;
113
- const wrapper = (element) => (child) => {
114
- push(parseLinkedInlineWrapper(element, child, context));
115
- };
116
- return {
117
- r: (child) => {
118
- const run = parseRun(child, styles, theme, rels, media, inScopeXmlns);
119
- if (runHoldsPayload(run)) push(run);
120
- },
121
- bookmarkStart: (child) => {
122
- push(parseBookmarkStart(child));
123
- },
124
- bookmarkEnd: (child) => {
125
- push(parseBookmarkEnd(child));
126
- },
127
- bdo: wrapper("bdo"),
128
- dir: wrapper("dir"),
129
- customXml: wrapper("customXml"),
130
- smartTag: wrapper("smartTag"),
131
- del: CAPTURE,
132
- ins: CAPTURE,
133
- moveFrom: CAPTURE,
134
- moveTo: CAPTURE,
135
- commentRangeEnd: CAPTURE,
136
- commentRangeStart: CAPTURE,
137
- customXmlDelRangeEnd: CAPTURE,
138
- customXmlDelRangeStart: CAPTURE,
139
- customXmlInsRangeEnd: CAPTURE,
140
- customXmlInsRangeStart: CAPTURE,
141
- customXmlMoveFromRangeEnd: CAPTURE,
142
- customXmlMoveFromRangeStart: CAPTURE,
143
- customXmlMoveToRangeEnd: CAPTURE,
144
- customXmlMoveToRangeStart: CAPTURE,
145
- fldSimple: (child) => {
146
- push(preserveInlineChild(child));
147
- },
148
- hyperlink: (child) => {
149
- push(preserveInlineChild(child));
150
- },
151
- moveFromRangeEnd: CAPTURE,
152
- moveFromRangeStart: CAPTURE,
153
- moveToRangeEnd: CAPTURE,
154
- moveToRangeStart: CAPTURE,
155
- permEnd: CAPTURE,
156
- permStart: CAPTURE,
157
- proofErr: CAPTURE,
158
- sdt: CAPTURE,
159
- subDoc: CAPTURE
160
- };
130
+ const HYPERLINK_CHILD_HANDLERS = {
131
+ r: (child, { push, styles, theme, rels, media, previews, inScopeXmlns }) => {
132
+ const run = parseRun(child, styles, theme, rels, media, inScopeXmlns, previews);
133
+ if (runHoldsPayload(run)) push(run);
134
+ },
135
+ bookmarkStart: (child, { push }) => {
136
+ push(parseBookmarkStart(child));
137
+ },
138
+ bookmarkEnd: (child, { push }) => {
139
+ push(parseBookmarkEnd(child));
140
+ },
141
+ bdo: linkedInlineWrapper("bdo"),
142
+ dir: linkedInlineWrapper("dir"),
143
+ customXml: linkedInlineWrapper("customXml"),
144
+ smartTag: linkedInlineWrapper("smartTag"),
145
+ del: CAPTURE,
146
+ ins: CAPTURE,
147
+ moveFrom: CAPTURE,
148
+ moveTo: CAPTURE,
149
+ commentRangeEnd: CAPTURE,
150
+ commentRangeStart: CAPTURE,
151
+ customXmlDelRangeEnd: CAPTURE,
152
+ customXmlDelRangeStart: CAPTURE,
153
+ customXmlInsRangeEnd: CAPTURE,
154
+ customXmlInsRangeStart: CAPTURE,
155
+ customXmlMoveFromRangeEnd: CAPTURE,
156
+ customXmlMoveFromRangeStart: CAPTURE,
157
+ customXmlMoveToRangeEnd: CAPTURE,
158
+ customXmlMoveToRangeStart: CAPTURE,
159
+ fldSimple: (child, { push }) => {
160
+ push(preserveInlineChild(child));
161
+ },
162
+ hyperlink: (child, { push }) => {
163
+ push(preserveInlineChild(child));
164
+ },
165
+ moveFromRangeEnd: CAPTURE,
166
+ moveFromRangeStart: CAPTURE,
167
+ moveToRangeEnd: CAPTURE,
168
+ moveToRangeStart: CAPTURE,
169
+ permEnd: CAPTURE,
170
+ permStart: CAPTURE,
171
+ proofErr: CAPTURE,
172
+ sdt: CAPTURE,
173
+ subDoc: CAPTURE
161
174
  };
162
175
  const LINKED_SMART_TAG_PROPERTIES_OWNER = ownedElsewhere({
163
176
  container: "run-level-content",
@@ -169,6 +182,12 @@ const LINKED_CUSTOM_XML_PROPERTIES_OWNER = ownedElsewhere({
169
182
  child: "customXmlPr",
170
183
  reader: "inlineWrapperParser#inlineWrapperOf"
171
184
  });
185
+ const LINKED_INLINE_WRAPPER_HANDLERS = {
186
+ ...HYPERLINK_CHILD_HANDLERS,
187
+ customXmlPr: LINKED_CUSTOM_XML_PROPERTIES_OWNER,
188
+ smartTagPr: LINKED_SMART_TAG_PROPERTIES_OWNER,
189
+ pPr: CAPTURE
190
+ };
172
191
  /**
173
192
  * A transparent wrapper a link holds, with the content the link would hold.
174
193
  *
@@ -185,21 +204,17 @@ const LINKED_CUSTOM_XML_PROPERTIES_OWNER = ownedElsewhere({
185
204
  const parseLinkedInlineWrapper = (element, node, context) => {
186
205
  const inScopeXmlns = mergeXmlnsDeclarations(context.inScopeXmlns, node);
187
206
  const content = [];
188
- return inlineWrapperOf(element, node, withPreservedChildren(content, dispatchChildren({
207
+ return inlineWrapperOf(element, node, withPreservedChildren(content, dispatchChildrenWithContext({
189
208
  element: node,
190
209
  container: "run-level-content",
191
210
  capturePosition: () => content.length,
192
- handlers: {
193
- ...hyperlinkChildHandlers({
194
- ...context,
195
- inScopeXmlns,
196
- push: (child) => {
197
- content.push(child);
198
- }
199
- }),
200
- customXmlPr: LINKED_CUSTOM_XML_PROPERTIES_OWNER,
201
- smartTagPr: LINKED_SMART_TAG_PROPERTIES_OWNER,
202
- pPr: CAPTURE
211
+ handlers: LINKED_INLINE_WRAPPER_HANDLERS,
212
+ context: {
213
+ ...context,
214
+ inScopeXmlns,
215
+ push: (child) => {
216
+ content.push(child);
217
+ }
203
218
  }
204
219
  }), preservedInlineCapture));
205
220
  };
@@ -346,4 +361,4 @@ function createExternalHyperlink(url, children, options) {
346
361
  };
347
362
  }
348
363
  //#endregion
349
- export { createExternalHyperlink, createInternalHyperlink, getHyperlinkRuns, getHyperlinkText, getHyperlinkUrl, hasContent, hyperlinkChildHandlers, isExternalLink, isInternalLink, parseHyperlink, resolveHyperlinkUrl };
364
+ export { HYPERLINK_CHILD_HANDLERS, createExternalHyperlink, createInternalHyperlink, getHyperlinkRuns, getHyperlinkText, getHyperlinkUrl, hasContent, isExternalLink, isInternalLink, parseHyperlink, parseHyperlinkShell, resolveHyperlinkUrl };