@stll/folio-core 0.42.0 → 0.44.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 (206) hide show
  1. package/dist/ai-edits/headless.js +6 -5
  2. package/dist/ai-edits/index.d.ts +2 -2
  3. package/dist/ai-edits/index.js +2 -2
  4. package/dist/ai-edits/snapshot.js +13 -9
  5. package/dist/compare/content-alignment.js +16 -1
  6. package/dist/compare/inline-atoms.js +1 -1
  7. package/dist/compare/style-resources.js +6 -0
  8. package/dist/compat/eigenpal.d.ts +2 -2
  9. package/dist/controller/layoutPipeline.d.ts +2 -1
  10. package/dist/controller/layoutPipeline.js +5 -2
  11. package/dist/controller/layoutSession.d.ts +2 -1
  12. package/dist/controller/layoutSession.js +1 -0
  13. package/dist/docx/appVersionNormalization.d.ts +0 -18
  14. package/dist/docx/blockContentParser.js +10 -1
  15. package/dist/docx/blockRangeMarkers.d.ts +36 -0
  16. package/dist/docx/blockRangeMarkers.js +59 -0
  17. package/dist/docx/bookmarkParser.d.ts +2 -20
  18. package/dist/docx/bookmarkParser.js +6 -30
  19. package/dist/docx/borderParser.d.ts +13 -0
  20. package/dist/docx/borderParser.js +71 -0
  21. package/dist/docx/builtInStyles.d.ts +165 -0
  22. package/dist/docx/builtInStyles.js +239 -0
  23. package/dist/docx/commentIdNormalization.d.ts +10 -0
  24. package/dist/docx/commentIdNormalization.js +33 -0
  25. package/dist/docx/commentParser.d.ts +2 -1
  26. package/dist/docx/commentParser.js +34 -7
  27. package/dist/docx/commentReferenceNormalization.d.ts +4 -1
  28. package/dist/docx/commentReferenceNormalization.js +23 -14
  29. package/dist/docx/danglingRelationshipReferences.d.ts +15 -0
  30. package/dist/docx/danglingRelationshipReferences.js +30 -0
  31. package/dist/docx/defaultParagraphStyle.d.ts +39 -0
  32. package/dist/docx/defaultParagraphStyle.js +54 -0
  33. package/dist/docx/documentParser.d.ts +2 -1
  34. package/dist/docx/documentParser.js +2 -2
  35. package/dist/docx/drawingUtils.d.ts +8 -1
  36. package/dist/docx/drawingUtils.js +12 -3
  37. package/dist/docx/fieldParser.js +3 -5
  38. package/dist/docx/footnoteParser.d.ts +3 -2
  39. package/dist/docx/footnoteParser.js +19 -2
  40. package/dist/docx/groupDrawingParser.js +1 -1
  41. package/dist/docx/headerFooterRefParser.d.ts +15 -3
  42. package/dist/docx/headerFooterRefParser.js +51 -14
  43. package/dist/docx/headerFooterReferenceNormalization.d.ts +4 -1
  44. package/dist/docx/headerFooterReferenceNormalization.js +5 -1
  45. package/dist/docx/hyperlinkParser.js +11 -15
  46. package/dist/docx/imageParser.d.ts +1 -1
  47. package/dist/docx/imageParser.js +22 -18
  48. package/dist/docx/imageRawXml.js +5 -5
  49. package/dist/docx/markupRangeMarker.d.ts +15 -0
  50. package/dist/docx/markupRangeMarker.js +44 -0
  51. package/dist/docx/noteReferenceStyles.d.ts +29 -0
  52. package/dist/docx/noteReferenceStyles.js +70 -0
  53. package/dist/docx/numberingParser.js +2 -1
  54. package/dist/docx/numberingReference.d.ts +21 -0
  55. package/dist/docx/numberingReference.js +21 -0
  56. package/dist/docx/numberingReferenceNormalization.d.ts +14 -2
  57. package/dist/docx/numberingReferenceNormalization.js +51 -9
  58. package/dist/docx/paraIdRangeNormalization.d.ts +0 -19
  59. package/dist/docx/paragraphParser.js +69 -101
  60. package/dist/docx/paragraphPropertySource.js +1 -0
  61. package/dist/docx/paragraphTraversal.d.ts +37 -1
  62. package/dist/docx/paragraphTraversal.js +84 -1
  63. package/dist/docx/parseContext.d.ts +37 -0
  64. package/dist/docx/parseContext.js +67 -0
  65. package/dist/docx/parseWarningMessage.d.ts +6 -0
  66. package/dist/docx/parseWarningMessage.js +44 -0
  67. package/dist/docx/parser.js +86 -24
  68. package/dist/docx/relsParser.d.ts +28 -11
  69. package/dist/docx/relsParser.js +26 -13
  70. package/dist/docx/revisionIdNormalization.js +81 -7
  71. package/dist/docx/rezip.js +85 -27
  72. package/dist/docx/runConsolidator.js +1 -2
  73. package/dist/docx/runParser.d.ts +8 -1
  74. package/dist/docx/runParser.js +30 -48
  75. package/dist/docx/sectionParser.d.ts +2 -1
  76. package/dist/docx/sectionParser.js +21 -65
  77. package/dist/docx/serializer/borderSerializer.d.ts +1 -2
  78. package/dist/docx/serializer/commentSerializer.js +22 -9
  79. package/dist/docx/serializer/documentSerializer.d.ts +1 -5
  80. package/dist/docx/serializer/documentSerializer.js +6 -16
  81. package/dist/docx/serializer/headerFooterSerializer.js +5 -0
  82. package/dist/docx/serializer/markupRangeAttributes.d.ts +8 -0
  83. package/dist/docx/serializer/markupRangeAttributes.js +24 -0
  84. package/dist/docx/serializer/noteSerializer.js +5 -0
  85. package/dist/docx/serializer/paragraphSerializer.d.ts +1 -5
  86. package/dist/docx/serializer/paragraphSerializer.js +29 -35
  87. package/dist/docx/serializer/runSerializer.js +13 -7
  88. package/dist/docx/serializer/tableSerializer.js +28 -13
  89. package/dist/docx/serializer/textFormattingSerializer.d.ts +2 -3
  90. package/dist/docx/server/build.js +8 -1
  91. package/dist/docx/server/createBilingualDocument.js +15 -22
  92. package/dist/docx/server/extractDocxText.js +3 -4
  93. package/dist/docx/shadingParser.d.ts +6 -0
  94. package/dist/docx/shadingParser.js +32 -0
  95. package/dist/docx/shapeParser.js +3 -3
  96. package/dist/docx/styleParser.js +15 -89
  97. package/dist/docx/styleReferenceResolution.d.ts +36 -0
  98. package/dist/docx/styleReferenceResolution.js +51 -0
  99. package/dist/docx/tableLook.d.ts +57 -0
  100. package/dist/docx/tableLook.js +63 -0
  101. package/dist/docx/tableParser.d.ts +7 -9
  102. package/dist/docx/tableParser.js +64 -110
  103. package/dist/docx/textBoxParser.js +4 -4
  104. package/dist/docx/trackedMoveRangeNormalization.d.ts +3 -1
  105. package/dist/docx/trackedMoveRangeNormalization.js +11 -21
  106. package/dist/docx/transitionalSpelling.d.ts +13 -2
  107. package/dist/docx/transitionalSpelling.js +23 -1
  108. package/dist/docx/verbatimCapture.js +4 -11
  109. package/dist/docx/vmlImageParser.js +2 -2
  110. package/dist/docx/watermarkParser.js +2 -2
  111. package/dist/docx/xmlParser.d.ts +22 -32
  112. package/dist/docx/xmlParser.js +36 -21
  113. package/dist/index.d.ts +2 -2
  114. package/dist/internal/pageBreakRunSourceDescendantIndex.d.ts +2 -0
  115. package/dist/internal/pageBreakRunSourceDescendantIndex.js +9 -6
  116. package/dist/internal/paragraphFormattingSerialization.d.ts +2 -3
  117. package/dist/internal/paragraphFormattingSerialization.js +26 -6
  118. package/dist/layout-bridge/convert/footnoteLayout.js +2 -7
  119. package/dist/layout-bridge/convert/templatePreviewFlow.d.ts +19 -11
  120. package/dist/layout-bridge/convert/templatePreviewFlow.js +103 -38
  121. package/dist/layout-bridge/convert/toFlowBlocks.js +12 -3
  122. package/dist/layout-engine/index.d.ts +2 -2
  123. package/dist/layout-engine/index.js +2 -2
  124. package/dist/layout-engine/measure/measureBlocks.js +1 -6
  125. package/dist/layout-engine/types.d.ts +8 -2
  126. package/dist/layout-engine/types.js +35 -2
  127. package/dist/markdown/index.js +1 -1
  128. package/dist/markdown/internals.d.ts +6 -1
  129. package/dist/markdown/internals.js +14 -1
  130. package/dist/markdown/renderBlock.js +35 -21
  131. package/dist/markdown/renderParagraph.js +14 -5
  132. package/dist/markdown/renderRuns.js +4 -3
  133. package/dist/markdown/renderTable.js +4 -3
  134. package/dist/markdown/trailers.js +41 -7
  135. package/dist/markdown/types.d.ts +3 -7
  136. package/dist/prosemirror/attrs/index.js +2 -5
  137. package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +11 -1
  138. package/dist/prosemirror/bookmarkBoundaryAttrs.js +18 -3
  139. package/dist/prosemirror/commands/index.d.ts +3 -3
  140. package/dist/prosemirror/commands/index.js +2 -2
  141. package/dist/prosemirror/commands/pageBreak.js +12 -1
  142. package/dist/prosemirror/commands/paragraph.d.ts +3 -3
  143. package/dist/prosemirror/commands/paragraph.js +2 -2
  144. package/dist/prosemirror/commentIdAllocator.js +2 -7
  145. package/dist/prosemirror/conversion/fromProseDoc.js +131 -41
  146. package/dist/prosemirror/conversion/toProseDoc.d.ts +1 -14
  147. package/dist/prosemirror/conversion/toProseDoc.js +402 -328
  148. package/dist/prosemirror/extensions/core/ParagraphExtension.d.ts +14 -1
  149. package/dist/prosemirror/extensions/core/ParagraphExtension.js +11 -6
  150. package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +3 -3
  151. package/dist/prosemirror/extensions/features/ListExtension.js +42 -4
  152. package/dist/prosemirror/extensions/features/PasteCleanupExtension.d.ts +4 -1
  153. package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +6 -2
  154. package/dist/prosemirror/extensions/features/pastedHeadingStyles.d.ts +7 -0
  155. package/dist/prosemirror/extensions/features/pastedHeadingStyles.js +74 -0
  156. package/dist/prosemirror/extensions/marks/markUtils.d.ts +11 -3
  157. package/dist/prosemirror/extensions/marks/markUtils.js +98 -19
  158. package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +7 -3
  159. package/dist/prosemirror/extensions/nodes/ImageExtension.js +2 -1
  160. package/dist/prosemirror/extensions/nodes/ShapeExtension.js +1 -0
  161. package/dist/prosemirror/extensions/nodes/TableExtension.js +15 -1
  162. package/dist/prosemirror/extensions/types.d.ts +2 -2
  163. package/dist/prosemirror/index.d.ts +3 -3
  164. package/dist/prosemirror/index.js +3 -3
  165. package/dist/prosemirror/insertOperations.d.ts +9 -2
  166. package/dist/prosemirror/insertOperations.js +9 -4
  167. package/dist/prosemirror/listMarker.js +2 -1
  168. package/dist/prosemirror/numberedRefFields.js +2 -1
  169. package/dist/prosemirror/pageBreakRunProjection.d.ts +11 -3
  170. package/dist/prosemirror/pageBreakRunProjection.js +16 -8
  171. package/dist/prosemirror/paragraphFormattingProvenance.d.ts +159 -0
  172. package/dist/prosemirror/paragraphFormattingProvenance.js +106 -0
  173. package/dist/prosemirror/plugins/documentStyles.d.ts +9 -1
  174. package/dist/prosemirror/plugins/documentStyles.js +11 -1
  175. package/dist/prosemirror/plugins/index.d.ts +2 -2
  176. package/dist/prosemirror/plugins/index.js +2 -2
  177. package/dist/prosemirror/plugins/revisionIds.d.ts +11 -2
  178. package/dist/prosemirror/plugins/revisionIds.js +21 -6
  179. package/dist/prosemirror/plugins/templatePreviewValues.d.ts +42 -1
  180. package/dist/prosemirror/plugins/templatePreviewValues.js +217 -14
  181. package/dist/prosemirror/runFormattingReconciliation.js +3 -2
  182. package/dist/prosemirror/runStyleFormatting.d.ts +1 -1
  183. package/dist/prosemirror/schema/nodes.d.ts +31 -0
  184. package/dist/prosemirror/styles/resolvedStyleAttrs.js +4 -1
  185. package/dist/prosemirror/styles/styleResolver.d.ts +9 -0
  186. package/dist/prosemirror/styles/styleResolver.js +15 -6
  187. package/dist/prosemirror/utils/visualLineNavigation.d.ts +22 -2
  188. package/dist/prosemirror/utils/visualLineNavigation.js +80 -63
  189. package/dist/style-engine/styleEngine.d.ts +4 -1
  190. package/dist/style-engine/styleEngine.js +3 -0
  191. package/dist/style-sets/extract.js +35 -11
  192. package/dist/style-sets/stellaStyle.js +46 -39
  193. package/dist/style-sets/styleSetNormalization.d.ts +19 -0
  194. package/dist/style-sets/styleSetNormalization.js +99 -0
  195. package/dist/types/content.d.ts +2 -2
  196. package/dist/utils/createDocument.js +145 -20
  197. package/dist/utils/headingCollector.d.ts +8 -5
  198. package/dist/utils/headingCollector.js +23 -25
  199. package/dist/utils/tableOfContentsStyle.js +9 -2
  200. package/package.json +3 -2
  201. package/dist/docx/textWhitespace.d.ts +0 -4
  202. package/dist/docx/textWhitespace.js +0 -4
  203. package/dist/layout-bridge/engine/tableWidthUtils.d.ts +0 -6
  204. package/dist/layout-bridge/engine/tableWidthUtils.js +0 -25
  205. package/dist/markdown/headings.d.ts +0 -13
  206. package/dist/markdown/headings.js +0 -20
