@cherrystudio/file-preview 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +247 -2
  3. package/dist/Combination-BLg27FvF.js +1044 -0
  4. package/dist/EchartsChartRenderer-e2b5JysX.js +39859 -0
  5. package/dist/FilePreviewTooLarge-DkHa6toZ.js +27 -0
  6. package/dist/ImageFilePreview-BO8rLRZv.js +2171 -0
  7. package/dist/PdfFilePreview-D3Ie0_mm.js +29747 -0
  8. package/dist/PowerPointFilePreview-BLfF0zcm.js +58032 -0
  9. package/dist/SpreadsheetFilePreview-DJdoyeis.js +3217 -0
  10. package/dist/WordFilePreview-DSqt7Uq2.js +4137 -0
  11. package/dist/assets/cmaps/78-EUC-H.bcmap +0 -0
  12. package/dist/assets/cmaps/78-EUC-V.bcmap +0 -0
  13. package/dist/assets/cmaps/78-H.bcmap +0 -0
  14. package/dist/assets/cmaps/78-RKSJ-H.bcmap +0 -0
  15. package/dist/assets/cmaps/78-RKSJ-V.bcmap +0 -0
  16. package/dist/assets/cmaps/78-V.bcmap +0 -0
  17. package/dist/assets/cmaps/78ms-RKSJ-H.bcmap +0 -0
  18. package/dist/assets/cmaps/78ms-RKSJ-V.bcmap +0 -0
  19. package/dist/assets/cmaps/83pv-RKSJ-H.bcmap +0 -0
  20. package/dist/assets/cmaps/90ms-RKSJ-H.bcmap +0 -0
  21. package/dist/assets/cmaps/90ms-RKSJ-V.bcmap +0 -0
  22. package/dist/assets/cmaps/90msp-RKSJ-H.bcmap +0 -0
  23. package/dist/assets/cmaps/90msp-RKSJ-V.bcmap +0 -0
  24. package/dist/assets/cmaps/90pv-RKSJ-H.bcmap +0 -0
  25. package/dist/assets/cmaps/90pv-RKSJ-V.bcmap +0 -0
  26. package/dist/assets/cmaps/Add-H.bcmap +0 -0
  27. package/dist/assets/cmaps/Add-RKSJ-H.bcmap +0 -0
  28. package/dist/assets/cmaps/Add-RKSJ-V.bcmap +0 -0
  29. package/dist/assets/cmaps/Add-V.bcmap +0 -0
  30. package/dist/assets/cmaps/Adobe-CNS1-0.bcmap +0 -0
  31. package/dist/assets/cmaps/Adobe-CNS1-1.bcmap +0 -0
  32. package/dist/assets/cmaps/Adobe-CNS1-2.bcmap +0 -0
  33. package/dist/assets/cmaps/Adobe-CNS1-3.bcmap +0 -0
  34. package/dist/assets/cmaps/Adobe-CNS1-4.bcmap +0 -0
  35. package/dist/assets/cmaps/Adobe-CNS1-5.bcmap +0 -0
  36. package/dist/assets/cmaps/Adobe-CNS1-6.bcmap +0 -0
  37. package/dist/assets/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
  38. package/dist/assets/cmaps/Adobe-GB1-0.bcmap +0 -0
  39. package/dist/assets/cmaps/Adobe-GB1-1.bcmap +0 -0
  40. package/dist/assets/cmaps/Adobe-GB1-2.bcmap +0 -0
  41. package/dist/assets/cmaps/Adobe-GB1-3.bcmap +0 -0
  42. package/dist/assets/cmaps/Adobe-GB1-4.bcmap +0 -0
  43. package/dist/assets/cmaps/Adobe-GB1-5.bcmap +0 -0
  44. package/dist/assets/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
  45. package/dist/assets/cmaps/Adobe-Japan1-0.bcmap +0 -0
  46. package/dist/assets/cmaps/Adobe-Japan1-1.bcmap +0 -0
  47. package/dist/assets/cmaps/Adobe-Japan1-2.bcmap +0 -0
  48. package/dist/assets/cmaps/Adobe-Japan1-3.bcmap +0 -0
  49. package/dist/assets/cmaps/Adobe-Japan1-4.bcmap +0 -0
  50. package/dist/assets/cmaps/Adobe-Japan1-5.bcmap +0 -0
  51. package/dist/assets/cmaps/Adobe-Japan1-6.bcmap +0 -0
  52. package/dist/assets/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
  53. package/dist/assets/cmaps/Adobe-Korea1-0.bcmap +0 -0
  54. package/dist/assets/cmaps/Adobe-Korea1-1.bcmap +0 -0
  55. package/dist/assets/cmaps/Adobe-Korea1-2.bcmap +0 -0
  56. package/dist/assets/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
  57. package/dist/assets/cmaps/B5-H.bcmap +0 -0
  58. package/dist/assets/cmaps/B5-V.bcmap +0 -0
  59. package/dist/assets/cmaps/B5pc-H.bcmap +0 -0
  60. package/dist/assets/cmaps/B5pc-V.bcmap +0 -0
  61. package/dist/assets/cmaps/CNS-EUC-H.bcmap +0 -0
  62. package/dist/assets/cmaps/CNS-EUC-V.bcmap +0 -0
  63. package/dist/assets/cmaps/CNS1-H.bcmap +0 -0
  64. package/dist/assets/cmaps/CNS1-V.bcmap +0 -0
  65. package/dist/assets/cmaps/CNS2-H.bcmap +0 -0
  66. package/dist/assets/cmaps/CNS2-V.bcmap +3 -0
  67. package/dist/assets/cmaps/ETHK-B5-H.bcmap +0 -0
  68. package/dist/assets/cmaps/ETHK-B5-V.bcmap +0 -0
  69. package/dist/assets/cmaps/ETen-B5-H.bcmap +0 -0
  70. package/dist/assets/cmaps/ETen-B5-V.bcmap +0 -0
  71. package/dist/assets/cmaps/ETenms-B5-H.bcmap +3 -0
  72. package/dist/assets/cmaps/ETenms-B5-V.bcmap +0 -0
  73. package/dist/assets/cmaps/EUC-H.bcmap +0 -0
  74. package/dist/assets/cmaps/EUC-V.bcmap +0 -0
  75. package/dist/assets/cmaps/Ext-H.bcmap +0 -0
  76. package/dist/assets/cmaps/Ext-RKSJ-H.bcmap +0 -0
  77. package/dist/assets/cmaps/Ext-RKSJ-V.bcmap +0 -0
  78. package/dist/assets/cmaps/Ext-V.bcmap +0 -0
  79. package/dist/assets/cmaps/GB-EUC-H.bcmap +0 -0
  80. package/dist/assets/cmaps/GB-EUC-V.bcmap +0 -0
  81. package/dist/assets/cmaps/GB-H.bcmap +4 -0
  82. package/dist/assets/cmaps/GB-V.bcmap +0 -0
  83. package/dist/assets/cmaps/GBK-EUC-H.bcmap +0 -0
  84. package/dist/assets/cmaps/GBK-EUC-V.bcmap +0 -0
  85. package/dist/assets/cmaps/GBK2K-H.bcmap +0 -0
  86. package/dist/assets/cmaps/GBK2K-V.bcmap +0 -0
  87. package/dist/assets/cmaps/GBKp-EUC-H.bcmap +0 -0
  88. package/dist/assets/cmaps/GBKp-EUC-V.bcmap +0 -0
  89. package/dist/assets/cmaps/GBT-EUC-H.bcmap +0 -0
  90. package/dist/assets/cmaps/GBT-EUC-V.bcmap +0 -0
  91. package/dist/assets/cmaps/GBT-H.bcmap +0 -0
  92. package/dist/assets/cmaps/GBT-V.bcmap +0 -0
  93. package/dist/assets/cmaps/GBTpc-EUC-H.bcmap +0 -0
  94. package/dist/assets/cmaps/GBTpc-EUC-V.bcmap +0 -0
  95. package/dist/assets/cmaps/GBpc-EUC-H.bcmap +0 -0
  96. package/dist/assets/cmaps/GBpc-EUC-V.bcmap +0 -0
  97. package/dist/assets/cmaps/H.bcmap +0 -0
  98. package/dist/assets/cmaps/HKdla-B5-H.bcmap +0 -0
  99. package/dist/assets/cmaps/HKdla-B5-V.bcmap +0 -0
  100. package/dist/assets/cmaps/HKdlb-B5-H.bcmap +0 -0
  101. package/dist/assets/cmaps/HKdlb-B5-V.bcmap +0 -0
  102. package/dist/assets/cmaps/HKgccs-B5-H.bcmap +0 -0
  103. package/dist/assets/cmaps/HKgccs-B5-V.bcmap +0 -0
  104. package/dist/assets/cmaps/HKm314-B5-H.bcmap +0 -0
  105. package/dist/assets/cmaps/HKm314-B5-V.bcmap +0 -0
  106. package/dist/assets/cmaps/HKm471-B5-H.bcmap +0 -0
  107. package/dist/assets/cmaps/HKm471-B5-V.bcmap +0 -0
  108. package/dist/assets/cmaps/HKscs-B5-H.bcmap +0 -0
  109. package/dist/assets/cmaps/HKscs-B5-V.bcmap +0 -0
  110. package/dist/assets/cmaps/Hankaku.bcmap +0 -0
  111. package/dist/assets/cmaps/Hiragana.bcmap +0 -0
  112. package/dist/assets/cmaps/KSC-EUC-H.bcmap +0 -0
  113. package/dist/assets/cmaps/KSC-EUC-V.bcmap +0 -0
  114. package/dist/assets/cmaps/KSC-H.bcmap +0 -0
  115. package/dist/assets/cmaps/KSC-Johab-H.bcmap +0 -0
  116. package/dist/assets/cmaps/KSC-Johab-V.bcmap +0 -0
  117. package/dist/assets/cmaps/KSC-V.bcmap +0 -0
  118. package/dist/assets/cmaps/KSCms-UHC-H.bcmap +0 -0
  119. package/dist/assets/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
  120. package/dist/assets/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
  121. package/dist/assets/cmaps/KSCms-UHC-V.bcmap +0 -0
  122. package/dist/assets/cmaps/KSCpc-EUC-H.bcmap +0 -0
  123. package/dist/assets/cmaps/KSCpc-EUC-V.bcmap +0 -0
  124. package/dist/assets/cmaps/Katakana.bcmap +0 -0
  125. package/dist/assets/cmaps/LICENSE +36 -0
  126. package/dist/assets/cmaps/NWP-H.bcmap +0 -0
  127. package/dist/assets/cmaps/NWP-V.bcmap +0 -0
  128. package/dist/assets/cmaps/RKSJ-H.bcmap +0 -0
  129. package/dist/assets/cmaps/RKSJ-V.bcmap +0 -0
  130. package/dist/assets/cmaps/Roman.bcmap +0 -0
  131. package/dist/assets/cmaps/UniCNS-UCS2-H.bcmap +0 -0
  132. package/dist/assets/cmaps/UniCNS-UCS2-V.bcmap +0 -0
  133. package/dist/assets/cmaps/UniCNS-UTF16-H.bcmap +0 -0
  134. package/dist/assets/cmaps/UniCNS-UTF16-V.bcmap +0 -0
  135. package/dist/assets/cmaps/UniCNS-UTF32-H.bcmap +0 -0
  136. package/dist/assets/cmaps/UniCNS-UTF32-V.bcmap +0 -0
  137. package/dist/assets/cmaps/UniCNS-UTF8-H.bcmap +0 -0
  138. package/dist/assets/cmaps/UniCNS-UTF8-V.bcmap +0 -0
  139. package/dist/assets/cmaps/UniGB-UCS2-H.bcmap +0 -0
  140. package/dist/assets/cmaps/UniGB-UCS2-V.bcmap +0 -0
  141. package/dist/assets/cmaps/UniGB-UTF16-H.bcmap +0 -0
  142. package/dist/assets/cmaps/UniGB-UTF16-V.bcmap +0 -0
  143. package/dist/assets/cmaps/UniGB-UTF32-H.bcmap +0 -0
  144. package/dist/assets/cmaps/UniGB-UTF32-V.bcmap +0 -0
  145. package/dist/assets/cmaps/UniGB-UTF8-H.bcmap +0 -0
  146. package/dist/assets/cmaps/UniGB-UTF8-V.bcmap +0 -0
  147. package/dist/assets/cmaps/UniJIS-UCS2-H.bcmap +0 -0
  148. package/dist/assets/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
  149. package/dist/assets/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
  150. package/dist/assets/cmaps/UniJIS-UCS2-V.bcmap +0 -0
  151. package/dist/assets/cmaps/UniJIS-UTF16-H.bcmap +0 -0
  152. package/dist/assets/cmaps/UniJIS-UTF16-V.bcmap +0 -0
  153. package/dist/assets/cmaps/UniJIS-UTF32-H.bcmap +0 -0
  154. package/dist/assets/cmaps/UniJIS-UTF32-V.bcmap +0 -0
  155. package/dist/assets/cmaps/UniJIS-UTF8-H.bcmap +0 -0
  156. package/dist/assets/cmaps/UniJIS-UTF8-V.bcmap +0 -0
  157. package/dist/assets/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
  158. package/dist/assets/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
  159. package/dist/assets/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
  160. package/dist/assets/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
  161. package/dist/assets/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
  162. package/dist/assets/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
  163. package/dist/assets/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
  164. package/dist/assets/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
  165. package/dist/assets/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
  166. package/dist/assets/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
  167. package/dist/assets/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
  168. package/dist/assets/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
  169. package/dist/assets/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
  170. package/dist/assets/cmaps/UniKS-UCS2-H.bcmap +0 -0
  171. package/dist/assets/cmaps/UniKS-UCS2-V.bcmap +0 -0
  172. package/dist/assets/cmaps/UniKS-UTF16-H.bcmap +0 -0
  173. package/dist/assets/cmaps/UniKS-UTF16-V.bcmap +0 -0
  174. package/dist/assets/cmaps/UniKS-UTF32-H.bcmap +0 -0
  175. package/dist/assets/cmaps/UniKS-UTF32-V.bcmap +0 -0
  176. package/dist/assets/cmaps/UniKS-UTF8-H.bcmap +0 -0
  177. package/dist/assets/cmaps/UniKS-UTF8-V.bcmap +0 -0
  178. package/dist/assets/cmaps/V.bcmap +0 -0
  179. package/dist/assets/cmaps/WP-Symbol.bcmap +0 -0
  180. package/dist/assets/pdf.worker.js +77187 -0
  181. package/dist/assets/standard_fonts/FoxitDingbats.pfb +0 -0
  182. package/dist/assets/standard_fonts/FoxitFixed.pfb +0 -0
  183. package/dist/assets/standard_fonts/FoxitFixedBold.pfb +0 -0
  184. package/dist/assets/standard_fonts/FoxitFixedBoldItalic.pfb +0 -0
  185. package/dist/assets/standard_fonts/FoxitFixedItalic.pfb +0 -0
  186. package/dist/assets/standard_fonts/FoxitSerif.pfb +0 -0
  187. package/dist/assets/standard_fonts/FoxitSerifBold.pfb +0 -0
  188. package/dist/assets/standard_fonts/FoxitSerifBoldItalic.pfb +0 -0
  189. package/dist/assets/standard_fonts/FoxitSerifItalic.pfb +0 -0
  190. package/dist/assets/standard_fonts/FoxitSymbol.pfb +0 -0
  191. package/dist/assets/standard_fonts/LICENSE_FOXIT +27 -0
  192. package/dist/assets/standard_fonts/LICENSE_LIBERATION +102 -0
  193. package/dist/assets/standard_fonts/LiberationSans-Bold.ttf +0 -0
  194. package/dist/assets/standard_fonts/LiberationSans-BoldItalic.ttf +0 -0
  195. package/dist/assets/standard_fonts/LiberationSans-Italic.ttf +0 -0
  196. package/dist/assets/standard_fonts/LiberationSans-Regular.ttf +0 -0
  197. package/dist/assets/xlsx.worker.js +61444 -0
  198. package/dist/core.d.ts +2 -0
  199. package/dist/core.js +3 -0
  200. package/dist/documentAnchor-J7GGLU15.js +69 -0
  201. package/dist/imageFilePreviewPlugin-CxIUlEmg.js +29 -0
  202. package/dist/jszip.min-uwqlc4KL.js +3108 -0
  203. package/dist/react.d.ts +105 -0
  204. package/dist/react.js +3114 -0
  205. package/dist/rolldown-runtime-B-lAHAz2.js +37 -0
  206. package/dist/rotate-ccw-YWx7RzY9.js +36 -0
  207. package/dist/selection-CQPD5a6C.js +47 -0
  208. package/dist/source-DjjzeN4t.d.ts +58 -0
  209. package/dist/source-Rx3etU3y.js +28 -0
  210. package/dist/styles.css +8778 -0
  211. package/dist/styles.js +0 -0
  212. package/dist/touchPinch-C4fl-9fg.js +34 -0
  213. package/dist/useTranslation-DMhY277o.js +7056 -0
  214. package/dist/zoom-out-DLOQGt1e.js +66 -0
  215. package/package.json +69 -3
