@stll/folio-core 0.45.0 → 0.46.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 (207) hide show
  1. package/dist/ai-edits/apply.js +59 -19
  2. package/dist/ai-edits/headless.js +1 -1
  3. package/dist/compare/compare.js +2 -5
  4. package/dist/compare/scenario.js +2 -5
  5. package/dist/compare/types.d.ts +9 -1
  6. package/dist/compare/types.js +12 -1
  7. package/dist/compat/eigenpal.d.ts +2 -1
  8. package/dist/compat/eigenpal.js +2 -1
  9. package/dist/content-controls/checkboxDisplay.d.ts +11 -0
  10. package/dist/content-controls/checkboxDisplay.js +40 -0
  11. package/dist/content-controls/findContentControls.js +3 -1
  12. package/dist/content-controls/mutateContentControls.js +17 -2
  13. package/dist/controller/contentControlWidgetController.d.ts +1 -0
  14. package/dist/controller/contentControlWidgetController.js +3 -0
  15. package/dist/controller/hiddenEditorApi.js +3 -1
  16. package/dist/controller/hiddenEditorManager.d.ts +1 -1
  17. package/dist/controller/hiddenEditorManager.js +6 -3
  18. package/dist/display-list/build/buildDisplayList.js +20 -1
  19. package/dist/display-list/build/imagePrimitives.d.ts +1 -1
  20. package/dist/display-list/build/imagePrimitives.js +3 -1
  21. package/dist/display-list/build/paragraphPrimitives.js +21 -2
  22. package/dist/display-list/dom/renderDisplayListToDom.js +10 -2
  23. package/dist/display-list/types.d.ts +17 -0
  24. package/dist/docx/attributeRemainder.d.ts +43 -0
  25. package/dist/docx/attributeRemainder.js +65 -0
  26. package/dist/docx/blockContentParser.d.ts +1 -1
  27. package/dist/docx/blockContentParser.js +87 -63
  28. package/dist/docx/blockPlainText.d.ts +3 -4
  29. package/dist/docx/blockPlainText.js +1 -0
  30. package/dist/docx/bookmarkPlacement.js +2 -0
  31. package/dist/docx/commentAnchorIndex.d.ts +30 -0
  32. package/dist/docx/commentAnchorIndex.js +50 -0
  33. package/dist/docx/commentParser.d.ts +1 -1
  34. package/dist/docx/commentParser.js +54 -37
  35. package/dist/docx/commentRangeIntegrity.d.ts +16 -1
  36. package/dist/docx/commentRangeIntegrity.js +42 -1
  37. package/dist/docx/commentRangeJoin.d.ts +9 -0
  38. package/dist/docx/commentRangeJoin.js +33 -0
  39. package/dist/docx/commentReferenceCompletion.d.ts +9 -0
  40. package/dist/docx/commentReferenceCompletion.js +47 -0
  41. package/dist/docx/commentReferenceNormalization.js +1 -0
  42. package/dist/docx/commentReplyMarkers.js +11 -19
  43. package/dist/docx/compatibility.js +1 -0
  44. package/dist/docx/containerChildren.d.ts +111 -0
  45. package/dist/docx/containerChildren.gen.d.ts +28 -0
  46. package/dist/docx/containerChildren.gen.js +246 -0
  47. package/dist/docx/containerChildren.js +103 -0
  48. package/dist/docx/documentParser.d.ts +1 -1
  49. package/dist/docx/documentParser.js +3 -3
  50. package/dist/docx/ensureParaIds.js +17 -7
  51. package/dist/docx/fieldParser.d.ts +1 -1
  52. package/dist/docx/fieldParser.js +4 -4
  53. package/dist/docx/fieldState.d.ts +26 -0
  54. package/dist/docx/fieldState.js +53 -0
  55. package/dist/docx/footnoteParser.d.ts +1 -1
  56. package/dist/docx/graphicFrameLocks.d.ts +16 -4
  57. package/dist/docx/graphicFrameLocks.js +19 -6
  58. package/dist/docx/headerFooterParser.js +1 -1
  59. package/dist/docx/headerFooterReferenceNormalization.js +1 -0
  60. package/dist/docx/hyperlinkParser.d.ts +27 -8
  61. package/dist/docx/hyperlinkParser.js +76 -18
  62. package/dist/docx/imageParser.js +33 -8
  63. package/dist/docx/inlineWrapperContent.d.ts +85 -0
  64. package/dist/docx/inlineWrapperContent.js +84 -0
  65. package/dist/docx/normalizeBaseDirection.js +10 -1
  66. package/dist/docx/paraIdAttribute.d.ts +21 -0
  67. package/dist/docx/paraIdAttribute.js +64 -0
  68. package/dist/docx/paragraphParser.d.ts +1 -1
  69. package/dist/docx/paragraphParser.js +277 -168
  70. package/dist/docx/paragraphPropertySource.js +5 -1
  71. package/dist/docx/paragraphTextBoxEnrichment.d.ts +1 -1
  72. package/dist/docx/paragraphTextBoxEnrichment.js +6 -52
  73. package/dist/docx/paragraphTraversal.js +7 -4
  74. package/dist/docx/parseWarningMessage.js +2 -1
  75. package/dist/docx/preservedRunContent.d.ts +32 -0
  76. package/dist/docx/preservedRunContent.js +86 -0
  77. package/dist/docx/renderedPageBreakNormalization.js +2 -4
  78. package/dist/docx/rezip.js +74 -18
  79. package/dist/docx/runParser.d.ts +1 -1
  80. package/dist/docx/runParser.js +16 -12
  81. package/dist/docx/sectionParser.js +8 -1
  82. package/dist/docx/selectiveXmlPatch.d.ts +46 -2
  83. package/dist/docx/selectiveXmlPatch.js +86 -39
  84. package/dist/docx/serializer/borderSerializer.js +2 -2
  85. package/dist/docx/serializer/commentSerializer.js +5 -7
  86. package/dist/docx/serializer/documentSerializer.js +8 -11
  87. package/dist/docx/serializer/headerFooterSerializer.js +7 -9
  88. package/dist/docx/serializer/noteSerializer.js +8 -8
  89. package/dist/docx/serializer/paragraphSerializer.js +76 -56
  90. package/dist/docx/serializer/runSerializer.js +25 -16
  91. package/dist/docx/serializer/sectionPropertiesSerializer.js +8 -4
  92. package/dist/docx/serializer/tableSerializer.js +18 -8
  93. package/dist/docx/server/createBilingualDocument.js +3 -1
  94. package/dist/docx/server/materializeYjsDocx.d.ts +1 -1
  95. package/dist/docx/server/materializeYjsDocx.js +9 -1
  96. package/dist/docx/server/migrateYjsAttrSchema.d.ts +55 -0
  97. package/dist/docx/server/migrateYjsAttrSchema.js +95 -0
  98. package/dist/docx/shapeParser.js +5 -5
  99. package/dist/docx/tableParser.d.ts +1 -1
  100. package/dist/docx/tableParser.js +206 -85
  101. package/dist/docx/textBoxParser.d.ts +25 -2
  102. package/dist/docx/textBoxParser.js +52 -2
  103. package/dist/docx/unzip.js +5 -4
  104. package/dist/docx/vmlImageParser.d.ts +17 -1
  105. package/dist/docx/vmlImageParser.js +17 -1
  106. package/dist/docx/xmlEncoding.d.ts +5 -0
  107. package/dist/docx/xmlEncoding.js +12 -0
  108. package/dist/docx/xmlParser.d.ts +10 -1
  109. package/dist/docx/xmlParser.js +14 -1
  110. package/dist/headless-layout.js +10 -1
  111. package/dist/index.d.ts +2 -1
  112. package/dist/index.js +2 -1
  113. package/dist/internal/pageBreakRunSourceDescendantIndex.js +5 -2
  114. package/dist/layout-bridge/convert/toFlowBlocks.js +102 -12
  115. package/dist/layout-engine/measure/tableCellFloating.d.ts +2 -0
  116. package/dist/layout-engine/measure/tableCellFloating.js +2 -0
  117. package/dist/layout-engine/types.d.ts +23 -1
  118. package/dist/layout-painter/renderImage.d.ts +5 -1
  119. package/dist/layout-painter/renderImage.js +10 -3
  120. package/dist/layout-painter/renderPage.d.ts +2 -0
  121. package/dist/layout-painter/renderPage.js +4 -0
  122. package/dist/layout-painter/renderParagraph.d.ts +13 -1
  123. package/dist/layout-painter/renderParagraph.js +22 -3
  124. package/dist/managers/autoSaveCodec.d.ts +9 -1
  125. package/dist/managers/autoSaveCodec.js +12 -4
  126. package/dist/markdown/renderBlock.js +1 -0
  127. package/dist/markdown/renderRuns.d.ts +1 -1
  128. package/dist/markdown/renderRuns.js +28 -5
  129. package/dist/markdown/renderTable.js +22 -5
  130. package/dist/markdown/trailers.js +4 -1
  131. package/dist/pdf/images.js +142 -6
  132. package/dist/prosemirror/attrs/index.d.ts +14 -3
  133. package/dist/prosemirror/attrs/index.js +155 -2
  134. package/dist/prosemirror/authoredTransformAttrs.d.ts +28 -0
  135. package/dist/prosemirror/authoredTransformAttrs.js +64 -0
  136. package/dist/prosemirror/commands/contentControls.js +10 -2
  137. package/dist/prosemirror/commands/image.d.ts +9 -2
  138. package/dist/prosemirror/commands/image.js +42 -28
  139. package/dist/prosemirror/commands/pageBreak.js +1 -1
  140. package/dist/prosemirror/commentReferenceAttrs.d.ts +8 -0
  141. package/dist/prosemirror/commentReferenceAttrs.js +33 -0
  142. package/dist/prosemirror/commentReferenceIntegrity.d.ts +47 -0
  143. package/dist/prosemirror/commentReferenceIntegrity.js +43 -0
  144. package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -13
  145. package/dist/prosemirror/conversion/fromProseDoc.js +269 -70
  146. package/dist/prosemirror/conversion/index.d.ts +2 -2
  147. package/dist/prosemirror/conversion/toProseDoc.d.ts +7 -9
  148. package/dist/prosemirror/conversion/toProseDoc.js +468 -308
  149. package/dist/prosemirror/extensions/StarterKit.js +8 -58
  150. package/dist/prosemirror/extensions/core/DocExtension.js +1 -1
  151. package/dist/prosemirror/extensions/core/ParagraphExtension.js +2 -1
  152. package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +45 -27
  153. package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +3 -1
  154. package/dist/prosemirror/extensions/features/ImagePasteExtension.js +5 -3
  155. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +1 -0
  156. package/dist/prosemirror/extensions/markRegistry.d.ts +41 -0
  157. package/dist/prosemirror/extensions/markRegistry.js +75 -0
  158. package/dist/prosemirror/extensions/marks/InlineWrapperExtension.d.ts +18 -0
  159. package/dist/prosemirror/extensions/marks/InlineWrapperExtension.js +63 -0
  160. package/dist/prosemirror/extensions/marks/markUtils.d.ts +2 -1
  161. package/dist/prosemirror/extensions/marks/markUtils.js +47 -4
  162. package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.d.ts +11 -0
  163. package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +87 -0
  164. package/dist/prosemirror/extensions/nodes/FieldExtension.js +9 -7
  165. package/dist/prosemirror/extensions/nodes/ImageExtension.js +16 -0
  166. package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.d.ts +32 -0
  167. package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.js +67 -0
  168. package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.d.ts +16 -0
  169. package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.js +60 -0
  170. package/dist/prosemirror/extensions/nodes/ShapeExtension.js +3 -0
  171. package/dist/prosemirror/extensions/nodes/TableExtension.js +3 -2
  172. package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +5 -1
  173. package/dist/prosemirror/inlineWrapperStack.d.ts +39 -0
  174. package/dist/prosemirror/inlineWrapperStack.js +75 -0
  175. package/dist/prosemirror/pageBreakRunProjection.d.ts +17 -7
  176. package/dist/prosemirror/pageBreakRunProjection.js +19 -9
  177. package/dist/prosemirror/replacedAnnotations.d.ts +59 -0
  178. package/dist/prosemirror/replacedAnnotations.js +165 -0
  179. package/dist/prosemirror/runFormattingInlineCarriers.d.ts +3 -1
  180. package/dist/prosemirror/runFormattingInlineCarriers.js +5 -1
  181. package/dist/prosemirror/schema/index.d.ts +3 -3
  182. package/dist/prosemirror/schema/marks.d.ts +25 -1
  183. package/dist/prosemirror/schema/nodes.d.ts +90 -3
  184. package/dist/prosemirror/schema/nodes.js +16 -1
  185. package/dist/prosemirror/trackedRunInlineAtoms.d.ts +2 -0
  186. package/dist/prosemirror/trackedRunInlineAtoms.js +2 -0
  187. package/dist/prosemirror/validation.js +16 -2
  188. package/dist/prosemirror/yjsDocumentMetadata.d.ts +73 -0
  189. package/dist/prosemirror/yjsDocumentMetadata.js +171 -0
  190. package/dist/prosemirror/zeroWidthAnchors.js +2 -0
  191. package/dist/render-dom/commentAnchorAttributes.d.ts +37 -0
  192. package/dist/render-dom/commentAnchorAttributes.js +54 -0
  193. package/dist/server.d.ts +3 -1
  194. package/dist/server.js +3 -1
  195. package/dist/types/content.d.ts +2 -2
  196. package/dist/utils/clipboard.d.ts +9 -1
  197. package/dist/utils/clipboard.js +27 -1
  198. package/dist/utils/findReplace.js +1 -1
  199. package/dist/utils/imageLuminance.d.ts +15 -0
  200. package/dist/utils/imageLuminance.js +32 -0
  201. package/dist/utils/mergeDocumentContent.js +7 -17
  202. package/dist/utils/replaceText.js +1 -0
  203. package/package.json +2 -2
  204. package/dist/docx/blockRangeMarkers.d.ts +0 -36
  205. package/dist/docx/blockRangeMarkers.js +0 -59
  206. package/dist/prosemirror/yjsParagraphSourceContract.d.ts +0 -9
  207. package/dist/prosemirror/yjsParagraphSourceContract.js +0 -26
