@stll/folio-core 0.54.2 → 0.56.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 (267) hide show
  1. package/dist/ai-edits/apply.js +185 -33
  2. package/dist/ai-edits/headless.js +3 -2
  3. package/dist/ai-edits/types.d.ts +7 -1
  4. package/dist/compare/compare.js +1 -0
  5. package/dist/compare/content-types.d.ts +3 -15
  6. package/dist/compare/reproducible-package.d.ts +0 -17
  7. package/dist/compare/reproducible-package.js +12 -18
  8. package/dist/controller/canonicalClipboard.d.ts +23 -0
  9. package/dist/controller/canonicalClipboard.js +476 -0
  10. package/dist/controller/canonicalClipboardResources.d.ts +21 -0
  11. package/dist/controller/canonicalClipboardResources.js +382 -0
  12. package/dist/controller/canonicalComposition.d.ts +53 -0
  13. package/dist/controller/canonicalComposition.js +296 -0
  14. package/dist/controller/canonicalInlineProjection.d.ts +113 -0
  15. package/dist/controller/canonicalInlineProjection.js +393 -0
  16. package/dist/controller/canonicalInput.d.ts +54 -0
  17. package/dist/controller/canonicalInput.js +377 -0
  18. package/dist/controller/canonicalInputTimer.d.ts +7 -0
  19. package/dist/controller/canonicalInputTimer.js +11 -0
  20. package/dist/controller/canonicalOperations.d.ts +22 -0
  21. package/dist/controller/canonicalOperations.js +85 -0
  22. package/dist/controller/canonicalPublicOperations.d.ts +48 -0
  23. package/dist/controller/canonicalPublicOperations.js +556 -0
  24. package/dist/controller/canonicalReview.d.ts +12 -0
  25. package/dist/controller/canonicalReview.js +19 -0
  26. package/dist/controller/canonicalSession.d.ts +167 -0
  27. package/dist/controller/canonicalSession.js +1186 -0
  28. package/dist/controller/canonicalStoryEditor.d.ts +36 -0
  29. package/dist/controller/canonicalStoryEditor.js +87 -0
  30. package/dist/controller/canonicalStructure.d.ts +16 -0
  31. package/dist/controller/canonicalStructure.js +322 -0
  32. package/dist/controller/canonicalTocSelection.d.ts +11 -0
  33. package/dist/controller/canonicalTocSelection.js +43 -0
  34. package/dist/controller/folioEditor.d.ts +3 -10
  35. package/dist/controller/folioEditor.js +14 -4
  36. package/dist/controller/headerFooterEditorManager.d.ts +5 -0
  37. package/dist/controller/headerFooterEditorManager.js +72 -3
  38. package/dist/controller/hiddenEditorApi.d.ts +45 -0
  39. package/dist/controller/hiddenEditorApi.js +29 -8
  40. package/dist/controller/hiddenEditorManager.d.ts +13 -2
  41. package/dist/controller/hiddenEditorManager.js +639 -31
  42. package/dist/controller/layoutPipeline.d.ts +1 -1
  43. package/dist/controller/layoutPipeline.js +2 -0
  44. package/dist/controller/noteEditorManager.d.ts +5 -0
  45. package/dist/controller/noteEditorManager.js +114 -15
  46. package/dist/document-operations.d.ts +8 -1
  47. package/dist/document-operations.js +6 -4
  48. package/dist/docx/attributeRemainder.js +1 -0
  49. package/dist/docx/blockPlainText.d.ts +1 -1
  50. package/dist/docx/blockPlainText.js +11 -3
  51. package/dist/docx/canonicalResourceSave.d.ts +16 -0
  52. package/dist/docx/canonicalResourceSave.js +27 -0
  53. package/dist/docx/canonicalSave.d.ts +29 -0
  54. package/dist/docx/canonicalSave.js +101 -0
  55. package/dist/docx/canonicalSessionInput.d.ts +11 -0
  56. package/dist/docx/canonicalSessionInput.js +27 -0
  57. package/dist/docx/canonicalStoryRepack.d.ts +10 -0
  58. package/dist/docx/canonicalStoryRepack.js +74 -0
  59. package/dist/docx/contentTypeRegistry.d.ts +8 -0
  60. package/dist/docx/contentTypeRegistry.js +64 -0
  61. package/dist/docx/documentParser.d.ts +1 -13
  62. package/dist/docx/documentParser.js +1 -47
  63. package/dist/docx/ensureParaIds.d.ts +7 -1
  64. package/dist/docx/ensureParaIds.js +173 -215
  65. package/dist/docx/foldedListNumberFields.d.ts +85 -0
  66. package/dist/docx/foldedListNumberFields.js +267 -0
  67. package/dist/docx/footnoteParser.d.ts +1 -11
  68. package/dist/docx/footnoteParser.js +1 -16
  69. package/dist/docx/headerFooterParser.d.ts +1 -9
  70. package/dist/docx/headerFooterParser.js +1 -12
  71. package/dist/docx/headerFooterVerbatim.d.ts +39 -1
  72. package/dist/docx/headerFooterVerbatim.js +173 -2
  73. package/dist/docx/imageParser.d.ts +13 -1
  74. package/dist/docx/imageParser.js +20 -11
  75. package/dist/docx/metadataPrivacy.js +6 -1
  76. package/dist/docx/noteIds.d.ts +5 -0
  77. package/dist/docx/noteIds.js +6 -2
  78. package/dist/docx/noteReferenceMark.d.ts +3 -1
  79. package/dist/docx/noteReferenceMark.js +15 -14
  80. package/dist/docx/numberingParser.d.ts +3 -1
  81. package/dist/docx/numberingParser.js +17 -3
  82. package/dist/docx/packageParts.d.ts +3 -1
  83. package/dist/docx/packageParts.js +74 -19
  84. package/dist/docx/paragraphMarkPropertyPresence.d.ts +9 -0
  85. package/dist/docx/paragraphMarkPropertyPresence.js +21 -0
  86. package/dist/docx/paragraphParser.js +101 -53
  87. package/dist/docx/paragraphPropertySource.d.ts +15 -1
  88. package/dist/docx/paragraphPropertySource.js +77 -22
  89. package/dist/docx/parser.js +3 -1
  90. package/dist/docx/removeHeaderFooterParts.js +17 -6
  91. package/dist/docx/reviewHistoryNamespace.d.ts +4 -0
  92. package/dist/docx/reviewHistoryNamespace.js +4 -0
  93. package/dist/docx/reviewResolutionProvenance.d.ts +25 -0
  94. package/dist/docx/reviewResolutionProvenance.js +153 -0
  95. package/dist/docx/rezip.d.ts +54 -6
  96. package/dist/docx/rezip.js +835 -257
  97. package/dist/docx/runConsolidator.d.ts +2 -58
  98. package/dist/docx/runConsolidator.js +3 -175
  99. package/dist/docx/runParser.d.ts +2 -1
  100. package/dist/docx/runParser.js +156 -116
  101. package/dist/docx/saveDiagnostics.d.ts +22 -0
  102. package/dist/docx/saveDiagnostics.js +0 -0
  103. package/dist/docx/selectiveSave.d.ts +3 -1
  104. package/dist/docx/selectiveSave.js +36 -4
  105. package/dist/docx/selectiveXmlPatch.d.ts +16 -8
  106. package/dist/docx/selectiveXmlPatch.js +81 -7
  107. package/dist/docx/serializer/documentSerializer.d.ts +9 -2
  108. package/dist/docx/serializer/documentSerializer.js +29 -10
  109. package/dist/docx/serializer/headerFooterSerializer.d.ts +5 -1
  110. package/dist/docx/serializer/headerFooterSerializer.js +19 -11
  111. package/dist/docx/serializer/noteSerializer.d.ts +2 -2
  112. package/dist/docx/serializer/noteSerializer.js +24 -8
  113. package/dist/docx/serializer/paragraphSerializer.js +41 -4
  114. package/dist/docx/serializer/partNamespaces.js +2 -1
  115. package/dist/docx/serializer/runSerializer.js +3 -1
  116. package/dist/docx/server/applyDocxXmlPatchProposal.js +14 -9
  117. package/dist/docx/settingsHeaderFooterUpdate.d.ts +5 -0
  118. package/dist/docx/settingsHeaderFooterUpdate.js +90 -0
  119. package/dist/docx/settingsParser.d.ts +1 -2
  120. package/dist/docx/settingsParser.js +5 -6
  121. package/dist/docx/storyBlockReplay.d.ts +31 -0
  122. package/dist/docx/storyBlockReplay.js +471 -0
  123. package/dist/docx/storyPlainText.d.ts +20 -0
  124. package/dist/docx/storyPlainText.js +23 -0
  125. package/dist/docx/streamingXmlParser.d.ts +22 -1
  126. package/dist/docx/streamingXmlParser.js +49 -3
  127. package/dist/docx/structuralXmlPatch.js +18 -23
  128. package/dist/docx/styleParser.d.ts +5 -1
  129. package/dist/docx/styleParser.js +1 -1
  130. package/dist/docx/tableParser.d.ts +1 -8
  131. package/dist/docx/tableParser.js +1 -28
  132. package/dist/docx/textBoxParser.d.ts +1 -5
  133. package/dist/docx/textBoxParser.js +1 -20
  134. package/dist/docx/unzip.js +6 -1
  135. package/dist/docx/verbatimCapture.d.ts +3 -1
  136. package/dist/docx/verbatimCapture.js +49 -6
  137. package/dist/i18n/messages/ar.gen.d.ts +5 -0
  138. package/dist/i18n/messages/ar.gen.js +656 -0
  139. package/dist/i18n/messages/cs.gen.d.ts +5 -0
  140. package/dist/i18n/messages/cs.gen.js +656 -0
  141. package/dist/i18n/messages/de.gen.d.ts +5 -0
  142. package/dist/i18n/messages/de.gen.js +656 -0
  143. package/dist/i18n/messages/en.gen.d.ts +5 -0
  144. package/dist/i18n/messages/en.gen.js +656 -0
  145. package/dist/i18n/messages/es.gen.d.ts +5 -0
  146. package/dist/i18n/messages/es.gen.js +656 -0
  147. package/dist/i18n/messages/et.gen.d.ts +5 -0
  148. package/dist/i18n/messages/et.gen.js +656 -0
  149. package/dist/i18n/messages/fr.gen.d.ts +5 -0
  150. package/dist/i18n/messages/fr.gen.js +656 -0
  151. package/dist/i18n/messages/he.gen.d.ts +5 -0
  152. package/dist/i18n/messages/he.gen.js +656 -0
  153. package/dist/i18n/messages/hi.gen.d.ts +5 -0
  154. package/dist/i18n/messages/hi.gen.js +656 -0
  155. package/dist/i18n/messages/hu.gen.d.ts +5 -0
  156. package/dist/i18n/messages/hu.gen.js +656 -0
  157. package/dist/i18n/messages/locales.d.ts +5 -0
  158. package/dist/i18n/messages/locales.js +22 -0
  159. package/dist/i18n/messages/lt.gen.d.ts +5 -0
  160. package/dist/i18n/messages/lt.gen.js +656 -0
  161. package/dist/i18n/messages/lv.gen.d.ts +5 -0
  162. package/dist/i18n/messages/lv.gen.js +656 -0
  163. package/dist/i18n/messages/pl.gen.d.ts +5 -0
  164. package/dist/i18n/messages/pl.gen.js +656 -0
  165. package/dist/i18n/messages/pt-BR.gen.d.ts +5 -0
  166. package/dist/i18n/messages/pt-BR.gen.js +656 -0
  167. package/dist/i18n/messages/sk.gen.d.ts +5 -0
  168. package/dist/i18n/messages/sk.gen.js +656 -0
  169. package/dist/i18n/messages/tr.gen.d.ts +5 -0
  170. package/dist/i18n/messages/tr.gen.js +656 -0
  171. package/dist/i18n/messages/zh-CN.gen.d.ts +5 -0
  172. package/dist/i18n/messages/zh-CN.gen.js +656 -0
  173. package/dist/i18n/messages.d.ts +2 -3
  174. package/dist/i18n/messages.js +1 -19
  175. package/dist/internal/acceptedBlockProjection.d.ts +12 -0
  176. package/dist/internal/acceptedBlockProjection.js +45 -0
  177. package/dist/internal/noteMarkerAttrs.d.ts +8 -0
  178. package/dist/internal/noteMarkerAttrs.js +16 -0
  179. package/dist/internal/pageBreakRunSourceDescendantIndex.js +1 -0
  180. package/dist/internal/prosemirrorAttrBoundary.d.ts +21 -0
  181. package/dist/internal/prosemirrorAttrBoundary.js +50 -0
  182. package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
  183. package/dist/layout-bridge/convert/footnoteLayout.js +3 -3
  184. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
  185. package/dist/layout-bridge/convert/headerFooterLayout.js +1 -0
  186. package/dist/layout-bridge/convert/noteReferences.d.ts +1 -3
  187. package/dist/layout-bridge/convert/noteReferences.js +1 -6
  188. package/dist/layout-bridge/convert/paragraphRuns.js +2 -4
  189. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +2 -2
  190. package/dist/layout-bridge/convert/toFlowBlocks.js +2 -2
  191. package/dist/managers/DocumentLoaderManager.d.ts +1 -0
  192. package/dist/managers/DocumentLoaderManager.js +9 -1
  193. package/dist/markdown/escape.d.ts +3 -1
  194. package/dist/markdown/escape.js +9 -2
  195. package/dist/markdown/renderBlock.js +20 -121
  196. package/dist/markdown/renderParagraph.js +13 -15
  197. package/dist/markdown/renderRuns.d.ts +7 -1
  198. package/dist/markdown/renderRuns.js +35 -15
  199. package/dist/markdown/renderTable.js +2 -0
  200. package/dist/markdown/types.d.ts +3 -9
  201. package/dist/prosemirror/attrs/index.d.ts +2 -12
  202. package/dist/prosemirror/attrs/index.js +22 -48
  203. package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +2 -1
  204. package/dist/prosemirror/canonicalCommands.d.ts +121 -0
  205. package/dist/prosemirror/canonicalCommands.js +35 -0
  206. package/dist/prosemirror/canonicalSelectionRange.d.ts +9 -0
  207. package/dist/prosemirror/canonicalSelectionRange.js +15 -0
  208. package/dist/prosemirror/clipboardIntent.d.ts +7 -0
  209. package/dist/prosemirror/clipboardIntent.js +9 -0
  210. package/dist/prosemirror/commands/pageBreak.js +15 -1
  211. package/dist/prosemirror/commands/pastePlainText.js +2 -1
  212. package/dist/prosemirror/commentReferenceAttrs.d.ts +2 -1
  213. package/dist/prosemirror/conversion/fromProseDoc.js +91 -19
  214. package/dist/prosemirror/conversion/hyphenTextCarriers.d.ts +8 -0
  215. package/dist/prosemirror/conversion/hyphenTextCarriers.js +8 -0
  216. package/dist/prosemirror/conversion/listRenderingDefinition.d.ts +6 -0
  217. package/dist/prosemirror/conversion/listRenderingDefinition.js +97 -0
  218. package/dist/prosemirror/conversion/toProseDoc.d.ts +11 -4
  219. package/dist/prosemirror/conversion/toProseDoc.js +55 -14
  220. package/dist/prosemirror/executeEditorCommand.d.ts +11 -0
  221. package/dist/prosemirror/executeEditorCommand.js +26 -0
  222. package/dist/prosemirror/extensions/StarterKit.js +2 -0
  223. package/dist/prosemirror/extensions/core/ParagraphExtension.js +88 -48
  224. package/dist/prosemirror/extensions/features/ListExtension.js +18 -5
  225. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +5 -2
  226. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +13 -1
  227. package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +56 -28
  228. package/dist/prosemirror/extensions/marks/TextColorExtension.js +3 -2
  229. package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +2 -0
  230. package/dist/prosemirror/extensions/marks/markUtils.js +72 -8
  231. package/dist/prosemirror/extensions/nodes/NoteMarkerExtension.d.ts +6 -0
  232. package/dist/prosemirror/extensions/nodes/NoteMarkerExtension.js +36 -0
  233. package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.js +4 -2
  234. package/dist/prosemirror/insertOperations.js +2 -1
  235. package/dist/prosemirror/listMarker.d.ts +1 -0
  236. package/dist/prosemirror/listMarker.js +16 -7
  237. package/dist/prosemirror/listNumbering.js +26 -5
  238. package/dist/prosemirror/listRenderingAttrs.d.ts +1 -0
  239. package/dist/prosemirror/listRenderingAttrs.js +3 -0
  240. package/dist/prosemirror/markupViewNotes.js +3 -2
  241. package/dist/prosemirror/moveRangeBoundaryAttrs.d.ts +2 -1
  242. package/dist/prosemirror/noteReferenceReview.js +5 -3
  243. package/dist/prosemirror/paragraphPropertyCarry.d.ts +7 -1
  244. package/dist/prosemirror/paragraphPropertyCarry.js +8 -3
  245. package/dist/prosemirror/plugins/suggestionMode.js +57 -7
  246. package/dist/prosemirror/rangeAnchorAttrs.d.ts +2 -1
  247. package/dist/prosemirror/runFormattingFromMarks.d.ts +4 -1
  248. package/dist/prosemirror/runFormattingFromMarks.js +15 -1
  249. package/dist/prosemirror/runFormattingInlineCarriers.d.ts +2 -1
  250. package/dist/prosemirror/runFormattingInlineCarriers.js +4 -1
  251. package/dist/prosemirror/schema/marks.d.ts +2 -0
  252. package/dist/prosemirror/schema/nodes.d.ts +10 -2
  253. package/dist/prosemirror/textBoxAnchorAttrs.d.ts +2 -1
  254. package/dist/prosemirror/textInput.js +5 -1
  255. package/dist/prosemirror/trackedRevisionPath.js +2 -1
  256. package/dist/prosemirror/trackedRunInlineAtoms.d.ts +1 -0
  257. package/dist/prosemirror/trackedRunInlineAtoms.js +1 -0
  258. package/dist/prosemirror/validation.js +4 -0
  259. package/dist/types/canonicalCapabilities.d.ts +215 -0
  260. package/dist/types/canonicalCapabilities.js +212 -0
  261. package/dist/types/canonicalSave.d.ts +11 -0
  262. package/dist/types/canonicalSave.js +0 -0
  263. package/dist/types/content.d.ts +2 -2
  264. package/dist/types/docxSerialization.d.ts +14 -0
  265. package/dist/types/docxSerialization.js +7 -0
  266. package/dist/utils/createDocument.js +2 -2
  267. package/package.json +16 -4
