@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,8 +1,10 @@
1
1
  import { commentThreadParaId } from "./commentThreadKey.js";
2
+ import { CAPTURE, dispatchChildren } from "./containerChildren.js";
3
+ import { PARA_ID_NAMESPACE_URIS, paraIdAttribute, paraIdParentAttribute } from "./paraIdAttribute.js";
2
4
  import { parseParagraph } from "./paragraphParser.js";
3
5
  import { cloneParagraphWithPropertySource } from "./paragraphPropertySource.js";
4
6
  import { parseRunProperties } from "./runParser.js";
5
- import { NAMESPACES, WORDPROCESSINGML_NAMESPACE_URIS, findChild, getAttribute, getAttributeByNamespaceUri, getChildElements, getLocalName, parseOnOffValue, parseXml } from "./xmlParser.js";
7
+ import { findChild, getAttribute, getAttributeByNamespaceUri, getChildElements, getLocalName, parseOnOffValue, parseXml } from "./xmlParser.js";
6
8
  import { PARSE_WARNING_CODES } from "@stll/docx-core/model";
7
9
  //#region src/docx/commentParser.ts
8
10
  /**
@@ -26,26 +28,6 @@ import { PARSE_WARNING_CODES } from "@stll/docx-core/model";
26
28
  /** The whole lexical form of `ST_DecimalNumber`: an optional sign and digits. */
27
29
  const DECIMAL_NUMBER = /^[+-]?\d+$/u;
28
30
  const DEFAULT_ANNOTATION_REFERENCE_STYLE_ID = "CommentReference";
