@portone/docx-editor 0.1.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 (347) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/CONTRIBUTING.md +63 -0
  3. package/LICENSE +203 -0
  4. package/README.md +48 -0
  5. package/assets/editor.png +0 -0
  6. package/dist/DocxEditor.d.ts +123 -0
  7. package/dist/DocxEditor.js +348 -0
  8. package/dist/core.d.ts +36 -0
  9. package/dist/core.js +38 -0
  10. package/dist/docx/comments/constants.d.ts +8 -0
  11. package/dist/docx/comments/constants.js +20 -0
  12. package/dist/docx/comments/model.d.ts +37 -0
  13. package/dist/docx/comments/model.js +104 -0
  14. package/dist/docx/comments/reading.d.ts +36 -0
  15. package/dist/docx/comments/reading.js +149 -0
  16. package/dist/docx/comments/writing.d.ts +11 -0
  17. package/dist/docx/comments/writing.js +327 -0
  18. package/dist/docx/comments.d.ts +3 -0
  19. package/dist/docx/comments.js +4 -0
  20. package/dist/docx/container.d.ts +12 -0
  21. package/dist/docx/container.js +130 -0
  22. package/dist/docx/documentSettings.d.ts +4 -0
  23. package/dist/docx/documentSettings.js +14 -0
  24. package/dist/docx/exportDocx.d.ts +15 -0
  25. package/dist/docx/exportDocx.js +163 -0
  26. package/dist/docx/exportRefs.d.ts +16 -0
  27. package/dist/docx/exportRefs.js +10 -0
  28. package/dist/docx/formatting/direct.d.ts +30 -0
  29. package/dist/docx/formatting/direct.js +201 -0
  30. package/dist/docx/formatting/effectiveParagraph.d.ts +15 -0
  31. package/dist/docx/formatting/effectiveParagraph.js +81 -0
  32. package/dist/docx/formatting/styles.d.ts +67 -0
  33. package/dist/docx/formatting/styles.js +165 -0
  34. package/dist/docx/formatting/tabStops.d.ts +8 -0
  35. package/dist/docx/formatting/tabStops.js +65 -0
  36. package/dist/docx/formatting.d.ts +4 -0
  37. package/dist/docx/formatting.js +4 -0
  38. package/dist/docx/headersFooters.d.ts +36 -0
  39. package/dist/docx/headersFooters.js +218 -0
  40. package/dist/docx/hyperlink.d.ts +75 -0
  41. package/dist/docx/hyperlink.js +71 -0
  42. package/dist/docx/importDocx.d.ts +21 -0
  43. package/dist/docx/importDocx.js +263 -0
  44. package/dist/docx/importParagraph.d.ts +32 -0
  45. package/dist/docx/importParagraph.js +308 -0
  46. package/dist/docx/importTable.d.ts +9 -0
  47. package/dist/docx/importTable.js +275 -0
  48. package/dist/docx/media.d.ts +60 -0
  49. package/dist/docx/media.js +213 -0
  50. package/dist/docx/notes.d.ts +22 -0
  51. package/dist/docx/notes.js +71 -0
  52. package/dist/docx/pageGeometry.d.ts +75 -0
  53. package/dist/docx/pageGeometry.js +88 -0
  54. package/dist/docx/paraProps.d.ts +74 -0
  55. package/dist/docx/paraProps.js +167 -0
  56. package/dist/docx/propsXml.d.ts +49 -0
  57. package/dist/docx/propsXml.js +302 -0
  58. package/dist/docx/relationships.d.ts +42 -0
  59. package/dist/docx/relationships.js +94 -0
  60. package/dist/docx/runProps.d.ts +51 -0
  61. package/dist/docx/runProps.js +207 -0
  62. package/dist/docx/scan.d.ts +20 -0
  63. package/dist/docx/scan.js +110 -0
  64. package/dist/docx/sdt.d.ts +56 -0
  65. package/dist/docx/sdt.js +104 -0
  66. package/dist/docx/sdtProps.d.ts +18 -0
  67. package/dist/docx/sdtProps.js +11 -0
  68. package/dist/docx/serializeBlock.d.ts +4 -0
  69. package/dist/docx/serializeBlock.js +30 -0
  70. package/dist/docx/serializeParagraph.d.ts +15 -0
  71. package/dist/docx/serializeParagraph.js +208 -0
  72. package/dist/docx/serializeTable.d.ts +12 -0
  73. package/dist/docx/serializeTable.js +134 -0
  74. package/dist/docx/session.d.ts +81 -0
  75. package/dist/docx/session.js +79 -0
  76. package/dist/docx/tableFormatting/editing.d.ts +64 -0
  77. package/dist/docx/tableFormatting/editing.js +318 -0
  78. package/dist/docx/tableFormatting/reading.d.ts +96 -0
  79. package/dist/docx/tableFormatting/reading.js +221 -0
  80. package/dist/docx/tableFormatting.d.ts +2 -0
  81. package/dist/docx/tableFormatting.js +3 -0
  82. package/dist/docx/tableTemplate.d.ts +22 -0
  83. package/dist/docx/tableTemplate.js +111 -0
  84. package/dist/docx/theme.d.ts +40 -0
  85. package/dist/docx/theme.js +61 -0
  86. package/dist/docx/uniqueControls.d.ts +14 -0
  87. package/dist/docx/uniqueControls.js +62 -0
  88. package/dist/download.d.ts +57 -0
  89. package/dist/download.js +44 -0
  90. package/dist/editor/clipboard/images.d.ts +14 -0
  91. package/dist/editor/clipboard/images.js +158 -0
  92. package/dist/editor/clipboard/inlineFormatting.d.ts +21 -0
  93. package/dist/editor/clipboard/inlineFormatting.js +232 -0
  94. package/dist/editor/commands/breakCommands.d.ts +8 -0
  95. package/dist/editor/commands/breakCommands.js +19 -0
  96. package/dist/editor/commands/canRunCommand.d.ts +6 -0
  97. package/dist/editor/commands/canRunCommand.js +10 -0
  98. package/dist/editor/commands/commentCommands.d.ts +3 -0
  99. package/dist/editor/commands/commentCommands.js +4 -0
  100. package/dist/editor/commands/comments/editing.d.ts +21 -0
  101. package/dist/editor/commands/comments/editing.js +305 -0
  102. package/dist/editor/commands/comments/model.d.ts +31 -0
  103. package/dist/editor/commands/comments/model.js +0 -0
  104. package/dist/editor/commands/comments/reading.d.ts +8 -0
  105. package/dist/editor/commands/comments/reading.js +58 -0
  106. package/dist/editor/commands/formatting/editing.d.ts +32 -0
  107. package/dist/editor/commands/formatting/editing.js +138 -0
  108. package/dist/editor/commands/formatting/reading.d.ts +57 -0
  109. package/dist/editor/commands/formatting/reading.js +82 -0
  110. package/dist/editor/commands/formatting/shared.d.ts +32 -0
  111. package/dist/editor/commands/formatting/shared.js +53 -0
  112. package/dist/editor/commands/formattingCommands.d.ts +2 -0
  113. package/dist/editor/commands/formattingCommands.js +3 -0
  114. package/dist/editor/commands/historyCommands.d.ts +11 -0
  115. package/dist/editor/commands/historyCommands.js +16 -0
  116. package/dist/editor/commands/indentCommands.d.ts +15 -0
  117. package/dist/editor/commands/indentCommands.js +44 -0
  118. package/dist/editor/commands/index.d.ts +82 -0
  119. package/dist/editor/commands/index.js +171 -0
  120. package/dist/editor/commands/linkCommands.d.ts +56 -0
  121. package/dist/editor/commands/linkCommands.js +146 -0
  122. package/dist/editor/commands/listCommands.d.ts +58 -0
  123. package/dist/editor/commands/listCommands.js +140 -0
  124. package/dist/editor/commands/lockCommands.d.ts +47 -0
  125. package/dist/editor/commands/lockCommands.js +198 -0
  126. package/dist/editor/commands/noteQueries.d.ts +12 -0
  127. package/dist/editor/commands/noteQueries.js +29 -0
  128. package/dist/editor/commands/paragraphCommands.d.ts +59 -0
  129. package/dist/editor/commands/paragraphCommands.js +113 -0
  130. package/dist/editor/commands/spacingCommands.d.ts +23 -0
  131. package/dist/editor/commands/spacingCommands.js +48 -0
  132. package/dist/editor/commands/tabCommands.d.ts +5 -0
  133. package/dist/editor/commands/tabCommands.js +65 -0
  134. package/dist/editor/createEditor.d.ts +59 -0
  135. package/dist/editor/createEditor.js +160 -0
  136. package/dist/editor/documentStyles.d.ts +60 -0
  137. package/dist/editor/documentStyles.js +80 -0
  138. package/dist/editor/externalClipboard.d.ts +11 -0
  139. package/dist/editor/externalClipboard.js +323 -0
  140. package/dist/editor/imageFiles.d.ts +74 -0
  141. package/dist/editor/imageFiles.js +173 -0
  142. package/dist/editor/insertImage.d.ts +31 -0
  143. package/dist/editor/insertImage.js +35 -0
  144. package/dist/editor/insertTable.d.ts +18 -0
  145. package/dist/editor/insertTable.js +44 -0
  146. package/dist/editor/paragraphEdits.d.ts +42 -0
  147. package/dist/editor/paragraphEdits.js +59 -0
  148. package/dist/editor/plainText.d.ts +3 -0
  149. package/dist/editor/plainText.js +50 -0
  150. package/dist/editor/plugins/bookmarkProtection.d.ts +3 -0
  151. package/dist/editor/plugins/bookmarkProtection.js +28 -0
  152. package/dist/editor/plugins/columnResize.d.ts +27 -0
  153. package/dist/editor/plugins/columnResize.js +192 -0
  154. package/dist/editor/plugins/commentDecorations.d.ts +3 -0
  155. package/dist/editor/plugins/commentDecorations.js +23 -0
  156. package/dist/editor/plugins/commentReservations.d.ts +5 -0
  157. package/dist/editor/plugins/commentReservations.js +26 -0
  158. package/dist/editor/plugins/dropCaret.d.ts +10 -0
  159. package/dist/editor/plugins/dropCaret.js +11 -0
  160. package/dist/editor/plugins/imagePaste.d.ts +8 -0
  161. package/dist/editor/plugins/imagePaste.js +265 -0
  162. package/dist/editor/plugins/keymap.d.ts +5 -0
  163. package/dist/editor/plugins/keymap.js +94 -0
  164. package/dist/editor/plugins/linkPanel.d.ts +23 -0
  165. package/dist/editor/plugins/linkPanel.js +39 -0
  166. package/dist/editor/plugins/listInputRules.d.ts +14 -0
  167. package/dist/editor/plugins/listInputRules.js +36 -0
  168. package/dist/editor/plugins/lockedContent.d.ts +6 -0
  169. package/dist/editor/plugins/lockedContent.js +41 -0
  170. package/dist/editor/plugins/noteProtection.d.ts +3 -0
  171. package/dist/editor/plugins/noteProtection.js +25 -0
  172. package/dist/editor/plugins/numberingDecorations.d.ts +42 -0
  173. package/dist/editor/plugins/numberingDecorations.js +110 -0
  174. package/dist/editor/plugins/rowResize.d.ts +15 -0
  175. package/dist/editor/plugins/rowResize.js +196 -0
  176. package/dist/editor/plugins/styledParagraphs.d.ts +15 -0
  177. package/dist/editor/plugins/styledParagraphs.js +65 -0
  178. package/dist/editor/plugins/tabCaret.d.ts +3 -0
  179. package/dist/editor/plugins/tabCaret.js +126 -0
  180. package/dist/editor/plugins/tabDecorations.d.ts +11 -0
  181. package/dist/editor/plugins/tabDecorations.js +87 -0
  182. package/dist/editor/plugins/tabLayout.d.ts +16 -0
  183. package/dist/editor/plugins/tabLayout.js +328 -0
  184. package/dist/editor/plugins/tabPointer.d.ts +7 -0
  185. package/dist/editor/plugins/tabPointer.js +95 -0
  186. package/dist/editor/plugins/tableContextMenu.d.ts +21 -0
  187. package/dist/editor/plugins/tableContextMenu.js +88 -0
  188. package/dist/editor/plugins/textContextMenu.d.ts +15 -0
  189. package/dist/editor/plugins/textContextMenu.js +90 -0
  190. package/dist/editor/views/imageResize.d.ts +53 -0
  191. package/dist/editor/views/imageResize.js +167 -0
  192. package/dist/editor/views/runMarkView.d.ts +15 -0
  193. package/dist/editor/views/runMarkView.js +9 -0
  194. package/dist/editor/views/tableView.d.ts +24 -0
  195. package/dist/editor/views/tableView.js +32 -0
  196. package/dist/index.d.ts +44 -0
  197. package/dist/index.js +38 -0
  198. package/dist/model/format.d.ts +240 -0
  199. package/dist/model/format.js +305 -0
  200. package/dist/model/tabStops.d.ts +17 -0
  201. package/dist/model/tabStops.js +22 -0
  202. package/dist/numbering/listTemplate.d.ts +29 -0
  203. package/dist/numbering/listTemplate.js +83 -0
  204. package/dist/numbering/markers.d.ts +24 -0
  205. package/dist/numbering/markers.js +93 -0
  206. package/dist/numbering/parseNumbering.d.ts +65 -0
  207. package/dist/numbering/parseNumbering.js +116 -0
  208. package/dist/numbering/writeNumbering.d.ts +13 -0
  209. package/dist/numbering/writeNumbering.js +49 -0
  210. package/dist/ooxml/errors.d.ts +39 -0
  211. package/dist/ooxml/errors.js +21 -0
  212. package/dist/ooxml/image.d.ts +88 -0
  213. package/dist/ooxml/image.js +106 -0
  214. package/dist/ooxml/tabStops.d.ts +3 -0
  215. package/dist/ooxml/tabStops.js +51 -0
  216. package/dist/ooxml/units.d.ts +37 -0
  217. package/dist/ooxml/units.js +116 -0
  218. package/dist/ooxml/xml.d.ts +36 -0
  219. package/dist/ooxml/xml.js +89 -0
  220. package/dist/page/PageGuides.d.ts +16 -0
  221. package/dist/page/PageGuides.js +114 -0
  222. package/dist/page/measureBlocks.d.ts +25 -0
  223. package/dist/page/measureBlocks.js +80 -0
  224. package/dist/page/pageDecorations.d.ts +36 -0
  225. package/dist/page/pageDecorations.js +211 -0
  226. package/dist/page/pageLayout.d.ts +176 -0
  227. package/dist/page/pageLayout.js +157 -0
  228. package/dist/page/tableMeasurements.d.ts +10 -0
  229. package/dist/page/tableMeasurements.js +115 -0
  230. package/dist/page/usePageLayout.d.ts +57 -0
  231. package/dist/page/usePageLayout.js +141 -0
  232. package/dist/schema/docxSchema.d.ts +9 -0
  233. package/dist/schema/docxSchema.js +863 -0
  234. package/dist/schema/index.d.ts +2 -0
  235. package/dist/schema/index.js +9 -0
  236. package/dist/schema/locks.d.ts +112 -0
  237. package/dist/schema/locks.js +211 -0
  238. package/dist/schema/rendering.d.ts +6 -0
  239. package/dist/schema/rendering.js +46 -0
  240. package/dist/styles/classNames.d.ts +214 -0
  241. package/dist/styles/classNames.js +208 -0
  242. package/dist/styles/colors.d.ts +11 -0
  243. package/dist/styles/colors.js +14 -0
  244. package/dist/styles/fontSizes.d.ts +6 -0
  245. package/dist/styles/fontSizes.js +20 -0
  246. package/dist/styles/fontStack.d.ts +55 -0
  247. package/dist/styles/fontStack.js +262 -0
  248. package/dist/styles/fonts.d.ts +6 -0
  249. package/dist/styles/fonts.js +11 -0
  250. package/dist/styles/inlineStyle.d.ts +67 -0
  251. package/dist/styles/inlineStyle.js +212 -0
  252. package/dist/styles/lineSpacings.d.ts +11 -0
  253. package/dist/styles/lineSpacings.js +10 -0
  254. package/dist/styles.css +1650 -0
  255. package/dist/table/cellBorders.d.ts +12 -0
  256. package/dist/table/cellBorders.js +9 -0
  257. package/dist/table/cellFormatting.d.ts +57 -0
  258. package/dist/table/cellFormatting.js +173 -0
  259. package/dist/table/columns.d.ts +25 -0
  260. package/dist/table/columns.js +155 -0
  261. package/dist/table/commands.d.ts +19 -0
  262. package/dist/table/commands.js +63 -0
  263. package/dist/table/format.d.ts +35 -0
  264. package/dist/table/format.js +26 -0
  265. package/dist/table/gridBorders.d.ts +42 -0
  266. package/dist/table/gridBorders.js +192 -0
  267. package/dist/table/index.d.ts +16 -0
  268. package/dist/table/index.js +52 -0
  269. package/dist/table/merge.d.ts +36 -0
  270. package/dist/table/merge.js +125 -0
  271. package/dist/table/resize.d.ts +55 -0
  272. package/dist/table/resize.js +66 -0
  273. package/dist/table/rowResize.d.ts +14 -0
  274. package/dist/table/rowResize.js +44 -0
  275. package/dist/table/rows.d.ts +32 -0
  276. package/dist/table/rows.js +89 -0
  277. package/dist/table/widths.d.ts +69 -0
  278. package/dist/table/widths.js +97 -0
  279. package/dist/ui/AlignMenu.d.ts +15 -0
  280. package/dist/ui/AlignMenu.js +64 -0
  281. package/dist/ui/CellStyleGroup.d.ts +15 -0
  282. package/dist/ui/CellStyleGroup.js +232 -0
  283. package/dist/ui/ColorPicker.d.ts +13 -0
  284. package/dist/ui/ColorPicker.js +165 -0
  285. package/dist/ui/CommentsPanel.d.ts +15 -0
  286. package/dist/ui/CommentsPanel.js +348 -0
  287. package/dist/ui/FontFamilySelect.d.ts +14 -0
  288. package/dist/ui/FontFamilySelect.js +59 -0
  289. package/dist/ui/FontSizeSelect.d.ts +11 -0
  290. package/dist/ui/FontSizeSelect.js +49 -0
  291. package/dist/ui/InsertImageButton.d.ts +9 -0
  292. package/dist/ui/InsertImageButton.js +47 -0
  293. package/dist/ui/LinkCard.d.ts +12 -0
  294. package/dist/ui/LinkCard.js +127 -0
  295. package/dist/ui/LinkPanel.d.ts +9 -0
  296. package/dist/ui/LinkPanel.js +121 -0
  297. package/dist/ui/MenuChoice.d.ts +11 -0
  298. package/dist/ui/MenuChoice.js +32 -0
  299. package/dist/ui/NotesPanel.d.ts +6 -0
  300. package/dist/ui/NotesPanel.js +33 -0
  301. package/dist/ui/ParagraphStyleSelect.d.ts +11 -0
  302. package/dist/ui/ParagraphStyleSelect.js +62 -0
  303. package/dist/ui/Popover.d.ts +22 -0
  304. package/dist/ui/Popover.js +74 -0
  305. package/dist/ui/SpacingMenu.d.ts +12 -0
  306. package/dist/ui/SpacingMenu.js +54 -0
  307. package/dist/ui/TableMenu.d.ts +12 -0
  308. package/dist/ui/TableMenu.js +112 -0
  309. package/dist/ui/TableSizePicker.d.ts +9 -0
  310. package/dist/ui/TableSizePicker.js +53 -0
  311. package/dist/ui/TextMenu.d.ts +15 -0
  312. package/dist/ui/TextMenu.js +194 -0
  313. package/dist/ui/Toolbar.d.ts +19 -0
  314. package/dist/ui/Toolbar.js +448 -0
  315. package/dist/ui/ToolbarButton.d.ts +23 -0
  316. package/dist/ui/ToolbarButton.js +56 -0
  317. package/dist/ui/Tooltip.d.ts +19 -0
  318. package/dist/ui/Tooltip.js +47 -0
  319. package/dist/ui/ZoomSelect.d.ts +7 -0
  320. package/dist/ui/ZoomSelect.js +44 -0
  321. package/dist/ui/comments/CommentComposer.d.ts +17 -0
  322. package/dist/ui/comments/CommentComposer.js +59 -0
  323. package/dist/ui/comments/useCommentRailLayout.d.ts +18 -0
  324. package/dist/ui/comments/useCommentRailLayout.js +183 -0
  325. package/dist/ui/keyboardWalk.d.ts +22 -0
  326. package/dist/ui/keyboardWalk.js +70 -0
  327. package/dist/ui/openAddress.d.ts +11 -0
  328. package/dist/ui/openAddress.js +16 -0
  329. package/dist/ui/panelPlacement.d.ts +51 -0
  330. package/dist/ui/panelPlacement.js +71 -0
  331. package/dist/ui/presets.d.ts +11 -0
  332. package/dist/ui/presets.js +0 -0
  333. package/dist/ui/rovingFocus.d.ts +20 -0
  334. package/dist/ui/rovingFocus.js +61 -0
  335. package/dist/ui/runCommand.d.ts +5 -0
  336. package/dist/ui/runCommand.js +13 -0
  337. package/dist/ui/useDismiss.d.ts +6 -0
  338. package/dist/ui/useDismiss.js +31 -0
  339. package/dist/ui/useFitWidthZoom.d.ts +2 -0
  340. package/dist/ui/useFitWidthZoom.js +26 -0
  341. package/dist/ui/useGridKeyboard.d.ts +12 -0
  342. package/dist/ui/useGridKeyboard.js +90 -0
  343. package/dist/ui/useMenuKeyboard.d.ts +12 -0
  344. package/dist/ui/useMenuKeyboard.js +56 -0
  345. package/dist/ui/zoom.d.ts +4 -0
  346. package/dist/ui/zoom.js +21 -0
  347. package/package.json +120 -0
