@stll/folio-core 0.11.0 → 0.13.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 (263) hide show
  1. package/dist/ai-edits/apply.d.ts +2 -1
  2. package/dist/ai-edits/apply.js +693 -63
  3. package/dist/ai-edits/block-identity.d.ts +4 -0
  4. package/dist/ai-edits/block-identity.js +9 -0
  5. package/dist/ai-edits/blockRange.d.ts +28 -1
  6. package/dist/ai-edits/blockRange.js +68 -2
  7. package/dist/ai-edits/clean-text.js +2 -1
  8. package/dist/ai-edits/headless.d.ts +4 -4
  9. package/dist/ai-edits/headless.js +9 -9
  10. package/dist/ai-edits/index.d.ts +2 -2
  11. package/dist/ai-edits/index.js +2 -2
  12. package/dist/ai-edits/read.d.ts +7 -7
  13. package/dist/ai-edits/read.js +110 -3
  14. package/dist/ai-edits/snapshot.js +21 -3
  15. package/dist/ai-edits/table-cell-mutations.d.ts +48 -0
  16. package/dist/ai-edits/table-cell-mutations.js +238 -0
  17. package/dist/ai-edits/table-mutation-plan.d.ts +38 -0
  18. package/dist/ai-edits/table-mutation-plan.js +90 -0
  19. package/dist/ai-edits/table-row-column-mutations.d.ts +108 -0
  20. package/dist/ai-edits/table-row-column-mutations.js +300 -0
  21. package/dist/ai-edits/table-targets.d.ts +32 -0
  22. package/dist/ai-edits/table-targets.js +70 -0
  23. package/dist/ai-edits/types.d.ts +62 -1
  24. package/dist/ai-edits/word-diff.js +21 -0
  25. package/dist/compat/eigenpal.d.ts +3 -3
  26. package/dist/compat/eigenpal.js +3 -3
  27. package/dist/content-controls/mutateContentControls.js +1 -1
  28. package/dist/controller/activeEditorStory.d.ts +36 -0
  29. package/dist/controller/activeEditorStory.js +30 -0
  30. package/dist/controller/contentControlWidgetController.d.ts +55 -0
  31. package/dist/controller/contentControlWidgetController.js +141 -0
  32. package/dist/controller/fontReadiness.js +2 -0
  33. package/dist/controller/headerFooterEditorManager.js +2 -2
  34. package/dist/controller/hiddenEditorApi.js +2 -2
  35. package/dist/controller/hiddenEditorManager.d.ts +12 -1
  36. package/dist/controller/hiddenEditorManager.js +44 -12
  37. package/dist/controller/layoutPipeline.d.ts +2 -0
  38. package/dist/controller/layoutPipeline.js +17 -2
  39. package/dist/controller/noteEditorManager.d.ts +36 -0
  40. package/dist/controller/noteEditorManager.js +210 -0
  41. package/dist/document-operations.d.ts +43 -11
  42. package/dist/document-operations.js +186 -18
  43. package/dist/docx/blockContentParser.js +21 -7
  44. package/dist/docx/commentParser.js +6 -1
  45. package/dist/docx/commentRangeIntegrity.d.ts +6 -0
  46. package/dist/docx/commentRangeIntegrity.js +186 -0
  47. package/dist/docx/conformance.js +62 -1
  48. package/dist/docx/documentGrid.d.ts +8 -0
  49. package/dist/docx/documentGrid.js +8 -0
  50. package/dist/docx/drawingUtils.js +1 -1
  51. package/dist/docx/encryption/agileDecryption.js +12 -2
  52. package/dist/docx/encryption/compoundFile.js +6 -1
  53. package/dist/docx/encryption/encryptionInfo.d.ts +9 -1
  54. package/dist/docx/encryption/encryptionInfo.js +18 -2
  55. package/dist/docx/encryption/openEncryptedDocx.js +1 -1
  56. package/dist/docx/ensureParaIds.js +8 -7
  57. package/dist/docx/fieldParser.js +1 -1
  58. package/dist/docx/groupDrawingParser.js +10 -5
  59. package/dist/docx/hyperlinkParser.js +1 -1
  60. package/dist/docx/imageParser.js +10 -6
  61. package/dist/docx/metadataPrivacy.js +17 -3
  62. package/dist/docx/notePropertiesParser.js +1 -1
  63. package/dist/docx/numberingParser.js +1 -1
  64. package/dist/docx/paragraphParser.js +70 -61
  65. package/dist/docx/paragraphTextBoxEnrichment.d.ts +2 -1
  66. package/dist/docx/paragraphTextBoxEnrichment.js +67 -13
  67. package/dist/docx/paragraphTraversal.js +1 -1
  68. package/dist/docx/parser.js +3 -3
  69. package/dist/docx/rezip.js +20 -9
  70. package/dist/docx/runParser.js +17 -6
  71. package/dist/docx/sdtProperties.js +1 -1
  72. package/dist/docx/sectionParser.js +18 -5
  73. package/dist/docx/selectiveSave.js +5 -1
  74. package/dist/docx/selectiveXmlPatch.d.ts +22 -1
  75. package/dist/docx/selectiveXmlPatch.js +61 -1
  76. package/dist/docx/serializer/blockSdtSerializer.js +3 -2
  77. package/dist/docx/serializer/commentSerializer.js +5 -6
  78. package/dist/docx/serializer/documentSerializer.js +2 -2
  79. package/dist/docx/serializer/headerFooterSerializer.js +2 -2
  80. package/dist/docx/serializer/noteSerializer.js +2 -2
  81. package/dist/docx/serializer/paragraphSerializer.js +23 -15
  82. package/dist/docx/serializer/runSerializer.js +25 -21
  83. package/dist/docx/serializer/sectionPropertiesSerializer.js +2 -1
  84. package/dist/docx/serializer/stylesSerializer.js +1 -1
  85. package/dist/docx/serializer/tableSerializer.d.ts +5 -4
  86. package/dist/docx/serializer/tableSerializer.js +26 -20
  87. package/dist/docx/serializer/xmlUtils.d.ts +13 -1
  88. package/dist/docx/serializer/xmlUtils.js +27 -1
  89. package/dist/docx/server/applyDocxXmlPatchProposal.d.ts +87 -0
  90. package/dist/docx/server/applyDocxXmlPatchProposal.js +204 -0
  91. package/dist/docx/server/boundedArchive.d.ts +14 -3
  92. package/dist/docx/server/boundedArchive.js +56 -11
  93. package/dist/docx/server/evaluateDocxXmlPatchProposal.d.ts +85 -0
  94. package/dist/docx/server/evaluateDocxXmlPatchProposal.js +361 -0
  95. package/dist/docx/server/extractDocxText.js +55 -8
  96. package/dist/docx/server/inspectDocxPackage.d.ts +70 -0
  97. package/dist/docx/server/inspectDocxPackage.js +217 -0
  98. package/dist/docx/server/validateDocxConformance.d.ts +41 -0
  99. package/dist/docx/server/validateDocxConformance.js +336 -0
  100. package/dist/docx/settingsParser.js +26 -3
  101. package/dist/docx/shapeParser.js +1 -1
  102. package/dist/docx/styleParser.js +4 -2
  103. package/dist/docx/tableParser.d.ts +8 -1
  104. package/dist/docx/tableParser.js +31 -10
  105. package/dist/docx/textBoxParser.d.ts +3 -3
  106. package/dist/docx/textBoxParser.js +16 -12
  107. package/dist/docx/unzip.js +1 -0
  108. package/dist/docx/vmlImageParser.js +11 -3
  109. package/dist/docx/xmlParser.js +11 -1
  110. package/dist/docx/xmlSafety.d.ts +5 -0
  111. package/dist/docx/xmlSafety.js +9 -0
  112. package/dist/fields/resolveFieldValues.js +1 -3
  113. package/dist/fonts/embeddedFonts.d.ts +33 -5
  114. package/dist/fonts/embeddedFonts.js +37 -8
  115. package/dist/i18n/messages/catalogs.gen.d.ts +17 -0
  116. package/dist/i18n/messages/catalogs.gen.js +17 -0
  117. package/dist/i18n/messages/messages.gen.d.ts +1 -0
  118. package/dist/index.d.ts +3 -3
  119. package/dist/index.js +3 -3
  120. package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
  121. package/dist/layout-bridge/convert/footnoteLayout.js +47 -40
  122. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
  123. package/dist/layout-bridge/convert/headerFooterLayout.js +3 -0
  124. package/dist/layout-bridge/convert/templatePreviewFlow.js +3 -3
  125. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +4 -2
  126. package/dist/layout-bridge/convert/toFlowBlocks.js +151 -20
  127. package/dist/layout-bridge/dom/noteStoryDom.d.ts +6 -0
  128. package/dist/layout-bridge/dom/noteStoryDom.js +17 -0
  129. package/dist/layout-bridge/engine/clickToPosition.js +2 -2
  130. package/dist/layout-engine/index.d.ts +2 -2
  131. package/dist/layout-engine/index.js +58 -30
  132. package/dist/layout-engine/justificationCompatibility.d.ts +6 -0
  133. package/dist/layout-engine/justificationCompatibility.js +8 -0
  134. package/dist/layout-engine/keep-together.js +11 -1
  135. package/dist/layout-engine/measure/cache.js +23 -5
  136. package/dist/layout-engine/measure/effectiveLineBreakPolicy.js +8 -2
  137. package/dist/layout-engine/measure/lineBreakProvider.d.ts +2 -2
  138. package/dist/layout-engine/measure/lineBreakProvider.js +56 -37
  139. package/dist/layout-engine/measure/measureBlocks.js +15 -4
  140. package/dist/layout-engine/measure/measureContainer.js +1 -1
  141. package/dist/layout-engine/measure/measureHelpers.d.ts +11 -2
  142. package/dist/layout-engine/measure/measureHelpers.js +15 -4
  143. package/dist/layout-engine/measure/measureParagraph.js +85 -25
  144. package/dist/layout-engine/measure/measureProvider.js +4 -3
  145. package/dist/layout-engine/measure/tableCellFlow.js +5 -2
  146. package/dist/layout-engine/measure/textBoxParagraphLayout.d.ts +9 -7
  147. package/dist/layout-engine/measure/textBoxParagraphLayout.js +22 -6
  148. package/dist/layout-engine/measure/textMeasurementPolicy.d.ts +3 -1
  149. package/dist/layout-engine/measure/textMeasurementPolicy.js +7 -1
  150. package/dist/layout-engine/paginator.js +5 -1
  151. package/dist/layout-engine/paragraphSpacing.d.ts +28 -4
  152. package/dist/layout-engine/paragraphSpacing.js +107 -13
  153. package/dist/layout-engine/renderedBreakReconciliation.js +1 -1
  154. package/dist/layout-engine/types.d.ts +48 -15
  155. package/dist/layout-painter/registry/modules/textBox.js +5 -1
  156. package/dist/layout-painter/renderImage.d.ts +12 -1
  157. package/dist/layout-painter/renderImage.js +21 -4
  158. package/dist/layout-painter/renderPage.d.ts +5 -2
  159. package/dist/layout-painter/renderPage.js +59 -14
  160. package/dist/layout-painter/renderParagraph.js +55 -15
  161. package/dist/layout-painter/renderTable.d.ts +5 -1
  162. package/dist/layout-painter/renderTable.js +7 -3
  163. package/dist/layout-painter/renderTextBox.d.ts +2 -1
  164. package/dist/layout-painter/renderTextBox.js +25 -14
  165. package/dist/layout-painter/renderWatermark.d.ts +1 -1
  166. package/dist/layout-painter/renderWatermark.js +2 -1
  167. package/dist/managers/DocumentLoaderManager.js +1 -1
  168. package/dist/markdown/fromMarkdown.js +1 -1
  169. package/dist/model.js +1 -1
  170. package/dist/prosemirror/attrs/index.d.ts +4 -2
  171. package/dist/prosemirror/attrs/index.js +175 -18
  172. package/dist/prosemirror/commands/comments.d.ts +79 -4
  173. package/dist/prosemirror/commands/comments.js +622 -13
  174. package/dist/prosemirror/commands/contentControls.js +1 -1
  175. package/dist/prosemirror/commands/hyperlink.js +15 -1
  176. package/dist/prosemirror/commands/image.js +7 -1
  177. package/dist/prosemirror/commands/index.d.ts +2 -2
  178. package/dist/prosemirror/commands/index.js +2 -2
  179. package/dist/prosemirror/commands/pageBreak.js +1 -1
  180. package/dist/prosemirror/commands/propertyChangeScope.d.ts +2 -2
  181. package/dist/prosemirror/commands/propertyChangeScope.js +3 -2
  182. package/dist/prosemirror/commands/tableCellMergeResolution.d.ts +9 -0
  183. package/dist/prosemirror/commands/tableCellMergeResolution.js +181 -0
  184. package/dist/prosemirror/commentIdAllocator.js +13 -3
  185. package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -1
  186. package/dist/prosemirror/conversion/fromProseDoc.js +404 -62
  187. package/dist/prosemirror/conversion/index.js +1 -1
  188. package/dist/prosemirror/conversion/sdtAttrs.d.ts +9 -0
  189. package/dist/prosemirror/conversion/sdtAttrs.js +49 -0
  190. package/dist/prosemirror/conversion/toProseDoc.d.ts +2 -1
  191. package/dist/prosemirror/conversion/toProseDoc.js +364 -103
  192. package/dist/prosemirror/extensions/ExtensionManager.js +1 -1
  193. package/dist/prosemirror/extensions/StarterKit.js +6 -1
  194. package/dist/prosemirror/extensions/core/ParagraphExtension.js +6 -2
  195. package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +1 -0
  196. package/dist/prosemirror/extensions/features/ImagePasteExtension.js +10 -2
  197. package/dist/prosemirror/extensions/features/ListExtension.js +1 -1
  198. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +10 -1
  199. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +93 -2
  200. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +2 -1
  201. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +6 -2
  202. package/dist/prosemirror/extensions/features/pasteCleanup.js +15 -2
  203. package/dist/prosemirror/extensions/marks/CharacterSpacingExtension.js +1 -1
  204. package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +30 -4
  205. package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.d.ts +9 -1
  206. package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +70 -11
  207. package/dist/prosemirror/extensions/nodes/FieldExtension.js +1 -1
  208. package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.d.ts +7 -0
  209. package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.js +22 -0
  210. package/dist/prosemirror/extensions/nodes/TableExtension.d.ts +1 -1
  211. package/dist/prosemirror/extensions/nodes/TableExtension.js +14 -6
  212. package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.d.ts +13 -0
  213. package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.js +41 -0
  214. package/dist/prosemirror/extensions/nodes/TextBoxExtension.d.ts +5 -2
  215. package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +4 -1
  216. package/dist/prosemirror/index.d.ts +1 -1
  217. package/dist/prosemirror/index.js +1 -1
  218. package/dist/prosemirror/plugins/contentControlWidgets.d.ts +36 -10
  219. package/dist/prosemirror/plugins/contentControlWidgets.js +128 -94
  220. package/dist/prosemirror/plugins/revisionIds.d.ts +23 -0
  221. package/dist/prosemirror/plugins/revisionIds.js +57 -0
  222. package/dist/prosemirror/plugins/selectionTracker.js +1 -0
  223. package/dist/prosemirror/plugins/suggestionMode.js +5 -4
  224. package/dist/prosemirror/runFormattingMarkNames.d.ts +14 -0
  225. package/dist/prosemirror/runFormattingMarkNames.js +40 -0
  226. package/dist/prosemirror/schema/index.d.ts +2 -2
  227. package/dist/prosemirror/schema/marks.d.ts +30 -3
  228. package/dist/prosemirror/schema/marks.js +15 -0
  229. package/dist/prosemirror/schema/nodes.d.ts +111 -6
  230. package/dist/prosemirror/selectionState.js +1 -0
  231. package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -0
  232. package/dist/prosemirror/tableCellMergeRevision.d.ts +9 -0
  233. package/dist/prosemirror/tableCellMergeRevision.js +22 -0
  234. package/dist/prosemirror/textBoxAnchorAttrs.d.ts +9 -0
  235. package/dist/prosemirror/textBoxAnchorAttrs.js +33 -0
  236. package/dist/prosemirror/utils/extractTrackedChanges.d.ts +1 -1
  237. package/dist/prosemirror/utils/extractTrackedChanges.js +62 -14
  238. package/dist/prosemirror/validation.js +9 -1
  239. package/dist/render-dom/RemoteSelectionOverlay.js +2 -2
  240. package/dist/server.d.ts +7 -3
  241. package/dist/server.js +7 -3
  242. package/dist/utils/clipboard.d.ts +10 -1
  243. package/dist/utils/clipboard.js +33 -6
  244. package/dist/utils/colorResolver.d.ts +8 -1
  245. package/dist/utils/colorResolver.js +35 -5
  246. package/dist/utils/fontFamilyMerge.js +9 -11
  247. package/dist/utils/fontLoader.js +3 -2
  248. package/dist/utils/fontResolver.d.ts +2 -1
  249. package/dist/utils/fontResolver.js +31 -7
  250. package/dist/utils/fontWeights.d.ts +1 -1
  251. package/dist/utils/fontWeights.js +1 -1
  252. package/dist/utils/hexId.d.ts +11 -1
  253. package/dist/utils/hexId.js +11 -1
  254. package/dist/utils/paragraphFormattingMerge.js +1 -0
  255. package/dist/utils/sanitizeImageSrc.d.ts +21 -0
  256. package/dist/utils/sanitizeImageSrc.js +30 -0
  257. package/dist/utils/stripXmlDeclarations.d.ts +11 -0
  258. package/dist/utils/stripXmlDeclarations.js +35 -0
  259. package/dist/version-comparison.d.ts +22 -2
  260. package/dist/version-comparison.js +41 -12
  261. package/dist/watermark/index.d.ts +11 -1
  262. package/dist/watermark/index.js +22 -1
  263. package/package.json +3 -2