@@ -1,6 +1,7 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
- import { StyleMap } from "./styleParser.js";
3
2
  import { XmlElement } from "./xmlParser.js";
3
+ import { StyleMap } from "./styleParser.js";
4
+ import { ChildHandlers } from "./containerChildren.js";
4
5
  //#region src/docx/hyperlinkParser.d.ts
5
6
  /**
6
7
  * Parse a hyperlink element (w:hyperlink)
@@ -16,14 +17,32 @@ import { XmlElement } from "./xmlParser.js";
16
17
  * @returns Parsed Hyperlink object
17
18
  */
18
19
  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;
20
+ /** What {@link hyperlinkChildHandlers} needs to read one child of a link. */
21
+ type HyperlinkChildContext = {
22
+ /** Where a parsed or captured child lands, in source order. */
23
+ push: (child: document_d_exports.Hyperlink["children"][number]) => void;
24
+ styles: StyleMap | null;
25
+ theme: document_d_exports.Theme | null;
26
+ rels: document_d_exports.RelationshipMap | null;
27
+ media: Map<string, document_d_exports.MediaFile> | null;
28
+ inScopeXmlns: Record<string, string>;
29
+ };
19
30
  /**
20
- * One `w:hyperlink` child, or `null` for markup the model does not carry.
21
- *
22
- * Exposed so a caller that has to segment a hyperlink — one holding revision
23
- * wrappers, which the model nests the other way round — parses its plain
24
- * children exactly as {@link parseHyperlink} does.
31
+ * What a `w:hyperlink` does with every child its content model declares.
32
+ *
33
+ * `CT_Hyperlink` is `EG_PContent`, so a link may hold a permission range, a
34
+ * proofing error, a nested field or one of the eight custom-XML revision
35
+ * ranges between its runs; folio models three of the thirty-two names and
36
+ * used to drop the other twenty-nine off the end of a `switch`.
37
+ *
38
+ * Two callers read this one map: {@link parseHyperlink}, and the paragraph
39
+ * parser's revision-segmenting walk, which overrides the four
40
+ * `CT_RunTrackChange` wrappers because OOXML nests a revision inside a link
41
+ * and the model nests the link inside the revision. Everything else is
42
+ * decided here once, so a child one caller starts recognising is recognised
43
+ * by both rather than by whichever list somebody remembered to update.
25
44
  */