@@ -0,0 +1,149 @@
1
+ // src/docx/comments/reading.ts
2
+ import {
3
+ decodeUtf8,
4
+ elementChildren,
5
+ parseXml,
6
+ serializeXml,
7
+ W_NS
8
+ } from "../../ooxml/xml.js";
9
+ import { readRelationships, relsPathOf, resolveTarget } from "../relationships.js";
10
+ import { COMMENTS_EXTENDED_REL_TYPE, COMMENTS_REL_TYPE } from "./constants.js";
11
+ function attribute(el, localName) {
12
+ return Array.from(el.attributes).find((entry) => entry.localName === localName)?.value ?? null;
13
+ }
14
+ function inlineCommentText(node) {
15
+ if (node.localName === "t") return node.textContent ?? "";
16
+ if (node.localName === "tab") return " ";
17
+ if (node.localName === "br" || node.localName === "cr") return "\n";
18
+ return elementChildren(node).map(inlineCommentText).join("");
19
+ }
20
+ function commentText(el) {
21
+ const paragraphs = Array.from(el.getElementsByTagNameNS(W_NS, "p"));
22
+ return paragraphs.map(inlineCommentText).join("\n");
23
+ }
24
+ var NO_COMMENTS = {
25
+ partPath: null,
26
+ xml: null,
27
+ hadBom: false,
28
+ ordered: [],
29
+ byId: /* @__PURE__ */ new Map(),
30
+ repliesByParentId: /* @__PURE__ */ new Map(),
31
+ extendedPartPath: null,
32
+ extendedXml: null,
33
+ extendedHadBom: false,
34
+ extendedOrdered: []
35
+ };
36
+ function lastParagraphId(comment) {
37
+ const paragraphs = Array.from(comment.getElementsByTagNameNS(W_NS, "p"));
38
+ return paragraphs.length === 0 ? null : attribute(paragraphs[paragraphs.length - 1], "paraId");
39
+ }
40
+ function readCommentExtensions(parts, mainPartPath) {
41
+ const relationship = readRelationships(parts, relsPathOf(mainPartPath)).find(
42
+ (entry) => entry.type === COMMENTS_EXTENDED_REL_TYPE && !entry.external
43
+ );
44
+ if (!relationship) {
45
+ return {
46
+ partPath: null,
47
+ xml: null,
48
+ hadBom: false,
49
+ byParaId: /* @__PURE__ */ new Map(),
50
+ ordered: []
51
+ };
52
+ }
53
+ const partPath = resolveTarget(mainPartPath, relationship.target);
54
+ const bytes = parts.get(partPath);
55
+ if (!bytes) {
56
+ return {
57
+ partPath,
58
+ xml: null,
59
+ hadBom: false,
60
+ byParaId: /* @__PURE__ */ new Map(),
61
+ ordered: []
62
+ };
63
+ }
64
+ const { text, hadBom } = decodeUtf8(bytes);
65
+ const root = parseXml(text).documentElement;
66
+ const byParaId = /* @__PURE__ */ new Map();
67
+ const ordered = [];
68
+ for (const el of elementChildren(root)) {
69
+ if (el.localName !== "commentEx") continue;
70
+ const paraId = attribute(el, "paraId");
71
+ if (paraId === null) continue;
72
+ const extension = {
73
+ paraId,
74
+ parentParaId: attribute(el, "paraIdParent"),
75
+ resolved: ["1", "true", "on"].includes(
76
+ attribute(el, "done")?.toLowerCase() ?? ""
77
+ ),
78
+ xml: serializeXml(el)
79
+ };
80
+ ordered.push(extension);
81
+ if (!byParaId.has(paraId)) byParaId.set(paraId, extension);
82
+ }
83
+ return { partPath, xml: text, hadBom, byParaId, ordered };
84
+ }
85
+ function readComments(parts, mainPartPath) {
86
+ const relationship = readRelationships(parts, relsPathOf(mainPartPath)).find(
87
+ (entry) => entry.type === COMMENTS_REL_TYPE && !entry.external
88
+ );
89
+ if (!relationship) return NO_COMMENTS;
90
+ const partPath = resolveTarget(mainPartPath, relationship.target);
91
+ const bytes = parts.get(partPath);
92
+ if (!bytes) return { ...NO_COMMENTS, partPath };
93
+ const { text, hadBom } = decodeUtf8(bytes);
94
+ const root = parseXml(text).documentElement;
95
+ const extensions = readCommentExtensions(parts, mainPartPath);
96
+ const base = elementChildren(root).filter((el) => el.localName === "comment").flatMap((el) => {
97
+ const id = attribute(el, "id");
98
+ if (id === null) return [];
99
+ const paraId = lastParagraphId(el);
100
+ const extension = paraId ? extensions.byParaId.get(paraId) : void 0;
101
+ return [
102
+ {
103
+ id,
104
+ author: attribute(el, "author"),
105
+ initials: attribute(el, "initials"),
106
+ date: attribute(el, "date"),
107
+ text: commentText(el),
108
+ xml: serializeXml(el),
109
+ paraId,
110
+ parentParaId: extension?.parentParaId ?? null,
111
+ resolved: extension?.resolved ?? false,
112
+ extensionXml: extension?.xml ?? null
113
+ }
114
+ ];
115
+ });
116
+ const idByParaId = new Map(
117
+ base.flatMap(
118
+ (comment) => comment.paraId === null ? [] : [[comment.paraId, comment.id]]
119
+ )
120
+ );
121
+ const ordered = base;
122
+ const byId = /* @__PURE__ */ new Map();
123
+ const repliesByParentId = /* @__PURE__ */ new Map();
124
+ for (const comment of ordered) {
125
+ if (!byId.has(comment.id)) byId.set(comment.id, comment);
126
+ const parentId = comment.parentParaId === null ? null : idByParaId.get(comment.parentParaId) ?? null;
127
+ if (parentId !== null) {
128
+ const replies = repliesByParentId.get(parentId) ?? [];
129
+ replies.push(comment);
130
+ repliesByParentId.set(parentId, replies);
131
+ }
132
+ }
133
+ return {
134
+ partPath,
135
+ xml: text,
136
+ hadBom,
137
+ ordered,
138
+ byId,
139
+ repliesByParentId,
140
+ extendedPartPath: extensions.partPath,
141
+ extendedXml: extensions.xml,
142
+ extendedHadBom: extensions.hadBom,
143
+ extendedOrdered: extensions.ordered
144
+ };
145
+ }
146
+ export {
147
+ NO_COMMENTS,
148
+ readComments
149
+ };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Plans changed comment package parts while preserving untouched XML.
3
+ */
4
+ import type { Node as PMNode } from "prosemirror-model";
5
+ import { type RelationshipWriter } from "../relationships";
6
+ import type { SessionStore } from "../session";
7
+ export interface CommentPartChanges {
8
+ parts: ReadonlyMap<string, Uint8Array>;
9
+ }
10
+ /** Plans the Comments part, relationship and content type only when comment state changed. */
11
+ export declare function planCommentParts(doc: PMNode, session: SessionStore, relationships: RelationshipWriter, currentContentTypes?: Uint8Array): CommentPartChanges | null;
@@ -0,0 +1,327 @@
1
+ // src/docx/comments/writing.ts
2
+ import { DocxExportError } from "../../ooxml/errors.js";
3
+ import { decodeUtf8, encodeUtf8, escapeXml, W_NS } from "../../ooxml/xml.js";
4
+ import { directoryOf } from "../relationships.js";
5
+ import {
6
+ COMMENTS_CONTENT_TYPE,
7
+ COMMENTS_EXTENDED_CONTENT_TYPE,
8
+ COMMENTS_EXTENDED_REL_TYPE,
9
+ COMMENTS_REL_TYPE,
10
+ CONTENT_TYPES_PATH,
11
+ MC_NS,
12
+ W14_NS,
13
+ W15_NS
14
+ } from "./constants.js";
15
+ import {
16
+ commentReferencesIn
17
+ } from "./model.js";
18
+ function commentsChanged(doc, session) {
19
+ const current = commentReferencesIn(doc);
20
+ if (current.size !== session.commentReferenceIds.size) return true;
21
+ const currentBodies = currentCommentBodies(current);
22
+ const originalBodies = originalThreadIds(
23
+ session.comments,
24
+ session.commentReferenceIds
25
+ );
26
+ if (currentBodies.size !== originalBodies.size) return true;
27
+ for (const id of originalBodies) {
28
+ if (!currentBodies.has(id)) return true;
29
+ }
30
+ for (const id of session.commentReferenceIds) {
31
+ const comment = current.get(id);
32
+ if (!comment?.imported) return true;
33
+ }
34
+ for (const comment of current.values()) {
35
+ if (comment.replies.some((reply) => !reply.imported)) return true;
36
+ }
37
+ return false;
38
+ }
39
+ function renderedExtension(comment) {
40
+ if (comment.extensionXml !== null) return comment.extensionXml;
41
+ const parent = "parentParaId" in comment ? ` w15:paraIdParent="${escapeXml(comment.parentParaId)}"` : "";
42
+ const done = "resolved" in comment ? ` w15:done="${comment.resolved ? "1" : "0"}"` : "";
43
+ return `<w15:commentEx w15:paraId="${escapeXml(comment.paraId)}"${parent}${done}/>`;
44
+ }
45
+ function extensionsXml(references, comments, originallyReferenced) {
46
+ const current = currentCommentBodies(references);
47
+ const originalThreads = originalThreadIds(comments, originallyReferenced);
48
+ const pieces = [];
49
+ const written = /* @__PURE__ */ new Set();
50
+ const idByParaId = new Map(
51
+ comments.ordered.flatMap(
52
+ (comment) => comment.paraId === null ? [] : [[comment.paraId, comment.id]]
53
+ )
54
+ );
55
+ for (const original of comments.extendedOrdered) {
56
+ const id = idByParaId.get(original.paraId);
57
+ const item = id === void 0 ? void 0 : current.get(id);
58
+ if (id !== void 0 && item && !written.has(id)) {
59
+ pieces.push(renderedExtension(item));
60
+ written.add(id);
61
+ } else if (id === void 0 || !originalThreads.has(id)) {
62
+ pieces.push(original.xml);
63
+ }
64
+ }
65
+ for (const [id, comment] of current) {
66
+ if (!written.has(id)) pieces.push(renderedExtension(comment));
67
+ }
68
+ if (comments.extendedXml === null) {
69
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w15:commentsEx xmlns:w15="${W15_NS}">${pieces.join("")}</w15:commentsEx>`;
70
+ }
71
+ const open = /<(?:[\w.-]+:)?commentsEx\b[^>]*>/.exec(comments.extendedXml);
72
+ if (!open) {
73
+ throw new DocxExportError(
74
+ "malformed-xml",
75
+ "the Comments Extended part has no commentsEx root element"
76
+ );
77
+ }
78
+ const name = /^<([^\s>]+)/.exec(open[0])?.[1];
79
+ const close = name ? comments.extendedXml.lastIndexOf(`</${name}>`) : -1;
80
+ if (close === -1) {
81
+ throw new DocxExportError(
82
+ "malformed-xml",
83
+ "the Comments Extended part has no closing commentsEx tag"
84
+ );
85
+ }
86
+ const bodyAt = open.index + open[0].length;
87
+ return comments.extendedXml.slice(0, bodyAt) + pieces.join("") + comments.extendedXml.slice(close);
88
+ }
89
+ function extensionsChanged(doc, session) {
90
+ const current = commentReferencesIn(doc);
91
+ for (const [id, comment] of current) {
92
+ if (!comment.threadImported) return true;
93
+ if (!session.commentReferenceIds.has(id)) continue;
94
+ }
95
+ for (const id of session.commentReferenceIds) {
96
+ if (current.has(id)) continue;
97
+ const original = session.comments.byId.get(id);
98
+ if (original?.extensionXml != null || (session.comments.repliesByParentId.get(id)?.length ?? 0) > 0) {
99
+ return true;
100
+ }
101
+ }
102
+ return false;
103
+ }
104
+ function commentTextXml(text) {
105
+ const lines = text.split("\n");
106
+ const pieces = [];
107
+ lines.forEach((line, index) => {
108
+ if (index > 0) pieces.push("<w:br/>");
109
+ if (line.length > 0 || lines.length === 1) {
110
+ pieces.push(`<w:t xml:space="preserve">${escapeXml(line)}</w:t>`);
111
+ }
112
+ });
113
+ return `<w:r>${pieces.join("")}</w:r>`;
114
+ }
115
+ function carriesThreadMetadata(comment) {
116
+ return comment.extensionXml !== null || "threadImported" in comment && !comment.threadImported || "parentParaId" in comment;
117
+ }
118
+ function renderedComment(comment) {
119
+ if (comment.imported && comment.commentXml !== null) {
120
+ return comment.commentXml;
121
+ }
122
+ const attrs = [
123
+ `w:id="${escapeXml(comment.id)}"`,
124
+ comment.author === null ? null : `w:author="${escapeXml(comment.author)}"`,
125
+ comment.date === null ? null : `w:date="${escapeXml(comment.date)}"`,
126
+ comment.initials === null ? null : `w:initials="${escapeXml(comment.initials)}"`
127
+ ].filter((entry) => entry !== null).join(" ");
128
+ const threaded = carriesThreadMetadata(comment);
129
+ const paragraphAttrs = threaded ? ` xmlns:w14="${W14_NS}" w14:paraId="${escapeXml(comment.paraId)}"` : "";
130
+ return `<w:comment xmlns:w="${W_NS}" ${attrs}><w:p${paragraphAttrs}>${commentTextXml(comment.text)}</w:p></w:comment>`;
131
+ }
132
+ function withThreadMarkupCompatibility(openTag) {
133
+ let updated = openTag;
134
+ if (!/\sxmlns:w14\s*=/.test(updated)) {
135
+ updated = updated.replace(/>$/, ` xmlns:w14="${W14_NS}">`);
136
+ }
137
+ if (!/\sxmlns:mc\s*=/.test(updated)) {
138
+ updated = updated.replace(/>$/, ` xmlns:mc="${MC_NS}">`);
139
+ }
140
+ const ignorable = /\smc:Ignorable\s*=\s*(["'])([^"']*)\1/.exec(updated);
141
+ if (!ignorable) {
142
+ return updated.replace(/>$/, ' mc:Ignorable="w14">');
143
+ }
144
+ const tokens = ignorable[2].split(/\s+/).filter(Boolean);
145
+ if (tokens.includes("w14")) return updated;
146
+ const replacement = ` mc:Ignorable=${ignorable[1]}${[...tokens, "w14"].join(" ")}${ignorable[1]}`;
147
+ return updated.slice(0, ignorable.index) + replacement + updated.slice(ignorable.index + ignorable[0].length);
148
+ }
149
+ function currentCommentBodies(references) {
150
+ const comments = /* @__PURE__ */ new Map();
151
+ for (const [id, comment] of references) {
152
+ comments.set(id, comment);
153
+ for (const reply of comment.replies) comments.set(reply.id, reply);
154
+ }
155
+ return comments;
156
+ }
157
+ function originalThreadIds(comments, rootIds) {
158
+ const ids = new Set(rootIds);
159
+ const pending = Array.from(rootIds);
160
+ while (pending.length > 0) {
161
+ const parent = pending.shift();
162
+ if (parent === void 0) break;
163
+ for (const reply of comments.repliesByParentId.get(parent) ?? []) {
164
+ if (ids.has(reply.id)) continue;
165
+ ids.add(reply.id);
166
+ pending.push(reply.id);
167
+ }
168
+ }
169
+ return ids;
170
+ }
171
+ function commentsXml(references, comments, originallyReferenced) {
172
+ const currentBodies = currentCommentBodies(references);
173
+ const hasThreadMetadata = Array.from(currentBodies.values()).some(
174
+ carriesThreadMetadata
175
+ );
176
+ const originalThreads = originalThreadIds(comments, originallyReferenced);
177
+ const pieces = [];
178
+ const written = /* @__PURE__ */ new Set();
179
+ for (const original of comments.ordered) {
180
+ const current = currentBodies.get(original.id);
181
+ if (current) {
182
+ pieces.push(renderedComment(current));
183
+ written.add(original.id);
184
+ continue;
185
+ }
186
+ if (!originalThreads.has(original.id)) {
187
+ pieces.push(original.xml);
188
+ written.add(original.id);
189
+ }
190
+ }
191
+ for (const [id, comment] of currentBodies) {
192
+ if (!written.has(id)) pieces.push(renderedComment(comment));
193
+ }
194
+ if (comments.xml === null) {
195
+ const compatibility = hasThreadMetadata ? ` xmlns:w14="${W14_NS}" xmlns:mc="${MC_NS}" mc:Ignorable="w14"` : "";
196
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w:comments xmlns:w="${W_NS}"${compatibility}>${pieces.join("")}</w:comments>`;
197
+ }
198
+ const open = /<(?:[\w.-]+:)?comments\b[^>]*>/.exec(comments.xml);
199
+ if (!open) {
200
+ throw new DocxExportError(
201
+ "malformed-xml",
202
+ "the Comments part has no comments root element"
203
+ );
204
+ }
205
+ const name = /^<([^\s>]+)/.exec(open[0])?.[1];
206
+ const close = name ? comments.xml.lastIndexOf(`</${name}>`) : -1;
207
+ if (close === -1) {
208
+ throw new DocxExportError(
209
+ "malformed-xml",
210
+ "the Comments part has no closing comments tag"
211
+ );
212
+ }
213
+ const openTag = hasThreadMetadata ? withThreadMarkupCompatibility(open[0]) : open[0];
214
+ return comments.xml.slice(0, open.index) + openTag + pieces.join("") + comments.xml.slice(close);
215
+ }
216
+ var TYPES_OPEN_TAG = /<(?:[\w.-]+:)?Types\b[^>]*>/;
217
+ function withContentType(parts, partPath, contentType, current) {
218
+ const original = current ?? parts.get(CONTENT_TYPES_PATH);
219
+ if (!original) {
220
+ throw new DocxExportError(
221
+ "missing-content-types",
222
+ `cannot add a Comments part to a package that has no ${CONTENT_TYPES_PATH}`
223
+ );
224
+ }
225
+ const { text, hadBom } = decodeUtf8(original);
226
+ const partName = `/${partPath}`;
227
+ if (new RegExp(
228
+ `<(?:[\\w.-]+:)?Override[^>]+PartName=["']${partName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}["']`,
229
+ "i"
230
+ ).test(text)) {
231
+ return null;
232
+ }
233
+ const open = TYPES_OPEN_TAG.exec(text);
234
+ if (!open) {
235
+ throw new DocxExportError(
236
+ "malformed-xml",
237
+ `${CONTENT_TYPES_PATH} has no Types element`
238
+ );
239
+ }
240
+ const rootName = /^<([^\s>]+)/.exec(open[0])?.[1] ?? "Types";
241
+ const separator = rootName.indexOf(":");
242
+ const prefix = separator < 0 ? "" : `${rootName.slice(0, separator)}:`;
243
+ const declaration = `<${prefix}Override PartName="${partName}" ContentType="${contentType}"/>`;
244
+ const at = open.index + open[0].length;
245
+ return encodeUtf8(text.slice(0, at) + declaration + text.slice(at), hadBom);
246
+ }
247
+ function availableCommentsPath(session) {
248
+ const directory = directoryOf(session.mainPartPath);
249
+ for (let suffix = 0; ; suffix += 1) {
250
+ const name = suffix === 0 ? "comments.xml" : `comments${suffix + 1}.xml`;
251
+ const path = directory + name;
252
+ if (!session.parts.has(path)) return path;
253
+ }
254
+ }
255
+ function availableCommentsExtendedPath(session) {
256
+ const directory = directoryOf(session.mainPartPath);
257
+ for (let suffix = 0; ; suffix += 1) {
258
+ const name = suffix === 0 ? "commentsExtended.xml" : `commentsExtended${suffix + 1}.xml`;
259
+ const path = directory + name;
260
+ if (!session.parts.has(path)) return path;
261
+ }
262
+ }
263
+ function planCommentParts(doc, session, relationships, currentContentTypes) {
264
+ const bodyChanged = commentsChanged(doc, session);
265
+ const threadChanged = extensionsChanged(doc, session);
266
+ if (!bodyChanged && !threadChanged) return null;
267
+ const references = commentReferencesIn(doc);
268
+ const addingPart = session.comments.partPath === null;
269
+ const partPath = session.comments.partPath ?? availableCommentsPath(session);
270
+ const parts = /* @__PURE__ */ new Map();
271
+ if (addingPart) {
272
+ const target = partPath.slice(directoryOf(session.mainPartPath).length);
273
+ relationships.add({ type: COMMENTS_REL_TYPE, target });
274
+ }
275
+ if (bodyChanged) {
276
+ parts.set(
277
+ partPath,
278
+ encodeUtf8(
279
+ commentsXml(references, session.comments, session.commentReferenceIds),
280
+ session.comments.hadBom
281
+ )
282
+ );
283
+ }
284
+ if (addingPart || session.comments.xml === null) {
285
+ const contentTypes = withContentType(
286
+ session.parts,
287
+ partPath,
288
+ COMMENTS_CONTENT_TYPE,
289
+ currentContentTypes
290
+ );
291
+ if (contentTypes) parts.set(CONTENT_TYPES_PATH, contentTypes);
292
+ }
293
+ if (threadChanged && (references.size > 0 || session.comments.extendedPartPath !== null)) {
294
+ const addingExtendedPart = session.comments.extendedPartPath === null;
295
+ const extendedPartPath = session.comments.extendedPartPath ?? availableCommentsExtendedPath(session);
296
+ if (addingExtendedPart) {
297
+ const target = extendedPartPath.slice(
298
+ directoryOf(session.mainPartPath).length
299
+ );
300
+ relationships.add({ type: COMMENTS_EXTENDED_REL_TYPE, target });
301
+ }
302
+ parts.set(
303
+ extendedPartPath,
304
+ encodeUtf8(
305
+ extensionsXml(
306
+ references,
307
+ session.comments,
308
+ session.commentReferenceIds
309
+ ),
310
+ session.comments.extendedHadBom
311
+ )
312
+ );
313
+ if (addingExtendedPart || session.comments.extendedXml === null) {
314
+ const contentTypes = withContentType(
315
+ session.parts,
316
+ extendedPartPath,
317
+ COMMENTS_EXTENDED_CONTENT_TYPE,
318
+ parts.get(CONTENT_TYPES_PATH) ?? currentContentTypes
319
+ );
320
+ if (contentTypes) parts.set(CONTENT_TYPES_PATH, contentTypes);
321
+ }
322
+ }
323
+ return { parts };
324
+ }
325
+ export {
326
+ planCommentParts
327
+ };
@@ -0,0 +1,3 @@
1
+ export * from "./comments/model";
2
+ export * from "./comments/reading";
3
+ export * from "./comments/writing";
@@ -0,0 +1,4 @@
1
+ // src/docx/comments.ts
2
+ export * from "./comments/model.js";
3
+ export * from "./comments/reading.js";
4
+ export * from "./comments/writing.js";
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Caps on one part and on the whole package. The bytes are untrusted and a zip chooses its own
3
+ * inflated size (a few hundred KB of zeros reach hundreds of MB), so both the stored size and the
4
+ * declared inflated size are checked off the directory before any entry is inflated. The caps sit
5
+ * far above a real document (low megabytes), so nothing legitimate is refused.
6
+ */
7
+ export declare const MAX_PART_BYTES: number;
8
+ export declare const MAX_PACKAGE_BYTES: number;
9
+ /** Collects every part in the zip, keeping the original order */
10
+ export declare function openParts(bytes: Uint8Array): Map<string, Uint8Array>;
11
+ /** Builds a zip that swaps in only the rewritten parts and keeps every other part's original bytes as they were */
12
+ export declare function repackParts(parts: Map<string, Uint8Array>, replacements: Map<string, Uint8Array>): Uint8Array;
@@ -0,0 +1,130 @@
1
+ // src/docx/container.ts
2
+ import { inflateSync, zipSync } from "fflate";
3
+ import { DocxImportError } from "../ooxml/errors.js";
4
+ var MAX_PART_BYTES = 32 * 1024 * 1024;
5
+ var MAX_PACKAGE_BYTES = 64 * 1024 * 1024;
6
+ function escapesPackage(name) {
7
+ const segments = name.split(/[/\\]/);
8
+ return segments[0] === "" || /^[A-Za-z]:$/.test(segments[0]) || segments.includes("..");
9
+ }
10
+ var END_OF_DIRECTORY = 101010256;
11
+ var DIRECTORY_ENTRY = 33639248;
12
+ var LOCAL_HEADER = 67324752;
13
+ var END_RECORD_SEARCH = 22 + 65535;
14
+ var STORED = 0;
15
+ var DEFLATED = 8;
16
+ var nameDecoder = new TextDecoder("utf-8");
17
+ function unreadable(why) {
18
+ throw new DocxImportError("not-a-docx", why);
19
+ }
20
+ function endOfDirectory(view) {
21
+ const earliest = Math.max(0, view.byteLength - END_RECORD_SEARCH);
22
+ for (let at = view.byteLength - 22; at >= earliest; at -= 1) {
23
+ if (view.getUint32(at, true) === END_OF_DIRECTORY) return at;
24
+ }
25
+ return unreadable("the bytes are not a zip package");
26
+ }
27
+ function dataStart(view, headerAt) {
28
+ if (headerAt + 30 > view.byteLength || view.getUint32(headerAt, true) !== LOCAL_HEADER) {
29
+ return unreadable("an entry of the package has no readable header");
30
+ }
31
+ const nameLength = view.getUint16(headerAt + 26, true);
32
+ const extraLength = view.getUint16(headerAt + 28, true);
33
+ return headerAt + 30 + nameLength + extraLength;
34
+ }
35
+ function directoryEntries(bytes) {
36
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
37
+ const end = endOfDirectory(view);
38
+ const count = view.getUint16(end + 10, true);
39
+ const entries = [];
40
+ let at = view.getUint32(end + 16, true);
41
+ for (let read = 0; read < count; read += 1) {
42
+ if (at + 46 > view.byteLength || view.getUint32(at, true) !== DIRECTORY_ENTRY) {
43
+ return unreadable("the package's directory does not read as one");
44
+ }
45
+ const nameLength = view.getUint16(at + 28, true);
46
+ const extraLength = view.getUint16(at + 30, true);
47
+ const commentLength = view.getUint16(at + 32, true);
48
+ entries.push({
49
+ name: nameDecoder.decode(bytes.subarray(at + 46, at + 46 + nameLength)),
50
+ compression: view.getUint16(at + 10, true),
51
+ storedSize: view.getUint32(at + 20, true),
52
+ declaredSize: view.getUint32(at + 24, true),
53
+ dataAt: dataStart(view, view.getUint32(at + 42, true))
54
+ });
55
+ at += 46 + nameLength + extraLength + commentLength;
56
+ }
57
+ return entries;
58
+ }
59
+ function entryBytes(bytes, entry) {
60
+ const end = entry.dataAt + entry.storedSize;
61
+ if (end > bytes.length) {
62
+ return unreadable("an entry of the package reaches past its end");
63
+ }
64
+ const held = bytes.subarray(entry.dataAt, end);
65
+ if (entry.storedSize === 0) {
66
+ if (entry.declaredSize !== 0) {
67
+ return unreadable("an empty entry of the package declares a size");
68
+ }
69
+ return held;
70
+ }
71
+ if (entry.compression === STORED) {
72
+ if (entry.storedSize !== entry.declaredSize) {
73
+ return unreadable("a stored entry does not hold the size it declares");
74
+ }
75
+ return held.slice();
76
+ }
77
+ if (entry.compression !== DEFLATED) {
78
+ return unreadable(
79
+ "the package holds an entry compressed in a way we cannot read"
80
+ );
81
+ }
82
+ const inflated = inflateSync(held, {
83
+ out: new Uint8Array(entry.declaredSize + 1)
84
+ });
85
+ if (inflated.length !== entry.declaredSize) {
86
+ return unreadable("an entry does not inflate to the size it declares");
87
+ }
88
+ return inflated;
89
+ }
90
+ function openParts(bytes) {
91
+ const parts = /* @__PURE__ */ new Map();
92
+ let packageBytes = 0;
93
+ try {
94
+ for (const entry of directoryEntries(bytes)) {
95
+ if (escapesPackage(entry.name)) {
96
+ unreadable("the package holds an entry whose name reaches outside it");
97
+ }
98
+ packageBytes += Math.max(entry.storedSize, entry.declaredSize);
99
+ if (entry.storedSize > MAX_PART_BYTES || entry.declaredSize > MAX_PART_BYTES || packageBytes > MAX_PACKAGE_BYTES) {
100
+ throw new DocxImportError(
101
+ "too-large",
102
+ "the docx file asks to inflate to more than we open"
103
+ );
104
+ }
105
+ parts.set(entry.name, entryBytes(bytes, entry));
106
+ }
107
+ return parts;
108
+ } catch (error) {
109
+ if (error instanceof DocxImportError) throw error;
110
+ throw new DocxImportError("not-a-docx", "could not open the docx file", {
111
+ cause: error
112
+ });
113
+ }
114
+ }
115
+ function repackParts(parts, replacements) {
116
+ const zippable = {};
117
+ for (const [name, data] of parts) {
118
+ zippable[name] = replacements.get(name) ?? data;
119
+ }
120
+ for (const [name, data] of replacements) {
121
+ if (!parts.has(name)) zippable[name] = data;
122
+ }
123
+ return zipSync(zippable, { level: 6, mtime: new Date(1980, 0, 1) });
124
+ }
125
+ export {
126
+ MAX_PACKAGE_BYTES,
127
+ MAX_PART_BYTES,
128
+ openParts,
129
+ repackParts
130
+ };
@@ -0,0 +1,4 @@
1
+ /** The interval OOXML assigns when settings.xml does not declare one. */
2
+ export declare const DEFAULT_TAB_STOP_PT = 36;
3
+ /** Reads the document-wide automatic tab interval from settings.xml. */
4
+ export declare function readDefaultTabStop(settings: Document | null): number | null;
@@ -0,0 +1,14 @@
1
+ // src/docx/documentSettings.ts
2
+ import { twipsToPt, wAttr } from "../ooxml/units.js";
3
+ import { childByLocalName } from "../ooxml/xml.js";
4
+ var DEFAULT_TAB_STOP_PT = 36;
5
+ function readDefaultTabStop(settings) {
6
+ if (!settings) return null;
7
+ const setting = childByLocalName(settings.documentElement, "defaultTabStop");
8
+ const value = setting ? twipsToPt(wAttr(setting, "val")) : null;
9
+ return value !== null && value > 0 ? value : null;
10
+ }
11
+ export {
12
+ DEFAULT_TAB_STOP_PT,
13
+ readDefaultTabStop
14
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Turns the edited document back into docx bytes.
3
+ *
4
+ * The body (document.xml) is always rebuilt from preserved and edited blocks. numbering.xml is
5
+ * rewritten only when a list was newly started, media parts only when an image was inserted, and
6
+ * the Comments part only when comments changed. Content types and relationships change only when
7
+ * one of those additions needs them.
8
+ *
9
+ * The body is written before that relationships part, because a link asks for its relationship as
10
+ * it is written (`docx/hyperlink`), and both writers hand out ids through the one writer so that
11
+ * they cannot pick the same one.
12
+ */
13
+ import type { Node as PMNode } from "prosemirror-model";
14
+ import { type DocxSession } from "./session";
15
+ export declare function exportDocx(doc: PMNode, session: DocxSession): Uint8Array;