@@ -0,0 +1,186 @@
1
+ //#region src/docx/commentRangeIntegrity.ts
2
+ const withoutOrphanCommentRanges = (doc) => {
3
+ const validCommentIds = new Set((doc.package.document.comments ?? []).map((comment) => comment.id));
4
+ const document = withoutOrphanDocumentBodyMarkers(doc.package.document, validCommentIds);
5
+ const headers = withoutOrphanHeaderFooterMapMarkers(doc.package.headers, validCommentIds);
6
+ const footers = withoutOrphanHeaderFooterMapMarkers(doc.package.footers, validCommentIds);
7
+ const footnotes = withoutOrphanNoteMarkers(doc.package.footnotes, validCommentIds);
8
+ const endnotes = withoutOrphanNoteMarkers(doc.package.endnotes, validCommentIds);
9
+ if (!document && !headers && !footers && !footnotes && !endnotes) return doc;
10
+ return {
11
+ ...doc,
12
+ package: {
13
+ ...doc.package,
14
+ ...document ? { document } : {},
15
+ ...headers ? { headers } : {},
16
+ ...footers ? { footers } : {},
17
+ ...footnotes ? { footnotes } : {},
18
+ ...endnotes ? { endnotes } : {}
19
+ }
20
+ };
21
+ };
22
+ const withoutOrphanDocumentBodyMarkers = (document, validCommentIds) => {
23
+ const content = withoutOrphanBlockMarkers(document.content, validCommentIds);
24
+ const comments = withoutOrphanCommentBodyMarkers(document.comments, validCommentIds);
25
+ if (!content && !comments) return null;
26
+ return {
27
+ ...document,
28
+ ...content ? { content } : {},
29
+ ...comments ? { comments } : {}
30
+ };
31
+ };
32
+ const withoutOrphanCommentBodyMarkers = (comments, validCommentIds) => {
33
+ if (!comments) return null;
34
+ let changed = false;
35
+ const next = [];
36
+ for (const comment of comments) {
37
+ const content = withoutOrphanParagraphListMarkers(comment.content, validCommentIds);
38
+ if (!content) {
39
+ next.push(comment);
40
+ continue;
41
+ }
42
+ changed = true;
43
+ next.push({
44
+ ...comment,
45
+ content
46
+ });
47
+ }
48
+ return changed ? next : null;
49
+ };
50
+ const withoutOrphanParagraphListMarkers = (paragraphs, validCommentIds) => {
51
+ let changed = false;
52
+ const next = [];
53
+ for (const paragraph of paragraphs) {
54
+ const nextParagraph = withoutOrphanParagraphMarkers(paragraph, validCommentIds);
55
+ if (nextParagraph !== paragraph) changed = true;
56
+ next.push(nextParagraph);
57
+ }
58
+ return changed ? next : null;
59
+ };
60
+ const withoutOrphanHeaderFooterMapMarkers = (map, validCommentIds) => {
61
+ if (!map) return null;
62
+ let changed = false;
63
+ const next = /* @__PURE__ */ new Map();
64
+ for (const [rId, headerFooter] of map) {
65
+ const content = withoutOrphanBlockMarkers(headerFooter.content, validCommentIds);
66
+ if (!content) {
67
+ next.set(rId, headerFooter);
68
+ continue;
69
+ }
70
+ changed = true;
71
+ next.set(rId, {
72
+ ...headerFooter,
73
+ content
74
+ });
75
+ }
76
+ return changed ? next : null;
77
+ };
78
+ const withoutOrphanNoteMarkers = (notes, validCommentIds) => {
79
+ if (!notes) return null;
80
+ let changed = false;
81
+ const next = [];
82
+ for (const note of notes) {
83
+ const content = withoutOrphanBlockMarkers(note.content, validCommentIds);
84
+ if (!content) {
85
+ next.push(note);
86
+ continue;
87
+ }
88
+ changed = true;
89
+ next.push({
90
+ ...note,
91
+ content
92
+ });
93
+ }
94
+ return changed ? next : null;
95
+ };
96
+ const withoutOrphanBlockMarkers = (blocks, validCommentIds) => {
97
+ let changed = false;
98
+ const next = [];
99
+ for (const block of blocks) {
100
+ const nextBlock = withoutOrphanBlockMarker(block, validCommentIds);
101
+ if (nextBlock !== block) changed = true;
102
+ next.push(nextBlock);
103
+ }
104
+ return changed ? next : null;
105
+ };
106
+ const withoutOrphanBlockMarker = (block, validCommentIds) => {
107
+ if (block.type === "paragraph") return withoutOrphanParagraphMarkers(block, validCommentIds);
108
+ if (block.type === "table") return withoutOrphanTableMarkers(block, validCommentIds);
109
+ if (!("content" in block) || !block.content) return block;
110
+ const content = withoutOrphanBlockMarkers(block.content, validCommentIds);
111
+ if (!content) return block;
112
+ return {
113
+ ...block,
114
+ content
115
+ };
116
+ };
117
+ const withoutOrphanTableMarkers = (table, validCommentIds) => {
118
+ let changed = false;
119
+ const rows = [];
120
+ for (const row of table.rows) {
121
+ const nextRow = withoutOrphanTableRowMarkers(row, validCommentIds);
122
+ if (nextRow !== row) changed = true;
123
+ rows.push(nextRow);
124
+ }
125
+ if (!changed) return table;
126
+ return {
127
+ ...table,
128
+ rows
129
+ };
130
+ };
131
+ const withoutOrphanTableRowMarkers = (row, validCommentIds) => {
132
+ let changed = false;
133
+ const cells = [];
134
+ for (const cell of row.cells) {
135
+ const nextCell = withoutOrphanTableCellMarkers(cell, validCommentIds);
136
+ if (nextCell !== cell) changed = true;
137
+ cells.push(nextCell);
138
+ }
139
+ if (!changed) return row;
140
+ return {
141
+ ...row,
142
+ cells
143
+ };
144
+ };
145
+ const withoutOrphanTableCellMarkers = (cell, validCommentIds) => {
146
+ const content = withoutOrphanTableCellBlockMarkers(cell.content, validCommentIds);
147
+ if (!content) return cell;
148
+ return {
149
+ ...cell,
150
+ content
151
+ };
152
+ };
153
+ const withoutOrphanTableCellBlockMarkers = (blocks, validCommentIds) => {
154
+ let changed = false;
155
+ const next = [];
156
+ for (const block of blocks) {
157
+ const nextBlock = withoutOrphanTableCellBlockMarker(block, validCommentIds);
158
+ if (nextBlock !== block) changed = true;
159
+ next.push(nextBlock);
160
+ }
161
+ return changed ? next : null;
162
+ };
163
+ const withoutOrphanTableCellBlockMarker = (block, validCommentIds) => {
164
+ if (block.type === "paragraph") return withoutOrphanParagraphMarkers(block, validCommentIds);
165
+ if (block.type === "table") return withoutOrphanTableMarkers(block, validCommentIds);
166
+ return block;
167
+ };
168
+ const withoutOrphanParagraphMarkers = (paragraph, validCommentIds) => {
169
+ let changed = false;
170
+ const content = [];
171
+ for (const item of paragraph.content) {
172
+ if (isCommentMarker(item) && !validCommentIds.has(item.id)) {
173
+ changed = true;
174
+ continue;
175
+ }
176
+ content.push(item);
177
+ }
178
+ if (!changed) return paragraph;
179
+ return {
180
+ ...paragraph,
181
+ content
182
+ };
183
+ };
184
+ const isCommentMarker = (content) => content.type === "commentRangeStart" || content.type === "commentRangeEnd" || content.type === "commentReference";
185
+ //#endregion
186
+ export { withoutOrphanCommentRanges };
@@ -3,9 +3,70 @@ import { DOCX_CONFORMANCE_CLASSES } from "@stll/docx-core/model";
3
3
  //#region src/docx/conformance.ts