26
- declare function parseHyperlinkChild(node: XmlElement, styles: StyleMap | null, theme: document_d_exports.Theme | null, rels: document_d_exports.RelationshipMap | null, media: Map<string, document_d_exports.MediaFile> | null, inScopeXmlns: Record<string, string>): document_d_exports.Hyperlink["children"][number] | null;
45
+ declare const hyperlinkChildHandlers: ({ push, styles, theme, rels, media, inScopeXmlns }: HyperlinkChildContext) => ChildHandlers<"w:hyperlink">;
27
46
  /**
28
47
  * Get the display text of a hyperlink
29
48
  *
@@ -112,4 +131,4 @@ declare function createExternalHyperlink(url: string, children: document_d_expor
112
131
  target?: string;
113
132
  }): document_d_exports.Hyperlink;
114
133
  //#endregion
115
- export { createExternalHyperlink, createInternalHyperlink, getHyperlinkRuns, getHyperlinkText, getHyperlinkUrl, hasContent, isExternalLink, isInternalLink, parseHyperlink, parseHyperlinkChild, resolveHyperlinkUrl };
134
+ export { HyperlinkChildContext, createExternalHyperlink, createInternalHyperlink, getHyperlinkRuns, getHyperlinkText, getHyperlinkUrl, hasContent, hyperlinkChildHandlers, isExternalLink, isInternalLink, parseHyperlink, resolveHyperlinkUrl };
@@ -1,7 +1,9 @@
1
1
  import { sanitizeExternalUrl } from "../utils/urlSecurity.js";
2
+ import { CAPTURE, dispatchChildren, withPreservedChildren } from "./containerChildren.js";
3
+ import { preserveInlineChild, preservedInlineCapture } from "./preservedRunContent.js";
2
4
  import { RELATIONSHIP_TYPES, resolveRelationshipIdOfType } from "./relsParser.js";
3
5
  import { parseRun } from "./runParser.js";
4
- import { getAttribute, getChildElements, getLocalName, mergeXmlnsDeclarations, parseNumericAttribute, parseOnOffAttribute } from "./xmlParser.js";
6
+ import { getAttribute, mergeXmlnsDeclarations, parseNumericAttribute, parseOnOffAttribute } from "./xmlParser.js";
5
7
  //#region src/docx/hyperlinkParser.ts
6
8
  /**
7
9
  * Parse bookmark start (w:bookmarkStart)
@@ -68,27 +70,83 @@ function parseHyperlink(node, rels, styles = null, theme = null, media = null, r
68
70
  const docLocation = getAttribute(node, "w", "docLocation");
69
71
  if (docLocation) hyperlink.docLocation = docLocation;
70
72
  const inScopeXmlns = mergeXmlnsDeclarations(rootXmlns, node);
71
- for (const child of getChildElements(node)) {
72
- const parsed = parseHyperlinkChild(child, styles, theme, rels, media, inScopeXmlns);
73
- if (parsed) hyperlink.children.push(parsed);
74
- }
73
+ const children = [];
74
+ hyperlink.children = withPreservedChildren(children, dispatchChildren({
75
+ element: node,
76
+ container: "w:hyperlink",
77
+ modelledCount: () => children.length,
78
+ handlers: hyperlinkChildHandlers({
79
+ push: (child) => {
80
+ children.push(child);
81
+ },
82
+ styles,
83
+ theme,
84
+ rels,
85
+ media,
86
+ inScopeXmlns
87
+ })
88
+ }), preservedInlineCapture);
75
89
  return hyperlink;
76
90
  }
77
91
  /**
78
- * One `w:hyperlink` child, or `null` for markup the model does not carry.
92
+ * What a `w:hyperlink` does with every child its content model declares.
93
+ *
94
+ * `CT_Hyperlink` is `EG_PContent`, so a link may hold a permission range, a
95
+ * proofing error, a nested field or one of the eight custom-XML revision
96
+ * ranges between its runs; folio models three of the thirty-two names and
97
+ * used to drop the other twenty-nine off the end of a `switch`.
79
98
  *
80
- * Exposed so a caller that has to segment a hyperlink — one holding revision
81
- * wrappers, which the model nests the other way round — parses its plain
82
- * children exactly as {@link parseHyperlink} does.
99
+ * Two callers read this one map: {@link parseHyperlink}, and the paragraph
100
+ * parser's revision-segmenting walk, which overrides the four
101
+ * `CT_RunTrackChange` wrappers because OOXML nests a revision inside a link
102
+ * and the model nests the link inside the revision. Everything else is
103
+ * decided here once, so a child one caller starts recognising is recognised
104
+ * by both rather than by whichever list somebody remembered to update.
83
105
  */
