@a3s-lab/office 0.2.2 → 0.4.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 (277) hide show
  1. package/COLLABORATION_ROADMAP.md +426 -0
  2. package/README.md +649 -10
  3. package/dist/0~1403.js +1 -1
  4. package/dist/0~2805.js +1279 -0
  5. package/dist/{0~use-office-draft.js → 0~345.js} +30 -1
  6. package/dist/0~3539.js +1 -1
  7. package/dist/0~3557.js +1 -1
  8. package/dist/0~3635.js +1 -1
  9. package/dist/0~4595.js +123 -12
  10. package/dist/0~4980.js +154 -0
  11. package/dist/0~5050.js +124 -113
  12. package/dist/{0~9512.js → 0~6090.js} +540 -3
  13. package/dist/0~7048.js +92 -66
  14. package/dist/0~7614.js +2 -1
  15. package/dist/0~7754.js +5653 -0
  16. package/dist/0~9445.js +1 -1
  17. package/dist/0~document-editor.js +4992 -3323
  18. package/dist/0~markdown-editor.js +250 -44
  19. package/dist/0~pdf-viewer.js +1016 -24
  20. package/dist/0~presentation-editor.js +179 -8
  21. package/dist/0~spreadsheet-editor.js +3371 -578
  22. package/dist/0~work-docx-export.js +6801 -658
  23. package/dist/0~work-docx-import.js +1388 -795
  24. package/dist/0~work-office-diagnostics.js +524 -30
  25. package/dist/0~work-pptx-export.js +2 -1
  26. package/dist/0~work-pptx-import.js +1 -2
  27. package/dist/0~work-presentation-charts.js +1 -1
  28. package/dist/2591.js +197 -0
  29. package/dist/3818.js +1090 -0
  30. package/dist/4104.js +970 -60
  31. package/dist/432.js +171 -14
  32. package/dist/4476.js +2008 -0
  33. package/dist/4560.js +674 -0
  34. package/dist/4650.js +70 -0
  35. package/dist/{1134.js → 5184.js} +183 -1
  36. package/dist/6489.js +18 -18
  37. package/dist/7060.js +132 -0
  38. package/dist/8715.js +2 -136
  39. package/dist/8928.js +16778 -0
  40. package/dist/9787.js +209 -0
  41. package/dist/core.d.ts +29 -9
  42. package/dist/core.js +10 -2
  43. package/dist/index.js +13 -3
  44. package/dist/internal/collaboration/office-collaboration-flat-json.d.ts +13 -0
  45. package/dist/internal/collaboration/office-collaboration-json.d.ts +4 -0
  46. package/dist/internal/collaboration/office-collaboration-presence.d.ts +86 -0
  47. package/dist/internal/collaboration/office-collaboration-transport.d.ts +42 -0
  48. package/dist/internal/collaboration/office-collaboration.d.ts +85 -0
  49. package/dist/internal/collaboration/office-document-collaboration-bibliography.d.ts +7 -0
  50. package/dist/internal/collaboration/office-document-collaboration-claims.d.ts +9 -0
  51. package/dist/internal/collaboration/office-document-collaboration-comments.d.ts +7 -0
  52. package/dist/internal/collaboration/office-document-collaboration-sidecar-utils.d.ts +27 -0
  53. package/dist/internal/collaboration/office-document-collaboration-sidecars.d.ts +16 -0
  54. package/dist/internal/collaboration/office-document-collaboration.d.ts +45 -0
  55. package/dist/internal/collaboration/office-markdown-collaboration.d.ts +31 -0
  56. package/dist/internal/collaboration/office-pdf-collaboration-claims.d.ts +4 -0
  57. package/dist/internal/collaboration/office-pdf-collaboration-conflicts.d.ts +2 -0
  58. package/dist/internal/collaboration/office-pdf-collaboration-model.d.ts +26 -0
  59. package/dist/internal/collaboration/office-pdf-collaboration-records.d.ts +21 -0
  60. package/dist/internal/collaboration/office-pdf-collaboration-types.d.ts +91 -0
  61. package/dist/internal/collaboration/office-pdf-collaboration-validation.d.ts +4 -0
  62. package/dist/internal/collaboration/office-pdf-collaboration.d.ts +35 -0
  63. package/dist/internal/collaboration/office-presentation-collaboration-model.d.ts +25 -0
  64. package/dist/internal/collaboration/office-presentation-collaboration-records.d.ts +22 -0
  65. package/dist/internal/collaboration/office-presentation-collaboration-validation.d.ts +4 -0
  66. package/dist/internal/collaboration/office-presentation-collaboration.d.ts +32 -0
  67. package/dist/internal/collaboration/office-spreadsheet-collaboration-cells.d.ts +13 -0
  68. package/dist/internal/collaboration/office-spreadsheet-collaboration-claims.d.ts +4 -0
  69. package/dist/internal/collaboration/office-spreadsheet-collaboration-conflicts.d.ts +2 -0
  70. package/dist/internal/collaboration/office-spreadsheet-collaboration-flat-json.d.ts +10 -0
  71. package/dist/internal/collaboration/office-spreadsheet-collaboration-model.d.ts +31 -0
  72. package/dist/internal/collaboration/office-spreadsheet-collaboration-records.d.ts +17 -0
  73. package/dist/internal/collaboration/office-spreadsheet-collaboration-validation.d.ts +4 -0
  74. package/dist/internal/collaboration/office-spreadsheet-collaboration.d.ts +32 -0
  75. package/dist/internal/design-system/primitives/navigation/tabs.d.ts +3 -1
  76. package/dist/internal/features/work/components/work-document-page-border.d.ts +6 -0
  77. package/dist/internal/features/work/editors/document-command-catalog.d.ts +536 -0
  78. package/dist/internal/features/work/editors/document-editor-focus.d.ts +1 -1
  79. package/dist/internal/features/work/editors/document-editor-support.d.ts +7 -3
  80. package/dist/internal/features/work/editors/document-editor.d.ts +8 -2
  81. package/dist/internal/features/work/editors/document-external-content.d.ts +14 -0
  82. package/dist/internal/features/work/editors/document-format-clipboard.d.ts +6 -0
  83. package/dist/internal/features/work/editors/document-format-tools.d.ts +4 -0
  84. package/dist/internal/features/work/editors/document-layout-panel.d.ts +4 -1
  85. package/dist/internal/features/work/editors/document-page-chrome-wps-shortcuts.d.ts +2 -0
  86. package/dist/internal/features/work/editors/document-page-layout-ribbon.d.ts +14 -0
  87. package/dist/internal/features/work/editors/document-page-stack.d.ts +10 -1
  88. package/dist/internal/features/work/editors/document-page-thumbnail.d.ts +2 -0
  89. package/dist/internal/features/work/editors/document-pagination-run-coordinator.d.ts +26 -0
  90. package/dist/internal/features/work/editors/document-picture-properties-dialog-model.d.ts +20 -1
  91. package/dist/internal/features/work/editors/document-review-navigation.d.ts +9 -0
  92. package/dist/internal/features/work/editors/document-statistics-dialog.d.ts +7 -0
  93. package/dist/internal/features/work/editors/document-status-bar.d.ts +2 -1
  94. package/dist/internal/features/work/editors/document-table-properties-dialog-model.d.ts +4 -1
  95. package/dist/internal/features/work/editors/document-toolbar.d.ts +19 -42
  96. package/dist/internal/features/work/editors/document-wps-shortcuts.d.ts +12 -0
  97. package/dist/internal/features/work/editors/document-zoom.d.ts +17 -0
  98. package/dist/internal/features/work/editors/markdown-editor-focus.d.ts +1 -1
  99. package/dist/internal/features/work/editors/markdown-editor.d.ts +5 -1
  100. package/dist/internal/features/work/editors/markdown-toolbar.d.ts +2 -1
  101. package/dist/internal/features/work/editors/office-collaboration-participants.d.ts +3 -0
  102. package/dist/internal/features/work/editors/office-collaboration-presence-context.d.ts +17 -0
  103. package/dist/internal/features/work/editors/office-collaboration-presence-ui.d.ts +25 -0
  104. package/dist/internal/features/work/editors/office-editor-focus-handoff.d.ts +27 -0
  105. package/dist/internal/features/work/editors/pdf-annotation-controller.d.ts +5 -0
  106. package/dist/internal/features/work/editors/pdf-collaboration-presence.d.ts +3 -0
  107. package/dist/internal/features/work/editors/pdf-collaboration-projection.d.ts +10 -0
  108. package/dist/internal/features/work/editors/pdf-evidence-contract.d.ts +36 -0
  109. package/dist/internal/features/work/editors/pdf-evidence-overlay.d.ts +37 -0
  110. package/dist/internal/features/work/editors/pdf-toolbar.d.ts +2 -1
  111. package/dist/internal/features/work/editors/pdf-viewer-controller.d.ts +7 -1
  112. package/dist/internal/features/work/editors/pdf-viewer.d.ts +11 -1
  113. package/dist/internal/features/work/editors/presentation-collaboration-presence.d.ts +5 -0
  114. package/dist/internal/features/work/editors/presentation-editor-focus.d.ts +3 -2
  115. package/dist/internal/features/work/editors/presentation-editor-types.d.ts +3 -0
  116. package/dist/internal/features/work/editors/presentation-editor.d.ts +1 -1
  117. package/dist/internal/features/work/editors/spreadsheet-auto-filter.d.ts +9 -0
  118. package/dist/internal/features/work/editors/spreadsheet-cell-clear.d.ts +3 -0
  119. package/dist/internal/features/work/editors/spreadsheet-cell-merge.d.ts +12 -0
  120. package/dist/internal/features/work/editors/spreadsheet-clipboard-shortcuts.d.ts +3 -7
  121. package/dist/internal/features/work/editors/spreadsheet-collaboration-presence.d.ts +9 -0
  122. package/dist/internal/features/work/editors/spreadsheet-command-catalog.d.ts +464 -0
  123. package/dist/internal/features/work/editors/spreadsheet-command-controller.d.ts +45 -9
  124. package/dist/internal/features/work/editors/spreadsheet-context-menu.d.ts +2 -0
  125. package/dist/internal/features/work/editors/spreadsheet-editor-ribbon.d.ts +9 -28
  126. package/dist/internal/features/work/editors/spreadsheet-editor.d.ts +8 -2
  127. package/dist/internal/features/work/editors/spreadsheet-format-painter.d.ts +27 -0
  128. package/dist/internal/features/work/editors/spreadsheet-freeze-panes.d.ts +14 -0
  129. package/dist/internal/features/work/editors/use-document-insert-commands.d.ts +3 -2
  130. package/dist/internal/features/work/editors/use-document-pagination.d.ts +6 -1
  131. package/dist/internal/features/work/editors/use-document-review-conflicts.d.ts +28 -0
  132. package/dist/internal/features/work/editors/use-spreadsheet-auto-filter.d.ts +21 -0
  133. package/dist/internal/features/work/editors/use-spreadsheet-collaboration.d.ts +27 -0
  134. package/dist/internal/features/work/editors/use-spreadsheet-format-painter.d.ts +18 -0
  135. package/dist/internal/features/work/editors/work-office-chrome.d.ts +22 -3
  136. package/dist/internal/features/work/editors/work-office-ribbon-overflow.d.ts +2 -0
  137. package/dist/internal/features/work/work-document-bookmark-references.d.ts +37 -0
  138. package/dist/internal/features/work/work-document-bookmarks.d.ts +29 -0
  139. package/dist/internal/features/work/work-document-caption-nodes.d.ts +4 -1
  140. package/dist/internal/features/work/work-document-comments.d.ts +1 -1
  141. package/dist/internal/features/work/work-document-equations.d.ts +513 -0
  142. package/dist/internal/features/work/work-document-extensions.d.ts +1 -0
  143. package/dist/internal/features/work/work-document-field-identity.d.ts +2 -0
  144. package/dist/internal/features/work/work-document-field-node.d.ts +2 -2
  145. package/dist/internal/features/work/work-document-fields.d.ts +7 -0
  146. package/dist/internal/features/work/work-document-image-identity.d.ts +30 -0
  147. package/dist/internal/features/work/work-document-image-layout.d.ts +46 -1
  148. package/dist/internal/features/work/work-document-image-wrap-contour.d.ts +16 -0
  149. package/dist/internal/features/work/work-document-incremental-layout.d.ts +2 -2
  150. package/dist/internal/features/work/work-document-model-codec.d.ts +4 -1
  151. package/dist/internal/features/work/work-document-note-integrity.d.ts +2 -0
  152. package/dist/internal/features/work/work-document-page-borders.d.ts +25 -0
  153. package/dist/internal/features/work/work-document-page-capture.d.ts +8 -0
  154. package/dist/internal/features/work/work-document-page-frames.d.ts +15 -0
  155. package/dist/internal/features/work/work-document-page-margins.d.ts +56 -0
  156. package/dist/internal/features/work/work-document-page-size.d.ts +47 -0
  157. package/dist/internal/features/work/work-document-pagination-measurement.d.ts +1 -2
  158. package/dist/internal/features/work/work-document-pagination-types.d.ts +7 -2
  159. package/dist/internal/features/work/work-document-pagination.d.ts +2 -2
  160. package/dist/internal/features/work/work-document-paragraph-borders.d.ts +32 -0
  161. package/dist/internal/features/work/work-document-paragraph-identity.d.ts +26 -0
  162. package/dist/internal/features/work/work-document-paragraph-shading.d.ts +18 -0
  163. package/dist/internal/features/work/work-document-review-conflicts.d.ts +35 -0
  164. package/dist/internal/features/work/work-document-section.d.ts +4 -0
  165. package/dist/internal/features/work/work-document-snapshot.d.ts +19 -0
  166. package/dist/internal/features/work/work-document-source.d.ts +23 -0
  167. package/dist/internal/features/work/work-document-table-column-widths.d.ts +7 -0
  168. package/dist/internal/features/work/work-document-table-property-changes.d.ts +3 -0
  169. package/dist/internal/features/work/work-document-table-row-identity.d.ts +15 -0
  170. package/dist/internal/features/work/work-document-table-sizing.d.ts +3 -0
  171. package/dist/internal/features/work/work-document-text-layout.d.ts +3 -1
  172. package/dist/internal/features/work/work-document-word-line-metrics.d.ts +2 -0
  173. package/dist/internal/features/work/work-docx-bookmark-diagnostics.d.ts +3 -0
  174. package/dist/internal/features/work/work-docx-bookmark-import.d.ts +24 -0
  175. package/dist/internal/features/work/work-docx-bookmarks.d.ts +17 -0
  176. package/dist/internal/features/work/work-docx-comment-durable-id-preservation.d.ts +2 -0
  177. package/dist/internal/features/work/work-docx-comment-export.d.ts +3 -0
  178. package/dist/internal/features/work/work-docx-comment-metadata.d.ts +2 -0
  179. package/dist/internal/features/work/work-docx-drawing-extension-preservation.d.ts +4 -0
  180. package/dist/internal/features/work/work-docx-equation-diagnostics.d.ts +3 -0
  181. package/dist/internal/features/work/work-docx-equation-export.d.ts +14 -0
  182. package/dist/internal/features/work/work-docx-equation-import.d.ts +30 -0
  183. package/dist/internal/features/work/work-docx-equation-story.d.ts +9 -0
  184. package/dist/internal/features/work/work-docx-export-formatting.d.ts +3 -1
  185. package/dist/internal/features/work/work-docx-export-image.d.ts +5 -1
  186. package/dist/internal/features/work/work-docx-export.d.ts +1 -1
  187. package/dist/internal/features/work/work-docx-field-instructions.d.ts +8 -0
  188. package/dist/internal/features/work/work-docx-font-table-preservation.d.ts +3 -0
  189. package/dist/internal/features/work/work-docx-ignorable-extension-preservation.d.ts +15 -0
  190. package/dist/internal/features/work/work-docx-image-crop.d.ts +12 -0
  191. package/dist/internal/features/work/work-docx-image-identity.d.ts +17 -0
  192. package/dist/internal/features/work/work-docx-image-layer.d.ts +12 -0
  193. package/dist/internal/features/work/work-docx-image-layout-import.d.ts +14 -2
  194. package/dist/internal/features/work/work-docx-image-wrap.d.ts +15 -0
  195. package/dist/internal/features/work/work-docx-import.d.ts +13 -3
  196. package/dist/internal/features/work/work-docx-list-export.d.ts +18 -0
  197. package/dist/internal/features/work/work-docx-list-import.d.ts +14 -0
  198. package/dist/internal/features/work/work-docx-note-comment-content-control-block-preservation.d.ts +18 -0
  199. package/dist/internal/features/work/work-docx-note-comment-content-control-model.d.ts +47 -0
  200. package/dist/internal/features/work/work-docx-note-comment-content-control-preservation.d.ts +4 -0
  201. package/dist/internal/features/work/work-docx-note-comment-content-control-properties.d.ts +17 -0
  202. package/dist/internal/features/work/work-docx-note-comment-content-control-table-model.d.ts +17 -0
  203. package/dist/internal/features/work/work-docx-note-comment-content-control-xml.d.ts +14 -0
  204. package/dist/internal/features/work/work-docx-note-comment-extension-preservation.d.ts +2 -0
  205. package/dist/internal/features/work/work-docx-note-comment-hyperlink-content.d.ts +40 -0
  206. package/dist/internal/features/work/work-docx-note-comment-hyperlink-preservation.d.ts +5 -0
  207. package/dist/internal/features/work/work-docx-note-comment-hyperlink-relationships.d.ts +35 -0
  208. package/dist/internal/features/work/work-docx-note-comment-identity.d.ts +15 -0
  209. package/dist/internal/features/work/work-docx-note-comment-run-preservation.d.ts +4 -0
  210. package/dist/internal/features/work/work-docx-note-comment-run-properties.d.ts +2 -0
  211. package/dist/internal/features/work/work-docx-note-image-import.d.ts +12 -0
  212. package/dist/internal/features/work/work-docx-note-image-relationships.d.ts +1 -0
  213. package/dist/internal/features/work/work-docx-numbering-extension-preservation.d.ts +6 -0
  214. package/dist/internal/features/work/work-docx-numbering.d.ts +1 -0
  215. package/dist/internal/features/work/work-docx-page-borders-diagnostics.d.ts +3 -0
  216. package/dist/internal/features/work/work-docx-page-borders-import.d.ts +10 -0
  217. package/dist/internal/features/work/work-docx-page-margins-diagnostics.d.ts +3 -0
  218. package/dist/internal/features/work/work-docx-page-margins-import.d.ts +18 -0
  219. package/dist/internal/features/work/work-docx-page-size-diagnostics.d.ts +2 -0
  220. package/dist/internal/features/work/work-docx-page-size-import.d.ts +17 -0
  221. package/dist/internal/features/work/work-docx-paragraph-borders-diagnostics.d.ts +3 -0
  222. package/dist/internal/features/work/work-docx-paragraph-borders-export.d.ts +18 -0
  223. package/dist/internal/features/work/work-docx-paragraph-borders-import.d.ts +24 -0
  224. package/dist/internal/features/work/work-docx-paragraph-default-collapsed.d.ts +19 -0
  225. package/dist/internal/features/work/work-docx-paragraph-extension-preservation.d.ts +2 -0
  226. package/dist/internal/features/work/work-docx-paragraph-identity-import.d.ts +10 -0
  227. package/dist/internal/features/work/work-docx-paragraph-identity.d.ts +18 -0
  228. package/dist/internal/features/work/work-docx-paragraph-pagination-import.d.ts +6 -1
  229. package/dist/internal/features/work/work-docx-paragraph-shading-diagnostics.d.ts +3 -0
  230. package/dist/internal/features/work/work-docx-paragraph-shading-export.d.ts +5 -0
  231. package/dist/internal/features/work/work-docx-paragraph-shading-import.d.ts +18 -0
  232. package/dist/internal/features/work/work-docx-run-formatting-import.d.ts +3 -0
  233. package/dist/internal/features/work/work-docx-settings-preservation.d.ts +10 -0
  234. package/dist/internal/features/work/work-docx-settings-xml.d.ts +16 -0
  235. package/dist/internal/features/work/work-docx-style-extension-preservation.d.ts +2 -0
  236. package/dist/internal/features/work/work-docx-table-cell-export.d.ts +2 -1
  237. package/dist/internal/features/work/work-docx-table-cell-import.d.ts +3 -0
  238. package/dist/internal/features/work/work-docx-table-extension-preservation.d.ts +2 -0
  239. package/dist/internal/features/work/work-docx-table-row-import.d.ts +2 -0
  240. package/dist/internal/features/work/work-docx-table-sizing-import.d.ts +1 -0
  241. package/dist/internal/features/work/work-docx-theme-reference.d.ts +23 -0
  242. package/dist/internal/features/work/work-docx-theme.d.ts +4 -1
  243. package/dist/internal/features/work/work-docx-twips.d.ts +12 -0
  244. package/dist/internal/features/work/work-file-contract.d.ts +1 -0
  245. package/dist/internal/features/work/work-file-io.d.ts +1 -1
  246. package/dist/internal/features/work/work-markdown-extensions.d.ts +4 -1
  247. package/dist/internal/features/work/work-ooxml-package-preservation.d.ts +12 -0
  248. package/dist/internal/features/work/work-ooxml-package-security.d.ts +6 -0
  249. package/dist/internal/features/work/work-ooxml-relationship-preservation.d.ts +10 -0
  250. package/dist/internal/features/work/work-ooxml-xml.d.ts +2 -0
  251. package/dist/internal/features/work/work-pdf-export.d.ts +10 -0
  252. package/dist/internal/features/work/work-repository.d.ts +2 -0
  253. package/dist/internal/features/work/work-types.d.ts +15 -2
  254. package/dist/internal/kernel/office-kernel-client-types.d.ts +1 -0
  255. package/dist/internal/kernel/office-kernel-protocol.d.ts +7 -0
  256. package/dist/internal/kernel/office-kernel-version.d.ts +1 -1
  257. package/dist/office-kernel.wasm +0 -0
  258. package/dist/office-kernel.worker.js +93 -41
  259. package/dist/react.d.ts +18 -12
  260. package/dist/react.js +1 -1
  261. package/dist/styles.css +1367 -16
  262. package/dist/vue.d.ts +48 -5
  263. package/dist/vue.js +42 -3
  264. package/dist/web-component.d.ts +24 -2
  265. package/dist/web-component.js +101 -2
  266. package/docs/latest/en/browser-editor-architecture.md +262 -47
  267. package/package.json +29 -4
  268. package/dist/0~152.js +0 -94
  269. package/dist/0~2582.js +0 -485
  270. package/dist/0~4750.js +0 -939
  271. package/dist/0~5861.js +0 -596
  272. package/dist/0~work-document-extensions.js +0 -3045
  273. package/dist/0~work-document-model-codec.js +0 -42
  274. package/dist/0~work-docx-bibliography.js +0 -347
  275. package/dist/0~work-docx-page-color.js +0 -42
  276. package/dist/2881.js +0 -1455
  277. package/dist/8728.js +0 -723
@@ -1,13 +1,281 @@
1
1
  import jszip from "jszip";