@@ -1,24 +1,31 @@
1
+ import { InlineContentRemovals, visitInlineContentSlots } from "./paragraphTraversal.js";
2
+ import { PARSE_WARNING_CODES } from "@stll/docx-core/model";
1
3
  //#region src/docx/commentReferenceNormalization.ts
4
+ /** The codes this normalisation is reported under, owned here, not at the caller. */
5
+ const DANGLING_COMMENT_REFERENCE_WARNING = PARSE_WARNING_CODES.danglingCommentReference;
6
+ const UNBALANCED_COMMENT_RANGE_WARNING = PARSE_WARNING_CODES.unbalancedCommentRange;
2
7
  const normalizeCommentReferences = ({ documentBody, comments, headers, footers, footnotes, endnotes }) => {
3
8
  const validCommentIds = new Set(comments.map((comment) => comment.id));
4
9
  const rangeMarkers = [];
10
+ const dangling = new InlineContentRemovals();
5
11
  let removedDanglingReferences = 0;
6
12
  const normalizeParagraph = (paragraph) => {
7
- const nextContent = [];
8
- for (const content of paragraph.content) {
9
- if (isCommentMarker(content) && !validCommentIds.has(content.id)) {
13
+ visitInlineContentSlots(paragraph, ({ content, index, item }) => {
14
+ if (isCommentMarker(item) && !validCommentIds.has(item.id)) {
15
+ dangling.mark({
16
+ content,
17
+ index
18
+ });
10
19
  removedDanglingReferences += 1;
11
- continue;
20
+ return;
12
21
  }
13
- nextContent.push(content);
14
- if (isCommentRangeMarker(content)) rangeMarkers.push({
15
- content: nextContent,
16
- index: nextContent.length - 1,
17
- id: content.id,
18
- type: content.type
22
+ if (isCommentRangeMarker(item)) rangeMarkers.push({
23
+ content,
24
+ index,
25
+ id: item.id,
26
+ type: item.type
19
27
  });
20
- }
21
- paragraph.content = nextContent;
28
+ });
22
29
  };
23
30
  const normalizeTable = (table) => {
24
31
  for (const row of table.rows) for (const cell of row.cells) normalizeBlocks(cell.content);
@@ -43,9 +50,11 @@ const normalizeCommentReferences = ({ documentBody, comments, headers, footers,
43
50
  for (const footnote of footnotes ?? []) normalizeBlocks(footnote.content);
44
51
  for (const endnote of endnotes ?? []) normalizeBlocks(endnote.content);
45
52
  for (const comment of comments) for (const paragraph of comment.content) normalizeParagraph(paragraph);
53
+ const reanchoredUnbalancedRanges = reanchorUnbalancedCommentRanges(rangeMarkers);
54
+ dangling.apply();
46
55
  return {
47
56
  removedDanglingReferences,
48
- reanchoredUnbalancedRanges: reanchorUnbalancedCommentRanges(rangeMarkers)
57
+ reanchoredUnbalancedRanges
49
58
  };
50
59
  };
51
60
  const reanchorUnbalancedCommentRanges = (rangeMarkers) => {
@@ -94,4 +103,4 @@ const reanchorCommentRangeMarker = (marker) => {
94
103
  const isCommentMarker = (content) => content.type === "commentRangeStart" || content.type === "commentRangeEnd" || content.type === "commentReference";
95
104
  const isCommentRangeMarker = (content) => content.type === "commentRangeStart" || content.type === "commentRangeEnd";
96
105
  //#endregion
97
- export { normalizeCommentReferences };
106
+ export { DANGLING_COMMENT_REFERENCE_WARNING, UNBALANCED_COMMENT_RANGE_WARNING, normalizeCommentReferences };
@@ -0,0 +1,15 @@
1
+ import { document_d_exports } from "../types/document.js";
2
+ //#region src/docx/danglingRelationshipReferences.d.ts
3
+ type DanglingRelationshipReferences = {
4
+ /** Drawings whose `r:embed` names no relationship. */
5
+ drawings: number;
6
+ /** Hyperlinks whose `r:id` names no relationship. */
7
+ hyperlinks: number;
8
+ };
9
+ type CountDanglingRelationshipReferencesOptions = {
10
+ content: readonly document_d_exports.BlockContent[];
11
+ relationships: document_d_exports.RelationshipMap | undefined;
12
+ };
13
+ declare const countDanglingRelationshipReferences: ({ content, relationships }: CountDanglingRelationshipReferencesOptions) => DanglingRelationshipReferences;
14
+ //#endregion
15
+ export { DanglingRelationshipReferences, countDanglingRelationshipReferences };
@@ -0,0 +1,30 @@
1
+ import { resolveRelationshipId } from "./relsParser.js";
2
+ //#region src/docx/danglingRelationshipReferences.ts
3
+ const countDanglingRelationshipReferences = ({ content, relationships }) => {
4
+ const counts = {
5
+ drawings: 0,
6
+ hyperlinks: 0
7
+ };
8
+ const isDangling = (rId) => resolveRelationshipId(relationships, rId).status === "dangling";
9
+ const visitBlocks = (blocks) => {
10
+ for (const block of blocks) {
11
+ if (block.type === "table") {
12
+ for (const row of block.rows) for (const cell of row.cells) visitBlocks(cell.content);
13
+ continue;
14
+ }
15
+ if (block.type !== "paragraph") continue;
16
+ for (const item of block.content) {
17
+ if (item.type === "hyperlink") {
18
+ if (isDangling(item.rId)) counts.hyperlinks += 1;
19
+ continue;
20
+ }
21
+ if (item.type !== "run") continue;
22
+ for (const child of item.content) if (child.type === "drawing" && isDangling(child.image.rId)) counts.drawings += 1;
23
+ }
24
+ }
25
+ };
26
+ visitBlocks(content);
27
+ return counts;
28
+ };
29
+ //#endregion
30
+ export { countDanglingRelationshipReferences };
@@ -0,0 +1,39 @@
1
+ import { document_d_exports } from "../types/document.js";
2
+ //#region src/docx/defaultParagraphStyle.d.ts
3
+ /** The name Word's built-in default paragraph style always carries in the file. */
4
+ declare const BUILT_IN_DEFAULT_PARAGRAPH_STYLE_NAME = "Normal";
5
+ /** The id English Word gives it, kept as the last resort for the reverse case. */
6
+ declare const BUILT_IN_DEFAULT_PARAGRAPH_STYLE_ID = "Normal";
7
+ /**
8
+ * The formatting Word's default template gives Normal: 8pt (160 twips) after
9
+ * spacing, 1.08x line spacing.
10
+ *
11
+ * A package that declares neither a default paragraph style nor `w:docDefaults`
12
+ * renders as though it declared this, so anything that mints the missing
13
+ * default has to mint the formatting with it.
14
+ */
15
+ declare const BUILT_IN_DEFAULT_PARAGRAPH_FORMATTING: {
16
+ spaceAfter: number;
17
+ lineSpacing: number;
18
+ lineSpacingRule: "auto";
19
+ };
20
+ type MintDefaultParagraphStyleOptions = {
21
+ takenStyleIds: ReadonlySet<string>;
22
+ /** Whether the source declared `w:docDefaults`, which the set carries over. */
23
+ hasDocDefaults: boolean;
24
+ };
25
+ /**
26
+ * The default paragraph style a set needs when its source declared none.
27
+ *
28
+ * The id only has to be free, because the set is what defines it. The
29
+ * formatting has to be the built-in template's whenever the source had no
30
+ * `w:docDefaults`, because that is what the source itself rendered as: a
31
+ * consumer applies its built-in Normal only where no default paragraph style
32
+ * exists, and this minted style is one. Where the source did declare
33
+ * `w:docDefaults`, the set carries them and they remain authoritative, so the
34
+ * minted style states nothing.
35
+ */
36
+ declare const mintDefaultParagraphStyle: ({ takenStyleIds, hasDocDefaults }: MintDefaultParagraphStyleOptions) => document_d_exports.Style;
37
+ declare const resolveDefaultParagraphStyle: (styles: Iterable<document_d_exports.Style>) => document_d_exports.Style | undefined;
38
+ //#endregion
39
+ export { BUILT_IN_DEFAULT_PARAGRAPH_FORMATTING, BUILT_IN_DEFAULT_PARAGRAPH_STYLE_ID, BUILT_IN_DEFAULT_PARAGRAPH_STYLE_NAME, mintDefaultParagraphStyle, resolveDefaultParagraphStyle };
@@ -0,0 +1,54 @@
1
+ //#region src/docx/defaultParagraphStyle.ts
2
+ /** The name Word's built-in default paragraph style always carries in the file. */
3
+ const BUILT_IN_DEFAULT_PARAGRAPH_STYLE_NAME = "Normal";
4
+ /** The id English Word gives it, kept as the last resort for the reverse case. */
5
+ const BUILT_IN_DEFAULT_PARAGRAPH_STYLE_ID = "Normal";
6
+ /**
7
+ * The formatting Word's default template gives Normal: 8pt (160 twips) after
8
+ * spacing, 1.08x line spacing.
9
+ *
10
+ * A package that declares neither a default paragraph style nor `w:docDefaults`
11
+ * renders as though it declared this, so anything that mints the missing
12
+ * default has to mint the formatting with it.
13
+ */
14
+ const BUILT_IN_DEFAULT_PARAGRAPH_FORMATTING = {
15
+ spaceAfter: 160,
16
+ lineSpacing: 259,
17
+ lineSpacingRule: "auto"
18
+ };
19
+ /**
20
+ * The default paragraph style a set needs when its source declared none.
21
+ *
22
+ * The id only has to be free, because the set is what defines it. The
23
+ * formatting has to be the built-in template's whenever the source had no
24
+ * `w:docDefaults`, because that is what the source itself rendered as: a
25
+ * consumer applies its built-in Normal only where no default paragraph style
26
+ * exists, and this minted style is one. Where the source did declare
27
+ * `w:docDefaults`, the set carries them and they remain authoritative, so the
28
+ * minted style states nothing.
29
+ */
30
+ const mintDefaultParagraphStyle = ({ takenStyleIds, hasDocDefaults }) => {
31
+ let styleId = BUILT_IN_DEFAULT_PARAGRAPH_STYLE_ID;
32
+ for (let suffix = 1; takenStyleIds.has(styleId); suffix += 1) styleId = `${BUILT_IN_DEFAULT_PARAGRAPH_STYLE_ID}${suffix}`;
33
+ return {
34
+ styleId,
35
+ type: "paragraph",
36
+ name: BUILT_IN_DEFAULT_PARAGRAPH_STYLE_NAME,
37
+ default: true,
38
+ ...hasDocDefaults ? {} : { pPr: { ...BUILT_IN_DEFAULT_PARAGRAPH_FORMATTING } }
39
+ };
40
+ };
41
+ const resolveDefaultParagraphStyle = (styles) => {
42
+ let flagged;
43
+ let namedBuiltIn;
44
+ let idBuiltIn;
45
+ for (const style of styles) {
46
+ if (style.type !== "paragraph") continue;
47
+ if (style.default) flagged = style;
48
+ if (namedBuiltIn === void 0 && style.name === "Normal") namedBuiltIn = style;
49
+ if (idBuiltIn === void 0 && style.styleId === "Normal") idBuiltIn = style;
50
+ }
51
+ return flagged ?? namedBuiltIn ?? idBuiltIn;
52
+ };
53
+ //#endregion
54
+ export { BUILT_IN_DEFAULT_PARAGRAPH_FORMATTING, BUILT_IN_DEFAULT_PARAGRAPH_STYLE_ID, BUILT_IN_DEFAULT_PARAGRAPH_STYLE_NAME, mintDefaultParagraphStyle, resolveDefaultParagraphStyle };
@@ -1,6 +1,7 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
2
  import { NumberingMap } from "./numberingParser.js";
3
3
  import { StyleMap } from "./styleParser.js";
4
+ import { ParseContext } from "./parseContext.js";
4
5
  //#region src/docx/documentParser.d.ts
5
6
  /**
6
7
  * Extract template variables from text
@@ -27,7 +28,7 @@ declare function extractAllTemplateVariables(content: document_d_exports.BlockCo
27
28
  * @param media - Media files
28
29
  * @returns DocumentBody with content, sections, and template variables
29
30
  */
30
- declare function parseDocumentBody(xml: string, 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.DocumentBody;
31
+ declare function parseDocumentBody(xml: string, 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, context?: ParseContext): document_d_exports.DocumentBody;
31
32
  /**
32
33
  * Get all paragraphs from document body (flattened)
33
34
  */
@@ -119,7 +119,7 @@ function canonicalizeLeadingBodySectionProperties(bodyElement, body) {
119
119
  * @param media - Media files
120
120
  * @returns DocumentBody with content, sections, and template variables
121
121
  */
122
- function parseDocumentBody(xml, styles = null, theme = null, numbering = null, rels = null, media = null) {
122
+ function parseDocumentBody(xml, styles = null, theme = null, numbering = null, rels = null, media = null, context) {
123
123
  const result = { content: [] };
124
124
  if (!xml) return result;
125
125
  const streamed = parseStreamingXml(xml);
@@ -129,7 +129,7 @@ function parseDocumentBody(xml, styles = null, theme = null, numbering = null, r
129
129
  if (!bodyEl) return result;
130
130
  result.content = parseBlockContent(bodyEl, styles, theme, numbering, rels, media, { rootXmlns: collectXmlnsDeclarations(documentEl) });
131
131
  const finalSectPr = findChild(bodyEl, "w", "sectPr");
132
- if (finalSectPr) result.finalSectionProperties = parseSectionProperties(finalSectPr);
132
+ if (finalSectPr) result.finalSectionProperties = parseSectionProperties(finalSectPr, context);
133
133
  canonicalizeLeadingBodySectionProperties(bodyEl, result);
134
134
  result.sections = buildSections(result.content, result.finalSectionProperties);
135
135
  return result;
@@ -67,6 +67,13 @@ declare function parseWrapElement(wrapEl: XmlElement | null, behindDoc: boolean,
67
67
  /**
68
68
  * Parse wrap from an anchor element (finds wrap child internally).
69
69
  */
70
+ /**
71
+ * Read `wp:anchor/@behindDoc`, the flag that puts an anchored object behind the
72
+ * body text. The attribute is xsd:boolean, so `1`, `0`, `true` and `false` are
73
+ * all legal spellings and producers differ: Word writes `1`, others `true`.
74
+ * Absent means in front of the text.
75
+ */
76
+ declare function parseAnchorBehindDoc(anchor: XmlElement): boolean;
70
77
  declare function parseAnchorWrap(anchor: XmlElement): document_d_exports.ImageWrap | undefined;
71
78
  /**
72
79
  * Resolve a ColorValue to a CSS hex string using default theme colors.
@@ -74,4 +81,4 @@ declare function parseAnchorWrap(anchor: XmlElement): document_d_exports.ImageWr
74
81
  */
75
82
  declare function resolveColorValueToHex(color: document_d_exports.ColorValue | undefined): string | undefined;
76
83
  //#endregion
77
- export { THEME_COLOR_TO_DRAWING_SCHEME, WRAP_ELEMENT_NAMES, parseAnchorPosition, parseAnchorWrap, parseColorElement, parseFill, parseOutline, parsePositionH, parsePositionV, parseWrapElement, resolveColorValueToHex };
84
+ export { THEME_COLOR_TO_DRAWING_SCHEME, WRAP_ELEMENT_NAMES, parseAnchorBehindDoc, parseAnchorPosition, parseAnchorWrap, parseColorElement, parseFill, parseOutline, parsePositionH, parsePositionV, parseWrapElement, resolveColorValueToHex };
@@ -1,6 +1,6 @@
1
1
  import { ImageHorizontalAlignmentSchema, ImageHorizontalRelativeToSchema, ImageVerticalAlignmentSchema, ImageVerticalRelativeToSchema, ImageWrapTextSchema, ShapeOutlineStyleSchema, narrowEnum } from "./parserEnums.js";
2
2
  import { captureVerbatimXml } from "./verbatimCapture.js";
3
- import { findByFullName, findChildByLocalName, findChildrenByLocalName, getAttribute, getChildElements, getTextContent, parseNumericAttribute } from "./xmlParser.js";
3
+ import { findByFullName, findChildByLocalName, findChildrenByLocalName, getAttribute, getChildElements, getTextContent, parseNumericAttribute, parseOnOffValue } from "./xmlParser.js";
4
4
  //#region src/docx/drawingUtils.ts
5
5
  /**
6
6
  * Map OOXML scheme names to standard theme color slots.
@@ -361,9 +361,18 @@ function parseWrapElement(wrapEl, behindDoc, anchorDistances) {
361
361
  /**
362
362
  * Parse wrap from an anchor element (finds wrap child internally).
363
363
  */
364
+ /**
365
+ * Read `wp:anchor/@behindDoc`, the flag that puts an anchored object behind the
366
+ * body text. The attribute is xsd:boolean, so `1`, `0`, `true` and `false` are
367
+ * all legal spellings and producers differ: Word writes `1`, others `true`.
368
+ * Absent means in front of the text.
369
+ */
370
+ function parseAnchorBehindDoc(anchor) {
371
+ return parseOnOffValue(getAttribute(anchor, null, "behindDoc")) ?? false;
372
+ }
364
373
  function parseAnchorWrap(anchor) {
365
374
  const children = getChildElements(anchor);
366
- const behindDoc = getAttribute(anchor, null, "behindDoc") === "1";
375
+ const behindDoc = parseAnchorBehindDoc(anchor);
367
376
  const wrapEl = children.find((el) => WRAP_ELEMENT_NAMES.includes(el.name ?? ""));
368
377
  const distT = parseNumericAttribute(anchor, null, "distT");
369
378
  const distB = parseNumericAttribute(anchor, null, "distB");
@@ -409,4 +418,4 @@ function resolveColorValueToHex(color) {
409
418
  if (color.themeColor) return `#${DEFAULT_THEME_COLOR_HEX[color.themeColor] ?? "000000"}`;
410
419
  }
411
420
  //#endregion
412
- export { THEME_COLOR_TO_DRAWING_SCHEME, WRAP_ELEMENT_NAMES, parseAnchorPosition, parseAnchorWrap, parseColorElement, parseFill, parseOutline, parsePositionH, parsePositionV, parseWrapElement, resolveColorValueToHex };
421
+ export { THEME_COLOR_TO_DRAWING_SCHEME, WRAP_ELEMENT_NAMES, parseAnchorBehindDoc, parseAnchorPosition, parseAnchorWrap, parseColorElement, parseFill, parseOutline, parsePositionH, parsePositionV, parseWrapElement, resolveColorValueToHex };
@@ -1,7 +1,7 @@
1
1
  import { formatOoxmlCounter } from "./ooxmlCounterFormatter.js";
2
2
  import { FieldTypeSchema, narrowEnum } from "./parserEnums.js";
3
3
  import { parseRun } from "./runParser.js";
4
- import { findChildren, getAttribute } from "./xmlParser.js";
4
+ import { findChildren, getAttribute, parseOnOffAttribute } from "./xmlParser.js";
5
5
  //#region src/docx/fieldParser.ts
6
6
  /**
7
7
  * All known field types from OOXML specification
@@ -164,10 +164,8 @@ function parseSimpleField(node, styles, theme) {
164
164
  fieldType: parseFieldType(instruction),
165
165
  content: []
166
166
  };
167
- const fldLock = getAttribute(node, "w", "fldLock");
168
- if (fldLock === "1" || fldLock === "true") field.fldLock = true;
169
- const dirty = getAttribute(node, "w", "dirty");
170
- if (dirty === "1" || dirty === "true") field.dirty = true;
167
+ if (parseOnOffAttribute(node, "w", "fldLock") === true) field.fldLock = true;
168
+ if (parseOnOffAttribute(node, "w", "dirty") === true) field.dirty = true;
171
169
  const children = findChildren(node, "w", "r");
172
170
  for (const child of children) {
173
171
  const run = parseRun(child, styles, theme);
@@ -1,6 +1,7 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
2
  import { NumberingMap } from "./numberingParser.js";
3
3
  import { StyleMap } from "./styleParser.js";
4
+ import { ParseContext } from "./parseContext.js";
4
5
  import { parseEndnoteProperties, parseFootnoteProperties } from "./notePropertiesParser.js";
5
6
  //#region src/docx/footnoteParser.d.ts
6
7
  /**
@@ -52,7 +53,7 @@ type EndnoteMap = {
52
53
  * @param media - Media files for images
53
54
  * @returns FootnoteMap with all footnotes
54
55
  */
55
- declare function parseFootnotes(footnotesXml: string | null, 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): FootnoteMap;
56
+ declare function parseFootnotes(footnotesXml: string | null, 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, context?: ParseContext): FootnoteMap;
56
57
  /**
57
58
  * Parse endnotes.xml
58
59
  *
@@ -64,7 +65,7 @@ declare function parseFootnotes(footnotesXml: string | null, styles?: StyleMap |
64
65
  * @param media - Media files for images
65
66
  * @returns EndnoteMap with all endnotes
66
67
  */
67
- declare function parseEndnotes(endnotesXml: string | null, 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): EndnoteMap;
68
+ declare function parseEndnotes(endnotesXml: string | null, 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, context?: ParseContext): EndnoteMap;
68
69
  /**
69
70
  * Get plain text content of a footnote.
70
71
  *
@@ -4,6 +4,7 @@ import { parseParagraph } from "./paragraphParser.js";
4
4
  import { parseSdtProperties } from "./sdtProperties.js";
5
5
  import { parseTable } from "./tableParser.js";
6
6
  import { findChild, findChildren, getAttributes, getChildElements, getLocalName, parseXml } from "./xmlParser.js";
7
+ import { PARSE_WARNING_CODES } from "@stll/docx-core/model";
7
8
  //#region src/docx/footnoteParser.ts
8
9
  /**
9
10
  * Parse note type attribute
@@ -69,7 +70,7 @@ function parseFootnote(element, styles, theme, numbering, rels, media) {
69
70
  * @param media - Media files for images
70
71
  * @returns FootnoteMap with all footnotes
71
72
  */
72
- function parseFootnotes(footnotesXml, styles = null, theme = null, numbering = null, rels = null, media = null) {
73
+ function parseFootnotes(footnotesXml, styles = null, theme = null, numbering = null, rels = null, media = null, context) {
73
74
  const byId = /* @__PURE__ */ new Map();
74
75
  const footnotes = [];
75
76
  if (!footnotesXml) return createFootnoteMap(byId, footnotes);
@@ -78,6 +79,14 @@ function parseFootnotes(footnotesXml, styles = null, theme = null, numbering = n
78
79
  const footnoteElements = findChildren(rootElement, "w", "footnote");
79
80
  for (const fnEl of footnoteElements) {
80
81
  const footnote = parseFootnote(fnEl, styles, theme, numbering, rels, media);
82
+ if (byId.has(footnote.id)) {
83
+ context?.warn({
84
+ code: PARSE_WARNING_CODES.duplicateNoteId,
85
+ element: "w:footnote",
86
+ at: `w:id ${String(footnote.id)}`
87
+ });
88
+ continue;
89
+ }
81
90
  byId.set(footnote.id, footnote);
82
91
  footnotes.push(footnote);
83
92
  }
@@ -129,7 +138,7 @@ function parseEndnote(element, styles, theme, numbering, rels, media) {
129
138
  * @param media - Media files for images
130
139
  * @returns EndnoteMap with all endnotes
131
140
  */
132
- function parseEndnotes(endnotesXml, styles = null, theme = null, numbering = null, rels = null, media = null) {
141
+ function parseEndnotes(endnotesXml, styles = null, theme = null, numbering = null, rels = null, media = null, context) {
133
142
  const byId = /* @__PURE__ */ new Map();
134
143
  const endnotes = [];
135
144
  if (!endnotesXml) return createEndnoteMap(byId, endnotes);
@@ -138,6 +147,14 @@ function parseEndnotes(endnotesXml, styles = null, theme = null, numbering = nul
138
147
  const endnoteElements = findChildren(rootElement, "w", "endnote");
139
148
  for (const enEl of endnoteElements) {
140
149
  const endnote = parseEndnote(enEl, styles, theme, numbering, rels, media);
150
+ if (byId.has(endnote.id)) {
151
+ context?.warn({
152
+ code: PARSE_WARNING_CODES.duplicateNoteId,
153
+ element: "w:endnote",
154
+ at: `w:id ${String(endnote.id)}`
155
+ });
156
+ continue;
157
+ }
141
158
  byId.set(endnote.id, endnote);
142
159
  endnotes.push(endnote);
143
160
  }
@@ -121,7 +121,7 @@ const renderPicture = (picture, index, rels, media) => {
121
121
  if (width <= 0 || height <= 0) return "";
122
122
  const blipFill = findChildByLocalName(picture, "blipFill");
123
123
  const blip = findChildByLocalName(blipFill, "blip");
124
- const { src } = resolveImageData(getAttribute(blip, "r", "embed") ?? getAttribute(blip, "r", "link") ?? "", rels, media);
124
+ const { src } = resolveImageData(getAttribute(blip, "r", "embed") ?? getAttribute(blip, "r", "link") ?? void 0, rels, media);
125
125
  if (!src) return "";
126
126
  const sourceRect = findChildByLocalName(blipFill, "srcRect");
127
127
  const left = Math.max(0, numericAttr(sourceRect, "l")) / CROP_SCALE;
@@ -1,14 +1,26 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
+ import { ParseContext } from "./parseContext.js";
2
3
  import { XmlElement } from "./xmlParser.js";
3
4
  //#region src/docx/headerFooterRefParser.d.ts
5
+ /**
6
+ * Read a `w:type` attribute as one of ECMA-376's three `ST_HdrFtr` values.
7
+ *
8
+ * The enumeration is `even`, `default` and `first` (17.18.36); `default` is
9
+ * the odd-page header, which is why a producer writing `odd` means the same
10
+ * thing. Word opens such a package, so anything outside the enumeration reads
11
+ * as the default the schema itself defaults to. Everything that compares
12
+ * header/footer reference types has to read them through here, or a
13
+ * normalisation at this boundary looks like a lost reference downstream.
14
+ */
15
+ declare function parseHeaderFooterType(typeAttr: string | null, context?: ParseContext): document_d_exports.HeaderFooterType;
4
16
  /**
5
17
  * Parse a header reference from sectPr (w:headerReference)
6
18
  */
7
- declare function parseHeaderReference(element: XmlElement): document_d_exports.HeaderReference;
19
+ declare function parseHeaderReference(element: XmlElement, context?: ParseContext): document_d_exports.HeaderReference | null;
8
20
  /**
9
21
  * Parse a footer reference from sectPr (w:footerReference)
10
22
  */
11
- declare function parseFooterReference(element: XmlElement): document_d_exports.FooterReference;
23
+ declare function parseFooterReference(element: XmlElement, context?: ParseContext): document_d_exports.FooterReference | null;
12
24
  /**
13
25
  * Parse all header references from a sectPr element
14
26
  */
@@ -18,4 +30,4 @@ declare function parseHeaderReferences(sectPr: XmlElement): document_d_exports.H
18
30
  */
19
31
  declare function parseFooterReferences(sectPr: XmlElement): document_d_exports.FooterReference[];
20
32
  //#endregion
21
- export { parseFooterReference, parseFooterReferences, parseHeaderReference, parseHeaderReferences };
33
+ export { parseFooterReference, parseFooterReferences, parseHeaderFooterType, parseHeaderReference, parseHeaderReferences };
@@ -1,34 +1,65 @@
1
1
  import { findChildren, getAttribute } from "./xmlParser.js";
2
+ import { PARSE_WARNING_CODES } from "@stll/docx-core/model";
2
3
  //#region src/docx/headerFooterRefParser.ts
3
4
  /**
4
- * Parse header type attribute
5
+ * Header/Footer Reference Parser
6
+ *
7
+ * Parses header/footer references (w:headerReference, w:footerReference) that
8
+ * appear in section properties. Extracted from headerFooterParser to break the
9
+ * circular dependency: headerFooterParser -> paragraphParser -> sectionParser -> headerFooterParser.
5
10
  */
6
- function parseHeaderFooterType(typeAttr) {
11
+ /**
12
+ * Read a `w:type` attribute as one of ECMA-376's three `ST_HdrFtr` values.
13
+ *
14
+ * The enumeration is `even`, `default` and `first` (17.18.36); `default` is
15
+ * the odd-page header, which is why a producer writing `odd` means the same
16
+ * thing. Word opens such a package, so anything outside the enumeration reads
17
+ * as the default the schema itself defaults to. Everything that compares
18
+ * header/footer reference types has to read them through here, or a
19
+ * normalisation at this boundary looks like a lost reference downstream.
20
+ */
21
+ function parseHeaderFooterType(typeAttr, context) {
7
22
  switch (typeAttr) {
8
23
  case "first": return "first";
9
24
  case "even": return "even";
10
- default: return "default";
25
+ case "default":
26
+ case null: return "default";
27
+ default:
28
+ context?.warn({
29
+ code: PARSE_WARNING_CODES.headerFooterTypeOutsideEnum,
30
+ value: typeAttr,
31
+ element: "w:type"
32
+ });
33
+ return "default";
11
34
  }
12
35
  }
13
- function parseHeaderFooterReference(element) {
14
- const typeAttr = getAttribute(element, "w", "type");
15
- const rId = getAttribute(element, "r", "id") ?? "";
36
+ /**
37
+ * A reference with no `r:id` names no part, so it is not a reference.
38
+ *
39
+ * Coercing the missing attribute to `""` used to put the empty string in the
40
+ * model, where it became a part-map key on one side and an `r:id=""` the
41
+ * schema rejects on the other. Null here keeps the reference out of the model
42
+ * entirely, which is what the source said.
43
+ */
44
+ function parseHeaderFooterReference(element, context) {
45
+ const rId = getAttribute(element, "r", "id");
46
+ if (rId === null || rId.length === 0) return null;
16
47
  return {
17
- type: parseHeaderFooterType(typeAttr),
48
+ type: parseHeaderFooterType(getAttribute(element, "w", "type"), context?.scoped({ at: `r:id "${rId}"` })),
18
49
  rId
19
50
  };
20
51
  }
21
52
  /**
22
53
  * Parse a header reference from sectPr (w:headerReference)
23
54
  */
24
- function parseHeaderReference(element) {
25
- return parseHeaderFooterReference(element);
55
+ function parseHeaderReference(element, context) {
56
+ return parseHeaderFooterReference(element, context);
26
57
  }
27
58
  /**
28
59
  * Parse a footer reference from sectPr (w:footerReference)
29
60
  */
30
- function parseFooterReference(element) {
31
- return parseHeaderFooterReference(element);
61
+ function parseFooterReference(element, context) {
62
+ return parseHeaderFooterReference(element, context);
32
63
  }
33
64
  /**
34
65
  * Parse all header references from a sectPr element
@@ -36,7 +67,10 @@ function parseFooterReference(element) {
36
67
  function parseHeaderReferences(sectPr) {
37
68
  const refs = [];
38
69
  const headerRefElements = findChildren(sectPr, "w", "headerReference");
39
- for (const el of headerRefElements) refs.push(parseHeaderReference(el));
70
+ for (const el of headerRefElements) {
71
+ const ref = parseHeaderReference(el);
72
+ if (ref) refs.push(ref);
73
+ }
40
74
  return refs;
41
75
  }
42
76
  /**
@@ -45,8 +79,11 @@ function parseHeaderReferences(sectPr) {
45
79
  function parseFooterReferences(sectPr) {
46
80
  const refs = [];
47
81
  const footerRefElements = findChildren(sectPr, "w", "footerReference");
48
- for (const el of footerRefElements) refs.push(parseFooterReference(el));
82
+ for (const el of footerRefElements) {
83
+ const ref = parseFooterReference(el);
84
+ if (ref) refs.push(ref);
85
+ }
49
86
  return refs;
50
87
  }
51
88
  //#endregion
52
- export { parseFooterReference, parseFooterReferences, parseHeaderReference, parseHeaderReferences };
89
+ export { parseFooterReference, parseFooterReferences, parseHeaderFooterType, parseHeaderReference, parseHeaderReferences };
@@ -1,5 +1,8 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
2
  //#region src/docx/headerFooterReferenceNormalization.d.ts
3
+ /** The codes this normalisation is reported under, owned here, not at the caller. */
4
+ declare const DANGLING_HEADER_REFERENCE_WARNING: "dangling-header-reference";
5
+ declare const DANGLING_FOOTER_REFERENCE_WARNING: "dangling-footer-reference";
3
6
  type NormalizeHeaderFooterReferencesInput = {
4
7
  documentBody: document_d_exports.DocumentBody;
5
8
  headers?: Map<string, document_d_exports.HeaderFooter>;
@@ -11,4 +14,4 @@ type NormalizeHeaderFooterReferencesResult = {
11
14
  };
12
15
  declare const normalizeHeaderFooterReferences: ({ documentBody, headers, footers }: NormalizeHeaderFooterReferencesInput) => NormalizeHeaderFooterReferencesResult;
13
16
  //#endregion
14
- export { normalizeHeaderFooterReferences };
17
+ export { DANGLING_FOOTER_REFERENCE_WARNING, DANGLING_HEADER_REFERENCE_WARNING, normalizeHeaderFooterReferences };
@@ -1,4 +1,8 @@
1
+ import { PARSE_WARNING_CODES } from "@stll/docx-core/model";
1
2
  //#region src/docx/headerFooterReferenceNormalization.ts
3
+ /** The codes this normalisation is reported under, owned here, not at the caller. */
4
+ const DANGLING_HEADER_REFERENCE_WARNING = PARSE_WARNING_CODES.danglingHeaderReference;
5
+ const DANGLING_FOOTER_REFERENCE_WARNING = PARSE_WARNING_CODES.danglingFooterReference;
2
6
  const normalizeHeaderFooterReferences = ({ documentBody, headers, footers }) => {
3
7
  const seenSectionProperties = /* @__PURE__ */ new Set();
4
8
  let removedDanglingHeaderReferences = 0;
@@ -61,4 +65,4 @@ const removeDanglingReferences = (references, validParts) => {
61
65
  };
62
66
  };
63
67
  //#endregion
64
- export { normalizeHeaderFooterReferences };
68
+ export { DANGLING_FOOTER_REFERENCE_WARNING, DANGLING_HEADER_REFERENCE_WARNING, normalizeHeaderFooterReferences };
@@ -1,6 +1,7 @@
1
1
  import { sanitizeExternalUrl, sanitizeLinkTarget } from "../utils/urlSecurity.js";
2
+ import { RELATIONSHIP_TYPES, resolveRelationshipIdOfType } from "./relsParser.js";
2
3
  import { parseRun } from "./runParser.js";
3
- import { getAttribute, getChildElements, getLocalName, mergeXmlnsDeclarations, parseNumericAttribute } from "./xmlParser.js";
4
+ import { getAttribute, getChildElements, getLocalName, mergeXmlnsDeclarations, parseNumericAttribute, parseOnOffAttribute } from "./xmlParser.js";
4
5
  //#region src/docx/hyperlinkParser.ts
5
6
  /**
6
7
  * Parse bookmark start (w:bookmarkStart)
@@ -49,11 +50,9 @@ function parseHyperlink(node, rels, styles = null, theme = null, media = null, r
49
50
  const rId = getAttribute(node, "r", "id");
50
51
  if (rId) {
51
52
  hyperlink.rId = rId;
52
- if (rels) {
53
- const rel = rels.get(rId);
54
- if (rel) {
55
- if (sanitizeExternalUrl(rel.target)) hyperlink.href = rel.target;
56
- }
53
+ const resolved = resolveRelationshipIdOfType(rels, rId, RELATIONSHIP_TYPES.hyperlink);
54
+ if (resolved.status === "resolved") {
55
+ if (sanitizeExternalUrl(resolved.relationship.target)) hyperlink.href = resolved.relationship.target;
57
56
  }
58
57
  }
59
58
  const anchor = getAttribute(node, "w", "anchor");
@@ -65,8 +64,7 @@ function parseHyperlink(node, rels, styles = null, theme = null, media = null, r
65
64
  if (tooltip) hyperlink.tooltip = tooltip;
66
65
  const tgtFrame = getAttribute(node, "w", "tgtFrame");
67
66
  if (tgtFrame) hyperlink.target = sanitizeLinkTarget(tgtFrame);
68
- const history = getAttribute(node, "w", "history");
69
- if (history === "1" || history === "true") hyperlink.history = true;
67
+ if (parseOnOffAttribute(node, "w", "history") === true) hyperlink.history = true;
70
68
  const docLocation = getAttribute(node, "w", "docLocation");
71
69
  if (docLocation) hyperlink.docLocation = docLocation;
72
70
  const inScopeXmlns = mergeXmlnsDeclarations(rootXmlns, node);
@@ -168,13 +166,11 @@ function getHyperlinkRuns(hyperlink) {
168
166
  * @returns The resolved URL or undefined
169
167
  */
170
168
  function resolveHyperlinkUrl(hyperlink, rels) {
171
- if (hyperlink.rId) {
172
- const rel = rels.get(hyperlink.rId);
173
- if (rel) {
174
- if (sanitizeExternalUrl(rel.target)) {
175
- hyperlink.href = rel.target;
176
- return hyperlink.href;
177
- }
169
+ const resolved = resolveRelationshipIdOfType(rels, hyperlink.rId, RELATIONSHIP_TYPES.hyperlink);
170
+ if (resolved.status === "resolved") {
171
+ if (sanitizeExternalUrl(resolved.relationship.target)) {
172
+ hyperlink.href = resolved.relationship.target;
173
+ return hyperlink.href;
178
174
  }
179
175
  }
180
176
  if (hyperlink.anchor && !hyperlink.href) {
@@ -9,7 +9,7 @@ import { XmlElement } from "./xmlParser.js";
9
9
  * @param media - Media files map
10
10
  * @returns Object with src (data URL or blob), mimeType, and filename
11
11
  */
12
- declare function resolveImageData(rId: string, rels: document_d_exports.RelationshipMap | undefined, media: Map<string, document_d_exports.MediaFile> | undefined): {
12
+ declare function resolveImageData(rId: string | undefined, rels: document_d_exports.RelationshipMap | undefined, media: Map<string, document_d_exports.MediaFile> | undefined): {
13
13
  src?: string;
14
14
  mimeType?: string;
15
15
  filename?: string;