84
- function parseHyperlinkChild(node, styles, theme, rels, media, inScopeXmlns) {
85
- switch (getLocalName(node.name)) {
86
- case "r": return parseRun(node, styles, theme, rels, media, inScopeXmlns);
87
- case "bookmarkStart": return parseBookmarkStart(node);
88
- case "bookmarkEnd": return parseBookmarkEnd(node);
89
- default: return null;
90
- }
91
- }
106
+ const hyperlinkChildHandlers = ({ push, styles, theme, rels, media, inScopeXmlns }) => ({
107
+ r: (child) => {
108
+ push(parseRun(child, styles, theme, rels, media, inScopeXmlns));
109
+ },
110
+ bookmarkStart: (child) => {
111
+ push(parseBookmarkStart(child));
112
+ },
113
+ bookmarkEnd: (child) => {
114
+ push(parseBookmarkEnd(child));
115
+ },
116
+ customXml: (child) => {
117
+ push(preserveInlineChild(child));
118
+ },
119
+ smartTag: (child) => {
120
+ push(preserveInlineChild(child));
121
+ },
122
+ del: CAPTURE,
123
+ ins: CAPTURE,
124
+ moveFrom: CAPTURE,
125
+ moveTo: CAPTURE,
126
+ bdo: CAPTURE,
127
+ commentRangeEnd: CAPTURE,
128
+ commentRangeStart: CAPTURE,
129
+ customXmlDelRangeEnd: CAPTURE,
130
+ customXmlDelRangeStart: CAPTURE,
131
+ customXmlInsRangeEnd: CAPTURE,
132
+ customXmlInsRangeStart: CAPTURE,
133
+ customXmlMoveFromRangeEnd: CAPTURE,
134
+ customXmlMoveFromRangeStart: CAPTURE,
135
+ customXmlMoveToRangeEnd: CAPTURE,
136
+ customXmlMoveToRangeStart: CAPTURE,
137
+ dir: CAPTURE,
138
+ fldSimple: CAPTURE,
139
+ hyperlink: CAPTURE,
140
+ moveFromRangeEnd: CAPTURE,
141
+ moveFromRangeStart: CAPTURE,
142
+ moveToRangeEnd: CAPTURE,
143
+ moveToRangeStart: CAPTURE,
144
+ permEnd: CAPTURE,
145
+ permStart: CAPTURE,
146
+ proofErr: CAPTURE,
147
+ sdt: CAPTURE,
148
+ subDoc: CAPTURE
149
+ });
92
150
  /**
93
151
  * Get the display text of a hyperlink
94
152
  *
@@ -219,4 +277,4 @@ function createExternalHyperlink(url, children, options) {
219
277
  };
220
278
  }
221
279
  //#endregion
222
- export { createExternalHyperlink, createInternalHyperlink, getHyperlinkRuns, getHyperlinkText, getHyperlinkUrl, hasContent, isExternalLink, isInternalLink, parseHyperlink, parseHyperlinkChild, resolveHyperlinkUrl };
280
+ export { createExternalHyperlink, createInternalHyperlink, getHyperlinkRuns, getHyperlinkText, getHyperlinkUrl, hasContent, hyperlinkChildHandlers, isExternalLink, isInternalLink, parseHyperlink, resolveHyperlinkUrl };
@@ -1,3 +1,4 @@
1
+ import { normalizeImageLuminancePercent } from "../utils/imageLuminance.js";
1
2
  import { sanitizeImageSrc } from "../utils/sanitizeImageSrc.js";
2
3
  import { emuToPixels } from "../utils/units.js";
3
4
  import { sanitizeExternalUrl } from "../utils/urlSecurity.js";
@@ -6,9 +7,12 @@ import { parseGraphicFrameLocks } from "./graphicFrameLocks.js";
6
7
  import { parseNonVisualDrawingNames } from "./nonVisualDrawingProps.js";
7
8
  import { RELATIONSHIP_TYPES, resolveRelationshipIdOfType } from "./relsParser.js";
8
9
  import { isTextBoxDrawing } from "./textBoxParser.js";
10
+ import { percentageSpelling } from "./transitionalSpelling.js";
9
11
  import { captureVerbatimXml } from "./verbatimCapture.js";
10
12
  import { findByFullName, findChild, findChildByNamespaceUri, findChildrenByNamespaceUri, getAttribute, getChildElements, getLocalName, getNamespaceUri, parseNumericAttribute, parseOnOffAttribute, parseOnOffValue } from "./xmlParser.js";
11
13
  //#region src/docx/imageParser.ts
14
+ const DRAWINGML_MAIN_NAMESPACE_URIS = /* @__PURE__ */ new Set(["http://schemas.openxmlformats.org/drawingml/2006/main", "http://purl.oclc.org/ooxml/drawingml/main"]);
15
+ const FIXED_PERCENTAGE = /^-?\d+$/u;
12
16
  /**
13
17
  * Convert rotation value (1/60000 of a degree) to degrees
14
18
  *
@@ -16,7 +20,7 @@ import { findByFullName, findChild, findChildByNamespaceUri, findChildrenByNames
16
20
  * @returns Rotation in degrees
17
21
  */