4
4
  const STRICT_MAIN_NAMESPACE = "http://purl.oclc.org/ooxml/wordprocessingml/main";
5
5
  const TRANSITIONAL_MAIN_NAMESPACE = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
6
+ const ROOT_START_TAG_SCAN_LIMIT = 64 * 1024;
7
+ const XML_WHITESPACE = /\s/u;
8
+ /**
9
+ * Find the root start tag within a bounded prefix of `document.xml`,
10
+ * without backtracking.
11
+ *
12
+ * Equivalent in captured-tag semantics to the previous
13
+ * `/^(?:\uFEFF|\s|<\?[\s\S]*?\?>|<!--[\s\S]*?-->)*(?<tag><[^\s/>]+(?:[^>"']|"[^"]*"|'[^']*')*>)/u`
14
+ * pattern, but as a linear hand-rolled scanner: the original alternation of
15
+ * greedy/lazy `[\s\S]*?` spans over an attacker-controlled prefix was
16
+ * susceptible to catastrophic backtracking on crafted input. This walks
17
+ * `scanTarget` once, tracking in-quote state, and returns `undefined` in
18
+ * every case the regex would have failed to match (unterminated PI/comment,
19
+ * no tag found before the scan limit, malformed tag open).
20
+ */
21
+ function scanRootStartTag(scanTarget) {
22
+ const length = scanTarget.length;
23
+ let index = 0;
24
+ for (;;) {
25
+ if (index >= length) return;
26
+ const character = scanTarget[index];
27
+ if (character === "" || XML_WHITESPACE.test(character ?? "")) {
28
+ index += 1;
29
+ continue;
30
+ }
31
+ if (scanTarget.startsWith("<?", index)) {
32
+ const closeIndex = scanTarget.indexOf("?>", index + 2);
33
+ if (closeIndex === -1) return;
34
+ index = closeIndex + 2;
35
+ continue;
36
+ }
37
+ if (scanTarget.startsWith("<!--", index)) {
38
+ const closeIndex = scanTarget.indexOf("-->", index + 4);
39
+ if (closeIndex === -1) return;
40
+ index = closeIndex + 3;
41
+ continue;
42
+ }
43
+ break;
44
+ }
45
+ if (scanTarget[index] !== "<") return;
46
+ const nameStart = index + 1;
47
+ const firstNameChar = scanTarget[nameStart];
48
+ if (firstNameChar === void 0 || firstNameChar === "/" || firstNameChar === ">" || XML_WHITESPACE.test(firstNameChar)) return;
49
+ let quote;
50
+ for (let cursor = nameStart; cursor < length; cursor++) {
51
+ const character = scanTarget[cursor];
52
+ if (quote) {
53
+ if (character === quote) quote = void 0;
54
+ continue;
55
+ }
56
+ if (character === "\"" || character === "'") {
57
+ quote = character;
58
+ continue;
59
+ }
60
+ if (character === ">") return scanTarget.slice(index, cursor + 1);
61
+ }
62
+ }
6
63
  const detectDocxConformanceClass = (documentXml) => {
7
64
  if (documentXml === null) return DOCX_CONFORMANCE_CLASSES.UNKNOWN;
8
- const root = parseXmlDocument(documentXml);
65
+ const rootStartTag = scanRootStartTag(documentXml.length <= ROOT_START_TAG_SCAN_LIMIT ? documentXml : documentXml.slice(0, ROOT_START_TAG_SCAN_LIMIT));
66
+ const root = (rootStartTag === void 0 ? null : parseXmlDocument(rootStartTag.endsWith("/>") ? rootStartTag : `${rootStartTag.slice(0, -1)}/>`)) ?? parseXmlDocument(documentXml);
67
+ return detectDocxConformanceClassFromRoot(root);
68
+ };
69
+ const detectDocxConformanceClassFromRoot = (root) => {
9
70
  if (root === null || getLocalName(root.name ?? "") !== "document") return DOCX_CONFORMANCE_CLASSES.UNKNOWN;
10
71
  const prefix = getNamespacePrefix(root.name ?? "");
11
72
  const namespaceAttribute = prefix === null ? "xmlns" : `xmlns:${prefix}`;
@@ -0,0 +1,8 @@
1
+ //#region src/docx/documentGrid.d.ts
2
+ type DocumentGrid = {
3
+ type?: "default" | "lines" | "linesAndChars" | "snapToChars";
4
+ linePitch?: number;
5
+ };
6
+ declare function resolveDocumentGridLinePitch(grid: DocumentGrid | undefined): number | undefined;
7
+ //#endregion
8
+ export { resolveDocumentGridLinePitch };
@@ -0,0 +1,8 @@
1
+ //#region src/docx/documentGrid.ts
2
+ function resolveDocumentGridLinePitch(grid) {
3
+ if (grid?.type === void 0 || grid.type === "default") return;
4
+ if (grid.linePitch === void 0 || grid.linePitch <= 0) return;
5
+ return grid.linePitch;
6
+ }
7
+ //#endregion
8
+ export { resolveDocumentGridLinePitch };
@@ -1,5 +1,5 @@
1
- import { findByFullName, getAttribute, getChildElements, getTextContent, parseNumericAttribute } from "./xmlParser.js";
2
1
  import { ImageHorizontalAlignmentSchema, ImageHorizontalRelativeToSchema, ImageVerticalAlignmentSchema, ImageVerticalRelativeToSchema, ImageWrapTextSchema, ShapeOutlineStyleSchema, narrowEnum } from "./parserEnums.js";
2
+ import { findByFullName, getAttribute, getChildElements, getTextContent, parseNumericAttribute } from "./xmlParser.js";
3
3
  //#region src/docx/drawingUtils.ts
4
4
  /**
5
5
  * Map OOXML scheme names to standard theme color slots.
@@ -1,5 +1,6 @@
1
1
  import { DOCX_ENCRYPTION_ERROR_CODES, DocxEncryptionError } from "./errors.js";
2
2
  import { bytesEqual, joinBytes, padToBlock, passwordToUtf16Le, toArrayBuffer, writeUint32Le } from "./cryptoBytes.js";
3
+ import { MAX_SPIN_COUNT } from "./encryptionInfo.js";
3
4
  //#region src/docx/encryption/agileDecryption.ts
4
5
  /**
5
6
  * Agile Encryption decryption (Office 2010+) using Web Crypto.
@@ -115,11 +116,20 @@ const decryptAesCbc = async (rawKey, iv, ciphertext) => {
115
116
  }, key, toArrayBuffer(paddedCiphertext));
116
117
  return new Uint8Array(decrypted).subarray(0, ciphertext.length);
117
118
  };
118
- /** [MS-OFFCRYPTO] 2.3.4.9 — iterated hash of password + salt. */
119
+ /**
120
+ * [MS-OFFCRYPTO] 2.3.4.9 — iterated hash of password + salt.
121
+ *
122
+ * `iterations` is expected to already be validated by
123
+ * `encryptionInfo.ts`'s `spinCount` parsing, but this loop drives real
124
+ * WebCrypto work per iteration, so it is clamped again here as well —
125
+ * this function must stay safe to call with an untrusted iteration count
126
+ * regardless of caller.
127
+ */
119
128
  const hashPassword = async (password, salt, iterations, hashName) => {
120
129
  const algorithm = webHashName(hashName);
130
+ const boundedIterations = Math.min(Math.max(iterations, 0), MAX_SPIN_COUNT);
121
131
  let state = await digest(algorithm, joinBytes([salt, passwordToUtf16Le(password)]));
122
- for (let i = 0; i < iterations; i++) state = await digest(algorithm, joinBytes([writeUint32Le(i), state]));
132
+ for (let i = 0; i < boundedIterations; i++) state = await digest(algorithm, joinBytes([writeUint32Le(i), state]));
123
133
  return state;
124
134
  };
125
135
  /** [MS-OFFCRYPTO] 2.3.4.9 — finalize a derived key with a block key suffix. */
@@ -83,9 +83,14 @@ const loadSector = (file, header, sectorId) => {
83
83
  };
84
84
  const loadFatSectorIds = (file, header) => {
85
85
  const ids = [...header.headerDifat];
86
+ const maxDifatSectors = Math.ceil(file.length / header.sectorBytes);
87
+ const stepLimit = Math.min(header.difatSectorCount, maxDifatSectors);
88
+ const seen = /* @__PURE__ */ new Set();
86
89
  let chain = header.difatStart;
87
- for (let step = 0; step < header.difatSectorCount; step++) {
90
+ for (let step = 0; step < stepLimit; step++) {
88
91
  if (chain === SECTOR_END || chain === SECTOR_FREE) break;
92
+ if (seen.has(chain)) throw new Error(`DIFAT chain loop at sector ${chain}`);
93
+ seen.add(chain);
89
94
  const sector = loadSector(file, header, chain);
90
95
  const view = viewOf(sector);
91
96
  const slotsPerSector = header.sectorBytes / 4 - 1;
@@ -27,6 +27,14 @@ type AgileEncryptionDescriptor = {
27
27
  scheme: "agile";
28
28
  material: AgileKeyMaterial;
29
29
  };
30
+ /**
31
+ * Cap on `encryptedKey/@spinCount`. MS-OFFCRYPTO's documented default is
32
+ * 100,000; a hostile/corrupt value here would drive `hashPassword`'s
33
+ * per-iteration WebCrypto digest loop (agileDecryption.ts) an
34
+ * attacker-chosen number of times, so reject anything past a generous
35
+ * multiple of that default instead of trusting the file.
36
+ */
37
+ declare const MAX_SPIN_COUNT = 200000;
30
38
  declare const parseAgileEncryptionInfo: (stream: Uint8Array) => AgileEncryptionDescriptor;
31
39
  //#endregion
32
- export { AgileEncryptionDescriptor, AgileKeyMaterial, parseAgileEncryptionInfo };
40
+ export { AgileEncryptionDescriptor, AgileKeyMaterial, MAX_SPIN_COUNT, parseAgileEncryptionInfo };
@@ -68,6 +68,22 @@ const requireInt = (attrs, name, element) => {
68
68
  return parsed;
69
69
  };
70
70
  const requireBase64 = (attrs, name, element) => decodeBase64(requireAttr(attrs, name, element));
71
+ /**
72
+ * Cap on `encryptedKey/@spinCount`. MS-OFFCRYPTO's documented default is
73
+ * 100,000; a hostile/corrupt value here would drive `hashPassword`'s
74
+ * per-iteration WebCrypto digest loop (agileDecryption.ts) an
75
+ * attacker-chosen number of times, so reject anything past a generous
76
+ * multiple of that default instead of trusting the file.
77
+ */
78
+ const MAX_SPIN_COUNT = 2e5;
79
+ const requireSpinCount = (attrs, element) => {
80
+ const spinCount = requireInt(attrs, "spinCount", element);
81
+ if (spinCount < 0 || spinCount > 2e5) throw new DocxEncryptionError({
82
+ code: DOCX_ENCRYPTION_ERROR_CODES.DECRYPTION_FAILED,
83
+ message: `EncryptionInfo <${element}> attribute "spinCount" out of range: ${spinCount}`
84
+ });
85
+ return spinCount;
86
+ };
71
87
  const parseAgileXml = (xmlBytes) => {
72
88
  const xml = new TextDecoder("utf-8").decode(xmlBytes);
73
89
  const keyDataTag = findElement(xml, "keyData");
@@ -88,7 +104,7 @@ const parseAgileXml = (xmlBytes) => {
88
104
  cipherBlockBytes: requireInt(keyData, "blockSize", "keyData"),
89
105
  cipherName: requireAttr(keyData, "cipherAlgorithm", "keyData"),
90
106
  cipherMode: requireAttr(keyData, "cipherChaining", "keyData"),
91
- passwordIterations: requireInt(encryptedKey, "spinCount", "encryptedKey"),
107
+ passwordIterations: requireSpinCount(encryptedKey, "encryptedKey"),
92
108
  passwordSalt: requireBase64(encryptedKey, "saltValue", "encryptedKey"),
93
109
  passwordHash: requireAttr(encryptedKey, "hashAlgorithm", "encryptedKey"),
94
110
  passwordKeyBits: requireInt(encryptedKey, "keyBits", "encryptedKey"),
@@ -125,4 +141,4 @@ const parseAgileEncryptionInfo = (stream) => {
125
141
  });
126
142
  };
127
143
  //#endregion
128
- export { parseAgileEncryptionInfo };
144
+ export { MAX_SPIN_COUNT, parseAgileEncryptionInfo };
@@ -1,9 +1,9 @@
1
1
  import { DOCX_ENCRYPTION_ERROR_CODES, DocxEncryptionError } from "./errors.js";
2
2
  import { toArrayBuffer } from "./cryptoBytes.js";
3
+ import { parseAgileEncryptionInfo } from "./encryptionInfo.js";
3
4
  import { decryptAgileEncryptedPackage } from "./agileDecryption.js";
4
5
  import { readEncryptedPackageStreams } from "./compoundFile.js";
5
6
  import { DOCX_CONTAINER_TYPES, detectDocxContainerType } from "./containerFormat.js";
6
- import { parseAgileEncryptionInfo } from "./encryptionInfo.js";
7
7
  //#region src/docx/encryption/openEncryptedDocx.ts
8
8
  /**
9
9
  * Decrypt password-protected OOXML before ZIP extraction.
@@ -1,5 +1,6 @@
1
- import { isXmlNameBoundary } from "./selectiveXmlPatch.js";
2
1
  import { deterministicHexId } from "../utils/hexId.js";
2
+ import { isXmlNameBoundary } from "./selectiveXmlPatch.js";
3
+ import { loadDocxArchive } from "./server/boundedArchive.js";
3
4
  import { TaggedError } from "better-result";
4
5
  import JSZip from "jszip";
5
6
  //#region src/docx/ensureParaIds.ts
@@ -350,18 +351,17 @@ const hasDigitalSignatureParts = (zip) => Object.values(zip.files).some(({ dir,
350
351
  * the buffer is not a WordprocessingML package or a part is malformed.
351
352
  */
352
353
  const ensureParaIdsInternal = async (docx, options) => {
353
- const zip = await JSZip.loadAsync(docx);
354
- const xmlPartNames = [];
355
- zip.forEach((relativePath, entry) => {
354
+ const archive = await loadDocxArchive(docx);
355
+ const xmlPartNames = archive.entries.filter((relativePath) => {
356
356
  const lower = relativePath.toLowerCase();
357
- if (!entry.dir && lower.startsWith("word/") && lower.endsWith(".xml")) xmlPartNames.push(relativePath);
357
+ return lower.startsWith("word/") && lower.endsWith(".xml");
358
358
  });
359
359
  const documentPartName = xmlPartNames.find((name) => name.toLowerCase() === DOCUMENT_PART);
360
360
  if (documentPartName === void 0) throw createEnsureParaIdsError("word/document.xml not found: not a WordprocessingML package");
361
361
  const partTexts = /* @__PURE__ */ new Map();
362
362
  for (const name of xmlPartNames) {
363
- const entry = zip.file(name);
364
- if (entry) partTexts.set(name, await entry.async("text"));
363
+ const text = await archive.readEntryString(name);
364
+ if (text !== null) partTexts.set(name, text);
365
365
  }
366
366
  const taken = /* @__PURE__ */ new Set();
367
367
  for (const text of partTexts.values()) collectExistingParaIds(text, taken);
@@ -390,6 +390,7 @@ const ensureParaIdsInternal = async (docx, options) => {
390
390
  deduplicated: 0,
391
391
  alreadyComplete: true
392
392
  };
393
+ const zip = await JSZip.loadAsync(docx);
393
394
  if (hasDigitalSignatureParts(zip) && options.allowSignedPackageMutation !== true) throw createEnsureParaIdsError("Refusing to normalize a digitally signed package because rewriting OOXML invalidates its signatures. Warn the user and pass allowSignedPackageMutation only if invalidation is acceptable.");
394
395
  for (const [partPath, content] of updates) zip.file(partPath, content, {
395
396
  compression: "DEFLATE",
@@ -1,5 +1,5 @@
1
- import { findChildren, getAttribute } from "./xmlParser.js";
2
1
  import { FieldTypeSchema, narrowEnum } from "./parserEnums.js";
2
+ import { findChildren, getAttribute } from "./xmlParser.js";
3
3
  import { parseRun } from "./runParser.js";
4
4
  //#region src/docx/fieldParser.ts
5
5
  /**
@@ -150,12 +150,17 @@ const groupViewBox = (group, width, height) => {
150
150
  };
151
151
  };
152
152
  const createSvg = (group, width, height, rels, media) => {
153
- const content = getChildElements(group).slice(0, MAX_GROUP_SHAPES).map((child, index) => {
153
+ const children = getChildElements(group).slice(0, MAX_GROUP_SHAPES);
154
+ let content = "";
155
+ for (const [index, child] of children.entries()) {
154
156
  const localName = getLocalName(child.name ?? "");
155
- if (localName === "pic") return renderPicture(child, index, rels, media);
156
- if (localName !== "wsp") return "";
157
- return findChildByLocalName(child, "txbx") ? renderTextBox(child) : renderGeometry(child);
158
- }).join("");
157
+ let piece;
158
+ if (localName === "pic") piece = renderPicture(child, index, rels, media);
159
+ else if (localName === "wsp") piece = findChildByLocalName(child, "txbx") ? renderTextBox(child) : renderGeometry(child);
160
+ else continue;
161
+ content += piece;
162
+ if (content.length > MAX_SVG_CHARACTERS) return null;
163
+ }
159
164
  if (!content) return null;
160
165
  const viewBox = groupViewBox(group, width, height);
161
166
  return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${viewBox.x} ${viewBox.y} ${viewBox.width} ${viewBox.height}" width="${emuToPixels(width)}" height="${emuToPixels(height)}">${content}</svg>`;
@@ -1,6 +1,6 @@
1
1
  import { getAttribute, getChildElements, mergeXmlnsDeclarations, parseNumericAttribute } from "./xmlParser.js";
2
- import { parseRun } from "./runParser.js";
3
2
  import { sanitizeExternalUrl, sanitizeLinkTarget } from "../utils/urlSecurity.js";
3
+ import { parseRun } from "./runParser.js";
4
4
  //#region src/docx/hyperlinkParser.ts
5
5
  /**
6
6
  * Get the local name of an element (without namespace prefix)
@@ -1,5 +1,7 @@
1
1
  import { findByFullName, findChild, getAttribute, getChildElements, parseNumericAttribute } from "./xmlParser.js";
2
2
  import { emuToPixels } from "../utils/units.js";
3
+ import { sanitizeExternalUrl } from "../utils/urlSecurity.js";
4
+ import { sanitizeImageSrc } from "../utils/sanitizeImageSrc.js";
3
5
  import { WRAP_ELEMENT_NAMES, parsePositionH, parsePositionV, parseWrapElement } from "./drawingUtils.js";
4
6
  import { resolveTarget } from "./relsParser.js";
5
7
  import { isTextBoxDrawing } from "./textBoxParser.js";
@@ -326,7 +328,8 @@ function parseInline(inlineEl, rels, media) {
326
328
  if (props.alt) image.alt = props.alt;
327
329
  if (props.title) image.title = props.title;
328
330
  if (props.decorative) image.decorative = true;
329
- if (imageData.src) image.src = imageData.src;
331
+ const safeSrc = sanitizeImageSrc(imageData.src);
332
+ if (safeSrc) image.src = safeSrc;
330
333
  if (imageData.mimeType) image.mimeType = imageData.mimeType;
331
334
  if (imageData.filename) image.filename = imageData.filename;
332
335
  if (padding) image.padding = padding;
@@ -334,8 +337,8 @@ function parseInline(inlineEl, rels, media) {
334
337
  if (crop) image.crop = crop;
335
338
  if (opacity !== void 0) image.opacity = opacity;
336
339
  if (props.hlinkRId && rels) {
337
- const href = resolveTarget(rels, props.hlinkRId);
338
- if (href) image.hlinkHref = href;
340
+ const safeHref = sanitizeExternalUrl(resolveTarget(rels, props.hlinkRId));
341
+ if (safeHref) image.hlinkHref = safeHref;
339
342
  }
340
343
  return image;
341
344
  }
@@ -391,7 +394,8 @@ function parseAnchor(anchorEl, rels, media) {
391
394
  if (props.alt) image.alt = props.alt;
392
395
  if (props.title) image.title = props.title;
393
396
  if (props.decorative) image.decorative = true;
394
- if (imageData.src) image.src = imageData.src;
397
+ const safeSrc = sanitizeImageSrc(imageData.src);
398
+ if (safeSrc) image.src = safeSrc;
395
399
  if (imageData.mimeType) image.mimeType = imageData.mimeType;
396
400
  if (imageData.filename) image.filename = imageData.filename;
397
401
  if (position) image.position = position;
@@ -402,8 +406,8 @@ function parseAnchor(anchorEl, rels, media) {
402
406
  if (layoutInCell !== void 0) image.layoutInCell = layoutInCell;
403
407
  if (allowOverlap !== void 0) image.allowOverlap = allowOverlap;
404
408
  if (props.hlinkRId && rels) {
405
- const href = resolveTarget(rels, props.hlinkRId);
406
- if (href) image.hlinkHref = href;
409
+ const safeHref = sanitizeExternalUrl(resolveTarget(rels, props.hlinkRId));
410
+ if (safeHref) image.hlinkHref = safeHref;
407
411
  }
408
412
  return image;
409
413
  }
@@ -44,6 +44,20 @@ const XML_DECLARATION_PATTERN = /^\s*<\?xml[^?]*\?>/u;
44
44
  const MAX_INPUT_BYTES = 50 * 1024 * 1024;
45
45
  const MAX_ARCHIVE_ENTRIES = 5e3;
46
46
  const MAX_CORE_PROPERTIES_BYTES = 1024 * 1024;
47
+ const CORE_PROPERTIES_PATH_LOWER = "docprops/core.xml";
48
+ /**
49
+ * Look up a package part by its conventional lowercase path, falling back to
50
+ * a case-insensitive scan. OPC part names are case-insensitive, so a
51
+ * producer that wrote `docProps/Core.xml` (or another casing) must still be
52
+ * found — otherwise the privacy rewrite silently no-ops and the unscrubbed
53
+ * buffer round-trips untouched.
54
+ */
55
+ const findZipEntryCaseInsensitive = (zip, lowerPath) => {
56
+ const direct = zip.file(lowerPath);
57
+ if (direct) return direct;
58
+ for (const [path, file] of Object.entries(zip.files)) if (!file.dir && path.toLowerCase() === lowerPath) return file;
59
+ return null;
60
+ };
47
61
  const loadPrivacyArchive = async (buffer) => {
48
62
  if (buffer.byteLength > MAX_INPUT_BYTES) throw new FolioDocumentPrivacyArchiveError({
49
63
  message: "Document privacy input exceeded the compressed-size limit",
@@ -63,7 +77,7 @@ const loadPrivacyArchive = async (buffer) => {
63
77
  message: "Document privacy input exceeded the package-entry limit",
64
78
  reason: "too-many-entries"
65
79
  });
66
- const coreProperties = zip.file("docProps/core.xml");
80
+ const coreProperties = findZipEntryCaseInsensitive(zip, CORE_PROPERTIES_PATH_LOWER);
67
81
  if (!coreProperties) return zip;
68
82
  const data = "_data" in coreProperties ? coreProperties._data : void 0;
69
83
  const declaredBytes = typeof data === "object" && data !== null && "uncompressedSize" in data ? data.uncompressedSize : void 0;
@@ -99,7 +113,7 @@ const rewriteCorePropertiesPrivacy = (xml, transforms) => {
99
113
  const rewriteDocxMetadataPrivacy = async (buffer, { transforms }) => {
100
114
  const appliedTransforms = resolveFolioDocumentPrivacyTransforms(transforms);
101
115
  const zip = await loadPrivacyArchive(buffer);
102
- const coreProperties = zip.file("docProps/core.xml");
116
+ const coreProperties = findZipEntryCaseInsensitive(zip, CORE_PROPERTIES_PATH_LOWER);
103
117
  if (!coreProperties) return {
104
118
  buffer,
105
119
  privacyReport: {
@@ -115,7 +129,7 @@ const rewriteDocxMetadataPrivacy = async (buffer, { transforms }) => {
115
129
  removedMetadataProperties: []
116
130
  }
117
131
  };
118
- zip.file("docProps/core.xml", rewritten.xml);
132
+ zip.file(coreProperties.name, rewritten.xml);
119
133
  return {
120
134
  buffer: await zip.generateAsync({
121
135
  type: "arraybuffer",
@@ -1,5 +1,5 @@
1
- import { findChild, getAttribute, parseNumericAttribute } from "./xmlParser.js";
2
1
  import { NumberFormatSchema, narrowEnum } from "./parserEnums.js";
2
+ import { findChild, getAttribute, parseNumericAttribute } from "./xmlParser.js";
3
3
  //#region src/docx/notePropertiesParser.ts
4
4
  function parseNumberFormat(numFmtAttr) {
5
5
  return narrowEnum(numFmtAttr, NumberFormatSchema);
@@ -1,5 +1,5 @@
1
- import { findChild, findChildren, getAttribute, parseBooleanElement, parseNumericAttribute, parseXmlDocument } from "./xmlParser.js";
2
1
  import { LevelSuffixSchema, ThemeColorSlotSchema, narrowEnum } from "./parserEnums.js";
2
+ import { findChild, findChildren, getAttribute, parseBooleanElement, parseNumericAttribute, parseXmlDocument } from "./xmlParser.js";
3
3
  //#region src/docx/numberingParser.ts
4
4
  const NUMBER_FORMAT_MAP = {
5
5
  decimal: "decimal",