@@ -0,0 +1,4137 @@
1
+ import { i as __toESM } from "./rolldown-runtime-B-lAHAz2.js";
2
+ import { r as readPreviewDocument, t as PreviewError } from "./source-Rx3etU3y.js";
3
+ import { I as LoaderCircle, N as EmptyState, c as FilePreviewToolbar, i as FilePreviewLayout, o as usePreviewHost, r as FilePreviewToolbarButton, t as useTranslation } from "./useTranslation-DMhY277o.js";
4
+ import { n as ChevronRight, r as ChevronLeft, t as RotateCcw } from "./rotate-ccw-YWx7RzY9.js";
5
+ import { r as CircleAlert, t as createPreviewSelection } from "./selection-CQPD5a6C.js";
6
+ import { n as ZoomIn, t as ZoomOut } from "./zoom-out-DLOQGt1e.js";
7
+ import { t as FilePreviewTooLarge } from "./FilePreviewTooLarge-DkHa6toZ.js";
8
+ import { t as attachTouchPinch } from "./touchPinch-C4fl-9fg.js";
9
+ import { t as require_jszip_min } from "./jszip.min-uwqlc4KL.js";
10
+ import { useCallback, useEffect, useId, useLayoutEffect, useRef, useState } from "react";
11
+ import { jsx, jsxs } from "react/jsx-runtime";
12
+ //#region ../../node_modules/.pnpm/docx-preview@0.3.7_patch_hash=d30b0b8d883838e98a8c1b7bd36ee5c68369e065be35545122ccd202bb9ffd1f/node_modules/docx-preview/dist/docx-preview.mjs
13
+ var import_jszip_min = /* @__PURE__ */ __toESM(require_jszip_min(), 1);
14
+ /*
15
+ * @license
16
+ * docx-preview <https://github.com/VolodymyrBaydalka/docxjs>
17
+ * Released under Apache License 2.0 <https://github.com/VolodymyrBaydalka/docxjs/blob/master/LICENSE>
18
+ * Copyright Volodymyr Baydalka
19
+ */
20
+ var RelationshipTypes;
21
+ (function(RelationshipTypes) {
22
+ RelationshipTypes["OfficeDocument"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
23
+ RelationshipTypes["FontTable"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable";
24
+ RelationshipTypes["Image"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
25
+ RelationshipTypes["Numbering"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering";
26
+ RelationshipTypes["Styles"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
27
+ RelationshipTypes["StylesWithEffects"] = "http://schemas.microsoft.com/office/2007/relationships/stylesWithEffects";
28
+ RelationshipTypes["Theme"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
29
+ RelationshipTypes["Settings"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings";
30
+ RelationshipTypes["WebSettings"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings";
31
+ RelationshipTypes["Hyperlink"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";
32
+ RelationshipTypes["Footnotes"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes";
33
+ RelationshipTypes["Endnotes"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes";
34
+ RelationshipTypes["Footer"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer";
35
+ RelationshipTypes["Header"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header";
36
+ RelationshipTypes["ExtendedProperties"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties";
37
+ RelationshipTypes["CoreProperties"] = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
38
+ RelationshipTypes["CustomProperties"] = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/custom-properties";
39
+ RelationshipTypes["Comments"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";
40
+ RelationshipTypes["CommentsExtended"] = "http://schemas.microsoft.com/office/2011/relationships/commentsExtended";
41
+ RelationshipTypes["AltChunk"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk";
42
+ })(RelationshipTypes || (RelationshipTypes = {}));
43
+ function parseRelationships(root, xml) {
44
+ return xml.elements(root).map((e) => ({
45
+ id: xml.attr(e, "Id"),
46
+ type: xml.attr(e, "Type"),
47
+ target: xml.attr(e, "Target"),
48
+ targetMode: xml.attr(e, "TargetMode")
49
+ }));
50
+ }
51
+ function escapeClassName(className) {
52
+ return className?.replace(/[ .]+/g, "-").replace(/[&]+/g, "and").toLowerCase();
53
+ }
54
+ function encloseFontFamily(fontFamily) {
55
+ return /^[^"'].*\s.*[^"']$/.test(fontFamily) ? `'${fontFamily}'` : fontFamily;
56
+ }
57
+ function splitPath(path) {
58
+ let si = path.lastIndexOf("/") + 1;
59
+ return [si == 0 ? "" : path.substring(0, si), si == 0 ? path : path.substring(si)];
60
+ }
61
+ function resolvePath(path, base) {
62
+ try {
63
+ return new URL(path, "http://docx/" + base).toString().substring(12);
64
+ } catch {
65
+ return `${base}${path}`;
66
+ }
67
+ }
68
+ function keyBy(array, by) {
69
+ return array.reduce((a, x) => {
70
+ a[by(x)] = x;
71
+ return a;
72
+ }, {});
73
+ }
74
+ function blobToBase64(blob) {
75
+ return new Promise((resolve, reject) => {
76
+ const reader = new FileReader();
77
+ reader.onloadend = () => resolve(reader.result);
78
+ reader.onerror = () => reject();
79
+ reader.readAsDataURL(blob);
80
+ });
81
+ }
82
+ function isObject(item) {
83
+ return item && typeof item === "object" && !Array.isArray(item);
84
+ }
85
+ function isString(item) {
86
+ return typeof item === "string" || item instanceof String;
87
+ }
88
+ function mergeDeep(target, ...sources) {
89
+ if (!sources.length) return target;
90
+ const source = sources.shift();
91
+ if (isObject(target) && isObject(source)) for (const key in source) if (isObject(source[key])) mergeDeep(target[key] ?? (target[key] = {}), source[key]);
92
+ else target[key] = source[key];
93
+ return mergeDeep(target, ...sources);
94
+ }
95
+ function asArray(val) {
96
+ return Array.isArray(val) ? val : [val];
97
+ }
98
+ function clamp$1(val, min, max) {
99
+ return min > val ? min : max < val ? max : val;
100
+ }
101
+ var ns$1 = { wordml: "http://schemas.openxmlformats.org/wordprocessingml/2006/main" };
102
+ var LengthUsage = {
103
+ Dxa: {
104
+ mul: .05,
105
+ unit: "pt"
106
+ },
107
+ Emu: {
108
+ mul: 1 / 12700,
109
+ unit: "pt"
110
+ },
111
+ FontSize: {
112
+ mul: .5,
113
+ unit: "pt"
114
+ },
115
+ Border: {
116
+ mul: .125,
117
+ unit: "pt",
118
+ min: .25,
119
+ max: 12
120
+ },
121
+ Point: {
122
+ mul: 1,
123
+ unit: "pt"
124
+ },
125
+ Percent: {
126
+ mul: .02,
127
+ unit: "%"
128
+ }
129
+ };
130
+ function convertLength(val, usage = LengthUsage.Dxa) {
131
+ if (val == null || /.+(p[xt]|[%])$/.test(val)) return val;
132
+ var num = parseInt(val) * usage.mul;
133
+ if (usage.min && usage.max) num = clamp$1(num, usage.min, usage.max);
134
+ return `${num.toFixed(2)}${usage.unit}`;
135
+ }
136
+ function convertBoolean(v, defaultValue = false) {
137
+ switch (v) {
138
+ case "1": return true;
139
+ case "0": return false;
140
+ case "on": return true;
141
+ case "off": return false;
142
+ case "true": return true;
143
+ case "false": return false;
144
+ default: return defaultValue;
145
+ }
146
+ }
147
+ function parseCommonProperty(elem, props, xml) {
148
+ if (elem.namespaceURI != ns$1.wordml) return false;
149
+ switch (elem.localName) {
150
+ case "color":
151
+ props.color = xml.attr(elem, "val");
152
+ break;
153
+ case "sz":
154
+ props.fontSize = xml.lengthAttr(elem, "val", LengthUsage.FontSize);
155
+ break;
156
+ default: return false;
157
+ }
158
+ return true;
159
+ }
160
+ function parseXmlString(xmlString, trimXmlDeclaration = false) {
161
+ if (trimXmlDeclaration) xmlString = xmlString.replace(/<[?].*[?]>/, "");
162
+ xmlString = removeUTF8BOM(xmlString);
163
+ const result = new DOMParser().parseFromString(xmlString, "application/xml");
164
+ const errorText = hasXmlParserError(result);
165
+ if (errorText) throw new Error(errorText);
166
+ return result;
167
+ }
168
+ function hasXmlParserError(doc) {
169
+ return doc.getElementsByTagName("parsererror")[0]?.textContent;
170
+ }
171
+ function removeUTF8BOM(data) {
172
+ return data.charCodeAt(0) === 65279 ? data.substring(1) : data;
173
+ }
174
+ function serializeXmlString(elem) {
175
+ return new XMLSerializer().serializeToString(elem);
176
+ }
177
+ var XmlParser = class {
178
+ elements(elem, localName = null) {
179
+ const result = [];
180
+ for (let i = 0, l = elem.childNodes.length; i < l; i++) {
181
+ let c = elem.childNodes.item(i);
182
+ if (c.nodeType == Node.ELEMENT_NODE && (localName == null || c.localName == localName)) result.push(c);
183
+ }
184
+ return result;
185
+ }
186
+ element(elem, localName) {
187
+ for (let i = 0, l = elem.childNodes.length; i < l; i++) {
188
+ let c = elem.childNodes.item(i);
189
+ if (c.nodeType == 1 && c.localName == localName) return c;
190
+ }
191
+ return null;
192
+ }
193
+ elementAttr(elem, localName, attrLocalName) {
194
+ var el = this.element(elem, localName);
195
+ return el ? this.attr(el, attrLocalName) : void 0;
196
+ }
197
+ attrs(elem) {
198
+ return Array.from(elem.attributes);
199
+ }
200
+ attr(elem, localName) {
201
+ for (let i = 0, l = elem.attributes.length; i < l; i++) {
202
+ let a = elem.attributes.item(i);
203
+ if (a.localName == localName) return a.value;
204
+ }
205
+ return null;
206
+ }
207
+ intAttr(node, attrName, defaultValue = null) {
208
+ var val = this.attr(node, attrName);
209
+ return val ? parseInt(val) : defaultValue;
210
+ }
211
+ hexAttr(node, attrName, defaultValue = null) {
212
+ var val = this.attr(node, attrName);
213
+ return val ? parseInt(val, 16) : defaultValue;
214
+ }
215
+ floatAttr(node, attrName, defaultValue = null) {
216
+ var val = this.attr(node, attrName);
217
+ return val ? parseFloat(val) : defaultValue;
218
+ }
219
+ boolAttr(node, attrName, defaultValue = null) {
220
+ return convertBoolean(this.attr(node, attrName), defaultValue);
221
+ }
222
+ lengthAttr(node, attrName, usage = LengthUsage.Dxa) {
223
+ return convertLength(this.attr(node, attrName), usage);
224
+ }
225
+ };
226
+ var globalXmlParser = new XmlParser();
227
+ var Part = class {
228
+ constructor(_package, path) {
229
+ this._package = _package;
230
+ this.path = path;
231
+ }
232
+ async load() {
233
+ this.rels = await this._package.loadRelationships(this.path);
234
+ const xmlText = await this._package.load(this.path);
235
+ const xmlDoc = this._package.parseXmlDocument(xmlText);
236
+ if (this._package.options.keepOrigin) this._xmlDocument = xmlDoc;
237
+ this.parseXml(xmlDoc.firstElementChild);
238
+ }
239
+ save() {
240
+ this._package.update(this.path, serializeXmlString(this._xmlDocument));
241
+ }
242
+ parseXml(root) {}
243
+ };
244
+ var embedFontTypeMap = {
245
+ embedRegular: "regular",
246
+ embedBold: "bold",
247
+ embedItalic: "italic",
248
+ embedBoldItalic: "boldItalic"
249
+ };
250
+ function parseFonts(root, xml) {
251
+ return xml.elements(root).map((el) => parseFont(el, xml));
252
+ }
253
+ function parseFont(elem, xml) {
254
+ let result = {
255
+ name: xml.attr(elem, "name"),
256
+ embedFontRefs: []
257
+ };
258
+ for (let el of xml.elements(elem)) switch (el.localName) {
259
+ case "family":
260
+ result.family = xml.attr(el, "val");
261
+ break;
262
+ case "altName":
263
+ result.altName = xml.attr(el, "val");
264
+ break;
265
+ case "embedRegular":
266
+ case "embedBold":
267
+ case "embedItalic":
268
+ case "embedBoldItalic": result.embedFontRefs.push(parseEmbedFontRef(el, xml));
269
+ }
270
+ return result;
271
+ }
272
+ function parseEmbedFontRef(elem, xml) {
273
+ return {
274
+ id: xml.attr(elem, "id"),
275
+ key: xml.attr(elem, "fontKey"),
276
+ type: embedFontTypeMap[elem.localName]
277
+ };
278
+ }
279
+ var FontTablePart = class extends Part {
280
+ parseXml(root) {
281
+ this.fonts = parseFonts(root, this._package.xmlParser);
282
+ }
283
+ };
284
+ var OpenXmlPackage = class OpenXmlPackage {
285
+ constructor(_zip, options) {
286
+ this._zip = _zip;
287
+ this.options = options;
288
+ this.xmlParser = new XmlParser();
289
+ }
290
+ get(path) {
291
+ const p = normalizePath(path);
292
+ return this._zip.files[p] ?? this._zip.files[p.replace(/\//g, "\\")];
293
+ }
294
+ update(path, content) {
295
+ this._zip.file(path, content);
296
+ }
297
+ static async load(input, options) {
298
+ const zip = await import_jszip_min.default.loadAsync(input);
299
+ return new OpenXmlPackage(zip, options);
300
+ }
301
+ save(type = "blob") {
302
+ return this._zip.generateAsync({ type });
303
+ }
304
+ load(path, type = "string") {
305
+ return this.get(path)?.async(type) ?? Promise.resolve(null);
306
+ }
307
+ async loadRelationships(path = null) {
308
+ let relsPath = `_rels/.rels`;
309
+ if (path != null) {
310
+ const [f, fn] = splitPath(path);
311
+ relsPath = `${f}_rels/${fn}.rels`;
312
+ }
313
+ const txt = await this.load(relsPath);
314
+ return txt ? parseRelationships(this.parseXmlDocument(txt).firstElementChild, this.xmlParser) : null;
315
+ }
316
+ parseXmlDocument(txt) {
317
+ return parseXmlString(txt, this.options.trimXmlDeclaration);
318
+ }
319
+ };
320
+ function normalizePath(path) {
321
+ return path.startsWith("/") ? path.substr(1) : path;
322
+ }
323
+ var DocumentPart = class extends Part {
324
+ constructor(pkg, path, parser) {
325
+ super(pkg, path);
326
+ this._documentParser = parser;
327
+ }
328
+ parseXml(root) {
329
+ this.body = this._documentParser.parseDocumentFile(root);
330
+ }
331
+ };
332
+ function parseBorder(elem, xml) {
333
+ return {
334
+ type: xml.attr(elem, "val"),
335
+ color: xml.attr(elem, "color"),
336
+ size: xml.lengthAttr(elem, "sz", LengthUsage.Border),
337
+ offset: xml.lengthAttr(elem, "space", LengthUsage.Point),
338
+ frame: xml.boolAttr(elem, "frame"),
339
+ shadow: xml.boolAttr(elem, "shadow")
340
+ };
341
+ }
342
+ function parseBorders(elem, xml) {
343
+ var result = {};
344
+ for (let e of xml.elements(elem)) switch (e.localName) {
345
+ case "left":
346
+ result.left = parseBorder(e, xml);
347
+ break;
348
+ case "top":
349
+ result.top = parseBorder(e, xml);
350
+ break;
351
+ case "right":
352
+ result.right = parseBorder(e, xml);
353
+ break;
354
+ case "bottom": result.bottom = parseBorder(e, xml);
355
+ }
356
+ return result;
357
+ }
358
+ var SectionType;
359
+ (function(SectionType) {
360
+ SectionType["Continuous"] = "continuous";
361
+ SectionType["NextPage"] = "nextPage";
362
+ SectionType["NextColumn"] = "nextColumn";
363
+ SectionType["EvenPage"] = "evenPage";
364
+ SectionType["OddPage"] = "oddPage";
365
+ })(SectionType || (SectionType = {}));
366
+ function parseSectionProperties(elem, xml = globalXmlParser) {
367
+ var section = {};
368
+ for (let e of xml.elements(elem)) switch (e.localName) {
369
+ case "pgSz":
370
+ section.pageSize = {
371
+ width: xml.lengthAttr(e, "w"),
372
+ height: xml.lengthAttr(e, "h"),
373
+ orientation: xml.attr(e, "orient")
374
+ };
375
+ break;
376
+ case "type":
377
+ section.type = xml.attr(e, "val");
378
+ break;
379
+ case "pgMar":
380
+ section.pageMargins = {
381
+ left: xml.lengthAttr(e, "left"),
382
+ right: xml.lengthAttr(e, "right"),
383
+ top: xml.lengthAttr(e, "top"),
384
+ bottom: xml.lengthAttr(e, "bottom"),
385
+ header: xml.lengthAttr(e, "header"),
386
+ footer: xml.lengthAttr(e, "footer"),
387
+ gutter: xml.lengthAttr(e, "gutter")
388
+ };
389
+ break;
390
+ case "cols":
391
+ section.columns = parseColumns(e, xml);
392
+ break;
393
+ case "headerReference":
394
+ (section.headerRefs ?? (section.headerRefs = [])).push(parseFooterHeaderReference(e, xml));
395
+ break;
396
+ case "footerReference":
397
+ (section.footerRefs ?? (section.footerRefs = [])).push(parseFooterHeaderReference(e, xml));
398
+ break;
399
+ case "titlePg":
400
+ section.titlePage = xml.boolAttr(e, "val", true);
401
+ break;
402
+ case "pgBorders":
403
+ section.pageBorders = parseBorders(e, xml);
404
+ break;
405
+ case "pgNumType": section.pageNumber = parsePageNumber(e, xml);
406
+ }
407
+ return section;
408
+ }
409
+ function parseColumns(elem, xml) {
410
+ return {
411
+ numberOfColumns: xml.intAttr(elem, "num"),
412
+ space: xml.lengthAttr(elem, "space"),
413
+ separator: xml.boolAttr(elem, "sep"),
414
+ equalWidth: xml.boolAttr(elem, "equalWidth", true),
415
+ columns: xml.elements(elem, "col").map((e) => ({
416
+ width: xml.lengthAttr(e, "w"),
417
+ space: xml.lengthAttr(e, "space")
418
+ }))
419
+ };
420
+ }
421
+ function parsePageNumber(elem, xml) {
422
+ return {
423
+ chapSep: xml.attr(elem, "chapSep"),
424
+ chapStyle: xml.attr(elem, "chapStyle"),
425
+ format: xml.attr(elem, "fmt"),
426
+ start: xml.intAttr(elem, "start")
427
+ };
428
+ }
429
+ function parseFooterHeaderReference(elem, xml) {
430
+ return {
431
+ id: xml.attr(elem, "id"),
432
+ type: xml.attr(elem, "type")
433
+ };
434
+ }
435
+ function parseLineSpacing(elem, xml) {
436
+ return {
437
+ before: xml.lengthAttr(elem, "before"),
438
+ after: xml.lengthAttr(elem, "after"),
439
+ line: xml.intAttr(elem, "line"),
440
+ lineRule: xml.attr(elem, "lineRule")
441
+ };
442
+ }
443
+ function parseRunProperties(elem, xml) {
444
+ let result = {};
445
+ for (let el of xml.elements(elem)) parseRunProperty(el, result, xml);
446
+ return result;
447
+ }
448
+ function parseRunProperty(elem, props, xml) {
449
+ if (parseCommonProperty(elem, props, xml)) return true;
450
+ return false;
451
+ }
452
+ function parseParagraphProperties(elem, xml) {
453
+ let result = {};
454
+ for (let el of xml.elements(elem)) parseParagraphProperty(el, result, xml);
455
+ return result;
456
+ }
457
+ function parseParagraphProperty(elem, props, xml) {
458
+ if (elem.namespaceURI != ns$1.wordml) return false;
459
+ if (parseCommonProperty(elem, props, xml)) return true;
460
+ switch (elem.localName) {
461
+ case "tabs":
462
+ props.tabs = parseTabs(elem, xml);
463
+ break;
464
+ case "sectPr":
465
+ props.sectionProps = parseSectionProperties(elem, xml);
466
+ break;
467
+ case "numPr":
468
+ props.numbering = parseNumbering$1(elem, xml);
469
+ break;
470
+ case "spacing":
471
+ props.lineSpacing = parseLineSpacing(elem, xml);
472
+ return false;
473
+ case "textAlignment":
474
+ props.textAlignment = xml.attr(elem, "val");
475
+ return false;
476
+ case "keepLines":
477
+ props.keepLines = xml.boolAttr(elem, "val", true);
478
+ break;
479
+ case "keepNext":
480
+ props.keepNext = xml.boolAttr(elem, "val", true);
481
+ break;
482
+ case "pageBreakBefore":
483
+ props.pageBreakBefore = xml.boolAttr(elem, "val", true);
484
+ break;
485
+ case "outlineLvl":
486
+ props.outlineLevel = xml.intAttr(elem, "val");
487
+ break;
488
+ case "pStyle":
489
+ props.styleName = xml.attr(elem, "val");
490
+ break;
491
+ case "rPr":
492
+ props.runProps = parseRunProperties(elem, xml);
493
+ break;
494
+ default: return false;
495
+ }
496
+ return true;
497
+ }
498
+ function parseTabs(elem, xml) {
499
+ return xml.elements(elem, "tab").map((e) => ({
500
+ position: xml.lengthAttr(e, "pos"),
501
+ leader: xml.attr(e, "leader"),
502
+ style: xml.attr(e, "val")
503
+ }));
504
+ }
505
+ function parseNumbering$1(elem, xml) {
506
+ var result = {};
507
+ for (let e of xml.elements(elem)) switch (e.localName) {
508
+ case "numId":
509
+ result.id = xml.attr(e, "val");
510
+ break;
511
+ case "ilvl": result.level = xml.intAttr(e, "val");
512
+ }
513
+ return result;
514
+ }
515
+ function parseNumberingPart(elem, xml) {
516
+ let result = {
517
+ numberings: [],
518
+ abstractNumberings: [],
519
+ bulletPictures: []
520
+ };
521
+ for (let e of xml.elements(elem)) switch (e.localName) {
522
+ case "num":
523
+ result.numberings.push(parseNumbering(e, xml));
524
+ break;
525
+ case "abstractNum":
526
+ result.abstractNumberings.push(parseAbstractNumbering(e, xml));
527
+ break;
528
+ case "numPicBullet": result.bulletPictures.push(parseNumberingBulletPicture(e, xml));
529
+ }
530
+ return result;
531
+ }
532
+ function parseNumbering(elem, xml) {
533
+ let result = {
534
+ id: xml.attr(elem, "numId"),
535
+ overrides: []
536
+ };
537
+ for (let e of xml.elements(elem)) switch (e.localName) {
538
+ case "abstractNumId":
539
+ result.abstractId = xml.attr(e, "val");
540
+ break;
541
+ case "lvlOverride": result.overrides.push(parseNumberingLevelOverrride(e, xml));
542
+ }
543
+ return result;
544
+ }
545
+ function parseAbstractNumbering(elem, xml) {
546
+ let result = {
547
+ id: xml.attr(elem, "abstractNumId"),
548
+ levels: []
549
+ };
550
+ for (let e of xml.elements(elem)) switch (e.localName) {
551
+ case "name":
552
+ result.name = xml.attr(e, "val");
553
+ break;
554
+ case "multiLevelType":
555
+ result.multiLevelType = xml.attr(e, "val");
556
+ break;
557
+ case "numStyleLink":
558
+ result.numberingStyleLink = xml.attr(e, "val");
559
+ break;
560
+ case "styleLink":
561
+ result.styleLink = xml.attr(e, "val");
562
+ break;
563
+ case "lvl": result.levels.push(parseNumberingLevel(e, xml));
564
+ }
565
+ return result;
566
+ }
567
+ function parseNumberingLevel(elem, xml) {
568
+ let result = { level: xml.intAttr(elem, "ilvl") };
569
+ for (let e of xml.elements(elem)) switch (e.localName) {
570
+ case "start":
571
+ result.start = xml.attr(e, "val");
572
+ break;
573
+ case "lvlRestart":
574
+ result.restart = xml.intAttr(e, "val");
575
+ break;
576
+ case "numFmt":
577
+ result.format = xml.attr(e, "val");
578
+ break;
579
+ case "lvlText":
580
+ result.text = xml.attr(e, "val");
581
+ break;
582
+ case "lvlJc":
583
+ result.justification = xml.attr(e, "val");
584
+ break;
585
+ case "lvlPicBulletId":
586
+ result.bulletPictureId = xml.attr(e, "val");
587
+ break;
588
+ case "pStyle":
589
+ result.paragraphStyle = xml.attr(e, "val");
590
+ break;
591
+ case "pPr":
592
+ result.paragraphProps = parseParagraphProperties(e, xml);
593
+ break;
594
+ case "rPr": result.runProps = parseRunProperties(e, xml);
595
+ }
596
+ return result;
597
+ }
598
+ function parseNumberingLevelOverrride(elem, xml) {
599
+ let result = { level: xml.intAttr(elem, "ilvl") };
600
+ for (let e of xml.elements(elem)) switch (e.localName) {
601
+ case "startOverride":
602
+ result.start = xml.intAttr(e, "val");
603
+ break;
604
+ case "lvl": result.numberingLevel = parseNumberingLevel(e, xml);
605
+ }
606
+ return result;
607
+ }
608
+ function parseNumberingBulletPicture(elem, xml) {
609
+ var pict = xml.element(elem, "pict");
610
+ var shape = pict && xml.element(pict, "shape");
611
+ var imagedata = shape && xml.element(shape, "imagedata");
612
+ return imagedata ? {
613
+ id: xml.attr(elem, "numPicBulletId"),
614
+ referenceId: xml.attr(imagedata, "id"),
615
+ style: xml.attr(shape, "style")
616
+ } : null;
617
+ }
618
+ var NumberingPart = class extends Part {
619
+ constructor(pkg, path, parser) {
620
+ super(pkg, path);
621
+ this._documentParser = parser;
622
+ }
623
+ parseXml(root) {
624
+ Object.assign(this, parseNumberingPart(root, this._package.xmlParser));
625
+ this.domNumberings = this._documentParser.parseNumberingFile(root);
626
+ }
627
+ };
628
+ var StylesPart = class extends Part {
629
+ constructor(pkg, path, parser) {
630
+ super(pkg, path);
631
+ this._documentParser = parser;
632
+ }
633
+ parseXml(root) {
634
+ this.styles = this._documentParser.parseStylesFile(root);
635
+ }
636
+ };
637
+ var DomType;
638
+ (function(DomType) {
639
+ DomType["Document"] = "document";
640
+ DomType["Paragraph"] = "paragraph";
641
+ DomType["Run"] = "run";
642
+ DomType["Break"] = "break";
643
+ DomType["NoBreakHyphen"] = "noBreakHyphen";
644
+ DomType["Table"] = "table";
645
+ DomType["Row"] = "row";
646
+ DomType["Cell"] = "cell";
647
+ DomType["Hyperlink"] = "hyperlink";
648
+ DomType["SmartTag"] = "smartTag";
649
+ DomType["Drawing"] = "drawing";
650
+ DomType["Image"] = "image";
651
+ DomType["Text"] = "text";
652
+ DomType["Tab"] = "tab";
653
+ DomType["Symbol"] = "symbol";
654
+ DomType["BookmarkStart"] = "bookmarkStart";
655
+ DomType["BookmarkEnd"] = "bookmarkEnd";
656
+ DomType["Footer"] = "footer";
657
+ DomType["Header"] = "header";
658
+ DomType["FootnoteReference"] = "footnoteReference";
659
+ DomType["EndnoteReference"] = "endnoteReference";
660
+ DomType["Footnote"] = "footnote";
661
+ DomType["Endnote"] = "endnote";
662
+ DomType["SimpleField"] = "simpleField";
663
+ DomType["ComplexField"] = "complexField";
664
+ DomType["Instruction"] = "instruction";
665
+ DomType["VmlPicture"] = "vmlPicture";
666
+ DomType["MmlMath"] = "mmlMath";
667
+ DomType["MmlMathParagraph"] = "mmlMathParagraph";
668
+ DomType["MmlFraction"] = "mmlFraction";
669
+ DomType["MmlFunction"] = "mmlFunction";
670
+ DomType["MmlFunctionName"] = "mmlFunctionName";
671
+ DomType["MmlNumerator"] = "mmlNumerator";
672
+ DomType["MmlDenominator"] = "mmlDenominator";
673
+ DomType["MmlRadical"] = "mmlRadical";
674
+ DomType["MmlBase"] = "mmlBase";
675
+ DomType["MmlDegree"] = "mmlDegree";
676
+ DomType["MmlSuperscript"] = "mmlSuperscript";
677
+ DomType["MmlSubscript"] = "mmlSubscript";
678
+ DomType["MmlPreSubSuper"] = "mmlPreSubSuper";
679
+ DomType["MmlSubArgument"] = "mmlSubArgument";
680
+ DomType["MmlSuperArgument"] = "mmlSuperArgument";
681
+ DomType["MmlNary"] = "mmlNary";
682
+ DomType["MmlDelimiter"] = "mmlDelimiter";
683
+ DomType["MmlRun"] = "mmlRun";
684
+ DomType["MmlEquationArray"] = "mmlEquationArray";
685
+ DomType["MmlLimit"] = "mmlLimit";
686
+ DomType["MmlLimitLower"] = "mmlLimitLower";
687
+ DomType["MmlMatrix"] = "mmlMatrix";
688
+ DomType["MmlMatrixRow"] = "mmlMatrixRow";
689
+ DomType["MmlBox"] = "mmlBox";
690
+ DomType["MmlBar"] = "mmlBar";
691
+ DomType["MmlGroupChar"] = "mmlGroupChar";
692
+ DomType["VmlElement"] = "vmlElement";
693
+ DomType["Inserted"] = "inserted";
694
+ DomType["Deleted"] = "deleted";
695
+ DomType["DeletedText"] = "deletedText";
696
+ DomType["Comment"] = "comment";
697
+ DomType["CommentReference"] = "commentReference";
698
+ DomType["CommentRangeStart"] = "commentRangeStart";
699
+ DomType["CommentRangeEnd"] = "commentRangeEnd";
700
+ DomType["AltChunk"] = "altChunk";
701
+ })(DomType || (DomType = {}));
702
+ var OpenXmlElementBase = class {
703
+ constructor() {
704
+ this.children = [];
705
+ this.cssStyle = {};
706
+ }
707
+ };
708
+ var WmlHeader = class extends OpenXmlElementBase {
709
+ constructor() {
710
+ super(...arguments);
711
+ this.type = DomType.Header;
712
+ }
713
+ };
714
+ var WmlFooter = class extends OpenXmlElementBase {
715
+ constructor() {
716
+ super(...arguments);
717
+ this.type = DomType.Footer;
718
+ }
719
+ };
720
+ var BaseHeaderFooterPart = class extends Part {
721
+ constructor(pkg, path, parser) {
722
+ super(pkg, path);
723
+ this._documentParser = parser;
724
+ }
725
+ parseXml(root) {
726
+ this.rootElement = this.createRootElement();
727
+ this.rootElement.children = this._documentParser.parseBodyElements(root, this.rootElement.type);
728
+ }
729
+ };
730
+ var HeaderPart = class extends BaseHeaderFooterPart {
731
+ createRootElement() {
732
+ return new WmlHeader();
733
+ }
734
+ };
735
+ var FooterPart = class extends BaseHeaderFooterPart {
736
+ createRootElement() {
737
+ return new WmlFooter();
738
+ }
739
+ };
740
+ function parseExtendedProps(root, xmlParser) {
741
+ const result = {};
742
+ for (let el of xmlParser.elements(root)) switch (el.localName) {
743
+ case "Template":
744
+ result.template = el.textContent;
745
+ break;
746
+ case "Pages":
747
+ result.pages = safeParseToInt(el.textContent);
748
+ break;
749
+ case "Words":
750
+ result.words = safeParseToInt(el.textContent);
751
+ break;
752
+ case "Characters":
753
+ result.characters = safeParseToInt(el.textContent);
754
+ break;
755
+ case "Application":
756
+ result.application = el.textContent;
757
+ break;
758
+ case "Lines":
759
+ result.lines = safeParseToInt(el.textContent);
760
+ break;
761
+ case "Paragraphs":
762
+ result.paragraphs = safeParseToInt(el.textContent);
763
+ break;
764
+ case "Company":
765
+ result.company = el.textContent;
766
+ break;
767
+ case "AppVersion": result.appVersion = el.textContent;
768
+ }
769
+ return result;
770
+ }
771
+ function safeParseToInt(value) {
772
+ if (typeof value === "undefined") return;
773
+ return parseInt(value);
774
+ }
775
+ var ExtendedPropsPart = class extends Part {
776
+ parseXml(root) {
777
+ this.props = parseExtendedProps(root, this._package.xmlParser);
778
+ }
779
+ };
780
+ function parseCoreProps(root, xmlParser) {
781
+ const result = {};
782
+ for (let el of xmlParser.elements(root)) switch (el.localName) {
783
+ case "title":
784
+ result.title = el.textContent;
785
+ break;
786
+ case "description":
787
+ result.description = el.textContent;
788
+ break;
789
+ case "subject":
790
+ result.subject = el.textContent;
791
+ break;
792
+ case "creator":
793
+ result.creator = el.textContent;
794
+ break;
795
+ case "keywords":
796
+ result.keywords = el.textContent;
797
+ break;
798
+ case "language":
799
+ result.language = el.textContent;
800
+ break;
801
+ case "lastModifiedBy":
802
+ result.lastModifiedBy = el.textContent;
803
+ break;
804
+ case "revision": el.textContent && (result.revision = parseInt(el.textContent));
805
+ }
806
+ return result;
807
+ }
808
+ var CorePropsPart = class extends Part {
809
+ parseXml(root) {
810
+ this.props = parseCoreProps(root, this._package.xmlParser);
811
+ }
812
+ };
813
+ var DmlTheme = class {};
814
+ function parseTheme(elem, xml) {
815
+ var result = new DmlTheme();
816
+ var themeElements = xml.element(elem, "themeElements");
817
+ for (let el of xml.elements(themeElements)) switch (el.localName) {
818
+ case "clrScheme":
819
+ result.colorScheme = parseColorScheme(el, xml);
820
+ break;
821
+ case "fontScheme": result.fontScheme = parseFontScheme(el, xml);
822
+ }
823
+ return result;
824
+ }
825
+ function parseColorScheme(elem, xml) {
826
+ var result = {
827
+ name: xml.attr(elem, "name"),
828
+ colors: {}
829
+ };
830
+ for (let el of xml.elements(elem)) {
831
+ var srgbClr = xml.element(el, "srgbClr");
832
+ var sysClr = xml.element(el, "sysClr");
833
+ if (srgbClr) result.colors[el.localName] = xml.attr(srgbClr, "val");
834
+ else if (sysClr) result.colors[el.localName] = xml.attr(sysClr, "lastClr");
835
+ }
836
+ return result;
837
+ }
838
+ function parseFontScheme(elem, xml) {
839
+ var result = { name: xml.attr(elem, "name") };
840
+ for (let el of xml.elements(elem)) switch (el.localName) {
841
+ case "majorFont":
842
+ result.majorFont = parseFontInfo(el, xml);
843
+ break;
844
+ case "minorFont": result.minorFont = parseFontInfo(el, xml);
845
+ }
846
+ return result;
847
+ }
848
+ function parseFontInfo(elem, xml) {
849
+ return {
850
+ latinTypeface: xml.elementAttr(elem, "latin", "typeface"),
851
+ eaTypeface: xml.elementAttr(elem, "ea", "typeface"),
852
+ csTypeface: xml.elementAttr(elem, "cs", "typeface")
853
+ };
854
+ }
855
+ var ThemePart = class extends Part {
856
+ constructor(pkg, path) {
857
+ super(pkg, path);
858
+ }
859
+ parseXml(root) {
860
+ this.theme = parseTheme(root, this._package.xmlParser);
861
+ }
862
+ };
863
+ var WmlBaseNote = class {};
864
+ var WmlFootnote = class extends WmlBaseNote {
865
+ constructor() {
866
+ super(...arguments);
867
+ this.type = DomType.Footnote;
868
+ }
869
+ };
870
+ var WmlEndnote = class extends WmlBaseNote {
871
+ constructor() {
872
+ super(...arguments);
873
+ this.type = DomType.Endnote;
874
+ }
875
+ };
876
+ var BaseNotePart = class extends Part {
877
+ constructor(pkg, path, parser) {
878
+ super(pkg, path);
879
+ this._documentParser = parser;
880
+ }
881
+ };
882
+ var FootnotesPart = class extends BaseNotePart {
883
+ constructor(pkg, path, parser) {
884
+ super(pkg, path, parser);
885
+ }
886
+ parseXml(root) {
887
+ this.notes = this._documentParser.parseNotes(root, "footnote", WmlFootnote);
888
+ }
889
+ };
890
+ var EndnotesPart = class extends BaseNotePart {
891
+ constructor(pkg, path, parser) {
892
+ super(pkg, path, parser);
893
+ }
894
+ parseXml(root) {
895
+ this.notes = this._documentParser.parseNotes(root, "endnote", WmlEndnote);
896
+ }
897
+ };
898
+ function parseSettings(elem, xml) {
899
+ var result = {};
900
+ for (let el of xml.elements(elem)) switch (el.localName) {
901
+ case "defaultTabStop":
902
+ result.defaultTabStop = xml.lengthAttr(el, "val");
903
+ break;
904
+ case "footnotePr":
905
+ result.footnoteProps = parseNoteProperties(el, xml);
906
+ break;
907
+ case "endnotePr":
908
+ result.endnoteProps = parseNoteProperties(el, xml);
909
+ break;
910
+ case "autoHyphenation": result.autoHyphenation = xml.boolAttr(el, "val");
911
+ }
912
+ return result;
913
+ }
914
+ function parseNoteProperties(elem, xml) {
915
+ var result = { defaultNoteIds: [] };
916
+ for (let el of xml.elements(elem)) switch (el.localName) {
917
+ case "numFmt":
918
+ result.nummeringFormat = xml.attr(el, "val");
919
+ break;
920
+ case "footnote":
921
+ case "endnote": result.defaultNoteIds.push(xml.attr(el, "id"));
922
+ }
923
+ return result;
924
+ }
925
+ var SettingsPart = class extends Part {
926
+ constructor(pkg, path) {
927
+ super(pkg, path);
928
+ }
929
+ parseXml(root) {
930
+ this.settings = parseSettings(root, this._package.xmlParser);
931
+ }
932
+ };
933
+ function parseCustomProps(root, xml) {
934
+ return xml.elements(root, "property").map((e) => {
935
+ const firstChild = e.firstChild;
936
+ return {
937
+ formatId: xml.attr(e, "fmtid"),
938
+ name: xml.attr(e, "name"),
939
+ type: firstChild.nodeName,
940
+ value: firstChild.textContent
941
+ };
942
+ });
943
+ }
944
+ var CustomPropsPart = class extends Part {
945
+ parseXml(root) {
946
+ this.props = parseCustomProps(root, this._package.xmlParser);
947
+ }
948
+ };
949
+ var CommentsPart = class extends Part {
950
+ constructor(pkg, path, parser) {
951
+ super(pkg, path);
952
+ this._documentParser = parser;
953
+ }
954
+ parseXml(root) {
955
+ this.comments = this._documentParser.parseComments(root);
956
+ this.commentMap = keyBy(this.comments, (x) => x.id);
957
+ }
958
+ };
959
+ var CommentsExtendedPart = class extends Part {
960
+ constructor(pkg, path) {
961
+ super(pkg, path);
962
+ this.comments = [];
963
+ }
964
+ parseXml(root) {
965
+ const xml = this._package.xmlParser;
966
+ for (let el of xml.elements(root, "commentEx")) this.comments.push({
967
+ paraId: xml.attr(el, "paraId"),
968
+ paraIdParent: xml.attr(el, "paraIdParent"),
969
+ done: xml.boolAttr(el, "done")
970
+ });
971
+ this.commentMap = keyBy(this.comments, (x) => x.paraId);
972
+ }
973
+ };
974
+ var topLevelRels = [
975
+ {
976
+ type: RelationshipTypes.OfficeDocument,
977
+ target: "word/document.xml"
978
+ },
979
+ {
980
+ type: RelationshipTypes.ExtendedProperties,
981
+ target: "docProps/app.xml"
982
+ },
983
+ {
984
+ type: RelationshipTypes.CoreProperties,
985
+ target: "docProps/core.xml"
986
+ },
987
+ {
988
+ type: RelationshipTypes.CustomProperties,
989
+ target: "docProps/custom.xml"
990
+ }
991
+ ];
992
+ var WordDocument = class WordDocument {
993
+ constructor() {
994
+ this.parts = [];
995
+ this.partsMap = {};
996
+ }
997
+ static async load(blob, parser, options) {
998
+ var d = new WordDocument();
999
+ d._options = options;
1000
+ d._parser = parser;
1001
+ d._package = await OpenXmlPackage.load(blob, options);
1002
+ d.rels = await d._package.loadRelationships();
1003
+ await Promise.all(topLevelRels.map((rel) => {
1004
+ const r = d.rels.find((x) => x.type === rel.type) ?? rel;
1005
+ return d.loadRelationshipPart(r.target, r.type);
1006
+ }));
1007
+ return d;
1008
+ }
1009
+ save(type = "blob") {
1010
+ return this._package.save(type);
1011
+ }
1012
+ async loadRelationshipPart(path, type) {
1013
+ if (this.partsMap[path]) return this.partsMap[path];
1014
+ if (!this._package.get(path)) return null;
1015
+ let part = null;
1016
+ switch (type) {
1017
+ case RelationshipTypes.OfficeDocument:
1018
+ this.documentPart = part = new DocumentPart(this._package, path, this._parser);
1019
+ break;
1020
+ case RelationshipTypes.FontTable:
1021
+ this.fontTablePart = part = new FontTablePart(this._package, path);
1022
+ break;
1023
+ case RelationshipTypes.Numbering:
1024
+ this.numberingPart = part = new NumberingPart(this._package, path, this._parser);
1025
+ break;
1026
+ case RelationshipTypes.Styles:
1027
+ this.stylesPart = part = new StylesPart(this._package, path, this._parser);
1028
+ break;
1029
+ case RelationshipTypes.Theme:
1030
+ this.themePart = part = new ThemePart(this._package, path);
1031
+ break;
1032
+ case RelationshipTypes.Footnotes:
1033
+ this.footnotesPart = part = new FootnotesPart(this._package, path, this._parser);
1034
+ break;
1035
+ case RelationshipTypes.Endnotes:
1036
+ this.endnotesPart = part = new EndnotesPart(this._package, path, this._parser);
1037
+ break;
1038
+ case RelationshipTypes.Footer:
1039
+ part = new FooterPart(this._package, path, this._parser);
1040
+ break;
1041
+ case RelationshipTypes.Header:
1042
+ part = new HeaderPart(this._package, path, this._parser);
1043
+ break;
1044
+ case RelationshipTypes.CoreProperties:
1045
+ this.corePropsPart = part = new CorePropsPart(this._package, path);
1046
+ break;
1047
+ case RelationshipTypes.ExtendedProperties:
1048
+ this.extendedPropsPart = part = new ExtendedPropsPart(this._package, path);
1049
+ break;
1050
+ case RelationshipTypes.CustomProperties:
1051
+ part = new CustomPropsPart(this._package, path);
1052
+ break;
1053
+ case RelationshipTypes.Settings:
1054
+ this.settingsPart = part = new SettingsPart(this._package, path);
1055
+ break;
1056
+ case RelationshipTypes.Comments:
1057
+ this.commentsPart = part = new CommentsPart(this._package, path, this._parser);
1058
+ break;
1059
+ case RelationshipTypes.CommentsExtended: this.commentsExtendedPart = part = new CommentsExtendedPart(this._package, path);
1060
+ }
1061
+ if (part == null) return Promise.resolve(null);
1062
+ this.partsMap[path] = part;
1063
+ this.parts.push(part);
1064
+ await part.load();
1065
+ if (part.rels?.length > 0) {
1066
+ const [folder] = splitPath(part.path);
1067
+ await Promise.all(part.rels.map((rel) => this.loadRelationshipPart(resolvePath(rel.target, folder), rel.type)));
1068
+ }
1069
+ return part;
1070
+ }
1071
+ async loadDocumentImage(id, part) {
1072
+ const x = await this.loadResource(part ?? this.documentPart, id, "blob");
1073
+ return this.blobToURL(x);
1074
+ }
1075
+ async loadNumberingImage(id) {
1076
+ const x = await this.loadResource(this.numberingPart, id, "blob");
1077
+ return this.blobToURL(x);
1078
+ }
1079
+ async loadFont(id, key) {
1080
+ const x = await this.loadResource(this.fontTablePart, id, "uint8array");
1081
+ return x ? this.blobToURL(new Blob([deobfuscate(x, key)])) : x;
1082
+ }
1083
+ async loadAltChunk(id, part) {
1084
+ return await this.loadResource(part ?? this.documentPart, id, "string");
1085
+ }
1086
+ blobToURL(blob) {
1087
+ if (!blob) return null;
1088
+ if (this._options.useBase64URL) return blobToBase64(blob);
1089
+ return URL.createObjectURL(blob);
1090
+ }
1091
+ findPartByRelId(id, basePart = null) {
1092
+ var rel = (basePart.rels ?? this.rels).find((r) => r.id == id);
1093
+ const folder = basePart ? splitPath(basePart.path)[0] : "";
1094
+ return rel ? this.partsMap[resolvePath(rel.target, folder)] : null;
1095
+ }
1096
+ getPathById(part, id) {
1097
+ const rel = part.rels.find((x) => x.id == id);
1098
+ const [folder] = splitPath(part.path);
1099
+ return rel ? resolvePath(rel.target, folder) : null;
1100
+ }
1101
+ loadResource(part, id, outputType) {
1102
+ const path = this.getPathById(part, id);
1103
+ return path ? this._package.load(path, outputType) : Promise.resolve(null);
1104
+ }
1105
+ };
1106
+ function deobfuscate(data, guidKey) {
1107
+ const len = 16;
1108
+ const trimmed = guidKey.replace(/{|}|-/g, "");
1109
+ const numbers = new Array(len);
1110
+ for (let i = 0; i < len; i++) numbers[len - i - 1] = parseInt(trimmed.substring(i * 2, i * 2 + 2), 16);
1111
+ for (let i = 0; i < 32; i++) data[i] = data[i] ^ numbers[i % len];
1112
+ return data;
1113
+ }
1114
+ function parseBookmarkStart(elem, xml) {
1115
+ return {
1116
+ type: DomType.BookmarkStart,
1117
+ id: xml.attr(elem, "id"),
1118
+ name: xml.attr(elem, "name"),
1119
+ colFirst: xml.intAttr(elem, "colFirst"),
1120
+ colLast: xml.intAttr(elem, "colLast")
1121
+ };
1122
+ }
1123
+ function parseBookmarkEnd(elem, xml) {
1124
+ return {
1125
+ type: DomType.BookmarkEnd,
1126
+ id: xml.attr(elem, "id")
1127
+ };
1128
+ }
1129
+ var VmlElement = class extends OpenXmlElementBase {
1130
+ constructor() {
1131
+ super(...arguments);
1132
+ this.type = DomType.VmlElement;
1133
+ this.attrs = {};
1134
+ }
1135
+ };
1136
+ function parseVmlElement(elem, parser) {
1137
+ var result = new VmlElement();
1138
+ switch (elem.localName) {
1139
+ case "rect":
1140
+ result.tagName = "rect";
1141
+ Object.assign(result.attrs, {
1142
+ width: "100%",
1143
+ height: "100%"
1144
+ });
1145
+ break;
1146
+ case "oval":
1147
+ result.tagName = "ellipse";
1148
+ Object.assign(result.attrs, {
1149
+ cx: "50%",
1150
+ cy: "50%",
1151
+ rx: "50%",
1152
+ ry: "50%"
1153
+ });
1154
+ break;
1155
+ case "line":
1156
+ result.tagName = "line";
1157
+ break;
1158
+ case "shape":
1159
+ result.tagName = "g";
1160
+ break;
1161
+ case "textbox":
1162
+ result.tagName = "foreignObject";
1163
+ Object.assign(result.attrs, {
1164
+ width: "100%",
1165
+ height: "100%"
1166
+ });
1167
+ break;
1168
+ default: return null;
1169
+ }
1170
+ for (const at of globalXmlParser.attrs(elem)) switch (at.localName) {
1171
+ case "style":
1172
+ result.cssStyleText = at.value;
1173
+ break;
1174
+ case "fillcolor":
1175
+ result.attrs.fill = at.value;
1176
+ break;
1177
+ case "from":
1178
+ const [x1, y1] = parsePoint(at.value);
1179
+ Object.assign(result.attrs, {
1180
+ x1,
1181
+ y1
1182
+ });
1183
+ break;
1184
+ case "to":
1185
+ const [x2, y2] = parsePoint(at.value);
1186
+ Object.assign(result.attrs, {
1187
+ x2,
1188
+ y2
1189
+ });
1190
+ }
1191
+ for (const el of globalXmlParser.elements(elem)) switch (el.localName) {
1192
+ case "stroke":
1193
+ Object.assign(result.attrs, parseStroke(el));
1194
+ break;
1195
+ case "fill":
1196
+ Object.assign(result.attrs, parseFill());
1197
+ break;
1198
+ case "imagedata":
1199
+ result.tagName = "image";
1200
+ Object.assign(result.attrs, {
1201
+ width: "100%",
1202
+ height: "100%"
1203
+ });
1204
+ result.imageHref = {
1205
+ id: globalXmlParser.attr(el, "id"),
1206
+ title: globalXmlParser.attr(el, "title")
1207
+ };
1208
+ break;
1209
+ case "txbxContent":
1210
+ result.children.push(...parser.parseBodyElements(el));
1211
+ break;
1212
+ default:
1213
+ const child = parseVmlElement(el, parser);
1214
+ child && result.children.push(child);
1215
+ }
1216
+ return result;
1217
+ }
1218
+ function parseStroke(el) {
1219
+ return {
1220
+ "stroke": globalXmlParser.attr(el, "color"),
1221
+ "stroke-width": globalXmlParser.lengthAttr(el, "weight", LengthUsage.Emu) ?? "1px"
1222
+ };
1223
+ }
1224
+ function parseFill(el) {
1225
+ return {};
1226
+ }
1227
+ function parsePoint(val) {
1228
+ return val.split(",");
1229
+ }
1230
+ var WmlComment = class extends OpenXmlElementBase {
1231
+ constructor() {
1232
+ super(...arguments);
1233
+ this.type = DomType.Comment;
1234
+ }
1235
+ };
1236
+ var WmlCommentReference = class extends OpenXmlElementBase {
1237
+ constructor(id) {
1238
+ super();
1239
+ this.id = id;
1240
+ this.type = DomType.CommentReference;
1241
+ }
1242
+ };
1243
+ var WmlCommentRangeStart = class extends OpenXmlElementBase {
1244
+ constructor(id) {
1245
+ super();
1246
+ this.id = id;
1247
+ this.type = DomType.CommentRangeStart;
1248
+ }
1249
+ };
1250
+ var WmlCommentRangeEnd = class extends OpenXmlElementBase {
1251
+ constructor(id) {
1252
+ super();
1253
+ this.id = id;
1254
+ this.type = DomType.CommentRangeEnd;
1255
+ }
1256
+ };
1257
+ var autos = {
1258
+ shd: "inherit",
1259
+ color: "black",
1260
+ borderColor: "black",
1261
+ highlight: "transparent"
1262
+ };
1263
+ var supportedNamespaceURIs = [];
1264
+ var mmlTagMap = {
1265
+ "oMath": DomType.MmlMath,
1266
+ "oMathPara": DomType.MmlMathParagraph,
1267
+ "f": DomType.MmlFraction,
1268
+ "func": DomType.MmlFunction,
1269
+ "fName": DomType.MmlFunctionName,
1270
+ "num": DomType.MmlNumerator,
1271
+ "den": DomType.MmlDenominator,
1272
+ "rad": DomType.MmlRadical,
1273
+ "deg": DomType.MmlDegree,
1274
+ "e": DomType.MmlBase,
1275
+ "sSup": DomType.MmlSuperscript,
1276
+ "sSub": DomType.MmlSubscript,
1277
+ "sPre": DomType.MmlPreSubSuper,
1278
+ "sup": DomType.MmlSuperArgument,
1279
+ "sub": DomType.MmlSubArgument,
1280
+ "d": DomType.MmlDelimiter,
1281
+ "nary": DomType.MmlNary,
1282
+ "eqArr": DomType.MmlEquationArray,
1283
+ "lim": DomType.MmlLimit,
1284
+ "limLow": DomType.MmlLimitLower,
1285
+ "m": DomType.MmlMatrix,
1286
+ "mr": DomType.MmlMatrixRow,
1287
+ "box": DomType.MmlBox,
1288
+ "bar": DomType.MmlBar,
1289
+ "groupChr": DomType.MmlGroupChar
1290
+ };
1291
+ var DocumentParser = class {
1292
+ constructor(options) {
1293
+ this.options = {
1294
+ ignoreWidth: false,
1295
+ debug: false,
1296
+ ...options
1297
+ };
1298
+ }
1299
+ parseNotes(xmlDoc, elemName, elemClass) {
1300
+ var result = [];
1301
+ for (let el of globalXmlParser.elements(xmlDoc, elemName)) {
1302
+ const node = new elemClass();
1303
+ node.id = globalXmlParser.attr(el, "id");
1304
+ node.noteType = globalXmlParser.attr(el, "type");
1305
+ node.children = this.parseBodyElements(el, elemName);
1306
+ result.push(node);
1307
+ }
1308
+ return result;
1309
+ }
1310
+ parseComments(xmlDoc) {
1311
+ var result = [];
1312
+ for (let el of globalXmlParser.elements(xmlDoc, "comment")) {
1313
+ const item = new WmlComment();
1314
+ item.id = globalXmlParser.attr(el, "id");
1315
+ item.author = globalXmlParser.attr(el, "author");
1316
+ item.initials = globalXmlParser.attr(el, "initials");
1317
+ item.date = globalXmlParser.attr(el, "date");
1318
+ item.children = this.parseBodyElements(el, "comment");
1319
+ result.push(item);
1320
+ }
1321
+ return result;
1322
+ }
1323
+ parseDocumentFile(xmlDoc) {
1324
+ var xbody = globalXmlParser.element(xmlDoc, "body");
1325
+ var background = globalXmlParser.element(xmlDoc, "background");
1326
+ var sectPr = globalXmlParser.element(xbody, "sectPr");
1327
+ return {
1328
+ type: DomType.Document,
1329
+ children: this.parseBodyElements(xbody, "body"),
1330
+ props: sectPr ? parseSectionProperties(sectPr, globalXmlParser) : {},
1331
+ cssStyle: background ? this.parseBackground(background) : {}
1332
+ };
1333
+ }
1334
+ parseBackground(elem) {
1335
+ var result = {};
1336
+ var color = xmlUtil.colorAttr(elem, "color");
1337
+ if (color) result["background-color"] = color;
1338
+ return result;
1339
+ }
1340
+ parseBodyElements(element, part) {
1341
+ var children = [];
1342
+ let ordinal = 0;
1343
+ for (const elem of globalXmlParser.elements(element)) switch (elem.localName) {
1344
+ case "p": {
1345
+ const p = this.parseParagraph(elem);
1346
+ if (part) {
1347
+ p.docxPart = part;
1348
+ p.docxIndex = ordinal;
1349
+ }
1350
+ ordinal++;
1351
+ children.push(p);
1352
+ break;
1353
+ }
1354
+ case "altChunk":
1355
+ children.push(this.parseAltChunk(elem));
1356
+ break;
1357
+ case "tbl":
1358
+ children.push(this.parseTable(elem));
1359
+ break;
1360
+ case "sdt": children.push(...this.parseSdt(elem, (e) => this.parseBodyElements(e)));
1361
+ }
1362
+ return children;
1363
+ }
1364
+ parseStylesFile(xstyles) {
1365
+ var result = [];
1366
+ for (const n of globalXmlParser.elements(xstyles)) switch (n.localName) {
1367
+ case "style":
1368
+ result.push(this.parseStyle(n));
1369
+ break;
1370
+ case "docDefaults": result.push(this.parseDefaultStyles(n));
1371
+ }
1372
+ return result;
1373
+ }
1374
+ parseDefaultStyles(node) {
1375
+ var result = {
1376
+ id: null,
1377
+ name: null,
1378
+ target: null,
1379
+ basedOn: null,
1380
+ styles: []
1381
+ };
1382
+ for (const c of globalXmlParser.elements(node)) switch (c.localName) {
1383
+ case "rPrDefault":
1384
+ var rPr = globalXmlParser.element(c, "rPr");
1385
+ if (rPr) result.styles.push({
1386
+ target: "span",
1387
+ values: this.parseDefaultProperties(rPr, {})
1388
+ });
1389
+ break;
1390
+ case "pPrDefault":
1391
+ var pPr = globalXmlParser.element(c, "pPr");
1392
+ if (pPr) result.styles.push({
1393
+ target: "p",
1394
+ values: this.parseDefaultProperties(pPr, {})
1395
+ });
1396
+ }
1397
+ return result;
1398
+ }
1399
+ parseStyle(node) {
1400
+ var result = {
1401
+ id: globalXmlParser.attr(node, "styleId"),
1402
+ isDefault: globalXmlParser.boolAttr(node, "default"),
1403
+ name: null,
1404
+ target: null,
1405
+ basedOn: null,
1406
+ styles: [],
1407
+ linked: null
1408
+ };
1409
+ switch (globalXmlParser.attr(node, "type")) {
1410
+ case "paragraph":
1411
+ result.target = "p";
1412
+ break;
1413
+ case "table":
1414
+ result.target = "table";
1415
+ break;
1416
+ case "character": result.target = "span";
1417
+ }
1418
+ for (const n of globalXmlParser.elements(node)) switch (n.localName) {
1419
+ case "basedOn":
1420
+ result.basedOn = globalXmlParser.attr(n, "val");
1421
+ break;
1422
+ case "name":
1423
+ result.name = globalXmlParser.attr(n, "val");
1424
+ break;
1425
+ case "link":
1426
+ result.linked = globalXmlParser.attr(n, "val");
1427
+ break;
1428
+ case "next":
1429
+ result.next = globalXmlParser.attr(n, "val");
1430
+ break;
1431
+ case "aliases":
1432
+ result.aliases = globalXmlParser.attr(n, "val").split(",");
1433
+ break;
1434
+ case "pPr":
1435
+ result.styles.push({
1436
+ target: "p",
1437
+ values: this.parseDefaultProperties(n, {})
1438
+ });
1439
+ result.paragraphProps = parseParagraphProperties(n, globalXmlParser);
1440
+ break;
1441
+ case "rPr":
1442
+ result.styles.push({
1443
+ target: "span",
1444
+ values: this.parseDefaultProperties(n, {})
1445
+ });
1446
+ result.runProps = parseRunProperties(n, globalXmlParser);
1447
+ break;
1448
+ case "tblPr":
1449
+ case "tcPr":
1450
+ result.styles.push({
1451
+ target: "td",
1452
+ values: this.parseDefaultProperties(n, {})
1453
+ });
1454
+ break;
1455
+ case "tblStylePr":
1456
+ for (let s of this.parseTableStyle(n)) result.styles.push(s);
1457
+ break;
1458
+ case "rsid":
1459
+ case "qFormat":
1460
+ case "hidden":
1461
+ case "semiHidden":
1462
+ case "unhideWhenUsed":
1463
+ case "autoRedefine":
1464
+ case "uiPriority": break;
1465
+ default: this.options.debug && console.warn(`DOCX: Unknown style element: ${n.localName}`);
1466
+ }
1467
+ return result;
1468
+ }
1469
+ parseTableStyle(node) {
1470
+ var result = [];
1471
+ var type = globalXmlParser.attr(node, "type");
1472
+ var selector = "";
1473
+ var modificator = "";
1474
+ switch (type) {
1475
+ case "firstRow":
1476
+ modificator = ".first-row";
1477
+ selector = "tr.first-row td";
1478
+ break;
1479
+ case "lastRow":
1480
+ modificator = ".last-row";
1481
+ selector = "tr.last-row td";
1482
+ break;
1483
+ case "firstCol":
1484
+ modificator = ".first-col";
1485
+ selector = "td.first-col";
1486
+ break;
1487
+ case "lastCol":
1488
+ modificator = ".last-col";
1489
+ selector = "td.last-col";
1490
+ break;
1491
+ case "band1Vert":
1492
+ modificator = ":not(.no-vband)";
1493
+ selector = "td.odd-col";
1494
+ break;
1495
+ case "band2Vert":
1496
+ modificator = ":not(.no-vband)";
1497
+ selector = "td.even-col";
1498
+ break;
1499
+ case "band1Horz":
1500
+ modificator = ":not(.no-hband)";
1501
+ selector = "tr.odd-row";
1502
+ break;
1503
+ case "band2Horz":
1504
+ modificator = ":not(.no-hband)";
1505
+ selector = "tr.even-row";
1506
+ break;
1507
+ default: return [];
1508
+ }
1509
+ for (const n of globalXmlParser.elements(node)) switch (n.localName) {
1510
+ case "pPr":
1511
+ result.push({
1512
+ target: `${selector} p`,
1513
+ mod: modificator,
1514
+ values: this.parseDefaultProperties(n, {})
1515
+ });
1516
+ break;
1517
+ case "rPr":
1518
+ result.push({
1519
+ target: `${selector} span`,
1520
+ mod: modificator,
1521
+ values: this.parseDefaultProperties(n, {})
1522
+ });
1523
+ break;
1524
+ case "tblPr":
1525
+ case "tcPr": result.push({
1526
+ target: selector,
1527
+ mod: modificator,
1528
+ values: this.parseDefaultProperties(n, {})
1529
+ });
1530
+ }
1531
+ return result;
1532
+ }
1533
+ parseNumberingFile(node) {
1534
+ var result = [];
1535
+ var mapping = {};
1536
+ var bullets = [];
1537
+ for (const n of globalXmlParser.elements(node)) switch (n.localName) {
1538
+ case "abstractNum":
1539
+ this.parseAbstractNumbering(n, bullets).forEach((x) => result.push(x));
1540
+ break;
1541
+ case "numPicBullet":
1542
+ bullets.push(this.parseNumberingPicBullet(n));
1543
+ break;
1544
+ case "num":
1545
+ var numId = globalXmlParser.attr(n, "numId");
1546
+ var abstractNumId = globalXmlParser.elementAttr(n, "abstractNumId", "val");
1547
+ mapping[abstractNumId] = numId;
1548
+ }
1549
+ result.forEach((x) => x.id = mapping[x.id]);
1550
+ return result;
1551
+ }
1552
+ parseNumberingPicBullet(elem) {
1553
+ var pict = globalXmlParser.element(elem, "pict");
1554
+ var shape = pict && globalXmlParser.element(pict, "shape");
1555
+ var imagedata = shape && globalXmlParser.element(shape, "imagedata");
1556
+ return imagedata ? {
1557
+ id: globalXmlParser.intAttr(elem, "numPicBulletId"),
1558
+ src: globalXmlParser.attr(imagedata, "id"),
1559
+ style: globalXmlParser.attr(shape, "style")
1560
+ } : null;
1561
+ }
1562
+ parseAbstractNumbering(node, bullets) {
1563
+ var result = [];
1564
+ var id = globalXmlParser.attr(node, "abstractNumId");
1565
+ for (const n of globalXmlParser.elements(node)) switch (n.localName) {
1566
+ case "lvl": result.push(this.parseNumberingLevel(id, n, bullets));
1567
+ }
1568
+ return result;
1569
+ }
1570
+ parseNumberingLevel(id, node, bullets) {
1571
+ var result = {
1572
+ id,
1573
+ level: globalXmlParser.intAttr(node, "ilvl"),
1574
+ start: 1,
1575
+ pStyleName: void 0,
1576
+ pStyle: {},
1577
+ rStyle: {},
1578
+ suff: "tab"
1579
+ };
1580
+ for (const n of globalXmlParser.elements(node)) switch (n.localName) {
1581
+ case "start":
1582
+ result.start = globalXmlParser.intAttr(n, "val");
1583
+ break;
1584
+ case "pPr":
1585
+ this.parseDefaultProperties(n, result.pStyle);
1586
+ break;
1587
+ case "rPr":
1588
+ this.parseDefaultProperties(n, result.rStyle);
1589
+ break;
1590
+ case "lvlPicBulletId":
1591
+ var bulletId = globalXmlParser.intAttr(n, "val");
1592
+ result.bullet = bullets.find((x) => x?.id == bulletId);
1593
+ break;
1594
+ case "lvlText":
1595
+ result.levelText = globalXmlParser.attr(n, "val");
1596
+ break;
1597
+ case "pStyle":
1598
+ result.pStyleName = globalXmlParser.attr(n, "val");
1599
+ break;
1600
+ case "numFmt":
1601
+ result.format = globalXmlParser.attr(n, "val");
1602
+ break;
1603
+ case "suff": result.suff = globalXmlParser.attr(n, "val");
1604
+ }
1605
+ return result;
1606
+ }
1607
+ parseSdt(node, parser) {
1608
+ const sdtContent = globalXmlParser.element(node, "sdtContent");
1609
+ return sdtContent ? parser(sdtContent) : [];
1610
+ }
1611
+ parseInserted(node, parentParser) {
1612
+ return {
1613
+ type: DomType.Inserted,
1614
+ children: parentParser(node)?.children ?? []
1615
+ };
1616
+ }
1617
+ parseDeleted(node, parentParser) {
1618
+ return {
1619
+ type: DomType.Deleted,
1620
+ children: parentParser(node)?.children ?? []
1621
+ };
1622
+ }
1623
+ parseAltChunk(node) {
1624
+ return {
1625
+ type: DomType.AltChunk,
1626
+ children: [],
1627
+ id: globalXmlParser.attr(node, "id")
1628
+ };
1629
+ }
1630
+ parseParagraph(node) {
1631
+ var result = {
1632
+ type: DomType.Paragraph,
1633
+ children: []
1634
+ };
1635
+ const paraId = globalXmlParser.attr(node, "paraId");
1636
+ if (paraId) result.paraId = paraId;
1637
+ for (let el of globalXmlParser.elements(node)) switch (el.localName) {
1638
+ case "pPr":
1639
+ this.parseParagraphProperties(el, result);
1640
+ break;
1641
+ case "r":
1642
+ result.children.push(this.parseRun(el, result));
1643
+ break;
1644
+ case "hyperlink":
1645
+ result.children.push(this.parseHyperlink(el, result));
1646
+ break;
1647
+ case "smartTag":
1648
+ result.children.push(this.parseSmartTag(el, result));
1649
+ break;
1650
+ case "bookmarkStart":
1651
+ result.children.push(parseBookmarkStart(el, globalXmlParser));
1652
+ break;
1653
+ case "bookmarkEnd":
1654
+ result.children.push(parseBookmarkEnd(el, globalXmlParser));
1655
+ break;
1656
+ case "commentRangeStart":
1657
+ result.children.push(new WmlCommentRangeStart(globalXmlParser.attr(el, "id")));
1658
+ break;
1659
+ case "commentRangeEnd":
1660
+ result.children.push(new WmlCommentRangeEnd(globalXmlParser.attr(el, "id")));
1661
+ break;
1662
+ case "oMath":
1663
+ case "oMathPara":
1664
+ result.children.push(this.parseMathElement(el));
1665
+ break;
1666
+ case "sdt":
1667
+ result.children.push(...this.parseSdt(el, (e) => this.parseParagraph(e).children));
1668
+ break;
1669
+ case "ins":
1670
+ result.children.push(this.parseInserted(el, (e) => this.parseParagraph(e)));
1671
+ break;
1672
+ case "del": result.children.push(this.parseDeleted(el, (e) => this.parseParagraph(e)));
1673
+ }
1674
+ return result;
1675
+ }
1676
+ parseParagraphProperties(elem, paragraph) {
1677
+ this.parseDefaultProperties(elem, paragraph.cssStyle = {}, null, (c) => {
1678
+ if (parseParagraphProperty(c, paragraph, globalXmlParser)) return true;
1679
+ switch (c.localName) {
1680
+ case "pStyle":
1681
+ paragraph.styleName = globalXmlParser.attr(c, "val");
1682
+ break;
1683
+ case "cnfStyle":
1684
+ paragraph.className = values.classNameOfCnfStyle(c);
1685
+ break;
1686
+ case "framePr":
1687
+ this.parseFrame(c, paragraph);
1688
+ break;
1689
+ case "rPr": break;
1690
+ default: return false;
1691
+ }
1692
+ return true;
1693
+ });
1694
+ }
1695
+ parseFrame(node, paragraph) {
1696
+ if (globalXmlParser.attr(node, "dropCap") == "drop") paragraph.cssStyle["float"] = "left";
1697
+ }
1698
+ parseHyperlink(node, parent) {
1699
+ var result = {
1700
+ type: DomType.Hyperlink,
1701
+ parent,
1702
+ children: []
1703
+ };
1704
+ result.anchor = globalXmlParser.attr(node, "anchor");
1705
+ result.id = globalXmlParser.attr(node, "id");
1706
+ for (const c of globalXmlParser.elements(node)) switch (c.localName) {
1707
+ case "r": result.children.push(this.parseRun(c, result));
1708
+ }
1709
+ return result;
1710
+ }
1711
+ parseSmartTag(node, parent) {
1712
+ var result = {
1713
+ type: DomType.SmartTag,
1714
+ parent,
1715
+ children: []
1716
+ };
1717
+ var uri = globalXmlParser.attr(node, "uri");
1718
+ var element = globalXmlParser.attr(node, "element");
1719
+ if (uri) result.uri = uri;
1720
+ if (element) result.element = element;
1721
+ for (const c of globalXmlParser.elements(node)) switch (c.localName) {
1722
+ case "r": result.children.push(this.parseRun(c, result));
1723
+ }
1724
+ return result;
1725
+ }
1726
+ parseRun(node, parent) {
1727
+ var result = {
1728
+ type: DomType.Run,
1729
+ parent,
1730
+ children: []
1731
+ };
1732
+ for (let c of globalXmlParser.elements(node)) {
1733
+ c = this.checkAlternateContent(c);
1734
+ switch (c.localName) {
1735
+ case "t":
1736
+ result.children.push({
1737
+ type: DomType.Text,
1738
+ text: c.textContent
1739
+ });
1740
+ break;
1741
+ case "delText":
1742
+ result.children.push({
1743
+ type: DomType.DeletedText,
1744
+ text: c.textContent
1745
+ });
1746
+ break;
1747
+ case "commentReference":
1748
+ result.children.push(new WmlCommentReference(globalXmlParser.attr(c, "id")));
1749
+ break;
1750
+ case "fldSimple":
1751
+ result.children.push({
1752
+ type: DomType.SimpleField,
1753
+ instruction: globalXmlParser.attr(c, "instr"),
1754
+ lock: globalXmlParser.boolAttr(c, "lock", false),
1755
+ dirty: globalXmlParser.boolAttr(c, "dirty", false)
1756
+ });
1757
+ break;
1758
+ case "instrText":
1759
+ result.fieldRun = true;
1760
+ result.children.push({
1761
+ type: DomType.Instruction,
1762
+ text: c.textContent
1763
+ });
1764
+ break;
1765
+ case "fldChar":
1766
+ result.fieldRun = true;
1767
+ result.children.push({
1768
+ type: DomType.ComplexField,
1769
+ charType: globalXmlParser.attr(c, "fldCharType"),
1770
+ lock: globalXmlParser.boolAttr(c, "lock", false),
1771
+ dirty: globalXmlParser.boolAttr(c, "dirty", false)
1772
+ });
1773
+ break;
1774
+ case "noBreakHyphen":
1775
+ result.children.push({ type: DomType.NoBreakHyphen });
1776
+ break;
1777
+ case "br":
1778
+ result.children.push({
1779
+ type: DomType.Break,
1780
+ break: globalXmlParser.attr(c, "type") || "textWrapping"
1781
+ });
1782
+ break;
1783
+ case "lastRenderedPageBreak":
1784
+ result.children.push({
1785
+ type: DomType.Break,
1786
+ break: "lastRenderedPageBreak"
1787
+ });
1788
+ break;
1789
+ case "sym":
1790
+ result.children.push({
1791
+ type: DomType.Symbol,
1792
+ font: encloseFontFamily(globalXmlParser.attr(c, "font")),
1793
+ char: globalXmlParser.attr(c, "char")
1794
+ });
1795
+ break;
1796
+ case "tab":
1797
+ result.children.push({ type: DomType.Tab });
1798
+ break;
1799
+ case "footnoteReference":
1800
+ result.children.push({
1801
+ type: DomType.FootnoteReference,
1802
+ id: globalXmlParser.attr(c, "id")
1803
+ });
1804
+ break;
1805
+ case "endnoteReference":
1806
+ result.children.push({
1807
+ type: DomType.EndnoteReference,
1808
+ id: globalXmlParser.attr(c, "id")
1809
+ });
1810
+ break;
1811
+ case "drawing":
1812
+ let d = this.parseDrawing(c);
1813
+ if (d) result.children = [d];
1814
+ break;
1815
+ case "pict":
1816
+ result.children.push(this.parseVmlPicture(c));
1817
+ break;
1818
+ case "rPr": this.parseRunProperties(c, result);
1819
+ }
1820
+ }
1821
+ return result;
1822
+ }
1823
+ parseMathElement(elem) {
1824
+ const propsTag = `${elem.localName}Pr`;
1825
+ const result = {
1826
+ type: mmlTagMap[elem.localName],
1827
+ children: []
1828
+ };
1829
+ for (const el of globalXmlParser.elements(elem)) if (mmlTagMap[el.localName]) result.children.push(this.parseMathElement(el));
1830
+ else if (el.localName == "r") {
1831
+ var run = this.parseRun(el);
1832
+ run.type = DomType.MmlRun;
1833
+ result.children.push(run);
1834
+ } else if (el.localName == propsTag) result.props = this.parseMathProperies(el);
1835
+ return result;
1836
+ }
1837
+ parseMathProperies(elem) {
1838
+ const result = {};
1839
+ for (const el of globalXmlParser.elements(elem)) switch (el.localName) {
1840
+ case "chr":
1841
+ result.char = globalXmlParser.attr(el, "val");
1842
+ break;
1843
+ case "vertJc":
1844
+ result.verticalJustification = globalXmlParser.attr(el, "val");
1845
+ break;
1846
+ case "pos":
1847
+ result.position = globalXmlParser.attr(el, "val");
1848
+ break;
1849
+ case "degHide":
1850
+ result.hideDegree = globalXmlParser.boolAttr(el, "val");
1851
+ break;
1852
+ case "begChr":
1853
+ result.beginChar = globalXmlParser.attr(el, "val");
1854
+ break;
1855
+ case "endChr": result.endChar = globalXmlParser.attr(el, "val");
1856
+ }
1857
+ return result;
1858
+ }
1859
+ parseRunProperties(elem, run) {
1860
+ this.parseDefaultProperties(elem, run.cssStyle = {}, null, (c) => {
1861
+ switch (c.localName) {
1862
+ case "rStyle":
1863
+ run.styleName = globalXmlParser.attr(c, "val");
1864
+ break;
1865
+ case "vertAlign":
1866
+ run.verticalAlign = values.valueOfVertAlign(c, true);
1867
+ break;
1868
+ default: return false;
1869
+ }
1870
+ return true;
1871
+ });
1872
+ }
1873
+ parseVmlPicture(elem) {
1874
+ const result = {
1875
+ type: DomType.VmlPicture,
1876
+ children: []
1877
+ };
1878
+ for (const el of globalXmlParser.elements(elem)) {
1879
+ const child = parseVmlElement(el, this);
1880
+ child && result.children.push(child);
1881
+ }
1882
+ return result;
1883
+ }
1884
+ checkAlternateContent(elem) {
1885
+ if (elem.localName != "AlternateContent") return elem;
1886
+ var choice = globalXmlParser.element(elem, "Choice");
1887
+ if (choice) {
1888
+ var requires = globalXmlParser.attr(choice, "Requires");
1889
+ var namespaceURI = elem.lookupNamespaceURI(requires);
1890
+ if (supportedNamespaceURIs.includes(namespaceURI)) return choice.firstElementChild;
1891
+ }
1892
+ return globalXmlParser.element(elem, "Fallback")?.firstElementChild;
1893
+ }
1894
+ parseDrawing(node) {
1895
+ for (var n of globalXmlParser.elements(node)) switch (n.localName) {
1896
+ case "inline":
1897
+ case "anchor": return this.parseDrawingWrapper(n);
1898
+ }
1899
+ }
1900
+ parseDrawingWrapper(node) {
1901
+ var result = {
1902
+ type: DomType.Drawing,
1903
+ children: [],
1904
+ cssStyle: {}
1905
+ };
1906
+ var isAnchor = node.localName == "anchor";
1907
+ let wrapType = null;
1908
+ let simplePos = globalXmlParser.boolAttr(node, "simplePos");
1909
+ globalXmlParser.boolAttr(node, "behindDoc");
1910
+ let posX = {
1911
+ relative: "page",
1912
+ align: "left",
1913
+ offset: "0"
1914
+ };
1915
+ let posY = {
1916
+ relative: "page",
1917
+ align: "top",
1918
+ offset: "0"
1919
+ };
1920
+ for (var n of globalXmlParser.elements(node)) switch (n.localName) {
1921
+ case "simplePos":
1922
+ if (simplePos) {
1923
+ posX.offset = globalXmlParser.lengthAttr(n, "x", LengthUsage.Emu);
1924
+ posY.offset = globalXmlParser.lengthAttr(n, "y", LengthUsage.Emu);
1925
+ }
1926
+ break;
1927
+ case "extent":
1928
+ result.cssStyle["width"] = globalXmlParser.lengthAttr(n, "cx", LengthUsage.Emu);
1929
+ result.cssStyle["height"] = globalXmlParser.lengthAttr(n, "cy", LengthUsage.Emu);
1930
+ break;
1931
+ case "positionH":
1932
+ case "positionV":
1933
+ if (!simplePos) {
1934
+ let pos = n.localName == "positionH" ? posX : posY;
1935
+ var alignNode = globalXmlParser.element(n, "align");
1936
+ var offsetNode = globalXmlParser.element(n, "posOffset");
1937
+ pos.relative = globalXmlParser.attr(n, "relativeFrom") ?? pos.relative;
1938
+ if (alignNode) pos.align = alignNode.textContent;
1939
+ if (offsetNode) pos.offset = convertLength(offsetNode.textContent, LengthUsage.Emu);
1940
+ }
1941
+ break;
1942
+ case "wrapTopAndBottom":
1943
+ wrapType = "wrapTopAndBottom";
1944
+ break;
1945
+ case "wrapNone":
1946
+ wrapType = "wrapNone";
1947
+ break;
1948
+ case "graphic":
1949
+ var g = this.parseGraphic(n);
1950
+ if (g) result.children.push(g);
1951
+ }
1952
+ if (wrapType == "wrapTopAndBottom") {
1953
+ result.cssStyle["display"] = "block";
1954
+ if (posX.align) {
1955
+ result.cssStyle["text-align"] = posX.align;
1956
+ result.cssStyle["width"] = "100%";
1957
+ }
1958
+ } else if (wrapType == "wrapNone") {
1959
+ result.cssStyle["display"] = "block";
1960
+ result.cssStyle["position"] = "relative";
1961
+ result.cssStyle["width"] = "0px";
1962
+ result.cssStyle["height"] = "0px";
1963
+ if (posX.offset) result.cssStyle["left"] = posX.offset;
1964
+ if (posY.offset) result.cssStyle["top"] = posY.offset;
1965
+ } else if (isAnchor && (posX.align == "left" || posX.align == "right")) result.cssStyle["float"] = posX.align;
1966
+ return result;
1967
+ }
1968
+ parseGraphic(elem) {
1969
+ var graphicData = globalXmlParser.element(elem, "graphicData");
1970
+ for (let n of globalXmlParser.elements(graphicData)) switch (n.localName) {
1971
+ case "pic": return this.parsePicture(n);
1972
+ }
1973
+ return null;
1974
+ }
1975
+ parsePicture(elem) {
1976
+ var result = {
1977
+ type: DomType.Image,
1978
+ src: "",
1979
+ cssStyle: {}
1980
+ };
1981
+ var blipFill = globalXmlParser.element(elem, "blipFill");
1982
+ var blip = globalXmlParser.element(blipFill, "blip");
1983
+ var srcRect = globalXmlParser.element(blipFill, "srcRect");
1984
+ result.src = globalXmlParser.attr(blip, "embed");
1985
+ if (srcRect) result.srcRect = [
1986
+ globalXmlParser.intAttr(srcRect, "l", 0) / 1e5,
1987
+ globalXmlParser.intAttr(srcRect, "t", 0) / 1e5,
1988
+ globalXmlParser.intAttr(srcRect, "r", 0) / 1e5,
1989
+ globalXmlParser.intAttr(srcRect, "b", 0) / 1e5
1990
+ ];
1991
+ var spPr = globalXmlParser.element(elem, "spPr");
1992
+ var xfrm = globalXmlParser.element(spPr, "xfrm");
1993
+ result.cssStyle["position"] = "relative";
1994
+ if (xfrm) {
1995
+ result.rotation = globalXmlParser.intAttr(xfrm, "rot", 0) / 6e4;
1996
+ for (var n of globalXmlParser.elements(xfrm)) switch (n.localName) {
1997
+ case "ext":
1998
+ result.cssStyle["width"] = globalXmlParser.lengthAttr(n, "cx", LengthUsage.Emu);
1999
+ result.cssStyle["height"] = globalXmlParser.lengthAttr(n, "cy", LengthUsage.Emu);
2000
+ break;
2001
+ case "off":
2002
+ result.cssStyle["left"] = globalXmlParser.lengthAttr(n, "x", LengthUsage.Emu);
2003
+ result.cssStyle["top"] = globalXmlParser.lengthAttr(n, "y", LengthUsage.Emu);
2004
+ }
2005
+ }
2006
+ return result;
2007
+ }
2008
+ parseTable(node) {
2009
+ var result = {
2010
+ type: DomType.Table,
2011
+ children: []
2012
+ };
2013
+ for (const c of globalXmlParser.elements(node)) switch (c.localName) {
2014
+ case "tr":
2015
+ result.children.push(this.parseTableRow(c));
2016
+ break;
2017
+ case "tblGrid":
2018
+ result.columns = this.parseTableColumns(c);
2019
+ break;
2020
+ case "tblPr": this.parseTableProperties(c, result);
2021
+ }
2022
+ return result;
2023
+ }
2024
+ parseTableColumns(node) {
2025
+ var result = [];
2026
+ for (const n of globalXmlParser.elements(node)) switch (n.localName) {
2027
+ case "gridCol": result.push({ width: globalXmlParser.lengthAttr(n, "w") });
2028
+ }
2029
+ return result;
2030
+ }
2031
+ parseTableProperties(elem, table) {
2032
+ table.cssStyle = {};
2033
+ table.cellStyle = {};
2034
+ this.parseDefaultProperties(elem, table.cssStyle, table.cellStyle, (c) => {
2035
+ switch (c.localName) {
2036
+ case "tblStyle":
2037
+ table.styleName = globalXmlParser.attr(c, "val");
2038
+ break;
2039
+ case "tblLook":
2040
+ table.className = values.classNameOftblLook(c);
2041
+ break;
2042
+ case "tblpPr":
2043
+ this.parseTablePosition(c, table);
2044
+ break;
2045
+ case "tblStyleColBandSize":
2046
+ table.colBandSize = globalXmlParser.intAttr(c, "val");
2047
+ break;
2048
+ case "tblStyleRowBandSize":
2049
+ table.rowBandSize = globalXmlParser.intAttr(c, "val");
2050
+ break;
2051
+ case "hidden":
2052
+ table.cssStyle["display"] = "none";
2053
+ break;
2054
+ default: return false;
2055
+ }
2056
+ return true;
2057
+ });
2058
+ switch (table.cssStyle["text-align"]) {
2059
+ case "center":
2060
+ delete table.cssStyle["text-align"];
2061
+ table.cssStyle["margin-left"] = "auto";
2062
+ table.cssStyle["margin-right"] = "auto";
2063
+ break;
2064
+ case "right":
2065
+ delete table.cssStyle["text-align"];
2066
+ table.cssStyle["margin-left"] = "auto";
2067
+ }
2068
+ }
2069
+ parseTablePosition(node, table) {
2070
+ var topFromText = globalXmlParser.lengthAttr(node, "topFromText");
2071
+ var bottomFromText = globalXmlParser.lengthAttr(node, "bottomFromText");
2072
+ var rightFromText = globalXmlParser.lengthAttr(node, "rightFromText");
2073
+ var leftFromText = globalXmlParser.lengthAttr(node, "leftFromText");
2074
+ table.cssStyle["float"] = "left";
2075
+ table.cssStyle["margin-bottom"] = values.addSize(table.cssStyle["margin-bottom"], bottomFromText);
2076
+ table.cssStyle["margin-left"] = values.addSize(table.cssStyle["margin-left"], leftFromText);
2077
+ table.cssStyle["margin-right"] = values.addSize(table.cssStyle["margin-right"], rightFromText);
2078
+ table.cssStyle["margin-top"] = values.addSize(table.cssStyle["margin-top"], topFromText);
2079
+ }
2080
+ parseTableRow(node) {
2081
+ var result = {
2082
+ type: DomType.Row,
2083
+ children: []
2084
+ };
2085
+ for (const c of globalXmlParser.elements(node)) switch (c.localName) {
2086
+ case "tc":
2087
+ result.children.push(this.parseTableCell(c));
2088
+ break;
2089
+ case "trPr":
2090
+ case "tblPrEx": this.parseTableRowProperties(c, result);
2091
+ }
2092
+ return result;
2093
+ }
2094
+ parseTableRowProperties(elem, row) {
2095
+ row.cssStyle = this.parseDefaultProperties(elem, {}, null, (c) => {
2096
+ switch (c.localName) {
2097
+ case "cnfStyle":
2098
+ row.className = values.classNameOfCnfStyle(c);
2099
+ break;
2100
+ case "tblHeader":
2101
+ row.isHeader = globalXmlParser.boolAttr(c, "val");
2102
+ break;
2103
+ case "gridBefore":
2104
+ row.gridBefore = globalXmlParser.intAttr(c, "val");
2105
+ break;
2106
+ case "gridAfter":
2107
+ row.gridAfter = globalXmlParser.intAttr(c, "val");
2108
+ break;
2109
+ default: return false;
2110
+ }
2111
+ return true;
2112
+ });
2113
+ }
2114
+ parseTableCell(node) {
2115
+ var result = {
2116
+ type: DomType.Cell,
2117
+ children: []
2118
+ };
2119
+ for (const c of globalXmlParser.elements(node)) switch (c.localName) {
2120
+ case "tbl":
2121
+ result.children.push(this.parseTable(c));
2122
+ break;
2123
+ case "p":
2124
+ result.children.push(this.parseParagraph(c));
2125
+ break;
2126
+ case "tcPr": this.parseTableCellProperties(c, result);
2127
+ }
2128
+ return result;
2129
+ }
2130
+ parseTableCellProperties(elem, cell) {
2131
+ cell.cssStyle = this.parseDefaultProperties(elem, {}, null, (c) => {
2132
+ switch (c.localName) {
2133
+ case "gridSpan":
2134
+ cell.span = globalXmlParser.intAttr(c, "val", null);
2135
+ break;
2136
+ case "vMerge":
2137
+ cell.verticalMerge = globalXmlParser.attr(c, "val") ?? "continue";
2138
+ break;
2139
+ case "cnfStyle":
2140
+ cell.className = values.classNameOfCnfStyle(c);
2141
+ break;
2142
+ default: return false;
2143
+ }
2144
+ return true;
2145
+ });
2146
+ this.parseTableCellVerticalText(elem, cell);
2147
+ }
2148
+ parseTableCellVerticalText(elem, cell) {
2149
+ const directionMap = {
2150
+ "btLr": {
2151
+ writingMode: "vertical-rl",
2152
+ transform: "rotate(180deg)"
2153
+ },
2154
+ "lrTb": {
2155
+ writingMode: "vertical-lr",
2156
+ transform: "none"
2157
+ },
2158
+ "tbRl": {
2159
+ writingMode: "vertical-rl",
2160
+ transform: "none"
2161
+ }
2162
+ };
2163
+ for (const c of globalXmlParser.elements(elem)) if (c.localName === "textDirection") {
2164
+ const style = directionMap[globalXmlParser.attr(c, "val")] || { writingMode: "horizontal-tb" };
2165
+ cell.cssStyle["writing-mode"] = style.writingMode;
2166
+ cell.cssStyle["transform"] = style.transform;
2167
+ }
2168
+ }
2169
+ parseDefaultProperties(elem, style = null, childStyle = null, handler = null) {
2170
+ style = style || {};
2171
+ for (const c of globalXmlParser.elements(elem)) {
2172
+ if (handler?.(c)) continue;
2173
+ switch (c.localName) {
2174
+ case "jc":
2175
+ style["text-align"] = values.valueOfJc(c);
2176
+ break;
2177
+ case "textAlignment":
2178
+ style["vertical-align"] = values.valueOfTextAlignment(c);
2179
+ break;
2180
+ case "color":
2181
+ style["color"] = xmlUtil.colorAttr(c, "val", null, autos.color);
2182
+ break;
2183
+ case "sz":
2184
+ style["font-size"] = style["min-height"] = globalXmlParser.lengthAttr(c, "val", LengthUsage.FontSize);
2185
+ break;
2186
+ case "shd":
2187
+ style["background-color"] = xmlUtil.colorAttr(c, "fill", null, autos.shd);
2188
+ break;
2189
+ case "highlight":
2190
+ style["background-color"] = xmlUtil.colorAttr(c, "val", null, autos.highlight);
2191
+ break;
2192
+ case "vertAlign": break;
2193
+ case "position":
2194
+ style.verticalAlign = globalXmlParser.lengthAttr(c, "val", LengthUsage.FontSize);
2195
+ break;
2196
+ case "tcW": if (this.options.ignoreWidth) break;
2197
+ case "tblW":
2198
+ style["width"] = values.valueOfSize(c, "w");
2199
+ break;
2200
+ case "trHeight":
2201
+ this.parseTrHeight(c, style);
2202
+ break;
2203
+ case "strike":
2204
+ style["text-decoration"] = globalXmlParser.boolAttr(c, "val", true) ? "line-through" : "none";
2205
+ break;
2206
+ case "b":
2207
+ style["font-weight"] = globalXmlParser.boolAttr(c, "val", true) ? "bold" : "normal";
2208
+ break;
2209
+ case "i":
2210
+ style["font-style"] = globalXmlParser.boolAttr(c, "val", true) ? "italic" : "normal";
2211
+ break;
2212
+ case "caps":
2213
+ style["text-transform"] = globalXmlParser.boolAttr(c, "val", true) ? "uppercase" : "none";
2214
+ break;
2215
+ case "smallCaps":
2216
+ style["font-variant"] = globalXmlParser.boolAttr(c, "val", true) ? "small-caps" : "none";
2217
+ break;
2218
+ case "u":
2219
+ this.parseUnderline(c, style);
2220
+ break;
2221
+ case "ind":
2222
+ case "tblInd":
2223
+ this.parseIndentation(c, style);
2224
+ break;
2225
+ case "rFonts":
2226
+ this.parseFont(c, style);
2227
+ break;
2228
+ case "tblBorders":
2229
+ this.parseBorderProperties(c, childStyle || style);
2230
+ break;
2231
+ case "tblCellSpacing":
2232
+ style["border-spacing"] = values.valueOfMargin(c);
2233
+ style["border-collapse"] = "separate";
2234
+ break;
2235
+ case "pBdr":
2236
+ this.parseBorderProperties(c, style);
2237
+ break;
2238
+ case "bdr":
2239
+ style["border"] = values.valueOfBorder(c);
2240
+ break;
2241
+ case "tcBorders":
2242
+ this.parseBorderProperties(c, style);
2243
+ break;
2244
+ case "vanish":
2245
+ if (globalXmlParser.boolAttr(c, "val", true)) style["display"] = "none";
2246
+ break;
2247
+ case "kern": break;
2248
+ case "noWrap": break;
2249
+ case "tblCellMar":
2250
+ case "tcMar":
2251
+ this.parseMarginProperties(c, childStyle || style);
2252
+ break;
2253
+ case "tblLayout":
2254
+ style["table-layout"] = values.valueOfTblLayout(c);
2255
+ break;
2256
+ case "vAlign":
2257
+ style["vertical-align"] = values.valueOfTextAlignment(c);
2258
+ break;
2259
+ case "spacing":
2260
+ if (elem.localName == "pPr") this.parseSpacing(c, style);
2261
+ break;
2262
+ case "wordWrap":
2263
+ if (globalXmlParser.boolAttr(c, "val")) style["overflow-wrap"] = "break-word";
2264
+ break;
2265
+ case "suppressAutoHyphens":
2266
+ style["hyphens"] = globalXmlParser.boolAttr(c, "val", true) ? "none" : "auto";
2267
+ break;
2268
+ case "lang":
2269
+ style["$lang"] = globalXmlParser.attr(c, "val");
2270
+ break;
2271
+ case "rtl":
2272
+ case "bidi":
2273
+ if (globalXmlParser.boolAttr(c, "val", true)) style["direction"] = "rtl";
2274
+ break;
2275
+ case "bCs":
2276
+ case "iCs":
2277
+ case "szCs":
2278
+ case "tabs":
2279
+ case "outlineLvl":
2280
+ case "contextualSpacing":
2281
+ case "tblStyleColBandSize":
2282
+ case "tblStyleRowBandSize":
2283
+ case "webHidden":
2284
+ case "pageBreakBefore":
2285
+ case "suppressLineNumbers":
2286
+ case "keepLines":
2287
+ case "keepNext":
2288
+ case "widowControl":
2289
+ case "bidi":
2290
+ case "rtl":
2291
+ case "noProof": break;
2292
+ default: if (this.options.debug) console.warn(`DOCX: Unknown document element: ${elem.localName}.${c.localName}`);
2293
+ }
2294
+ }
2295
+ return style;
2296
+ }
2297
+ parseUnderline(node, style) {
2298
+ var val = globalXmlParser.attr(node, "val");
2299
+ if (val == null) return;
2300
+ switch (val) {
2301
+ case "dash":
2302
+ case "dashDotDotHeavy":
2303
+ case "dashDotHeavy":
2304
+ case "dashedHeavy":
2305
+ case "dashLong":
2306
+ case "dashLongHeavy":
2307
+ case "dotDash":
2308
+ case "dotDotDash":
2309
+ style["text-decoration"] = "underline dashed";
2310
+ break;
2311
+ case "dotted":
2312
+ case "dottedHeavy":
2313
+ style["text-decoration"] = "underline dotted";
2314
+ break;
2315
+ case "double":
2316
+ style["text-decoration"] = "underline double";
2317
+ break;
2318
+ case "single":
2319
+ case "thick":
2320
+ style["text-decoration"] = "underline";
2321
+ break;
2322
+ case "wave":
2323
+ case "wavyDouble":
2324
+ case "wavyHeavy":
2325
+ style["text-decoration"] = "underline wavy";
2326
+ break;
2327
+ case "words":
2328
+ style["text-decoration"] = "underline";
2329
+ break;
2330
+ case "none": style["text-decoration"] = "none";
2331
+ }
2332
+ var col = xmlUtil.colorAttr(node, "color");
2333
+ if (col) style["text-decoration-color"] = col;
2334
+ }
2335
+ parseFont(node, style) {
2336
+ var fonts = [
2337
+ globalXmlParser.attr(node, "ascii"),
2338
+ values.themeValue(node, "asciiTheme"),
2339
+ globalXmlParser.attr(node, "eastAsia")
2340
+ ].filter((x) => x).map((x) => encloseFontFamily(x));
2341
+ if (fonts.length > 0) style["font-family"] = [...new Set(fonts)].join(", ");
2342
+ }
2343
+ parseIndentation(node, style) {
2344
+ var firstLine = globalXmlParser.lengthAttr(node, "firstLine");
2345
+ var hanging = globalXmlParser.lengthAttr(node, "hanging");
2346
+ var left = globalXmlParser.lengthAttr(node, "left");
2347
+ var start = globalXmlParser.lengthAttr(node, "start");
2348
+ var right = globalXmlParser.lengthAttr(node, "right");
2349
+ var end = globalXmlParser.lengthAttr(node, "end");
2350
+ if (firstLine) style["text-indent"] = firstLine;
2351
+ if (hanging) style["text-indent"] = `-${hanging}`;
2352
+ if (left || start) style["margin-inline-start"] = left || start;
2353
+ if (right || end) style["margin-inline-end"] = right || end;
2354
+ }
2355
+ parseSpacing(node, style) {
2356
+ var before = globalXmlParser.lengthAttr(node, "before");
2357
+ var after = globalXmlParser.lengthAttr(node, "after");
2358
+ var line = globalXmlParser.intAttr(node, "line", null);
2359
+ var lineRule = globalXmlParser.attr(node, "lineRule");
2360
+ if (before) style["margin-top"] = before;
2361
+ if (after) style["margin-bottom"] = after;
2362
+ if (line !== null) switch (lineRule) {
2363
+ case "auto":
2364
+ style["line-height"] = `${(line / 240).toFixed(2)}`;
2365
+ break;
2366
+ case "atLeast":
2367
+ style["line-height"] = `calc(100% + ${line / 20}pt)`;
2368
+ break;
2369
+ default: style["line-height"] = style["min-height"] = `${line / 20}pt`;
2370
+ }
2371
+ }
2372
+ parseMarginProperties(node, output) {
2373
+ for (const c of globalXmlParser.elements(node)) switch (c.localName) {
2374
+ case "left":
2375
+ output["padding-left"] = values.valueOfMargin(c);
2376
+ break;
2377
+ case "right":
2378
+ output["padding-right"] = values.valueOfMargin(c);
2379
+ break;
2380
+ case "top":
2381
+ output["padding-top"] = values.valueOfMargin(c);
2382
+ break;
2383
+ case "bottom": output["padding-bottom"] = values.valueOfMargin(c);
2384
+ }
2385
+ }
2386
+ parseTrHeight(node, output) {
2387
+ switch (globalXmlParser.attr(node, "hRule")) {
2388
+ case "exact":
2389
+ output["height"] = globalXmlParser.lengthAttr(node, "val");
2390
+ break;
2391
+ default: output["height"] = globalXmlParser.lengthAttr(node, "val");
2392
+ }
2393
+ }
2394
+ parseBorderProperties(node, output) {
2395
+ for (const c of globalXmlParser.elements(node)) switch (c.localName) {
2396
+ case "start":
2397
+ case "left":
2398
+ output["border-left"] = values.valueOfBorder(c);
2399
+ break;
2400
+ case "end":
2401
+ case "right":
2402
+ output["border-right"] = values.valueOfBorder(c);
2403
+ break;
2404
+ case "top":
2405
+ output["border-top"] = values.valueOfBorder(c);
2406
+ break;
2407
+ case "bottom": output["border-bottom"] = values.valueOfBorder(c);
2408
+ }
2409
+ }
2410
+ };
2411
+ var knownColors = [
2412
+ "black",
2413
+ "blue",
2414
+ "cyan",
2415
+ "darkBlue",
2416
+ "darkCyan",
2417
+ "darkGray",
2418
+ "darkGreen",
2419
+ "darkMagenta",
2420
+ "darkRed",
2421
+ "darkYellow",
2422
+ "green",
2423
+ "lightGray",
2424
+ "magenta",
2425
+ "none",
2426
+ "red",
2427
+ "white",
2428
+ "yellow"
2429
+ ];
2430
+ var xmlUtil = class {
2431
+ static colorAttr(node, attrName, defValue = null, autoColor = "black") {
2432
+ var v = globalXmlParser.attr(node, attrName);
2433
+ if (v) {
2434
+ if (v == "auto") return autoColor;
2435
+ else if (knownColors.includes(v)) return v;
2436
+ return `#${v}`;
2437
+ }
2438
+ var themeColor = globalXmlParser.attr(node, "themeColor");
2439
+ return themeColor ? `var(--docx-${themeColor}-color)` : defValue;
2440
+ }
2441
+ };
2442
+ var values = class values {
2443
+ static themeValue(c, attr) {
2444
+ var val = globalXmlParser.attr(c, attr);
2445
+ return val ? `var(--docx-${val}-font)` : null;
2446
+ }
2447
+ static valueOfSize(c, attr) {
2448
+ var type = LengthUsage.Dxa;
2449
+ switch (globalXmlParser.attr(c, "type")) {
2450
+ case "dxa": break;
2451
+ case "pct":
2452
+ type = LengthUsage.Percent;
2453
+ break;
2454
+ case "auto": return "auto";
2455
+ }
2456
+ return globalXmlParser.lengthAttr(c, attr, type);
2457
+ }
2458
+ static valueOfMargin(c) {
2459
+ return globalXmlParser.lengthAttr(c, "w");
2460
+ }
2461
+ static valueOfBorder(c) {
2462
+ var type = values.parseBorderType(globalXmlParser.attr(c, "val"));
2463
+ if (type == "none") return "none";
2464
+ var color = xmlUtil.colorAttr(c, "color");
2465
+ return `${globalXmlParser.lengthAttr(c, "sz", LengthUsage.Border)} ${type} ${color == "auto" ? autos.borderColor : color}`;
2466
+ }
2467
+ static parseBorderType(type) {
2468
+ switch (type) {
2469
+ case "single": return "solid";
2470
+ case "dashDotStroked": return "solid";
2471
+ case "dashed": return "dashed";
2472
+ case "dashSmallGap": return "dashed";
2473
+ case "dotDash": return "dotted";
2474
+ case "dotDotDash": return "dotted";
2475
+ case "dotted": return "dotted";
2476
+ case "double": return "double";
2477
+ case "doubleWave": return "double";
2478
+ case "inset": return "inset";
2479
+ case "nil": return "none";
2480
+ case "none": return "none";
2481
+ case "outset": return "outset";
2482
+ case "thick": return "solid";
2483
+ case "thickThinLargeGap": return "solid";
2484
+ case "thickThinMediumGap": return "solid";
2485
+ case "thickThinSmallGap": return "solid";
2486
+ case "thinThickLargeGap": return "solid";
2487
+ case "thinThickMediumGap": return "solid";
2488
+ case "thinThickSmallGap": return "solid";
2489
+ case "thinThickThinLargeGap": return "solid";
2490
+ case "thinThickThinMediumGap": return "solid";
2491
+ case "thinThickThinSmallGap": return "solid";
2492
+ case "threeDEmboss": return "solid";
2493
+ case "threeDEngrave": return "solid";
2494
+ case "triple": return "double";
2495
+ case "wave": return "solid";
2496
+ }
2497
+ return "solid";
2498
+ }
2499
+ static valueOfTblLayout(c) {
2500
+ return globalXmlParser.attr(c, "val") == "fixed" ? "fixed" : "auto";
2501
+ }
2502
+ static classNameOfCnfStyle(c) {
2503
+ const val = globalXmlParser.attr(c, "val");
2504
+ return [
2505
+ "first-row",
2506
+ "last-row",
2507
+ "first-col",
2508
+ "last-col",
2509
+ "odd-col",
2510
+ "even-col",
2511
+ "odd-row",
2512
+ "even-row",
2513
+ "ne-cell",
2514
+ "nw-cell",
2515
+ "se-cell",
2516
+ "sw-cell"
2517
+ ].filter((_, i) => val[i] == "1").join(" ");
2518
+ }
2519
+ static valueOfJc(c) {
2520
+ var type = globalXmlParser.attr(c, "val");
2521
+ switch (type) {
2522
+ case "start":
2523
+ case "left": return "left";
2524
+ case "center": return "center";
2525
+ case "end":
2526
+ case "right": return "right";
2527
+ case "both": return "justify";
2528
+ }
2529
+ return type;
2530
+ }
2531
+ static valueOfVertAlign(c, asTagName = false) {
2532
+ var type = globalXmlParser.attr(c, "val");
2533
+ switch (type) {
2534
+ case "subscript": return "sub";
2535
+ case "superscript": return asTagName ? "sup" : "super";
2536
+ }
2537
+ return asTagName ? null : type;
2538
+ }
2539
+ static valueOfTextAlignment(c) {
2540
+ var type = globalXmlParser.attr(c, "val");
2541
+ switch (type) {
2542
+ case "auto":
2543
+ case "baseline": return "baseline";
2544
+ case "top": return "top";
2545
+ case "center": return "middle";
2546
+ case "bottom": return "bottom";
2547
+ }
2548
+ return type;
2549
+ }
2550
+ static addSize(a, b) {
2551
+ if (a == null) return b;
2552
+ if (b == null) return a;
2553
+ return `calc(${a} + ${b})`;
2554
+ }
2555
+ static classNameOftblLook(c) {
2556
+ const val = globalXmlParser.hexAttr(c, "val", 0);
2557
+ let className = "";
2558
+ if (globalXmlParser.boolAttr(c, "firstRow") || val & 32) className += " first-row";
2559
+ if (globalXmlParser.boolAttr(c, "lastRow") || val & 64) className += " last-row";
2560
+ if (globalXmlParser.boolAttr(c, "firstColumn") || val & 128) className += " first-col";
2561
+ if (globalXmlParser.boolAttr(c, "lastColumn") || val & 256) className += " last-col";
2562
+ if (globalXmlParser.boolAttr(c, "noHBand") || val & 512) className += " no-hband";
2563
+ if (globalXmlParser.boolAttr(c, "noVBand") || val & 1024) className += " no-vband";
2564
+ return className.trim();
2565
+ }
2566
+ };
2567
+ var defaultTab = {
2568
+ pos: 0,
2569
+ leader: "none",
2570
+ style: "left"
2571
+ };
2572
+ var maxTabs = 50;
2573
+ function computePixelToPoint(container = document.body) {
2574
+ const temp = document.createElement("div");
2575
+ temp.style.width = "100pt";
2576
+ container.appendChild(temp);
2577
+ const result = 100 / temp.offsetWidth;
2578
+ container.removeChild(temp);
2579
+ return result;
2580
+ }
2581
+ function updateTabStop(elem, tabs, defaultTabSize, pixelToPoint = 72 / 96) {
2582
+ const p = elem.closest("p");
2583
+ const ebb = elem.getBoundingClientRect();
2584
+ const pbb = p.getBoundingClientRect();
2585
+ const pcs = getComputedStyle(p);
2586
+ const tabStops = tabs?.length > 0 ? tabs.map((t) => ({
2587
+ pos: lengthToPoint(t.position),
2588
+ leader: t.leader,
2589
+ style: t.style
2590
+ })).sort((a, b) => a.pos - b.pos) : [defaultTab];
2591
+ const lastTab = tabStops[tabStops.length - 1];
2592
+ const pWidthPt = pbb.width * pixelToPoint;
2593
+ const size = lengthToPoint(defaultTabSize);
2594
+ let pos = lastTab.pos + size;
2595
+ if (pos < pWidthPt) for (; pos < pWidthPt && tabStops.length < maxTabs; pos += size) tabStops.push({
2596
+ ...defaultTab,
2597
+ pos
2598
+ });
2599
+ const marginLeft = parseFloat(pcs.marginLeft);
2600
+ const pOffset = pbb.left + marginLeft;
2601
+ const left = (ebb.left - pOffset) * pixelToPoint;
2602
+ const tab = tabStops.find((t) => t.style != "clear" && t.pos > left);
2603
+ if (tab == null) return;
2604
+ let width = 1;
2605
+ if (tab.style == "right" || tab.style == "center") {
2606
+ const tabStops = Array.from(p.querySelectorAll(`.${elem.className}`));
2607
+ const nextIdx = tabStops.indexOf(elem) + 1;
2608
+ const range = document.createRange();
2609
+ range.setStart(elem, 1);
2610
+ if (nextIdx < tabStops.length) range.setEndBefore(tabStops[nextIdx]);
2611
+ else range.setEndAfter(p);
2612
+ const mul = tab.style == "center" ? .5 : 1;
2613
+ const nextBB = range.getBoundingClientRect();
2614
+ const offset = nextBB.left + mul * nextBB.width - (pbb.left - marginLeft);
2615
+ width = tab.pos - offset * pixelToPoint;
2616
+ } else width = tab.pos - left;
2617
+ elem.innerHTML = "&nbsp;";
2618
+ elem.style.textDecoration = "inherit";
2619
+ elem.style.wordSpacing = `${width.toFixed(0)}pt`;
2620
+ switch (tab.leader) {
2621
+ case "dot":
2622
+ case "middleDot":
2623
+ elem.style.textDecoration = "underline";
2624
+ elem.style.textDecorationStyle = "dotted";
2625
+ break;
2626
+ case "hyphen":
2627
+ case "heavy":
2628
+ case "underscore": elem.style.textDecoration = "underline";
2629
+ }
2630
+ }
2631
+ function lengthToPoint(length) {
2632
+ return parseFloat(length);
2633
+ }
2634
+ var ns = {
2635
+ svg: "http://www.w3.org/2000/svg",
2636
+ mathML: "http://www.w3.org/1998/Math/MathML"
2637
+ };
2638
+ var HtmlRenderer = class {
2639
+ constructor(htmlDocument) {
2640
+ this.htmlDocument = htmlDocument;
2641
+ this.className = "docx";
2642
+ this.styleMap = {};
2643
+ this.currentPart = null;
2644
+ this.tableVerticalMerges = [];
2645
+ this.currentVerticalMerge = null;
2646
+ this.tableCellPositions = [];
2647
+ this.currentCellPosition = null;
2648
+ this.footnoteMap = {};
2649
+ this.endnoteMap = {};
2650
+ this.currentEndnoteIds = [];
2651
+ this.usedHederFooterParts = [];
2652
+ this.currentTabs = [];
2653
+ this.commentMap = {};
2654
+ this.tasks = [];
2655
+ this.postRenderTasks = [];
2656
+ }
2657
+ async render(document, bodyContainer, styleContainer = null, options) {
2658
+ this.document = document;
2659
+ this.options = options;
2660
+ this.className = options.className;
2661
+ this.rootSelector = options.inWrapper ? `.${this.className}-wrapper` : ":root";
2662
+ this.styleMap = null;
2663
+ this.tasks = [];
2664
+ if (this.options.renderComments && globalThis.Highlight) this.commentHighlight = new Highlight();
2665
+ styleContainer = styleContainer || bodyContainer;
2666
+ removeAllElements(styleContainer);
2667
+ removeAllElements(bodyContainer);
2668
+ styleContainer.appendChild(this.createComment("docxjs library predefined styles"));
2669
+ styleContainer.appendChild(this.renderDefaultStyle());
2670
+ if (document.themePart) {
2671
+ styleContainer.appendChild(this.createComment("docxjs document theme values"));
2672
+ this.renderTheme(document.themePart, styleContainer);
2673
+ }
2674
+ if (document.stylesPart != null) {
2675
+ this.styleMap = this.processStyles(document.stylesPart.styles);
2676
+ styleContainer.appendChild(this.createComment("docxjs document styles"));
2677
+ styleContainer.appendChild(this.renderStyles(document.stylesPart.styles));
2678
+ }
2679
+ if (document.numberingPart) {
2680
+ this.prodessNumberings(document.numberingPart.domNumberings);
2681
+ styleContainer.appendChild(this.createComment("docxjs document numbering styles"));
2682
+ styleContainer.appendChild(this.renderNumbering(document.numberingPart.domNumberings, styleContainer));
2683
+ }
2684
+ if (document.footnotesPart) this.footnoteMap = keyBy(document.footnotesPart.notes, (x) => x.id);
2685
+ if (document.endnotesPart) this.endnoteMap = keyBy(document.endnotesPart.notes, (x) => x.id);
2686
+ if (document.settingsPart) this.defaultTabSize = document.settingsPart.settings?.defaultTabStop;
2687
+ if (!options.ignoreFonts && document.fontTablePart) this.renderFontTable(document.fontTablePart, styleContainer);
2688
+ var sectionElements = this.renderSections(document.documentPart.body);
2689
+ if (this.options.inWrapper) bodyContainer.appendChild(this.renderWrapper(sectionElements));
2690
+ else appendChildren(bodyContainer, sectionElements);
2691
+ if (this.commentHighlight && options.renderComments) CSS.highlights.set(`${this.className}-comments`, this.commentHighlight);
2692
+ this.postRenderTasks.forEach((t) => t());
2693
+ await Promise.allSettled(this.tasks);
2694
+ this.refreshTabStops();
2695
+ }
2696
+ renderTheme(themePart, styleContainer) {
2697
+ const variables = {};
2698
+ const fontScheme = themePart.theme?.fontScheme;
2699
+ if (fontScheme) {
2700
+ if (fontScheme.majorFont) variables["--docx-majorHAnsi-font"] = fontScheme.majorFont.latinTypeface;
2701
+ if (fontScheme.minorFont) variables["--docx-minorHAnsi-font"] = fontScheme.minorFont.latinTypeface;
2702
+ }
2703
+ const colorScheme = themePart.theme?.colorScheme;
2704
+ if (colorScheme) for (let [k, v] of Object.entries(colorScheme.colors)) variables[`--docx-${k}-color`] = `#${v}`;
2705
+ const cssText = this.styleToString(`.${this.className}`, variables);
2706
+ styleContainer.appendChild(this.createStyleElement(cssText));
2707
+ }
2708
+ renderFontTable(fontsPart, styleContainer) {
2709
+ for (let f of fontsPart.fonts) for (let ref of f.embedFontRefs) this.tasks.push(this.document.loadFont(ref.id, ref.key).then((fontData) => {
2710
+ const cssValues = {
2711
+ "font-family": encloseFontFamily(f.name),
2712
+ "src": `url(${fontData})`
2713
+ };
2714
+ if (ref.type == "bold" || ref.type == "boldItalic") cssValues["font-weight"] = "bold";
2715
+ if (ref.type == "italic" || ref.type == "boldItalic") cssValues["font-style"] = "italic";
2716
+ const cssText = this.styleToString("@font-face", cssValues);
2717
+ styleContainer.appendChild(this.createComment(`docxjs ${f.name} font`));
2718
+ styleContainer.appendChild(this.createStyleElement(cssText));
2719
+ }));
2720
+ }
2721
+ processStyleName(className) {
2722
+ return className ? `${this.className}_${escapeClassName(className)}` : this.className;
2723
+ }
2724
+ processStyles(styles) {
2725
+ const stylesMap = keyBy(styles.filter((x) => x.id != null), (x) => x.id);
2726
+ for (const style of styles.filter((x) => x.basedOn)) {
2727
+ var baseStyle = stylesMap[style.basedOn];
2728
+ if (baseStyle) {
2729
+ style.paragraphProps = mergeDeep(style.paragraphProps, baseStyle.paragraphProps);
2730
+ style.runProps = mergeDeep(style.runProps, baseStyle.runProps);
2731
+ for (const baseValues of baseStyle.styles) {
2732
+ const styleValues = style.styles.find((x) => x.target == baseValues.target);
2733
+ if (styleValues) this.copyStyleProperties(baseValues.values, styleValues.values);
2734
+ else style.styles.push({
2735
+ ...baseValues,
2736
+ values: { ...baseValues.values }
2737
+ });
2738
+ }
2739
+ } else if (this.options.debug) console.warn(`Can't find base style ${style.basedOn}`);
2740
+ }
2741
+ for (let style of styles) style.cssName = this.processStyleName(style.id);
2742
+ return stylesMap;
2743
+ }
2744
+ prodessNumberings(numberings) {
2745
+ for (let num of numberings.filter((n) => n.pStyleName)) {
2746
+ const style = this.findStyle(num.pStyleName);
2747
+ if (style?.paragraphProps?.numbering) style.paragraphProps.numbering.level = num.level;
2748
+ }
2749
+ }
2750
+ processElement(element) {
2751
+ if (element.children) for (var e of element.children) {
2752
+ e.parent = element;
2753
+ if (e.type == DomType.Table) this.processTable(e);
2754
+ else this.processElement(e);
2755
+ }
2756
+ }
2757
+ processTable(table) {
2758
+ for (var r of table.children) for (var c of r.children) {
2759
+ c.cssStyle = this.copyStyleProperties(table.cellStyle, c.cssStyle, [
2760
+ "border-left",
2761
+ "border-right",
2762
+ "border-top",
2763
+ "border-bottom",
2764
+ "padding-left",
2765
+ "padding-right",
2766
+ "padding-top",
2767
+ "padding-bottom"
2768
+ ]);
2769
+ this.processElement(c);
2770
+ }
2771
+ }
2772
+ copyStyleProperties(input, output, attrs = null) {
2773
+ if (!input) return output;
2774
+ if (output == null) output = {};
2775
+ if (attrs == null) attrs = Object.getOwnPropertyNames(input);
2776
+ for (var key of attrs) if (input.hasOwnProperty(key) && !output.hasOwnProperty(key)) output[key] = input[key];
2777
+ return output;
2778
+ }
2779
+ createPageElement(className, props) {
2780
+ var elem = this.createElement("section", { className });
2781
+ if (props) {
2782
+ if (props.pageMargins) {
2783
+ elem.style.paddingLeft = props.pageMargins.left;
2784
+ elem.style.paddingRight = props.pageMargins.right;
2785
+ elem.style.paddingTop = props.pageMargins.top;
2786
+ elem.style.paddingBottom = props.pageMargins.bottom;
2787
+ }
2788
+ if (props.pageSize) {
2789
+ if (!this.options.ignoreWidth) elem.style.width = props.pageSize.width;
2790
+ if (!this.options.ignoreHeight) elem.style.minHeight = props.pageSize.height;
2791
+ }
2792
+ }
2793
+ return elem;
2794
+ }
2795
+ createSectionContent(props) {
2796
+ var elem = this.createElement("article");
2797
+ if (props.columns && props.columns.numberOfColumns) {
2798
+ elem.style.columnCount = `${props.columns.numberOfColumns}`;
2799
+ elem.style.columnGap = props.columns.space;
2800
+ if (props.columns.separator) elem.style.columnRule = "1px solid black";
2801
+ }
2802
+ return elem;
2803
+ }
2804
+ renderSections(document) {
2805
+ const result = [];
2806
+ this.processElement(document);
2807
+ const sections = this.splitBySection(document.children, document.props);
2808
+ const pages = this.groupByPageBreaks(sections);
2809
+ let prevProps = null;
2810
+ for (let i = 0, l = pages.length; i < l; i++) {
2811
+ this.currentFootnoteIds = [];
2812
+ let props = pages[i][0].sectProps;
2813
+ const pageElement = this.createPageElement(this.className, props);
2814
+ this.renderStyleValues(document.cssStyle, pageElement);
2815
+ this.options.renderHeaders && this.renderHeaderFooter(props.headerRefs, props, result.length, prevProps != props, pageElement);
2816
+ for (const sect of pages[i]) {
2817
+ var contentElement = this.createSectionContent(sect.sectProps);
2818
+ this.renderElements(sect.elements, contentElement);
2819
+ pageElement.appendChild(contentElement);
2820
+ props = sect.sectProps;
2821
+ }
2822
+ if (this.options.renderFootnotes) this.renderNotes(this.currentFootnoteIds, this.footnoteMap, pageElement);
2823
+ if (this.options.renderEndnotes && i == l - 1) this.renderNotes(this.currentEndnoteIds, this.endnoteMap, pageElement);
2824
+ this.options.renderFooters && this.renderHeaderFooter(props.footerRefs, props, result.length, prevProps != props, pageElement);
2825
+ result.push(pageElement);
2826
+ prevProps = props;
2827
+ }
2828
+ return result;
2829
+ }
2830
+ renderHeaderFooter(refs, props, page, firstOfSection, into) {
2831
+ if (!refs) return;
2832
+ var ref = (props.titlePage && firstOfSection ? refs.find((x) => x.type == "first") : null) ?? (page % 2 == 1 ? refs.find((x) => x.type == "even") : null) ?? refs.find((x) => x.type == "default");
2833
+ var part = ref && this.document.findPartByRelId(ref.id, this.document.documentPart);
2834
+ if (part) {
2835
+ this.currentPart = part;
2836
+ if (!this.usedHederFooterParts.includes(part.path)) {
2837
+ this.processElement(part.rootElement);
2838
+ this.usedHederFooterParts.push(part.path);
2839
+ }
2840
+ const [el] = this.renderElements([part.rootElement], into);
2841
+ if (props?.pageMargins) {
2842
+ if (part.rootElement.type === DomType.Header) {
2843
+ el.style.marginTop = `calc(${props.pageMargins.header} - ${props.pageMargins.top})`;
2844
+ el.style.minHeight = `calc(${props.pageMargins.top} - ${props.pageMargins.header})`;
2845
+ } else if (part.rootElement.type === DomType.Footer) {
2846
+ el.style.marginBottom = `calc(${props.pageMargins.footer} - ${props.pageMargins.bottom})`;
2847
+ el.style.minHeight = `calc(${props.pageMargins.bottom} - ${props.pageMargins.footer})`;
2848
+ }
2849
+ }
2850
+ this.currentPart = null;
2851
+ }
2852
+ }
2853
+ isPageBreakElement(elem) {
2854
+ if (elem.type != DomType.Break) return false;
2855
+ if (elem.break == "lastRenderedPageBreak") return !this.options.ignoreLastRenderedPageBreak;
2856
+ return elem.break == "page";
2857
+ }
2858
+ isPageBreakSection(prev, next) {
2859
+ if (!prev) return false;
2860
+ if (!next) return false;
2861
+ return prev.pageSize?.orientation != next.pageSize?.orientation || prev.pageSize?.width != next.pageSize?.width || prev.pageSize?.height != next.pageSize?.height;
2862
+ }
2863
+ splitBySection(elements, defaultProps) {
2864
+ var current = {
2865
+ sectProps: null,
2866
+ elements: [],
2867
+ pageBreak: false
2868
+ };
2869
+ var result = [current];
2870
+ for (let elem of elements) {
2871
+ if (elem.type == DomType.Paragraph) {
2872
+ if (this.findStyle(elem.styleName)?.paragraphProps?.pageBreakBefore) {
2873
+ current.sectProps = sectProps;
2874
+ current.pageBreak = true;
2875
+ current = {
2876
+ sectProps: null,
2877
+ elements: [],
2878
+ pageBreak: false
2879
+ };
2880
+ result.push(current);
2881
+ }
2882
+ }
2883
+ current.elements.push(elem);
2884
+ if (elem.type == DomType.Paragraph) {
2885
+ const p = elem;
2886
+ var sectProps = p.sectionProps;
2887
+ var pBreakIndex = -1;
2888
+ var rBreakIndex = -1;
2889
+ if (this.options.breakPages && p.children) pBreakIndex = p.children.findIndex((r) => {
2890
+ rBreakIndex = r.children?.findIndex(this.isPageBreakElement.bind(this)) ?? -1;
2891
+ return rBreakIndex != -1;
2892
+ });
2893
+ if (sectProps || pBreakIndex != -1) {
2894
+ current.sectProps = sectProps;
2895
+ current.pageBreak = pBreakIndex != -1;
2896
+ current = {
2897
+ sectProps: null,
2898
+ elements: [],
2899
+ pageBreak: false
2900
+ };
2901
+ result.push(current);
2902
+ }
2903
+ if (pBreakIndex != -1) {
2904
+ let breakRun = p.children[pBreakIndex];
2905
+ let splitRun = rBreakIndex < breakRun.children.length - 1;
2906
+ if (pBreakIndex < p.children.length - 1 || splitRun) {
2907
+ var children = elem.children;
2908
+ var newParagraph = {
2909
+ ...elem,
2910
+ children: children.slice(pBreakIndex)
2911
+ };
2912
+ elem.children = children.slice(0, pBreakIndex);
2913
+ current.elements.push(newParagraph);
2914
+ if (splitRun) {
2915
+ let runChildren = breakRun.children;
2916
+ let newRun = {
2917
+ ...breakRun,
2918
+ children: runChildren.slice(0, rBreakIndex)
2919
+ };
2920
+ elem.children.push(newRun);
2921
+ breakRun.children = runChildren.slice(rBreakIndex);
2922
+ }
2923
+ }
2924
+ }
2925
+ }
2926
+ }
2927
+ let currentSectProps = null;
2928
+ for (let i = result.length - 1; i >= 0; i--) if (result[i].sectProps == null) result[i].sectProps = currentSectProps ?? defaultProps;
2929
+ else currentSectProps = result[i].sectProps;
2930
+ return result;
2931
+ }
2932
+ groupByPageBreaks(sections) {
2933
+ let current = [];
2934
+ let prev;
2935
+ const result = [current];
2936
+ for (let s of sections) {
2937
+ current.push(s);
2938
+ if (this.options.ignoreLastRenderedPageBreak || s.pageBreak || this.isPageBreakSection(prev, s.sectProps)) result.push(current = []);
2939
+ prev = s.sectProps;
2940
+ }
2941
+ return result.filter((x) => x.length > 0);
2942
+ }
2943
+ renderWrapper(children) {
2944
+ return this.createElement("div", { className: `${this.className}-wrapper` }, children);
2945
+ }
2946
+ renderDefaultStyle() {
2947
+ var c = this.className;
2948
+ var wrapperStyle = `
2949
+ .${c}-wrapper { background: gray; padding: 30px; padding-bottom: 0px; display: flex; flex-flow: column; align-items: center; }
2950
+ .${c}-wrapper>section.${c} { background: white; box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); margin-bottom: 30px; }`;
2951
+ if (this.options.hideWrapperOnPrint) wrapperStyle = `@media not print { ${wrapperStyle} }`;
2952
+ var styleText = `${wrapperStyle}
2953
+ .${c} { color: black; hyphens: auto; text-underline-position: from-font; }
2954
+ section.${c} { box-sizing: border-box; display: flex; flex-flow: column nowrap; position: relative; overflow: hidden; }
2955
+ section.${c}>article { margin-bottom: auto; z-index: 1; }
2956
+ section.${c}>footer { z-index: 1; }
2957
+ .${c} table { border-collapse: collapse; }
2958
+ .${c} table td, .${c} table th { vertical-align: top; }
2959
+ .${c} p { margin: 0pt; min-height: 1em; }
2960
+ .${c} span { white-space: pre-wrap; overflow-wrap: break-word; }
2961
+ .${c} a { color: inherit; text-decoration: inherit; }
2962
+ .${c} svg { fill: transparent; }
2963
+ `;
2964
+ if (this.options.renderComments) styleText += `
2965
+ .${c}-comment-ref { cursor: default; }
2966
+ .${c}-comment-popover { display: none; z-index: 1000; padding: 0.5rem; background: white; position: absolute; box-shadow: 0 0 0.25rem rgba(0, 0, 0, 0.25); width: 30ch; }
2967
+ .${c}-comment-ref:hover~.${c}-comment-popover { display: block; }
2968
+ .${c}-comment-author,.${c}-comment-date { font-size: 0.875rem; color: #888; }
2969
+ `;
2970
+ return this.createStyleElement(styleText);
2971
+ }
2972
+ renderNumbering(numberings, styleContainer) {
2973
+ var styleText = "";
2974
+ var resetCounters = [];
2975
+ for (var num of numberings) {
2976
+ var selector = `p.${this.numberingClass(num.id, num.level)}`;
2977
+ var listStyleType = "none";
2978
+ if (num.bullet) {
2979
+ let valiable = `--${this.className}-${num.bullet.src}`.toLowerCase();
2980
+ styleText += this.styleToString(`${selector}:before`, {
2981
+ "content": "' '",
2982
+ "display": "inline-block",
2983
+ "background": `var(${valiable})`
2984
+ }, num.bullet.style);
2985
+ this.tasks.push(this.document.loadNumberingImage(num.bullet.src).then((data) => {
2986
+ var text = `${this.rootSelector} { ${valiable}: url(${data}) }`;
2987
+ styleContainer.appendChild(this.createStyleElement(text));
2988
+ }));
2989
+ } else if (num.levelText) {
2990
+ let counter = this.numberingCounter(num.id, num.level);
2991
+ const counterReset = counter + " " + (num.start - 1);
2992
+ if (num.level > 0) styleText += this.styleToString(`p.${this.numberingClass(num.id, num.level - 1)}`, { "counter-set": counterReset });
2993
+ resetCounters.push(counterReset);
2994
+ let levelText = num.levelText;
2995
+ let runStyle = num.rStyle;
2996
+ if (this.options.normalizeSymbolBullets && num.format === "bullet") {
2997
+ const font = (runStyle?.["font-family"] ?? "").split(",")[0].trim().replace(/^['"]|['"]$/g, "").toLowerCase();
2998
+ const symbols = font === "symbol" ? { "": "•" } : font === "wingdings" ? {
2999
+ "": "▪",
3000
+ "": "➢",
3001
+ "": "✓"
3002
+ } : null;
3003
+ const replacement = symbols && Object.hasOwn(symbols, levelText) ? symbols[levelText] : null;
3004
+ if (replacement) {
3005
+ levelText = replacement;
3006
+ runStyle = { ...runStyle };
3007
+ delete runStyle["font-family"];
3008
+ }
3009
+ }
3010
+ styleText += this.styleToString(`${selector}:before`, {
3011
+ "content": this.levelTextToContent(levelText, num.suff, num.id, this.numFormatToCssValue(num.format)),
3012
+ "counter-increment": counter,
3013
+ ...runStyle
3014
+ });
3015
+ } else listStyleType = this.numFormatToCssValue(num.format);
3016
+ styleText += this.styleToString(selector, {
3017
+ "display": "list-item",
3018
+ "list-style-position": "inside",
3019
+ "list-style-type": listStyleType,
3020
+ ...num.pStyle
3021
+ });
3022
+ }
3023
+ if (resetCounters.length > 0) styleText += this.styleToString(this.rootSelector, { "counter-reset": resetCounters.join(" ") });
3024
+ return this.createStyleElement(styleText);
3025
+ }
3026
+ renderStyles(styles) {
3027
+ var styleText = "";
3028
+ const stylesMap = this.styleMap;
3029
+ const defautStyles = keyBy(styles.filter((s) => s.isDefault), (s) => s.target);
3030
+ for (const style of styles) {
3031
+ var subStyles = style.styles;
3032
+ if (style.linked) {
3033
+ var linkedStyle = style.linked && stylesMap[style.linked];
3034
+ if (linkedStyle) subStyles = subStyles.concat(linkedStyle.styles);
3035
+ else if (this.options.debug) console.warn(`Can't find linked style ${style.linked}`);
3036
+ }
3037
+ for (const subStyle of subStyles) {
3038
+ var selector = `${style.target ?? ""}.${style.cssName}`;
3039
+ if (style.target != subStyle.target) selector += ` ${subStyle.target}`;
3040
+ if (defautStyles[style.target] == style) selector = `.${this.className} ${style.target}, ` + selector;
3041
+ styleText += this.styleToString(selector, subStyle.values);
3042
+ }
3043
+ }
3044
+ return this.createStyleElement(styleText);
3045
+ }
3046
+ renderNotes(noteIds, notesMap, into) {
3047
+ var notes = noteIds.map((id) => notesMap[id]).filter((x) => x);
3048
+ if (notes.length > 0) {
3049
+ var result = this.createElement("ol", null, this.renderElements(notes));
3050
+ into.appendChild(result);
3051
+ }
3052
+ }
3053
+ renderElement(elem) {
3054
+ switch (elem.type) {
3055
+ case DomType.Paragraph: return this.renderParagraph(elem);
3056
+ case DomType.BookmarkStart: return this.renderBookmarkStart(elem);
3057
+ case DomType.BookmarkEnd: return null;
3058
+ case DomType.Run: return this.renderRun(elem);
3059
+ case DomType.Table: return this.renderTable(elem);
3060
+ case DomType.Row: return this.renderTableRow(elem);
3061
+ case DomType.Cell: return this.renderTableCell(elem);
3062
+ case DomType.Hyperlink: return this.renderHyperlink(elem);
3063
+ case DomType.SmartTag: return this.renderSmartTag(elem);
3064
+ case DomType.Drawing: return this.renderDrawing(elem);
3065
+ case DomType.Image: return this.renderImage(elem);
3066
+ case DomType.Text: return this.renderText(elem);
3067
+ case DomType.Text: return this.renderText(elem);
3068
+ case DomType.DeletedText: return this.renderDeletedText(elem);
3069
+ case DomType.Tab: return this.renderTab(elem);
3070
+ case DomType.Symbol: return this.renderSymbol(elem);
3071
+ case DomType.Break: return this.renderBreak(elem);
3072
+ case DomType.Footer: return this.renderContainer(elem, "footer");
3073
+ case DomType.Header: return this.renderContainer(elem, "header");
3074
+ case DomType.Footnote:
3075
+ case DomType.Endnote: return this.renderContainer(elem, "li");
3076
+ case DomType.FootnoteReference: return this.renderFootnoteReference(elem);
3077
+ case DomType.EndnoteReference: return this.renderEndnoteReference(elem);
3078
+ case DomType.NoBreakHyphen: return this.createElement("wbr");
3079
+ case DomType.VmlPicture: return this.renderVmlPicture(elem);
3080
+ case DomType.VmlElement: return this.renderVmlElement(elem);
3081
+ case DomType.MmlMath: return this.renderContainerNS(elem, ns.mathML, "math", { xmlns: ns.mathML });
3082
+ case DomType.MmlMathParagraph: return this.renderContainer(elem, "span");
3083
+ case DomType.MmlFraction: return this.renderContainerNS(elem, ns.mathML, "mfrac");
3084
+ case DomType.MmlBase: return this.renderContainerNS(elem, ns.mathML, elem.parent.type == DomType.MmlMatrixRow ? "mtd" : "mrow");
3085
+ case DomType.MmlNumerator:
3086
+ case DomType.MmlDenominator:
3087
+ case DomType.MmlFunction:
3088
+ case DomType.MmlLimit:
3089
+ case DomType.MmlBox: return this.renderContainerNS(elem, ns.mathML, "mrow");
3090
+ case DomType.MmlGroupChar: return this.renderMmlGroupChar(elem);
3091
+ case DomType.MmlLimitLower: return this.renderContainerNS(elem, ns.mathML, "munder");
3092
+ case DomType.MmlMatrix: return this.renderContainerNS(elem, ns.mathML, "mtable");
3093
+ case DomType.MmlMatrixRow: return this.renderContainerNS(elem, ns.mathML, "mtr");
3094
+ case DomType.MmlRadical: return this.renderMmlRadical(elem);
3095
+ case DomType.MmlSuperscript: return this.renderContainerNS(elem, ns.mathML, "msup");
3096
+ case DomType.MmlSubscript: return this.renderContainerNS(elem, ns.mathML, "msub");
3097
+ case DomType.MmlDegree:
3098
+ case DomType.MmlSuperArgument:
3099
+ case DomType.MmlSubArgument: return this.renderContainerNS(elem, ns.mathML, "mn");
3100
+ case DomType.MmlFunctionName: return this.renderContainerNS(elem, ns.mathML, "ms");
3101
+ case DomType.MmlDelimiter: return this.renderMmlDelimiter(elem);
3102
+ case DomType.MmlRun: return this.renderMmlRun(elem);
3103
+ case DomType.MmlNary: return this.renderMmlNary(elem);
3104
+ case DomType.MmlPreSubSuper: return this.renderMmlPreSubSuper(elem);
3105
+ case DomType.MmlBar: return this.renderMmlBar(elem);
3106
+ case DomType.MmlEquationArray: return this.renderMllList(elem);
3107
+ case DomType.Inserted: return this.renderInserted(elem);
3108
+ case DomType.Deleted: return this.renderDeleted(elem);
3109
+ case DomType.CommentRangeStart: return this.renderCommentRangeStart(elem);
3110
+ case DomType.CommentRangeEnd: return this.renderCommentRangeEnd(elem);
3111
+ case DomType.CommentReference: return this.renderCommentReference(elem);
3112
+ case DomType.AltChunk: return this.renderAltChunk(elem);
3113
+ }
3114
+ return null;
3115
+ }
3116
+ renderElements(elems, into) {
3117
+ if (elems == null) return null;
3118
+ var result = elems.flatMap((e) => this.renderElement(e)).filter((e) => e != null);
3119
+ if (into) appendChildren(into, result);
3120
+ return result;
3121
+ }
3122
+ renderContainer(elem, tagName, props) {
3123
+ return this.createElement(tagName, props, this.renderElements(elem.children));
3124
+ }
3125
+ renderContainerNS(elem, ns, tagName, props) {
3126
+ return this.createElementNS(ns, tagName, props, this.renderElements(elem.children));
3127
+ }
3128
+ renderParagraph(elem) {
3129
+ var result = this.renderContainer(elem, "p");
3130
+ const style = this.findStyle(elem.styleName);
3131
+ elem.tabs ?? (elem.tabs = style?.paragraphProps?.tabs);
3132
+ this.renderClass(elem, result);
3133
+ this.renderStyleValues(elem.cssStyle, result);
3134
+ this.renderCommonProperties(result.style, elem);
3135
+ const numbering = elem.numbering ?? style?.paragraphProps?.numbering;
3136
+ if (numbering) result.classList.add(this.numberingClass(numbering.id, numbering.level));
3137
+ if (elem.paraId) result.dataset.paraId = elem.paraId;
3138
+ if (elem.docxPart) {
3139
+ result.dataset.docxPart = elem.docxPart;
3140
+ if (elem.docxIndex !== void 0) result.dataset.docxIndex = String(elem.docxIndex);
3141
+ }
3142
+ return result;
3143
+ }
3144
+ renderRunProperties(style, props) {
3145
+ this.renderCommonProperties(style, props);
3146
+ }
3147
+ renderCommonProperties(style, props) {
3148
+ if (props == null) return;
3149
+ if (props.color) style["color"] = props.color;
3150
+ if (props.fontSize) style["font-size"] = props.fontSize;
3151
+ }
3152
+ renderHyperlink(elem) {
3153
+ var result = this.renderContainer(elem, "a");
3154
+ this.renderStyleValues(elem.cssStyle, result);
3155
+ let href = "";
3156
+ if (elem.id) href = this.document.documentPart.rels.find((it) => it.id == elem.id && it.targetMode === "External")?.target ?? href;
3157
+ if (elem.anchor) href += `#${elem.anchor}`;
3158
+ result.href = href;
3159
+ return result;
3160
+ }
3161
+ renderSmartTag(elem) {
3162
+ return this.renderContainer(elem, "span");
3163
+ }
3164
+ renderCommentRangeStart(commentStart) {
3165
+ if (!this.options.renderComments) return null;
3166
+ const rng = new Range();
3167
+ this.commentHighlight?.add(rng);
3168
+ const result = this.createComment(`start of comment #${commentStart.id}`);
3169
+ this.later(() => rng.setStart(result, 0));
3170
+ this.commentMap[commentStart.id] = rng;
3171
+ return result;
3172
+ }
3173
+ renderCommentRangeEnd(commentEnd) {
3174
+ if (!this.options.renderComments) return null;
3175
+ const rng = this.commentMap[commentEnd.id];
3176
+ const result = this.createComment(`end of comment #${commentEnd.id}`);
3177
+ this.later(() => rng?.setEnd(result, 0));
3178
+ return result;
3179
+ }
3180
+ renderCommentReference(commentRef) {
3181
+ if (!this.options.renderComments) return null;
3182
+ var comment = this.document.commentsPart?.commentMap[commentRef.id];
3183
+ if (!comment) return null;
3184
+ const frg = new DocumentFragment();
3185
+ const commentRefEl = this.createElement("span", { className: `${this.className}-comment-ref` }, ["💬"]);
3186
+ const commentsContainerEl = this.createElement("div", { className: `${this.className}-comment-popover` });
3187
+ this.renderCommentContent(comment, commentsContainerEl);
3188
+ frg.appendChild(this.createComment(`comment #${comment.id} by ${comment.author} on ${comment.date}`));
3189
+ frg.appendChild(commentRefEl);
3190
+ frg.appendChild(commentsContainerEl);
3191
+ return frg;
3192
+ }
3193
+ renderAltChunk(elem) {
3194
+ if (!this.options.renderAltChunks) return null;
3195
+ var result = this.createElement("iframe");
3196
+ this.tasks.push(this.document.loadAltChunk(elem.id, this.currentPart).then((x) => {
3197
+ result.srcdoc = x;
3198
+ }));
3199
+ return result;
3200
+ }
3201
+ renderCommentContent(comment, container) {
3202
+ container.appendChild(this.createElement("div", { className: `${this.className}-comment-author` }, [comment.author]));
3203
+ container.appendChild(this.createElement("div", { className: `${this.className}-comment-date` }, [new Date(comment.date).toLocaleString()]));
3204
+ this.renderElements(comment.children, container);
3205
+ }
3206
+ renderDrawing(elem) {
3207
+ var result = this.renderContainer(elem, "div");
3208
+ result.style.display = "inline-block";
3209
+ result.style.position = "relative";
3210
+ result.style.textIndent = "0px";
3211
+ this.renderStyleValues(elem.cssStyle, result);
3212
+ return result;
3213
+ }
3214
+ renderImage(elem) {
3215
+ let result = this.createElement("img");
3216
+ let transform = elem.cssStyle?.transform;
3217
+ this.renderStyleValues(elem.cssStyle, result);
3218
+ if (elem.srcRect && elem.srcRect.some((x) => x != 0)) {
3219
+ var [left, top, right, bottom] = elem.srcRect;
3220
+ transform = `scale(${1 / (1 - left - right)}, ${1 / (1 - top - bottom)})`;
3221
+ result.style["clip-path"] = `rect(${(100 * top).toFixed(2)}% ${(100 * (1 - right)).toFixed(2)}% ${(100 * (1 - bottom)).toFixed(2)}% ${(100 * left).toFixed(2)}%)`;
3222
+ }
3223
+ if (elem.rotation) transform = `rotate(${elem.rotation}deg) ${transform ?? ""}`;
3224
+ result.style.transform = transform?.trim();
3225
+ if (this.document) this.tasks.push(this.document.loadDocumentImage(elem.src, this.currentPart).then((x) => {
3226
+ result.src = x;
3227
+ }));
3228
+ return result;
3229
+ }
3230
+ renderText(elem) {
3231
+ return this.htmlDocument.createTextNode(elem.text);
3232
+ }
3233
+ renderDeletedText(elem) {
3234
+ return this.options.renderChanges ? this.renderText(elem) : null;
3235
+ }
3236
+ renderBreak(elem) {
3237
+ if (elem.break == "textWrapping") return this.createElement("br");
3238
+ return null;
3239
+ }
3240
+ renderInserted(elem) {
3241
+ if (this.options.renderChanges) return this.renderContainer(elem, "ins");
3242
+ return this.renderElements(elem.children);
3243
+ }
3244
+ renderDeleted(elem) {
3245
+ if (this.options.renderChanges) return this.renderContainer(elem, "del");
3246
+ return null;
3247
+ }
3248
+ renderSymbol(elem) {
3249
+ var span = this.createElement("span");
3250
+ span.style.fontFamily = elem.font;
3251
+ span.innerHTML = `&#x${elem.char};`;
3252
+ return span;
3253
+ }
3254
+ renderFootnoteReference(elem) {
3255
+ var result = this.createElement("sup");
3256
+ this.currentFootnoteIds.push(elem.id);
3257
+ result.textContent = `${this.currentFootnoteIds.length}`;
3258
+ return result;
3259
+ }
3260
+ renderEndnoteReference(elem) {
3261
+ var result = this.createElement("sup");
3262
+ this.currentEndnoteIds.push(elem.id);
3263
+ result.textContent = `${this.currentEndnoteIds.length}`;
3264
+ return result;
3265
+ }
3266
+ renderTab(elem) {
3267
+ var tabSpan = this.createElement("span");
3268
+ tabSpan.innerHTML = "&emsp;";
3269
+ if (this.options.experimental) {
3270
+ tabSpan.className = this.tabStopClass();
3271
+ var stops = findParent(elem, DomType.Paragraph)?.tabs;
3272
+ this.currentTabs.push({
3273
+ stops,
3274
+ span: tabSpan
3275
+ });
3276
+ }
3277
+ return tabSpan;
3278
+ }
3279
+ renderBookmarkStart(elem) {
3280
+ return this.createElement("span", { id: elem.name });
3281
+ }
3282
+ renderRun(elem) {
3283
+ if (elem.fieldRun) return null;
3284
+ const result = this.createElement("span");
3285
+ if (elem.id) result.id = elem.id;
3286
+ this.renderClass(elem, result);
3287
+ this.renderStyleValues(elem.cssStyle, result);
3288
+ if (elem.verticalAlign) {
3289
+ const wrapper = this.createElement(elem.verticalAlign);
3290
+ this.renderElements(elem.children, wrapper);
3291
+ result.appendChild(wrapper);
3292
+ } else this.renderElements(elem.children, result);
3293
+ return result;
3294
+ }
3295
+ renderTable(elem) {
3296
+ let result = this.createElement("table");
3297
+ this.tableCellPositions.push(this.currentCellPosition);
3298
+ this.tableVerticalMerges.push(this.currentVerticalMerge);
3299
+ this.currentVerticalMerge = {};
3300
+ this.currentCellPosition = {
3301
+ col: 0,
3302
+ row: 0
3303
+ };
3304
+ if (elem.columns) result.appendChild(this.renderTableColumns(elem.columns));
3305
+ this.renderClass(elem, result);
3306
+ this.renderElements(elem.children, result);
3307
+ this.renderStyleValues(elem.cssStyle, result);
3308
+ this.currentVerticalMerge = this.tableVerticalMerges.pop();
3309
+ this.currentCellPosition = this.tableCellPositions.pop();
3310
+ return result;
3311
+ }
3312
+ renderTableColumns(columns) {
3313
+ let result = this.createElement("colgroup");
3314
+ for (let col of columns) {
3315
+ let colElem = this.createElement("col");
3316
+ if (col.width) colElem.style.width = col.width;
3317
+ result.appendChild(colElem);
3318
+ }
3319
+ return result;
3320
+ }
3321
+ renderTableRow(elem) {
3322
+ let result = this.createElement("tr");
3323
+ this.currentCellPosition.col = 0;
3324
+ if (elem.gridBefore) result.appendChild(this.renderTableCellPlaceholder(elem.gridBefore));
3325
+ this.renderClass(elem, result);
3326
+ this.renderElements(elem.children, result);
3327
+ this.renderStyleValues(elem.cssStyle, result);
3328
+ if (elem.gridAfter) result.appendChild(this.renderTableCellPlaceholder(elem.gridAfter));
3329
+ this.currentCellPosition.row++;
3330
+ return result;
3331
+ }
3332
+ renderTableCellPlaceholder(colSpan) {
3333
+ const result = this.createElement("td", { colSpan });
3334
+ result.style["border"] = "none";
3335
+ return result;
3336
+ }
3337
+ renderTableCell(elem) {
3338
+ let result = this.renderContainer(elem, "td");
3339
+ const key = this.currentCellPosition.col;
3340
+ if (elem.verticalMerge) {
3341
+ if (elem.verticalMerge == "restart") {
3342
+ this.currentVerticalMerge[key] = result;
3343
+ result.rowSpan = 1;
3344
+ } else if (this.currentVerticalMerge[key]) {
3345
+ this.currentVerticalMerge[key].rowSpan += 1;
3346
+ result.style.display = "none";
3347
+ }
3348
+ } else this.currentVerticalMerge[key] = null;
3349
+ this.renderClass(elem, result);
3350
+ this.renderStyleValues(elem.cssStyle, result);
3351
+ if (elem.span) result.colSpan = elem.span;
3352
+ this.currentCellPosition.col += result.colSpan;
3353
+ return result;
3354
+ }
3355
+ renderVmlPicture(elem) {
3356
+ return this.renderContainer(elem, "div");
3357
+ }
3358
+ renderVmlElement(elem) {
3359
+ var container = this.createSvgElement("svg");
3360
+ container.setAttribute("style", elem.cssStyleText);
3361
+ const result = this.renderVmlChildElement(elem);
3362
+ if (elem.imageHref?.id) this.tasks.push(this.document?.loadDocumentImage(elem.imageHref.id, this.currentPart).then((x) => result.setAttribute("href", x)));
3363
+ container.appendChild(result);
3364
+ requestAnimationFrame(() => {
3365
+ const bb = container.firstElementChild.getBBox();
3366
+ container.setAttribute("width", `${Math.ceil(bb.x + bb.width)}`);
3367
+ container.setAttribute("height", `${Math.ceil(bb.y + bb.height)}`);
3368
+ });
3369
+ return container;
3370
+ }
3371
+ renderVmlChildElement(elem) {
3372
+ const result = this.createSvgElement(elem.tagName);
3373
+ Object.entries(elem.attrs).forEach(([k, v]) => result.setAttribute(k, v));
3374
+ for (let child of elem.children) if (child.type == DomType.VmlElement) result.appendChild(this.renderVmlChildElement(child));
3375
+ else result.appendChild(...asArray(this.renderElement(child)));
3376
+ return result;
3377
+ }
3378
+ renderMmlRadical(elem) {
3379
+ const base = elem.children.find((el) => el.type == DomType.MmlBase);
3380
+ if (elem.props?.hideDegree) return this.createElementNS(ns.mathML, "msqrt", null, this.renderElements([base]));
3381
+ const degree = elem.children.find((el) => el.type == DomType.MmlDegree);
3382
+ return this.createElementNS(ns.mathML, "mroot", null, this.renderElements([base, degree]));
3383
+ }
3384
+ renderMmlDelimiter(elem) {
3385
+ const children = [];
3386
+ children.push(this.createElementNS(ns.mathML, "mo", null, [elem.props.beginChar ?? "("]));
3387
+ children.push(...this.renderElements(elem.children));
3388
+ children.push(this.createElementNS(ns.mathML, "mo", null, [elem.props.endChar ?? ")"]));
3389
+ return this.createElementNS(ns.mathML, "mrow", null, children);
3390
+ }
3391
+ renderMmlNary(elem) {
3392
+ const children = [];
3393
+ const grouped = keyBy(elem.children, (x) => x.type);
3394
+ const sup = grouped[DomType.MmlSuperArgument];
3395
+ const sub = grouped[DomType.MmlSubArgument];
3396
+ const supElem = sup ? this.createElementNS(ns.mathML, "mo", null, asArray(this.renderElement(sup))) : null;
3397
+ const subElem = sub ? this.createElementNS(ns.mathML, "mo", null, asArray(this.renderElement(sub))) : null;
3398
+ const charElem = this.createElementNS(ns.mathML, "mo", null, [elem.props?.char ?? "∫"]);
3399
+ if (supElem || subElem) children.push(this.createElementNS(ns.mathML, "munderover", null, [
3400
+ charElem,
3401
+ subElem,
3402
+ supElem
3403
+ ]));
3404
+ else if (supElem) children.push(this.createElementNS(ns.mathML, "mover", null, [charElem, supElem]));
3405
+ else if (subElem) children.push(this.createElementNS(ns.mathML, "munder", null, [charElem, subElem]));
3406
+ else children.push(charElem);
3407
+ children.push(...this.renderElements(grouped[DomType.MmlBase].children));
3408
+ return this.createElementNS(ns.mathML, "mrow", null, children);
3409
+ }
3410
+ renderMmlPreSubSuper(elem) {
3411
+ const children = [];
3412
+ const grouped = keyBy(elem.children, (x) => x.type);
3413
+ const sup = grouped[DomType.MmlSuperArgument];
3414
+ const sub = grouped[DomType.MmlSubArgument];
3415
+ const supElem = sup ? this.createElementNS(ns.mathML, "mo", null, asArray(this.renderElement(sup))) : null;
3416
+ const subElem = sub ? this.createElementNS(ns.mathML, "mo", null, asArray(this.renderElement(sub))) : null;
3417
+ const stubElem = this.createElementNS(ns.mathML, "mo", null);
3418
+ children.push(this.createElementNS(ns.mathML, "msubsup", null, [
3419
+ stubElem,
3420
+ subElem,
3421
+ supElem
3422
+ ]));
3423
+ children.push(...this.renderElements(grouped[DomType.MmlBase].children));
3424
+ return this.createElementNS(ns.mathML, "mrow", null, children);
3425
+ }
3426
+ renderMmlGroupChar(elem) {
3427
+ const tagName = elem.props.verticalJustification === "bot" ? "mover" : "munder";
3428
+ const result = this.renderContainerNS(elem, ns.mathML, tagName);
3429
+ if (elem.props.char) result.appendChild(this.createElementNS(ns.mathML, "mo", null, [elem.props.char]));
3430
+ return result;
3431
+ }
3432
+ renderMmlBar(elem) {
3433
+ const result = this.renderContainerNS(elem, ns.mathML, "mrow");
3434
+ switch (elem.props.position) {
3435
+ case "top":
3436
+ result.style.textDecoration = "overline";
3437
+ break;
3438
+ case "bottom": result.style.textDecoration = "underline";
3439
+ }
3440
+ return result;
3441
+ }
3442
+ renderMmlRun(elem) {
3443
+ const result = this.createElementNS(ns.mathML, "ms", null, this.renderElements(elem.children));
3444
+ this.renderClass(elem, result);
3445
+ this.renderStyleValues(elem.cssStyle, result);
3446
+ return result;
3447
+ }
3448
+ renderMllList(elem) {
3449
+ const result = this.createElementNS(ns.mathML, "mtable");
3450
+ this.renderClass(elem, result);
3451
+ this.renderStyleValues(elem.cssStyle, result);
3452
+ for (let child of this.renderElements(elem.children)) result.appendChild(this.createElementNS(ns.mathML, "mtr", null, [this.createElementNS(ns.mathML, "mtd", null, [child])]));
3453
+ return result;
3454
+ }
3455
+ renderStyleValues(style, ouput) {
3456
+ for (let k in style) if (k.startsWith("$")) ouput.setAttribute(k.slice(1), style[k]);
3457
+ else ouput.style[k] = style[k];
3458
+ }
3459
+ renderClass(input, ouput) {
3460
+ if (input.className) ouput.className = input.className;
3461
+ if (input.styleName) ouput.classList.add(this.processStyleName(input.styleName));
3462
+ }
3463
+ findStyle(styleName) {
3464
+ return styleName && this.styleMap?.[styleName];
3465
+ }
3466
+ numberingClass(id, lvl) {
3467
+ return `${this.className}-num-${id}-${lvl}`;
3468
+ }
3469
+ tabStopClass() {
3470
+ return `${this.className}-tab-stop`;
3471
+ }
3472
+ styleToString(selectors, values, cssText = null) {
3473
+ let result = `${selectors} {\r\n`;
3474
+ for (const key in values) {
3475
+ if (key.startsWith("$")) continue;
3476
+ result += ` ${key}: ${values[key]};\r\n`;
3477
+ }
3478
+ if (cssText) result += cssText;
3479
+ return result + "}\r\n";
3480
+ }
3481
+ numberingCounter(id, lvl) {
3482
+ return `${this.className}-num-${id}-${lvl}`;
3483
+ }
3484
+ levelTextToContent(text, suff, id, numformat) {
3485
+ return `"${text.replace(/%\d*/g, (s) => {
3486
+ let lvl = parseInt(s.substring(1), 10) - 1;
3487
+ return `"counter(${this.numberingCounter(id, lvl)}, ${numformat})"`;
3488
+ })}${{
3489
+ "tab": "\\9",
3490
+ "space": "\\a0"
3491
+ }[suff] ?? ""}"`;
3492
+ }
3493
+ numFormatToCssValue(format) {
3494
+ return {
3495
+ none: "none",
3496
+ bullet: "disc",
3497
+ decimal: "decimal",
3498
+ lowerLetter: "lower-alpha",
3499
+ upperLetter: "upper-alpha",
3500
+ lowerRoman: "lower-roman",
3501
+ upperRoman: "upper-roman",
3502
+ decimalZero: "decimal-leading-zero",
3503
+ aiueo: "katakana",
3504
+ aiueoFullWidth: "katakana",
3505
+ chineseCounting: "simp-chinese-informal",
3506
+ chineseCountingThousand: "simp-chinese-informal",
3507
+ chineseLegalSimplified: "simp-chinese-formal",
3508
+ chosung: "hangul-consonant",
3509
+ ideographDigital: "cjk-ideographic",
3510
+ ideographTraditional: "cjk-heavenly-stem",
3511
+ ideographLegalTraditional: "trad-chinese-formal",
3512
+ ideographZodiac: "cjk-earthly-branch",
3513
+ iroha: "katakana-iroha",
3514
+ irohaFullWidth: "katakana-iroha",
3515
+ japaneseCounting: "japanese-informal",
3516
+ japaneseDigitalTenThousand: "cjk-decimal",
3517
+ japaneseLegal: "japanese-formal",
3518
+ thaiNumbers: "thai",
3519
+ koreanCounting: "korean-hangul-formal",
3520
+ koreanDigital: "korean-hangul-formal",
3521
+ koreanDigital2: "korean-hanja-informal",
3522
+ hebrew1: "hebrew",
3523
+ hebrew2: "hebrew",
3524
+ hindiNumbers: "devanagari",
3525
+ ganada: "hangul",
3526
+ taiwaneseCounting: "cjk-ideographic",
3527
+ taiwaneseCountingThousand: "cjk-ideographic",
3528
+ taiwaneseDigital: "cjk-decimal"
3529
+ }[format] ?? format;
3530
+ }
3531
+ refreshTabStops() {
3532
+ if (!this.options.experimental) return;
3533
+ setTimeout(() => {
3534
+ const pixelToPoint = computePixelToPoint();
3535
+ for (let tab of this.currentTabs) updateTabStop(tab.span, tab.stops, this.defaultTabSize, pixelToPoint);
3536
+ }, 500);
3537
+ }
3538
+ createElementNS(ns, tagName, props, children) {
3539
+ var result = ns ? this.htmlDocument.createElementNS(ns, tagName) : this.htmlDocument.createElement(tagName);
3540
+ Object.assign(result, props);
3541
+ children && appendChildren(result, children);
3542
+ return result;
3543
+ }
3544
+ createElement(tagName, props, children) {
3545
+ return this.createElementNS(void 0, tagName, props, children);
3546
+ }
3547
+ createSvgElement(tagName, props, children) {
3548
+ return this.createElementNS(ns.svg, tagName, props, children);
3549
+ }
3550
+ createStyleElement(cssText) {
3551
+ return this.createElement("style", { innerHTML: cssText });
3552
+ }
3553
+ createComment(text) {
3554
+ return this.htmlDocument.createComment(text);
3555
+ }
3556
+ later(func) {
3557
+ this.postRenderTasks.push(func);
3558
+ }
3559
+ };
3560
+ function removeAllElements(elem) {
3561
+ elem.innerHTML = "";
3562
+ }
3563
+ function appendChildren(elem, children) {
3564
+ children.forEach((c) => elem.appendChild(isString(c) ? document.createTextNode(c) : c));
3565
+ }
3566
+ function findParent(elem, type) {
3567
+ var parent = elem.parent;
3568
+ while (parent != null && parent.type != type) parent = parent.parent;
3569
+ return parent;
3570
+ }
3571
+ var defaultOptions = {
3572
+ ignoreHeight: false,
3573
+ ignoreWidth: false,
3574
+ ignoreFonts: false,
3575
+ breakPages: true,
3576
+ debug: false,
3577
+ experimental: false,
3578
+ className: "docx",
3579
+ inWrapper: true,
3580
+ hideWrapperOnPrint: false,
3581
+ trimXmlDeclaration: true,
3582
+ ignoreLastRenderedPageBreak: true,
3583
+ renderHeaders: true,
3584
+ renderFooters: true,
3585
+ renderFootnotes: true,
3586
+ renderEndnotes: true,
3587
+ useBase64URL: false,
3588
+ renderChanges: false,
3589
+ renderComments: false,
3590
+ renderAltChunks: true
3591
+ };
3592
+ function parseAsync(data, userOptions) {
3593
+ const ops = {
3594
+ ...defaultOptions,
3595
+ ...userOptions
3596
+ };
3597
+ return WordDocument.load(data, new DocumentParser(ops), ops);
3598
+ }
3599
+ async function renderDocument(document, bodyContainer, styleContainer, userOptions) {
3600
+ const ops = {
3601
+ ...defaultOptions,
3602
+ ...userOptions
3603
+ };
3604
+ return await new HtmlRenderer(window.document).render(document, bodyContainer, styleContainer, ops);
3605
+ }
3606
+ async function renderAsync(data, bodyContainer, styleContainer, userOptions) {
3607
+ const doc = await parseAsync(data, userOptions);
3608
+ await renderDocument(doc, bodyContainer, styleContainer, userOptions);
3609
+ return doc;
3610
+ }
3611
+ //#endregion
3612
+ //#region src/officeZipPreflight.ts
3613
+ var ZIP_EOCD_SIGNATURE = 101010256;
3614
+ var ZIP_CENTRAL_FILE_HEADER_SIGNATURE = 33639248;
3615
+ var ZIP_EOCD_MIN_BYTES = 22;
3616
+ var ZIP_CENTRAL_FILE_HEADER_BYTES = 46;
3617
+ var ZIP_MAX_COMMENT_BYTES = 65535;
3618
+ var ZIP_UINT16_MAX = 65535;
3619
+ var ZIP_UINT32_MAX = 4294967295;
3620
+ var OFFICE_ZIP_LIMITS = {
3621
+ maxEntries: 4e3,
3622
+ maxEntryUncompressedBytes: 67108864,
3623
+ maxTotalUncompressedBytes: 268435456
3624
+ };
3625
+ function findEndOfCentralDirectory(view, label) {
3626
+ const minOffset = Math.max(0, view.byteLength - ZIP_EOCD_MIN_BYTES - ZIP_MAX_COMMENT_BYTES);
3627
+ for (let offset = view.byteLength - ZIP_EOCD_MIN_BYTES; offset >= minOffset; offset -= 1) {
3628
+ if (view.getUint32(offset, true) !== ZIP_EOCD_SIGNATURE) continue;
3629
+ const commentLength = view.getUint16(offset + 20, true);
3630
+ if (offset + ZIP_EOCD_MIN_BYTES + commentLength === view.byteLength) return offset;
3631
+ }
3632
+ throw new Error(`${label} preview requires a valid ZIP archive`);
3633
+ }
3634
+ function assertNoZip64Uint16Marker(value, label) {
3635
+ if (value === ZIP_UINT16_MAX) throw new Error(`${label} preview does not support ZIP64 archives`);
3636
+ }
3637
+ function assertNoZip64Uint32Marker(value, label) {
3638
+ if (value === ZIP_UINT32_MAX) throw new Error(`${label} preview does not support ZIP64 archives`);
3639
+ }
3640
+ /**
3641
+ * OOXML (docx/xlsx/pptx) ZIP central-directory preflight. Before handing bytes to an unzip library, reject archives
3642
+ * whose declared entry count or uncompressed size exceeds the preview budget. These fields are attacker-controlled
3643
+ * metadata, so this is declared-size defense rather than a hard cap on actual decompressor output. `label` is the
3644
+ * user-facing format name, such as 'DOCX' or 'XLSX'.
3645
+ */
3646
+ function assertZipLimits(bytes, label, limits = OFFICE_ZIP_LIMITS) {
3647
+ if (bytes.byteLength < ZIP_EOCD_MIN_BYTES) throw new Error(`${label} preview requires a valid ZIP archive`);
3648
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
3649
+ const eocdOffset = findEndOfCentralDirectory(view, label);
3650
+ const diskNumber = view.getUint16(eocdOffset + 4, true);
3651
+ const centralDirectoryDisk = view.getUint16(eocdOffset + 6, true);
3652
+ const entriesOnDisk = view.getUint16(eocdOffset + 8, true);
3653
+ const entryCount = view.getUint16(eocdOffset + 10, true);
3654
+ const centralDirectorySize = view.getUint32(eocdOffset + 12, true);
3655
+ const centralDirectoryOffset = view.getUint32(eocdOffset + 16, true);
3656
+ if (diskNumber !== 0 || centralDirectoryDisk !== 0 || entriesOnDisk !== entryCount) throw new Error(`${label} preview does not support multi-disk ZIP archives`);
3657
+ assertNoZip64Uint16Marker(entryCount, label);
3658
+ assertNoZip64Uint32Marker(centralDirectorySize, label);
3659
+ assertNoZip64Uint32Marker(centralDirectoryOffset, label);
3660
+ if (entryCount > limits.maxEntries) throw new Error(`${label} preview supports ZIP archives with up to ${limits.maxEntries} entries`);
3661
+ const centralDirectoryEnd = centralDirectoryOffset + centralDirectorySize;
3662
+ if (centralDirectoryEnd > eocdOffset || centralDirectoryEnd < centralDirectoryOffset) throw new Error(`${label} preview requires a valid ZIP central directory`);
3663
+ let cursor = centralDirectoryOffset;
3664
+ let totalUncompressedBytes = 0;
3665
+ for (let index = 0; index < entryCount; index += 1) {
3666
+ if (cursor + ZIP_CENTRAL_FILE_HEADER_BYTES > centralDirectoryEnd) throw new Error(`${label} preview requires a valid ZIP central directory`);
3667
+ if (view.getUint32(cursor, true) !== ZIP_CENTRAL_FILE_HEADER_SIGNATURE) throw new Error(`${label} preview requires a valid ZIP central directory`);
3668
+ const compressedBytes = view.getUint32(cursor + 20, true);
3669
+ const uncompressedBytes = view.getUint32(cursor + 24, true);
3670
+ const fileNameLength = view.getUint16(cursor + 28, true);
3671
+ const extraFieldLength = view.getUint16(cursor + 30, true);
3672
+ const commentLength = view.getUint16(cursor + 32, true);
3673
+ const diskStart = view.getUint16(cursor + 34, true);
3674
+ const localHeaderOffset = view.getUint32(cursor + 42, true);
3675
+ assertNoZip64Uint32Marker(compressedBytes, label);
3676
+ assertNoZip64Uint32Marker(uncompressedBytes, label);
3677
+ assertNoZip64Uint32Marker(localHeaderOffset, label);
3678
+ if (diskStart !== 0) throw new Error(`${label} preview does not support multi-disk ZIP archives`);
3679
+ if (uncompressedBytes > limits.maxEntryUncompressedBytes) throw new Error(`${label} preview supports ZIP entries up to ${limits.maxEntryUncompressedBytes} uncompressed bytes`);
3680
+ totalUncompressedBytes += uncompressedBytes;
3681
+ if (totalUncompressedBytes > limits.maxTotalUncompressedBytes) throw new Error(`${label} preview supports ZIP archives up to ${limits.maxTotalUncompressedBytes} total uncompressed bytes`);
3682
+ cursor += ZIP_CENTRAL_FILE_HEADER_BYTES + fileNameLength + extraFieldLength + commentLength;
3683
+ if (cursor > centralDirectoryEnd) throw new Error(`${label} preview requires a valid ZIP central directory`);
3684
+ }
3685
+ if (cursor !== centralDirectoryEnd) throw new Error(`${label} preview requires a valid ZIP central directory`);
3686
+ }
3687
+ //#endregion
3688
+ //#region src/plugins/word/docxSelectionAnchor.ts
3689
+ /**
3690
+ * Plain text of a rendered paragraph, spelled with the separators python-docx's `Paragraph.text`
3691
+ * emits — the string the office-transform skill checks the excerpt against.
3692
+ *
3693
+ * `textContent` is not that string. docx-preview renders a line break (`w:br` of the default
3694
+ * `textWrapping` type) as `<br>` and `w:noBreakHyphen` as `<wbr>`; neither holds text, while python
3695
+ * spells them `\n` and `-`, so an unchanged paragraph containing either fails the skill's anchor
3696
+ * containment check. Nothing else renders as `<wbr>`.
3697
+ *
3698
+ * `w:tab` needs no case: docx-preview renders it as a span holding U+2003, which is inside the
3699
+ * whitespace class `normalizeSelectionText` collapses — the same single space python's `\t` collapses
3700
+ * to. Every other element contributes no separator of its own, so recursing into it is the whole mapping.
3701
+ */
3702
+ function paragraphExcerpt(paragraph) {
3703
+ const walker = paragraph.ownerDocument.createTreeWalker(paragraph, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT);
3704
+ let excerpt = "";
3705
+ for (let node = walker.nextNode(); node !== null; node = walker.nextNode()) if (node.nodeType === Node.TEXT_NODE) excerpt += node.nodeValue ?? "";
3706
+ else if (node.localName === "br") excerpt += "\n";
3707
+ else if (node.localName === "wbr") excerpt += "-";
3708
+ return excerpt;
3709
+ }
3710
+ /**
3711
+ * Derives a DOCX paragraph anchor + plain-text excerpt from an element the user picked inside the
3712
+ * docx-preview render. Relies on the `data-docx-part` / `data-docx-index` / `data-para-id`
3713
+ * attributes added by the repo's `docx-preview` patch.
3714
+ *
3715
+ * Returns null unless the pick lands in a **body-level** paragraph: `paragraph` is a required anchor
3716
+ * field, and only body paragraphs carry an ordinal that matches the document's own addressing.
3717
+ * Headers, footers, footnotes, endnotes, comments and table cells therefore produce no anchor at all
3718
+ * rather than a half-truthful one.
3719
+ *
3720
+ * The innermost paragraph is resolved and the ordinal is required on that exact element: docx-preview
3721
+ * parses `w:txbxContent` through `parseBodyElements` without a part, so a text box's paragraphs carry
3722
+ * no ordinal while the body paragraph wrapping the shape does. Matching `[data-docx-index]` directly
3723
+ * would skip past the text box and anchor to the outer paragraph, which a later edit would then
3724
+ * replace instead of the text the user actually picked.
3725
+ *
3726
+ * Never resolve `data-para-id` with a global query — headers/footers and footnotes are re-rendered
3727
+ * per page, so the same id appears many times.
3728
+ */
3729
+ function paragraphToDocxAnchor(element) {
3730
+ const paragraphElement = element.closest("p");
3731
+ if (!paragraphElement || paragraphElement.dataset.docxPart !== "body") return null;
3732
+ const paragraph = Number(paragraphElement.dataset.docxIndex);
3733
+ if (!Number.isInteger(paragraph) || paragraph < 0) return null;
3734
+ const paraId = paragraphElement.dataset.paraId;
3735
+ return {
3736
+ anchor: {
3737
+ format: "docx",
3738
+ paragraph,
3739
+ ...paraId ? { paraId } : {}
3740
+ },
3741
+ excerpt: paragraphExcerpt(paragraphElement),
3742
+ element: paragraphElement
3743
+ };
3744
+ }
3745
+ //#endregion
3746
+ //#region src/plugins/word/WordFilePreviewToolbar.tsx
3747
+ function WordFilePreviewToolbar({ canNextPage, canPreviousPage, canResetZoom, canZoomIn, canZoomOut, currentPage, onNextPage, onPreviousPage, onResetZoom, onZoomIn, onZoomOut, pageCount, zoomLabel }) {
3748
+ const { t } = useTranslation();
3749
+ return /* @__PURE__ */ jsxs(FilePreviewToolbar, {
3750
+ "aria-label": t("preview.label"),
3751
+ children: [
3752
+ /* @__PURE__ */ jsx(FilePreviewToolbarButton, {
3753
+ label: t("common.previous"),
3754
+ disabled: !canPreviousPage,
3755
+ onClick: onPreviousPage,
3756
+ children: /* @__PURE__ */ jsx(ChevronLeft, { "aria-hidden": true })
3757
+ }),
3758
+ /* @__PURE__ */ jsxs("span", {
3759
+ "aria-live": "polite",
3760
+ className: "min-w-14 px-1 text-center text-xs text-muted-foreground tabular-nums",
3761
+ "data-testid": "docx-preview-page-indicator",
3762
+ children: [
3763
+ currentPage,
3764
+ " / ",
3765
+ pageCount
3766
+ ]
3767
+ }),
3768
+ /* @__PURE__ */ jsx(FilePreviewToolbarButton, {
3769
+ label: t("common.next"),
3770
+ disabled: !canNextPage,
3771
+ onClick: onNextPage,
3772
+ children: /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": true })
3773
+ }),
3774
+ /* @__PURE__ */ jsx("span", {
3775
+ className: "mx-1 h-4 w-px bg-border-subtle",
3776
+ "aria-hidden": true
3777
+ }),
3778
+ /* @__PURE__ */ jsx(FilePreviewToolbarButton, {
3779
+ label: t("preview.zoom_out"),
3780
+ disabled: !canZoomOut,
3781
+ onClick: onZoomOut,
3782
+ children: /* @__PURE__ */ jsx(ZoomOut, { "aria-hidden": true })
3783
+ }),
3784
+ /* @__PURE__ */ jsx("span", {
3785
+ className: "min-w-12 px-1 text-center text-xs text-muted-foreground tabular-nums",
3786
+ "data-testid": "docx-preview-zoom-value",
3787
+ children: zoomLabel
3788
+ }),
3789
+ /* @__PURE__ */ jsx(FilePreviewToolbarButton, {
3790
+ label: t("preview.zoom_in"),
3791
+ disabled: !canZoomIn,
3792
+ onClick: onZoomIn,
3793
+ children: /* @__PURE__ */ jsx(ZoomIn, { "aria-hidden": true })
3794
+ }),
3795
+ /* @__PURE__ */ jsx(FilePreviewToolbarButton, {
3796
+ label: t("preview.reset"),
3797
+ disabled: !canResetZoom,
3798
+ onClick: onResetZoom,
3799
+ children: /* @__PURE__ */ jsx(RotateCcw, { "aria-hidden": true })
3800
+ })
3801
+ ]
3802
+ });
3803
+ }
3804
+ //#endregion
3805
+ //#region src/plugins/word/WordFilePreview.tsx
3806
+ var DOCX_PREVIEW_DEFAULT_ZOOM = 1;
3807
+ var DOCX_PREVIEW_ZOOM_STEP = .1;
3808
+ var DOCX_PREVIEW_MIN_ZOOM = .5;
3809
+ var DOCX_PREVIEW_MAX_ZOOM = 2;
3810
+ var DOCX_PREVIEW_MAX_SOURCE_BYTES = 26214400;
3811
+ var SAFE_HYPERLINK_PROTOCOLS = /* @__PURE__ */ new Set([
3812
+ "http:",
3813
+ "https:",
3814
+ "mailto:"
3815
+ ]);
3816
+ var clamp = (value, min, max) => Math.min(Math.max(value, min), max);
3817
+ var formatDocxZoom = (zoom) => `${Math.round(zoom * 100)}%`;
3818
+ function getRenderedPages(body) {
3819
+ const sections = Array.from(body.querySelectorAll("section"));
3820
+ if (sections.length > 0) return sections;
3821
+ return Array.from(body.children).filter((child) => child instanceof HTMLElement);
3822
+ }
3823
+ function sanitizeHyperlinks(body) {
3824
+ body.querySelectorAll("a[href]").forEach((anchor) => {
3825
+ const href = anchor.getAttribute("href") ?? "";
3826
+ let protocol = null;
3827
+ try {
3828
+ protocol = new URL(href, "https://docx-preview.invalid/").protocol;
3829
+ } catch {
3830
+ protocol = null;
3831
+ }
3832
+ if (!protocol || !SAFE_HYPERLINK_PROTOCOLS.has(protocol)) anchor.removeAttribute("href");
3833
+ anchor.setAttribute("rel", "noopener noreferrer");
3834
+ });
3835
+ }
3836
+ function WordFilePreview({ sourceId, fileName, document: previewDocument, onSelection }) {
3837
+ const { options, failDocument } = usePreviewHost();
3838
+ const { t } = useTranslation();
3839
+ const docxClassName = `docx-preview-${useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
3840
+ const containerRef = useRef(null);
3841
+ const bodyRef = useRef(null);
3842
+ const styleRef = useRef(null);
3843
+ const renderTokenRef = useRef(0);
3844
+ const fitScrollTopRef = useRef(null);
3845
+ const committedZoomRef = useRef(DOCX_PREVIEW_DEFAULT_ZOOM);
3846
+ const pinchAnchorRef = useRef(null);
3847
+ const [error, setError] = useState(null);
3848
+ const [loading, setLoading] = useState(true);
3849
+ const [currentPage, setCurrentPage] = useState(0);
3850
+ const [pageCount, setPageCount] = useState(0);
3851
+ const [zoom, setZoom] = useState(DOCX_PREVIEW_DEFAULT_ZOOM);
3852
+ const [fitZoom, setFitZoom] = useState(DOCX_PREVIEW_DEFAULT_ZOOM);
3853
+ const [manualZoom, setManualZoom] = useState(false);
3854
+ const [normalizeSymbolBullets] = useState(() => options?.docx?.normalizeSymbolBullets === true);
3855
+ const fitWidth = options?.docx?.initialZoom === "fit-width";
3856
+ const minZoom = fitWidth ? Math.min(DOCX_PREVIEW_MIN_ZOOM, fitZoom) : DOCX_PREVIEW_MIN_ZOOM;
3857
+ useLayoutEffect(() => {
3858
+ committedZoomRef.current = zoom;
3859
+ const anchor = pinchAnchorRef.current;
3860
+ pinchAnchorRef.current = null;
3861
+ const container = containerRef.current;
3862
+ const body = bodyRef.current;
3863
+ if (!anchor || !container || !body) return;
3864
+ const rect = body.getBoundingClientRect();
3865
+ container.scrollLeft += rect.left + anchor.x * zoom - anchor.origin[0];
3866
+ container.scrollTop += rect.top + anchor.y * zoom - anchor.origin[1];
3867
+ }, [zoom]);
3868
+ useLayoutEffect(() => {
3869
+ const container = containerRef.current;
3870
+ const body = bodyRef.current;
3871
+ if (!fitWidth || !container || !body || pageCount <= 0) return;
3872
+ const fit = () => {
3873
+ const width = body.offsetWidth;
3874
+ if (container.clientWidth > 0 && width > 0) setFitZoom(Math.min(DOCX_PREVIEW_DEFAULT_ZOOM, container.clientWidth / width));
3875
+ };
3876
+ fit();
3877
+ const observer = new ResizeObserver(fit);
3878
+ observer.observe(container);
3879
+ observer.observe(body);
3880
+ return () => observer.disconnect();
3881
+ }, [fitWidth, pageCount]);
3882
+ useLayoutEffect(() => {
3883
+ if (!fitWidth || manualZoom) return;
3884
+ const container = containerRef.current;
3885
+ if (zoom === fitZoom) {
3886
+ if (container && fitScrollTopRef.current !== null) container.scrollTop = fitScrollTopRef.current;
3887
+ fitScrollTopRef.current = null;
3888
+ return;
3889
+ }
3890
+ if (container) fitScrollTopRef.current = container.scrollTop * (fitZoom / zoom);
3891
+ setZoom(fitZoom);
3892
+ }, [
3893
+ fitWidth,
3894
+ fitZoom,
3895
+ manualZoom,
3896
+ zoom
3897
+ ]);
3898
+ const focusContainer = useCallback(() => {
3899
+ containerRef.current?.focus({ preventScroll: true });
3900
+ }, []);
3901
+ const jumpToPage = useCallback((pageNumber) => {
3902
+ if (pageCount <= 0) return;
3903
+ const nextPage = clamp(pageNumber, 1, pageCount);
3904
+ setCurrentPage(nextPage);
3905
+ bodyRef.current?.querySelector(`#docx-preview-page-${nextPage}`)?.scrollIntoView?.({ block: "start" });
3906
+ focusContainer();
3907
+ }, [focusContainer, pageCount]);
3908
+ const zoomBy = useCallback((direction) => {
3909
+ setManualZoom(true);
3910
+ setZoom((value) => clamp(Number((value + (direction === "in" ? DOCX_PREVIEW_ZOOM_STEP : -.1)).toFixed(2)), minZoom, DOCX_PREVIEW_MAX_ZOOM));
3911
+ focusContainer();
3912
+ }, [focusContainer, minZoom]);
3913
+ const resetZoom = useCallback(() => {
3914
+ setManualZoom(false);
3915
+ if (!fitWidth) setZoom(DOCX_PREVIEW_DEFAULT_ZOOM);
3916
+ focusContainer();
3917
+ }, [focusContainer, fitWidth]);
3918
+ useEffect(() => {
3919
+ const bodyContainer = bodyRef.current;
3920
+ const styleContainer = styleRef.current;
3921
+ if (!bodyContainer || !styleContainer) return;
3922
+ const controller = new AbortController();
3923
+ const token = ++renderTokenRef.current;
3924
+ const isCurrent = () => renderTokenRef.current === token;
3925
+ setError(null);
3926
+ setLoading(true);
3927
+ setCurrentPage(0);
3928
+ setPageCount(0);
3929
+ setZoom(DOCX_PREVIEW_DEFAULT_ZOOM);
3930
+ setFitZoom(DOCX_PREVIEW_DEFAULT_ZOOM);
3931
+ setManualZoom(false);
3932
+ fitScrollTopRef.current = null;
3933
+ pinchAnchorRef.current = null;
3934
+ const stagingHost = document.createElement("div");
3935
+ const stagingBody = document.createElement("div");
3936
+ const stagingStyle = document.createElement("div");
3937
+ stagingHost.style.cssText = "position:fixed;top:0;left:-99999px;visibility:hidden;";
3938
+ stagingHost.append(stagingStyle, stagingBody);
3939
+ document.body.appendChild(stagingHost);
3940
+ (async () => {
3941
+ try {
3942
+ const docxData = await readPreviewDocument(previewDocument, DOCX_PREVIEW_MAX_SOURCE_BYTES, controller.signal);
3943
+ if (!isCurrent()) return;
3944
+ assertZipLimits(docxData, "DOCX");
3945
+ if (!isCurrent()) return;
3946
+ await renderAsync(docxData, stagingBody, stagingStyle, {
3947
+ className: docxClassName,
3948
+ inWrapper: true,
3949
+ breakPages: true,
3950
+ ignoreLastRenderedPageBreak: true,
3951
+ renderHeaders: true,
3952
+ renderFooters: true,
3953
+ renderFootnotes: true,
3954
+ renderEndnotes: true,
3955
+ useBase64URL: true,
3956
+ renderAltChunks: false,
3957
+ normalizeSymbolBullets
3958
+ });
3959
+ if (!isCurrent()) return;
3960
+ stagingBody.querySelector(`.${docxClassName}-wrapper`)?.classList.add("docx-preview-wrapper");
3961
+ const pages = getRenderedPages(stagingBody);
3962
+ pages.forEach((page, index) => {
3963
+ page.id = `docx-preview-page-${index + 1}`;
3964
+ page.dataset.docxPreviewPage = String(index + 1);
3965
+ page.classList.add("docx-preview-page", "docx-preview");
3966
+ });
3967
+ sanitizeHyperlinks(stagingBody);
3968
+ bodyContainer.replaceChildren(...stagingBody.childNodes);
3969
+ styleContainer.replaceChildren(...stagingStyle.childNodes);
3970
+ const nextPageCount = Math.max(pages.length, 1);
3971
+ setPageCount(nextPageCount);
3972
+ setCurrentPage(nextPageCount > 0 ? 1 : 0);
3973
+ focusContainer();
3974
+ } catch (loadError) {
3975
+ if (!isCurrent()) return;
3976
+ const normalized = loadError instanceof Error ? loadError : new Error(String(loadError));
3977
+ failDocument?.(normalized);
3978
+ setError(normalized);
3979
+ } finally {
3980
+ if (isCurrent()) setLoading(false);
3981
+ stagingHost.remove();
3982
+ }
3983
+ })();
3984
+ return () => {
3985
+ controller.abort();
3986
+ renderTokenRef.current += 1;
3987
+ bodyContainer.innerHTML = "";
3988
+ styleContainer.innerHTML = "";
3989
+ stagingHost.remove();
3990
+ };
3991
+ }, [
3992
+ sourceId,
3993
+ focusContainer,
3994
+ previewDocument,
3995
+ failDocument,
3996
+ docxClassName,
3997
+ normalizeSymbolBullets
3998
+ ]);
3999
+ useEffect(() => {
4000
+ const scrollRoot = containerRef.current;
4001
+ const bodyContainer = bodyRef.current;
4002
+ if (!scrollRoot || !bodyContainer || pageCount <= 0) return;
4003
+ const pages = Array.from(bodyContainer.querySelectorAll(".docx-preview-page"));
4004
+ if (pages.length === 0) return;
4005
+ const visiblePages = /* @__PURE__ */ new Set();
4006
+ const observer = new IntersectionObserver((entries) => {
4007
+ for (const entry of entries) {
4008
+ const page = entry.target;
4009
+ if (entry.isIntersecting) visiblePages.add(page);
4010
+ else visiblePages.delete(page);
4011
+ }
4012
+ const topmost = pages.find((page) => visiblePages.has(page));
4013
+ const pageNumber = topmost ? Number(topmost.dataset.docxPreviewPage) : null;
4014
+ if (pageNumber && Number.isFinite(pageNumber)) setCurrentPage(pageNumber);
4015
+ }, {
4016
+ root: scrollRoot,
4017
+ threshold: [
4018
+ 0,
4019
+ .5,
4020
+ 1
4021
+ ]
4022
+ });
4023
+ pages.forEach((page) => observer.observe(page));
4024
+ return () => observer.disconnect();
4025
+ }, [pageCount]);
4026
+ const handlePick = useCallback((event) => {
4027
+ if (!onSelection || !(event.target instanceof Element)) return;
4028
+ if (event.target.closest("a[href]")) event.preventDefault();
4029
+ const previous = bodyRef.current?.querySelector("[data-docx-picked=\"true\"]") ?? null;
4030
+ const resolved = paragraphToDocxAnchor(event.target);
4031
+ previous?.removeAttribute("data-docx-picked");
4032
+ if (!resolved || resolved.element === previous) {
4033
+ onSelection(null);
4034
+ return;
4035
+ }
4036
+ const reference = createPreviewSelection({
4037
+ sourceId,
4038
+ anchor: resolved.anchor,
4039
+ excerpt: resolved.excerpt,
4040
+ revision: previewDocument.revision
4041
+ });
4042
+ if (reference) resolved.element.setAttribute("data-docx-picked", "true");
4043
+ onSelection(reference);
4044
+ }, [
4045
+ sourceId,
4046
+ previewDocument,
4047
+ onSelection
4048
+ ]);
4049
+ useEffect(() => {
4050
+ if (onSelection) return;
4051
+ bodyRef.current?.querySelector("[data-docx-picked=\"true\"]")?.removeAttribute("data-docx-picked");
4052
+ }, [onSelection]);
4053
+ useEffect(() => {
4054
+ const container = containerRef.current;
4055
+ if (!container) return;
4056
+ return attachTouchPinch(container, (scaleFactor, origin) => {
4057
+ const body = bodyRef.current;
4058
+ if (!body) return;
4059
+ const currentZoom = committedZoomRef.current;
4060
+ const nextZoom = clamp((pinchAnchorRef.current?.zoom ?? currentZoom) * scaleFactor, minZoom, DOCX_PREVIEW_MAX_ZOOM);
4061
+ const rect = body.getBoundingClientRect();
4062
+ pinchAnchorRef.current = nextZoom === currentZoom ? null : {
4063
+ zoom: nextZoom,
4064
+ x: (origin[0] - rect.left) / currentZoom,
4065
+ y: (origin[1] - rect.top) / currentZoom,
4066
+ origin
4067
+ };
4068
+ setManualZoom(true);
4069
+ setZoom(nextZoom);
4070
+ });
4071
+ }, [minZoom]);
4072
+ const hasPages = !error && pageCount > 0;
4073
+ const contentStyle = { zoom };
4074
+ return /* @__PURE__ */ jsxs(FilePreviewLayout.Frame, { children: [/* @__PURE__ */ jsx(WordFilePreviewToolbar, {
4075
+ currentPage: hasPages ? currentPage : 0,
4076
+ pageCount: hasPages ? pageCount : 0,
4077
+ zoomLabel: formatDocxZoom(zoom),
4078
+ canPreviousPage: hasPages && currentPage > 1,
4079
+ canNextPage: hasPages && currentPage < pageCount,
4080
+ canZoomOut: hasPages && zoom > minZoom,
4081
+ canZoomIn: hasPages && zoom < DOCX_PREVIEW_MAX_ZOOM,
4082
+ canResetZoom: hasPages && (fitWidth ? manualZoom : zoom !== DOCX_PREVIEW_DEFAULT_ZOOM),
4083
+ onPreviousPage: () => jumpToPage(currentPage - 1),
4084
+ onNextPage: () => jumpToPage(currentPage + 1),
4085
+ onZoomOut: () => zoomBy("out"),
4086
+ onZoomIn: () => zoomBy("in"),
4087
+ onResetZoom: resetZoom
4088
+ }), /* @__PURE__ */ jsx(FilePreviewLayout.Content, {
4089
+ scrollsInternally: true,
4090
+ children: /* @__PURE__ */ jsxs("div", {
4091
+ "data-testid": "word-file-preview",
4092
+ className: "relative h-full min-h-0 w-full overflow-hidden bg-background",
4093
+ children: [
4094
+ /* @__PURE__ */ jsxs("div", {
4095
+ ref: containerRef,
4096
+ style: options?.bottomInset === "content" ? { paddingBottom: "var(--file-preview-bottom-inset, 0px)" } : void 0,
4097
+ role: "region",
4098
+ "aria-label": fileName,
4099
+ className: "absolute inset-0 touch-pan-x touch-pan-y overflow-auto bg-background outline-none focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-inset",
4100
+ tabIndex: 0,
4101
+ children: [/* @__PURE__ */ jsx("div", { ref: styleRef }), /* @__PURE__ */ jsx("div", {
4102
+ ref: bodyRef,
4103
+ "data-testid": "docx-preview-content",
4104
+ "data-zoom": zoom,
4105
+ "data-picker": onSelection ? "true" : void 0,
4106
+ onClick: handlePick,
4107
+ style: contentStyle,
4108
+ className: "mx-auto w-fit min-w-0 [&[data-picker=true]_p[data-docx-part=body]:not([data-docx-picked=true]):hover]:bg-primary/10 [&[data-picker=true]_p[data-docx-part=body]]:cursor-pointer [&_.docx-preview-wrapper]:mx-auto [&_.docx-preview]:box-border [&_.docx-preview]:max-w-full [&_p[data-docx-picked=true]]:bg-primary/15 [&_p[data-docx-picked=true]]:outline [&_p[data-docx-picked=true]]:outline-1 [&_p[data-docx-picked=true]]:outline-primary/60 [&_section]:overflow-hidden [&_section]:rounded-sm [&_section]:shadow-md"
4109
+ })]
4110
+ }),
4111
+ loading ? /* @__PURE__ */ jsxs("div", {
4112
+ role: "status",
4113
+ className: "absolute inset-0 flex items-center justify-center gap-2 bg-background text-sm text-muted-foreground",
4114
+ children: [/* @__PURE__ */ jsx(LoaderCircle, {
4115
+ className: "size-4 animate-spin",
4116
+ "aria-hidden": true
4117
+ }), /* @__PURE__ */ jsx("span", { children: t("file_preview.loading") })]
4118
+ }) : null,
4119
+ error ? /* @__PURE__ */ jsx("div", {
4120
+ role: "alert",
4121
+ className: "absolute inset-0 bg-background",
4122
+ children: error instanceof PreviewError && error.code === "too_large" ? /* @__PURE__ */ jsx(FilePreviewTooLarge, {
4123
+ sizeBytes: previewDocument.size,
4124
+ limitBytes: DOCX_PREVIEW_MAX_SOURCE_BYTES
4125
+ }) : /* @__PURE__ */ jsx(EmptyState, {
4126
+ icon: CircleAlert,
4127
+ title: t("file_preview.load_error.title"),
4128
+ description: t("file_preview.load_error.description"),
4129
+ className: "h-full"
4130
+ })
4131
+ }) : null
4132
+ ]
4133
+ })
4134
+ })] });
4135
+ }
4136
+ //#endregion
4137
+ export { WordFilePreview as default };