29
- /**
30
- * The namespaces a paraId may be written in: Word 2010 and Word 2012 wordml.
31
- *
32
- * Resolved by URI rather than by prefix, because the value is a thread key: an
33
- * unrelated `vendor:paraId` picked up by local name alone would key a comment
34
- * to the wrong thread and carry that thread's date, parent and resolved state.
35
- */
36
- const PARA_ID_NAMESPACE_URIS = /* @__PURE__ */ new Set([NAMESPACES.w14, NAMESPACES.w15]);
37
- /**
38
- * A paraId join key, wherever an exporter writes it: on `w:comment` or `w:p`.
39
- *
40
- * One reading for both, so the wrapper and the paragraphs cannot come to
41
- * disagree about what counts as a key. The literal reads are the fallback for
42
- * a part that writes a conventional prefix without binding it, which no URI
43
- * lookup can resolve.
44
- */
45
- const paraIdAttribute = (element) => {
46
- const raw = getAttributeByNamespaceUri(element, PARA_ID_NAMESPACE_URIS, "paraId") ?? element.attributes?.["w14:paraId"] ?? element.attributes?.["w15:paraId"] ?? getAttributeByNamespaceUri(element, WORDPROCESSINGML_NAMESPACE_URIS, "paraId") ?? element.attributes?.["w:paraId"];
47
- return raw === null || raw === void 0 ? void 0 : String(raw);
48
- };
49
31
  const normalizeAnnotationReferenceFormatting = (formatting) => {
50
32
  if (formatting?.styleId === DEFAULT_ANNOTATION_REFERENCE_STYLE_ID && Object.keys(formatting).length === 1) return;
51
33
  return formatting;
@@ -57,7 +39,7 @@ const normalizeFirstCommentParagraph = (paragraphElement, paragraph, theme) => {
57
39
  const annotationReferenceFormatting = normalizeAnnotationReferenceFormatting(runProperties ? parseRunProperties(runProperties, theme) : void 0);
58
40
  const firstParsedContent = paragraph.content.at(0);
59
41
  return {
60
- paragraph: firstParsedContent?.type === "run" && firstParsedContent.content.length === 0 ? cloneParagraphWithPropertySource(paragraph, { content: paragraph.content.slice(1) }) : paragraph,
42
+ paragraph: firstParsedContent?.type === "run" && firstParsedContent.content.every((item) => item.type === "preservedXml" && item.text === "") ? cloneParagraphWithPropertySource(paragraph, { content: paragraph.content.slice(1) }) : paragraph,
61
43
  ...annotationReferenceFormatting !== void 0 ? { annotationReferenceFormatting } : {}
62
44
  };
63
45
  };
@@ -75,9 +57,9 @@ function parseCommentsExtensible(xml) {
75
57
  const container = findChild(root, "w16cex", "commentsExtensible") ?? root;
76
58
  for (const child of getChildElements(container)) {
77
59
  if ((child.name?.replace(/^.*:/u, "") ?? "") !== "comment") continue;
78
- const paraId = getAttribute(child, "w16cex", "paraId") ?? getAttribute(child, "w15", "paraId") ?? child.attributes?.["w16cex:paraId"] ?? child.attributes?.["w15:paraId"];
79
- const dateUtc = getAttribute(child, "w16cex", "dateUtc") ?? getAttribute(child, "w15", "dateUtc") ?? child.attributes?.["w16cex:dateUtc"] ?? child.attributes?.["w15:dateUtc"];
80
- const key = paraId === null || paraId === void 0 ? null : String(paraId).toUpperCase();
60
+ const paraId = paraIdAttribute(child);
61
+ const dateUtc = getAttributeByNamespaceUri(child, PARA_ID_NAMESPACE_URIS, "dateUtc") ?? child.attributes?.["w16cex:dateUtc"] ?? child.attributes?.["w15:dateUtc"];
62
+ const key = paraId === void 0 ? null : paraId.toUpperCase();
81
63
  if (key && dateUtc && !dateUtcByParaId.has(key)) dateUtcByParaId.set(key, String(dateUtc));
82
64
  }
83
65
  return dateUtcByParaId;
@@ -102,11 +84,11 @@ function parseCommentsExtended(xml) {
102
84
  const container = findChild(root, "w15", "commentsEx") ?? root;
103
85
  for (const child of getChildElements(container)) {
104
86
  if ((child.name?.replace(/^.*:/u, "") ?? "") !== "commentEx") continue;
105
- const paraId = getAttribute(child, "w15", "paraId") ?? child.attributes?.["w15:paraId"];
87
+ const paraId = paraIdAttribute(child);
106
88
  if (!paraId) continue;
107
- const key = String(paraId).toUpperCase();
89
+ const key = paraId.toUpperCase();
108
90
  if (infoByParaId.has(key)) continue;
109
- const parentParaId = getAttribute(child, "w15", "paraIdParent") ?? child.attributes?.["w15:paraIdParent"];
91
+ const parentParaId = paraIdParentAttribute(child);
110
92
  const doneAttr = getAttribute(child, "w15", "done") ?? child.attributes?.["w15:done"];
111
93
  const info = {};
112
94
  if (parentParaId) info.parentParaId = String(parentParaId).toUpperCase();
@@ -155,16 +137,50 @@ function parseComments(commentsXml, styles, theme, rels, media, commentsExtensib
155
137
  const done = (paraId ? extendedByParaId.get(paraId) : void 0)?.done;
156
138
  const paragraphs = [];
157
139
  let annotationReferenceFormatting;
158
- for (const contentChild of getChildElements(child)) if ((contentChild.name?.replace(/^.*:/u, "") ?? "") === "p") {
159
- const paragraph = parseParagraph(contentChild, styles, theme, null, rels, media);
160
- if (paragraphs.length > 0) {
161
- paragraphs.push(paragraph);
162
- continue;
140
+ const preserved = dispatchChildren({
141
+ element: child,
142
+ container: "w:comment",
143
+ modelledCount: () => paragraphs.length,
144
+ handlers: {
145
+ p: (contentChild) => {
146
+ const paragraph = parseParagraph(contentChild, styles, theme, null, rels, media);
147
+ if (paragraphs.length > 0) {
148
+ paragraphs.push(paragraph);
149
+ return;
150
+ }
151
+ const normalized = normalizeFirstCommentParagraph(contentChild, paragraph, theme);
152
+ annotationReferenceFormatting = normalized.annotationReferenceFormatting;
153
+ paragraphs.push(normalized.paragraph);
154
+ },
155
+ altChunk: CAPTURE,
156
+ bookmarkEnd: CAPTURE,
157
+ bookmarkStart: CAPTURE,
158
+ commentRangeEnd: CAPTURE,
159
+ commentRangeStart: CAPTURE,
160
+ customXml: CAPTURE,
161
+ customXmlDelRangeEnd: CAPTURE,
162
+ customXmlDelRangeStart: CAPTURE,
163
+ customXmlInsRangeEnd: CAPTURE,
164
+ customXmlInsRangeStart: CAPTURE,
165
+ customXmlMoveFromRangeEnd: CAPTURE,
166
+ customXmlMoveFromRangeStart: CAPTURE,
167
+ customXmlMoveToRangeEnd: CAPTURE,
168
+ customXmlMoveToRangeStart: CAPTURE,
169
+ del: CAPTURE,
170
+ ins: CAPTURE,
171
+ moveFrom: CAPTURE,
172
+ moveFromRangeEnd: CAPTURE,
173
+ moveFromRangeStart: CAPTURE,
174
+ moveTo: CAPTURE,
175
+ moveToRangeEnd: CAPTURE,
176
+ moveToRangeStart: CAPTURE,
177
+ permEnd: CAPTURE,
178
+ permStart: CAPTURE,
179
+ proofErr: CAPTURE,
180
+ sdt: CAPTURE,
181
+ tbl: CAPTURE
163
182
  }
164
- const normalized = normalizeFirstCommentParagraph(contentChild, paragraph, theme);
165
- annotationReferenceFormatting = normalized.annotationReferenceFormatting;
166
- paragraphs.push(normalized.paragraph);
167
- }
183
+ });
168
184
  if (paraId && !commentIdByParaId.has(paraId)) commentIdByParaId.set(paraId, id);
169
185
  parsed.push({
170
186
  comment: {
@@ -174,6 +190,7 @@ function parseComments(commentsXml, styles, theme, rels, media, commentsExtensib
174
190
  ...date !== void 0 ? { date } : {},
175
191
  ...done !== void 0 ? { done } : {},
176
192
  ...annotationReferenceFormatting !== void 0 ? { annotationReferenceFormatting } : {},
193
+ ...preserved !== void 0 ? { preserved } : {},
177
194
  content: paragraphs
178
195
  },
179
196
  threadParaId: paraId
@@ -1,5 +1,20 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
2
  //#region src/docx/commentRangeIntegrity.d.ts
3
+ /**
4
+ * Comment ids whose range is not a start followed by an end in this story's
5
+ * XML. Either half alone is invalid OOXML and anchors nothing: Word shows no
6
+ * comment for a range that never opens.
7
+ */
8
+ declare const unbalancedCommentRangeIds: (xml: string) => Set<string>;
9
+ /**
10
+ * Whether rewriting `originalXml` into `patchedXml` left a comment range with
11
+ * only one half. A save patches the paragraphs an edit touched and keeps the
12
+ * rest of the part byte-for-byte, so an edit that moves a range's only start
13
+ * out of a patched paragraph and into an untouched one writes an end with no
14
+ * start. Ranges the source already had unbalanced are not this save's doing
15
+ * and stay tolerated.
16
+ */
17
+ declare const patchBreaksCommentRangeBalance: (originalXml: string, patchedXml: string) => boolean;
3
18
  declare const withoutOrphanCommentRanges: (doc: document_d_exports.Document) => document_d_exports.Document;
4
19
  //#endregion
5
- export { withoutOrphanCommentRanges };
20
+ export { patchBreaksCommentRangeBalance, unbalancedCommentRangeIds, withoutOrphanCommentRanges };
@@ -1,5 +1,45 @@
1
1
  import { cloneParagraphWithPropertySource } from "./paragraphPropertySource.js";
2
2
  //#region src/docx/commentRangeIntegrity.ts
3
+ const COMMENT_RANGE_MARKER_PATTERN = /<w:commentRange(Start|End)\s[^>]*w:id="(\d+)"/gu;
4
+ /**
5
+ * Comment ids whose range is not a start followed by an end in this story's
6
+ * XML. Either half alone is invalid OOXML and anchors nothing: Word shows no
7
+ * comment for a range that never opens.
8
+ */
9
+ const unbalancedCommentRangeIds = (xml) => {
10
+ const firstStart = /* @__PURE__ */ new Map();
11
+ const lastEnd = /* @__PURE__ */ new Map();
12
+ for (const match of xml.matchAll(COMMENT_RANGE_MARKER_PATTERN)) {
13
+ const [, half, id] = match;
14
+ if (id === void 0) continue;
15
+ if (half === "Start") {
16
+ if (!firstStart.has(id)) firstStart.set(id, match.index);
17
+ continue;
18
+ }
19
+ lastEnd.set(id, match.index);
20
+ }
21
+ const unbalanced = /* @__PURE__ */ new Set();
22
+ for (const id of /* @__PURE__ */ new Set([...firstStart.keys(), ...lastEnd.keys()])) {
23
+ const start = firstStart.get(id);
24
+ const end = lastEnd.get(id);
25
+ if (start === void 0 || end === void 0 || end < start) unbalanced.add(id);
26
+ }
27
+ return unbalanced;
28
+ };
29
+ /**
30
+ * Whether rewriting `originalXml` into `patchedXml` left a comment range with
31
+ * only one half. A save patches the paragraphs an edit touched and keeps the
32
+ * rest of the part byte-for-byte, so an edit that moves a range's only start
33
+ * out of a patched paragraph and into an untouched one writes an end with no
34
+ * start. Ranges the source already had unbalanced are not this save's doing
35
+ * and stay tolerated.
36
+ */
37
+ const patchBreaksCommentRangeBalance = (originalXml, patchedXml) => {
38
+ const introduced = unbalancedCommentRangeIds(patchedXml);
39
+ if (introduced.size === 0) return false;
40
+ const preexisting = unbalancedCommentRangeIds(originalXml);
41
+ return [...introduced].some((id) => !preexisting.has(id));
42
+ };
3
43
  const withoutOrphanCommentRanges = (doc) => {
4
44
  const validCommentIds = new Set((doc.package.document.comments ?? []).map((comment) => comment.id));
5
45
  const document = withoutOrphanDocumentBodyMarkers(doc.package.document, validCommentIds);
@@ -107,6 +147,7 @@ const withoutOrphanBlockMarkers = (blocks, validCommentIds) => {
107
147
  const withoutOrphanBlockMarker = (block, validCommentIds) => {
108
148
  if (block.type === "paragraph") return withoutOrphanParagraphMarkers(block, validCommentIds);
109
149
  if (block.type === "table") return withoutOrphanTableMarkers(block, validCommentIds);
150
+ if (block.type === "preservedBlock") return block;
110
151
  const content = withoutOrphanBlockMarkers(block.content, validCommentIds);
111
152
  if (!content) return block;
112
153
  return {
@@ -180,4 +221,4 @@ const withoutOrphanParagraphMarkers = (paragraph, validCommentIds) => {
180
221
  };
181
222
  const isCommentMarker = (content) => content.type === "commentRangeStart" || content.type === "commentRangeEnd" || content.type === "commentReference";
182
223
  //#endregion
183
- export { withoutOrphanCommentRanges };
224
+ export { patchBreaksCommentRangeBalance, unbalancedCommentRangeIds, withoutOrphanCommentRanges };
@@ -0,0 +1,9 @@
1
+ import { document_d_exports } from "../types/document.js";
2
+ //#region src/docx/commentRangeJoin.d.ts
3
+ /**
4
+ * Collapse each comment's range markers to its first start and its last end.
5
+ * Answers how many markers were dropped.
6
+ */
7
+ declare const joinCommentRangesAcrossParagraphs: (blocks: readonly document_d_exports.BlockContent[]) => number;
8
+ //#endregion
9
+ export { joinCommentRangesAcrossParagraphs };
@@ -0,0 +1,33 @@
1
+ import { visitCommentMarkers } from "./commentAnchorIndex.js";
2
+ import { InlineContentRemovals } from "./paragraphTraversal.js";
3
+ //#region src/docx/commentRangeJoin.ts
4
+ /**
5
+ * Collapse each comment's range markers to its first start and its last end.
6
+ * Answers how many markers were dropped.
7
+ */
8
+ const joinCommentRangesAcrossParagraphs = (blocks) => {
9
+ const startsById = /* @__PURE__ */ new Map();
10
+ const endsById = /* @__PURE__ */ new Map();
11
+ visitCommentMarkers(blocks, ({ content, index, item }) => {
12
+ if (item.type === "commentReference") return;
13
+ const slotsById = item.type === "commentRangeStart" ? startsById : endsById;
14
+ const slots = slotsById.get(item.id);
15
+ if (slots) {
16
+ slots.push({
17
+ content,
18
+ index
19
+ });
20
+ return;
21
+ }
22
+ slotsById.set(item.id, [{
23
+ content,
24
+ index
25
+ }]);
26
+ });
27
+ const removals = new InlineContentRemovals();
28
+ for (const slots of startsById.values()) for (const slot of slots.slice(1)) removals.mark(slot);
29
+ for (const slots of endsById.values()) for (const slot of slots.slice(0, -1)) removals.mark(slot);
30
+ return removals.apply();
31
+ };
32
+ //#endregion
33
+ export { joinCommentRangesAcrossParagraphs };
@@ -0,0 +1,9 @@
1
+ import { document_d_exports } from "../types/document.js";
2
+ //#region src/docx/commentReferenceCompletion.d.ts
3
+ /**
4
+ * Give every comment that a `commentRangeEnd` closes but no `commentReference`
5
+ * names a reference after its last end. Answers how many were added.
6
+ */
7
+ declare const completeCommentReferences: (blocks: readonly document_d_exports.BlockContent[]) => number;
8
+ //#endregion
9
+ export { completeCommentReferences };
@@ -0,0 +1,47 @@
1
+ import { visitCommentMarkers } from "./commentAnchorIndex.js";
2
+ //#region src/docx/commentReferenceCompletion.ts
3
+ /**
4
+ * Give every comment that a `commentRangeEnd` closes but no `commentReference`
5
+ * names a reference after its last end. Answers how many were added.
6
+ */
7
+ const completeCommentReferences = (blocks) => {
8
+ const lastRangeEnds = /* @__PURE__ */ new Map();
9
+ const referencedIds = /* @__PURE__ */ new Set();
10
+ visitCommentMarkers(blocks, ({ content, index, item }) => {
11
+ if (item.type === "commentReference") {
12
+ referencedIds.add(item.id);
13
+ return;
14
+ }
15
+ if (item.type === "commentRangeEnd") lastRangeEnds.set(item.id, {
16
+ content,
17
+ index
18
+ });
19
+ });
20
+ const insertionsByContent = /* @__PURE__ */ new Map();
21
+ for (const [id, { content, index }] of lastRangeEnds) {
22
+ if (referencedIds.has(id)) continue;
23
+ const pending = insertionsByContent.get(content);
24
+ if (pending) {
25
+ pending.push({
26
+ index,
27
+ id
28
+ });
29
+ continue;
30
+ }
31
+ insertionsByContent.set(content, [{
32
+ index,
33
+ id
34
+ }]);
35
+ }
36
+ let added = 0;
37
+ for (const [content, pending] of insertionsByContent) for (const { index, id } of pending.toSorted((first, second) => second.index - first.index || second.id - first.id)) {
38
+ content.splice(index + 1, 0, {
39
+ type: "commentReference",
40
+ id
41
+ });
42
+ added += 1;
43
+ }
44
+ return added;
45
+ };
46
+ //#endregion
47
+ export { completeCommentReferences };
@@ -39,6 +39,7 @@ const normalizeCommentReferences = ({ documentBody, comments, headers, footers,
39
39
  normalizeTable(block);
40
40
  return;
41
41
  }
42
+ if (block.type === "preservedBlock") return;
42
43
  normalizeBlocks(block.content);
43
44
  };
44
45
  const normalizeBlocks = (blocks) => {
@@ -25,34 +25,26 @@ const eachParagraph = (blocks, visit) => {
25
25
  for (const row of block.rows ?? []) for (const cell of row.cells ?? []) eachParagraph(cell.content ?? [], visit);
26
26
  continue;
27
27
  }
28
+ if (block.type === "preservedBlock") continue;
28
29
  eachParagraph(block.content ?? [], visit);
29
30
  }
30
31
  };
31
- const scanAnchors = (surfaces) => {
32
- const rangeIds = /* @__PURE__ */ new Set();
32
+ /** Comment ids with any anchor (a range start OR a `commentReference` run). */
33
+ const scanAnchoredIds = (surfaces) => {
33
34
  const anchoredIds = /* @__PURE__ */ new Set();
34
35
  for (const group of surfaceBlockGroups(surfaces)) eachParagraph(group, (paragraph) => {
35
- for (const item of paragraph.content ?? []) if (item.type === "commentRangeStart") {
36
- rangeIds.add(item.id);
37
- anchoredIds.add(item.id);
38
- } else if (item.type === "commentReference") anchoredIds.add(item.id);
36
+ for (const item of paragraph.content ?? []) if (item.type === "commentRangeStart" || item.type === "commentReference") anchoredIds.add(item.id);
39
37
  });
40
- return {
41
- rangeIds,
42
- anchoredIds
43
- };
38
+ return anchoredIds;
44
39
  };
45
40
  /** Replies whose parent is another comment (the threaded-discussion shape). */
46
41
  const commentParentedReplies = (comments) => {
47
42
  const commentIds = new Set(comments.map((comment) => comment.id));
48
43
  return comments.filter((comment) => comment.parentId !== void 0 && commentIds.has(comment.parentId));
49
44
  };
50
- const injectIntoParagraph = (paragraph, replyIdsByParent, parentsWithRange) => {
45
+ const injectIntoParagraph = (paragraph, replyIdsByParent) => {
51
46
  const content = paragraph.content ?? [];
52
- if (!content.some((item) => {
53
- if (item.type === "commentRangeStart" || item.type === "commentRangeEnd") return replyIdsByParent.has(item.id);
54
- return item.type === "commentReference" && !parentsWithRange.has(item.id) ? replyIdsByParent.has(item.id) : false;
55
- })) return 0;
47
+ if (!content.some((item) => (item.type === "commentRangeStart" || item.type === "commentRangeEnd" || item.type === "commentReference") && replyIdsByParent.has(item.id))) return 0;
56
48
  const next = [];
57
49
  let injected = 0;
58
50
  for (const item of content) {
@@ -68,7 +60,7 @@ const injectIntoParagraph = (paragraph, replyIdsByParent, parentsWithRange) => {
68
60
  type: "commentRangeEnd",
69
61
  id: replyId
70
62
  });
71
- else if (item.type === "commentReference" && !parentsWithRange.has(item.id)) for (const replyId of replyIdsByParent.get(item.id) ?? []) {
63
+ else if (item.type === "commentReference") for (const replyId of replyIdsByParent.get(item.id) ?? []) {
72
64
  next.push({
73
65
  type: "commentReference",
74
66
  id: replyId
@@ -82,7 +74,7 @@ const injectIntoParagraph = (paragraph, replyIdsByParent, parentsWithRange) => {
82
74
  const synthesizeReplyRangeMarkers = (surfaces) => {
83
75
  const replies = commentParentedReplies(surfaces.comments);
84
76
  if (replies.length === 0) return 0;
85
- const { rangeIds, anchoredIds } = scanAnchors(surfaces);
77
+ const anchoredIds = scanAnchoredIds(surfaces);
86
78
  const replyIdsByParent = /* @__PURE__ */ new Map();
87
79
  for (const reply of replies) {
88
80
  if (anchoredIds.has(reply.id) || reply.parentId === void 0) continue;
@@ -93,7 +85,7 @@ const synthesizeReplyRangeMarkers = (surfaces) => {
93
85
  if (replyIdsByParent.size === 0) return 0;
94
86
  let injected = 0;
95
87
  const visit = (paragraph) => {
96
- injected += injectIntoParagraph(paragraph, replyIdsByParent, rangeIds);
88
+ injected += injectIntoParagraph(paragraph, replyIdsByParent);
97
89
  };
98
90
  for (const group of surfaceBlockGroups(surfaces)) eachParagraph(group, visit);
99
91
  return injected;
@@ -116,7 +108,7 @@ const hasUnsynthesizedReplyRanges = (doc) => {
116
108
  const surfaces = surfacesFromDocument(doc);
117
109
  const replies = commentParentedReplies(surfaces.comments);
118
110
  if (replies.length === 0) return false;
119
- const { anchoredIds } = scanAnchors(surfaces);
111
+ const anchoredIds = scanAnchoredIds(surfaces);
120
112
  return replies.some((reply) => !anchoredIds.has(reply.id));
121
113
  };
122
114
  //#endregion
@@ -97,6 +97,7 @@ function inspectBlocks(blocks, context) {
97
97
  });
98
98
  continue;
99
99
  }
100
+ if (block.type === "preservedBlock") continue;
100
101
  inspectBlocks(block.content, {
101
102
  part: context.part,
102
103
  path: `${blockPath}.content`,
@@ -0,0 +1,111 @@
1
+ import { XmlElement } from "./xmlParser.js";
2
+ import { DeclaredChild, DispatchedContainer } from "./containerChildren.gen.js";
3
+ import { PreservedMarkup } from "@stll/docx-core/model";
4
+ //#region src/docx/containerChildren.d.ts
5
+ /** Keep this child's markup verbatim, in place. */
6
+ declare 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
+ declare 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
+ declare const DROPPED_WITH_ITS_WRAPPER = "dropped-with-its-wrapper";
27
+ /** What a container does with one declared child. */
28
+ type ChildDisposition = ((child: XmlElement) => void) | typeof CAPTURE | typeof DROPPED_WITH_ITS_WRAPPER | typeof OWNED_ELSEWHERE;
29
+ /**
30
+ * A total decision per declared child.
31
+ *
32
+ * `Record`, never `Partial<Record>`: a partial map lets a new declared child
33
+ * land without a decision, which is the drop this module exists to prevent.
34
+ */
35
+ type ChildHandlers<Container extends DispatchedContainer> = Readonly<Record<DeclaredChild<Container>, ChildDisposition>>;
36
+ type DispatchChildrenOptions<Container extends DispatchedContainer> = {
37
+ /** The container element, as the source wrote it. */
38
+ element: XmlElement;
39
+ /** Which container's declared-child set the handler map must be total over. */
40
+ container: Container;
41
+ handlers: ChildHandlers<Container>;
42
+ /**
43
+ * How many modelled children the caller holds right now. Called once per
44
+ * captured child, so the capture lands after the siblings already read.
45
+ */
46
+ modelledCount: () => number;
47
+ /**
48
+ * Dispositions for names the container's content model does not declare.
49
+ *
50
+ * The schema declares a container's children in one namespace, so anything
51
+ * else is undeclared by construction — which is why the sink is the default
52
+ * and why this map is not part of the totality check: there is no finite set
53
+ * to be total over. `mc:AlternateContent` is the case that needs it. It is
54
+ * markup compatibility, legal wherever its fallback is, and folio models it
55
+ * by selecting a branch and reading that; capturing the wrapper whole would
56
+ * keep the bytes and lose every paragraph inside it to the editor.
57
+ *
58
+ * Each entry is a claim that folio reads this name in this container.
59
+ */
60
+ undeclared?: Readonly<Record<string, ChildDisposition>>;
61
+ /**
62
+ * Dispositions for whole namespaces the declared set does not cover, by
63
+ * namespace URI, consulted after {@link undeclared} and before the sink.
64
+ *
65
+ * OOXML maths is the case. `m:EG_OMathMathElements` is admitted wherever
66
+ * `m:oMath` is, so `<w:ins><m:f/></w:ins>` is a tracked insertion of a
67
+ * fraction with no `m:oMath` around it; there are two dozen such names and
68
+ * folio treats every one of them the same way, as markup it carries rather
69
+ * than a structure it models. Naming the namespace states that once. It is
70
+ * not a `default` in disguise: a child from any *other* namespace still goes
71
+ * to the sink, which is the branch a hand-written `default` gets wrong.
72
+ */
73
+ undeclaredNamespaces?: Readonly<Record<string, ChildDisposition>>;
74
+ };
75
+ /**
76
+ * The Transitional spelling of a namespace, so one disposition covers both.
77
+ *
78
+ * ISO Strict writes the same content model under its own URIs: maths is
79
+ * `purl.oclc.org/ooxml/officeDocument/math` rather than
80
+ * `schemas.openxmlformats.org/officeDocument/2006/math`. A namespace-keyed
81
+ * disposition written in Transitional would otherwise send a Strict
82
+ * document's maths to the sink, which models it as bytes instead of an
83
+ * equation. The pairs come from the generated table rather than a second list
84
+ * here, so a namespace cannot be paired in one place and forgotten in the
85
+ * other.
86
+ */
87
+ declare const transitionalNamespaceOf: (namespace: string) => string;
88
+ /**
89
+ * Walk a container's children, handing each to its handler and the rest to the
90
+ * sink.
91
+ *
92
+ * @returns the container's unmodelled markup, or `undefined` when it held
93
+ * none — an empty record is never written, so a fully modelled container
94
+ * stays byte-identical in the model.
95
+ */
96
+ declare const dispatchChildren: <Container extends DispatchedContainer>({ element, handlers, modelledCount, undeclared, undeclaredNamespaces }: DispatchChildrenOptions<Container>) => PreservedMarkup | undefined;
97
+ /**
98
+ * Put a container's modelled children back with its preserved ones between
99
+ * them, in source position.
100
+ *
101
+ * Where the content model demands schema order the caller has already put its
102
+ * modelled children in that order; the sink's `index` then places each capture
103
+ * between the same two siblings it sat between when it was read.
104
+ *
105
+ * @param wrap turns one capture's markup into whatever the caller's list holds
106
+ */
107
+ declare const withPreservedChildren: <Item>(modelled: readonly Item[], preserved: PreservedMarkup | undefined, wrap: (xml: string) => Item) => Item[];
108
+ /** {@link withPreservedChildren} for a caller that already holds markup. */
109
+ declare const serializeWithPreservedChildren: (modelled: readonly string[], preserved: PreservedMarkup | undefined) => string;
110
+ //#endregion
111
+ export { CAPTURE, ChildDisposition, ChildHandlers, DROPPED_WITH_ITS_WRAPPER, OWNED_ELSEWHERE, dispatchChildren, serializeWithPreservedChildren, transitionalNamespaceOf, withPreservedChildren };
@@ -0,0 +1,28 @@
1
+ //#region src/docx/containerChildren.gen.d.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
+ declare const CONTAINER_CHILDREN: {
15
+ readonly "w:comment": readonly ["altChunk", "bookmarkEnd", "bookmarkStart", "commentRangeEnd", "commentRangeStart", "customXml", "customXmlDelRangeEnd", "customXmlDelRangeStart", "customXmlInsRangeEnd", "customXmlInsRangeStart", "customXmlMoveFromRangeEnd", "customXmlMoveFromRangeStart", "customXmlMoveToRangeEnd", "customXmlMoveToRangeStart", "del", "ins", "moveFrom", "moveFromRangeEnd", "moveFromRangeStart", "moveTo", "moveToRangeEnd", "moveToRangeStart", "p", "permEnd", "permStart", "proofErr", "sdt", "tbl"];
16
+ readonly "run-level-content": readonly ["bdo", "bookmarkEnd", "bookmarkStart", "commentRangeEnd", "commentRangeStart", "customXml", "customXmlDelRangeEnd", "customXmlDelRangeStart", "customXmlInsRangeEnd", "customXmlInsRangeStart", "customXmlMoveFromRangeEnd", "customXmlMoveFromRangeStart", "customXmlMoveToRangeEnd", "customXmlMoveToRangeStart", "del", "dir", "fldSimple", "hyperlink", "ins", "moveFrom", "moveFromRangeEnd", "moveFromRangeStart", "moveTo", "moveToRangeEnd", "moveToRangeStart", "pPr", "permEnd", "permStart", "proofErr", "r", "sdt", "smartTag", "smartTagPr", "subDoc"];
17
+ readonly "table-content": readonly ["bookmarkEnd", "bookmarkStart", "commentRangeEnd", "commentRangeStart", "customXml", "customXmlDelRangeEnd", "customXmlDelRangeStart", "customXmlInsRangeEnd", "customXmlInsRangeStart", "customXmlMoveFromRangeEnd", "customXmlMoveFromRangeStart", "customXmlMoveToRangeEnd", "customXmlMoveToRangeStart", "customXmlPr", "del", "ins", "moveFrom", "moveFromRangeEnd", "moveFromRangeStart", "moveTo", "moveToRangeEnd", "moveToRangeStart", "permEnd", "permStart", "proofErr", "sdt", "tblGrid", "tblPr", "tr"];
18
+ readonly "row-content": readonly ["bookmarkEnd", "bookmarkStart", "commentRangeEnd", "commentRangeStart", "customXml", "customXmlDelRangeEnd", "customXmlDelRangeStart", "customXmlInsRangeEnd", "customXmlInsRangeStart", "customXmlMoveFromRangeEnd", "customXmlMoveFromRangeStart", "customXmlMoveToRangeEnd", "customXmlMoveToRangeStart", "del", "ins", "moveFrom", "moveFromRangeEnd", "moveFromRangeStart", "moveTo", "moveToRangeEnd", "moveToRangeStart", "permEnd", "permStart", "proofErr", "sdt", "tblPrEx", "tc", "tr", "trPr"];
19
+ readonly "w:hyperlink": readonly ["bdo", "bookmarkEnd", "bookmarkStart", "commentRangeEnd", "commentRangeStart", "customXml", "customXmlDelRangeEnd", "customXmlDelRangeStart", "customXmlInsRangeEnd", "customXmlInsRangeStart", "customXmlMoveFromRangeEnd", "customXmlMoveFromRangeStart", "customXmlMoveToRangeEnd", "customXmlMoveToRangeStart", "del", "dir", "fldSimple", "hyperlink", "ins", "moveFrom", "moveFromRangeEnd", "moveFromRangeStart", "moveTo", "moveToRangeEnd", "moveToRangeStart", "permEnd", "permStart", "proofErr", "r", "sdt", "smartTag", "subDoc"];
20
+ readonly "w:fldSimple": readonly ["bdo", "bookmarkEnd", "bookmarkStart", "commentRangeEnd", "commentRangeStart", "customXml", "customXmlDelRangeEnd", "customXmlDelRangeStart", "customXmlInsRangeEnd", "customXmlInsRangeStart", "customXmlMoveFromRangeEnd", "customXmlMoveFromRangeStart", "customXmlMoveToRangeEnd", "customXmlMoveToRangeStart", "del", "dir", "fldData", "fldSimple", "hyperlink", "ins", "moveFrom", "moveFromRangeEnd", "moveFromRangeStart", "moveTo", "moveToRangeEnd", "moveToRangeStart", "permEnd", "permStart", "proofErr", "r", "sdt", "smartTag", "subDoc"];
21
+ readonly "block-content": readonly ["altChunk", "bookmarkEnd", "bookmarkStart", "commentRangeEnd", "commentRangeStart", "customXml", "customXmlDelRangeEnd", "customXmlDelRangeStart", "customXmlInsRangeEnd", "customXmlInsRangeStart", "customXmlMoveFromRangeEnd", "customXmlMoveFromRangeStart", "customXmlMoveToRangeEnd", "customXmlMoveToRangeStart", "del", "ins", "moveFrom", "moveFromRangeEnd", "moveFromRangeStart", "moveTo", "moveToRangeEnd", "moveToRangeStart", "p", "permEnd", "permStart", "proofErr", "sdt", "sectPr", "tbl", "tcPr"];
22
+ };
23
+ /** A container the shared child dispatcher covers. */
24
+ type DispatchedContainer = keyof typeof CONTAINER_CHILDREN;
25
+ /** Every child name the schema declares for `Container`. */
26
+ type DeclaredChild<Container extends DispatchedContainer> = (typeof CONTAINER_CHILDREN)[Container][number];
27
+ //#endregion
28
+ export { CONTAINER_CHILDREN, DeclaredChild, DispatchedContainer };