2
- import { contentTypeForPart, directChildren, bytesToDataUrl, OoxmlPackage, firstDescendant, descendants, directChild, childPath, attribute } from "./8715.js";
3
- import { docxCaptionSequenceKind, docxFieldOccurrences, docxCaptionBookmark, docxFieldResultText, docxCaptionReferenceTarget } from "./0~152.js";
4
- import { documentContentLayoutProperties, documentPageChromeLegacyFields, normalizeDocumentFieldsHtml, documentInitialSectionLayout, documentSectionDomAttributes, documentCaptionLabel, normalizeDocumentPageChrome, normalizeDocumentCitationsHtml, normalizeDocumentColumns, normalizeDocumentCaptionsHtml, normalizeDocumentNotesHtml, documentCitationTagsFromInstruction, docxDocumentFieldKind, createDocumentNoteElement } from "./2881.js";
5
- import { renderDocumentTableBorders, renderDocumentTableCellMarginOverrides, normalizeDocumentImageAlignment, documentTableBordersFromElement, normalizeDocumentImageLayoutOptions, normalizeDocumentTabStops, DEFAULT_DOCUMENT_TABLE_GEOMETRY, DEFAULT_DOCUMENT_TABLE_CELL_MARGINS, serializeDocumentTabStops, applyDocumentTableGeometryToElement } from "./0~4750.js";
6
- import { normalizeDocumentParagraphIndent, documentAutoLineHeight, documentWordLineHeightFactor, renderDocumentAutoLineHeight } from "./0~5861.js";
7
- import { readDocxBibliography } from "./0~work-docx-bibliography.js";
8
- import { importDocxPageColor } from "./0~work-docx-page-color.js";
2
+ import { contentTypeForPart, directChildren, bytesToDataUrl, OoxmlPackage, firstDescendant, descendants, directChild, attribute } from "./5184.js";
3
+ import { normalizeDocumentBookmarkName, renderDocumentTableCellMarginOverrides, applyDocumentImageIdentityToElement, normalizeDocumentTabStops, createDocumentImageIdentityRegistry, normalizeDocumentColumns, normalizeDocumentImageWrapContour, DOCUMENT_TABLE_ROW_ID_ATTRIBUTE, normalizeDocumentBookmarksHtml, applyDocumentTableRowIdentityToElement, normalizeDocumentCaptionsHtml, normalizeDocumentImageAlignment, normalizeDocumentParagraphId, applyDocumentImageLayerToElement, normalizeDocumentNotesHtml, normalizeDocumentBookmarkReferencesHtml, documentCitationTagsFromInstruction, applyDocumentImageWrapContourToElement, renderDocumentAutoLineHeight, applyDocumentPageGeometry, normalizeDocumentPageChrome, normalizeDocumentImageLayoutOptions, applyDocumentImageCropToElement, documentPageMarginsForLayout, createDocumentNoteElement, serializeDocumentTabStops, normalizeDocumentImageLayer, DOCUMENT_TABLE_ROW_TEXT_ID_ATTRIBUTE, documentBookmarkReferenceInstruction, documentInitialSectionLayout, normalizeDocumentFieldsHtml, documentCaptionLabel, documentTableBordersFromElement, isContourImageLayout, normalizeDocumentCitationsHtml, normalizeDocumentImageIdentity, normalizeDocumentImageWrapSide, applyDocumentParagraphIdentityToElement, documentAutoLineHeight, docxDocumentFieldKind, serializeDocxThemeReference, renderDocumentTableBorders, docxBookmarkReferenceTarget, normalizeDocumentImagePosition, wrapsBesideImage, documentPageChromeLegacyFields, documentParagraphShadingDomAttributes, DEFAULT_DOCUMENT_TABLE_GEOMETRY, documentParagraphBordersDomAttributes, documentSectionDomAttributes, DEFAULT_DOCUMENT_TABLE_CELL_MARGINS, normalizeDocumentParagraphIdentity, documentPageMarginBody, normalizeDocumentParagraphIndent, normalizeDocumentTableRowIdentity, normalizeDocumentBookmarkNativeId, uniqueDocumentImageIdentity, applyDocumentTableGeometryToElement, normalizeDocumentImageCrop, documentContentLayoutProperties, documentWordLineHeightFactor } from "./8928.js";
4
+ import { parseDocxPageMargins, parseDocxPageGeometry, parseDocxPageBorders, docxCaptionReferenceTarget, applyImportedDocxEquationMarkers, createDocxTableStyleResolver, hasImportedDocxParagraphShadingMarkers, isDocxEquationLikeRoot, inspectDocxPageMarginSettings, docxTableRunPropertySources, docxParagraphPropertySources, docxCaptionSequenceKind, resolveDocxParagraphBordersForParagraph, applyImportedDocxParagraphShadingMarkers, hasImportedDocxParagraphBorderMarkers, docxCaptionBookmark, docxFieldResultText, resolveDocxParagraphStyleResolver, createDocxParagraphStyleResolver, docxEquationHtml, docxFieldOccurrences, docxTableParagraphPropertySources, resolveDocxTableStyleResolver, docxTableCellStyleLayers, markDocxParagraphBorders, docxFieldOccurrenceIsInlineEditable, applyImportedDocxParagraphBorderMarkers, parseDocxPaperSource, docxTablePropertySources, docxRunPropertySources, parseDirectDocxParagraphShading, markDocxParagraphShading, markDocxPackageEquations } from "./0~7754.js";
5
+ import { xmlAttributeLocalName, docxThemeFont, readDocxBibliography, createDocxThemeResolver, docxThemeColor, parseDocxParagraphDefaultCollapsed, resolveDocxThemeResolver, DOCX_WORDPROCESSING_NAMESPACES, xmlAttributeNamespace } from "./0~2805.js";
6
+ import { importDocxPageColor, importedDocumentNoteId } from "./0~4980.js";
9
7
  const WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
10
8
  const XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