18
22
  function rotToDegrees(rot) {
19
- if (!rot) return;
23
+ if (rot === null || rot === void 0) return;
20
24
  const val = Number.parseInt(rot, 10);
21
25
  if (Number.isNaN(val)) return;
22
26
  return val / 6e4;
@@ -134,15 +138,14 @@ function parseDocProps(docPr) {
134
138
  */
135
139
  function parseTransform(xfrm) {
136
140
  if (!xfrm) return;
137
- const rot = getAttribute(xfrm, null, "rot");
138
- const flipH = parseOnOffValue(getAttribute(xfrm, null, "flipH")) === true;
139
- const flipV = parseOnOffValue(getAttribute(xfrm, null, "flipV")) === true;
140
- const rotation = rotToDegrees(rot);
141
- if (rotation === void 0 && !flipH && !flipV) return;
141
+ const flipH = parseOnOffValue(getAttribute(xfrm, null, "flipH"));
142
+ const flipV = parseOnOffValue(getAttribute(xfrm, null, "flipV"));
143
+ const rotation = rotToDegrees(getAttribute(xfrm, null, "rot"));
144
+ if (rotation === void 0 && flipH === void 0 && flipV === void 0) return;
142
145
  const transform = {};
143
146
  if (rotation !== void 0) transform.rotation = rotation;
144
- if (flipH) transform.flipH = true;
145
- if (flipV) transform.flipV = true;
147
+ if (flipH !== void 0) transform.flipH = flipH;
148
+ if (flipV !== void 0) transform.flipV = flipV;
146
149
  return transform;
147
150
  }
148
151
  /**
@@ -219,6 +222,24 @@ function parseImageOpacity(blip) {
219
222
  if (amt === void 0 || amt >= 1e5) return;
220
223
  return Math.max(0, amt / 1e5);
221
224
  }
225
+ const parseLuminancePercent = (luminance, attribute) => {
226
+ const raw = getAttribute(luminance, null, attribute);
227
+ if (raw === null) return;
228
+ const percent = percentageSpelling(raw) ?? (FIXED_PERCENTAGE.test(raw.trim()) ? Number(raw) / 1e3 : void 0);
229
+ return percent === void 0 || !Number.isFinite(percent) ? void 0 : normalizeImageLuminancePercent(percent);
230
+ };
231
+ /** Parse DrawingML `a:lum` into signed percentage values, preserving explicit zeroes. */
232
+ function parseImageLuminance(blip) {
233
+ const luminance = findChildByNamespaceUri(blip, DRAWINGML_MAIN_NAMESPACE_URIS, "lum");
234
+ if (!luminance) return;
235
+ const brightness = parseLuminancePercent(luminance, "bright");
236
+ const contrast = parseLuminancePercent(luminance, "contrast");
237
+ if (brightness === void 0 && contrast === void 0) return;
238
+ return {
239
+ ...brightness === void 0 ? {} : { brightness },
240
+ ...contrast === void 0 ? {} : { contrast }
241
+ };
242
+ }
222
243
  /**
223
244
  * Extract rId from a:blip element.
224
245
  *
@@ -350,6 +371,7 @@ function parseInline(inlineEl, rels, media) {
350
371
  const rId = extractBlipRId(blip);
351
372
  const crop = parseImageCrop(blipFill);
352
373
  const opacity = parseImageOpacity(blip);
374
+ const effects = parseImageLuminance(blip);
353
375
  const imageData = resolveImageData(rId, rels, media);
354
376
  const transform = parseTransform(findPictureTransform(inlineEl));
355
377
  const distT = parseNumericAttribute(inlineEl, null, "distT") ?? void 0;
@@ -382,6 +404,7 @@ function parseInline(inlineEl, rels, media) {
382
404
  if (transform) image.transform = transform;
383
405
  if (crop) image.crop = crop;
384
406
  if (opacity !== void 0) image.opacity = opacity;
407
+ if (effects !== void 0) image.effects = effects;
385
408
  if (frameLocks) image.frameLocks = frameLocks;
386
409
  const hlink = resolveRelationshipIdOfType(rels, props.hlinkRId, RELATIONSHIP_TYPES.hyperlink);
387
410
  if (hlink.status === "resolved") {
@@ -434,6 +457,7 @@ function parseAnchor(anchorEl, rels, media) {
434
457
  const rId = extractBlipRId(blip);
435
458
  const crop = parseImageCrop(blipFill);
436
459
  const opacity = parseImageOpacity(blip);
460
+ const effects = parseImageLuminance(blip);
437
461
  const imageData = resolveImageData(rId, rels, media);
438
462
  const transform = parseTransform(findPictureTransform(anchorEl));
439
463
  const image = {
@@ -458,6 +482,7 @@ function parseAnchor(anchorEl, rels, media) {
458
482
  if (transform) image.transform = transform;
459
483
  if (crop) image.crop = crop;
460
484
  if (opacity !== void 0) image.opacity = opacity;
485
+ if (effects !== void 0) image.effects = effects;
461
486
  if (frameLocks) image.frameLocks = frameLocks;
462
487
  if (layoutInCell !== void 0) image.layoutInCell = layoutInCell;
463
488
  if (allowOverlap !== void 0) image.allowOverlap = allowOverlap;
@@ -0,0 +1,85 @@
1
+ import { document_d_exports } from "../types/document.js";
2
+ //#region src/docx/inlineWrapperContent.d.ts
3
+ /**
4
+ * What a run-level tracked-change wrapper keeps inside itself (CT_RunTrackChange).
5
+ *
6
+ * Runs, links, fields, bookmark boundaries, equations, nested revisions and
7
+ * markup folio does not model.
8
+ *
9
+ * The transparent wrappers are admitted too: `w:bdo` / `w:dir` state how their
10
+ * content is laid out, and `w:sdt` states what the content is bound to.
11
+ * Neither says anything about the revision, so lifting one out of a revision
12
+ * takes its text out of the revision with it.
13
+ *
14
+ * The range markers are not: a `w:commentRangeStart` or `w:moveFromRangeStart`
15
+ * inside a revision is a marker the revision does not own, and the pairing
16
+ * passes read it as a paragraph-level sibling.
17
+ */
18
+ declare const TRACKED_CHANGE_WRAPPER_CONTENT: {
19
+ readonly inlineWrapper: true;
20
+ readonly bookmarkEnd: true;
21
+ readonly bookmarkStart: true;
22
+ readonly complexField: true;
23
+ readonly deletion: true;
24
+ readonly hyperlink: true;
25
+ readonly inlineSdt: true;
26
+ readonly insertion: true;
27
+ readonly mathEquation: true;
28
+ readonly moveFrom: true;
29
+ readonly moveTo: true;
30
+ readonly preservedInline: true;
31
+ readonly run: true;
32
+ readonly simpleField: true;
33
+ readonly commentRangeEnd: false;
34
+ readonly commentRangeStart: false;
35
+ readonly commentReference: false;
36
+ readonly moveFromRangeEnd: false;
37
+ readonly moveFromRangeStart: false;
38
+ readonly moveToRangeEnd: false;
39
+ readonly moveToRangeStart: false;
40
+ };
41
+ /**
42
+ * What an inline content control keeps inside `<w:sdtContent>`.
43
+ *
44
+ * Mirror of upstream eigenpal/docx-editor PR #482 (commit 29f95751d), plus
45
+ * the bidirectional wrapper: OOXML allows runs, hyperlinks, simple/complex
46
+ * fields, nested SDTs, tracked insertions/deletions/moves, math, markup folio
47
+ * does not model, and the bidirectional controls directly inside
48
+ * `<w:sdtContent>`. Bookmarks and range markers are lifted out as siblings of
49
+ * the SDT so the control itself stays valid.
50
+ */
51
+ declare const INLINE_SDT_CONTENT: {
52
+ readonly inlineWrapper: true;
53
+ readonly complexField: true;
54
+ readonly deletion: true;
55
+ readonly hyperlink: true;
56
+ readonly inlineSdt: true;
57
+ readonly insertion: true;
58
+ readonly mathEquation: true;
59
+ readonly moveFrom: true;
60
+ readonly moveTo: true;
61
+ readonly preservedInline: true;
62
+ readonly run: true;
63
+ readonly simpleField: true;
64
+ readonly bookmarkEnd: false;
65
+ readonly bookmarkStart: false;
66
+ readonly commentRangeEnd: false;
67
+ readonly commentRangeStart: false;
68
+ readonly commentReference: false;
69
+ readonly moveFromRangeEnd: false;
70
+ readonly moveFromRangeStart: false;
71
+ readonly moveToRangeEnd: false;
72
+ readonly moveToRangeStart: false;
73
+ };
74
+ /**
75
+ * Whether a revision wrapper keeps this content inside itself.
76
+ *
77
+ * Generic in the input so a caller that has already narrowed its content
78
+ * keeps that narrowing: filtering a list the bidirectional wrappers are
79
+ * already flattened out of must not put one back into the result type.
80
+ */
81
+ declare const isTrackedChangeWrapperChild: <Content extends document_d_exports.ParagraphContent>(content: Content) => content is Extract<Content, document_d_exports.TrackedRunContent>;
82
+ /** Whether an inline content control keeps this content inside `<w:sdtContent>`. */
83
+ declare const isInlineSdtContent: <Content extends document_d_exports.ParagraphContent>(content: Content) => content is Extract<Content, document_d_exports.InlineSdt["content"][number]>;
84
+ //#endregion
85
+ export { INLINE_SDT_CONTENT, TRACKED_CHANGE_WRAPPER_CONTENT, isInlineSdtContent, isTrackedChangeWrapperChild };
@@ -0,0 +1,84 @@
1
+ //#region src/docx/inlineWrapperContent.ts
2
+ /**
3
+ * What a run-level tracked-change wrapper keeps inside itself (CT_RunTrackChange).
4
+ *
5
+ * Runs, links, fields, bookmark boundaries, equations, nested revisions and
6
+ * markup folio does not model.
7
+ *
8
+ * The transparent wrappers are admitted too: `w:bdo` / `w:dir` state how their
9
+ * content is laid out, and `w:sdt` states what the content is bound to.
10
+ * Neither says anything about the revision, so lifting one out of a revision
11
+ * takes its text out of the revision with it.
12
+ *
13
+ * The range markers are not: a `w:commentRangeStart` or `w:moveFromRangeStart`
14
+ * inside a revision is a marker the revision does not own, and the pairing
15
+ * passes read it as a paragraph-level sibling.
16
+ */
17
+ const TRACKED_CHANGE_WRAPPER_CONTENT = {
18
+ inlineWrapper: true,
19
+ bookmarkEnd: true,
20
+ bookmarkStart: true,
21
+ complexField: true,
22
+ deletion: true,
23
+ hyperlink: true,
24
+ inlineSdt: true,
25
+ insertion: true,
26
+ mathEquation: true,
27
+ moveFrom: true,
28
+ moveTo: true,
29
+ preservedInline: true,
30
+ run: true,
31
+ simpleField: true,
32
+ commentRangeEnd: false,
33
+ commentRangeStart: false,
34
+ commentReference: false,
35
+ moveFromRangeEnd: false,
36
+ moveFromRangeStart: false,
37
+ moveToRangeEnd: false,
38
+ moveToRangeStart: false
39
+ };
40
+ /**
41
+ * What an inline content control keeps inside `<w:sdtContent>`.
42
+ *
43
+ * Mirror of upstream eigenpal/docx-editor PR #482 (commit 29f95751d), plus
44
+ * the bidirectional wrapper: OOXML allows runs, hyperlinks, simple/complex
45
+ * fields, nested SDTs, tracked insertions/deletions/moves, math, markup folio
46
+ * does not model, and the bidirectional controls directly inside
47
+ * `<w:sdtContent>`. Bookmarks and range markers are lifted out as siblings of
48
+ * the SDT so the control itself stays valid.
49
+ */
50
+ const INLINE_SDT_CONTENT = {
51
+ inlineWrapper: true,
52
+ complexField: true,
53
+ deletion: true,
54
+ hyperlink: true,
55
+ inlineSdt: true,
56
+ insertion: true,
57
+ mathEquation: true,
58
+ moveFrom: true,
59
+ moveTo: true,
60
+ preservedInline: true,
61
+ run: true,
62
+ simpleField: true,
63
+ bookmarkEnd: false,
64
+ bookmarkStart: false,
65
+ commentRangeEnd: false,
66
+ commentRangeStart: false,
67
+ commentReference: false,
68
+ moveFromRangeEnd: false,
69
+ moveFromRangeStart: false,
70
+ moveToRangeEnd: false,
71
+ moveToRangeStart: false
72
+ };
73
+ /**
74
+ * Whether a revision wrapper keeps this content inside itself.
75
+ *
76
+ * Generic in the input so a caller that has already narrowed its content
77
+ * keeps that narrowing: filtering a list the bidirectional wrappers are
78
+ * already flattened out of must not put one back into the result type.
79
+ */
80
+ const isTrackedChangeWrapperChild = (content) => TRACKED_CHANGE_WRAPPER_CONTENT[content.type];
81
+ /** Whether an inline content control keeps this content inside `<w:sdtContent>`. */
82
+ const isInlineSdtContent = (content) => INLINE_SDT_CONTENT[content.type];
83
+ //#endregion
84
+ export { INLINE_SDT_CONTENT, TRACKED_CHANGE_WRAPPER_CONTENT, isInlineSdtContent, isTrackedChangeWrapperChild };
@@ -44,13 +44,22 @@ const normalizeTable = (table, styles) => ({
44
44
  ...row,
45
45
  cells: row.cells.map((cell) => ({
46
46
  ...cell,
47
- content: cell.content.map((block) => block.type === "paragraph" ? normalizeParagraph(block, styles) : normalizeTable(block, styles))
47
+ content: cell.content.map((block) => normalizeCellBlock(block, styles))
48
48
  }))
49
49
  }))
50
50
  });
