@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
@@ -0,0 +1,246 @@
1
+ //#region src/docx/containerChildren.gen.ts
2
+ /**
3
+ * GENERATED FILE — do not edit.
4
+ *
5
+ * Every child the Transitional content model declares for a container folio
6
+ * dispatches, derived from the committed schema graph by
7
+ * `scripts/generate-container-children.ts`. The shared child dispatcher makes
8
+ * a handler map total over these names, so a container cannot gain a declared
9
+ * child without somebody deciding whether it is modelled or captured.
10
+ * Regenerate with:
11
+ *
12
+ * bun run generate:container-children
13
+ */
14
+ const CONTAINER_CHILDREN = {
15
+ "w:comment": [
16
+ "altChunk",
17
+ "bookmarkEnd",
18
+ "bookmarkStart",
19
+ "commentRangeEnd",
20
+ "commentRangeStart",
21
+ "customXml",
22
+ "customXmlDelRangeEnd",
23
+ "customXmlDelRangeStart",
24
+ "customXmlInsRangeEnd",
25
+ "customXmlInsRangeStart",
26
+ "customXmlMoveFromRangeEnd",
27
+ "customXmlMoveFromRangeStart",
28
+ "customXmlMoveToRangeEnd",
29
+ "customXmlMoveToRangeStart",
30
+ "del",
31
+ "ins",
32
+ "moveFrom",
33
+ "moveFromRangeEnd",
34
+ "moveFromRangeStart",
35
+ "moveTo",
36
+ "moveToRangeEnd",
37
+ "moveToRangeStart",
38
+ "p",
39
+ "permEnd",
40
+ "permStart",
41
+ "proofErr",
42
+ "sdt",
43
+ "tbl"
44
+ ],
45
+ "run-level-content": [
46
+ "bdo",
47
+ "bookmarkEnd",
48
+ "bookmarkStart",
49
+ "commentRangeEnd",
50
+ "commentRangeStart",
51
+ "customXml",
52
+ "customXmlDelRangeEnd",
53
+ "customXmlDelRangeStart",
54
+ "customXmlInsRangeEnd",
55
+ "customXmlInsRangeStart",
56
+ "customXmlMoveFromRangeEnd",
57
+ "customXmlMoveFromRangeStart",
58
+ "customXmlMoveToRangeEnd",
59
+ "customXmlMoveToRangeStart",
60
+ "del",
61
+ "dir",
62
+ "fldSimple",
63
+ "hyperlink",
64
+ "ins",
65
+ "moveFrom",
66
+ "moveFromRangeEnd",
67
+ "moveFromRangeStart",
68
+ "moveTo",
69
+ "moveToRangeEnd",
70
+ "moveToRangeStart",
71
+ "pPr",
72
+ "permEnd",
73
+ "permStart",
74
+ "proofErr",
75
+ "r",
76
+ "sdt",
77
+ "smartTag",
78
+ "smartTagPr",
79
+ "subDoc"
80
+ ],
81
+ "table-content": [
82
+ "bookmarkEnd",
83
+ "bookmarkStart",
84
+ "commentRangeEnd",
85
+ "commentRangeStart",
86
+ "customXml",
87
+ "customXmlDelRangeEnd",
88
+ "customXmlDelRangeStart",
89
+ "customXmlInsRangeEnd",
90
+ "customXmlInsRangeStart",
91
+ "customXmlMoveFromRangeEnd",
92
+ "customXmlMoveFromRangeStart",
93
+ "customXmlMoveToRangeEnd",
94
+ "customXmlMoveToRangeStart",
95
+ "customXmlPr",
96
+ "del",
97
+ "ins",
98
+ "moveFrom",
99
+ "moveFromRangeEnd",
100
+ "moveFromRangeStart",
101
+ "moveTo",
102
+ "moveToRangeEnd",
103
+ "moveToRangeStart",
104
+ "permEnd",
105
+ "permStart",
106
+ "proofErr",
107
+ "sdt",
108
+ "tblGrid",
109
+ "tblPr",
110
+ "tr"
111
+ ],
112
+ "row-content": [
113
+ "bookmarkEnd",
114
+ "bookmarkStart",
115
+ "commentRangeEnd",
116
+ "commentRangeStart",
117
+ "customXml",
118
+ "customXmlDelRangeEnd",
119
+ "customXmlDelRangeStart",
120
+ "customXmlInsRangeEnd",
121
+ "customXmlInsRangeStart",
122
+ "customXmlMoveFromRangeEnd",
123
+ "customXmlMoveFromRangeStart",
124
+ "customXmlMoveToRangeEnd",
125
+ "customXmlMoveToRangeStart",
126
+ "del",
127
+ "ins",
128
+ "moveFrom",
129
+ "moveFromRangeEnd",
130
+ "moveFromRangeStart",
131
+ "moveTo",
132
+ "moveToRangeEnd",
133
+ "moveToRangeStart",
134
+ "permEnd",
135
+ "permStart",
136
+ "proofErr",
137
+ "sdt",
138
+ "tblPrEx",
139
+ "tc",
140
+ "tr",
141
+ "trPr"
142
+ ],
143
+ "w:hyperlink": [
144
+ "bdo",
145
+ "bookmarkEnd",
146
+ "bookmarkStart",
147
+ "commentRangeEnd",
148
+ "commentRangeStart",
149
+ "customXml",
150
+ "customXmlDelRangeEnd",
151
+ "customXmlDelRangeStart",
152
+ "customXmlInsRangeEnd",
153
+ "customXmlInsRangeStart",
154
+ "customXmlMoveFromRangeEnd",
155
+ "customXmlMoveFromRangeStart",
156
+ "customXmlMoveToRangeEnd",
157
+ "customXmlMoveToRangeStart",
158
+ "del",
159
+ "dir",
160
+ "fldSimple",
161
+ "hyperlink",
162
+ "ins",
163
+ "moveFrom",
164
+ "moveFromRangeEnd",
165
+ "moveFromRangeStart",
166
+ "moveTo",
167
+ "moveToRangeEnd",
168
+ "moveToRangeStart",
169
+ "permEnd",
170
+ "permStart",
171
+ "proofErr",
172
+ "r",
173
+ "sdt",
174
+ "smartTag",
175
+ "subDoc"
176
+ ],
177
+ "w:fldSimple": [
178
+ "bdo",
179
+ "bookmarkEnd",
180
+ "bookmarkStart",
181
+ "commentRangeEnd",
182
+ "commentRangeStart",
183
+ "customXml",
184
+ "customXmlDelRangeEnd",
185
+ "customXmlDelRangeStart",
186
+ "customXmlInsRangeEnd",
187
+ "customXmlInsRangeStart",
188
+ "customXmlMoveFromRangeEnd",
189
+ "customXmlMoveFromRangeStart",
190
+ "customXmlMoveToRangeEnd",
191
+ "customXmlMoveToRangeStart",
192
+ "del",
193
+ "dir",
194
+ "fldData",
195
+ "fldSimple",
196
+ "hyperlink",
197
+ "ins",
198
+ "moveFrom",
199
+ "moveFromRangeEnd",
200
+ "moveFromRangeStart",
201
+ "moveTo",
202
+ "moveToRangeEnd",
203
+ "moveToRangeStart",
204
+ "permEnd",
205
+ "permStart",
206
+ "proofErr",
207
+ "r",
208
+ "sdt",
209
+ "smartTag",
210
+ "subDoc"
211
+ ],
212
+ "block-content": [
213
+ "altChunk",
214
+ "bookmarkEnd",
215
+ "bookmarkStart",
216
+ "commentRangeEnd",
217
+ "commentRangeStart",
218
+ "customXml",
219
+ "customXmlDelRangeEnd",
220
+ "customXmlDelRangeStart",
221
+ "customXmlInsRangeEnd",
222
+ "customXmlInsRangeStart",
223
+ "customXmlMoveFromRangeEnd",
224
+ "customXmlMoveFromRangeStart",
225
+ "customXmlMoveToRangeEnd",
226
+ "customXmlMoveToRangeStart",
227
+ "del",
228
+ "ins",
229
+ "moveFrom",
230
+ "moveFromRangeEnd",
231
+ "moveFromRangeStart",
232
+ "moveTo",
233
+ "moveToRangeEnd",
234
+ "moveToRangeStart",
235
+ "p",
236
+ "permEnd",
237
+ "permStart",
238
+ "proofErr",
239
+ "sdt",
240
+ "sectPr",
241
+ "tbl",
242
+ "tcPr"
243
+ ]
244
+ };
245
+ //#endregion
246
+ export { CONTAINER_CHILDREN };
@@ -0,0 +1,103 @@
1
+ import { TRANSITIONAL_NAMESPACE_BY_STRICT_URI } from "./strictValueEncodings.gen.js";
2
+ import { captureVerbatimXml } from "./verbatimCapture.js";
3
+ import { WORDPROCESSINGML_NAMESPACE_URIS, getChildElements, getLocalName, getNamespaceUri } from "./xmlParser.js";
4
+ //#region src/docx/containerChildren.ts
5
+ /** Keep this child's markup verbatim, in place. */
6
+ const CAPTURE = "capture";
7
+ /**
8
+ * Another reader owns this child, and re-emits it.
9
+ *
10
+ * `w:rPr` under a run, read by `parseRunProperties`; `w:commentReference`
11
+ * under a run, lifted out by the paragraph parser. Capturing one of these as
12
+ * well would write it twice, so the disposition has to be stated rather than
13
+ * left to a bare `break`.
14
+ */
15
+ const OWNED_ELSEWHERE = "owned-elsewhere";
16
+ /**
17
+ * This child goes with the wrapper folio does not keep.
18
+ *
19
+ * `w:smartTagPr` is the case: folio unwraps `w:smartTag` and splices its
20
+ * content into the paragraph, so the properties describing the wrapper have
21
+ * nothing left to describe and capturing them would put a `w:smartTagPr`
22
+ * where the schema does not admit one. The drop is stated here and recorded
23
+ * in `specifications/container-contract/contract.json`, which is the whole
24
+ * difference between this and a `default` that says nothing.
25
+ */
26
+ const DROPPED_WITH_ITS_WRAPPER = "dropped-with-its-wrapper";
27
+ /**
28
+ * The Transitional spelling of a namespace, so one disposition covers both.
29
+ *
30
+ * ISO Strict writes the same content model under its own URIs: maths is
31
+ * `purl.oclc.org/ooxml/officeDocument/math` rather than
32
+ * `schemas.openxmlformats.org/officeDocument/2006/math`. A namespace-keyed
33
+ * disposition written in Transitional would otherwise send a Strict
34
+ * document's maths to the sink, which models it as bytes instead of an
35
+ * equation. The pairs come from the generated table rather than a second list
36
+ * here, so a namespace cannot be paired in one place and forgotten in the
37
+ * other.
38
+ */
39
+ const transitionalNamespaceOf = (namespace) => TRANSITIONAL_NAMESPACE_BY_STRICT_URI.get(namespace) ?? namespace;
40
+ /**
41
+ * Walk a container's children, handing each to its handler and the rest to the
42
+ * sink.
43
+ *
44
+ * @returns the container's unmodelled markup, or `undefined` when it held
45
+ * none — an empty record is never written, so a fully modelled container
46
+ * stays byte-identical in the model.
47
+ */
48
+ const dispatchChildren = ({ element, handlers, modelledCount, undeclared, undeclaredNamespaces }) => {
49
+ const children = [];
50
+ const capture = (child) => {
51
+ children.push({
52
+ index: modelledCount(),
53
+ xml: captureVerbatimXml(child)
54
+ });
55
+ };
56
+ const declared = new Map(Object.entries(handlers));
57
+ const byName = new Map(Object.entries(undeclared ?? {}));
58
+ const byNamespace = new Map(Object.entries(undeclaredNamespaces ?? {}));
59
+ for (const child of getChildElements(element)) {
60
+ const localName = getLocalName(child.name);
61
+ const namespace = getNamespaceUri(child);
62
+ const disposition = namespace === void 0 || WORDPROCESSINGML_NAMESPACE_URIS.has(namespace) ? declared.get(localName) ?? byName.get(localName) : byName.get(localName) ?? byNamespace.get(transitionalNamespaceOf(namespace));
63
+ if (disposition === void 0 || disposition === "capture") {
64
+ capture(child);
65
+ continue;
66
+ }
67
+ if (disposition === "dropped-with-its-wrapper" || disposition === "owned-elsewhere") continue;
68
+ disposition(child);
69
+ }
70
+ return children.length === 0 ? void 0 : { children };
71
+ };
72
+ /**
73
+ * Put a container's modelled children back with its preserved ones between
74
+ * them, in source position.
75
+ *
76
+ * Where the content model demands schema order the caller has already put its
77
+ * modelled children in that order; the sink's `index` then places each capture
78
+ * between the same two siblings it sat between when it was read.
79
+ *
80
+ * @param wrap turns one capture's markup into whatever the caller's list holds
81
+ */
82
+ const withPreservedChildren = (modelled, preserved, wrap) => {
83
+ const captures = preserved?.children;
84
+ if (captures === void 0 || captures.length === 0) return [...modelled];
85
+ const byIndex = /* @__PURE__ */ new Map();
86
+ for (const { index, xml } of captures) {
87
+ const slot = Math.min(Math.max(index, 0), modelled.length);
88
+ const bucket = byIndex.get(slot);
89
+ if (bucket) {
90
+ bucket.push(wrap(xml));
91
+ continue;
92
+ }
93
+ byIndex.set(slot, [wrap(xml)]);
94
+ }
95
+ const items = [];
96
+ for (const [index, item] of modelled.entries()) items.push(...byIndex.get(index) ?? [], item);
97
+ items.push(...byIndex.get(modelled.length) ?? []);
98
+ return items;
99
+ };
100
+ /** {@link withPreservedChildren} for a caller that already holds markup. */
101
+ const serializeWithPreservedChildren = (modelled, preserved) => withPreservedChildren(modelled, preserved, (xml) => xml).join("");
102
+ //#endregion
103
+ export { CAPTURE, DROPPED_WITH_ITS_WRAPPER, OWNED_ELSEWHERE, dispatchChildren, serializeWithPreservedChildren, transitionalNamespaceOf, withPreservedChildren };
@@ -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 { ParseContext } from "./parseContext.js";
4
+ import { StyleMap } from "./styleParser.js";
5
5
  //#region src/docx/documentParser.d.ts