9
+ const MAX_BOOKMARK_NAME_LENGTH = 40;
10
+ const MAX_BOOKMARK_NATIVE_ID = 0x7fffffff;
11
+ function markDocxBookmarks(document) {
12
+ const captionBookmarks = captionBookmarkStarts(document);
13
+ const captionNames = new Set(Array.from(captionBookmarks).map((bookmark)=>attribute(bookmark, 'name')?.trim().toLowerCase()).filter((name)=>Boolean(name)));
14
+ const pairs = docxBookmarkPairs(document).filter((pair)=>!captionBookmarks.has(pair.start) && '_GoBack' !== pair.sourceName);
15
+ const names = new Set();
16
+ const normalizedNames = new Map();
17
+ for(let index = pairs.length - 1; index >= 0; index -= 1){
18
+ const pair = pairs[index];
19
+ if (!pair) continue;
20
+ const base = normalizeDocumentBookmarkName(pair.sourceName) ?? safeImportedBookmarkName(pair.sourceName, index + 1);
21
+ const name = uniqueImportedBookmarkName(base, names);
22
+ names.add(name.toLowerCase());
23
+ normalizedNames.set(pair, name);
24
+ }
25
+ const nativeIds = new Set();
26
+ const internalIds = new Set();
27
+ const bookmarks = [];
28
+ for (const [index, pair] of pairs.entries()){
29
+ const preferredNativeId = normalizeDocumentBookmarkNativeId(pair.sourceNativeId);
30
+ const nativeId = null === preferredNativeId || nativeIds.has(preferredNativeId) ? nextNativeId(nativeIds) : preferredNativeId;
31
+ nativeIds.add(nativeId);
32
+ const name = normalizedNames.get(pair) ?? `Bookmark_${index + 1}`;
33
+ const id = uniqueImportedBookmarkId(name, nativeId, index + 1, internalIds);
34
+ internalIds.add(id);
35
+ const marker = importedBookmarkMarker(index + 1, id, name, pair.sourceName, nativeId, document.documentElement.textContent ?? '');
36
+ insertBoundaryMarker(document, pair.start, marker.start);
37
+ insertBoundaryMarker(document, pair.end, marker.end);
38
+ pair.start.remove();
39
+ pair.end.remove();
40
+ bookmarks.push(marker);
41
+ }
42
+ const targets = new Map();
43
+ for (const bookmark of bookmarks)targets.set(bookmark.sourceName.toLowerCase(), bookmark);
44
+ const references = docxFieldOccurrences(document).flatMap((field, index)=>{
45
+ const sourceTarget = docxBookmarkReferenceTarget(field.instruction);
46
+ const target = sourceTarget ? targets.get(sourceTarget.toLowerCase()) : null;
47
+ if (!sourceTarget || !target || captionNames.has(sourceTarget.toLowerCase()) || !canMarkField(field)) return [];
48
+ const marker = importedBookmarkReferenceMarker(index + 1, target, field.instruction, docxFieldResultText(field), document.documentElement.textContent ?? '');
49
+ insertFieldBoundaryMarkers(document, field, marker.start, marker.end);
50
+ return [
51
+ marker
52
+ ];
53
+ });
54
+ return {
55
+ bookmarks,
56
+ references
57
+ };
58
+ }
59
+ function applyImportedDocxBookmarkMarkers(document, markers) {
60
+ for (const reference of markers.references){
61
+ const element = document.createElement('span');
62
+ element.dataset.documentCrossReference = 'true';
63
+ element.dataset.referenceTargetType = 'bookmark';
64
+ element.dataset.referenceTargetId = reference.targetId;
65
+ element.dataset.referenceTargetName = reference.targetName;
66
+ element.dataset.referenceInstruction = reference.instruction;
67
+ const convertedDisplay = replaceBookmarkReferenceMarkerRange(document.body, reference.start, reference.end, element);
68
+ const display = reference.display.trim() || convertedDisplay.trim() || reference.targetName;
69
+ element.dataset.referenceDisplay = display;
70
+ element.className = 'work-document-cross-reference';
71
+ element.textContent = display;
72
+ }
73
+ const targetNames = new Map();
74
+ for (const bookmark of markers.bookmarks){
75
+ targetNames.set(bookmark.sourceName.toLowerCase(), bookmark.name);
76
+ replaceBookmarkMarker(document.body, bookmark.start, {
77
+ ...bookmark,
78
+ kind: 'start'
79
+ });
80
+ replaceBookmarkMarker(document.body, bookmark.end, {
81
+ ...bookmark,
82
+ kind: 'end'
83
+ });
84
+ }
85
+ for (const link of document.body.querySelectorAll('a[href^="#"]')){
86
+ const sourceName = (link.getAttribute('href') ?? '').slice(1);
87
+ const name = targetNames.get(sourceName.toLowerCase());
88
+ if (name) link.setAttribute('href', `#${name}`);
89
+ }
90
+ }
91
+ function hasImportedDocxBookmarkMarkers(markers) {
92
+ return markers.bookmarks.length > 0 || markers.references.length > 0;
93
+ }
94
+ function docxBookmarkPairs(document) {
95
+ const open = new Map();
96
+ const pairs = [];
97
+ for (const element of Array.from(document.getElementsByTagName('*'))){
98
+ if ('bookmarkStart' === element.localName) {
99
+ const id = attribute(element, 'id')?.trim() ?? '';
100
+ const stack = open.get(id) ?? [];
101
+ stack.push(element);
102
+ open.set(id, stack);
103
+ continue;
104
+ }
105
+ if ('bookmarkEnd' !== element.localName) continue;
106
+ const id = attribute(element, 'id')?.trim() ?? '';
107
+ const start = open.get(id)?.pop();
108
+ if (start) pairs.push({
109
+ start,
110
+ end: element,
111
+ sourceName: attribute(start, 'name')?.trim() ?? '',
112
+ sourceNativeId: id
113
+ });
114
+ }
115
+ pairs.sort((left, right)=>{
116
+ const position = left.start.compareDocumentPosition(right.start);
117
+ if (position & Node.DOCUMENT_POSITION_FOLLOWING) return -1;
118
+ if (position & Node.DOCUMENT_POSITION_PRECEDING) return 1;
119
+ return 0;
120
+ });
121
+ return pairs;
122
+ }
123
+ function captionBookmarkStarts(document) {
124
+ const bookmarks = new Set();
125
+ for (const paragraph of descendants(document, 'p'))for (const field of docxFieldOccurrences(paragraph)){
126
+ if (!docxCaptionSequenceKind(field.instruction)) continue;
127
+ const bookmark = docxCaptionBookmark(paragraph, field);
128
+ if (bookmark) bookmarks.add(bookmark);
129
+ }
130
+ return bookmarks;
131
+ }
132
+ function importedBookmarkMarker(index, id, name, sourceName, nativeId, occupiedText) {
133
+ const base = `${index}_${stableHash(`${id}:${name}`)}`;
134
+ let suffix = base;
135
+ let collision = 2;
136
+ while(occupiedText.includes(`__A3S_WORK_BOOKMARK_START_${suffix}__`) || occupiedText.includes(`__A3S_WORK_BOOKMARK_END_${suffix}__`)){
137
+ suffix = `${base}_${collision}`;
138
+ collision += 1;
139
+ }
140
+ return {
141
+ start: `__A3S_WORK_BOOKMARK_START_${suffix}__`,
142
+ end: `__A3S_WORK_BOOKMARK_END_${suffix}__`,
143
+ id,
144
+ name,
145
+ sourceName,
146
+ nativeId
147
+ };
148
+ }
149
+ function importedBookmarkReferenceMarker(index, target, sourceInstruction, display, occupiedText) {
150
+ const base = `${index}_${stableHash(`${target.id}:${sourceInstruction}`)}`;
151
+ let suffix = base;
152
+ let collision = 2;
153
+ while(occupiedText.includes(`__A3S_WORK_BOOKMARK_REFERENCE_START_${suffix}__`) || occupiedText.includes(`__A3S_WORK_BOOKMARK_REFERENCE_END_${suffix}__`)){
154
+ suffix = `${base}_${collision}`;
155
+ collision += 1;
156
+ }
157
+ return {
158
+ start: `__A3S_WORK_BOOKMARK_REFERENCE_START_${suffix}__`,
159
+ end: `__A3S_WORK_BOOKMARK_REFERENCE_END_${suffix}__`,
160
+ targetId: target.id,
161
+ targetName: target.name,
162
+ instruction: documentBookmarkReferenceInstruction(target.name, sourceInstruction),
163
+ display
164
+ };
165
+ }
166
+ function insertBoundaryMarker(document, boundary, marker) {
167
+ boundary.parentNode?.insertBefore(work_docx_bookmark_import_markerRun(document, marker), boundary);
168
+ }
169
+ function insertFieldBoundaryMarkers(document, field, start, end) {
170
+ if ('fldChar' === field.start.localName && 'fldChar' === field.end.localName) {
171
+ field.start.parentNode?.insertBefore(markerText(document, start), field.start);
172
+ field.end.parentNode?.insertBefore(markerText(document, end), field.end.nextSibling);
173
+ return;
174
+ }
175
+ field.start.parentNode?.insertBefore(work_docx_bookmark_import_markerRun(document, start), field.start);
176
+ field.end.parentNode?.insertBefore(work_docx_bookmark_import_markerRun(document, end), field.end.nextSibling);
177
+ }
178
+ function work_docx_bookmark_import_markerRun(document, marker) {
179
+ const run = document.createElementNS(WORD_NAMESPACE, 'w:r');
180
+ run.append(markerText(document, marker));
181
+ return run;
182
+ }
183
+ function markerText(document, marker) {
184
+ const text = document.createElementNS(WORD_NAMESPACE, 'w:t');
185
+ text.setAttributeNS(XML_NAMESPACE, 'xml:space', 'preserve');
186
+ text.textContent = marker;
187
+ return text;
188
+ }
189
+ function replaceBookmarkMarker(root, marker, bookmark) {
190
+ const text = textNodes(root).find((node)=>node.data.includes(marker));
191
+ if (!text) return false;
192
+ const offset = text.data.indexOf(marker);
193
+ const element = root.ownerDocument.createElement('span');
194
+ element.dataset.documentBookmarkBoundary = 'true';
195
+ element.dataset.bookmarkKind = bookmark.kind;
196
+ element.dataset.bookmarkId = bookmark.id;
197
+ element.dataset.bookmarkName = bookmark.name;
198
+ element.dataset.officeBookmarkId = String(bookmark.nativeId);
199
+ element.className = `work-document-bookmark-boundary ${bookmark.kind}`;
200
+ element.contentEditable = 'false';
201
+ element.setAttribute('aria-hidden', 'true');
202
+ if ('start' === bookmark.kind) element.id = bookmark.name;
203
+ const before = text.data.slice(0, offset);
204
+ const after = text.data.slice(offset + marker.length);
205
+ const fragment = root.ownerDocument.createDocumentFragment();
206
+ if (before) fragment.append(root.ownerDocument.createTextNode(before));
207
+ fragment.append(element);
208
+ if (after) fragment.append(root.ownerDocument.createTextNode(after));
209
+ text.replaceWith(fragment);
210
+ return true;
211
+ }
212
+ function replaceBookmarkReferenceMarkerRange(root, start, end, replacement) {
213
+ const nodes = textNodes(root);
214
+ const startNode = nodes.find((node)=>node.data.includes(start));
215
+ const endNode = nodes.find((node)=>node.data.includes(end));
216
+ if (!startNode || !endNode) return '';
217
+ const range = root.ownerDocument.createRange();
218
+ range.setStart(startNode, startNode.data.indexOf(start));
219
+ range.setEnd(endNode, endNode.data.indexOf(end) + end.length);
220
+ const content = range.cloneContents();
221
+ removeMarkerText(content, start);
222
+ removeMarkerText(content, end);
223
+ const display = content.textContent ?? '';
224
+ range.deleteContents();
225
+ range.insertNode(replacement);
226
+ return display;
227
+ }
228
+ function removeMarkerText(root, marker) {
229
+ for (const node of textNodes(root))node.data = node.data.replace(marker, '');
230
+ }
231
+ function canMarkField(field) {
232
+ return field.start !== field.end || 'fldSimple' === field.start.localName;
233
+ }
234
+ function safeImportedBookmarkName(source, index) {
235
+ const characters = Array.from(source.trim()).map((character)=>/^[\p{L}\p{N}_]$/u.test(character) ? character : '_').join('');
236
+ const leading = /^[\p{L}_]/u.test(characters) ? characters : `Bookmark_${characters}`;
237
+ return Array.from(leading || `Bookmark_${index}`).slice(0, MAX_BOOKMARK_NAME_LENGTH).join('') || `Bookmark_${index}`;
238
+ }
239
+ function uniqueImportedBookmarkName(base, names) {
240
+ if (!names.has(base.toLowerCase())) return base;
241
+ let suffix = 2;
242
+ while(suffix <= MAX_BOOKMARK_NATIVE_ID){
243
+ const ending = `_${suffix}`;
244
+ const prefix = Array.from(base).slice(0, MAX_BOOKMARK_NAME_LENGTH - ending.length).join('');
245
+ const candidate = `${prefix}${ending}`;
246
+ if (!names.has(candidate.toLowerCase())) return candidate;
247
+ suffix += 1;
248
+ }
249
+ throw new Error('No unique imported Word bookmark name is available.');
250
+ }
251
+ function uniqueImportedBookmarkId(name, nativeId, index, ids) {
252
+ const base = `docx-bookmark-${nativeId}-${stableHash(name)}`;
253
+ if (!ids.has(base)) return base;
254
+ let suffix = index;
255
+ while(ids.has(`${base}-${suffix}`))suffix += 1;
256
+ return `${base}-${suffix}`;
257
+ }
258
+ function nextNativeId(ids) {
259
+ for(let id = 0; id <= MAX_BOOKMARK_NATIVE_ID; id += 1)if (!ids.has(id)) return id;
260
+ throw new Error('No unique imported Word bookmark identifier is available.');
261
+ }
262
+ function stableHash(source) {
263
+ let hash = 0x811c9dc5;
264
+ for(let index = 0; index < source.length; index += 1){
265
+ hash ^= source.charCodeAt(index);
266
+ hash = Math.imul(hash, 0x01000193);
267
+ }
268
+ return (hash >>> 0).toString(36);
269
+ }
270
+ function textNodes(root) {
271
+ const walker = root.ownerDocument?.createTreeWalker(root, NodeFilter.SHOW_TEXT);
272
+ const nodes = [];
273
+ if (!walker) return nodes;
274
+ while(walker.nextNode())nodes.push(walker.currentNode);
275
+ return nodes;
276
+ }
277
+ const work_docx_caption_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
278
+ const work_docx_caption_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
11
279
  function markDocxCaptionFields(document) {
12
280
  const captions = [];
13
281
  const bookmarkTargets = new Map();
@@ -32,7 +300,7 @@ function markDocxCaptionFields(document) {
32
300
  const targetId = bookmarkName ? bookmarkTargets.get(bookmarkName) : void 0;
33
301
  if (!targetId) continue;
34
302
  const marker = referenceMarker(references.length + 1, targetId);
35
- insertFieldBoundaryMarkers(document, field, marker.start, marker.end);
303
+ work_docx_caption_import_insertFieldBoundaryMarkers(document, field, marker.start, marker.end);
36
304
  references.push(marker);
37
305
  }
38
306
  return {
@@ -50,8 +318,8 @@ function applyImportedDocxCaptionMarkers(document, markers) {
50
318
  for (const caption of markers.captions){
51
319
  const block = markerBlock(document.body, caption.start, caption.end);
52
320
  if (!block) continue;
53
- removeMarkerText(block, caption.start);
54
- removeMarkerText(block, caption.end);
321
+ work_docx_caption_import_removeMarkerText(block, caption.start);
322
+ work_docx_caption_import_removeMarkerText(block, caption.end);
55
323
  removeCaptionPrefix(block, caption.kind);
56
324
  const element = document.createElement('figcaption');
57
325
  element.dataset.documentCaption = 'true';
@@ -93,29 +361,29 @@ function insertParagraphBoundaryMarkers(document, paragraph, start, end) {
93
361
  paragraph.insertBefore(work_docx_caption_import_markerRun(document, start), firstContent ?? null);
94
362
  paragraph.append(work_docx_caption_import_markerRun(document, end));
95
363
  }
96
- function insertFieldBoundaryMarkers(document, field, start, end) {
364
+ function work_docx_caption_import_insertFieldBoundaryMarkers(document, field, start, end) {
97
365
  if ('fldChar' === field.start.localName && 'fldChar' === field.end.localName) {
98
- field.start.parentNode?.insertBefore(markerText(document, start), field.start);
99
- field.end.parentNode?.insertBefore(markerText(document, end), field.end.nextSibling);
366
+ field.start.parentNode?.insertBefore(work_docx_caption_import_markerText(document, start), field.start);
367
+ field.end.parentNode?.insertBefore(work_docx_caption_import_markerText(document, end), field.end.nextSibling);
100
368
  return;
101
369
  }
102
370
  field.start.parentNode?.insertBefore(work_docx_caption_import_markerRun(document, start), field.start);
103
371
  field.end.parentNode?.insertBefore(work_docx_caption_import_markerRun(document, end), field.end.nextSibling);
104
372
  }
105
373
  function work_docx_caption_import_markerRun(document, text) {
106
- const run = document.createElementNS(WORD_NAMESPACE, 'w:r');
107
- run.append(markerText(document, text));
374
+ const run = document.createElementNS(work_docx_caption_import_WORD_NAMESPACE, 'w:r');
375
+ run.append(work_docx_caption_import_markerText(document, text));
108
376
  return run;
109
377
  }
110
- function markerText(document, text) {
111
- const value = document.createElementNS(WORD_NAMESPACE, 'w:t');
112
- value.setAttributeNS(XML_NAMESPACE, 'xml:space', 'preserve');
378
+ function work_docx_caption_import_markerText(document, text) {
379
+ const value = document.createElementNS(work_docx_caption_import_WORD_NAMESPACE, 'w:t');
380
+ value.setAttributeNS(work_docx_caption_import_XML_NAMESPACE, 'xml:space', 'preserve');
113
381
  value.textContent = text;
114
382
  return value;
115
383
  }
116
384
  function markerBlock(root, start, end) {
117
- const startNode = textNodes(root).find((node)=>node.data.includes(start));
118
- const endNode = textNodes(root).find((node)=>node.data.includes(end));
385
+ const startNode = work_docx_caption_import_textNodes(root).find((node)=>node.data.includes(start));
386
+ const endNode = work_docx_caption_import_textNodes(root).find((node)=>node.data.includes(end));
119
387
  if (!startNode || !endNode) return null;
120
388
  let current = startNode.parentElement;
121
389
  while(current && current !== root){
@@ -125,7 +393,7 @@ function markerBlock(root, start, end) {
125
393
  return null;
126
394
  }
127
395
  function replaceMarkerRange(root, start, end, replacement) {
128
- const nodes = textNodes(root);
396
+ const nodes = work_docx_caption_import_textNodes(root);
129
397
  const startNode = nodes.find((node)=>node.data.includes(start));
130
398
  const endNode = nodes.find((node)=>node.data.includes(end));
131
399
  if (!startNode || !endNode) return false;
@@ -136,8 +404,8 @@ function replaceMarkerRange(root, start, end, replacement) {
136
404
  range.insertNode(replacement);
137
405
  return true;
138
406
  }
139
- function removeMarkerText(root, marker) {
140
- for (const node of textNodes(root))node.data = node.data.replace(marker, '');
407
+ function work_docx_caption_import_removeMarkerText(root, marker) {
408
+ for (const node of work_docx_caption_import_textNodes(root))node.data = node.data.replace(marker, '');
141
409
  }
142
410
  function removeCaptionPrefix(root, kind) {
143
411
  const label = documentCaptionLabel(kind);
@@ -146,14 +414,14 @@ function removeCaptionPrefix(root, kind) {
146
414
  const match = expression.exec(source);
147
415
  if (!match || !source.trimStart().startsWith(label) && !/^(?:Figure|Fig|Table)/i.test(source.trimStart())) return;
148
416
  let remaining = match[0].length;
149
- for (const node of textNodes(root)){
417
+ for (const node of work_docx_caption_import_textNodes(root)){
150
418
  if (remaining <= 0) break;
151
419
  const removed = Math.min(remaining, node.data.length);
152
420
  node.data = node.data.slice(removed);
153
421
  remaining -= removed;
154
422
  }
155
423
  }
156
- function textNodes(root) {
424
+ function work_docx_caption_import_textNodes(root) {
157
425
  const walker = root.ownerDocument?.createTreeWalker(root, NodeFilter.SHOW_TEXT);
158
426
  const nodes = [];
159
427
  if (!walker) return nodes;
@@ -298,7 +566,7 @@ function markDocxCitationFields(document) {
298
566
  const citations = [];
299
567
  const bibliographies = [];
300
568
  for (const field of docxFieldOccurrences(document)){
301
- if (!canMarkField(field)) continue;
569
+ if (!work_docx_citation_import_canMarkField(field)) continue;
302
570
  const tags = documentCitationTagsFromInstruction(field.instruction);
303
571
  if (tags.length) {
304
572
  const index = citations.length + 1;
@@ -349,7 +617,7 @@ function applyImportedDocxCitationMarkers(document, markers) {
349
617
  function hasImportedDocxCitationMarkers(markers) {
350
618
  return markers.citations.length > 0 || markers.bibliographies.length > 0;
351
619
  }
352
- function canMarkField(field) {
620
+ function work_docx_citation_import_canMarkField(field) {
353
621
  return field.start !== field.end || 'fldSimple' === field.start.localName;
354
622
  }
355
623
  function work_docx_citation_import_insertFieldBoundaryMarkers(document, field, start, end) {
@@ -439,6 +707,45 @@ function work_docx_citation_import_textNodes(root) {
439
707
  while(walker.nextNode())nodes.push(walker.currentNode);
440
708
  return nodes;
441
709
  }
710
+ const TWIPS_PER_MILLIMETER = 1440 / 25.4;
711
+ function importDocxColumns(element, fallback) {
712
+ const columnElements = directChildren(element, 'col');
713
+ const sourceCount = numberAttribute(element, 'num') || columnElements.length || fallback.count;
714
+ const count = Math.min(6, Math.max(1, sourceCount));
715
+ const spacingAttribute = attribute(element, 'space');
716
+ const spacing = null === spacingAttribute ? fallback.spacing : twipsToMillimeters(Number(spacingAttribute), fallback.spacing);
717
+ const base = {
718
+ count,
719
+ spacing,
720
+ separator: enabledAttribute(element, 'sep')
721
+ };
722
+ if (!columnElements.length) return normalizeDocumentColumns(base);
723
+ return normalizeDocumentColumns({
724
+ ...base,
725
+ count: Math.min(count, columnElements.length),
726
+ custom: columnElements.slice(0, count).map((column, index)=>{
727
+ const columnSpacing = attribute(column, 'space');
728
+ return {
729
+ widthPercent: Math.max(1, numberAttribute(column, 'w')),
730
+ spacing: index === Math.min(count, columnElements.length) - 1 ? 0 : null === columnSpacing ? spacing : twipsToMillimeters(Number(columnSpacing), spacing)
731
+ };
732
+ })
733
+ });
734
+ }
735
+ function numberAttribute(element, name) {
736
+ const value = Number(attribute(element, name));
737
+ return Number.isFinite(value) ? value : 0;
738
+ }
739
+ function enabledAttribute(element, name) {
740
+ const value = attribute(element, name)?.toLowerCase();
741
+ return '1' === value || 'true' === value || 'on' === value;
742
+ }
743
+ function twipsToMillimeters(value, fallback) {
744
+ return Number.isFinite(value) ? roundOne(Math.max(0, value) / TWIPS_PER_MILLIMETER) : fallback;
745
+ }
746
+ function roundOne(value) {
747
+ return Math.round(10 * value) / 10;
748
+ }
442
749
  const work_docx_comment_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
443
750
  const work_docx_comment_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
444
751
  async function markDocxComments(document, archive) {
@@ -641,51 +948,12 @@ function work_docx_comment_import_compareDocumentOrder(left, right) {
641
948
  if (left === right) return 0;
642
949
  return left.compareDocumentPosition(right) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;
643
950
  }
644
- const TWIPS_PER_MILLIMETER = 1440 / 25.4;
645
- function importDocxColumns(element, fallback) {
646
- const columnElements = directChildren(element, 'col');
647
- const sourceCount = numberAttribute(element, 'num') || columnElements.length || fallback.count;
648
- const count = Math.min(6, Math.max(1, sourceCount));
649
- const spacingAttribute = attribute(element, 'space');
650
- const spacing = null === spacingAttribute ? fallback.spacing : twipsToMillimeters(Number(spacingAttribute), fallback.spacing);
651
- const base = {
652
- count,
653
- spacing,
654
- separator: enabledAttribute(element, 'sep')
655
- };
656
- if (!columnElements.length) return normalizeDocumentColumns(base);
657
- return normalizeDocumentColumns({
658
- ...base,
659
- count: Math.min(count, columnElements.length),
660
- custom: columnElements.slice(0, count).map((column, index)=>{
661
- const columnSpacing = attribute(column, 'space');
662
- return {
663
- widthPercent: Math.max(1, numberAttribute(column, 'w')),
664
- spacing: index === Math.min(count, columnElements.length) - 1 ? 0 : null === columnSpacing ? spacing : twipsToMillimeters(Number(columnSpacing), spacing)
665
- };
666
- })
667
- });
668
- }
669
- function numberAttribute(element, name) {
670
- const value = Number(attribute(element, name));
671
- return Number.isFinite(value) ? value : 0;
672
- }
673
- function enabledAttribute(element, name) {
674
- const value = attribute(element, name)?.toLowerCase();
675
- return '1' === value || 'true' === value || 'on' === value;
676
- }
677
- function twipsToMillimeters(value, fallback) {
678
- return Number.isFinite(value) ? roundOne(Math.max(0, value) / TWIPS_PER_MILLIMETER) : fallback;
679
- }
680
- function roundOne(value) {
681
- return Math.round(10 * value) / 10;
682
- }
683
951
  const work_docx_field_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
684
952
  const work_docx_field_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
685
953
  function markDocxBodyFields(document) {
686
954
  const fields = docxFieldOccurrences(document).flatMap((field, index)=>{
687
955
  const kind = docxDocumentFieldKind(field.instruction);
688
- if (!kind || !work_docx_field_import_canMarkField(field)) return [];
956
+ if (!kind || !docxFieldOccurrenceIsInlineEditable(field)) return [];
689
957
  const marker = {
690
958
  start: `__A3S_WORK_FIELD_START_${index + 1}__`,
691
959
  end: `__A3S_WORK_FIELD_END_${index + 1}__`,
@@ -719,9 +987,6 @@ function applyImportedDocxFieldMarkers(document, markers) {
719
987
  function hasImportedDocxFieldMarkers(markers) {
720
988
  return markers.fields.length > 0;
721
989
  }
722
- function work_docx_field_import_canMarkField(field) {
723
- return field.start !== field.end || 'fldSimple' === field.start.localName;
724
- }
725
990
  function work_docx_field_import_insertFieldBoundaryMarkers(document, field, start, end) {
726
991
  if ('fldChar' === field.start.localName && 'fldChar' === field.end.localName) {
727
992
  field.start.parentNode?.insertBefore(work_docx_field_import_markerText(document, start), field.start);
@@ -769,68 +1034,262 @@ function work_docx_field_import_textNodes(root) {
769
1034
  while(walker.nextNode())nodes.push(walker.currentNode);
770
1035
  return nodes;
771
1036
  }
772
- function extractMammothDocumentNotes(document) {
773
- const definitions = extractDefinitions(document);
774
- const notes = new Map();
775
- const counters = {
776
- footnote: 0,
777
- endnote: 0
1037
+ const work_docx_image_layout_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
1038
+ const work_docx_image_layout_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
1039
+ const EMUS_PER_MILLIMETER = 36000;
1040
+ const IMAGE_LAYOUT_MARKER_PATTERN = /__A3S_WORK_IMAGE_LAYOUT_\d+_(?:START|END)__/g;
1041
+ const MAX_IMPORTED_IMAGE_LAYOUTS = 4096;
1042
+ function createImportedDocxImageLayoutMarkerState() {
1043
+ return {
1044
+ identityRegistry: createDocumentImageIdentityRegistry(),
1045
+ nextMarker: 1
778
1046
  };
779
- const references = Array.from(document.body.querySelectorAll('a[href^="#footnote-"], a[href^="#endnote-"]'));
780
- for (const reference of references){
781
- const target = reference.getAttribute('href')?.slice(1) ?? '';
782
- const kind = noteKindFromTarget(target);
783
- if (!kind) continue;
784
- let note = notes.get(target);
785
- if (!note) {
786
- counters[kind] += 1;
787
- note = {
788
- id: `document-${kind}-${counters[kind]}`,
789
- kind,
790
- number: counters[kind],
791
- html: definitions.get(target) ?? '<p></p>'
792
- };
793
- notes.set(target, note);
794
- }
795
- const marker = document.createElement('sup');
796
- marker.setAttribute('data-document-note-reference', 'true');
797
- marker.setAttribute('data-note-kind', note.kind);
798
- marker.setAttribute('data-note-id', note.id);
799
- marker.setAttribute('data-note-number', String(note.number));
800
- marker.textContent = String(note.number);
801
- const wrapper = reference.parentElement;
802
- if (wrapper?.tagName.toLowerCase() === 'sup' && 1 === wrapper.childNodes.length) wrapper.replaceWith(marker);
803
- else reference.replaceWith(marker);
804
- }
805
- return Array.from(notes.values());
806
1047
  }
807
- function placeMammothDocumentNotes(document, notes) {
808
- const sections = Array.from(document.body.querySelectorAll('section[data-document-section]'));
809
- for (const note of notes){
810
- const reference = Array.from(document.body.querySelectorAll('sup[data-document-note-reference]')).find((element)=>element.dataset.noteKind === note.kind && element.dataset.noteId === note.id);
811
- const target = 'footnote' === note.kind ? reference?.closest('section[data-document-section]') : sections.at(-1);
812
- (target ?? document.body).append(createDocumentNoteElement(document, note));
1048
+ function markDocxImageLayouts(document, state = createImportedDocxImageLayoutMarkerState()) {
1049
+ const images = [];
1050
+ const markedRuns = new Set();
1051
+ const drawings = [
1052
+ ...descendants(document, 'anchor'),
1053
+ ...descendants(document, 'inline')
1054
+ ];
1055
+ for (const anchor of drawings){
1056
+ const run = closestAncestor(anchor, 'r');
1057
+ if (!run || markedRuns.has(run)) continue;
1058
+ const crop = anchorCrop(anchor);
1059
+ const layout = 'inline' === anchor.localName ? 'inline' : anchorLayout(anchor);
1060
+ if (!layout) continue;
1061
+ if (state.nextMarker > MAX_IMPORTED_IMAGE_LAYOUTS) throw new Error('Imported DOCX exceeds the image-layout limit.');
1062
+ markedRuns.add(run);
1063
+ const index = state.nextMarker;
1064
+ state.nextMarker += 1;
1065
+ const startMarker = `__A3S_WORK_IMAGE_LAYOUT_${index}_START__`;
1066
+ const endMarker = `__A3S_WORK_IMAGE_LAYOUT_${index}_END__`;
1067
+ insertMarkerRun(document, run, startMarker, 'before');
1068
+ insertMarkerRun(document, run, endMarker, 'after');
1069
+ images.push({
1070
+ startMarker,
1071
+ endMarker,
1072
+ options: normalizeDocumentImageLayoutOptions({
1073
+ layout,
1074
+ alignment: anchorAlignment(anchor),
1075
+ wrapDistance: anchorWrapDistance(anchor, layout),
1076
+ wrapSide: anchorWrapSide(anchor, layout)
1077
+ }),
1078
+ position: anchorPosition(anchor),
1079
+ crop,
1080
+ contour: isContourImageLayout(layout) ? anchorWrapContour(anchor, layout) : null,
1081
+ layer: 'anchor' === anchor.localName ? anchorLayer(anchor) : null,
1082
+ identity: uniqueDocumentImageIdentity(drawingIdentitySource(anchor), state.identityRegistry)
1083
+ });
813
1084
  }
1085
+ return {
1086
+ images
1087
+ };
814
1088
  }
815
- function extractDefinitions(document) {
816
- const definitions = new Map();
817
- const elements = Array.from(document.body.querySelectorAll('li[id^="footnote-"], li[id^="endnote-"]'));
818
- for (const element of elements){
819
- const id = element.id;
820
- const clone = element.cloneNode(true);
821
- for (const backlink of Array.from(clone.querySelectorAll('a[href^="#footnote-ref-"], a[href^="#endnote-ref-"]')))backlink.remove();
822
- definitions.set(id, clone.innerHTML.trim() || '<p></p>');
823
- const parent = element.parentElement;
824
- element.remove();
825
- if (parent && !parent.children.length) parent.remove();
1089
+ function applyImportedDocxImageLayoutMarkers(document, markers) {
1090
+ const starts = new Map(markers.images.map((image)=>[
1091
+ image.startMarker,
1092
+ image
1093
+ ]));
1094
+ const ends = new Set(markers.images.map((image)=>image.endMarker));
1095
+ const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT);
1096
+ const nodes = [];
1097
+ while(walker.nextNode())nodes.push(walker.currentNode);
1098
+ const state = {
1099
+ active: null,
1100
+ applied: false
1101
+ };
1102
+ for (const node of nodes){
1103
+ if (node instanceof Text) {
1104
+ node.data = node.data.replace(IMAGE_LAYOUT_MARKER_PATTERN, (marker)=>{
1105
+ const start = starts.get(marker);
1106
+ if (start) {
1107
+ state.active = start;
1108
+ state.applied = false;
1109
+ } else if (ends.has(marker)) {
1110
+ state.active = null;
1111
+ state.applied = false;
1112
+ }
1113
+ return '';
1114
+ });
1115
+ continue;
1116
+ }
1117
+ if (!state.applied && state.active && node instanceof HTMLImageElement) {
1118
+ applyImageLayout(node, state.active.options, state.active.position, state.active.crop, state.active.contour, state.active.layer, state.active.identity);
1119
+ state.applied = true;
1120
+ }
826
1121
  }
827
- return definitions;
1122
+ document.body.normalize();
828
1123
  }
829
- function noteKindFromTarget(target) {
830
- if (target.startsWith('footnote-')) return 'footnote';
831
- if (target.startsWith('endnote-')) return 'endnote';
1124
+ function hasImportedDocxImageLayoutMarkers(markers) {
1125
+ return markers.images.length > 0;
1126
+ }
1127
+ function anchorLayout(anchor) {
1128
+ if (directChild(anchor, 'wrapNone')) return 'none';
1129
+ if (directChild(anchor, 'wrapTopAndBottom')) return 'topBottom';
1130
+ if (directChild(anchor, 'wrapSquare')) return 'square';
1131
+ if (directChild(anchor, 'wrapTight')) return 'tight';
1132
+ if (directChild(anchor, 'wrapThrough')) return 'through';
832
1133
  return null;
833
1134
  }
1135
+ function anchorAlignment(anchor) {
1136
+ const position = directChild(anchor, 'positionH');
1137
+ const alignment = position ? directChild(position, 'align') : void 0;
1138
+ const value = alignment?.textContent?.trim();
1139
+ if ('inside' === value) return 'left';
1140
+ if ('outside' === value) return 'right';
1141
+ return normalizeDocumentImageAlignment(value);
1142
+ }
1143
+ function anchorWrapDistance(anchor, layout) {
1144
+ const wrap = anchorWrapElement(anchor, layout);
1145
+ const names = 'topBottom' === layout ? [
1146
+ 'distT',
1147
+ 'distB'
1148
+ ] : [
1149
+ 'distL',
1150
+ 'distR'
1151
+ ];
1152
+ const distance = Math.max(0, ...names.flatMap((name)=>[
1153
+ numericAttribute(wrap, name) ?? 0,
1154
+ numericAttribute(anchor, name) ?? 0
1155
+ ]));
1156
+ return distance / EMUS_PER_MILLIMETER;
1157
+ }
1158
+ function anchorWrapSide(anchor, layout) {
1159
+ return normalizeDocumentImageWrapSide(attribute(anchorWrapElement(anchor, layout) ?? anchor, 'wrapText'));
1160
+ }
1161
+ function anchorWrapElement(anchor, layout) {
1162
+ if ('square' === layout) return directChild(anchor, 'wrapSquare');
1163
+ if ('tight' === layout) return directChild(anchor, 'wrapTight');
1164
+ if ('through' === layout) return directChild(anchor, 'wrapThrough');
1165
+ if ('topBottom' === layout) return directChild(anchor, 'wrapTopAndBottom');
1166
+ if ('none' === layout) return directChild(anchor, 'wrapNone');
1167
+ }
1168
+ function anchorWrapContour(anchor, layout) {
1169
+ const wrap = anchorWrapElement(anchor, layout);
1170
+ const polygon = wrap ? directChild(wrap, 'wrapPolygon') : void 0;
1171
+ if (!polygon) return null;
1172
+ const vertices = directChildren(polygon);
1173
+ if (vertices[0]?.localName !== 'start' || vertices.slice(1).some((element)=>'lineTo' !== element.localName)) return null;
1174
+ return normalizeDocumentImageWrapContour({
1175
+ edited: attribute(polygon, 'edited'),
1176
+ points: vertices.map((point)=>({
1177
+ x: attribute(point, 'x'),
1178
+ y: attribute(point, 'y')
1179
+ }))
1180
+ });
1181
+ }
1182
+ function anchorPosition(anchor) {
1183
+ const horizontal = directChild(anchor, 'positionH');
1184
+ const vertical = directChild(anchor, 'positionV');
1185
+ const horizontalOffset = positionOffset(horizontal);
1186
+ const verticalOffset = positionOffset(vertical);
1187
+ if (null === horizontalOffset && null === verticalOffset) return null;
1188
+ return normalizeDocumentImagePosition({
1189
+ horizontalOffset,
1190
+ verticalOffset,
1191
+ horizontalReference: horizontal ? attribute(horizontal, 'relativeFrom') : null,
1192
+ verticalReference: vertical ? attribute(vertical, 'relativeFrom') : null
1193
+ });
1194
+ }
1195
+ function anchorCrop(anchor) {
1196
+ const source = descendants(anchor, 'srcRect')[0];
1197
+ if (!source) return null;
1198
+ return normalizeDocumentImageCrop({
1199
+ cropTop: cropPercentage(source, 't'),
1200
+ cropRight: cropPercentage(source, 'r'),
1201
+ cropBottom: cropPercentage(source, 'b'),
1202
+ cropLeft: cropPercentage(source, 'l')
1203
+ });
1204
+ }
1205
+ function anchorLayer(anchor) {
1206
+ return normalizeDocumentImageLayer({
1207
+ relativeHeight: attribute(anchor, 'relativeHeight'),
1208
+ behindDocument: anchorBooleanAttribute(anchor, 'behindDoc', false),
1209
+ allowOverlap: anchorBooleanAttribute(anchor, 'allowOverlap', false),
1210
+ layoutInCell: anchorBooleanAttribute(anchor, 'layoutInCell', true),
1211
+ lockAnchor: anchorBooleanAttribute(anchor, 'locked', false)
1212
+ });
1213
+ }
1214
+ function drawingIdentitySource(anchor) {
1215
+ const properties = directChild(anchor, 'docPr');
1216
+ return {
1217
+ docPropertiesId: properties ? attribute(properties, 'id') : null,
1218
+ anchorId: attribute(anchor, 'anchorId'),
1219
+ editId: attribute(anchor, 'editId')
1220
+ };
1221
+ }
1222
+ function cropPercentage(source, name) {
1223
+ const value = attribute(source, name)?.trim() ?? '';
1224
+ if (!value) return 0;
1225
+ const number = Number(value.endsWith('%') ? value.slice(0, -1) : value);
1226
+ if (!Number.isFinite(number)) return 0;
1227
+ return value.endsWith('%') ? number : number / 1000;
1228
+ }
1229
+ function positionOffset(position) {
1230
+ const value = position ? directChild(position, 'posOffset') : void 0;
1231
+ if (!value?.textContent?.trim()) return null;
1232
+ const emus = Number(value.textContent);
1233
+ return Number.isFinite(emus) ? emus / EMUS_PER_MILLIMETER : null;
1234
+ }
1235
+ function insertMarkerRun(document, run, marker, position) {
1236
+ const markerRun = document.createElementNS(work_docx_image_layout_import_WORD_NAMESPACE, 'w:r');
1237
+ const text = document.createElementNS(work_docx_image_layout_import_WORD_NAMESPACE, 'w:t');
1238
+ text.setAttributeNS(work_docx_image_layout_import_XML_NAMESPACE, 'xml:space', 'preserve');
1239
+ text.textContent = marker;
1240
+ markerRun.append(text);
1241
+ const parent = run.parentNode;
1242
+ if (!parent) return;
1243
+ parent.insertBefore(markerRun, 'before' === position ? run : run.nextSibling);
1244
+ }
1245
+ function applyImageLayout(image, options, position, crop, contour, layer, identity) {
1246
+ applyDocumentImageIdentityToElement(image, identity);
1247
+ image.dataset.officeImageLayout = options.layout;
1248
+ image.dataset.officeImageAlignment = options.alignment;
1249
+ image.dataset.officeImageWrapDistance = formatNumber(options.wrapDistance);
1250
+ if (wrapsBesideImage(options.layout) || 'bothSides' !== options.wrapSide) image.dataset.officeImageWrapSide = options.wrapSide;
1251
+ else delete image.dataset.officeImageWrapSide;
1252
+ image.style.setProperty('--work-document-image-wrap-distance', `${formatNumber(options.wrapDistance)}mm`);
1253
+ if (position) {
1254
+ if (null !== position.horizontalOffset) {
1255
+ image.dataset.officeImageHorizontalOffset = formatNumber(position.horizontalOffset);
1256
+ image.style.setProperty('--work-document-image-horizontal-offset', `${formatNumber(position.horizontalOffset)}mm`);
1257
+ }
1258
+ if (null !== position.verticalOffset) {
1259
+ image.dataset.officeImageVerticalOffset = formatNumber(position.verticalOffset);
1260
+ image.style.setProperty('--work-document-image-vertical-offset', `${formatNumber(position.verticalOffset)}mm`);
1261
+ }
1262
+ image.dataset.officeImageHorizontalReference = position.horizontalReference;
1263
+ image.dataset.officeImageVerticalReference = position.verticalReference;
1264
+ }
1265
+ applyDocumentImageCropToElement(image, crop);
1266
+ applyDocumentImageWrapContourToElement(image, contour);
1267
+ if (layer) applyDocumentImageLayerToElement(image, layer);
1268
+ }
1269
+ function anchorBooleanAttribute(element, name, fallback) {
1270
+ const value = attribute(element, name)?.trim().toLowerCase();
1271
+ if ('1' === value || 'true' === value || 'on' === value) return true;
1272
+ if ('0' === value || 'false' === value || 'off' === value) return false;
1273
+ return fallback;
1274
+ }
1275
+ function numericAttribute(element, name) {
1276
+ if (!element) return null;
1277
+ const source = attribute(element, name);
1278
+ if (null === source || !source.trim()) return null;
1279
+ const value = Number(source);
1280
+ return Number.isFinite(value) && value >= 0 ? value : null;
1281
+ }
1282
+ function closestAncestor(element, localName) {
1283
+ let current = element;
1284
+ while(current){
1285
+ if (current.localName === localName) return current;
1286
+ current = current.parentElement;
1287
+ }
1288
+ return null;
1289
+ }
1290
+ function formatNumber(value) {
1291
+ return Number(value.toFixed(2)).toString();
1292
+ }
834
1293
  const work_docx_list_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
835
1294
  const work_docx_list_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
836
1295
  const LIST_START_MARKER_PATTERN = /__A3S_WORK_LIST_START_\d+__/g;
@@ -871,14 +1330,65 @@ function markDocxLists(document, numbering) {
871
1330
  const abstractId = integerAttribute(concrete ? directChild(concrete, 'abstractNumId') : null, 'val');
872
1331
  const abstract = null === abstractId ? void 0 : abstractNumbering.get(abstractId);
873
1332
  const start = effectiveListStart(concrete, abstract, level);
1333
+ const definition = effectiveListLevel(concrete, abstract, level);
1334
+ const format = stringAttribute(definition ? directChild(definition, 'numFmt') : null, 'val');
1335
+ const text = rawStringAttribute(definition ? directChild(definition, 'lvlText') : null, 'val');
1336
+ const suffix = stringAttribute(definition ? directChild(definition, 'suff') : null, 'val');
1337
+ const alignment = stringAttribute(definition ? directChild(definition, 'lvlJc') : null, 'val');
1338
+ const paragraphProperties = definition ? directChild(definition, 'pPr') : void 0;
1339
+ const indent = paragraphProperties ? directChild(paragraphProperties, 'ind') : void 0;
1340
+ const indentLeft = signedIntegerAttribute(indent, 'left');
1341
+ const indentStart = signedIntegerAttribute(indent, 'start');
1342
+ const indentRight = signedIntegerAttribute(indent, 'right');
1343
+ const indentEnd = signedIntegerAttribute(indent, 'end');
1344
+ const indentHanging = integerAttribute(indent, 'hanging');
1345
+ const indentFirstLine = integerAttribute(indent, 'firstLine');
1346
+ const restartAfterLevel = integerAttribute(definition ? directChild(definition, 'lvlRestart') : null, 'val');
874
1347
  const type = effectiveOrderedListType(concrete, abstract, level);
875
1348
  const bulletStyle = effectiveBulletListStyle(concrete, abstract, level);
876
- if (start <= 1 && !type && !bulletStyle) continue;
877
1349
  const marker = `__A3S_WORK_LIST_START_${lists.length + 1}__`;
878
1350
  insertParagraphMarker(document, paragraph, marker);
879
1351
  lists.push({
880
1352
  marker,
881
1353
  start,
1354
+ numberingId: numId,
1355
+ ...null === abstractId ? {} : {
1356
+ abstractNumberingId: abstractId
1357
+ },
1358
+ level,
1359
+ ...format ? {
1360
+ format
1361
+ } : {},
1362
+ ...text ? {
1363
+ text
1364
+ } : {},
1365
+ ...suffix ? {
1366
+ suffix
1367
+ } : {},
1368
+ ...alignment ? {
1369
+ alignment
1370
+ } : {},
1371
+ ...null === indentLeft ? {} : {
1372
+ indentLeft
1373
+ },
1374
+ ...null === indentRight ? {} : {
1375
+ indentRight
1376
+ },
1377
+ ...null === indentStart ? {} : {
1378
+ indentStart
1379
+ },
1380
+ ...null === indentEnd ? {} : {
1381
+ indentEnd
1382
+ },
1383
+ ...null === indentHanging ? {} : {
1384
+ indentHanging
1385
+ },
1386
+ ...null === indentFirstLine ? {} : {
1387
+ indentFirstLine
1388
+ },
1389
+ ...null === restartAfterLevel ? {} : {
1390
+ restartAfterLevel
1391
+ },
882
1392
  ...type ? {
883
1393
  type
884
1394
  } : {},
@@ -903,6 +1413,20 @@ function applyImportedDocxListMarkers(document, markers) {
903
1413
  node.data = node.data.replace(LIST_START_MARKER_PATTERN, (marker)=>{
904
1414
  const imported = listByMarker.get(marker);
905
1415
  if (imported && list instanceof HTMLElement) {
1416
+ list.dataset.officeNumberingId = String(imported.numberingId);
1417
+ list.dataset.officeNumberingLevel = String(imported.level);
1418
+ if (imported.format) list.dataset.officeNumberingFormat = imported.format;
1419
+ if (imported.text) list.dataset.officeNumberingText = imported.text;
1420
+ setOptionalDataset(list, 'officeNumberingSuffix', imported.suffix);
1421
+ setOptionalDataset(list, 'officeNumberingAlignment', imported.alignment);
1422
+ setOptionalDataset(list, 'officeNumberingIndentLeft', imported.indentLeft);
1423
+ setOptionalDataset(list, 'officeNumberingIndentRight', imported.indentRight);
1424
+ setOptionalDataset(list, 'officeNumberingIndentStart', imported.indentStart);
1425
+ setOptionalDataset(list, 'officeNumberingIndentEnd', imported.indentEnd);
1426
+ setOptionalDataset(list, 'officeNumberingIndentHanging', imported.indentHanging);
1427
+ setOptionalDataset(list, 'officeNumberingIndentFirstLine', imported.indentFirstLine);
1428
+ setOptionalDataset(list, 'officeNumberingRestartAfterLevel', imported.restartAfterLevel);
1429
+ if (void 0 !== imported.abstractNumberingId) list.dataset.officeAbstractNumberingId = String(imported.abstractNumberingId);
906
1430
  if ('ol' === list.tagName.toLowerCase()) {
907
1431
  if (imported.start > 1) list.setAttribute('start', String(imported.start));
908
1432
  if (imported.type) list.setAttribute('type', imported.type);
@@ -967,11 +1491,25 @@ function integerAttribute(element, name) {
967
1491
  const value = Number(source);
968
1492
  return Number.isSafeInteger(value) && value >= 0 ? value : null;
969
1493
  }
1494
+ function signedIntegerAttribute(element, name) {
1495
+ if (!element) return null;
1496
+ const source = attribute(element, name) ?? (name.includes(':') ? null : attribute(element, `w:${name}`));
1497
+ if (null === source) return null;
1498
+ const value = Number(source);
1499
+ return Number.isSafeInteger(value) ? value : null;
1500
+ }
1501
+ function setOptionalDataset(element, key, value) {
1502
+ if (void 0 !== value) element.dataset[key] = String(value);
1503
+ }
970
1504
  function stringAttribute(element, name) {
971
1505
  if (!element) return null;
972
1506
  const value = attribute(element, name) ?? (name.includes(':') ? null : attribute(element, `w:${name}`));
973
1507
  return value?.trim() || null;
974
1508
  }
1509
+ function rawStringAttribute(element, name) {
1510
+ if (!element) return null;
1511
+ return attribute(element, name) ?? (name.includes(':') ? null : attribute(element, `w:${name}`));
1512
+ }
975
1513
  function work_docx_list_import_textNodes(root) {
976
1514
  const document = root.ownerDocument;
977
1515
  const walker = document?.createTreeWalker(root, NodeFilter.SHOW_TEXT);
@@ -980,138 +1518,107 @@ function work_docx_list_import_textNodes(root) {
980
1518
  while(walker.nextNode())nodes.push(walker.currentNode);
981
1519
  return nodes;
982
1520
  }
983
- const work_docx_image_layout_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
984
- const work_docx_image_layout_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
985
- const EMUS_PER_MILLIMETER = 36000;
986
- const IMAGE_LAYOUT_MARKER_PATTERN = /__A3S_WORK_IMAGE_LAYOUT_\d+_(?:START|END)__/g;
987
- function markDocxImageLayouts(document) {
988
- const images = [];
989
- const markedRuns = new Set();
990
- for (const anchor of descendants(document, 'anchor')){
991
- const run = closestAncestor(anchor, 'r');
992
- if (!run || markedRuns.has(run)) continue;
993
- const layout = anchorLayout(anchor);
994
- if (!layout) continue;
995
- markedRuns.add(run);
996
- const index = images.length + 1;
997
- const startMarker = `__A3S_WORK_IMAGE_LAYOUT_${index}_START__`;
998
- const endMarker = `__A3S_WORK_IMAGE_LAYOUT_${index}_END__`;
999
- insertMarkerRun(document, run, startMarker, 'before');
1000
- insertMarkerRun(document, run, endMarker, 'after');
1001
- images.push({
1002
- startMarker,
1003
- endMarker,
1004
- options: normalizeDocumentImageLayoutOptions({
1005
- layout,
1006
- alignment: anchorAlignment(anchor),
1007
- wrapDistance: anchorWrapDistance(anchor, layout)
1008
- })
1009
- });
1521
+ async function markDocxNoteImageLayouts(archive, state) {
1522
+ const markers = {
1523
+ images: []
1524
+ };
1525
+ const parts = [];
1526
+ for (const config of [
1527
+ {
1528
+ path: 'word/footnotes.xml',
1529
+ root: 'footnotes'
1530
+ },
1531
+ {
1532
+ path: 'word/endnotes.xml',
1533
+ root: 'endnotes'
1534
+ }
1535
+ ]){
1536
+ if (!archive.has(config.path)) continue;
1537
+ const document = await archive.xml(config.path);
1538
+ const root = document.documentElement;
1539
+ if (root.localName !== config.root || !DOCX_WORDPROCESSING_NAMESPACES.has(root.namespaceURI ?? '')) continue;
1540
+ const partMarkers = markDocxImageLayouts(document, state);
1541
+ if (partMarkers.images.length) {
1542
+ markers.images.push(...partMarkers.images);
1543
+ parts.push({
1544
+ document,
1545
+ path: config.path
1546
+ });
1547
+ }
1010
1548
  }
1011
1549
  return {
1012
- images
1550
+ markers,
1551
+ parts
1013
1552
  };
1014
1553
  }
1015
- function applyImportedDocxImageLayoutMarkers(document, markers) {
1016
- const starts = new Map(markers.images.map((image)=>[
1017
- image.startMarker,
1018
- image
1019
- ]));
1020
- const ends = new Set(markers.images.map((image)=>image.endMarker));
1021
- const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT);
1022
- const nodes = [];
1023
- while(walker.nextNode())nodes.push(walker.currentNode);
1024
- const state = {
1025
- active: null,
1026
- applied: false
1554
+ function extractMammothDocumentNotes(document) {
1555
+ const definitions = extractDefinitions(document);
1556
+ const notes = new Map();
1557
+ const counters = {
1558
+ footnote: 0,
1559
+ endnote: 0
1027
1560
  };
1028
- for (const node of nodes){
1029
- if (node instanceof Text) {
1030
- node.data = node.data.replace(IMAGE_LAYOUT_MARKER_PATTERN, (marker)=>{
1031
- const start = starts.get(marker);
1032
- if (start) {
1033
- state.active = start;
1034
- state.applied = false;
1035
- } else if (ends.has(marker)) {
1036
- state.active = null;
1037
- state.applied = false;
1038
- }
1039
- return '';
1040
- });
1041
- continue;
1042
- }
1043
- if (!state.applied && state.active && node instanceof HTMLImageElement) {
1044
- applyImageLayout(node, state.active.options);
1045
- state.applied = true;
1561
+ const references = Array.from(document.body.querySelectorAll('a[href^="#footnote-"], a[href^="#endnote-"]'));
1562
+ for (const reference of references){
1563
+ const target = reference.getAttribute('href')?.slice(1) ?? '';
1564
+ const kind = noteKindFromTarget(target);
1565
+ if (!kind) continue;
1566
+ let note = notes.get(target);
1567
+ if (!note) {
1568
+ counters[kind] += 1;
1569
+ note = {
1570
+ id: importedDocumentNoteId(kind, target) ?? `document-${kind}-${counters[kind]}`,
1571
+ kind,
1572
+ number: counters[kind],
1573
+ html: definitions.get(target) ?? '<p></p>'
1574
+ };
1575
+ notes.set(target, note);
1046
1576
  }
1577
+ const marker = document.createElement('sup');
1578
+ marker.setAttribute('data-document-note-reference', 'true');
1579
+ marker.setAttribute('data-note-kind', note.kind);
1580
+ marker.setAttribute('data-note-id', note.id);
1581
+ marker.setAttribute('data-note-number', String(note.number));
1582
+ marker.textContent = String(note.number);
1583
+ const wrapper = reference.parentElement;
1584
+ if (wrapper?.tagName.toLowerCase() === 'sup' && 1 === wrapper.childNodes.length) wrapper.replaceWith(marker);
1585
+ else reference.replaceWith(marker);
1047
1586
  }
1048
- document.body.normalize();
1049
- }
1050
- function hasImportedDocxImageLayoutMarkers(markers) {
1051
- return markers.images.length > 0;
1052
- }
1053
- function anchorLayout(anchor) {
1054
- if (directChild(anchor, 'wrapTopAndBottom')) return 'topBottom';
1055
- if (directChild(anchor, 'wrapSquare') || directChild(anchor, 'wrapTight') || directChild(anchor, 'wrapThrough')) return 'square';
1056
- return null;
1057
- }
1058
- function anchorAlignment(anchor) {
1059
- const position = directChild(anchor, 'positionH');
1060
- const alignment = position ? directChild(position, 'align') : void 0;
1061
- const value = alignment?.textContent?.trim();
1062
- if ('inside' === value) return 'left';
1063
- if ('outside' === value) return 'right';
1064
- return normalizeDocumentImageAlignment(value);
1065
- }
1066
- function anchorWrapDistance(anchor, layout) {
1067
- const wrap = directChild(anchor, 'square' === layout ? 'wrapSquare' : 'wrapTopAndBottom') ?? ('square' === layout ? directChild(anchor, 'wrapTight') ?? directChild(anchor, 'wrapThrough') : void 0);
1068
- const names = 'square' === layout ? [
1069
- 'distL',
1070
- 'distR'
1071
- ] : [
1072
- 'distT',
1073
- 'distB'
1074
- ];
1075
- const distance = Math.max(0, ...names.flatMap((name)=>[
1076
- numericAttribute(wrap, name) ?? 0,
1077
- numericAttribute(anchor, name) ?? 0
1078
- ]));
1079
- return distance / EMUS_PER_MILLIMETER;
1080
- }
1081
- function insertMarkerRun(document, run, marker, position) {
1082
- const markerRun = document.createElementNS(work_docx_image_layout_import_WORD_NAMESPACE, 'w:r');
1083
- const text = document.createElementNS(work_docx_image_layout_import_WORD_NAMESPACE, 'w:t');
1084
- text.setAttributeNS(work_docx_image_layout_import_XML_NAMESPACE, 'xml:space', 'preserve');
1085
- text.textContent = marker;
1086
- markerRun.append(text);
1087
- const parent = run.parentNode;
1088
- if (!parent) return;
1089
- parent.insertBefore(markerRun, 'before' === position ? run : run.nextSibling);
1090
- }
1091
- function applyImageLayout(image, options) {
1092
- image.dataset.officeImageLayout = options.layout;
1093
- image.dataset.officeImageAlignment = options.alignment;
1094
- image.dataset.officeImageWrapDistance = formatNumber(options.wrapDistance);
1095
- image.style.setProperty('--work-document-image-wrap-distance', `${formatNumber(options.wrapDistance)}mm`);
1587
+ return Array.from(notes.values());
1096
1588
  }
1097
- function numericAttribute(element, name) {
1098
- if (!element) return null;
1099
- const source = attribute(element, name);
1100
- if (null === source || !source.trim()) return null;
1101
- const value = Number(source);
1102
- return Number.isFinite(value) && value >= 0 ? value : null;
1589
+ function placeMammothDocumentNotes(document, notes) {
1590
+ const sections = Array.from(document.body.querySelectorAll('section[data-document-section]'));
1591
+ for (const note of notes){
1592
+ const reference = Array.from(document.body.querySelectorAll('sup[data-document-note-reference]')).find((element)=>element.dataset.noteKind === note.kind && element.dataset.noteId === note.id);
1593
+ const target = 'footnote' === note.kind ? reference?.closest('section[data-document-section]') : sections.at(-1);
1594
+ (target ?? document.body).append(createDocumentNoteElement(document, note));
1595
+ }
1103
1596
  }
1104
- function closestAncestor(element, localName) {
1105
- let current = element;
1106
- while(current){
1107
- if (current.localName === localName) return current;
1108
- current = current.parentElement;
1597
+ function extractDefinitions(document) {
1598
+ const definitions = new Map();
1599
+ const elements = Array.from(document.body.querySelectorAll('li[id^="footnote-"], li[id^="endnote-"]'));
1600
+ for (const element of elements){
1601
+ const id = element.id;
1602
+ const clone = element.cloneNode(true);
1603
+ for (const backlink of Array.from(clone.querySelectorAll('a[href^="#footnote-ref-"], a[href^="#endnote-ref-"]')))backlink.remove();
1604
+ definitions.set(id, clone.innerHTML.trim() || '<p></p>');
1605
+ const parent = element.parentElement;
1606
+ element.remove();
1607
+ if (parent && !parent.children.length) parent.remove();
1109
1608
  }
1110
- return null;
1609
+ return definitions;
1111
1610
  }
1112
- function formatNumber(value) {
1113
- return Number(value.toFixed(2)).toString();
1611
+ function noteKindFromTarget(target) {
1612
+ if (target.startsWith('footnote-')) return 'footnote';
1613
+ if (target.startsWith('endnote-')) return 'endnote';
1614
+ return null;
1114
1615
  }
1616
+ const WORDPROCESSING_DRAWING_NAMESPACES = new Set([
1617
+ 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing',
1618
+ 'http://purl.oclc.org/ooxml/drawingml/wordprocessingDrawing'
1619
+ ]);
1620
+ const WORDPROCESSING_DRAWING_2010_NAMESPACE = 'http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing';
1621
+ const WORD_2010_NAMESPACE = 'http://schemas.microsoft.com/office/word/2010/wordml';
1115
1622
  async function importSectionPageChrome(section, archive, documentRelationships, previous, oddEvenEnabled) {
1116
1623
  const fallback = normalizeDocumentPageChrome(previous.pageChrome, previous);
1117
1624
  const variants = await Promise.all([
@@ -1162,16 +1669,25 @@ async function importReferencedPart(section, referenceName, variant, archive, do
1162
1669
  }
1163
1670
  async function pageChromePartHtml(document, archive, partPath) {
1164
1671
  const relationships = await archive.relationships(partPath);
1672
+ const themePath = archive.paths('word/theme/').find((path)=>/\/theme\d*\.xml$/i.test(path));
1673
+ const themeDocument = themePath ? await archive.xml(themePath) : null;
1674
+ const settingsDocument = archive.has('word/settings.xml') ? await archive.xml('word/settings.xml') : null;
1675
+ const stylesDocument = archive.has('word/styles.xml') ? await archive.xml('word/styles.xml') : null;
1676
+ const theme = createDocxThemeResolver(themeDocument, settingsDocument);
1677
+ const paragraphStyles = createDocxParagraphStyleResolver(stylesDocument);
1678
+ const tableStyles = createDocxTableStyleResolver(stylesDocument);
1165
1679
  const root = document.documentElement;
1166
1680
  const blocks = [];
1167
1681
  for (const child of directChildren(root)){
1168
- if ('p' === child.localName) blocks.push(await paragraphHtml(child, archive, relationships));
1169
- if ('tbl' === child.localName) blocks.push(await tableHtml(child, archive, relationships));
1682
+ if ('p' === child.localName) blocks.push(await paragraphHtml(child, archive, relationships, theme, paragraphStyles, tableStyles));
1683
+ if ('tbl' === child.localName) blocks.push(await tableHtml(child, archive, relationships, theme, paragraphStyles, tableStyles));
1684
+ if (isDocxEquationLikeRoot(child)) blocks.push(`<p>${docxEquationHtml(child)}</p>`);
1170
1685
  }
1171
1686
  return blocks.join('');
1172
1687
  }
1173
- async function paragraphHtml(paragraph, archive, relationships) {
1174
- const alignmentValue = attribute(firstDescendant(directChild(paragraph, 'pPr'), 'jc') ?? paragraph, 'val');
1688
+ async function paragraphHtml(paragraph, archive, relationships, theme, paragraphStyles, tableStyles) {
1689
+ const properties = directChild(paragraph, 'pPr');
1690
+ const alignmentValue = attribute(firstDescendant(properties, 'jc') ?? paragraph, 'val');
1175
1691
  const alignment = 'center' === alignmentValue ? 'center' : 'right' === alignmentValue || 'end' === alignmentValue ? 'right' : 'both' === alignmentValue || 'distribute' === alignmentValue ? 'justify' : 'left' === alignmentValue || 'start' === alignmentValue ? 'left' : '';
1176
1692
  const field = {
1177
1693
  active: false,
@@ -1181,6 +1697,10 @@ async function paragraphHtml(paragraph, archive, relationships) {
1181
1697
  };
1182
1698
  let html = '';
1183
1699
  for (const child of directChildren(paragraph))if ('pPr' !== child.localName) {
1700
+ if (isDocxEquationLikeRoot(child)) {
1701
+ html += docxEquationHtml(child);
1702
+ continue;
1703
+ }
1184
1704
  if ('hyperlink' === child.localName) {
1185
1705
  const content = await containerRunsHtml(child, field, archive, relationships);
1186
1706
  const relationship = relationships.get(attribute(child, 'r:id') ?? '');
@@ -1196,12 +1716,44 @@ async function paragraphHtml(paragraph, archive, relationships) {
1196
1716
  }
1197
1717
  html += await containerRunsHtml(child, field, archive, relationships);
1198
1718
  }
1199
- return `<p${alignment ? ` style="text-align: ${alignment}"` : ''}>${html}</p>`;
1719
+ const identityAttributes = paragraphIdentityAttributes(paragraph);
1720
+ const defaultCollapsed = properties ? parseDocxParagraphDefaultCollapsed(properties) : {
1721
+ status: 'absent'
1722
+ };
1723
+ const defaultCollapsedAttribute = 'valid' === defaultCollapsed.status ? ` data-office-default-collapsed="${defaultCollapsed.value}"` : '';
1724
+ const parsedShading = properties ? parseDirectDocxParagraphShading(properties, theme) : void 0;
1725
+ const shading = null === parsedShading ? {
1726
+ pattern: 'nil'
1727
+ } : parsedShading;
1728
+ const shadingAttributes = documentParagraphShadingDomAttributes(shading);
1729
+ const borders = resolveDocxParagraphBordersForParagraph(paragraph, paragraphStyles, theme, tableStyles).borders;
1730
+ const borderAttributes = documentParagraphBordersDomAttributes(borders);
1731
+ const styles = [
1732
+ alignment ? `text-align: ${alignment}` : '',
1733
+ borderAttributes.style ?? '',
1734
+ shadingAttributes.style ?? ''
1735
+ ].filter(Boolean);
1736
+ const borderAttribute = borderAttributes['data-office-paragraph-borders'];
1737
+ const shadingAttribute = shadingAttributes['data-office-paragraph-shading'];
1738
+ return `<p${styles.length ? ` style="${escapeHtml(styles.join('; '))}"` : ''}${identityAttributes}${defaultCollapsedAttribute}${borderAttribute ? ` data-office-paragraph-borders="${escapeHtml(borderAttribute)}"` : ''}${shadingAttribute ? ` data-office-paragraph-shading="${escapeHtml(shadingAttribute)}"` : ''}>${html}</p>`;
1739
+ }
1740
+ function paragraphIdentityAttributes(paragraph) {
1741
+ const identity = normalizeDocumentParagraphIdentity({
1742
+ paragraphId: namespacedAttribute(paragraph, WORD_2010_NAMESPACE, 'paraId'),
1743
+ textId: namespacedAttribute(paragraph, WORD_2010_NAMESPACE, 'textId')
1744
+ });
1745
+ return identity ? ` data-office-paragraph-id="${identity.paragraphId}" data-office-paragraph-text-id="${identity.textId}"` : '';
1200
1746
  }
1201
1747
  async function containerRunsHtml(container, field, archive, relationships) {
1202
1748
  if ('r' === container.localName) return runHtml(container, field, archive, relationships);
1203
1749
  let html = '';
1204
- for (const run of descendants(container, 'r'))html += await runHtml(run, field, archive, relationships);
1750
+ for (const child of directChildren(container)){
1751
+ if (isDocxEquationLikeRoot(child)) {
1752
+ html += docxEquationHtml(child);
1753
+ continue;
1754
+ }
1755
+ html += await containerRunsHtml(child, field, archive, relationships);
1756
+ }
1205
1757
  return html;
1206
1758
  }
1207
1759
  async function runHtml(run, field, archive, relationships) {
@@ -1216,6 +1768,10 @@ async function runHtml(run, field, archive, relationships) {
1216
1768
  continue;
1217
1769
  }
1218
1770
  if (fieldContentVisible(field)) {
1771
+ if (isDocxEquationLikeRoot(child)) {
1772
+ content += docxEquationHtml(child);
1773
+ continue;
1774
+ }
1219
1775
  if ('t' === child.localName) content += escapeHtml(child.textContent ?? '');
1220
1776
  if ('tab' === child.localName) content += '&#9;';
1221
1777
  if ('br' === child.localName || 'cr' === child.localName) content += '<br>';
@@ -1243,20 +1799,48 @@ async function drawingHtml(drawing, archive, relationships) {
1243
1799
  const extent = firstDescendant(drawing, 'extent');
1244
1800
  const width = Math.max(1, Math.round(Number(attribute(extent ?? drawing, 'cx')) / 9525));
1245
1801
  const height = Math.max(1, Math.round(Number(attribute(extent ?? drawing, 'cy')) / 9525));
1246
- return `<img src="${source}" alt="Header or footer image"${width > 1 ? ` width="${width}"` : ''}${height > 1 ? ` height="${height}"` : ''}>`;
1802
+ const identityAttributes = drawingIdentityAttributes(drawing);
1803
+ return `<img src="${source}" alt="Header or footer image"${width > 1 ? ` width="${width}"` : ''}${height > 1 ? ` height="${height}"` : ''}${identityAttributes}>`;
1804
+ }
1805
+ function drawingIdentityAttributes(drawing) {
1806
+ const anchor = Array.from(drawing.querySelectorAll('*')).find((element)=>('anchor' === element.localName || 'inline' === element.localName) && WORDPROCESSING_DRAWING_NAMESPACES.has(element.namespaceURI ?? ''));
1807
+ const properties = anchor ? directChildren(anchor, 'docPr').find((element)=>WORDPROCESSING_DRAWING_NAMESPACES.has(element.namespaceURI ?? '')) : void 0;
1808
+ const identity = normalizeDocumentImageIdentity({
1809
+ docPropertiesId: properties?.getAttribute('id'),
1810
+ anchorId: anchor ? namespacedAttribute(anchor, WORDPROCESSING_DRAWING_2010_NAMESPACE, 'anchorId') : null,
1811
+ editId: anchor ? namespacedAttribute(anchor, WORDPROCESSING_DRAWING_2010_NAMESPACE, 'editId') : null
1812
+ });
1813
+ if (!identity) return '';
1814
+ return [
1815
+ ` data-office-image-object-id="${identity.objectId}"`,
1816
+ ` data-office-image-doc-properties-id="${identity.docPropertiesId}"`,
1817
+ ` data-office-image-anchor-id="${identity.anchorId}"`,
1818
+ ` data-office-image-edit-id="${identity.editId}"`
1819
+ ].join('');
1820
+ }
1821
+ function namespacedAttribute(element, namespace, localName) {
1822
+ for (const item of Array.from(element.attributes))if (xmlAttributeLocalName(item) === localName && xmlAttributeNamespace(element, item) === namespace) return item.value;
1823
+ return null;
1247
1824
  }
1248
- async function tableHtml(table, archive, relationships) {
1825
+ async function tableHtml(table, archive, relationships, theme, paragraphStyles, tableStyles) {
1249
1826
  const rows = [];
1250
1827
  for (const row of directChildren(table, 'tr')){
1251
1828
  const cells = [];
1252
1829
  for (const cell of directChildren(row, 'tc')){
1253
- const paragraphs = await Promise.all(directChildren(cell, 'p').map((item)=>paragraphHtml(item, archive, relationships)));
1830
+ const paragraphs = await Promise.all(directChildren(cell, 'p').map((item)=>paragraphHtml(item, archive, relationships, theme, paragraphStyles, tableStyles)));
1254
1831
  cells.push(`<td>${paragraphs.join('')}</td>`);
1255
1832
  }
1256
- rows.push(`<tr>${cells.join('')}</tr>`);
1833
+ rows.push(`<tr${tableRowIdentityAttributes(row)}>${cells.join('')}</tr>`);
1257
1834
  }
1258
1835
  return `<table><tbody>${rows.join('')}</tbody></table>`;
1259
1836
  }
1837
+ function tableRowIdentityAttributes(row) {
1838
+ const identity = normalizeDocumentTableRowIdentity({
1839
+ rowId: namespacedAttribute(row, WORD_2010_NAMESPACE, 'paraId'),
1840
+ rowTextId: namespacedAttribute(row, WORD_2010_NAMESPACE, 'textId')
1841
+ });
1842
+ return identity ? ` ${DOCUMENT_TABLE_ROW_ID_ATTRIBUTE}="${identity.rowId}" ${DOCUMENT_TABLE_ROW_TEXT_ID_ATTRIBUTE}="${identity.rowTextId}"` : '';
1843
+ }
1260
1844
  function containsPageNumber(document) {
1261
1845
  return descendants(document, 'instrText').some((element)=>/\bPAGE\b/i.test(element.textContent ?? '')) || descendants(document, 'fldSimple').some((element)=>/\bPAGE\b/i.test(attribute(element, 'instr') ?? ''));
1262
1846
  }
@@ -1297,339 +1881,135 @@ function updateFieldState(field, fieldType) {
1297
1881
  function fieldContentVisible(field) {
1298
1882
  return !field.active || field.separated && !field.skipResult;
1299
1883
  }
1300
- const MAX_STYLE_INHERITANCE_DEPTH = 64;
1301
- function createDocxParagraphStyleResolver(stylesDocument) {
1302
- if (!stylesDocument) return {
1303
- styles: new Map(),
1304
- characterStyles: new Map()
1305
- };
1306
- const styles = new Map();
1307
- const characterStyles = new Map();
1308
- let defaultStyleId;
1309
- for (const style of descendants(stylesDocument, 'style')){
1310
- const type = wordAttribute(style, 'type');
1311
- if ('paragraph' !== type && 'character' !== type) continue;
1312
- const styleId = wordAttribute(style, 'styleId')?.trim();
1313
- if (!styleId) continue;
1314
- const basedOn = directChild(style, 'basedOn');
1315
- const value = {
1316
- basedOn: basedOn ? wordAttribute(basedOn, 'val')?.trim() || void 0 : void 0,
1317
- paragraphProperties: directChild(style, 'pPr'),
1318
- runProperties: directChild(style, 'rPr')
1319
- };
1320
- if ('paragraph' === type) styles.set(styleId, value);
1321
- else characterStyles.set(styleId, value);
1322
- if ('paragraph' === type && !defaultStyleId && onOffAttribute(style, 'default')) defaultStyleId = styleId;
1323
- }
1324
- return {
1325
- defaultProperties: childPath(stylesDocument.documentElement, 'docDefaults', 'pPrDefault', 'pPr'),
1326
- defaultRunProperties: childPath(stylesDocument.documentElement, 'docDefaults', 'rPrDefault', 'rPr'),
1327
- defaultStyleId,
1328
- styles,
1329
- characterStyles
1330
- };
1331
- }
1332
- function resolveDocxParagraphStyleResolver(source) {
1333
- return source && 'styles' in source ? source : createDocxParagraphStyleResolver(source);
1334
- }
1335
- function docxParagraphPropertySources(directProperties, resolver, contextualProperties = []) {
1336
- const sources = [];
1337
- if (resolver.defaultProperties) sources.push(resolver.defaultProperties);
1338
- const styleReference = directProperties ? directChild(directProperties, 'pStyle') : void 0;
1339
- const styleId = (styleReference ? wordAttribute(styleReference, 'val')?.trim() : void 0) || resolver.defaultStyleId;
1340
- if (styleId) sources.push(...stylePropertySources(resolver.styles, styleId, 'paragraphProperties'));
1341
- sources.push(...contextualProperties);
1342
- if (directProperties) sources.push(directProperties);
1343
- return sources;
1344
- }
1345
- function docxRunPropertySources(paragraphProperties, runProperties, resolver, contextualProperties = []) {
1346
- const sources = [];
1347
- if (resolver.defaultRunProperties) sources.push(resolver.defaultRunProperties);
1348
- const paragraphStyleReference = paragraphProperties ? directChild(paragraphProperties, 'pStyle') : void 0;
1349
- const paragraphStyleId = (paragraphStyleReference ? wordAttribute(paragraphStyleReference, 'val')?.trim() : void 0) || resolver.defaultStyleId;
1350
- if (paragraphStyleId) sources.push(...stylePropertySources(resolver.styles, paragraphStyleId, 'runProperties'));
1351
- sources.push(...contextualProperties);
1352
- const paragraphRunProperties = paragraphProperties ? directChild(paragraphProperties, 'rPr') : void 0;
1353
- if (paragraphRunProperties) sources.push(paragraphRunProperties);
1354
- const characterStyleReference = runProperties ? directChild(runProperties, 'rStyle') : void 0;
1355
- const characterStyleId = characterStyleReference ? wordAttribute(characterStyleReference, 'val')?.trim() : void 0;
1356
- if (characterStyleId) sources.push(...stylePropertySources(resolver.characterStyles, characterStyleId, 'runProperties'));
1357
- if (runProperties) sources.push(runProperties);
1358
- return sources;
1359
- }
1360
- function stylePropertySources(styles, styleId, property) {
1361
- const inherited = [];
1362
- const visited = new Set();
1363
- let currentStyleId = styleId;
1364
- let depth = 0;
1365
- while(currentStyleId && depth < MAX_STYLE_INHERITANCE_DEPTH && !visited.has(currentStyleId)){
1366
- depth += 1;
1367
- visited.add(currentStyleId);
1368
- const style = styles.get(currentStyleId);
1369
- if (!style) break;
1370
- const properties = style[property];
1371
- if (properties) inherited.push(properties);
1372
- currentStyleId = style.basedOn;
1373
- }
1374
- return inherited.reverse();
1375
- }
1376
- function onOffAttribute(element, name) {
1377
- const value = wordAttribute(element, name)?.trim().toLowerCase();
1378
- if (null == value) return false;
1379
- return '0' !== value && 'false' !== value && 'off' !== value;
1380
- }
1381
- function wordAttribute(element, name) {
1382
- return attribute(element, name) ?? attribute(element, `w:${name}`);
1383
- }
1384
- const work_docx_table_styles_MAX_STYLE_INHERITANCE_DEPTH = 64;
1385
- const DEFAULT_TABLE_LOOK = {
1386
- firstRow: true,
1387
- lastRow: false,
1388
- firstColumn: true,
1389
- lastColumn: false,
1390
- noHorizontalBand: false,
1391
- noVerticalBand: true
1392
- };
1393
- const TABLE_LOOK_BITS = {
1394
- firstRow: 0x0020,
1395
- lastRow: 0x0040,
1396
- firstColumn: 0x0080,
1397
- lastColumn: 0x0100,
1398
- noHorizontalBand: 0x0200,
1399
- noVerticalBand: 0x0400
1400
- };
1401
- function createDocxTableStyleResolver(stylesDocument) {
1402
- if (!stylesDocument) return {
1403
- tableStyles: new Map()
1404
- };
1405
- const tableStyles = new Map();
1406
- let defaultStyleId;
1407
- for (const style of descendants(stylesDocument, 'style')){
1408
- if ('table' !== work_docx_table_styles_wordAttribute(style, 'type')) continue;
1409
- const styleId = work_docx_table_styles_wordAttribute(style, 'styleId')?.trim();
1410
- if (!styleId) continue;
1411
- const basedOn = directChild(style, 'basedOn');
1412
- const conditional = new Map();
1413
- for (const conditionalStyle of directChildren(style, 'tblStylePr')){
1414
- const type = work_docx_table_styles_wordAttribute(conditionalStyle, 'type')?.trim();
1415
- if (type) conditional.set(type, styleLayer(conditionalStyle));
1416
- }
1417
- tableStyles.set(styleId, {
1418
- ...styleLayer(style),
1419
- basedOn: basedOn ? work_docx_table_styles_wordAttribute(basedOn, 'val')?.trim() || void 0 : void 0,
1420
- conditional
1884
+ const work_docx_paragraph_alignment_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
1885
+ const work_docx_paragraph_alignment_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
1886
+ const PARAGRAPH_ALIGNMENT_MARKER_PATTERN = /__A3S_WORK_PARAGRAPH_ALIGNMENT_\d+__/g;
1887
+ function markDocxParagraphAlignments(document, styleSource, tableStyleSource) {
1888
+ const paragraphs = [];
1889
+ const styles = resolveDocxParagraphStyleResolver(styleSource);
1890
+ const tableStyles = resolveDocxTableStyleResolver(tableStyleSource);
1891
+ for (const paragraph of descendants(document, 'p')){
1892
+ let properties = directChild(paragraph, 'pPr');
1893
+ const sources = docxParagraphPropertySources(properties, styles, docxTableParagraphPropertySources(paragraph, tableStyles));
1894
+ const alignment = paragraphAlignment(sources);
1895
+ if (!alignment) continue;
1896
+ properties ??= insertParagraphProperties(document, paragraph);
1897
+ const marker = `__A3S_WORK_PARAGRAPH_ALIGNMENT_${paragraphs.length + 1}__`;
1898
+ work_docx_paragraph_alignment_import_insertParagraphMarker(document, paragraph, properties, marker);
1899
+ paragraphs.push({
1900
+ marker,
1901
+ alignment
1421
1902
  });
1422
- if (!defaultStyleId && work_docx_table_styles_onOffAttribute(style, 'default')) defaultStyleId = styleId;
1423
1903
  }
1424
1904
  return {
1425
- defaultStyleId,
1426
- tableStyles
1905
+ paragraphs
1427
1906
  };
1428
1907
  }
1429
- function resolveDocxTableStyleResolver(source) {
1430
- return source && 'tableStyles' in source ? source : createDocxTableStyleResolver(source);
1431
- }
1432
- function docxTablePropertySources(table, resolver) {
1433
- const directTableProperties = directChild(table, 'tblPr');
1434
- const styleReference = directTableProperties ? directChild(directTableProperties, 'tblStyle') : void 0;
1435
- const styleId = (styleReference ? work_docx_table_styles_wordAttribute(styleReference, 'val')?.trim() : void 0) || resolver.defaultStyleId;
1436
- const sources = styleId ? tableStyleChain(resolver.tableStyles, styleId).map(({ tableProperties })=>tableProperties).filter((properties)=>Boolean(properties)) : [];
1437
- if (directTableProperties) sources.push(directTableProperties);
1438
- return sources;
1439
- }
1440
- function docxTableCellStyleLayers(cell, resolver) {
1441
- const table = work_docx_table_styles_closestAncestor(cell, 'tbl');
1442
- if (!table) return [];
1443
- const directTableProperties = directChild(table, 'tblPr');
1444
- const styleReference = directTableProperties ? directChild(directTableProperties, 'tblStyle') : void 0;
1445
- const styleId = (styleReference ? work_docx_table_styles_wordAttribute(styleReference, 'val')?.trim() : void 0) || resolver.defaultStyleId;
1446
- if (!styleId) return [];
1447
- const styles = tableStyleChain(resolver.tableStyles, styleId);
1448
- if (!styles.length) return [];
1449
- const unconditionalLayers = styles.map(styleLayerFromStyle);
1450
- const propertySources = unconditionalLayers.map(({ tableProperties })=>tableProperties).filter((properties)=>Boolean(properties));
1451
- if (directTableProperties) propertySources.push(directTableProperties);
1452
- const position = tableCellPosition(table, cell);
1453
- if (!position) return unconditionalLayers;
1454
- const look = resolveTableLook(propertySources);
1455
- const rowBandSize = resolveBandSize(propertySources, 'tblStyleRowBandSize');
1456
- const columnBandSize = resolveBandSize(propertySources, 'tblStyleColBandSize');
1457
- const layers = [
1458
- ...unconditionalLayers
1459
- ];
1460
- for (const condition of applicableConditions(position, look, rowBandSize, columnBandSize))for (const style of styles){
1461
- const layer = style.conditional.get(condition);
1462
- if (layer) layers.push(layer);
1463
- }
1464
- return layers;
1465
- }
1466
- function docxTableRunPropertySources(element, resolver) {
1467
- const cell = work_docx_table_styles_closestAncestor(element, 'tc');
1468
- if (!cell) return [];
1469
- const sources = [];
1470
- for (const layer of docxTableCellStyleLayers(cell, resolver)){
1471
- const paragraphRunProperties = layer.paragraphProperties ? directChild(layer.paragraphProperties, 'rPr') : void 0;
1472
- if (paragraphRunProperties) sources.push(paragraphRunProperties);
1473
- if (layer.runProperties) sources.push(layer.runProperties);
1474
- }
1475
- return sources;
1476
- }
1477
- function docxTableParagraphPropertySources(element, resolver) {
1478
- const cell = work_docx_table_styles_closestAncestor(element, 'tc');
1479
- if (!cell) return [];
1480
- return docxTableCellStyleLayers(cell, resolver).map(({ paragraphProperties })=>paragraphProperties).filter((properties)=>Boolean(properties));
1481
- }
1482
- function styleLayer(parent) {
1483
- return {
1484
- tableProperties: directChild(parent, 'tblPr'),
1485
- cellProperties: directChild(parent, 'tcPr'),
1486
- paragraphProperties: directChild(parent, 'pPr'),
1487
- runProperties: directChild(parent, 'rPr')
1488
- };
1908
+ function applyImportedDocxParagraphAlignmentMarkers(document, markers) {
1909
+ const alignmentByMarker = new Map(markers.paragraphs.map(({ marker, alignment })=>[
1910
+ marker,
1911
+ alignment
1912
+ ]));
1913
+ for (const node of work_docx_paragraph_alignment_import_textNodes(document.body))if (node.data.includes('__A3S_WORK_PARAGRAPH_ALIGNMENT_')) node.data = node.data.replace(PARAGRAPH_ALIGNMENT_MARKER_PATTERN, (marker)=>{
1914
+ const alignment = alignmentByMarker.get(marker);
1915
+ const block = alignment ? closestParagraphBlock(node.parentElement, node) : null;
1916
+ if (block && alignment) block.style.textAlign = alignment;
1917
+ return '';
1918
+ });
1919
+ document.body.normalize();
1489
1920
  }
1490
- function styleLayerFromStyle(style) {
1491
- return {
1492
- tableProperties: style.tableProperties,
1493
- cellProperties: style.cellProperties,
1494
- paragraphProperties: style.paragraphProperties,
1495
- runProperties: style.runProperties
1496
- };
1921
+ function hasImportedDocxParagraphAlignmentMarkers(markers) {
1922
+ return markers.paragraphs.length > 0;
1497
1923
  }
1498
- function tableStyleChain(styles, styleId) {
1499
- const inherited = [];
1500
- const visited = new Set();
1501
- let currentStyleId = styleId;
1502
- let depth = 0;
1503
- while(currentStyleId && depth < work_docx_table_styles_MAX_STYLE_INHERITANCE_DEPTH && !visited.has(currentStyleId)){
1504
- depth += 1;
1505
- visited.add(currentStyleId);
1506
- const style = styles.get(currentStyleId);
1507
- if (!style) break;
1508
- inherited.push(style);
1509
- currentStyleId = style.basedOn;
1510
- }
1511
- return inherited.reverse();
1512
- }
1513
- function applicableConditions(position, look, rowBandSize, columnBandSize) {
1514
- const conditions = [
1515
- 'wholeTable'
1516
- ];
1517
- const isFirstRow = 0 === position.rowIndex;
1518
- const isLastRow = position.rowIndex === position.rowCount - 1;
1519
- const isFirstColumn = 0 === position.columnStart;
1520
- const isLastColumn = position.columnEnd === position.columnCount - 1;
1521
- if (!look.noVerticalBand) {
1522
- const offset = look.firstColumn ? 1 : 0;
1523
- const bandIndex = position.columnStart - offset;
1524
- if (bandIndex >= 0) conditions.push(Math.floor(bandIndex / columnBandSize) % 2 === 0 ? 'band1Vert' : 'band2Vert');
1525
- }
1526
- if (!look.noHorizontalBand) {
1527
- const offset = look.firstRow ? 1 : 0;
1528
- const bandIndex = position.rowIndex - offset;
1529
- if (bandIndex >= 0) conditions.push(Math.floor(bandIndex / rowBandSize) % 2 === 0 ? 'band1Horz' : 'band2Horz');
1530
- }
1531
- if (look.firstColumn && isFirstColumn) conditions.push('firstCol');
1532
- if (look.lastColumn && isLastColumn) conditions.push('lastCol');
1533
- if (look.firstRow && isFirstRow) conditions.push('firstRow');
1534
- if (look.lastRow && isLastRow) conditions.push('lastRow');
1535
- if (look.firstRow && isFirstRow && look.firstColumn && isFirstColumn) conditions.push('nwCell');
1536
- if (look.firstRow && isFirstRow && look.lastColumn && isLastColumn) conditions.push('neCell');
1537
- if (look.lastRow && isLastRow && look.firstColumn && isFirstColumn) conditions.push('swCell');
1538
- if (look.lastRow && isLastRow && look.lastColumn && isLastColumn) conditions.push('seCell');
1539
- return conditions;
1540
- }
1541
- function resolveTableLook(propertySources) {
1542
- const look = {
1543
- ...DEFAULT_TABLE_LOOK
1544
- };
1924
+ function paragraphAlignment(propertySources) {
1925
+ let direction = 'ltr';
1926
+ let justification = null;
1927
+ let hasJustification = false;
1545
1928
  for (const properties of propertySources){
1546
- const element = directChild(properties, 'tblLook');
1547
- if (!element) continue;
1548
- const encoded = work_docx_table_styles_wordAttribute(element, 'val')?.trim();
1549
- if (encoded && /^[0-9a-f]{1,4}$/i.test(encoded)) {
1550
- const value = Number.parseInt(encoded, 16);
1551
- look.firstRow = Boolean(value & TABLE_LOOK_BITS.firstRow);
1552
- look.lastRow = Boolean(value & TABLE_LOOK_BITS.lastRow);
1553
- look.firstColumn = Boolean(value & TABLE_LOOK_BITS.firstColumn);
1554
- look.lastColumn = Boolean(value & TABLE_LOOK_BITS.lastColumn);
1555
- look.noHorizontalBand = Boolean(value & TABLE_LOOK_BITS.noHorizontalBand);
1556
- look.noVerticalBand = Boolean(value & TABLE_LOOK_BITS.noVerticalBand);
1929
+ const bidi = directChild(properties, 'bidi');
1930
+ if (bidi) direction = onOffValue(bidi) ? 'rtl' : 'ltr';
1931
+ const source = directChild(properties, 'jc');
1932
+ if (source) {
1933
+ hasJustification = true;
1934
+ justification = wordAttribute(source, 'val')?.trim() ?? null;
1557
1935
  }
1558
- assignLookFlag(look, 'firstRow', element, 'firstRow');
1559
- assignLookFlag(look, 'lastRow', element, 'lastRow');
1560
- assignLookFlag(look, 'firstColumn', element, 'firstColumn');
1561
- assignLookFlag(look, 'lastColumn', element, 'lastColumn');
1562
- assignLookFlag(look, 'noHorizontalBand', element, 'noHBand');
1563
- assignLookFlag(look, 'noVerticalBand', element, 'noVBand');
1564
1936
  }
1565
- return look;
1566
- }
1567
- function assignLookFlag(look, key, element, attributeName) {
1568
- const value = onOffValue(work_docx_table_styles_wordAttribute(element, attributeName));
1569
- if (void 0 !== value) look[key] = value;
1937
+ if (!hasJustification || !justification) return null;
1938
+ if ('center' === justification) return 'center';
1939
+ if ('left' === justification) return 'left';
1940
+ if ('right' === justification) return 'right';
1941
+ if ('start' === justification) return 'rtl' === direction ? 'right' : 'left';
1942
+ if ('end' === justification) return 'rtl' === direction ? 'left' : 'right';
1943
+ if ('both' === justification || 'distribute' === justification || 'highKashida' === justification || 'lowKashida' === justification || 'mediumKashida' === justification || 'thaiDistribute' === justification) return 'justify';
1944
+ return null;
1570
1945
  }
1571
- function resolveBandSize(propertySources, propertyName) {
1572
- let size = 1;
1573
- for (const properties of propertySources){
1574
- const element = directChild(properties, propertyName);
1575
- const value = Number(element ? work_docx_table_styles_wordAttribute(element, 'val') : void 0);
1576
- if (Number.isInteger(value) && value > 0 && value <= 64) size = value;
1577
- }
1578
- return size;
1579
- }
1580
- function tableCellPosition(table, targetCell) {
1581
- const rows = descendants(table, 'tr').filter((row)=>work_docx_table_styles_closestAncestor(row, 'tbl') === table);
1582
- const targetRow = work_docx_table_styles_closestAncestor(targetCell, 'tr');
1583
- if (!targetRow) return null;
1584
- const rowIndex = rows.indexOf(targetRow);
1585
- if (rowIndex < 0) return null;
1586
- const cells = rowCells(targetRow);
1587
- const cellIndex = cells.indexOf(targetCell);
1588
- if (cellIndex < 0) return null;
1589
- const columnStart = rowGridOffset(targetRow, 'gridBefore') + cells.slice(0, cellIndex).reduce((total, cell)=>total + cellGridSpan(cell), 0);
1590
- const columnEnd = columnStart + cellGridSpan(targetCell) - 1;
1591
- const columnCount = Math.max(1, ...rows.map((row)=>rowGridOffset(row, 'gridBefore') + rowCells(row).reduce((total, cell)=>total + cellGridSpan(cell), 0) + rowGridOffset(row, 'gridAfter')));
1592
- return {
1593
- rowIndex,
1594
- rowCount: rows.length,
1595
- columnStart,
1596
- columnEnd,
1597
- columnCount
1598
- };
1946
+ function onOffValue(element) {
1947
+ const value = wordAttribute(element, 'val')?.trim().toLowerCase();
1948
+ return '0' !== value && 'false' !== value && 'off' !== value;
1599
1949
  }
1600
- function rowCells(row) {
1601
- return descendants(row, 'tc').filter((cell)=>work_docx_table_styles_closestAncestor(cell, 'tr') === row);
1950
+ function wordAttribute(element, name) {
1951
+ return attribute(element, name) ?? attribute(element, `w:${name}`);
1602
1952
  }
1603
- function cellGridSpan(cell) {
1604
- const properties = directChild(cell, 'tcPr');
1605
- const gridSpan = properties ? directChild(properties, 'gridSpan') : void 0;
1606
- const value = Number(gridSpan ? work_docx_table_styles_wordAttribute(gridSpan, 'val') : void 0);
1607
- return Number.isInteger(value) && value > 0 && value <= 256 ? value : 1;
1953
+ function work_docx_paragraph_alignment_import_insertParagraphMarker(document, paragraph, properties, marker) {
1954
+ const run = document.createElementNS(work_docx_paragraph_alignment_import_WORD_NAMESPACE, 'w:r');
1955
+ const text = document.createElementNS(work_docx_paragraph_alignment_import_WORD_NAMESPACE, 'w:t');
1956
+ text.setAttributeNS(work_docx_paragraph_alignment_import_XML_NAMESPACE, 'xml:space', 'preserve');
1957
+ text.textContent = marker;
1958
+ run.append(text);
1959
+ paragraph.insertBefore(run, properties.nextSibling);
1608
1960
  }
1609
- function rowGridOffset(row, propertyName) {
1610
- const properties = directChild(row, 'trPr');
1611
- const element = properties ? directChild(properties, propertyName) : void 0;
1612
- const value = Number(element ? work_docx_table_styles_wordAttribute(element, 'val') : void 0);
1613
- return Number.isInteger(value) && value > 0 && value <= 256 ? value : 0;
1961
+ function insertParagraphProperties(document, paragraph) {
1962
+ const properties = document.createElementNS(work_docx_paragraph_alignment_import_WORD_NAMESPACE, 'w:pPr');
1963
+ paragraph.insertBefore(properties, paragraph.firstChild);
1964
+ return properties;
1614
1965
  }
1615
- function work_docx_table_styles_closestAncestor(element, localName) {
1616
- let current = element;
1617
- while(current){
1618
- if (current.localName === localName) return current;
1619
- current = current.parentElement;
1620
- }
1621
- return null;
1966
+ function closestParagraphBlock(element, markerNode) {
1967
+ const block = element?.closest('p, h1, h2, h3, h4, h5, h6, blockquote, li');
1968
+ if (!(block instanceof HTMLElement)) return null;
1969
+ return 'li' === block.tagName.toLowerCase() ? wrapListItemParagraph(block, markerNode) : block;
1622
1970
  }
1623
- function work_docx_table_styles_onOffAttribute(element, name) {
1624
- return onOffValue(work_docx_table_styles_wordAttribute(element, name)) ?? false;
1971
+ function wrapListItemParagraph(item, markerNode) {
1972
+ let anchor = markerNode;
1973
+ while(anchor.parentNode && anchor.parentNode !== item)anchor = anchor.parentNode;
1974
+ const children = Array.from(item.childNodes);
1975
+ const anchorIndex = children.indexOf(anchor);
1976
+ if (anchorIndex < 0) return item;
1977
+ let start = anchorIndex;
1978
+ let end = anchorIndex;
1979
+ while(start > 0 && !isListItemBlock(children[start - 1]))start -= 1;
1980
+ while(end + 1 < children.length && !isListItemBlock(children[end + 1]))end += 1;
1981
+ const paragraph = item.ownerDocument.createElement('p');
1982
+ const grouped = children.slice(start, end + 1);
1983
+ item.insertBefore(paragraph, grouped[0] ?? null);
1984
+ paragraph.append(...grouped);
1985
+ return paragraph;
1625
1986
  }
1626
- function onOffValue(value) {
1627
- if (null == value) return;
1628
- const normalized = value.trim().toLowerCase();
1629
- return '0' !== normalized && 'false' !== normalized && 'off' !== normalized;
1987
+ function isListItemBlock(node) {
1988
+ if (!(node instanceof HTMLElement)) return false;
1989
+ return [
1990
+ 'blockquote',
1991
+ 'div',
1992
+ 'h1',
1993
+ 'h2',
1994
+ 'h3',
1995
+ 'h4',
1996
+ 'h5',
1997
+ 'h6',
1998
+ 'hr',
1999
+ 'ol',
2000
+ 'p',
2001
+ 'pre',
2002
+ 'table',
2003
+ 'ul'
2004
+ ].includes(node.tagName.toLowerCase());
1630
2005
  }
1631
- function work_docx_table_styles_wordAttribute(element, name) {
1632
- return attribute(element, name) ?? attribute(element, `w:${name}`);
2006
+ function work_docx_paragraph_alignment_import_textNodes(root) {
2007
+ const document = root.ownerDocument;
2008
+ const walker = document?.createTreeWalker(root, NodeFilter.SHOW_TEXT);
2009
+ const nodes = [];
2010
+ if (!walker) return nodes;
2011
+ while(walker.nextNode())nodes.push(walker.currentNode);
2012
+ return nodes;
1633
2013
  }
1634
2014
  const work_docx_paragraph_direction_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
1635
2015
  const work_docx_paragraph_direction_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
@@ -1643,7 +2023,7 @@ function markDocxParagraphDirections(document, styleSource, tableStyleSource) {
1643
2023
  const sources = docxParagraphPropertySources(properties, styles, docxTableParagraphPropertySources(paragraph, tableStyles));
1644
2024
  const direction = paragraphDirection(sources);
1645
2025
  if (!direction) continue;
1646
- properties ??= insertParagraphProperties(document, paragraph);
2026
+ properties ??= work_docx_paragraph_direction_import_insertParagraphProperties(document, paragraph);
1647
2027
  const marker = `__A3S_WORK_PARAGRAPH_DIRECTION_${paragraphs.length + 1}__`;
1648
2028
  work_docx_paragraph_direction_import_insertParagraphMarker(document, paragraph, properties, marker);
1649
2029
  paragraphs.push({
@@ -1662,7 +2042,7 @@ function applyImportedDocxParagraphDirectionMarkers(document, markers) {
1662
2042
  ]));
1663
2043
  for (const node of work_docx_paragraph_direction_import_textNodes(document.body)){
1664
2044
  if (!node.data.includes('__A3S_WORK_PARAGRAPH_DIRECTION_')) continue;
1665
- const block = closestParagraphBlock(node.parentElement);
2045
+ const block = work_docx_paragraph_direction_import_closestParagraphBlock(node.parentElement);
1666
2046
  node.data = node.data.replace(PARAGRAPH_DIRECTION_MARKER_PATTERN, (marker)=>{
1667
2047
  const direction = directionByMarker.get(marker);
1668
2048
  if (block && direction) block.setAttribute('dir', direction);
@@ -1694,12 +2074,12 @@ function work_docx_paragraph_direction_import_insertParagraphMarker(document, pa
1694
2074
  run.append(text);
1695
2075
  paragraph.insertBefore(run, properties.nextSibling);
1696
2076
  }
1697
- function insertParagraphProperties(document, paragraph) {
2077
+ function work_docx_paragraph_direction_import_insertParagraphProperties(document, paragraph) {
1698
2078
  const properties = document.createElementNS(work_docx_paragraph_direction_import_WORD_NAMESPACE, 'w:pPr');
1699
2079
  paragraph.insertBefore(properties, paragraph.firstChild);
1700
2080
  return properties;
1701
2081
  }
1702
- function closestParagraphBlock(element) {
2082
+ function work_docx_paragraph_direction_import_closestParagraphBlock(element) {
1703
2083
  const block = element?.closest('p, h1, h2, h3, h4, h5, h6, blockquote, li');
1704
2084
  return block instanceof HTMLElement ? block : null;
1705
2085
  }
@@ -1711,114 +2091,117 @@ function work_docx_paragraph_direction_import_textNodes(root) {
1711
2091
  while(walker.nextNode())nodes.push(walker.currentNode);
1712
2092
  return nodes;
1713
2093
  }
1714
- const work_docx_paragraph_alignment_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
1715
- const work_docx_paragraph_alignment_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
1716
- const PARAGRAPH_ALIGNMENT_MARKER_PATTERN = /__A3S_WORK_PARAGRAPH_ALIGNMENT_\d+__/g;
1717
- function markDocxParagraphAlignments(document, styleSource, tableStyleSource) {
2094
+ const work_docx_paragraph_identity_import_WORD_2010_NAMESPACE = 'http://schemas.microsoft.com/office/word/2010/wordml';
2095
+ const work_docx_paragraph_identity_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
2096
+ const PARAGRAPH_IDENTITY_MARKER_PATTERN = /__A3S_WORK_PARAGRAPH_IDENTITY_\d+__/g;
2097
+ const MAX_PARAGRAPH_IDENTITIES = 65536;
2098
+ function markDocxParagraphIdentities(document) {
2099
+ const counts = wordIdentityIdCounts(document);
2100
+ const candidates = descendants(document, 'p').flatMap((element)=>{
2101
+ if (!DOCX_WORDPROCESSING_NAMESPACES.has(element.namespaceURI ?? '')) return [];
2102
+ const identity = wordParagraphIdentity(element);
2103
+ return identity ? [
2104
+ {
2105
+ element,
2106
+ identity
2107
+ }
2108
+ ] : [];
2109
+ });
2110
+ if (candidates.length > MAX_PARAGRAPH_IDENTITIES) throw new Error('DOCX exceeds the paragraph-identity limit.');
1718
2111
  const paragraphs = [];
1719
- const styles = resolveDocxParagraphStyleResolver(styleSource);
1720
- const tableStyles = resolveDocxTableStyleResolver(tableStyleSource);
1721
- for (const paragraph of descendants(document, 'p')){
1722
- let properties = directChild(paragraph, 'pPr');
1723
- const sources = docxParagraphPropertySources(properties, styles, docxTableParagraphPropertySources(paragraph, tableStyles));
1724
- const alignment = paragraphAlignment(sources);
1725
- if (!alignment) continue;
1726
- properties ??= work_docx_paragraph_alignment_import_insertParagraphProperties(document, paragraph);
1727
- const marker = `__A3S_WORK_PARAGRAPH_ALIGNMENT_${paragraphs.length + 1}__`;
1728
- work_docx_paragraph_alignment_import_insertParagraphMarker(document, paragraph, properties, marker);
2112
+ for (const candidate of candidates){
2113
+ if (1 !== counts.get(candidate.identity.paragraphId)) continue;
2114
+ const marker = `__A3S_WORK_PARAGRAPH_IDENTITY_${paragraphs.length + 1}__`;
2115
+ work_docx_paragraph_identity_import_insertParagraphMarker(candidate.element, marker);
1729
2116
  paragraphs.push({
1730
2117
  marker,
1731
- alignment
2118
+ ...candidate.identity
1732
2119
  });
1733
2120
  }
1734
2121
  return {
1735
2122
  paragraphs
1736
2123
  };
1737
2124
  }
1738
- function applyImportedDocxParagraphAlignmentMarkers(document, markers) {
1739
- const alignmentByMarker = new Map(markers.paragraphs.map(({ marker, alignment })=>[
2125
+ function wordIdentityIdCounts(document) {
2126
+ const counts = new Map();
2127
+ for (const localName of [
2128
+ 'p',
2129
+ 'tr'
2130
+ ])for (const element of descendants(document, localName)){
2131
+ if (!DOCX_WORDPROCESSING_NAMESPACES.has(element.namespaceURI ?? '')) continue;
2132
+ const paragraphId = normalizeDocumentParagraphId(word2010Attribute(element, 'paraId'));
2133
+ if (paragraphId) counts.set(paragraphId, (counts.get(paragraphId) ?? 0) + 1);
2134
+ }
2135
+ return counts;
2136
+ }
2137
+ function applyImportedDocxParagraphIdentityMarkers(document, markers) {
2138
+ const identities = new Map(markers.paragraphs.map(({ marker, paragraphId, textId })=>[
1740
2139
  marker,
1741
- alignment
2140
+ {
2141
+ paragraphId,
2142
+ textId
2143
+ }
1742
2144
  ]));
1743
- for (const node of work_docx_paragraph_alignment_import_textNodes(document.body))if (node.data.includes('__A3S_WORK_PARAGRAPH_ALIGNMENT_')) node.data = node.data.replace(PARAGRAPH_ALIGNMENT_MARKER_PATTERN, (marker)=>{
1744
- const alignment = alignmentByMarker.get(marker);
1745
- const block = alignment ? work_docx_paragraph_alignment_import_closestParagraphBlock(node.parentElement, node) : null;
1746
- if (block && alignment) block.style.textAlign = alignment;
2145
+ for (const node of work_docx_paragraph_identity_import_textNodes(document.body))if (node.data.includes('__A3S_WORK_PARAGRAPH_IDENTITY_')) node.data = node.data.replace(PARAGRAPH_IDENTITY_MARKER_PATTERN, (marker)=>{
2146
+ const identity = identities.get(marker);
2147
+ const block = identity ? work_docx_paragraph_identity_import_closestParagraphBlock(node.parentElement, node) : null;
2148
+ if (identity && block) applyDocumentParagraphIdentityToElement(block, identity);
1747
2149
  return '';
1748
2150
  });
1749
2151
  document.body.normalize();
1750
2152
  }
1751
- function hasImportedDocxParagraphAlignmentMarkers(markers) {
2153
+ function hasImportedDocxParagraphIdentityMarkers(markers) {
1752
2154
  return markers.paragraphs.length > 0;
1753
2155
  }
1754
- function paragraphAlignment(propertySources) {
1755
- let direction = 'ltr';
1756
- let justification = null;
1757
- let hasJustification = false;
1758
- for (const properties of propertySources){
1759
- const bidi = directChild(properties, 'bidi');
1760
- if (bidi) direction = work_docx_paragraph_alignment_import_onOffValue(bidi) ? 'rtl' : 'ltr';
1761
- const source = directChild(properties, 'jc');
1762
- if (source) {
1763
- hasJustification = true;
1764
- justification = work_docx_paragraph_alignment_import_wordAttribute(source, 'val')?.trim() ?? null;
1765
- }
1766
- }
1767
- if (!hasJustification || !justification) return null;
1768
- if ('center' === justification) return 'center';
1769
- if ('left' === justification) return 'left';
1770
- if ('right' === justification) return 'right';
1771
- if ('start' === justification) return 'rtl' === direction ? 'right' : 'left';
1772
- if ('end' === justification) return 'rtl' === direction ? 'left' : 'right';
1773
- if ('both' === justification || 'distribute' === justification || 'highKashida' === justification || 'lowKashida' === justification || 'mediumKashida' === justification || 'thaiDistribute' === justification) return 'justify';
1774
- return null;
1775
- }
1776
- function work_docx_paragraph_alignment_import_onOffValue(element) {
1777
- const value = work_docx_paragraph_alignment_import_wordAttribute(element, 'val')?.trim().toLowerCase();
1778
- return '0' !== value && 'false' !== value && 'off' !== value;
2156
+ function wordParagraphIdentity(paragraph) {
2157
+ return normalizeDocumentParagraphIdentity({
2158
+ paragraphId: word2010Attribute(paragraph, 'paraId'),
2159
+ textId: word2010Attribute(paragraph, 'textId')
2160
+ });
1779
2161
  }
1780
- function work_docx_paragraph_alignment_import_wordAttribute(element, name) {
1781
- return attribute(element, name) ?? attribute(element, `w:${name}`);
2162
+ function word2010Attribute(element, localName) {
2163
+ return Array.from(element.attributes).find((item)=>xmlAttributeLocalName(item) === localName && xmlAttributeNamespace(element, item) === work_docx_paragraph_identity_import_WORD_2010_NAMESPACE)?.value ?? null;
1782
2164
  }
1783
- function work_docx_paragraph_alignment_import_insertParagraphMarker(document, paragraph, properties, marker) {
1784
- const run = document.createElementNS(work_docx_paragraph_alignment_import_WORD_NAMESPACE, 'w:r');
1785
- const text = document.createElementNS(work_docx_paragraph_alignment_import_WORD_NAMESPACE, 'w:t');
1786
- text.setAttributeNS(work_docx_paragraph_alignment_import_XML_NAMESPACE, 'xml:space', 'preserve');
2165
+ function work_docx_paragraph_identity_import_insertParagraphMarker(paragraph, marker) {
2166
+ const document = paragraph.ownerDocument;
2167
+ const namespace = paragraph.namespaceURI ?? '';
2168
+ const prefix = paragraph.prefix ? `${paragraph.prefix}:` : '';
2169
+ const run = document.createElementNS(namespace, `${prefix}r`);
2170
+ const text = document.createElementNS(namespace, `${prefix}t`);
2171
+ text.setAttributeNS(work_docx_paragraph_identity_import_XML_NAMESPACE, 'xml:space', 'preserve');
1787
2172
  text.textContent = marker;
1788
2173
  run.append(text);
1789
- paragraph.insertBefore(run, properties.nextSibling);
1790
- }
1791
- function work_docx_paragraph_alignment_import_insertParagraphProperties(document, paragraph) {
1792
- const properties = document.createElementNS(work_docx_paragraph_alignment_import_WORD_NAMESPACE, 'w:pPr');
1793
- paragraph.insertBefore(properties, paragraph.firstChild);
1794
- return properties;
2174
+ const properties = directChildren(paragraph, 'pPr').find((element)=>DOCX_WORDPROCESSING_NAMESPACES.has(element.namespaceURI ?? ''));
2175
+ paragraph.insertBefore(run, properties?.nextSibling ?? paragraph.firstChild);
1795
2176
  }
1796
- function work_docx_paragraph_alignment_import_closestParagraphBlock(element, markerNode) {
1797
- const block = element?.closest('p, h1, h2, h3, h4, h5, h6, blockquote, li');
1798
- if (!(block instanceof HTMLElement)) return null;
1799
- return 'li' === block.tagName.toLowerCase() ? wrapListItemParagraph(block, markerNode) : block;
2177
+ function work_docx_paragraph_identity_import_closestParagraphBlock(element, markerNode) {
2178
+ const explicit = element?.closest('p, h1, h2, h3, h4, h5, h6, figcaption');
2179
+ if (explicit instanceof HTMLElement) return explicit;
2180
+ const container = element?.closest('li, blockquote, td, th, div');
2181
+ return container instanceof HTMLElement ? wrapParagraphSegment(container, markerNode) : null;
1800
2182
  }
1801
- function wrapListItemParagraph(item, markerNode) {
2183
+ function wrapParagraphSegment(container, markerNode) {
1802
2184
  let anchor = markerNode;
1803
- while(anchor.parentNode && anchor.parentNode !== item)anchor = anchor.parentNode;
1804
- const children = Array.from(item.childNodes);
2185
+ while(anchor.parentNode && anchor.parentNode !== container)anchor = anchor.parentNode;
2186
+ const children = Array.from(container.childNodes);
1805
2187
  const anchorIndex = children.indexOf(anchor);
1806
- if (anchorIndex < 0) return item;
2188
+ if (anchorIndex < 0) return container;
1807
2189
  let start = anchorIndex;
1808
2190
  let end = anchorIndex;
1809
- while(start > 0 && !isListItemBlock(children[start - 1]))start -= 1;
1810
- while(end + 1 < children.length && !isListItemBlock(children[end + 1]))end += 1;
1811
- const paragraph = item.ownerDocument.createElement('p');
2191
+ while(start > 0 && !isParagraphBoundary(children[start - 1]))start -= 1;
2192
+ while(end + 1 < children.length && !isParagraphBoundary(children[end + 1]))end += 1;
2193
+ const paragraph = container.ownerDocument.createElement('p');
1812
2194
  const grouped = children.slice(start, end + 1);
1813
- item.insertBefore(paragraph, grouped[0] ?? null);
2195
+ container.insertBefore(paragraph, grouped[0] ?? null);
1814
2196
  paragraph.append(...grouped);
1815
2197
  return paragraph;
1816
2198
  }
1817
- function isListItemBlock(node) {
2199
+ function isParagraphBoundary(node) {
1818
2200
  if (!(node instanceof HTMLElement)) return false;
1819
2201
  return [
1820
2202
  'blockquote',
1821
2203
  'div',
2204
+ 'figcaption',
1822
2205
  'h1',
1823
2206
  'h2',
1824
2207
  'h3',
@@ -1833,9 +2216,8 @@ function isListItemBlock(node) {
1833
2216
  'ul'
1834
2217
  ].includes(node.tagName.toLowerCase());
1835
2218
  }
1836
- function work_docx_paragraph_alignment_import_textNodes(root) {
1837
- const document = root.ownerDocument;
1838
- const walker = document?.createTreeWalker(root, NodeFilter.SHOW_TEXT);
2219
+ function work_docx_paragraph_identity_import_textNodes(root) {
2220
+ const walker = root.ownerDocument?.createTreeWalker(root, NodeFilter.SHOW_TEXT);
1839
2221
  const nodes = [];
1840
2222
  if (!walker) return nodes;
1841
2223
  while(walker.nextNode())nodes.push(walker.currentNode);
@@ -2011,10 +2393,18 @@ function paragraphPagination(sources) {
2011
2393
  const keepWithNext = directChild(properties, 'keepNext');
2012
2394
  const pageBreakBefore = directChild(properties, 'pageBreakBefore');
2013
2395
  const widowControl = directChild(properties, 'widowControl');
2396
+ const contextualSpacing = directChild(properties, 'contextualSpacing');
2397
+ const outlineLevel = directChild(properties, 'outlineLvl');
2398
+ const defaultCollapsed = parseDocxParagraphDefaultCollapsed(properties);
2014
2399
  if (keepLines) pagination.keepLines = work_docx_paragraph_pagination_import_onOffValue(keepLines);
2015
2400
  if (keepWithNext) pagination.keepWithNext = work_docx_paragraph_pagination_import_onOffValue(keepWithNext);
2016
2401
  if (pageBreakBefore) pagination.pageBreakBefore = work_docx_paragraph_pagination_import_onOffValue(pageBreakBefore);
2017
2402
  if (widowControl) pagination.widowControl = work_docx_paragraph_pagination_import_onOffValue(widowControl);
2403
+ if (contextualSpacing) pagination.contextualSpacing = work_docx_paragraph_pagination_import_onOffValue(contextualSpacing);
2404
+ const outline = integerValue(outlineLevel);
2405
+ if (null !== outline && outline <= 9) pagination.outlineLevel = outline;
2406
+ if ('valid' === defaultCollapsed.status) pagination.defaultCollapsed = defaultCollapsed.value;
2407
+ else if ('invalid' === defaultCollapsed.status) delete pagination.defaultCollapsed;
2018
2408
  }
2019
2409
  return pagination;
2020
2410
  }
@@ -2044,6 +2434,14 @@ function applyParagraphPagination(element, pagination) {
2044
2434
  setBooleanAttribute(element, 'data-office-keep-with-next', pagination.keepWithNext);
2045
2435
  setBooleanAttribute(element, 'data-office-page-break-before', pagination.pageBreakBefore);
2046
2436
  setBooleanAttribute(element, 'data-office-widow-control', pagination.widowControl);
2437
+ setBooleanAttribute(element, 'data-office-contextual-spacing', pagination.contextualSpacing);
2438
+ setBooleanAttribute(element, 'data-office-default-collapsed', pagination.defaultCollapsed);
2439
+ if (void 0 !== pagination.outlineLevel) element.dataset.officeOutlineLevel = String(pagination.outlineLevel);
2440
+ }
2441
+ function integerValue(element) {
2442
+ if (!element) return null;
2443
+ const value = Number(attribute(element, 'val') ?? attribute(element, 'w:val'));
2444
+ return Number.isSafeInteger(value) && value >= 0 ? value : null;
2047
2445
  }
2048
2446
  function setBooleanAttribute(element, name, value) {
2049
2447
  if (void 0 !== value) element.setAttribute(name, String(value));
@@ -2195,93 +2593,6 @@ function work_docx_paragraph_spacing_import_textNodes(root) {
2195
2593
  while(walker.nextNode())nodes.push(walker.currentNode);
2196
2594
  return nodes;
2197
2595
  }
2198
- function createDocxThemeResolver(themeDocument) {
2199
- if (!themeDocument) return {
2200
- colors: new Map(),
2201
- fonts: new Map()
2202
- };
2203
- const fonts = new Map();
2204
- const fontScheme = firstDescendant(themeDocument, 'fontScheme');
2205
- addThemeFontFamily(fonts, 'major', fontScheme ? directChild(fontScheme, 'majorFont') : void 0);
2206
- addThemeFontFamily(fonts, 'minor', fontScheme ? directChild(fontScheme, 'minorFont') : void 0);
2207
- const colors = new Map();
2208
- const colorScheme = firstDescendant(themeDocument, 'clrScheme');
2209
- if (colorScheme) for (const entry of directChildren(colorScheme)){
2210
- const color = themeColorValue(directChildren(entry)[0]);
2211
- if (color) colors.set(entry.localName.toLowerCase(), color);
2212
- }
2213
- return {
2214
- colors,
2215
- fonts
2216
- };
2217
- }
2218
- function resolveDocxThemeResolver(source) {
2219
- return isDocxThemeResolver(source) ? source : createDocxThemeResolver(source);
2220
- }
2221
- function docxThemeFont(resolver, key) {
2222
- return key ? resolver.fonts.get(key.trim().toLowerCase()) : void 0;
2223
- }
2224
- function docxThemeColor(resolver, key, tint, shade) {
2225
- const color = key ? resolver.colors.get(key.trim().toLowerCase()) : void 0;
2226
- if (!color) return;
2227
- const channels = [
2228
- Number.parseInt(color.slice(0, 2), 16),
2229
- Number.parseInt(color.slice(2, 4), 16),
2230
- Number.parseInt(color.slice(4, 6), 16)
2231
- ];
2232
- const shadeFactor = hexFactor(shade);
2233
- const tintFactor = hexFactor(tint);
2234
- const transformed = channels.map((channel)=>{
2235
- const shaded = void 0 === shadeFactor ? channel : channel * shadeFactor;
2236
- const tinted = void 0 === tintFactor ? shaded : shaded + (255 - shaded) * tintFactor;
2237
- return Math.max(0, Math.min(255, Math.round(tinted)));
2238
- });
2239
- return transformed.map((channel)=>channel.toString(16).padStart(2, '0')).join('');
2240
- }
2241
- function addThemeFontFamily(fonts, prefix, family) {
2242
- if (!family) return;
2243
- const latin = typeface(directChild(family, 'latin'));
2244
- const eastAsia = typeface(directChild(family, 'ea')) || scriptTypeface(family, [
2245
- 'Hans',
2246
- 'Hant',
2247
- 'Jpan',
2248
- 'Hang'
2249
- ]) || latin;
2250
- const complex = typeface(directChild(family, 'cs')) || latin;
2251
- if (latin) {
2252
- fonts.set(`${prefix}ascii`, latin);
2253
- fonts.set(`${prefix}hansi`, latin);
2254
- }
2255
- if (eastAsia) fonts.set(`${prefix}eastasia`, eastAsia);
2256
- if (complex) fonts.set(`${prefix}bidi`, complex);
2257
- }
2258
- function scriptTypeface(family, scripts) {
2259
- const fonts = directChildren(family, 'font');
2260
- for (const script of scripts){
2261
- const font = fonts.find((candidate)=>drawingAttribute(candidate, "script") === script);
2262
- const value = font ? typeface(font) : void 0;
2263
- if (value) return value;
2264
- }
2265
- }
2266
- function typeface(element) {
2267
- const value = element ? drawingAttribute(element, 'typeface')?.trim() : void 0;
2268
- return value || void 0;
2269
- }
2270
- function themeColorValue(element) {
2271
- if (!element) return;
2272
- const value = 'sysClr' === element.localName ? drawingAttribute(element, 'lastClr') : drawingAttribute(element, 'val');
2273
- return value && /^[0-9a-f]{6}$/i.test(value) ? value.toLowerCase() : void 0;
2274
- }
2275
- function drawingAttribute(element, name) {
2276
- return attribute(element, name) ?? attribute(element, `a:${name}`);
2277
- }
2278
- function hexFactor(value) {
2279
- if (!value || !/^[0-9a-f]{2}$/i.test(value)) return;
2280
- return Number.parseInt(value, 16) / 255;
2281
- }
2282
- function isDocxThemeResolver(source) {
2283
- return Boolean(source && 'colors' in source && source.colors instanceof Map && 'fonts' in source && source.fonts instanceof Map);
2284
- }
2285
2596
  const work_docx_run_formatting_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
2286
2597
  const work_docx_run_formatting_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
2287
2598
  const RUN_FORMATTING_MARKER_PATTERN = /__A3S_WORK_RUN_(?:START|END)_\d+__/g;
@@ -2331,6 +2642,8 @@ function resolvedRunFormatting(propertySources, theme, runText) {
2331
2642
  let complexFontSize;
2332
2643
  let color;
2333
2644
  let backgroundColor;
2645
+ let themeColor;
2646
+ let themeFill;
2334
2647
  let bold;
2335
2648
  let complexBold;
2336
2649
  let italic;
@@ -2368,21 +2681,38 @@ function resolvedRunFormatting(propertySources, theme, runText) {
2368
2681
  if (colorElement) {
2369
2682
  const value = work_docx_run_formatting_import_wordAttribute(colorElement, 'val')?.trim();
2370
2683
  const themed = docxThemeColor(theme, work_docx_run_formatting_import_wordAttribute(colorElement, 'themeColor'), work_docx_run_formatting_import_wordAttribute(colorElement, 'themeTint'), work_docx_run_formatting_import_wordAttribute(colorElement, 'themeShade'));
2371
- if (themed) color = `#${themed}`;
2372
- else if (value?.toLowerCase() === 'auto') color = 'inherit';
2373
- else if (value && /^[0-9a-f]{6}$/i.test(value)) color = `#${value.toLowerCase()}`;
2684
+ if (themed) {
2685
+ color = `#${themed}`;
2686
+ themeColor = themeReference(colorElement, 'themeColor', 'themeTint', 'themeShade', color);
2687
+ } else if (value?.toLowerCase() === 'auto') {
2688
+ color = 'inherit';
2689
+ themeColor = void 0;
2690
+ } else if (value && /^[0-9a-f]{6}$/i.test(value)) {
2691
+ color = `#${value.toLowerCase()}`;
2692
+ themeColor = void 0;
2693
+ }
2374
2694
  }
2375
2695
  const highlight = directChild(properties, 'highlight');
2376
2696
  if (highlight) {
2377
2697
  const value = work_docx_run_formatting_import_wordAttribute(highlight, 'val')?.trim().toLowerCase();
2378
- if (value) backgroundColor = wordHighlightColor(value);
2698
+ if (value) {
2699
+ backgroundColor = wordHighlightColor(value);
2700
+ themeFill = void 0;
2701
+ }
2379
2702
  } else {
2380
2703
  const shading = directChild(properties, 'shd');
2381
2704
  const fill = shading ? work_docx_run_formatting_import_wordAttribute(shading, 'fill')?.trim() : void 0;
2382
2705
  const themed = shading ? docxThemeColor(theme, work_docx_run_formatting_import_wordAttribute(shading, 'themeFill'), work_docx_run_formatting_import_wordAttribute(shading, 'themeFillTint'), work_docx_run_formatting_import_wordAttribute(shading, 'themeFillShade')) : void 0;
2383
- if (themed) backgroundColor = `#${themed}`;
2384
- else if (fill?.toLowerCase() === 'auto') backgroundColor = 'transparent';
2385
- else if (fill && /^[0-9a-f]{6}$/i.test(fill)) backgroundColor = `#${fill.toLowerCase()}`;
2706
+ if (themed) {
2707
+ backgroundColor = `#${themed}`;
2708
+ themeFill = themeReference(shading, 'themeFill', 'themeFillTint', 'themeFillShade', backgroundColor);
2709
+ } else if (fill?.toLowerCase() === 'auto') {
2710
+ backgroundColor = 'transparent';
2711
+ themeFill = void 0;
2712
+ } else if (fill && /^[0-9a-f]{6}$/i.test(fill)) {
2713
+ backgroundColor = `#${fill.toLowerCase()}`;
2714
+ themeFill = void 0;
2715
+ }
2386
2716
  }
2387
2717
  }
2388
2718
  const fontSlot = true === complexScriptFormatting || true === rightToLeft ? 'complex' : docxFontSlotForText(runText, fontHint);
@@ -2426,6 +2756,12 @@ function resolvedRunFormatting(propertySources, theme, runText) {
2426
2756
  } : {},
2427
2757
  ...backgroundColor ? {
2428
2758
  backgroundColor
2759
+ } : {},
2760
+ ...themeColor ? {
2761
+ themeColor
2762
+ } : {},
2763
+ ...themeFill ? {
2764
+ themeFill
2429
2765
  } : {}
2430
2766
  };
2431
2767
  }
@@ -2455,7 +2791,11 @@ function formattingMarkup(document, formatting) {
2455
2791
  if (void 0 !== formatting.wordSnapToGrid) span.dataset.officeWordSnapToGrid = String(formatting.wordSnapToGrid);
2456
2792
  if (void 0 !== formatting.fontSize) span.style.fontSize = `${work_docx_run_formatting_import_formatNumber(formatting.fontSize)}pt`;
2457
2793
  if (formatting.color) span.style.color = formatting.color;
2794
+ const themeColor = serializeDocxThemeReference(formatting.themeColor ?? null);
2795
+ if (themeColor) span.dataset.officeThemeColor = themeColor;
2458
2796
  if (formatting.backgroundColor) span.style.backgroundColor = formatting.backgroundColor;
2797
+ const themeFill = serializeDocxThemeReference(formatting.themeFill ?? null);
2798
+ if (themeFill) span.dataset.officeThemeFill = themeFill;
2459
2799
  const html = span.outerHTML;
2460
2800
  const tags = [
2461
2801
  ...formatting.bold ? [
@@ -2478,6 +2818,26 @@ function formattingMarkup(document, formatting) {
2478
2818
  ].reverse().map((tag)=>`</${tag}>`).join('')}</span>`
2479
2819
  };
2480
2820
  }
2821
+ function themeReference(element, themeName, tintName, shadeName, resolved) {
2822
+ const theme = work_docx_run_formatting_import_wordAttribute(element, themeName)?.trim();
2823
+ if (!theme) return;
2824
+ const tint = normalizedByteHex(work_docx_run_formatting_import_wordAttribute(element, tintName));
2825
+ const shade = normalizedByteHex(work_docx_run_formatting_import_wordAttribute(element, shadeName));
2826
+ return {
2827
+ theme,
2828
+ resolved,
2829
+ ...tint ? {
2830
+ tint
2831
+ } : {},
2832
+ ...shade ? {
2833
+ shade
2834
+ } : {}
2835
+ };
2836
+ }
2837
+ function normalizedByteHex(value) {
2838
+ const normalized = value?.trim().toUpperCase();
2839
+ return normalized && /^[0-9A-F]{2}$/.test(normalized) ? normalized : void 0;
2840
+ }
2481
2841
  function overriddenBoolean(current, next) {
2482
2842
  return void 0 === next ? current : next;
2483
2843
  }
@@ -2805,18 +3165,21 @@ function markDocxTableCells(document, themeSource, tableStyleSource) {
2805
3165
  ] : []
2806
3166
  ];
2807
3167
  const borders = importedTableCellBorders(cell, layers, theme);
2808
- const backgroundColor = importedTableCellBackgroundColor(layers, theme);
3168
+ const background = importedTableCellBackgroundColor(layers, theme);
2809
3169
  const verticalAlign = importedTableCellVerticalAlign(layers);
2810
3170
  const margins = importedTableCellMargins(layers);
2811
- if (!backgroundColor && !verticalAlign && !borders && !margins) continue;
3171
+ if (!background && !verticalAlign && !borders && !margins) continue;
2812
3172
  const paragraph = firstTableCellParagraph(document, cell);
2813
3173
  if (!paragraph) continue;
2814
3174
  const marker = `__A3S_WORK_TABLE_CELL_${cells.length + 1}__`;
2815
3175
  insertCellMarker(document, paragraph, marker);
2816
3176
  cells.push({
2817
3177
  marker,
2818
- ...backgroundColor ? {
2819
- backgroundColor
3178
+ ...background ? {
3179
+ backgroundColor: background.color
3180
+ } : {},
3181
+ ...background?.theme ? {
3182
+ themeFill: background.theme
2820
3183
  } : {},
2821
3184
  ...verticalAlign ? {
2822
3185
  verticalAlign
@@ -2857,6 +3220,8 @@ function applyCellFormat(cell, format) {
2857
3220
  cell.dataset.officeCellFill = format.backgroundColor;
2858
3221
  cell.style.backgroundColor = format.backgroundColor;
2859
3222
  }
3223
+ const themeFill = serializeDocxThemeReference(format.themeFill ?? null);
3224
+ if (themeFill) cell.dataset.officeCellThemeFill = themeFill;
2860
3225
  if (format.verticalAlign) {
2861
3226
  cell.dataset.officeCellVerticalAlign = format.verticalAlign;
2862
3227
  cell.style.verticalAlign = format.verticalAlign;
@@ -2872,6 +3237,8 @@ function applyCellFormat(cell, format) {
2872
3237
  if (border) borders[edge] = {
2873
3238
  ...border
2874
3239
  };
3240
+ const theme = serializeDocxThemeReference(border?.theme ?? null);
3241
+ if (theme) cell.dataset[`officeCellBorderTheme${capitalize(edge)}`] = theme;
2875
3242
  }
2876
3243
  const rendered = renderDocumentTableBorders(borders);
2877
3244
  for (const [name, value] of Object.entries(rendered))if ('style' !== name) cell.setAttribute(name, value);
@@ -3000,7 +3367,10 @@ function parseBorder(edge, theme) {
3000
3367
  return {
3001
3368
  color,
3002
3369
  style,
3003
- width: Math.max(0.5, Math.min(6, Math.round(2 * width) / 2))
3370
+ width: Math.max(0.5, Math.min(6, Math.round(2 * width) / 2)),
3371
+ ...themed ? {
3372
+ theme: work_docx_table_cell_import_themeReference(edge, 'themeColor', 'themeTint', 'themeShade', color)
3373
+ } : {}
3004
3374
  };
3005
3375
  }
3006
3376
  function importedTableCellBackgroundColor(layers, theme) {
@@ -3015,7 +3385,36 @@ function importedTableCellBackgroundColor(layers, theme) {
3015
3385
  }
3016
3386
  function tableCellBackgroundColor(shading, theme) {
3017
3387
  const themed = docxThemeColor(theme, attribute(shading, 'themeFill'), attribute(shading, 'themeFillTint'), attribute(shading, 'themeFillShade'));
3018
- return themed ? `#${themed}` : ooxmlColor(attribute(shading, 'fill'));
3388
+ if (themed) {
3389
+ const color = `#${themed}`;
3390
+ return {
3391
+ color,
3392
+ theme: work_docx_table_cell_import_themeReference(shading, 'themeFill', 'themeFillTint', 'themeFillShade', color)
3393
+ };
3394
+ }
3395
+ const color = ooxmlColor(attribute(shading, 'fill'));
3396
+ return color ? {
3397
+ color
3398
+ } : null;
3399
+ }
3400
+ function work_docx_table_cell_import_themeReference(element, themeName, tintName, shadeName, resolved) {
3401
+ const theme = attribute(element, themeName)?.trim() ?? '';
3402
+ const tint = work_docx_table_cell_import_normalizedByteHex(attribute(element, tintName));
3403
+ const shade = work_docx_table_cell_import_normalizedByteHex(attribute(element, shadeName));
3404
+ return {
3405
+ theme,
3406
+ resolved,
3407
+ ...tint ? {
3408
+ tint
3409
+ } : {},
3410
+ ...shade ? {
3411
+ shade
3412
+ } : {}
3413
+ };
3414
+ }
3415
+ function work_docx_table_cell_import_normalizedByteHex(value) {
3416
+ const normalized = value?.trim().toUpperCase();
3417
+ return normalized && /^[0-9A-F]{2}$/.test(normalized) ? normalized : void 0;
3019
3418
  }
3020
3419
  function importedTableCellVerticalAlign(layers) {
3021
3420
  let alignment = null;
@@ -3079,20 +3478,33 @@ function work_docx_table_cell_import_textNodes(root) {
3079
3478
  while(walker.nextNode())nodes.push(walker.currentNode);
3080
3479
  return nodes;
3081
3480
  }
3481
+ function capitalize(value) {
3482
+ return `${value.slice(0, 1).toUpperCase()}${value.slice(1)}`;
3483
+ }
3082
3484
  const work_docx_table_row_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
3485
+ const work_docx_table_row_import_WORD_2010_NAMESPACE = 'http://schemas.microsoft.com/office/word/2010/wordml';
3083
3486
  const work_docx_table_row_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
3084
3487
  const TABLE_ROW_MARKER_PATTERN = /__A3S_WORK_TABLE_ROW_\d+__/g;
3085
3488
  const work_docx_table_row_import_PIXELS_PER_TWIP = 96 / 1440;
3086
3489
  function markDocxTableRows(document) {
3490
+ const wordRows = descendants(document, 'tr').filter((row)=>DOCX_WORDPROCESSING_NAMESPACES.has(row.namespaceURI ?? ''));
3491
+ const identities = new Map();
3492
+ const identityCounts = work_docx_table_row_import_wordIdentityIdCounts(document);
3493
+ for (const row of wordRows){
3494
+ const identity = wordTableRowIdentity(row);
3495
+ if (identity) identities.set(row, identity);
3496
+ }
3087
3497
  const rows = [];
3088
- for (const row of descendants(document, 'tr')){
3498
+ for (const row of wordRows){
3089
3499
  const properties = directChild(row, 'trPr');
3090
3500
  const cantSplit = properties ? directChild(properties, 'cantSplit') : void 0;
3091
3501
  const repeatHeader = properties ? directChild(properties, 'tblHeader') : void 0;
3092
3502
  const height = properties ? directChild(properties, 'trHeight') : void 0;
3093
3503
  const rowHeight = height ? work_docx_table_row_import_twipsToPixels(Number(attribute(height, 'val'))) : null;
3094
3504
  const rowHeightRule = tableRowHeightRule(attribute(height ?? row, 'hRule'));
3095
- if (!cantSplit && !repeatHeader && null === rowHeight) continue;
3505
+ const rowIdentity = identities.get(row);
3506
+ const uniqueIdentity = rowIdentity && 1 === identityCounts.get(rowIdentity.rowId) ? rowIdentity : null;
3507
+ if (!cantSplit && !repeatHeader && null === rowHeight && !uniqueIdentity) continue;
3096
3508
  const paragraph = firstTableRowParagraph(document, row);
3097
3509
  if (!paragraph) continue;
3098
3510
  const marker = `__A3S_WORK_TABLE_ROW_${rows.length + 1}__`;
@@ -3105,6 +3517,7 @@ function markDocxTableRows(document) {
3105
3517
  ...repeatHeader ? {
3106
3518
  repeatHeader: work_docx_table_row_import_onOffValue(repeatHeader)
3107
3519
  } : {},
3520
+ ...uniqueIdentity ?? {},
3108
3521
  ...null !== rowHeight ? {
3109
3522
  rowHeight
3110
3523
  } : {},
@@ -3117,6 +3530,18 @@ function markDocxTableRows(document) {
3117
3530
  rows
3118
3531
  };
3119
3532
  }
3533
+ function work_docx_table_row_import_wordIdentityIdCounts(document) {
3534
+ const counts = new Map();
3535
+ for (const localName of [
3536
+ 'p',
3537
+ 'tr'
3538
+ ])for (const element of descendants(document, localName)){
3539
+ if (!DOCX_WORDPROCESSING_NAMESPACES.has(element.namespaceURI ?? '')) continue;
3540
+ const paragraphId = normalizeDocumentParagraphId(work_docx_table_row_import_word2010Attribute(element, 'paraId'));
3541
+ if (paragraphId) counts.set(paragraphId, (counts.get(paragraphId) ?? 0) + 1);
3542
+ }
3543
+ return counts;
3544
+ }
3120
3545
  function applyImportedDocxTableRowMarkers(document, markers) {
3121
3546
  const rowByMarker = new Map(markers.rows.map((row)=>[
3122
3547
  row.marker,
@@ -3128,6 +3553,7 @@ function applyImportedDocxTableRowMarkers(document, markers) {
3128
3553
  node.data = node.data.replace(TABLE_ROW_MARKER_PATTERN, (marker)=>{
3129
3554
  const properties = rowByMarker.get(marker);
3130
3555
  if (row instanceof HTMLTableRowElement && properties) {
3556
+ applyDocumentTableRowIdentityToElement(row, properties);
3131
3557
  work_docx_table_row_import_setBooleanAttribute(row, 'data-office-cant-split', properties.cantSplit);
3132
3558
  work_docx_table_row_import_setBooleanAttribute(row, 'data-office-repeat-header', properties.repeatHeader);
3133
3559
  if (void 0 !== properties.rowHeight) {
@@ -3149,19 +3575,32 @@ function firstTableRowParagraph(document, row) {
3149
3575
  if (!cell) return null;
3150
3576
  const existing = directChild(cell, 'p') ?? descendants(cell, 'p').find((paragraph)=>work_docx_table_row_import_closestAncestor(paragraph, 'tr') === row);
3151
3577
  if (existing) return existing;
3152
- const paragraph = document.createElementNS(work_docx_table_row_import_WORD_NAMESPACE, 'w:p');
3578
+ const namespace = cell.namespaceURI ?? work_docx_table_row_import_WORD_NAMESPACE;
3579
+ const prefix = cell.prefix ? `${cell.prefix}:` : '';
3580
+ const paragraph = document.createElementNS(namespace, `${prefix}p`);
3153
3581
  cell.append(paragraph);
3154
3582
  return paragraph;
3155
3583
  }
3156
3584
  function insertRowMarker(document, paragraph, marker) {
3157
- const run = document.createElementNS(work_docx_table_row_import_WORD_NAMESPACE, 'w:r');
3158
- const text = document.createElementNS(work_docx_table_row_import_WORD_NAMESPACE, 'w:t');
3585
+ const namespace = paragraph.namespaceURI ?? work_docx_table_row_import_WORD_NAMESPACE;
3586
+ const prefix = paragraph.prefix ? `${paragraph.prefix}:` : '';
3587
+ const run = document.createElementNS(namespace, `${prefix}r`);
3588
+ const text = document.createElementNS(namespace, `${prefix}t`);
3159
3589
  text.setAttributeNS(work_docx_table_row_import_XML_NAMESPACE, 'xml:space', 'preserve');
3160
3590
  text.textContent = marker;
3161
3591
  run.append(text);
3162
3592
  const properties = directChild(paragraph, 'pPr');
3163
3593
  paragraph.insertBefore(run, properties?.nextSibling ?? paragraph.firstChild);
3164
3594
  }
3595
+ function wordTableRowIdentity(row) {
3596
+ return normalizeDocumentTableRowIdentity({
3597
+ rowId: work_docx_table_row_import_word2010Attribute(row, 'paraId'),
3598
+ rowTextId: work_docx_table_row_import_word2010Attribute(row, 'textId')
3599
+ });
3600
+ }
3601
+ function work_docx_table_row_import_word2010Attribute(element, localName) {
3602
+ return Array.from(element.attributes).find((item)=>xmlAttributeLocalName(item) === localName && xmlAttributeNamespace(element, item) === work_docx_table_row_import_WORD_2010_NAMESPACE)?.value ?? null;
3603
+ }
3165
3604
  function work_docx_table_row_import_onOffValue(element) {
3166
3605
  const value = (attribute(element, 'val') ?? attribute(element, 'w:val'))?.trim().toLowerCase();
3167
3606
  return '0' !== value && 'false' !== value && 'off' !== value;
@@ -3210,7 +3649,8 @@ function markDocxTableSizing(document, tableStyleSource) {
3210
3649
  tables.push({
3211
3650
  marker,
3212
3651
  geometry: importedTableGeometry(docxTablePropertySources(table, tableStyles)),
3213
- columnWidths
3652
+ columnWidths,
3653
+ columnPercentages: importedColumnPercentages(table, columnWidths)
3214
3654
  });
3215
3655
  }
3216
3656
  return {
@@ -3231,6 +3671,7 @@ function applyImportedDocxTableSizingMarkers(document, markers) {
3231
3671
  table.dataset.officeTableImported = 'true';
3232
3672
  applyDocumentTableGeometryToElement(table, sizing.geometry);
3233
3673
  if (sizing.columnWidths.length) applyColumnWidths(table, sizing.columnWidths);
3674
+ if (sizing.columnPercentages.length) applyColumnPercentages(table, sizing.columnPercentages);
3234
3675
  }
3235
3676
  return '';
3236
3677
  });
@@ -3341,9 +3782,9 @@ function percentageValue(value) {
3341
3782
  }
3342
3783
  function applyColumnWidths(table, columnWidths) {
3343
3784
  const occupiedUntilRow = [];
3344
- Array.from(table.rows).forEach((row, rowIndex)=>{
3785
+ ownedTableRows(table).forEach((row, rowIndex)=>{
3345
3786
  let columnIndex = 0;
3346
- for (const cell of Array.from(row.cells)){
3787
+ for (const cell of ownedTableRowCells(row)){
3347
3788
  while((occupiedUntilRow[columnIndex] ?? 0) > rowIndex)columnIndex += 1;
3348
3789
  const widths = columnWidths.slice(columnIndex, columnIndex + cell.colSpan);
3349
3790
  if (widths.length === cell.colSpan) cell.setAttribute('colwidth', widths.join(','));
@@ -3352,6 +3793,70 @@ function applyColumnWidths(table, columnWidths) {
3352
3793
  }
3353
3794
  });
3354
3795
  }
3796
+ function applyColumnPercentages(table, columnPercentages) {
3797
+ const occupiedUntilRow = [];
3798
+ ownedTableRows(table).forEach((row, rowIndex)=>{
3799
+ let columnIndex = 0;
3800
+ for (const cell of ownedTableRowCells(row)){
3801
+ while((occupiedUntilRow[columnIndex] ?? 0) > rowIndex)columnIndex += 1;
3802
+ const percentages = columnPercentages.slice(columnIndex, columnIndex + cell.colSpan);
3803
+ if (percentages.length === cell.colSpan) cell.dataset.officeColumnWidthsPercent = percentages.join(',');
3804
+ if (cell.rowSpan > 1) for(let offset = 0; offset < cell.colSpan; offset += 1)occupiedUntilRow[columnIndex + offset] = rowIndex + cell.rowSpan;
3805
+ columnIndex += cell.colSpan;
3806
+ }
3807
+ });
3808
+ }
3809
+ function ownedTableRows(table) {
3810
+ return Array.from(table.rows).filter((row)=>row.closest('table') === table);
3811
+ }
3812
+ function ownedTableRowCells(row) {
3813
+ return Array.from(row.cells).filter((cell)=>cell.closest('tr') === row);
3814
+ }
3815
+ function importedColumnPercentages(table, columnWidths) {
3816
+ const columnCount = columnWidths.length || logicalTableColumnCount(table);
3817
+ const percentages = Array.from({
3818
+ length: columnCount
3819
+ }, ()=>null);
3820
+ const rows = directChildren(table, 'tr');
3821
+ for (const row of rows){
3822
+ let column = rowGridBefore(row);
3823
+ for (const cell of directChildren(row, 'tc')){
3824
+ const properties = directChild(cell, 'tcPr');
3825
+ const gridSpan = directChild(properties ?? cell, 'gridSpan');
3826
+ const span = Math.max(1, Number(gridSpan ? attribute(gridSpan, 'val') : null) || 1);
3827
+ const width = directChild(properties ?? cell, 'tcW');
3828
+ const total = width && 'pct' === attribute(width, 'type') ? percentageValue(attribute(width, 'w')) : null;
3829
+ if (null !== total) {
3830
+ const physical = columnWidths.slice(column, column + span);
3831
+ const physicalTotal = physical.reduce((sum, value)=>sum + value, 0);
3832
+ for(let offset = 0; offset < span; offset += 1){
3833
+ if (null !== percentages[column + offset]) continue;
3834
+ const share = physicalTotal > 0 ? total * ((physical[offset] ?? 0) / physicalTotal) : total / span;
3835
+ percentages[column + offset] = Math.round(100 * share) / 100;
3836
+ }
3837
+ }
3838
+ column += span;
3839
+ }
3840
+ }
3841
+ return percentages.every((value)=>null !== value && value > 0) ? percentages : [];
3842
+ }
3843
+ function logicalTableColumnCount(table) {
3844
+ return directChildren(table, 'tr').reduce((maximum, row)=>{
3845
+ const count = directChildren(row, 'tc').reduce((sum, cell)=>{
3846
+ const properties = directChild(cell, 'tcPr');
3847
+ const gridSpan = directChild(properties ?? cell, 'gridSpan');
3848
+ const span = Number(gridSpan ? attribute(gridSpan, 'val') : null);
3849
+ return sum + (Number.isSafeInteger(span) && span > 0 ? span : 1);
3850
+ }, rowGridBefore(row));
3851
+ return Math.max(maximum, count);
3852
+ }, 0);
3853
+ }
3854
+ function rowGridBefore(row) {
3855
+ const properties = directChild(row, 'trPr');
3856
+ const gridBefore = directChild(properties ?? row, 'gridBefore');
3857
+ const value = Number(gridBefore ? attribute(gridBefore, 'val') : null);
3858
+ return Number.isSafeInteger(value) && value > 0 ? value : 0;
3859
+ }
3355
3860
  function firstTableParagraph(document, table) {
3356
3861
  const cell = descendants(table, 'tc').find((candidate)=>work_docx_table_sizing_import_closestAncestor(candidate, 'tbl') === table);
3357
3862
  if (!cell) return null;
@@ -3390,7 +3895,6 @@ function work_docx_table_sizing_import_textNodes(root) {
3390
3895
  while(walker.nextNode())nodes.push(walker.currentNode);
3391
3896
  return nodes;
3392
3897
  }
3393
- const work_docx_import_TWIPS_PER_MILLIMETER = 1440 / 25.4;
3394
3898
  const work_docx_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
3395
3899
  const work_docx_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
3396
3900
  async function prepareDocxImport(buffer) {
@@ -3413,6 +3917,10 @@ async function prepareDocxImport(buffer) {
3413
3917
  captions: [],
3414
3918
  references: []
3415
3919
  },
3920
+ bookmarkMarkers: {
3921
+ bookmarks: [],
3922
+ references: []
3923
+ },
3416
3924
  changeMarkers: {
3417
3925
  changes: []
3418
3926
  },
@@ -3423,6 +3931,9 @@ async function prepareDocxImport(buffer) {
3423
3931
  fieldMarkers: {
3424
3932
  fields: []
3425
3933
  },
3934
+ equationMarkers: {
3935
+ equations: []
3936
+ },
3426
3937
  citationMarkers: {
3427
3938
  citations: [],
3428
3939
  bibliographies: []
@@ -3433,6 +3944,9 @@ async function prepareDocxImport(buffer) {
3433
3944
  imageLayoutMarkers: {
3434
3945
  images: []
3435
3946
  },
3947
+ paragraphIdentityMarkers: {
3948
+ paragraphs: []
3949
+ },
3436
3950
  paragraphAlignmentMarkers: {
3437
3951
  paragraphs: []
3438
3952
  },
@@ -3445,6 +3959,16 @@ async function prepareDocxImport(buffer) {
3445
3959
  paragraphPaginationMarkers: {
3446
3960
  paragraphs: []
3447
3961
  },
3962
+ paragraphBorderMarkers: {
3963
+ paragraphs: [],
3964
+ invalidCount: 0,
3965
+ spoofedCount: 0
3966
+ },
3967
+ paragraphShadingMarkers: {
3968
+ paragraphs: [],
3969
+ invalidCount: 0,
3970
+ spoofedCount: 0
3971
+ },
3448
3972
  paragraphSpacingMarkers: {
3449
3973
  paragraphs: []
3450
3974
  },
@@ -3469,14 +3993,20 @@ async function prepareDocxImport(buffer) {
3469
3993
  };
3470
3994
  const document = await archive.xml('word/document.xml');
3471
3995
  const pageColor = importDocxPageColor(document);
3996
+ const paragraphIdentityMarkers = markDocxParagraphIdentities(document);
3472
3997
  const numbering = archive.has('word/numbering.xml') ? await archive.xml('word/numbering.xml') : null;
3473
3998
  const commentMarkers = await markDocxComments(document, archive);
3474
3999
  const changeMarkers = markDocxTextChanges(document);
3475
4000
  const captionMarkers = markDocxCaptionFields(document);
4001
+ const bookmarkMarkers = markDocxBookmarks(document);
3476
4002
  const citationMarkers = markDocxCitationFields(document);
3477
4003
  const fieldMarkers = markDocxBodyFields(document);
3478
4004
  const listMarkers = markDocxLists(document, numbering);
3479
- const imageLayoutMarkers = markDocxImageLayouts(document);
4005
+ const imageLayoutMarkerState = createImportedDocxImageLayoutMarkerState();
4006
+ const imageLayoutMarkers = markDocxImageLayouts(document, imageLayoutMarkerState);
4007
+ const noteImageMarkers = await markDocxNoteImageLayouts(archive, imageLayoutMarkerState);
4008
+ imageLayoutMarkers.images.push(...noteImageMarkers.markers.images);
4009
+ const equationMarkers = await markDocxPackageEquations(archive, document, noteImageMarkers.parts);
3480
4010
  const paragraphStylesDocument = archive.has('word/styles.xml') ? await archive.xml('word/styles.xml') : null;
3481
4011
  const paragraphStyles = createDocxParagraphStyleResolver(paragraphStylesDocument);
3482
4012
  const tableStyles = createDocxTableStyleResolver(paragraphStylesDocument);
@@ -3487,16 +4017,20 @@ async function prepareDocxImport(buffer) {
3487
4017
  const paragraphPaginationMarkers = markDocxParagraphPagination(document, paragraphStyles, tableStyles);
3488
4018
  const themePath = archive.paths('word/theme/').find((path)=>/\/theme\d*\.xml$/i.test(path));
3489
4019
  const themeDocument = themePath ? await archive.xml(themePath) : null;
3490
- const runFormattingMarkers = markDocxRunFormatting(document, paragraphStyles, themeDocument, tableStyles);
4020
+ const settings = archive.has('word/settings.xml') ? await archive.xml('word/settings.xml') : null;
4021
+ const pageMarginSettings = inspectDocxPageMarginSettings(settings);
4022
+ const theme = createDocxThemeResolver(themeDocument, settings);
4023
+ const paragraphBorderMarkers = markDocxParagraphBorders(document, paragraphStyles, theme, tableStyles);
4024
+ const paragraphShadingMarkers = markDocxParagraphShading(document, paragraphStyles, theme, tableStyles);
4025
+ const runFormattingMarkers = markDocxRunFormatting(document, paragraphStyles, theme, tableStyles);
3491
4026
  const tabStopMarkers = markDocxParagraphTabStops(document, paragraphStyles, tableStyles);
3492
- const tableCellMarkers = markDocxTableCells(document, themeDocument, tableStyles);
4027
+ const tableCellMarkers = markDocxTableCells(document, theme, tableStyles);
3493
4028
  const tableRowMarkers = markDocxTableRows(document);
3494
4029
  const tableSizingMarkers = markDocxTableSizing(document, tableStyles);
3495
- const settings = archive.has('word/settings.xml') ? await archive.xml('word/settings.xml') : null;
3496
4030
  const trackChanges = Boolean(settings && firstDescendant(settings, 'trackRevisions')) || changeMarkers.changes.length > 0;
3497
4031
  const sectionElements = effectiveSectionProperties(document);
3498
4032
  if (!sectionElements.length) return {
3499
- conversionBuffer: hasImportedDocxCaptionMarkers(captionMarkers) || hasImportedDocxChangeMarkers(changeMarkers) || hasImportedDocxCommentMarkers(commentMarkers) || hasImportedDocxCitationMarkers(citationMarkers) || hasImportedDocxFieldMarkers(fieldMarkers) || hasImportedDocxListMarkers(listMarkers) || hasImportedDocxImageLayoutMarkers(imageLayoutMarkers) || hasImportedDocxParagraphAlignmentMarkers(paragraphAlignmentMarkers) || hasImportedDocxParagraphDirectionMarkers(paragraphDirectionMarkers) || hasImportedDocxParagraphIndentMarkers(paragraphIndentMarkers) || hasImportedDocxParagraphSpacingMarkers(paragraphSpacingMarkers) || hasImportedDocxParagraphPaginationMarkers(paragraphPaginationMarkers) || hasImportedDocxRunFormattingMarkers(runFormattingMarkers) || hasImportedDocxParagraphTabStopMarkers(tabStopMarkers) || hasImportedDocxTableCellMarkers(tableCellMarkers) || hasImportedDocxTableRowMarkers(tableRowMarkers) || hasImportedDocxTableSizingMarkers(tableSizingMarkers) ? await writeDocumentXml(buffer, document) : buffer,
4033
+ conversionBuffer: hasImportedDocxCaptionMarkers(captionMarkers) || hasImportedDocxBookmarkMarkers(bookmarkMarkers) || hasImportedDocxChangeMarkers(changeMarkers) || hasImportedDocxCommentMarkers(commentMarkers) || hasImportedDocxCitationMarkers(citationMarkers) || hasImportedDocxFieldMarkers(fieldMarkers) || equationMarkers.changed || hasImportedDocxListMarkers(listMarkers) || hasImportedDocxImageLayoutMarkers(imageLayoutMarkers) || hasImportedDocxParagraphIdentityMarkers(paragraphIdentityMarkers) || hasImportedDocxParagraphAlignmentMarkers(paragraphAlignmentMarkers) || hasImportedDocxParagraphDirectionMarkers(paragraphDirectionMarkers) || hasImportedDocxParagraphIndentMarkers(paragraphIndentMarkers) || hasImportedDocxParagraphSpacingMarkers(paragraphSpacingMarkers) || hasImportedDocxParagraphBorderMarkers(paragraphBorderMarkers) || hasImportedDocxParagraphShadingMarkers(paragraphShadingMarkers) || hasImportedDocxParagraphPaginationMarkers(paragraphPaginationMarkers) || hasImportedDocxRunFormattingMarkers(runFormattingMarkers) || hasImportedDocxParagraphTabStopMarkers(tabStopMarkers) || hasImportedDocxTableCellMarkers(tableCellMarkers) || hasImportedDocxTableRowMarkers(tableRowMarkers) || hasImportedDocxTableSizingMarkers(tableSizingMarkers) ? await writeDocumentXml(buffer, document, equationMarkers.parts) : buffer,
3500
4034
  sections: [
3501
4035
  {
3502
4036
  id: 'document-section-1',
@@ -3505,16 +4039,21 @@ async function prepareDocxImport(buffer) {
3505
4039
  ],
3506
4040
  pageColor,
3507
4041
  captionMarkers,
4042
+ bookmarkMarkers,
3508
4043
  changeMarkers,
3509
4044
  commentMarkers,
3510
4045
  fieldMarkers,
4046
+ equationMarkers: equationMarkers.markers,
3511
4047
  citationMarkers,
3512
4048
  listMarkers,
3513
4049
  imageLayoutMarkers,
4050
+ paragraphIdentityMarkers,
3514
4051
  paragraphAlignmentMarkers,
3515
4052
  paragraphDirectionMarkers,
3516
4053
  paragraphIndentMarkers,
3517
4054
  paragraphPaginationMarkers,
4055
+ paragraphBorderMarkers,
4056
+ paragraphShadingMarkers,
3518
4057
  paragraphSpacingMarkers,
3519
4058
  runFormattingMarkers,
3520
4059
  tabStopMarkers,
@@ -3529,7 +4068,7 @@ async function prepareDocxImport(buffer) {
3529
4068
  const sections = [];
3530
4069
  let previous = fallback;
3531
4070
  for (const [index, element] of sectionElements.entries()){
3532
- const layout = await parseSectionLayout(element, archive, relationships, previous, oddEvenPageChrome);
4071
+ const layout = await parseSectionLayout(element, archive, relationships, previous, oddEvenPageChrome, theme, pageMarginSettings);
3533
4072
  sections.push({
3534
4073
  id: `document-section-${index + 1}`,
3535
4074
  layout
@@ -3538,20 +4077,25 @@ async function prepareDocxImport(buffer) {
3538
4077
  }
3539
4078
  if (sections.length > 1) addSectionMarkers(document, sectionElements);
3540
4079
  return {
3541
- conversionBuffer: sections.length > 1 || hasImportedDocxCaptionMarkers(captionMarkers) || hasImportedDocxChangeMarkers(changeMarkers) || hasImportedDocxCommentMarkers(commentMarkers) || hasImportedDocxCitationMarkers(citationMarkers) || hasImportedDocxFieldMarkers(fieldMarkers) || hasImportedDocxListMarkers(listMarkers) || hasImportedDocxImageLayoutMarkers(imageLayoutMarkers) || hasImportedDocxParagraphAlignmentMarkers(paragraphAlignmentMarkers) || hasImportedDocxParagraphDirectionMarkers(paragraphDirectionMarkers) || hasImportedDocxParagraphIndentMarkers(paragraphIndentMarkers) || hasImportedDocxParagraphSpacingMarkers(paragraphSpacingMarkers) || hasImportedDocxParagraphPaginationMarkers(paragraphPaginationMarkers) || hasImportedDocxRunFormattingMarkers(runFormattingMarkers) || hasImportedDocxParagraphTabStopMarkers(tabStopMarkers) || hasImportedDocxTableCellMarkers(tableCellMarkers) || hasImportedDocxTableRowMarkers(tableRowMarkers) || hasImportedDocxTableSizingMarkers(tableSizingMarkers) ? await writeDocumentXml(buffer, document) : buffer,
4080
+ conversionBuffer: sections.length > 1 || hasImportedDocxCaptionMarkers(captionMarkers) || hasImportedDocxBookmarkMarkers(bookmarkMarkers) || hasImportedDocxChangeMarkers(changeMarkers) || hasImportedDocxCommentMarkers(commentMarkers) || hasImportedDocxCitationMarkers(citationMarkers) || hasImportedDocxFieldMarkers(fieldMarkers) || equationMarkers.changed || hasImportedDocxListMarkers(listMarkers) || hasImportedDocxImageLayoutMarkers(imageLayoutMarkers) || hasImportedDocxParagraphIdentityMarkers(paragraphIdentityMarkers) || hasImportedDocxParagraphAlignmentMarkers(paragraphAlignmentMarkers) || hasImportedDocxParagraphDirectionMarkers(paragraphDirectionMarkers) || hasImportedDocxParagraphIndentMarkers(paragraphIndentMarkers) || hasImportedDocxParagraphSpacingMarkers(paragraphSpacingMarkers) || hasImportedDocxParagraphBorderMarkers(paragraphBorderMarkers) || hasImportedDocxParagraphShadingMarkers(paragraphShadingMarkers) || hasImportedDocxParagraphPaginationMarkers(paragraphPaginationMarkers) || hasImportedDocxRunFormattingMarkers(runFormattingMarkers) || hasImportedDocxParagraphTabStopMarkers(tabStopMarkers) || hasImportedDocxTableCellMarkers(tableCellMarkers) || hasImportedDocxTableRowMarkers(tableRowMarkers) || hasImportedDocxTableSizingMarkers(tableSizingMarkers) ? await writeDocumentXml(buffer, document, equationMarkers.parts) : buffer,
3542
4081
  sections,
3543
4082
  pageColor,
3544
4083
  captionMarkers,
4084
+ bookmarkMarkers,
3545
4085
  changeMarkers,
3546
4086
  commentMarkers,
3547
4087
  fieldMarkers,
4088
+ equationMarkers: equationMarkers.markers,
3548
4089
  citationMarkers,
3549
4090
  listMarkers,
3550
4091
  imageLayoutMarkers,
4092
+ paragraphIdentityMarkers,
3551
4093
  paragraphAlignmentMarkers,
3552
4094
  paragraphDirectionMarkers,
3553
4095
  paragraphIndentMarkers,
3554
4096
  paragraphPaginationMarkers,
4097
+ paragraphBorderMarkers,
4098
+ paragraphShadingMarkers,
3555
4099
  paragraphSpacingMarkers,
3556
4100
  runFormattingMarkers,
3557
4101
  tabStopMarkers,
@@ -3565,6 +4109,9 @@ async function prepareDocxImport(buffer) {
3565
4109
  function applyDocxSectionsToHtml(html, sections, captionMarkers = {
3566
4110
  captions: [],
3567
4111
  references: []
4112
+ }, bookmarkMarkers = {
4113
+ bookmarks: [],
4114
+ references: []
3568
4115
  }, changeMarkers = {
3569
4116
  changes: []
3570
4117
  }, commentMarkers = {
@@ -3572,6 +4119,8 @@ function applyDocxSectionsToHtml(html, sections, captionMarkers = {
3572
4119
  ranges: []
3573
4120
  }, fieldMarkers = {
3574
4121
  fields: []
4122
+ }, equationMarkers = {
4123
+ equations: []
3575
4124
  }, citationMarkers = {
3576
4125
  citations: [],
3577
4126
  bibliographies: []
@@ -3579,6 +4128,8 @@ function applyDocxSectionsToHtml(html, sections, captionMarkers = {
3579
4128
  lists: []
3580
4129
  }, imageLayoutMarkers = {
3581
4130
  images: []
4131
+ }, paragraphIdentityMarkers = {
4132
+ paragraphs: []
3582
4133
  }, paragraphAlignmentMarkers = {
3583
4134
  paragraphs: []
3584
4135
  }, runFormattingMarkers = {
@@ -3589,6 +4140,14 @@ function applyDocxSectionsToHtml(html, sections, captionMarkers = {
3589
4140
  paragraphs: []
3590
4141
  }, paragraphSpacingMarkers = {
3591
4142
  paragraphs: []
4143
+ }, paragraphBorderMarkers = {
4144
+ paragraphs: [],
4145
+ invalidCount: 0,
4146
+ spoofedCount: 0
4147
+ }, paragraphShadingMarkers = {
4148
+ paragraphs: [],
4149
+ invalidCount: 0,
4150
+ spoofedCount: 0
3592
4151
  }, paragraphPaginationMarkers = {
3593
4152
  paragraphs: []
3594
4153
  }, bibliography, tabStopMarkers = {
@@ -3603,14 +4162,18 @@ function applyDocxSectionsToHtml(html, sections, captionMarkers = {
3603
4162
  }) {
3604
4163
  const document = new DOMParser().parseFromString(html, 'text/html');
3605
4164
  applyImportedDocxRunFormattingMarkers(document, runFormattingMarkers);
4165
+ applyImportedDocxBookmarkMarkers(document, bookmarkMarkers);
3606
4166
  applyImportedDocxCaptionMarkers(document, captionMarkers);
3607
4167
  applyImportedDocxCitationMarkers(document, citationMarkers);
3608
4168
  applyImportedDocxFieldMarkers(document, fieldMarkers);
4169
+ applyImportedDocxEquationMarkers(document, equationMarkers);
3609
4170
  applyImportedDocxListMarkers(document, listMarkers);
3610
4171
  applyImportedDocxImageLayoutMarkers(document, imageLayoutMarkers);
3611
4172
  applyImportedDocxParagraphDirectionMarkers(document, paragraphDirectionMarkers);
3612
4173
  applyImportedDocxParagraphIndentMarkers(document, paragraphIndentMarkers);
3613
4174
  applyImportedDocxParagraphSpacingMarkers(document, paragraphSpacingMarkers);
4175
+ applyImportedDocxParagraphBorderMarkers(document, paragraphBorderMarkers);
4176
+ applyImportedDocxParagraphShadingMarkers(document, paragraphShadingMarkers);
3614
4177
  applyImportedDocxParagraphPaginationMarkers(document, paragraphPaginationMarkers);
3615
4178
  applyImportedDocxParagraphTabStopMarkers(document, tabStopMarkers);
3616
4179
  applyImportedDocxParagraphAlignmentMarkers(document, paragraphAlignmentMarkers);
@@ -3619,6 +4182,7 @@ function applyDocxSectionsToHtml(html, sections, captionMarkers = {
3619
4182
  applyImportedDocxTableRowMarkers(document, tableRowMarkers);
3620
4183
  applyImportedDocxChangeMarkers(document, changeMarkers);
3621
4184
  applyImportedDocxCommentMarkers(document, commentMarkers);
4185
+ applyImportedDocxParagraphIdentityMarkers(document, paragraphIdentityMarkers);
3622
4186
  const notes = extractMammothDocumentNotes(document);
3623
4187
  const sourceNodes = Array.from(document.body.childNodes);
3624
4188
  document.body.replaceChildren();
@@ -3643,7 +4207,7 @@ function applyDocxSectionsToHtml(html, sections, captionMarkers = {
3643
4207
  document.body.append(missing);
3644
4208
  }
3645
4209
  placeMammothDocumentNotes(document, notes);
3646
- return normalizeDocumentCitationsHtml(normalizeDocumentFieldsHtml(normalizeDocumentCaptionsHtml(normalizeDocumentNotesHtml(document.body.innerHTML))), bibliography);
4210
+ return normalizeDocumentBookmarkReferencesHtml(normalizeDocumentBookmarksHtml(normalizeDocumentCitationsHtml(normalizeDocumentFieldsHtml(normalizeDocumentCaptionsHtml(normalizeDocumentNotesHtml(document.body.innerHTML))), bibliography)));
3647
4211
  }
3648
4212
  async function readDocxLayout(buffer) {
3649
4213
  const prepared = await prepareDocxImport(buffer);
@@ -3654,24 +4218,22 @@ async function readDocxLayout(buffer) {
3654
4218
  } : {}
3655
4219
  };
3656
4220
  }
3657
- async function parseSectionLayout(section, archive, relationships, previous, oddEvenPageChrome) {
3658
- const pageSize = firstDescendant(section, 'pgSz');
3659
- const width = work_docx_import_numberAttribute(pageSize, 'w');
3660
- const height = work_docx_import_numberAttribute(pageSize, 'h');
3661
- const orientation = 'landscape' === attribute(pageSize ?? section, 'orient') || width > 0 && height > 0 && width > height ? 'landscape' : pageSize ? 'portrait' : previous.orientation;
3662
- const shortEdge = Math.min(width || 11906, height || 16838);
3663
- const size = pageSize ? Math.abs(shortEdge - 12240) < Math.abs(shortEdge - 11906) ? 'letter' : 'a4' : previous.pageSize;
3664
- const marginsElement = firstDescendant(section, 'pgMar');
4221
+ async function parseSectionLayout(section, archive, relationships, previous, oddEvenPageChrome, theme, pageMarginSettings) {
4222
+ const parsedPageGeometry = parseDocxPageGeometry(section, previous.pageGeometry);
4223
+ const pageGeometry = null === parsedPageGeometry ? previous.pageGeometry : parsedPageGeometry;
4224
+ const parsedPaperSource = parseDocxPaperSource(section, previous.paperSource);
4225
+ const paperSource = null === parsedPaperSource ? previous.paperSource : parsedPaperSource;
3665
4226
  const columnsElement = firstDescendant(section, 'cols');
3666
4227
  const documentGridElement = directChild(section, 'docGrid');
4228
+ const pageBorders = parseDocxPageBorders(section, theme);
4229
+ const parsedPageMargins = parseDocxPageMargins(section, pageMarginSettings, documentPageMarginsForLayout(previous));
4230
+ const pageMargins = null === parsedPageMargins ? documentPageMarginsForLayout(previous) : parsedPageMargins;
3667
4231
  const pageChrome = await importSectionPageChrome(section, archive, relationships, previous, oddEvenPageChrome);
3668
4232
  const pageNumberStart = work_docx_import_numberAttribute(firstDescendant(section, 'pgNumType'), 'start');
3669
- return {
3670
- pageSize: size,
3671
- orientation,
3672
- margins: marginsElement ? parseMargins(marginsElement, previous.margins) : {
3673
- ...previous.margins
3674
- },
4233
+ const layout = {
4234
+ pageSize: previous.pageSize,
4235
+ orientation: previous.orientation,
4236
+ margins: documentPageMarginBody(pageMargins, previous.margins),
3675
4237
  columns: columnsElement ? importDocxColumns(columnsElement, previous.columns) : {
3676
4238
  ...previous.columns
3677
4239
  },
@@ -3682,10 +4244,23 @@ async function parseSectionLayout(section, archive, relationships, previous, odd
3682
4244
  ...previous.documentGrid
3683
4245
  }
3684
4246
  } : {},
4247
+ ...pageBorders ? {
4248
+ pageBorders
4249
+ } : {},
4250
+ ...pageMargins ? {
4251
+ pageMargins
4252
+ } : {},
4253
+ ...pageGeometry ? {
4254
+ pageGeometry
4255
+ } : {},
4256
+ ...paperSource ? {
4257
+ paperSource
4258
+ } : {},
3685
4259
  breakAfter: parseSectionBreak(firstDescendant(section, 'type')),
3686
4260
  ...pageChrome,
3687
4261
  pageNumberStart: pageNumberStart > 0 ? pageNumberStart : void 0
3688
4262
  };
4263
+ return pageGeometry ? applyDocumentPageGeometry(layout, pageGeometry) : layout;
3689
4264
  }
3690
4265
  function parseDocumentGrid(element) {
3691
4266
  const sourceType = attribute(element, 'type');
@@ -3710,13 +4285,43 @@ function addSectionMarkers(document, sectionElements) {
3710
4285
  paragraph.parentNode.insertBefore(marker, paragraph.nextSibling);
3711
4286
  }
3712
4287
  }
3713
- async function writeDocumentXml(buffer, document) {
4288
+ async function writeDocumentXml(buffer, document, additionalParts = []) {
3714
4289
  const zip = await jszip.loadAsync(buffer);
3715
- zip.file('word/document.xml', new XMLSerializer().serializeToString(document));
4290
+ zip.file('word/document.xml', serializeDocxConversionXml(document));
4291
+ for (const part of additionalParts)zip.file(part.path, serializeDocxConversionXml(part.document));
3716
4292
  return zip.generateAsync({
3717
4293
  type: 'arraybuffer'
3718
4294
  });
3719
4295
  }
4296
+ function serializeDocxConversionXml(document) {
4297
+ const dialects = new Map([
4298
+ [
4299
+ 'http://purl.oclc.org/ooxml/wordprocessingml/main',
4300
+ 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'
4301
+ ],
4302
+ [
4303
+ 'http://purl.oclc.org/ooxml/officeDocument/math',
4304
+ 'http://schemas.openxmlformats.org/officeDocument/2006/math'
4305
+ ],
4306
+ [
4307
+ 'http://purl.oclc.org/ooxml/officeDocument/relationships',
4308
+ 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'
4309
+ ],
4310
+ [
4311
+ 'http://purl.oclc.org/ooxml/drawingml/wordprocessingDrawing',
4312
+ 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing'
4313
+ ],
4314
+ [
4315
+ 'http://purl.oclc.org/ooxml/drawingml/main',
4316
+ 'http://schemas.openxmlformats.org/drawingml/2006/main'
4317
+ ],
4318
+ [
4319
+ 'http://purl.oclc.org/ooxml/drawingml/picture',
4320
+ 'http://schemas.openxmlformats.org/drawingml/2006/picture'
4321
+ ]
4322
+ ]);
4323
+ return new XMLSerializer().serializeToString(document).replace(/(\sxmlns(?::[A-Za-z_][A-Za-z0-9_.-]*)?\s*=\s*)(["'])([^"']+)\2/g, (_declaration, assignment, quote, namespace)=>`${assignment}${quote}${dialects.get(namespace) ?? namespace}${quote}`);
4324
+ }
3720
4325
  function effectiveSectionProperties(document) {
3721
4326
  return descendants(document, 'sectPr').filter((element)=>!work_docx_import_closestAncestor(element, 'sectPrChange'));
3722
4327
  }
@@ -3741,14 +4346,6 @@ function isSectionMarker(node, index) {
3741
4346
  function sectionMarker(index) {
3742
4347
  return `__A3S_WORK_DOCUMENT_SECTION_${index + 1}__`;
3743
4348
  }
3744
- function parseMargins(element, fallback) {
3745
- return {
3746
- top: work_docx_import_twipsToMillimeters(work_docx_import_numberAttribute(element, 'top'), fallback.top),
3747
- right: work_docx_import_twipsToMillimeters(work_docx_import_numberAttribute(element, 'right'), fallback.right),
3748
- bottom: work_docx_import_twipsToMillimeters(work_docx_import_numberAttribute(element, 'bottom'), fallback.bottom),
3749
- left: work_docx_import_twipsToMillimeters(work_docx_import_numberAttribute(element, 'left'), fallback.left)
3750
- };
3751
- }
3752
4349
  function parseSectionBreak(element) {
3753
4350
  if (!element) return 'nextPage';
3754
4351
  const value = attribute(element, 'val');
@@ -3768,8 +4365,4 @@ function work_docx_import_closestAncestor(element, localName) {
3768
4365
  }
3769
4366
  return null;
3770
4367
  }
3771
- function work_docx_import_twipsToMillimeters(value, fallback) {
3772
- if (value <= 0) return fallback;
3773
- return Math.round(value / work_docx_import_TWIPS_PER_MILLIMETER * 10) / 10;
3774
- }
3775
4368
  export { applyDocxSectionsToHtml, prepareDocxImport, readDocxLayout };