51
+ const normalizeCellBlock = (block, styles) => {
52
+ switch (block.type) {
53
+ case "paragraph": return normalizeParagraph(block, styles);
54
+ case "table": return normalizeTable(block, styles);
55
+ case "preservedBlock": return block;
56
+ default: return block;
57
+ }
58
+ };
51
59
  const normalizeBlocks = (blocks, styles) => blocks.map((block) => {
52
60
  if (block.type === "paragraph") return normalizeParagraph(block, styles);
53
61
  if (block.type === "table") return normalizeTable(block, styles);
62
+ if (block.type === "preservedBlock") return block;
54
63
  return {
55
64
  ...block,
56
65
  content: normalizeBlocks(block.content, styles)
@@ -0,0 +1,21 @@
1
+ import { XmlElement } from "./xmlParser.js";
2
+ //#region src/docx/paraIdAttribute.d.ts
3
+ /**
4
+ * The namespaces a paraId-valued attribute may be written in: the Word 2010,
5
+ * 2012 and 2018 wordml extensions.
6
+ *
7
+ * The 2018 URI is read from the serializer's table rather than retyped, so the
8
+ * spelling folio writes and the spelling it accepts cannot drift.
9
+ */
10
+ declare const PARA_ID_NAMESPACE_URIS: ReadonlySet<string>;
11
+ /** The paraId this element carries, or `undefined` when it carries none. */
12
+ declare const paraIdAttribute: (element: XmlElement) => string | undefined;
13
+ /** The paraId of the parent this element names, by the same rule. */
14
+ declare const paraIdParentAttribute: (element: XmlElement) => string | undefined;
15
+ /**
16
+ * The textId this element carries: a paragraph identity written beside
17
+ * `paraId`, in the same namespaces and by the same rule.
18
+ */
19
+ declare const textIdAttribute: (element: XmlElement) => string | undefined;
20
+ //#endregion
21
+ export { PARA_ID_NAMESPACE_URIS, paraIdAttribute, paraIdParentAttribute, textIdAttribute };
@@ -0,0 +1,64 @@
1
+ import { OOXML_NAMESPACES } from "./serializer/partNamespaces.js";
2
+ import { NAMESPACES, WORDPROCESSINGML_NAMESPACE_URIS, getAttributeByNamespaceUri } from "./xmlParser.js";
3
+ //#region src/docx/paraIdAttribute.ts
4
+ /**
5
+ * The one reader for "the paraId written on this element".
6
+ *
7
+ * A `paraId` is a join key: `w15:commentEx/@w15:paraId`,
8
+ * `w16cex:comment/@w16cex:paraId` and `w15:paraIdParent` all name a paragraph
9
+ * through the `w14:paraId` it carries. Three Word generations write the same
10
+ * key under three prefixes, and a producer is free to bind any of those
11
+ * namespaces to a prefix of its own choosing, so the key must be resolved by
12
+ * namespace URI. Resolving it by local name alone is worse than missing it: an
13
+ * unrelated `vendor:paraId` would key a comment into another thread and carry
14
+ * that thread's date, parent and resolved state.
15
+ *
16
+ * Every reader of the key calls this, so no call site can come to disagree
17
+ * with another about which attribute is a paraId.
18
+ */
19
+ /**
20
+ * The namespaces a paraId-valued attribute may be written in: the Word 2010,
21
+ * 2012 and 2018 wordml extensions.
22
+ *
23
+ * The 2018 URI is read from the serializer's table rather than retyped, so the
24
+ * spelling folio writes and the spelling it accepts cannot drift.
25
+ */
26
+ const PARA_ID_NAMESPACE_URIS = /* @__PURE__ */ new Set([
27
+ NAMESPACES.w14,
28
+ NAMESPACES.w15,
29
+ OOXML_NAMESPACES.w16cex.uri
30
+ ]);
31
+ /**
32
+ * The conventional prefixes, read literally as a last resort.
33
+ *
34
+ * A part that writes `w14:paraId` without declaring `xmlns:w14` is malformed,
35
+ * and no URI lookup can resolve it; Word reads those files, so folio does too.
36
+ */
37
+ const CONVENTIONAL_PARA_ID_PREFIXES = [
38
+ "w14",
39
+ "w15",
40
+ "w16cex"
41
+ ];
42
+ const paraIdValuedAttribute = (element, localName) => {
43
+ const byUri = getAttributeByNamespaceUri(element, PARA_ID_NAMESPACE_URIS, localName);
44
+ if (byUri !== null) return byUri;
45
+ for (const prefix of CONVENTIONAL_PARA_ID_PREFIXES) {
46
+ const literal = element.attributes?.[`${prefix}:${localName}`];
47
+ if (literal !== void 0) return String(literal);
48
+ }
49
+ const inWordprocessingml = getAttributeByNamespaceUri(element, WORDPROCESSINGML_NAMESPACE_URIS, localName);
50
+ if (inWordprocessingml !== null) return inWordprocessingml;
51
+ const literalW = element.attributes?.[`w:${localName}`];
52
+ return literalW === void 0 ? void 0 : String(literalW);
53
+ };
54
+ /** The paraId this element carries, or `undefined` when it carries none. */
55
+ const paraIdAttribute = (element) => paraIdValuedAttribute(element, "paraId");
56
+ /** The paraId of the parent this element names, by the same rule. */
57
+ const paraIdParentAttribute = (element) => paraIdValuedAttribute(element, "paraIdParent");
58
+ /**
59
+ * The textId this element carries: a paragraph identity written beside
60
+ * `paraId`, in the same namespaces and by the same rule.
61
+ */
62
+ const textIdAttribute = (element) => paraIdValuedAttribute(element, "textId");
63
+ //#endregion
64
+ export { PARA_ID_NAMESPACE_URIS, paraIdAttribute, paraIdParentAttribute, textIdAttribute };
@@ -1,7 +1,7 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
2
  import { NumberingMap } from "./numberingParser.js";
3
- import { StyleMap } from "./styleParser.js";
4
3
  import { XmlElement } from "./xmlParser.js";
4
+ import { StyleMap } from "./styleParser.js";
5
5
  //#region src/docx/paragraphParser.d.ts
6
6
  /**
7
7
  * Parse paragraph formatting properties (w:pPr)