6
6
  /**
7
7
  * Extract template variables from text
@@ -49,7 +49,7 @@ function extractTableVariables(table) {
49
49
  for (const row of table.rows) for (const cell of row.cells) for (const cellContent of cell.content) if (cellContent.type === "paragraph") {
50
50
  const vars = extractTemplateVariables(getParagraphText(cellContent));
51
51
  for (const v of vars) if (!variables.includes(v)) variables.push(v);
52
- } else {
52
+ } else if (cellContent.type === "table") {
53
53
  const nestedVars = extractTableVariables(cellContent);
54
54
  for (const v of nestedVars) if (!variables.includes(v)) variables.push(v);
55
55
  }
@@ -149,7 +149,7 @@ function getAllParagraphs(body) {
149
149
  function getTableParagraphs(table) {
150
150
  const paragraphs = [];
151
151
  for (const row of table.rows) for (const cell of row.cells) for (const content of cell.content) if (content.type === "paragraph") paragraphs.push(content);
152
- else paragraphs.push(...getTableParagraphs(content));
152
+ else if (content.type === "table") paragraphs.push(...getTableParagraphs(content));
153
153
  return paragraphs;
154
154
  }
155
155
  /**
@@ -193,7 +193,7 @@ function getTableText(table) {
193
193
  for (const cell of row.cells) {
194
194
  const cellTexts = [];
195
195
  for (const content of cell.content) if (content.type === "paragraph") cellTexts.push(getParagraphText(content));
196
- else cellTexts.push(getTableText(content));
196
+ else if (content.type === "table") cellTexts.push(getTableText(content));
197
197
  rowTexts.push(cellTexts.join("\n"));
198
198
  }
199
199
  lines.push(rowTexts.join(" "));
@@ -1,5 +1,5 @@
1
1
  import { deterministicHexId } from "../utils/hexId.js";
2
- import { isXmlNameBoundary } from "./selectiveXmlPatch.js";
2
+ import { isXmlNameBoundary, spliceXml } from "./selectiveXmlPatch.js";
3
3
  import { loadDocxArchive } from "./server/boundedArchive.js";
4
4
  import { TaggedError } from "better-result";
5
5
  import JSZip from "jszip";
@@ -97,11 +97,21 @@ const OPEN_TAG_TEXT_ID_PATTERN = /\sw(?:14)?:textId=(?<quote>["'])(?<id>[\s\S]*?
97
97
  const XMLNS_W14_PATTERN = /\sxmlns:w14=(?<quote>["'])(?<value>[\s\S]*?)\k<quote>/u;
98
98
  const XMLNS_MC_PATTERN = /\sxmlns:mc=(?<quote>["'])(?<value>[\s\S]*?)\k<quote>/u;
99
99
  const MC_IGNORABLE_PATTERN = /\smc:Ignorable=(?<quote>["'])(?<value>[\s\S]*?)\k<quote>/u;
100
- const applySplices = (xml, edits) => {
101
- const ordered = [...edits].sort((a, b) => b.start - a.start);
102
- let result = xml;
103
- for (const { start, end, text } of ordered) result = result.slice(0, start) + text + result.slice(end);
104
- return result;
100
+ /**
101
+ * Stamp the edits into the part through the splice owner, which refuses a
102
+ * result that would leave a comment range with only one half. These edits
103
+ * rewrite `<w:p …>` open tags and the root element's attributes, so they
104
+ * should never cut across a range marker; the owner is what makes that
105
+ * structural rather than a reading of the scanner.
106
+ */
107
+ const applySplices = (xml, edits, partPath) => {
108
+ const patched = spliceXml(xml, edits.map(({ start, end, text }) => ({
109
+ start,
110
+ end,
111
+ newXml: text
112
+ })));
113
+ if (patched === null) throw createEnsureParaIdsError(`Stamping paragraph ids into ${partPath} broke a comment range`);
114
+ return patched;
105
115
  };