@@ -10,7 +10,7 @@ import { RELATIONSHIP_TYPES, resolveRelationshipIdOfType } from "./relsParser.js
10
10
  import { isTextBoxDrawing } from "./textBoxParser.js";
11
11
  import { percentageSpelling } from "./transitionalSpelling.js";
12
12
  import { captureVerbatimXml } from "./verbatimCapture.js";
13
- import { findByFullName, findChildByNamespaceUri, findChildrenByNamespaceUri, getAttribute, getChildElements, getLocalName, getNamespaceUri, parseNumericAttribute, parseOnOffAttribute, parseOnOffValue } from "./xmlParser.js";
13
+ import { OFFICE_RELATIONSHIP_NAMESPACE_URIS, findAttributeByNamespaceUri, findByFullName, findChildByNamespaceUri, findChildrenByNamespaceUri, getAttribute, getChildElements, getLocalName, getNamespaceUri, parseNumericAttribute, parseOnOffAttribute, parseOnOffValue } from "./xmlParser.js";
14
14
  import { relationshipIdOf } from "@stll/docx-core/model";
15
15
  //#region src/docx/imageParser.ts
16
16
  /**
@@ -129,7 +129,7 @@ const parseDocPropsExtensions = (docPr) => {
129
129
  const parseDocPrLink = (docPr, localName) => {
130
130
  const element = findChildByNamespaceUri(docPr, DRAWINGML_NAMESPACE_URIS, localName);
131
131
  if (!element) return;
132
- const rId = getAttribute(element, "r", "id");
132
+ const rId = findAttributeByNamespaceUri(element, OFFICE_RELATIONSHIP_NAMESPACE_URIS, "id")?.value;
133
133
  return {
134
134
  xml: captureVerbatimXml(element),
135
135
  ...rId == null ? {} : { rId }
@@ -382,6 +382,13 @@ function resolveImageData(rId, rels, media) {
382
382
  ...filename !== void 0 ? { filename } : {}
383
383
  };
384
384
  }
385
+ /** Facts the parser obtains from exported drawing markup and image relationships. */
386
+ const imageDerivedFactsOf = ({ id, pictureNames, imageData }) => ({
387
+ ...id ? { id } : {},
388
+ ...Object.keys(pictureNames).length > 0 ? { pictureNames } : {},
389
+ ...imageData.mimeType ? { mimeType: imageData.mimeType } : {},
390
+ ...imageData.filename ? { filename: imageData.filename } : {}
391
+ });
385
392
  /**
386
393
  * Parse a wp:inline element (inline image)
387
394
  *
@@ -411,18 +418,19 @@ function parseInline(inlineEl, rels, media) {
411
418
  size,
412
419
  wrap
413
420
  };
414
- if (props.id) image.id = props.id;
421
+ Object.assign(image, imageDerivedFactsOf({
422
+ id: props.id,
423
+ pictureNames,
424
+ imageData
425
+ }));
415
426
  if (props.name !== void 0) image.docPrName = props.name;
416
427
  if (props.alt !== void 0) image.alt = props.alt;
417
428
  if (props.title !== void 0) image.title = props.title;
418
- if (Object.keys(pictureNames).length > 0) image.pictureNames = pictureNames;
419
429
  if (props.decorative !== void 0) image.decorative = props.decorative;
420
430
  if (props.hidden !== void 0) image.hidden = props.hidden;
421
431
  if (props.docPrExtensions !== void 0) image.docPrExtensions = props.docPrExtensions;
422
432
  const safeSrc = sanitizeImageSrc(imageData.src);
423
433
  if (safeSrc) image.src = safeSrc;
424
- if (imageData.mimeType) image.mimeType = imageData.mimeType;
425
- if (imageData.filename) image.filename = imageData.filename;
426
434
  if (padding) image.padding = padding;
427
435
  if (transform) image.transform = transform;
428
436
  if (crop) image.crop = crop;
@@ -492,18 +500,19 @@ function parseAnchor(anchorEl, rels, media) {
492
500
  size,
493
501
  wrap
494
502
  };
495
- if (props.id) image.id = props.id;
503
+ Object.assign(image, imageDerivedFactsOf({
504
+ id: props.id,
505
+ pictureNames,
506
+ imageData
507
+ }));
496
508
  if (props.name !== void 0) image.docPrName = props.name;
497
509
  if (props.alt !== void 0) image.alt = props.alt;
498
510
  if (props.title !== void 0) image.title = props.title;
499
- if (Object.keys(pictureNames).length > 0) image.pictureNames = pictureNames;
500
511
  if (props.decorative !== void 0) image.decorative = props.decorative;
501
512
  if (props.hidden !== void 0) image.hidden = props.hidden;
502
513
  if (props.docPrExtensions !== void 0) image.docPrExtensions = props.docPrExtensions;
503
514
  const safeSrc = sanitizeImageSrc(imageData.src);
504
515
  if (safeSrc) image.src = safeSrc;
505
- if (imageData.mimeType) image.mimeType = imageData.mimeType;
506
- if (imageData.filename) image.filename = imageData.filename;
507
516
  if (position) image.position = position;
508
517
  if (padding) image.padding = padding;
509
518
  if (transform) image.transform = transform;
@@ -628,4 +637,4 @@ function needsTextWrapping(image) {
628
637
  ].includes(image.wrap.type);
629
638
  }
630
639
  //#endregion
631
- export { DECORATIVE_EXTENSION_URI, DECORATIVE_NAMESPACE, getImageDimensionsPx, getImageHeightPx, getImageWidthPx, getWrapDistancesPx, hasAltText, isBehindText, isDecorativeImage, isFloatingImage, isInFrontOfText, isInlineImage, needsTextWrapping, parseDrawing, parseImage, resolveImageData };
640
+ export { DECORATIVE_EXTENSION_URI, DECORATIVE_NAMESPACE, getImageDimensionsPx, getImageHeightPx, getImageWidthPx, getWrapDistancesPx, hasAltText, imageDerivedFactsOf, isBehindText, isDecorativeImage, isFloatingImage, isInFrontOfText, isInlineImage, needsTextWrapping, parseDrawing, parseImage, resolveImageData };
@@ -1,6 +1,7 @@
1
1
  import { countCentralDirectoryRecords, createInflationBudget, inflateEntryWithinLimits } from "./archiveInflation.js";
2
2
  import { elementToXml, getLocalName, parseXmlDocument } from "./xmlParser.js";
3
3
  import { TaggedError } from "better-result";
4
+ import { writeZipPart } from "@stll/docx-core/zip";
4
5
  import JSZip from "jszip";
5
6
  //#region src/docx/metadataPrivacy.ts
6
7
  const FOLIO_DOCUMENT_METADATA_PROPERTIES = Object.freeze([
@@ -152,7 +153,11 @@ const rewriteDocxMetadataPrivacy = async (buffer, { transforms }) => {
152
153
  removedMetadataProperties: []
153
154
  }
154
155
  };
155
- zip.file(coreProperties.name, rewritten.xml);
156
+ writeZipPart({
157
+ zip,
158
+ path: coreProperties.name,
159
+ data: rewritten.xml
160
+ });
156
161
  return {
157
162
  buffer: await zip.generateAsync({
158
163
  type: "arraybuffer",
@@ -1,4 +1,9 @@
1
1
  //#region src/docx/noteIds.d.ts
2
+ /**
3
+ * The next free endnote id among `existingIds`, a document's endnotes. Ids are
4
+ * unique per document, so the allocator lives for one call: the result
5
+ * depends only on the document, never on what other documents minted.
6
+ */
2
7
  declare const mintEndnoteId: (existingIds: Iterable<number>) => number;