106
116
  const createEnsureParaIdsError = (message, cause) => new EnsureParaIdsError({
107
117
  message,
@@ -382,7 +392,7 @@ const ensureParaIdsInternal = async (docx, options) => {
382
392
  if (scan.edits.length === 0) continue;
383
393
  assigned += scan.assigned;
384
394
  deduplicated += scan.deduplicated;
385
- updates.set(partPath, applySplices(xml, [...scan.edits, ...ensureRootNamespaces(xml, partPath)]));
395
+ updates.set(partPath, applySplices(xml, [...scan.edits, ...ensureRootNamespaces(xml, partPath)], partPath));
386
396
  }
387
397
  if (updates.size === 0) return {
388
398
  docx: toUint8Array(docx),
@@ -1,6 +1,6 @@
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
4
  //#region src/docx/fieldParser.d.ts
5
5
  /**
6
6
  * All known field types from OOXML specification
@@ -1,7 +1,8 @@
1
+ import { parseFieldState } from "./fieldState.js";
1
2
  import { formatOoxmlCounter } from "./ooxmlCounterFormatter.js";
2
3
  import { FieldTypeSchema, narrowEnum } from "./parserEnums.js";
3
4
  import { parseRun } from "./runParser.js";
4
- import { findChildren, getAttribute, parseOnOffAttribute } from "./xmlParser.js";
5
+ import { findChildren, getAttribute } from "./xmlParser.js";
5
6
  //#region src/docx/fieldParser.ts
6
7
  /**
7
8
  * All known field types from OOXML specification
@@ -162,10 +163,9 @@ function parseSimpleField(node, styles, theme) {
162
163
  type: "simpleField",
163
164
  instruction,
164
165
  fieldType: parseFieldType(instruction),
165
- content: []
166
+ content: [],
167
+ ...parseFieldState(node)
166
168
  };
167
- if (parseOnOffAttribute(node, "w", "fldLock") === true) field.fldLock = true;
168
- if (parseOnOffAttribute(node, "w", "dirty") === true) field.dirty = true;
169
169
  const children = findChildren(node, "w", "r");
170
170
  for (const child of children) {
171
171
  const run = parseRun(child, styles, theme);
@@ -0,0 +1,26 @@
1
+ import { XmlElement } from "./xmlParser.js";
2
+ //#region src/docx/fieldState.d.ts
3
+ /** What a field element states about its lock and dirty flags. */
4
+ type FieldState = {
5
+ fldLock?: boolean;
6
+ dirty?: boolean;
7
+ };
8
+ /** Read both attributes off a `w:fldSimple` or `w:fldChar`, keeping an explicit off. */
9
+ declare const parseFieldState: (element: XmlElement) => FieldState;
10
+ /**
11
+ * The stated flags of a field, without the rest of it.
12
+ *
13
+ * The complex-field assembly carries the begin `w:fldChar`'s state across the
14
+ * runs between `begin` and `end`, and this is the one place that knows which
15
+ * fields that state is made of.
16
+ */
17
+ declare const fieldStateOf: ({ fldLock, dirty }: FieldState) => FieldState;
18
+ /**
19
+ * The attributes to write for a field's stated flags, in schema order.
20
+ *
21
+ * `1`/`0` is what Word writes and what the table, section and border
22
+ * serializers write.
23
+ */
24
+ declare const fieldStateAttributes: ({ fldLock, dirty }: FieldState) => string[];
25
+ //#endregion
26
+ export { FieldState, fieldStateAttributes, fieldStateOf, parseFieldState };
@@ -0,0 +1,53 @@
1
+ import { parseOnOffAttribute } from "./xmlParser.js";
2
+ //#region src/docx/fieldState.ts
3
+ /**
4
+ * `@w:fldLock` and `@w:dirty`, the two `ST_OnOff` attributes every field form
5
+ * carries.
6
+ *
7
+ * A simple field states them on `<w:fldSimple>`; a complex field states them on
8
+ * the `<w:fldChar w:fldCharType="begin"/>` that opens it, and folio hoists them
9
+ * from there onto the assembled `ComplexField`. Neither attribute has an XSD
10
+ * default, so a field states one of three things about each: nothing, an
11
+ * explicit off, an explicit on. `w:dirty="0"` on a field inside a `TOC` result
12
+ * is the case that matters: it says "do not recompute this", which is not what
13
+ * an absent attribute says.
14
+ *
15
+ * Three readers and three writers had drifted into the same `=== true` /
16
+ * truthiness collapse, so both directions live here instead.
17
+ */
18
+ /** Read both attributes off a `w:fldSimple` or `w:fldChar`, keeping an explicit off. */
19
+ const parseFieldState = (element) => {
20
+ const state = {};
21
+ const fldLock = parseOnOffAttribute(element, "w", "fldLock");
22
+ if (fldLock !== void 0) state.fldLock = fldLock;
23
+ const dirty = parseOnOffAttribute(element, "w", "dirty");
24
+ if (dirty !== void 0) state.dirty = dirty;
25
+ return state;
26
+ };
27
+ /**
28
+ * The stated flags of a field, without the rest of it.
29
+ *
30
+ * The complex-field assembly carries the begin `w:fldChar`'s state across the
31
+ * runs between `begin` and `end`, and this is the one place that knows which
32
+ * fields that state is made of.
33
+ */
34
+ const fieldStateOf = ({ fldLock, dirty }) => {
35
+ const state = {};
36
+ if (fldLock !== void 0) state.fldLock = fldLock;
37
+ if (dirty !== void 0) state.dirty = dirty;
38
+ return state;
39
+ };
40
+ /**
41
+ * The attributes to write for a field's stated flags, in schema order.
42
+ *
43
+ * `1`/`0` is what Word writes and what the table, section and border
44
+ * serializers write.
45
+ */
46
+ const fieldStateAttributes = ({ fldLock, dirty }) => {
47
+ const attrs = [];
48
+ if (fldLock !== void 0) attrs.push(`w:fldLock="${fldLock ? "1" : "0"}"`);
49
+ if (dirty !== void 0) attrs.push(`w:dirty="${dirty ? "1" : "0"}"`);
50
+ return attrs;
51
+ };
52
+ //#endregion
53
+ export { fieldStateAttributes, fieldStateOf, parseFieldState };
@@ -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 { ParseContext } from "./parseContext.js";
4
+ import { StyleMap } from "./styleParser.js";
5
5
  import { parseEndnoteProperties, parseFootnoteProperties } from "./notePropertiesParser.js";
6
6
  //#region src/docx/footnoteParser.d.ts
7
7
  /**
@@ -12,11 +12,23 @@ declare const GRAPHIC_FRAME_LOCK_KEYS: ("noGrp" | "noDrilldown" | "noSelect" | "
12
12
  */
13
13
  declare const parseGraphicFrameLocks: (parent: XmlElement) => document_d_exports.ImageFrameLocks | undefined;
14
14
  /**
15
- * Emit the whole `wp:cNvGraphicFramePr` element for regenerated DrawingML.
15
+ * The locks folio gives a picture it creates itself, at the insert that creates
16
+ * it: Word writes `noChangeAspect="1"` on a picture inserted through its own
17
+ * UI, and an inserted picture should behave the same in both.
16
18
  *
17
- * Absent locks mean no authored frame was ever parsed (a Folio-created
18
- * picture), which keeps the historical `noChangeAspect="1"`.
19
+ * It lives here because it is a fact about this element, and it is applied at
20
+ * construction rather than at serialization, where "the author wrote no frame"
21
+ * and "folio made this picture" are the same `undefined`.
22
+ */
23
+ declare const FOLIO_INSERTED_PICTURE_FRAME_LOCKS: document_d_exports.ImageFrameLocks;
24
+ /**
25
+ * Emit `wp:cNvGraphicFramePr` for regenerated DrawingML, or nothing.
26
+ *
27
+ * Absent locks are the author's silence, and silence is written back as
28
+ * silence: a frame the source never carried is not invented on the rebuild
29
+ * path, where it would appear on every edited document and on none of the
30
+ * replayed ones.
19
31
  */
20
32
  declare const serializeGraphicFrameLocks: (locks: document_d_exports.ImageFrameLocks | undefined) => string;
21
33
  //#endregion
22
- export { GRAPHIC_FRAME_LOCK_KEYS, parseGraphicFrameLocks, serializeGraphicFrameLocks };
34
+ export { FOLIO_INSERTED_PICTURE_FRAME_LOCKS, GRAPHIC_FRAME_LOCK_KEYS, parseGraphicFrameLocks, serializeGraphicFrameLocks };
@@ -38,18 +38,31 @@ const parseGraphicFrameLocks = (parent) => {
38
38
  return present ? locks : void 0;
39
39
  };
40
40
  /**
41
- * Emit the whole `wp:cNvGraphicFramePr` element for regenerated DrawingML.
41
+ * The locks folio gives a picture it creates itself, at the insert that creates
42
+ * it: Word writes `noChangeAspect="1"` on a picture inserted through its own
43
+ * UI, and an inserted picture should behave the same in both.
42
44
  *
43
- * Absent locks mean no authored frame was ever parsed (a Folio-created
44
- * picture), which keeps the historical `noChangeAspect="1"`.
45
+ * It lives here because it is a fact about this element, and it is applied at
46
+ * construction rather than at serialization, where "the author wrote no frame"
47
+ * and "folio made this picture" are the same `undefined`.
48
+ */
49
+ const FOLIO_INSERTED_PICTURE_FRAME_LOCKS = { noChangeAspect: true };
50
+ /**
51
+ * Emit `wp:cNvGraphicFramePr` for regenerated DrawingML, or nothing.
52
+ *
53
+ * Absent locks are the author's silence, and silence is written back as
54
+ * silence: a frame the source never carried is not invented on the rebuild
55
+ * path, where it would appear on every edited document and on none of the
56
+ * replayed ones.
45
57
  */
46
58
  const serializeGraphicFrameLocks = (locks) => {
47
- const attrs = locks ? GRAPHIC_FRAME_LOCK_KEYS.flatMap((key) => {
59
+ if (!locks) return "";
60
+ const attrs = GRAPHIC_FRAME_LOCK_KEYS.flatMap((key) => {
48
61
  const value = locks[key];
49
62
  return value === void 0 ? [] : [`${GRAPHIC_FRAME_LOCK_ATTRIBUTES[key]}="${value ? "1" : "0"}"`];
50
- }) : ["noChangeAspect=\"1\""];
63
+ });
51
64
  const attrList = attrs.length > 0 ? ` ${attrs.join(" ")}` : "";
52
65
  return `<wp:cNvGraphicFramePr><a:graphicFrameLocks ${DRAWINGML_NAMESPACE}${attrList}/></wp:cNvGraphicFramePr>`;
53
66
  };
54
67
  //#endregion
55
- export { GRAPHIC_FRAME_LOCK_KEYS, parseGraphicFrameLocks, serializeGraphicFrameLocks };
68
+ export { FOLIO_INSERTED_PICTURE_FRAME_LOCKS, GRAPHIC_FRAME_LOCK_KEYS, parseGraphicFrameLocks, serializeGraphicFrameLocks };
@@ -155,7 +155,7 @@ function getHeaderFooterText(hf) {
155
155
  function isEmptyHeaderFooter(hf) {
156
156
  if (hf.content.length === 0) return true;
157
157
  for (const item of hf.content) {
158
- if (item.type === "table") return false;
158
+ if (item.type !== "paragraph") return false;
159
159
  if (item.content.length > 0) for (const content of item.content) {
160
160
  if (content.type !== "run") return false;
161
161
  for (const rc of content.content) {
@@ -38,6 +38,7 @@ const normalizeHeaderFooterReferences = ({ documentBody, headers, footers }) =>
38
38
  normalizeTable(block);
39
39
  return;
40
40
  }
41
+ if (block.type === "preservedBlock") return;
41
42
  normalizeBlocks(block.content);
42
43
  };
43
44
  const normalizeBlocks = (blocks) => {