3
8
  //#endregion
4
9
  export { mintEndnoteId };
@@ -1,8 +1,12 @@
1
1
  import { createNumericIdAllocator } from "./numericIdAllocator.js";
2
2
  //#region src/docx/noteIds.ts
3
- let endnoteIds;
3
+ /**
4
+ * The next free endnote id among `existingIds`, a document's endnotes. Ids are
5
+ * unique per document, so the allocator lives for one call: the result
6
+ * depends only on the document, never on what other documents minted.
7
+ */
4
8
  const mintEndnoteId = (existingIds) => {
5
- const allocator = endnoteIds ??= createNumericIdAllocator({
9
+ const allocator = createNumericIdAllocator({
6
10
  space: "endnote",
7
11
  firstId: 1
8
12
  });
@@ -3,6 +3,8 @@ import { document_d_exports } from "../types/document.js";
3
3
  type NoteKind = "footnote" | "endnote";
4
4
  /** The run carrying a note's in-note reference mark, in the note reference style. */
5
5
  declare const noteReferenceMarkRun: (kind: NoteKind) => document_d_exports.Run;
6
+ /** Whether a note already owns its typed marker, including inside tracked content. */
7
+ declare const hasNoteReferenceMark: (kind: NoteKind, content: readonly document_d_exports.BlockContent[]) => boolean;
6
8
  /**
7
9
  * A note's content with its reference mark run at the start of its first
8
10
  * paragraph, added when the note has none.
@@ -12,4 +14,4 @@ declare const withNoteReferenceMark: (kind: NoteKind, content: readonly document
12
14
  declare function createNote(kind: "footnote", id: number, content: readonly document_d_exports.BlockContent[]): document_d_exports.Footnote;
13
15
  declare function createNote(kind: "endnote", id: number, content: readonly document_d_exports.BlockContent[]): document_d_exports.Endnote;
14
16
  //#endregion
15
- export { createNote, noteReferenceMarkRun, withNoteReferenceMark };
17
+ export { createNote, hasNoteReferenceMark, noteReferenceMarkRun, withNoteReferenceMark };
@@ -1,37 +1,38 @@
1
1
  import { cloneParagraphWithPropertySource } from "./paragraphPropertySource.js";
2
+ import { visitDocxParagraphs, visitParagraphRuns } from "./paragraphTraversal.js";
2
3
  //#region src/docx/noteReferenceMark.ts
3
- const MARK_ELEMENT = /<(?:[\w.-]+:)?(?:footnote|endnote)Ref[\s/>]/u;
4
4
  /** The run carrying a note's in-note reference mark, in the note reference style. */
5
5
  const noteReferenceMarkRun = (kind) => ({
6
6
  type: "run",
7
7
  formatting: { styleId: kind === "footnote" ? "FootnoteReference" : "EndnoteReference" },
8
8
  content: [{
9
- type: "preservedXml",
10
- xml: `<w:${kind}Ref/>`,
11
- text: ""
9
+ type: "noteMarker",
10
+ kind
12
11
  }]
13
12
  });
14
- const holdsReferenceMark = (value) => {
15
- if (Array.isArray(value)) return value.some(holdsReferenceMark);
16
- if (typeof value !== "object" || value === null) return false;
17
- const record = value;
18
- if (record["type"] === "preservedXml" && typeof record["xml"] === "string") return MARK_ELEMENT.test(record["xml"]);
19
- return Object.values(record).some(holdsReferenceMark);
13
+ /** Whether a note already owns its typed marker, including inside tracked content. */
14
+ const hasNoteReferenceMark = (kind, content) => {
15
+ let found = false;
16
+ visitDocxParagraphs({ documentBody: { content: [...content] } }, (paragraph) => {
17
+ visitParagraphRuns(paragraph, (run) => {
18
+ if (run.content.some((child) => child.type === "noteMarker" && child.kind === kind)) found = true;
19
+ });
20
+ });
21
+ return found;
20
22
  };
21
23
  /**
22
24
  * A note's content with its reference mark run at the start of its first
23
25
  * paragraph, added when the note has none.
24
26
  */
25
27
  const withNoteReferenceMark = (kind, content) => {
26
- if (holdsReferenceMark(content)) return [...content];
28
+ if (hasNoteReferenceMark(kind, content)) return [...content];
27
29
  const index = content.findIndex((block) => block.type === "paragraph");
28
30
  const mark = noteReferenceMarkRun(kind);
29
31
  if (index === -1) return [{
30
32
  type: "paragraph",
31
33
  content: [mark]
32
34
  }, ...content];
33
- const paragraph = content[index];
34
- return content.map((block, position) => position === index ? cloneParagraphWithPropertySource(paragraph, { content: [mark, ...paragraph.content] }) : block);
35
+ return content.map((block, position) => position === index && block.type === "paragraph" ? cloneParagraphWithPropertySource(block, { content: [mark, ...block.content] }) : block);
35
36
  };
36
37
  function createNote(kind, id, content) {
37
38
  return kind === "footnote" ? {
@@ -45,4 +46,4 @@ function createNote(kind, id, content) {
45
46
  };
46
47
  }
47
48
  //#endregion
48
- export { createNote, noteReferenceMarkRun, withNoteReferenceMark };
49
+ export { createNote, hasNoteReferenceMark, noteReferenceMarkRun, withNoteReferenceMark };
@@ -81,7 +81,9 @@ declare function getBulletCharacter(level: document_d_exports.ListLevel): string
81
81
  * Check if a list level is a bullet (not numbered)
82
82
  */
83
83
  declare function isBulletLevel(level: document_d_exports.ListLevel): boolean;
84
+ /** Whether a numbering definition uses a bullet marker rather than a numeric or hidden one. */
85
+ declare const numberingLevelUsesBulletMarker: (level: Pick<document_d_exports.ListLevel, "numFmt"> | null | undefined) => boolean;
84
86
  /** Whether a numbering level reserves horizontal space for a visible marker. */
85
87
  declare const numberingLevelHasMarkerSlot: (level: Pick<document_d_exports.ListLevel, "numFmt">) => boolean;
86
88
  //#endregion
87
- export { NumberingMap, computeListRendering, counterFormatOf, createNumberingMap, customNumberFormatPadWidth, formatOoxmlCounter as formatNumber, getBulletCharacter, getCachedNumberingMap, isBulletLevel, markerAlignmentForLevel, markerFormattingFromLevel, numberingLevelHasMarkerSlot, padDecimal, parseNumbering, renderListMarker };
89
+ export { NumberingMap, computeListRendering, counterFormatOf, createNumberingMap, customNumberFormatPadWidth, formatOoxmlCounter as formatNumber, getBulletCharacter, getCachedNumberingMap, isBulletLevel, markerAlignmentForLevel, markerFormattingFromLevel, numberingLevelHasMarkerSlot, numberingLevelUsesBulletMarker, padDecimal, parseNumbering, renderListMarker };
@@ -6,7 +6,20 @@ import { parseParagraphProperties } from "./paragraphProperties.js";
6
6
  import { LevelSuffixSchema, NumberFormatSchema, ParagraphAlignmentSchema, narrowEnum } from "./parserEnums.js";
7
7
  import { RUN_PROPERTY_OWNERS, parseRunProperties } from "./runParser.js";
8
8
  import { findChild, getAttribute, parseBooleanElement, parseNumericAttribute, parseOnOffAttribute, parseXmlDocument } from "./xmlParser.js";
9
+ import { isNumberingLevel } from "@stll/docx-core/model";
9
10
  //#region src/docx/numberingParser.ts
11
+ /**
12
+ * Numbering/List Parser for DOCX
13
+ *
14
+ * Parses numbering.xml to extract:
15
+ * - Abstract numbering definitions (templates with levels)
16
+ * - Numbering instances (concrete references with optional overrides)
17
+ *
18
+ * OOXML Structure:
19
+ * - w:abstractNum - Template definitions with 9 levels (0-8)
20
+ * - w:num - Instances that reference abstractNum and can override levels
21
+ * - w:lvl - Level definition with start, format, text pattern, etc.
22
+ */
10
23
  /** `w:abstractNum` reads its id; everything else it carries is the remainder's. */
11
24
  const MODELLED_ABSTRACT_NUM_ATTRIBUTES = /* @__PURE__ */ new Set(["abstractNumId"]);
12
25
  /** `w:lvl` reads the level it defines and Word's two template markers. */
@@ -117,7 +130,6 @@ function parseAbstractNumbering(element) {
117
130
  return abstractNum;
118
131
  }
119
132
  /** ECMA-376 §17.9.1: a `w:abstractNum` defines levels 0 through 8 and no more. */
120
- const MAX_LIST_LEVEL = 8;
121
133
  const MULTI_LEVEL_TYPES = [
122
134
  "hybridMultilevel",
123
135
  "multilevel",
@@ -392,7 +404,7 @@ function createNumberingMap(definitions) {
392
404
  return {
393
405
  definitions,
394
406
  getLevel(numId, ilvl) {
395
- if (ilvl < 0 || ilvl > MAX_LIST_LEVEL) return null;
407
+ if (!isNumberingLevel(ilvl)) return null;
396
408
  const num = numMap.get(numId);
397
409
  if (!num) return null;
398
410
  if (num.levelOverrides) {
@@ -524,7 +536,9 @@ function getBulletCharacter(level) {
524
536
  function isBulletLevel(level) {
525
537
  return level.numFmt === "bullet" || level.numFmt === "none";
526
538
  }
539
+ /** Whether a numbering definition uses a bullet marker rather than a numeric or hidden one. */
540
+ const numberingLevelUsesBulletMarker = (level) => level?.numFmt === "bullet";
527
541
  /** Whether a numbering level reserves horizontal space for a visible marker. */
528
542
  const numberingLevelHasMarkerSlot = (level) => level.numFmt !== "none";
529
543
  //#endregion
530
- export { computeListRendering, counterFormatOf, createNumberingMap, customNumberFormatPadWidth, formatOoxmlCounter as formatNumber, getBulletCharacter, getCachedNumberingMap, isBulletLevel, markerAlignmentForLevel, markerFormattingFromLevel, numberingLevelHasMarkerSlot, padDecimal, parseNumbering, renderListMarker };
544
+ export { computeListRendering, counterFormatOf, createNumberingMap, customNumberFormatPadWidth, formatOoxmlCounter as formatNumber, getBulletCharacter, getCachedNumberingMap, isBulletLevel, markerAlignmentForLevel, markerFormattingFromLevel, numberingLevelHasMarkerSlot, numberingLevelUsesBulletMarker, padDecimal, parseNumbering, renderListMarker };
@@ -1,5 +1,7 @@
1
1
  import JSZip from "jszip";
2
2
  //#region src/docx/packageParts.d.ts
3
+ /** Resolve an internal URI reference once, before comparing it with ZIP entries. */
4
+ declare const resolvePackageRelationshipTarget: (target: string, relsPath: string) => string | undefined;
3
5
  /**
4
6
  * Whether an entry path would escape the package when a host writes the archive
5
7
  * to disk: absolute, backslash-separated, or climbing out through `..`. This is
@@ -76,4 +78,4 @@ type PackageIntegrityReport = {
76
78
  */
77
79
  declare const checkPackageIntegrity: (zip: JSZip) => Promise<PackageIntegrityReport>;
78
80
  //#endregion
79
- export { PackageIntegrityReport, PackageReferenceRepair, checkPackageIntegrity, isUnsafePackagePath, reconcilePackageReferences, removeUnsafeEntries };
81
+ export { PackageIntegrityReport, PackageReferenceRepair, checkPackageIntegrity, isUnsafePackagePath, reconcilePackageReferences, removeUnsafeEntries, resolvePackageRelationshipTarget };
@@ -1,5 +1,31 @@
1
- import { resolveRelativePath } from "./relsParser.js";
1
+ import { Result } from "better-result";
2
+ import { writeZipPart } from "@stll/docx-core/zip";
2
3
  //#region src/docx/packageParts.ts
4
+ /**
5
+ * What a repack carries out of the source package, and the guarantee that
6
+ * nothing in the output points at a part the output does not hold.
7
+ *
8
+ * A `.docx` is an OPC package: `[Content_Types].xml` declares every part in it
9
+ * and the `.rels` parts wire them together. Folio models a handful of those
10
+ * parts (the document body, headers, footers, notes, numbering, styles,
11
+ * comments) and rewrites them on save. Everything else — embedded objects,
12
+ * media, custom XML, fonts, charts, macro projects, parts folio has never heard
13
+ * of — belongs to the author, and a repack hands it back byte for byte.
14
+ *
15
+ * Folio never executes document content and never removes it. The document is
16
+ * the user's; the only thing a save refuses is a package path that would let
17
+ * the archive escape its own directory when a host writes it out, which is a
18
+ * property of the package structure rather than of the content. A macro-enabled
19
+ * document therefore stays macro-enabled, main-part content type included:
20
+ * silently handing back a `.docm` stripped of its project is data loss dressed
21
+ * up as safety.
22
+ *
23
+ * A refused path loses its relationships and its content-type override with it.
24
+ * That is the invariant this module exists for: Word and LibreOffice both
25
+ * refuse a package whose `document.xml.rels` points at nothing, so a repack
26
+ * that removes a part without removing its references produces a file that
27
+ * does not open.
28
+ */
3
29
  const CONTENT_TYPE_ELEMENT = /<(?:Default|Override)\b[^>]*?\/?>/giu;
4
30
  const PART_NAME_ATTRIBUTE = /\bPartName\s*=\s*(?<quote>["'])(?<value>[^"']*)\k<quote>/u;
5
31
  const RELATIONSHIP_ELEMENT = /<Relationship\b[^>]*?(?:\/>|>\s*<\/Relationship>)/giu;
@@ -24,12 +50,38 @@ const owningPartPath = (relsPath) => {
24
50
  };
25
51
  /** Normalize a package path for comparison: lower case, no leading slash. */
26
52
  const normalizePartPath = (path) => (path.startsWith("/") ? path.slice(1) : path).toLowerCase();
27
- /**
28
- * Decode `%XX` escapes in a part name. `decodeURI` throws on a malformed
29
- * escape, and a malformed target is exactly the input this has to survive, so
30
- * the replacement is done by hand.
31
- */
32
- const decodePartName = (name) => name.replaceAll(/%[0-9A-Fa-f]{2}/gu, (escape) => String.fromCharCode(Number.parseInt(escape.slice(1), 16)));
53
+ /** Decode URI escapes as UTF-8; malformed references cannot name a part. */
54
+ const decodePartName = (name) => {
55
+ const decoded = Result.try({
56
+ try: () => decodeURIComponent(name),
57
+ catch: () => void 0
58
+ });
59
+ return decoded.isOk() ? decoded.value : void 0;
60
+ };
61
+ /** Resolve an internal URI reference once, before comparing it with ZIP entries. */
62
+ const resolvePackageRelationshipTarget = (target, relsPath) => {
63
+ const fragment = target.indexOf("#");
64
+ if (fragment === 0) {
65
+ const owner = owningPartPath(relsPath);
66
+ return owner === void 0 ? void 0 : normalizePartPath(owner);
67
+ }
68
+ const reference = fragment > 0 ? target.slice(0, fragment) : target;
69
+ if (!reference || reference.startsWith("//") || /[\\?:]/u.test(reference)) return void 0;
70
+ const owner = owningPartPath(relsPath);
71
+ const segments = reference.startsWith("/") || owner === void 0 ? [] : owner.split("/").slice(0, -1);
72
+ for (const encoded of reference.split("/")) {
73
+ const segment = decodePartName(encoded);
74
+ if (segment === void 0 || /[/\\]/u.test(segment) || segment.includes(String.fromCharCode(0))) return void 0;
75
+ if (segment === "" || segment === ".") continue;
76
+ if (segment === "..") {
77
+ if (segments.pop() === void 0) return void 0;
78
+ continue;
79
+ }
80
+ segments.push(segment);
81
+ }
82
+ const path = normalizePartPath(segments.join("/"));
83
+ return isUnsafePackagePath(path) ? void 0 : path;
84
+ };
33
85
  /**
34
86
  * Whether an entry path would escape the package when a host writes the archive
35
87
  * to disk: absolute, backslash-separated, or climbing out through `..`. This is
@@ -53,15 +105,13 @@ const presentPartPaths = (zip) => {
53
105
  for (const [path, file] of Object.entries(zip.files)) if (!file.dir) present.add(normalizePartPath(path));
54
106
  return present;
55
107
  };
56
- const isPresent = (present, partPath) => present.has(normalizePartPath(partPath)) || present.has(normalizePartPath(decodePartName(partPath)));
108
+ const isPresent = (present, partPath) => present.has(normalizePartPath(partPath)) || present.has(normalizePartPath(decodePartName(partPath) ?? ""));
57
109
  /** The part a relationship names, or null when it points outside the package. */
58
110
  const relationshipTarget = (element, relsPath) => {
59
111
  if (TARGET_MODE_ATTRIBUTE.exec(element)?.groups?.["value"] === "External") return null;
60
112
  const target = TARGET_ATTRIBUTE.exec(element)?.groups?.["value"];
61
113
  if (target === void 0) return null;
62
- const fragment = target.indexOf("#");
63
- if (fragment === 0) return owningPartPath(relsPath) ?? "";
64
- return resolveRelativePath(relsPath, fragment > 0 ? target.slice(0, fragment) : target);
114
+ return resolvePackageRelationshipTarget(target, relsPath) ?? "";
65
115
  };
66
116
  /**
67
117
  * Every `.rels` part with its text. Read one at a time rather than through
@@ -80,9 +130,14 @@ const readRelationshipParts = async (zip) => {
80
130
  return parts;
81
131
  };
82
132
  const writePart = ({ zip, path, xml, compressionLevel }) => {
83
- zip.file(path, xml, {
84
- compression: "DEFLATE",
85
- compressionOptions: { level: compressionLevel }
133
+ writeZipPart({
134
+ zip,
135
+ path,
136
+ data: xml,
137
+ options: {
138
+ compression: "DEFLATE",
139
+ compressionOptions: { level: compressionLevel }
140
+ }
86
141
  });
87
142
  };
88
143
  /**
@@ -107,8 +162,8 @@ const reconcilePackageReferences = async (zip, compressionLevel) => {
107
162
  let dropped = false;
108
163
  const pruned = xml.replaceAll(RELATIONSHIP_ELEMENT, (element) => {
109
164
  const target = relationshipTarget(element, path);
110
- if (target === null || isPresent(present, target)) return element;
111
- repair.danglingRelationships.push(target);
165
+ if (target === null || present.has(target)) return element;
166
+ repair.danglingRelationships.push(target || TARGET_ATTRIBUTE.exec(element)?.groups?.["value"] || "");
112
167
  dropped = true;
113
168
  const id = RELATIONSHIP_ID_ATTRIBUTE.exec(element)?.groups?.["value"];
114
169
  const owningPart = owningPartPath(path);
@@ -154,7 +209,7 @@ const reconcilePackageReferences = async (zip, compressionLevel) => {
154
209
  const prunedContentTypes = (await contentTypes.async("text")).replaceAll(CONTENT_TYPE_ELEMENT, (element) => {
155
210
  const partName = PART_NAME_ATTRIBUTE.exec(element)?.groups?.["value"];
156
211
  if (partName === void 0 || isPresent(present, partName)) return element;
157
- repair.danglingOverrides.push(normalizePartPath(decodePartName(partName)));
212
+ repair.danglingOverrides.push(normalizePartPath(decodePartName(partName) ?? partName));
158
213
  droppedOverride = true;
159
214
  return "";
160
215
  });
@@ -195,7 +250,7 @@ const checkPackageIntegrity = async (zip) => {
195
250
  const id = RELATIONSHIP_ID_ATTRIBUTE.exec(element)?.groups?.["value"];
196
251
  if (id !== void 0) ids.add(id);
197
252
  const target = relationshipTarget(element, path);
198
- if (target !== null && !isPresent(present, target)) report.danglingRelationshipTargets.push(`${path}|${target}`);
253
+ if (target !== null && !present.has(target)) report.danglingRelationshipTargets.push(`${path}|${target || TARGET_ATTRIBUTE.exec(element)?.groups?.["value"] || ""}`);
199
254
  }
200
255
  if (owningPart !== void 0) idsByOwningPart.set(owningPart, ids);
201
256
  }
@@ -211,4 +266,4 @@ const checkPackageIntegrity = async (zip) => {
211
266
  return report;
212
267
  };
213
268
  //#endregion
214
- export { checkPackageIntegrity, isUnsafePackagePath, reconcilePackageReferences, removeUnsafeEntries };
269
+ export { checkPackageIntegrity, isUnsafePackagePath, reconcilePackageReferences, removeUnsafeEntries, resolvePackageRelationshipTarget };
@@ -0,0 +1,9 @@
1
+ import { document_d_exports } from "../types/document.js";
2
+ import { XmlElement } from "./xmlParser.js";
3
+ //#region src/docx/paragraphMarkPropertyPresence.d.ts
4
+ declare const EMPTY_MARK_PROPERTIES_ATTRIBUTE = "emptyMarkProperties";
5
+ /** A paragraph-owned rPr carrier cannot distinguish absent and explicitly empty formatting. */
6
+ declare const serializeEmptyMarkProperties: (paragraph: document_d_exports.Paragraph) => string | undefined;
7
+ declare const restoreEmptyMarkProperties: (paragraph: document_d_exports.Paragraph, element: XmlElement) => void;
8
+ //#endregion
9
+ export { EMPTY_MARK_PROPERTIES_ATTRIBUTE, restoreEmptyMarkProperties, serializeEmptyMarkProperties };
@@ -0,0 +1,21 @@
1
+ import { OOXML_NAMESPACES } from "./serializer/partNamespaces.js";
2
+ import { getAttributeByNamespaceUri } from "./xmlParser.js";
3
+ import { EMPTY_PROPERTY_SETS } from "@stll/docx-core/ops";
4
+ //#region src/docx/paragraphMarkPropertyPresence.ts
5
+ const EMPTY_MARK_PROPERTIES_ATTRIBUTE = "emptyMarkProperties";
6
+ const REVIEW_HISTORY_NAMESPACES = /* @__PURE__ */ new Set([OOXML_NAMESPACES.folio.uri]);
7
+ /** A paragraph-owned rPr carrier cannot distinguish absent and explicitly empty formatting. */
8
+ const serializeEmptyMarkProperties = (paragraph) => {
9
+ const properties = paragraph.formatting?.runProperties;
10
+ if (!(paragraph.pPrMark !== void 0 || paragraph.formatting?.runInWithNext !== void 0) || properties === void 0 || Object.keys(properties).length !== 0) return void 0;
11
+ return `folio:${EMPTY_MARK_PROPERTIES_ATTRIBUTE}="${EMPTY_PROPERTY_SETS.KEEP}"`;
12
+ };
13
+ const restoreEmptyMarkProperties = (paragraph, element) => {
14
+ if (paragraph.pPrMark === void 0 && paragraph.formatting?.runInWithNext === void 0 || getAttributeByNamespaceUri(element, REVIEW_HISTORY_NAMESPACES, "emptyMarkProperties") !== EMPTY_PROPERTY_SETS.KEEP || paragraph.formatting?.runProperties !== void 0) return;
15
+ paragraph.formatting = {
16
+ ...paragraph.formatting,
17
+ runProperties: {}
18
+ };
19
+ };
20
+ //#endregion
21
+ export { EMPTY_MARK_PROPERTIES_ATTRIBUTE, restoreEmptyMarkProperties, serializeEmptyMarkProperties };