@l1yp/file-viewer 0.1.0 → 0.1.2

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 (439) hide show
  1. package/README.md +2 -0
  2. package/dist/FileViewer.js +2 -0
  3. package/dist/FileViewer.js.map +1 -0
  4. package/dist/FileViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  5. package/dist/FileViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  6. package/dist/components/AppxViewer.js +2 -0
  7. package/dist/components/AppxViewer.js.map +1 -0
  8. package/dist/components/AppxViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  9. package/dist/components/AppxViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  10. package/dist/components/ArchiveBrowser.js +2 -0
  11. package/dist/components/ArchiveBrowser.js.map +1 -0
  12. package/dist/components/ArchiveBrowser.vue_vue_type_script_setup_true_lang.js +2 -0
  13. package/dist/components/ArchiveBrowser.vue_vue_type_script_setup_true_lang.js.map +1 -0
  14. package/dist/components/AudioViewer.js +2 -0
  15. package/dist/components/AudioViewer.js.map +1 -0
  16. package/dist/components/AudioViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  17. package/dist/components/AudioViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  18. package/dist/components/BinObjBrowser.js +2 -0
  19. package/dist/components/BinObjBrowser.js.map +1 -0
  20. package/dist/components/BinObjBrowser.vue_vue_type_script_setup_true_lang.js +2 -0
  21. package/dist/components/BinObjBrowser.vue_vue_type_script_setup_true_lang.js.map +1 -0
  22. package/dist/components/CertViewer.js +2 -0
  23. package/dist/components/CertViewer.js.map +1 -0
  24. package/dist/components/CertViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  25. package/dist/components/CertViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  26. package/dist/components/ClassViewer.js +2 -0
  27. package/dist/components/ClassViewer.js.map +1 -0
  28. package/dist/components/ClassViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  29. package/dist/components/ClassViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  30. package/dist/components/CodeBlock.js +2 -0
  31. package/dist/components/CodeBlock.js.map +1 -0
  32. package/dist/components/CodeBlock.vue_vue_type_script_setup_true_lang.js +2 -0
  33. package/dist/components/CodeBlock.vue_vue_type_script_setup_true_lang.js.map +1 -0
  34. package/dist/components/CodeView.js +2 -0
  35. package/dist/components/CodeView.js.map +1 -0
  36. package/dist/components/CodeView.vue_vue_type_script_setup_true_lang.js +2 -0
  37. package/dist/components/CodeView.vue_vue_type_script_setup_true_lang.js.map +1 -0
  38. package/dist/components/CsvViewer.js +2 -0
  39. package/dist/components/CsvViewer.js.map +1 -0
  40. package/dist/components/CsvViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  41. package/dist/components/CsvViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  42. package/dist/components/DicomViewer.js +2 -0
  43. package/dist/components/DicomViewer.js.map +1 -0
  44. package/dist/components/DicomViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  45. package/dist/components/DicomViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  46. package/dist/components/DocxNavigationPane.js +9 -0
  47. package/dist/components/DocxNavigationPane.js.map +1 -0
  48. package/dist/components/DocxNavigationPane.vue.d.ts +23 -0
  49. package/dist/components/DocxNavigationPane.vue_vue_type_script_setup_true_lang.js +98 -0
  50. package/dist/components/DocxNavigationPane.vue_vue_type_script_setup_true_lang.js.map +1 -0
  51. package/dist/components/DocxViewer.js +3 -1
  52. package/dist/components/DocxViewer.js.map +1 -0
  53. package/dist/components/DocxViewer.vue_vue_type_script_setup_true_lang.js +72 -37
  54. package/dist/components/DocxViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  55. package/dist/components/DrawioViewer.js +2 -0
  56. package/dist/components/DrawioViewer.js.map +1 -0
  57. package/dist/components/DrawioViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  58. package/dist/components/DrawioViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  59. package/dist/components/DxfViewer.js +2 -0
  60. package/dist/components/DxfViewer.js.map +1 -0
  61. package/dist/components/DxfViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  62. package/dist/components/DxfViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  63. package/dist/components/EbookViewer.js +2 -0
  64. package/dist/components/EbookViewer.js.map +1 -0
  65. package/dist/components/EbookViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  66. package/dist/components/EbookViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  67. package/dist/components/EmlViewer.js +2 -0
  68. package/dist/components/EmlViewer.js.map +1 -0
  69. package/dist/components/EmlViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  70. package/dist/components/EmlViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  71. package/dist/components/EplViewer.js +2 -0
  72. package/dist/components/EplViewer.js.map +1 -0
  73. package/dist/components/EplViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  74. package/dist/components/EplViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  75. package/dist/components/FileViewerBody.js +3 -1
  76. package/dist/components/FileViewerBody.js.map +1 -0
  77. package/dist/components/FileViewerBody.vue.d.ts +5 -0
  78. package/dist/components/FileViewerBody.vue_vue_type_script_setup_true_lang.js +250 -247
  79. package/dist/components/FileViewerBody.vue_vue_type_script_setup_true_lang.js.map +1 -0
  80. package/dist/components/FileViewerPanel.js +2 -0
  81. package/dist/components/FileViewerPanel.js.map +1 -0
  82. package/dist/components/FileViewerPanel.vue_vue_type_script_setup_true_lang.js +2 -0
  83. package/dist/components/FileViewerPanel.vue_vue_type_script_setup_true_lang.js.map +1 -0
  84. package/dist/components/FontViewer.js +2 -0
  85. package/dist/components/FontViewer.js.map +1 -0
  86. package/dist/components/FontViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  87. package/dist/components/FontViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  88. package/dist/components/FrontmatterCard.js +2 -0
  89. package/dist/components/FrontmatterCard.js.map +1 -0
  90. package/dist/components/FrontmatterCard.vue_vue_type_script_setup_true_lang.js +2 -0
  91. package/dist/components/FrontmatterCard.vue_vue_type_script_setup_true_lang.js.map +1 -0
  92. package/dist/components/GeoViewer.js +2 -0
  93. package/dist/components/GeoViewer.js.map +1 -0
  94. package/dist/components/GeoViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  95. package/dist/components/GeoViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  96. package/dist/components/HarViewer.js +2 -0
  97. package/dist/components/HarViewer.js.map +1 -0
  98. package/dist/components/HarViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  99. package/dist/components/HarViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  100. package/dist/components/HexViewer.js +2 -0
  101. package/dist/components/HexViewer.js.map +1 -0
  102. package/dist/components/HexViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  103. package/dist/components/HexViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  104. package/dist/components/HprofViewer.js +2 -0
  105. package/dist/components/HprofViewer.js.map +1 -0
  106. package/dist/components/HprofViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  107. package/dist/components/HprofViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  108. package/dist/components/ImageLightbox.js +2 -0
  109. package/dist/components/ImageLightbox.js.map +1 -0
  110. package/dist/components/ImageLightbox.vue_vue_type_script_setup_true_lang.js +2 -0
  111. package/dist/components/ImageLightbox.vue_vue_type_script_setup_true_lang.js.map +1 -0
  112. package/dist/components/InlineText.js +2 -0
  113. package/dist/components/InlineText.js.map +1 -0
  114. package/dist/components/JksViewer.js +2 -0
  115. package/dist/components/JksViewer.js.map +1 -0
  116. package/dist/components/JksViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  117. package/dist/components/JksViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  118. package/dist/components/JsonlViewer.js +2 -0
  119. package/dist/components/JsonlViewer.js.map +1 -0
  120. package/dist/components/JsonlViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  121. package/dist/components/JsonlViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  122. package/dist/components/LogViewer.js +2 -0
  123. package/dist/components/LogViewer.js.map +1 -0
  124. package/dist/components/LogViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  125. package/dist/components/LogViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  126. package/dist/components/LrcViewer.js +2 -0
  127. package/dist/components/LrcViewer.js.map +1 -0
  128. package/dist/components/LrcViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  129. package/dist/components/LrcViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  130. package/dist/components/MarkdownTable.js +2 -0
  131. package/dist/components/MarkdownTable.js.map +1 -0
  132. package/dist/components/MarkdownTable.vue_vue_type_script_setup_true_lang.js +2 -0
  133. package/dist/components/MarkdownTable.vue_vue_type_script_setup_true_lang.js.map +1 -0
  134. package/dist/components/MarkdownText.js +2 -0
  135. package/dist/components/MarkdownText.js.map +1 -0
  136. package/dist/components/MhtViewer.js +2 -0
  137. package/dist/components/MhtViewer.js.map +1 -0
  138. package/dist/components/MhtViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  139. package/dist/components/MhtViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  140. package/dist/components/MindMapView.js +2 -0
  141. package/dist/components/MindMapView.js.map +1 -0
  142. package/dist/components/MindMapView.vue_vue_type_script_setup_true_lang.js +2 -0
  143. package/dist/components/MindMapView.vue_vue_type_script_setup_true_lang.js.map +1 -0
  144. package/dist/components/MissingDependency.js +2 -0
  145. package/dist/components/MissingDependency.js.map +1 -0
  146. package/dist/components/MissingDependency.vue_vue_type_script_setup_true_lang.js +2 -0
  147. package/dist/components/MissingDependency.vue_vue_type_script_setup_true_lang.js.map +1 -0
  148. package/dist/components/ModelViewer.js +2 -0
  149. package/dist/components/ModelViewer.js.map +1 -0
  150. package/dist/components/ModelViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  151. package/dist/components/ModelViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  152. package/dist/components/MsiViewer.js +2 -0
  153. package/dist/components/MsiViewer.js.map +1 -0
  154. package/dist/components/MsiViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  155. package/dist/components/MsiViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  156. package/dist/components/NotebookViewer.js +2 -0
  157. package/dist/components/NotebookViewer.js.map +1 -0
  158. package/dist/components/NotebookViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  159. package/dist/components/NotebookViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  160. package/dist/components/PdfViewer.js +2 -0
  161. package/dist/components/PdfViewer.js.map +1 -0
  162. package/dist/components/PdfViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  163. package/dist/components/PdfViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  164. package/dist/components/PptxNavigationPane.js +9 -0
  165. package/dist/components/PptxNavigationPane.js.map +1 -0
  166. package/dist/components/PptxNavigationPane.vue.d.ts +20 -0
  167. package/dist/components/PptxNavigationPane.vue_vue_type_script_setup_true_lang.js +120 -0
  168. package/dist/components/PptxNavigationPane.vue_vue_type_script_setup_true_lang.js.map +1 -0
  169. package/dist/components/PptxViewer.js +3 -1
  170. package/dist/components/PptxViewer.js.map +1 -0
  171. package/dist/components/PptxViewer.vue_vue_type_script_setup_true_lang.js +71 -39
  172. package/dist/components/PptxViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  173. package/dist/components/PsdViewer.js +2 -0
  174. package/dist/components/PsdViewer.js.map +1 -0
  175. package/dist/components/PsdViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  176. package/dist/components/PsdViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  177. package/dist/components/QmcAudioViewer.js +2 -0
  178. package/dist/components/QmcAudioViewer.js.map +1 -0
  179. package/dist/components/QmcAudioViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  180. package/dist/components/QmcAudioViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  181. package/dist/components/RasterViewer.js +2 -0
  182. package/dist/components/RasterViewer.js.map +1 -0
  183. package/dist/components/RasterViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  184. package/dist/components/RasterViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  185. package/dist/components/RtfViewer.js +2 -0
  186. package/dist/components/RtfViewer.js.map +1 -0
  187. package/dist/components/RtfViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  188. package/dist/components/RtfViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  189. package/dist/components/SevenZipBrowser.js +2 -0
  190. package/dist/components/SevenZipBrowser.js.map +1 -0
  191. package/dist/components/SevenZipBrowser.vue_vue_type_script_setup_true_lang.js +2 -0
  192. package/dist/components/SevenZipBrowser.vue_vue_type_script_setup_true_lang.js.map +1 -0
  193. package/dist/components/SqliteViewer.js +2 -0
  194. package/dist/components/SqliteViewer.js.map +1 -0
  195. package/dist/components/SqliteViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  196. package/dist/components/SqliteViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  197. package/dist/components/SubtitleViewer.js +2 -0
  198. package/dist/components/SubtitleViewer.js.map +1 -0
  199. package/dist/components/SubtitleViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  200. package/dist/components/SubtitleViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  201. package/dist/components/XlsxChart.js +2 -0
  202. package/dist/components/XlsxChart.js.map +1 -0
  203. package/dist/components/XlsxChart.vue_vue_type_script_setup_true_lang.js +2 -0
  204. package/dist/components/XlsxChart.vue_vue_type_script_setup_true_lang.js.map +1 -0
  205. package/dist/components/XlsxViewer.js +3 -1
  206. package/dist/components/XlsxViewer.js.map +1 -0
  207. package/dist/components/XlsxViewer.vue_vue_type_script_setup_true_lang.js +301 -304
  208. package/dist/components/XlsxViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  209. package/dist/components/XmindViewer.js +2 -0
  210. package/dist/components/XmindViewer.js.map +1 -0
  211. package/dist/components/XmindViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  212. package/dist/components/XmindViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  213. package/dist/components/ZipBrowser.js +3 -1
  214. package/dist/components/ZipBrowser.js.map +1 -0
  215. package/dist/components/ZipBrowser.vue.d.ts +3 -1
  216. package/dist/components/ZipBrowser.vue_vue_type_script_setup_true_lang.js +154 -122
  217. package/dist/components/ZipBrowser.vue_vue_type_script_setup_true_lang.js.map +1 -0
  218. package/dist/components/ZoomImage.js +2 -0
  219. package/dist/components/ZoomImage.js.map +1 -0
  220. package/dist/components/ZoomImage.vue_vue_type_script_setup_true_lang.js +2 -0
  221. package/dist/components/ZoomImage.vue_vue_type_script_setup_true_lang.js.map +1 -0
  222. package/dist/components/epl/EplCodeBlock.js +2 -0
  223. package/dist/components/epl/EplCodeBlock.js.map +1 -0
  224. package/dist/components/epl/EplCodeBlock.vue_vue_type_script_setup_true_lang.js +2 -0
  225. package/dist/components/epl/EplCodeBlock.vue_vue_type_script_setup_true_lang.js.map +1 -0
  226. package/dist/components/epl/EplDoc.js +2 -0
  227. package/dist/components/epl/EplDoc.js.map +1 -0
  228. package/dist/components/epl/EplDoc.vue_vue_type_script_setup_true_lang.js +2 -0
  229. package/dist/components/epl/EplDoc.vue_vue_type_script_setup_true_lang.js.map +1 -0
  230. package/dist/components/epl/EplMethod.js +2 -0
  231. package/dist/components/epl/EplMethod.js.map +1 -0
  232. package/dist/components/epl/EplMethod.vue_vue_type_script_setup_true_lang.js +2 -0
  233. package/dist/components/epl/EplMethod.vue_vue_type_script_setup_true_lang.js.map +1 -0
  234. package/dist/components/epl/EplResource.js +2 -0
  235. package/dist/components/epl/EplResource.js.map +1 -0
  236. package/dist/components/epl/EplResource.vue_vue_type_script_setup_true_lang.js +2 -0
  237. package/dist/components/epl/EplResource.vue_vue_type_script_setup_true_lang.js.map +1 -0
  238. package/dist/components/epl/EplTree.js +2 -0
  239. package/dist/components/epl/EplTree.js.map +1 -0
  240. package/dist/components/epl/EplTree.vue_vue_type_script_setup_true_lang.js +2 -0
  241. package/dist/components/epl/EplTree.vue_vue_type_script_setup_true_lang.js.map +1 -0
  242. package/dist/components/epl/EplVarTable.js +2 -0
  243. package/dist/components/epl/EplVarTable.js.map +1 -0
  244. package/dist/components/epl/EplVarTable.vue_vue_type_script_setup_true_lang.js +2 -0
  245. package/dist/components/epl/EplVarTable.vue_vue_type_script_setup_true_lang.js.map +1 -0
  246. package/dist/components/epl/numbering.js +2 -0
  247. package/dist/components/epl/numbering.js.map +1 -0
  248. package/dist/components/icons/Icon.js +2 -0
  249. package/dist/components/icons/Icon.js.map +1 -0
  250. package/dist/components/icons/Icon.vue_vue_type_script_setup_true_lang.js +2 -0
  251. package/dist/components/icons/Icon.vue_vue_type_script_setup_true_lang.js.map +1 -0
  252. package/dist/components/icons/iconPaths.js +2 -0
  253. package/dist/components/icons/iconPaths.js.map +1 -0
  254. package/dist/components/optionalViewer.js +2 -0
  255. package/dist/components/optionalViewer.js.map +1 -0
  256. package/dist/components/ui/ClampBlock.js +2 -0
  257. package/dist/components/ui/ClampBlock.js.map +1 -0
  258. package/dist/composables/useElementNavigation.d.ts +21 -0
  259. package/dist/composables/useElementNavigation.js +63 -0
  260. package/dist/composables/useElementNavigation.js.map +1 -0
  261. package/dist/composables/useFileViewer.js +2 -0
  262. package/dist/composables/useFileViewer.js.map +1 -0
  263. package/dist/composables/useLightbox.js +2 -0
  264. package/dist/composables/useLightbox.js.map +1 -0
  265. package/dist/composables/useLogRules.js +2 -0
  266. package/dist/composables/useLogRules.js.map +1 -0
  267. package/dist/lib/aes.js +2 -0
  268. package/dist/lib/aes.js.map +1 -0
  269. package/dist/lib/appx.js +2 -0
  270. package/dist/lib/appx.js.map +1 -0
  271. package/dist/lib/archiveHtml.d.ts +49 -0
  272. package/dist/lib/archiveHtml.js +377 -0
  273. package/dist/lib/archiveHtml.js.map +1 -0
  274. package/dist/lib/asn1.js +2 -0
  275. package/dist/lib/asn1.js.map +1 -0
  276. package/dist/lib/binobj.js +2 -0
  277. package/dist/lib/binobj.js.map +1 -0
  278. package/dist/lib/brotli.js +2 -0
  279. package/dist/lib/brotli.js.map +1 -0
  280. package/dist/lib/bzip2.js +2 -0
  281. package/dist/lib/bzip2.js.map +1 -0
  282. package/dist/lib/classfile.js +2 -0
  283. package/dist/lib/classfile.js.map +1 -0
  284. package/dist/lib/codePreview.js +2 -0
  285. package/dist/lib/codePreview.js.map +1 -0
  286. package/dist/lib/codefold.js +2 -0
  287. package/dist/lib/codefold.js.map +1 -0
  288. package/dist/lib/codeformat.js +2 -0
  289. package/dist/lib/codeformat.js.map +1 -0
  290. package/dist/lib/csv.js +2 -0
  291. package/dist/lib/csv.js.map +1 -0
  292. package/dist/lib/des.js +2 -0
  293. package/dist/lib/des.js.map +1 -0
  294. package/dist/lib/diagram.js +2 -0
  295. package/dist/lib/diagram.js.map +1 -0
  296. package/dist/lib/dicom.js +2 -0
  297. package/dist/lib/dicom.js.map +1 -0
  298. package/dist/lib/dicomCodecs.js +2 -0
  299. package/dist/lib/dicomCodecs.js.map +1 -0
  300. package/dist/lib/dicomRender.js +2 -0
  301. package/dist/lib/dicomRender.js.map +1 -0
  302. package/dist/lib/docxNavigation.d.ts +31 -0
  303. package/dist/lib/docxNavigation.js +65 -0
  304. package/dist/lib/docxNavigation.js.map +1 -0
  305. package/dist/lib/dxf.js +2 -0
  306. package/dist/lib/dxf.js.map +1 -0
  307. package/dist/lib/eml.js +2 -0
  308. package/dist/lib/eml.js.map +1 -0
  309. package/dist/lib/encoding.js +2 -0
  310. package/dist/lib/encoding.js.map +1 -0
  311. package/dist/lib/epl/code/codeDataParser.js +2 -0
  312. package/dist/lib/epl/code/codeDataParser.js.map +1 -0
  313. package/dist/lib/epl/code/codeLines.js +2 -0
  314. package/dist/lib/epl/code/codeLines.js.map +1 -0
  315. package/dist/lib/epl/code/textCode.js +2 -0
  316. package/dist/lib/epl/code/textCode.js.map +1 -0
  317. package/dist/lib/epl/eplDocument.js +2 -0
  318. package/dist/lib/epl/eplDocument.js.map +1 -0
  319. package/dist/lib/epl/imageList.js +2 -0
  320. package/dist/lib/epl/imageList.js.map +1 -0
  321. package/dist/lib/epl/index.js +2 -0
  322. package/dist/lib/epl/index.js.map +1 -0
  323. package/dist/lib/epl/io/binaryReader.js +2 -0
  324. package/dist/lib/epl/io/binaryReader.js.map +1 -0
  325. package/dist/lib/epl/io/encoding.js +2 -0
  326. package/dist/lib/epl/io/encoding.js.map +1 -0
  327. package/dist/lib/epl/model/eplSystemId.js +2 -0
  328. package/dist/lib/epl/model/eplSystemId.js.map +1 -0
  329. package/dist/lib/epl/names/eplLibData.js +2 -0
  330. package/dist/lib/epl/names/eplLibData.js.map +1 -0
  331. package/dist/lib/epl/names/idToNameMap.js +2 -0
  332. package/dist/lib/epl/names/idToNameMap.js.map +1 -0
  333. package/dist/lib/epl/names/libNameProvider.js +2 -0
  334. package/dist/lib/epl/names/libNameProvider.js.map +1 -0
  335. package/dist/lib/epl/program.js +2 -0
  336. package/dist/lib/epl/program.js.map +1 -0
  337. package/dist/lib/epl/projectFileReader.js +2 -0
  338. package/dist/lib/epl/projectFileReader.js.map +1 -0
  339. package/dist/lib/fb2.js +2 -0
  340. package/dist/lib/fb2.js.map +1 -0
  341. package/dist/lib/fileType.js +2 -0
  342. package/dist/lib/fileType.js.map +1 -0
  343. package/dist/lib/fonts.js +2 -0
  344. package/dist/lib/fonts.js.map +1 -0
  345. package/dist/lib/format.js +2 -0
  346. package/dist/lib/format.js.map +1 -0
  347. package/dist/lib/frontmatter.js +2 -0
  348. package/dist/lib/frontmatter.js.map +1 -0
  349. package/dist/lib/geo.js +2 -0
  350. package/dist/lib/geo.js.map +1 -0
  351. package/dist/lib/har.js +2 -0
  352. package/dist/lib/har.js.map +1 -0
  353. package/dist/lib/highlight.js +2 -0
  354. package/dist/lib/highlight.js.map +1 -0
  355. package/dist/lib/highlightLangs.js +2 -0
  356. package/dist/lib/highlightLangs.js.map +1 -0
  357. package/dist/lib/hprof.js +2 -0
  358. package/dist/lib/hprof.js.map +1 -0
  359. package/dist/lib/ipynb.js +2 -0
  360. package/dist/lib/ipynb.js.map +1 -0
  361. package/dist/lib/jks.js +2 -0
  362. package/dist/lib/jks.js.map +1 -0
  363. package/dist/lib/jsonl.js +2 -0
  364. package/dist/lib/jsonl.js.map +1 -0
  365. package/dist/lib/lrc.js +2 -0
  366. package/dist/lib/lrc.js.map +1 -0
  367. package/dist/lib/lzma.js +2 -0
  368. package/dist/lib/lzma.js.map +1 -0
  369. package/dist/lib/markdown/blocks.js +2 -0
  370. package/dist/lib/markdown/blocks.js.map +1 -0
  371. package/dist/lib/markdown/inline.js +2 -0
  372. package/dist/lib/markdown/inline.js.map +1 -0
  373. package/dist/lib/markdown/math.js +2 -0
  374. package/dist/lib/markdown/math.js.map +1 -0
  375. package/dist/lib/markdown/segmentize.js +2 -0
  376. package/dist/lib/markdown/segmentize.js.map +1 -0
  377. package/dist/lib/markdown/styles.js +2 -0
  378. package/dist/lib/markdown/styles.js.map +1 -0
  379. package/dist/lib/mht.js +2 -0
  380. package/dist/lib/mht.js.map +1 -0
  381. package/dist/lib/midi.js +2 -0
  382. package/dist/lib/midi.js.map +1 -0
  383. package/dist/lib/mime.js +2 -0
  384. package/dist/lib/mime.js.map +1 -0
  385. package/dist/lib/mindmap.js +2 -0
  386. package/dist/lib/mindmap.js.map +1 -0
  387. package/dist/lib/mobi.js +2 -0
  388. package/dist/lib/mobi.js.map +1 -0
  389. package/dist/lib/msi.js +2 -0
  390. package/dist/lib/msi.js.map +1 -0
  391. package/dist/lib/optionalDep.js +2 -0
  392. package/dist/lib/optionalDep.js.map +1 -0
  393. package/dist/lib/pkcs12.js +2 -0
  394. package/dist/lib/pkcs12.js.map +1 -0
  395. package/dist/lib/pptxNavigation.d.ts +7 -0
  396. package/dist/lib/pptxNavigation.js +29 -0
  397. package/dist/lib/pptxNavigation.js.map +1 -0
  398. package/dist/lib/qmc.js +2 -0
  399. package/dist/lib/qmc.js.map +1 -0
  400. package/dist/lib/rar.js +2 -0
  401. package/dist/lib/rar.js.map +1 -0
  402. package/dist/lib/rawPreview.js +2 -0
  403. package/dist/lib/rawPreview.js.map +1 -0
  404. package/dist/lib/rc2.js +2 -0
  405. package/dist/lib/rc2.js.map +1 -0
  406. package/dist/lib/resolveInput.js +2 -0
  407. package/dist/lib/resolveInput.js.map +1 -0
  408. package/dist/lib/rtf.js +2 -0
  409. package/dist/lib/rtf.js.map +1 -0
  410. package/dist/lib/sevenZip.js +2 -0
  411. package/dist/lib/sevenZip.js.map +1 -0
  412. package/dist/lib/sha1.js +2 -0
  413. package/dist/lib/sha1.js.map +1 -0
  414. package/dist/lib/sha256.js +2 -0
  415. package/dist/lib/sha256.js.map +1 -0
  416. package/dist/lib/speechAudio.js +2 -0
  417. package/dist/lib/speechAudio.js.map +1 -0
  418. package/dist/lib/sqlite.js +2 -0
  419. package/dist/lib/sqlite.js.map +1 -0
  420. package/dist/lib/subtitle.js +2 -0
  421. package/dist/lib/subtitle.js.map +1 -0
  422. package/dist/lib/tarball.js +2 -0
  423. package/dist/lib/tarball.js.map +1 -0
  424. package/dist/lib/viewerFormats.js +2 -0
  425. package/dist/lib/viewerFormats.js.map +1 -0
  426. package/dist/lib/viewerKind.js +2 -0
  427. package/dist/lib/viewerKind.js.map +1 -0
  428. package/dist/lib/x509.js +2 -0
  429. package/dist/lib/x509.js.map +1 -0
  430. package/dist/lib/xlsx.js +2 -0
  431. package/dist/lib/xlsx.js.map +1 -0
  432. package/dist/lib/xlsxCharts.js +2 -0
  433. package/dist/lib/xlsxCharts.js.map +1 -0
  434. package/dist/lib/xmind.js +2 -0
  435. package/dist/lib/xmind.js.map +1 -0
  436. package/dist/lib/zip.js +2 -0
  437. package/dist/lib/zip.js.map +1 -0
  438. package/dist/style.css +1 -1
  439. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xlsx.js","names":[],"sources":["../../src/lib/xlsx.ts"],"sourcesContent":["/**\n * In-browser `.xlsx` (and `.xlsm`) parsing for the side viewer's spreadsheet preview.\n *\n * exceljs does the OOXML heavy lifting (unzip + parse the SpreadsheetML); here we flatten one of its\n * Workbooks into a small, serializable model the {@link XlsxViewer} renders as plain HTML `<table>`s —\n * one table per worksheet, with merged cells, column widths, and the common cell styling (bold/italic/\n * color/fill/alignment/borders) carried over so the preview reads like the original sheet.\n *\n * exceljs is heavy (~1MB), so this module is only ever imported by the async-loaded XlsxViewer — it never\n * lands in the main bundle. We import the namespace (not named exports) because exceljs's browser entry is\n * a UMD bundle: `new ExcelJS.Workbook()` resolves identically under Vite's CJS interop and the .d.ts.\n */\nimport * as ExcelJS from 'exceljs'\nimport { format as nfFormat, isDateFormat as nfIsDateFormat } from 'numfmt'\n\n/** One rendered cell. A cell covered by a merge is dropped from the row entirely (see {@link XlsxRow}). */\nexport interface XlsxCell {\n text: string\n rowSpan: number\n colSpan: number\n /** 1-based column index of this cell's left edge — lets the renderer place cells after merge gaps. */\n col: number\n bold?: boolean\n italic?: boolean\n underline?: boolean\n strike?: boolean\n /** Font size in px (converted from the workbook's points), or undefined to use the table default. */\n fontSize?: number\n /** The cell's formula expression WITHOUT a leading `=` (e.g. `数据基表!B10`, `#REF!`), for the source view. */\n formula?: string\n /** CSS color for the text / the cell background, derived from the workbook's ARGB colors. */\n color?: string\n bg?: string\n align?: 'left' | 'center' | 'right'\n valign?: 'top' | 'middle' | 'bottom'\n wrap?: boolean\n /** Which borders the cell draws (true = a visible edge in the source). */\n bt?: boolean\n br?: boolean\n bb?: boolean\n bl?: boolean\n}\n\nexport interface XlsxRow {\n /** 1-based row number in the worksheet (so the viewer can label the gutter and key frozen/hidden state). */\n num: number\n /** Row height in px (converted from Excel points), or undefined to size to content. */\n height?: number\n /** Hidden in the source (\"hide rows\") — the viewer collapses it behind an expander, like Excel/WPS. */\n hidden?: boolean\n /** Only the cells that actually render — merge-covered slots are omitted; use {@link XlsxCell.col}. */\n cells: XlsxCell[]\n}\n\nexport interface XlsxSheet {\n name: string\n /** Per-column width in px (index 0 = column A); columns past this use a default width. */\n colWidths: number[]\n /** Per-column hidden flag (index 0 = column A) — collapsed behind an expander, like Excel/WPS. */\n colHidden: boolean[]\n rows: XlsxRow[]\n cols: number\n /** Frozen pane sizes (Excel \"freeze panes\"): the first N rows / M columns stay pinned while scrolling. */\n frozenRows: number\n frozenCols: number\n}\n\nexport interface XlsxModel {\n sheets: XlsxSheet[]\n}\n\n// Guardrails: a corrupt or absurdly large sheet shouldn't lock up the tab. We cap the rendered range and\n// let the viewer note the truncation. (Real attachments are tiny; these only bite pathological files.)\nconst MAX_ROWS = 2000\nconst MAX_COLS = 200\n\n// Excel column-letter (A, B, …, AA) → 1-based index.\nfunction colToNum(s: string): number {\n let n = 0\n for (let i = 0; i < s.length; i++) n = n * 26 + (s.charCodeAt(i) - 64)\n return n\n}\n\n// 1-based index → Excel column-letter (1→A, 26→Z, 27→AA). Used by the viewer's A/B/C… header row.\nexport function numToCol(n: number): string {\n let s = ''\n while (n > 0) {\n const m = (n - 1) % 26\n s = String.fromCharCode(65 + m) + s\n n = Math.floor((n - 1) / 26)\n }\n return s\n}\n\ninterface Span {\n rowSpan: number\n colSpan: number\n}\n\n// Parse exceljs's merge ranges (\"A1:B2\") into: span info keyed at each master cell, and a set of the\n// addresses (`r,c`) covered by a merge (which we then skip rendering).\nfunction parseMerges(merges: string[]): { spans: Map<string, Span>; covered: Set<string> } {\n const spans = new Map<string, Span>()\n const covered = new Set<string>()\n for (const range of merges) {\n const m = /^([A-Z]+)(\\d+):([A-Z]+)(\\d+)$/.exec(range)\n if (!m) continue\n const c1 = colToNum(m[1])\n const r1 = parseInt(m[2], 10)\n const c2 = colToNum(m[3])\n const r2 = parseInt(m[4], 10)\n const top = Math.min(r1, r2)\n const bottom = Math.max(r1, r2)\n const left = Math.min(c1, c2)\n const right = Math.max(c1, c2)\n spans.set(`${top},${left}`, { rowSpan: bottom - top + 1, colSpan: right - left + 1 })\n for (let r = top; r <= bottom; r++) {\n for (let c = left; c <= right; c++) {\n if (r === top && c === left) continue\n covered.add(`${r},${c}`)\n }\n }\n }\n return { spans, covered }\n}\n\n// Excel's legacy 56-colour indexed palette (BIFF8). Cells/fonts that don't carry an explicit ARGB reference\n// a palette slot instead (e.g. `{ indexed: 47 }`) — very common in older workbooks. 64/65 are the system\n// foreground/background (\"automatic\"), handled specially below.\n// prettier-ignore\nconst INDEXED_COLORS = [\n '000000', 'FFFFFF', 'FF0000', '00FF00', '0000FF', 'FFFF00', 'FF00FF', '00FFFF',\n '000000', 'FFFFFF', 'FF0000', '00FF00', '0000FF', 'FFFF00', 'FF00FF', '00FFFF',\n '800000', '008000', '000080', '808000', '800080', '008080', 'C0C0C0', '808080',\n '9999FF', '993366', 'FFFFCC', 'CCFFFF', '660066', 'FF8080', '0066CC', 'CCCCFF',\n '000080', 'FF00FF', 'FFFF00', '00FFFF', '800080', '800000', '008080', '0000FF',\n '00CCFF', 'CCFFFF', 'CCFFCC', 'FFFF99', '99CCFF', 'FF99CC', 'CC99FF', 'FFCC99',\n '3366FF', '33CCCC', '99CC00', 'FFCC00', 'FF9900', 'FF6600', '666699', '969696',\n '003366', '339966', '003300', '333300', '993300', '993366', '333399', '333333',\n]\n\n// Default Office theme colours, in the order the styles `theme` attribute indexes them (0=bg1/white,\n// 1=text1/black, 2=bg2, 3=text2, 4..9=accent1..6, 10=hlink, 11=folHlink). We don't parse the workbook's\n// actual theme XML (exceljs doesn't surface it), so this default scheme is a best-effort — but it gets the\n// common cases right (notably theme 1 = black text, theme 0 = white) and `tint` is applied on top.\n// prettier-ignore\nconst THEME_COLORS = [\n 'FFFFFF', '000000', 'E7E6E6', '44546A', '4472C4', 'ED7D31',\n 'A5A5A5', 'FFC000', '5B9BD5', '70AD47', '0563C1', '954F72',\n]\n\nfunction rgbToHsl(r: number, g: number, b: number): [number, number, number] {\n r /= 255\n g /= 255\n b /= 255\n const max = Math.max(r, g, b)\n const min = Math.min(r, g, b)\n let h = 0\n let s = 0\n const l = (max + min) / 2\n if (max !== min) {\n const d = max - min\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min)\n if (max === r) h = (g - b) / d + (g < b ? 6 : 0)\n else if (max === g) h = (b - r) / d + 2\n else h = (r - g) / d + 4\n h /= 6\n }\n return [h, s, l]\n}\n\nfunction hue2rgb(p: number, q: number, t: number): number {\n if (t < 0) t += 1\n if (t > 1) t -= 1\n if (t < 1 / 6) return p + (q - p) * 6 * t\n if (t < 1 / 2) return q\n if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6\n return p\n}\n\nfunction hslToRgb(h: number, s: number, l: number): [number, number, number] {\n if (s === 0) {\n const v = Math.round(l * 255)\n return [v, v, v]\n }\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s\n const p = 2 * l - q\n return [\n Math.round(hue2rgb(p, q, h + 1 / 3) * 255),\n Math.round(hue2rgb(p, q, h) * 255),\n Math.round(hue2rgb(p, q, h - 1 / 3) * 255),\n ]\n}\n\n// Excel applies `tint` to a theme/indexed colour by shifting its HSL luminance: negative darkens, positive\n// lightens. Mirrors the algorithm in the OOXML spec so shaded theme fills come out the right tone.\nfunction applyTint(hex: string, tint: number): string {\n const r = parseInt(hex.slice(0, 2), 16)\n const g = parseInt(hex.slice(2, 4), 16)\n const b = parseInt(hex.slice(4, 6), 16)\n const [h, s, l0] = rgbToHsl(r, g, b)\n let l = tint < 0 ? l0 * (1 + tint) : l0 * (1 - tint) + tint\n l = Math.max(0, Math.min(1, l))\n const [nr, ng, nb] = hslToRgb(h, s, l)\n const hx = (n: number): string => n.toString(16).padStart(2, '0')\n return hx(nr) + hx(ng) + hx(nb)\n}\n\n/**\n * Resolve any exceljs colour object to a CSS `#RRGGBB`, covering all three references Excel uses: explicit\n * `argb`, the legacy `indexed` palette, and `theme` index (+ optional `tint`). Returns undefined for \"no\n * colour\" — a fully-transparent argb, the system-automatic indices, or an unresolvable shape.\n */\nfunction colorToCss(color: unknown): string | undefined {\n if (!color || typeof color !== 'object') return undefined\n const c = color as { argb?: string; theme?: number; indexed?: number; tint?: number }\n let hex: string | undefined\n if (typeof c.argb === 'string') {\n if (c.argb.length === 8) {\n if (c.argb.slice(0, 2).toLowerCase() === '00') return undefined // fully transparent → no colour\n hex = c.argb.slice(2)\n } else if (c.argb.length === 6) {\n hex = c.argb\n }\n } else if (typeof c.theme === 'number') {\n hex = THEME_COLORS[c.theme]\n } else if (typeof c.indexed === 'number') {\n if (c.indexed === 64) return undefined // system foreground / automatic → let the default apply\n hex = c.indexed === 65 ? 'FFFFFF' : INDEXED_COLORS[c.indexed]\n }\n if (!hex || !/^[0-9a-fA-F]{6}$/.test(hex)) return undefined\n if (typeof c.tint === 'number' && c.tint !== 0) hex = applyTint(hex, c.tint)\n return `#${hex}`\n}\n\n// Excel font sizes are in points; CSS wants px. The conventional screen conversion is pt × 96/72 (= ×4/3),\n// which keeps relative sizing faithful (a 24pt title reads clearly larger than 10pt body text).\nfunction fontSizeToPx(size: number | undefined): number | undefined {\n if (!size || size <= 0) return undefined\n return Math.round((size * 4) / 3)\n}\n\n// Excel column width is in \"character\" units; the conventional pixel conversion to the COLUMN's total width is\n// width*7 + 5 (the +5 is Excel's own internal cell padding). But our HTML cell adds its OWN padding (~4px each\n// side) and a gridline border on top of the `<col>` width, so reusing Excel's total width would leave the\n// content area ~8px short and clip text into \"…\". We add that HTML chrome back (+9 instead of +5) so the\n// usable content width matches Excel's, keeping the cell `padding`/border in sync (see XlsxViewer .xv__cell).\nfunction colWidthToPx(w: number | undefined): number {\n if (!w || w <= 0) return 80\n return Math.round(w * 7 + 9)\n}\n\n// A two-digit zero-pad for the date formatter.\nfunction pad2(n: number): string {\n return n < 10 ? `0${n}` : String(n)\n}\n\n// Render a Date the way a spreadsheet preview should — `YYYY-MM-DD`, plus a `HH:MM[:SS]` tail only when the\n// value carries a time-of-day. (exceljs's own `cell.text` gives the raw JS `Date.toString()`, e.g.\n// \"Sat May 04 2019 08:00:00 GMT+0800 (中国标准时间)\", which is useless in a cell.)\nfunction formatDate(d: Date): string {\n const date = `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`\n const h = d.getHours()\n const mi = d.getMinutes()\n const s = d.getSeconds()\n if (!h && !mi && !s) return date\n return `${date} ${pad2(h)}:${pad2(mi)}${s ? `:${pad2(s)}` : ''}`\n}\n\nfunction richTextToString(runs: unknown): string {\n if (!Array.isArray(runs)) return ''\n return runs\n .map((r) => (r && typeof r === 'object' ? ((r as { text?: string }).text ?? '') : ''))\n .join('')\n}\n\n// CJK numeral digits/units for Excel's `[DBNum1]` (中文小写) and `[DBNum2]` (中文大写/financial) — numfmt does\n// not implement these (Excel's 特殊 → 中文数字), so we convert the integer ourselves with proper 万/亿 grouping.\nconst DBNUM_DIGITS = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']\nconst DBNUM_DIGITS_UP = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']\nconst DBNUM_UNITS = ['', '十', '百', '千']\nconst DBNUM_UNITS_UP = ['', '拾', '佰', '仟']\nconst DBNUM_BIG = ['', '万', '亿', '兆']\n\n// Convert one 0..9999 group to CJK numerals, collapsing internal zeros to a single 零 (no trailing zero unit).\nfunction dbNumGroup(n: number, digits: string[], units: string[]): string {\n let s = ''\n let pendingZero = false\n for (let i = 3; i >= 0; i--) {\n const x = Math.floor(n / 10 ** i) % 10\n if (x === 0) {\n if (s !== '') pendingZero = true\n } else {\n if (pendingZero) {\n s += digits[0]\n pendingZero = false\n }\n s += digits[x] + units[i]\n }\n }\n return s\n}\n\n// Excel `[DBNum1]`/`[DBNum2]` of a non-negative integer: e.g. 1234 → 一千二百三十四 / 壹仟贰佰叁拾肆, 10001 → 一万零一,\n// 100000001 → 一亿零一. (Keeps Excel's leading 一十 for 10-19, single 零 between groups, like Excel's own output.)\nfunction toChineseNumeral(n: number, upper: boolean): string {\n const digits = upper ? DBNUM_DIGITS_UP : DBNUM_DIGITS\n const units = upper ? DBNUM_UNITS_UP : DBNUM_UNITS\n if (n === 0) return digits[0]\n const groups: number[] = []\n let x = n\n while (x > 0) {\n groups.push(x % 10000)\n x = Math.floor(x / 10000)\n }\n let s = ''\n for (let i = groups.length - 1; i >= 0; i--) {\n const g = groups[i]\n if (g === 0) continue // an all-zero group: the next non-zero group's leading 零 covers the gap\n let gs = dbNumGroup(g, digits, units)\n if (i < groups.length - 1 && g < 1000) gs = digits[0] + gs // 1,0001 → 一万零一 (zero after a higher group)\n s += gs + DBNUM_BIG[i]\n }\n return s\n}\n\n// Map ASCII digits to full-width — Excel's `[DBNum3]` (全角数字); applied over numfmt's normal output so any\n// separators / decimals survive.\nfunction toFullWidthDigits(s: string): string {\n return s.replace(/[0-9]/g, (d) => '0123456789'[Number(d)])\n}\n\n// Honor Excel's `[DBNumN]` CJK-numeral prefixes that numfmt can't render. Returns null to fall back to numfmt\n// (negatives / non-integers for DBNum1/2, where Excel's behavior is fiddly — a plain number is safer than a guess).\nfunction formatDbNum(value: number, n: number, fmt: string): string | null {\n if (n === 3) {\n try {\n const out = nfFormat(fmt, value) // numfmt strips the [DBNum3] tag and formats the rest\n if (typeof out === 'string') return toFullWidthDigits(out)\n } catch {\n /* fall through */\n }\n return null\n }\n if (Number.isInteger(value) && value >= 0) return toChineseNumeral(value, n === 2)\n return null\n}\n\n// numfmt understands the English \"General\" keyword but not Excel's LOCALIZED one (Simplified Chinese \"G/通用格式\",\n// Japanese \"G/標準\", etc.), throwing \"Invalid pattern\" — normalize those to \"General\" so a locale-tagged General\n// format (common in CJK files after a [DBNum]/[$-…] prefix) parses. (Plain \"[$-NNN]\" locale tags numfmt handles.)\nfunction cleanFmt(fmt: string): string {\n return fmt.replace(/G\\/(通用格式|標準|标准|표준)/g, 'General')\n}\n\n// Apply the cell's Excel number format (`cell.numFmt`) to a numeric value the way Excel DISPLAYS it — exceljs's\n// `cell.text` returns the raw stored number, so an integer-formatted cell (\"0\") shows the stored float\n// \"2.9999999999\" instead of \"3\", a percent format shows \"0.5\" instead of \"50%\", thousands separators go missing,\n// etc. An undefined format → \"General\", which (like Excel) also strips IEEE float noise (0.1+0.2 → \"0.3\"); this is\n// why a cell *referencing* a formatted one rendered wrong too — its cached result is the noisy float. numfmt covers\n// currency / accounting / fraction / scientific / percent / text(@) / 邮编 / custom codes; `[DBNumN]` CJK numerals\n// (which numfmt doesn't implement) are handled here. Unsupported codes / unexpected output fall back to a plain\n// string, never throwing.\nfunction formatNumber(value: number, numFmt: string | undefined): string {\n const fmt = cleanFmt(numFmt || 'General')\n const dbnum = /\\[DBNum([123])\\]/.exec(fmt)\n if (dbnum) {\n const out = formatDbNum(value, Number(dbnum[1]), fmt)\n if (out != null) return out\n }\n try {\n const out = nfFormat(fmt, value)\n return typeof out === 'string' ? out : String(value)\n } catch {\n return String(value)\n }\n}\n\n// Format a date the way Excel's number format dictates — exceljs hands us a JS `Date`, and numfmt formats it\n// directly (reading its local components) for any date/time format code: ISO, 中文 yyyy\"年\"m\"月\"d\"日\", h:mm AM/PM,\n// custom date-times, etc. Only route through numfmt when the format actually IS a date format; otherwise (no/General\n// format) keep the viewer's plain YYYY-MM-DD default from {@link formatDate}.\nfunction formatDateValue(d: Date, numFmt: string | undefined): string {\n if (numFmt && numFmt !== 'General' && nfIsDateFormat(numFmt)) {\n try {\n const out = nfFormat(numFmt, d)\n if (typeof out === 'string' && out !== '') return out\n } catch {\n /* fall through to the plain default */\n }\n }\n return formatDate(d)\n}\n\n/**\n * Resolve a cell's display text from its value SHAPE rather than exceljs's `cell.text` — which returns the\n * raw object for some value kinds (so a formula whose cached result is an error renders as \"[object Object]\")\n * and even throws on certain merged cells. We cover every {@link ExcelJS.ValueType}: numbers/strings/booleans\n * verbatim, dates formatted, rich text joined, hyperlinks as their label, formula results unwrapped (errors →\n * their code like \"#REF!\", a nested date/rich-text result resolved), and error cells as their code. Anything\n * unexpected falls back to a guarded `cell.text`, never to a stringified object.\n */\nfunction cellText(cell: ExcelJS.Cell): string {\n const v = cell.value as unknown\n if (v == null) return ''\n if (typeof v === 'number') return formatNumber(v, cell.numFmt)\n if (typeof v === 'string' || typeof v === 'boolean') return String(v)\n if (v instanceof Date) return formatDateValue(v, cell.numFmt)\n if (typeof v === 'object') {\n const o = v as Record<string, unknown>\n if (typeof o.error === 'string') return o.error // error cell: { error: '#DIV/0!' }\n if (Array.isArray(o.richText)) return richTextToString(o.richText) // rich text\n if ('hyperlink' in o) {\n // hyperlink: { text, hyperlink } — text may itself be rich text\n const t = o.text\n if (Array.isArray((t as { richText?: unknown })?.richText)) {\n return richTextToString((t as { richText?: unknown }).richText)\n }\n return t == null ? String(o.hyperlink) : String(t)\n }\n if ('result' in o || 'formula' in o || 'sharedFormula' in o) {\n // formula: { formula, result } — the result is what Excel shows in the cell\n const res = o.result as unknown\n if (res == null) return ''\n if (typeof res === 'number') return formatNumber(res, cell.numFmt)\n if (typeof res === 'string' || typeof res === 'boolean') return String(res)\n if (res instanceof Date) return formatDateValue(res, cell.numFmt)\n if (res && typeof res === 'object') {\n const ro = res as Record<string, unknown>\n if (typeof ro.error === 'string') return ro.error // formula result is an error → its code\n if (Array.isArray(ro.richText)) return richTextToString(ro.richText)\n }\n return ''\n }\n }\n // Unknown shape: try exceljs's own text, but never surface a stringified object (and never throw).\n try {\n const t = cell.text\n return t != null && t !== '[object Object]' ? String(t) : ''\n } catch {\n return ''\n }\n}\n\n// Numbers and dates align right by default in Excel (text aligns left). Mirror that when the cell has no\n// explicit horizontal alignment — including formula cells whose cached result is a number or date.\nfunction defaultRight(value: unknown): boolean {\n if (typeof value === 'number') return true\n if (value instanceof Date) return true\n if (value && typeof value === 'object' && 'result' in value) {\n const res = (value as { result?: unknown }).result\n return typeof res === 'number' || res instanceof Date\n }\n return false\n}\n\nfunction buildSheet(ws: ExcelJS.Worksheet): XlsxSheet {\n const merges = Array.isArray(ws.model?.merges) ? (ws.model.merges as string[]) : []\n const { spans, covered } = parseMerges(merges)\n\n const cols = Math.min(ws.columnCount || 0, MAX_COLS)\n const rowCount = Math.min(ws.rowCount || 0, MAX_ROWS)\n\n const colWidths: number[] = []\n const colHidden: boolean[] = []\n for (let c = 1; c <= cols; c++) {\n const col = ws.getColumn(c)\n colWidths.push(colWidthToPx(col?.width))\n colHidden.push(!!col?.hidden)\n }\n\n const rows: XlsxRow[] = []\n for (let r = 1; r <= rowCount; r++) {\n const row = ws.getRow(r)\n const cells: XlsxCell[] = []\n for (let c = 1; c <= cols; c++) {\n if (covered.has(`${r},${c}`)) continue\n const cell = row.getCell(c)\n const span = spans.get(`${r},${c}`)\n const text = cellText(cell)\n // Formula source (without leading `=`): regular cells carry `{ formula }`, shared-formula dependents\n // carry `{ sharedFormula }` (exceljs's per-cell expression). Read from the value shape to avoid the\n // `.formula` getter's side effects.\n let formula: string | undefined\n const cv = cell.value as unknown\n if (cv && typeof cv === 'object') {\n const o = cv as Record<string, unknown>\n if (typeof o.formula === 'string' && o.formula) formula = o.formula\n else if (typeof o.sharedFormula === 'string' && o.sharedFormula) formula = o.sharedFormula\n }\n // Skip truly empty, unstyled, unmerged cells but still emit a placeholder so columns line up — we do\n // that by always pushing a cell (with its `col`), letting the renderer position via colSpan gaps.\n const font = cell.font || {}\n const align = cell.alignment || {}\n const border = cell.border || {}\n const horizontal =\n align.horizontal === 'center' || align.horizontal === 'centerContinuous'\n ? 'center'\n : align.horizontal === 'right'\n ? 'right'\n : align.horizontal === 'left'\n ? 'left'\n : defaultRight(cell.value)\n ? 'right'\n : undefined\n const vertical =\n align.vertical === 'top'\n ? 'top'\n : align.vertical === 'bottom'\n ? 'bottom'\n : align.vertical === 'middle'\n ? 'middle'\n : undefined\n cells.push({\n text,\n col: c,\n rowSpan: span?.rowSpan ?? 1,\n colSpan: span?.colSpan ?? 1,\n bold: font.bold || undefined,\n italic: font.italic || undefined,\n underline: !!font.underline || undefined,\n strike: font.strike || undefined,\n fontSize: fontSizeToPx(font.size),\n formula,\n color: colorToCss(font.color),\n bg:\n cell.fill && cell.fill.type === 'pattern'\n ? colorToCss((cell.fill as { fgColor?: unknown }).fgColor)\n : undefined,\n align: horizontal,\n valign: vertical,\n wrap: align.wrapText || undefined,\n bt: !!border.top?.style || undefined,\n br: !!border.right?.style || undefined,\n bb: !!border.bottom?.style || undefined,\n bl: !!border.left?.style || undefined,\n })\n }\n rows.push({\n num: r,\n height: row.height ? Math.round((row.height * 4) / 3) : undefined,\n hidden: !!row.hidden,\n cells,\n })\n }\n\n // Freeze panes: exceljs surfaces the active view as { state:'frozen', xSplit, ySplit } where xSplit/ySplit\n // are the counts of columns/rows held fixed. Clamp to the rendered range so a stale split can't pin offscreen.\n const view = Array.isArray(ws.views) ? ws.views[0] : undefined\n const frozen = view && (view as { state?: string }).state === 'frozen' ? view : undefined\n const frozenCols = frozen\n ? Math.min(Math.max(0, (frozen as { xSplit?: number }).xSplit ?? 0), cols)\n : 0\n const frozenRows = frozen\n ? Math.min(Math.max(0, (frozen as { ySplit?: number }).ySplit ?? 0), rowCount)\n : 0\n\n return { name: ws.name || `Sheet`, colWidths, colHidden, rows, cols, frozenRows, frozenCols }\n}\n\n/** Parse `.xlsx` bytes into the render model. Throws on a non-spreadsheet / corrupt file. */\nexport async function parseXlsx(buf: ArrayBuffer): Promise<XlsxModel> {\n const wb = new ExcelJS.Workbook()\n await wb.xlsx.load(buf)\n const sheets = wb.worksheets\n // Hidden sheets (state 'hidden'/'veryHidden') aren't shown in Excel's tab bar; skip them too.\n .filter((ws) => ws && ws.state !== 'hidden' && ws.state !== 'veryHidden')\n .map(buildSheet)\n if (sheets.length === 0) throw new Error('工作簿中没有可显示的工作表')\n return { sheets }\n}\n"],"mappings":";;;AAyEA,IAAM,IAAW,KACX,IAAW;AAGjB,SAAS,EAAS,GAAmB;CACnC,IAAI,IAAI;CACR,KAAK,IAAI,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK,IAAI,IAAI,MAAM,EAAE,WAAW,CAAC,IAAI;CACnE,OAAO;AACT;AAGA,SAAgB,EAAS,GAAmB;CAC1C,IAAI,IAAI;CACR,OAAO,IAAI,IAAG;EACZ,IAAM,KAAK,IAAI,KAAK;EAEpB,AADA,IAAI,OAAO,aAAa,KAAK,CAAC,IAAI,GAClC,IAAI,KAAK,OAAO,IAAI,KAAK,EAAE;CAC7B;CACA,OAAO;AACT;AASA,SAAS,EAAY,GAAsE;CACzF,IAAM,oBAAQ,IAAI,IAAkB,GAC9B,oBAAU,IAAI,IAAY;CAChC,KAAK,IAAM,KAAS,GAAQ;EAC1B,IAAM,IAAI,gCAAgC,KAAK,CAAK;EACpD,IAAI,CAAC,GAAG;EACR,IAAM,IAAK,EAAS,EAAE,EAAE,GAClB,IAAK,SAAS,EAAE,IAAI,EAAE,GACtB,IAAK,EAAS,EAAE,EAAE,GAClB,IAAK,SAAS,EAAE,IAAI,EAAE,GACtB,IAAM,KAAK,IAAI,GAAI,CAAE,GACrB,IAAS,KAAK,IAAI,GAAI,CAAE,GACxB,IAAO,KAAK,IAAI,GAAI,CAAE,GACtB,IAAQ,KAAK,IAAI,GAAI,CAAE;EAC7B,EAAM,IAAI,GAAG,EAAI,GAAG,KAAQ;GAAE,SAAS,IAAS,IAAM;GAAG,SAAS,IAAQ,IAAO;EAAE,CAAC;EACpF,KAAK,IAAI,IAAI,GAAK,KAAK,GAAQ,KAC7B,KAAK,IAAI,IAAI,GAAM,KAAK,GAAO,KACzB,MAAM,KAAO,MAAM,KACvB,EAAQ,IAAI,GAAG,EAAE,GAAG,GAAG;CAG7B;CACA,OAAO;EAAE;EAAO;CAAQ;AAC1B;AAMA,IAAM,IAAiB,2dASvB,GAOM,IAAe;CACnB;CAAU;CAAU;CAAU;CAAU;CAAU;CAClD;CAAU;CAAU;CAAU;CAAU;CAAU;AACpD;AAEA,SAAS,EAAS,GAAW,GAAW,GAAqC;CAG3E,AAFA,KAAK,KACL,KAAK,KACL,KAAK;CACL,IAAM,IAAM,KAAK,IAAI,GAAG,GAAG,CAAC,GACtB,IAAM,KAAK,IAAI,GAAG,GAAG,CAAC,GACxB,IAAI,GACJ,IAAI,GACF,KAAK,IAAM,KAAO;CACxB,IAAI,MAAQ,GAAK;EACf,IAAM,IAAI,IAAM;EAKhB,AAJA,IAAI,IAAI,KAAM,KAAK,IAAI,IAAM,KAAO,KAAK,IAAM,IAC/C,AAEK,IAFD,MAAQ,KAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,KACrC,MAAQ,KAAQ,IAAI,KAAK,IAAI,KAC5B,IAAI,KAAK,IAAI,GACvB,KAAK;CACP;CACA,OAAO;EAAC;EAAG;EAAG;CAAC;AACjB;AAEA,SAAS,EAAQ,GAAW,GAAW,GAAmB;CAMxD,OALI,IAAI,MAAG,KAAK,IACZ,IAAI,KAAG,KACP,IAAI,IAAI,IAAU,KAAK,IAAI,KAAK,IAAI,IACpC,IAAI,IAAI,IAAU,IAClB,IAAI,IAAI,IAAU,KAAK,IAAI,MAAM,IAAI,IAAI,KAAK,IAC3C;AACT;AAEA,SAAS,EAAS,GAAW,GAAW,GAAqC;CAC3E,IAAI,MAAM,GAAG;EACX,IAAM,IAAI,KAAK,MAAM,IAAI,GAAG;EAC5B,OAAO;GAAC;GAAG;GAAG;EAAC;CACjB;CACA,IAAM,IAAI,IAAI,KAAM,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,GACxC,IAAI,IAAI,IAAI;CAClB,OAAO;EACL,KAAK,MAAM,EAAQ,GAAG,GAAG,IAAI,IAAI,CAAC,IAAI,GAAG;EACzC,KAAK,MAAM,EAAQ,GAAG,GAAG,CAAC,IAAI,GAAG;EACjC,KAAK,MAAM,EAAQ,GAAG,GAAG,IAAI,IAAI,CAAC,IAAI,GAAG;CAC3C;AACF;AAIA,SAAS,EAAU,GAAa,GAAsB;CAIpD,IAAM,CAAC,GAAG,GAAG,KAAM,EAHT,SAAS,EAAI,MAAM,GAAG,CAAC,GAAG,EAGR,GAFlB,SAAS,EAAI,MAAM,GAAG,CAAC,GAAG,EAEL,GADrB,SAAS,EAAI,MAAM,GAAG,CAAC,GAAG,EACF,CAAC,GAC/B,IAAI,IAAO,IAAI,KAAM,IAAI,KAAQ,KAAM,IAAI,KAAQ;CACvD,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;CAC9B,IAAM,CAAC,GAAI,GAAI,KAAM,EAAS,GAAG,GAAG,CAAC,GAC/B,KAAM,MAAsB,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG;CAChE,OAAO,EAAG,CAAE,IAAI,EAAG,CAAE,IAAI,EAAG,CAAE;AAChC;AAOA,SAAS,EAAW,GAAoC;CACtD,IAAI,CAAC,KAAS,OAAO,KAAU,UAAU;CACzC,IAAM,IAAI,GACN;CACJ,IAAI,OAAO,EAAE,QAAS,cAChB,EAAE,KAAK,WAAW,GAAG;EACvB,IAAI,EAAE,KAAK,MAAM,GAAG,CAAC,CAAC,CAAC,YAAY,MAAM,MAAM;EAC/C,IAAM,EAAE,KAAK,MAAM,CAAC;CACtB,OAAO,AAAI,EAAE,KAAK,WAAW,MAC3B,IAAM,EAAE;MAEL,IAAI,OAAO,EAAE,SAAU,UAC5B,IAAM,EAAa,EAAE;MAChB,IAAI,OAAO,EAAE,WAAY,UAAU;EACxC,IAAI,EAAE,YAAY,IAAI;EACtB,IAAM,EAAE,YAAY,KAAK,WAAW,EAAe,EAAE;CACvD;CACI,OAAC,KAAO,CAAC,mBAAmB,KAAK,CAAG,IAExC,OADI,OAAO,EAAE,QAAS,YAAY,EAAE,SAAS,MAAG,IAAM,EAAU,GAAK,EAAE,IAAI,IACpE,IAAI;AACb;AAIA,SAAS,EAAa,GAA8C;CAC9D,OAAC,KAAQ,KAAQ,IACrB,OAAO,KAAK,MAAO,IAAO,IAAK,CAAC;AAClC;AAOA,SAAS,EAAa,GAA+B;CAEnD,OADI,CAAC,KAAK,KAAK,IAAU,KAClB,KAAK,MAAM,IAAI,IAAI,CAAC;AAC7B;AAGA,SAAS,EAAK,GAAmB;CAC/B,OAAO,IAAI,KAAK,IAAI,MAAM,OAAO,CAAC;AACpC;AAKA,SAAS,EAAW,GAAiB;CACnC,IAAM,IAAO,GAAG,EAAE,YAAY,EAAE,GAAG,EAAK,EAAE,SAAS,IAAI,CAAC,EAAE,GAAG,EAAK,EAAE,QAAQ,CAAC,KACvE,IAAI,EAAE,SAAS,GACf,IAAK,EAAE,WAAW,GAClB,IAAI,EAAE,WAAW;CAEvB,OADI,CAAC,KAAK,CAAC,KAAM,CAAC,IAAU,IACrB,GAAG,EAAK,GAAG,EAAK,CAAC,EAAE,GAAG,EAAK,CAAE,IAAI,IAAI,IAAI,EAAK,CAAC,MAAM;AAC9D;AAEA,SAAS,EAAiB,GAAuB;CAE/C,OADK,MAAM,QAAQ,CAAI,IAChB,EACJ,KAAK,MAAO,KAAK,OAAO,KAAM,WAAa,EAAwB,QAAQ,KAAM,EAAG,CAAC,CACrF,KAAK,EAAE,IAHuB;AAInC;AAIA,IAAM,IAAe;CAAC;CAAK;CAAK;CAAK;CAAK;CAAK;CAAK;CAAK;CAAK;CAAK;AAAG,GAChE,IAAkB;CAAC;CAAK;CAAK;CAAK;CAAK;CAAK;CAAK;CAAK;CAAK;CAAK;AAAG,GACnE,IAAc;CAAC;CAAI;CAAK;CAAK;AAAG,GAChC,IAAiB;CAAC;CAAI;CAAK;CAAK;AAAG,GACnC,IAAY;CAAC;CAAI;CAAK;CAAK;AAAG;AAGpC,SAAS,EAAW,GAAW,GAAkB,GAAyB;CACxE,IAAI,IAAI,IACJ,IAAc;CAClB,KAAK,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK;EAC3B,IAAM,IAAI,KAAK,MAAM,IAAI,MAAM,CAAC,IAAI;EACpC,AAAI,MAAM,IACJ,MAAM,OAAI,IAAc,OAE5B,AAEE,OADA,KAAK,EAAO,IACE,KAEhB,KAAK,EAAO,KAAK,EAAM;CAE3B;CACA,OAAO;AACT;AAIA,SAAS,EAAiB,GAAW,GAAwB;CAC3D,IAAM,IAAS,IAAQ,IAAkB,GACnC,IAAQ,IAAQ,IAAiB;CACvC,IAAI,MAAM,GAAG,OAAO,EAAO;CAC3B,IAAM,IAAmB,CAAC,GACtB,IAAI;CACR,OAAO,IAAI,IAET,AADA,EAAO,KAAK,IAAI,GAAK,GACrB,IAAI,KAAK,MAAM,IAAI,GAAK;CAE1B,IAAI,IAAI;CACR,KAAK,IAAI,IAAI,EAAO,SAAS,GAAG,KAAK,GAAG,KAAK;EAC3C,IAAM,IAAI,EAAO;EACjB,IAAI,MAAM,GAAG;EACb,IAAI,IAAK,EAAW,GAAG,GAAQ,CAAK;EAEpC,AADI,IAAI,EAAO,SAAS,KAAK,IAAI,QAAM,IAAK,EAAO,KAAK,IACxD,KAAK,IAAK,EAAU;CACtB;CACA,OAAO;AACT;AAIA,SAAS,EAAkB,GAAmB;CAC5C,OAAO,EAAE,QAAQ,WAAW,MAAM,aAAa,OAAO,CAAC,EAAE;AAC3D;AAIA,SAAS,EAAY,GAAe,GAAW,GAA4B;CACzE,IAAI,MAAM,GAAG;EACX,IAAI;GACF,IAAM,IAAM,EAAS,GAAK,CAAK;GAC/B,IAAI,OAAO,KAAQ,UAAU,OAAO,EAAkB,CAAG;EAC3D,QAAQ,CAER;EACA,OAAO;CACT;CAEA,OADI,OAAO,UAAU,CAAK,KAAK,KAAS,IAAU,EAAiB,GAAO,MAAM,CAAC,IAC1E;AACT;AAKA,SAAS,EAAS,GAAqB;CACrC,OAAO,EAAI,QAAQ,uBAAuB,SAAS;AACrD;AAUA,SAAS,EAAa,GAAe,GAAoC;CACvE,IAAM,IAAM,EAAS,KAAU,SAAS,GAClC,IAAQ,mBAAmB,KAAK,CAAG;CACzC,IAAI,GAAO;EACT,IAAM,IAAM,EAAY,GAAO,OAAO,EAAM,EAAE,GAAG,CAAG;EACpD,IAAI,KAAO,MAAM,OAAO;CAC1B;CACA,IAAI;EACF,IAAM,IAAM,EAAS,GAAK,CAAK;EAC/B,OAAO,OAAO,KAAQ,WAAW,IAAM,OAAO,CAAK;CACrD,QAAQ;EACN,OAAO,OAAO,CAAK;CACrB;AACF;AAMA,SAAS,EAAgB,GAAS,GAAoC;CACpE,IAAI,KAAU,MAAW,aAAa,EAAe,CAAM,GACzD,IAAI;EACF,IAAM,IAAM,EAAS,GAAQ,CAAC;EAC9B,IAAI,OAAO,KAAQ,YAAY,MAAQ,IAAI,OAAO;CACpD,QAAQ,CAER;CAEF,OAAO,EAAW,CAAC;AACrB;AAUA,SAAS,EAAS,GAA4B;CAC5C,IAAM,IAAI,EAAK;CACf,IAAI,KAAK,MAAM,OAAO;CACtB,IAAI,OAAO,KAAM,UAAU,OAAO,EAAa,GAAG,EAAK,MAAM;CAC7D,IAAI,OAAO,KAAM,YAAY,OAAO,KAAM,WAAW,OAAO,OAAO,CAAC;CACpE,IAAI,aAAa,MAAM,OAAO,EAAgB,GAAG,EAAK,MAAM;CAC5D,IAAI,OAAO,KAAM,UAAU;EACzB,IAAM,IAAI;EACV,IAAI,OAAO,EAAE,SAAU,UAAU,OAAO,EAAE;EAC1C,IAAI,MAAM,QAAQ,EAAE,QAAQ,GAAG,OAAO,EAAiB,EAAE,QAAQ;EACjE,IAAI,eAAe,GAAG;GAEpB,IAAM,IAAI,EAAE;GAIZ,OAHI,MAAM,QAAS,GAA8B,QAAQ,IAChD,EAAkB,EAA6B,QAAQ,IAE7C,OAAZ,KAAmB,EAAE,SAAqB;EACnD;EACA,IAAI,YAAY,KAAK,aAAa,KAAK,mBAAmB,GAAG;GAE3D,IAAM,IAAM,EAAE;GACd,IAAI,KAAO,MAAM,OAAO;GACxB,IAAI,OAAO,KAAQ,UAAU,OAAO,EAAa,GAAK,EAAK,MAAM;GACjE,IAAI,OAAO,KAAQ,YAAY,OAAO,KAAQ,WAAW,OAAO,OAAO,CAAG;GAC1E,IAAI,aAAe,MAAM,OAAO,EAAgB,GAAK,EAAK,MAAM;GAChE,IAAI,KAAO,OAAO,KAAQ,UAAU;IAClC,IAAM,IAAK;IACX,IAAI,OAAO,EAAG,SAAU,UAAU,OAAO,EAAG;IAC5C,IAAI,MAAM,QAAQ,EAAG,QAAQ,GAAG,OAAO,EAAiB,EAAG,QAAQ;GACrE;GACA,OAAO;EACT;CACF;CAEA,IAAI;EACF,IAAM,IAAI,EAAK;EACf,OAAO,KAAK,QAAQ,MAAM,oBAAoB,OAAO,CAAC,IAAI;CAC5D,QAAQ;EACN,OAAO;CACT;AACF;AAIA,SAAS,EAAa,GAAyB;CAE7C,IADI,OAAO,KAAU,YACjB,aAAiB,MAAM,OAAO;CAClC,IAAI,KAAS,OAAO,KAAU,YAAY,YAAY,GAAO;EAC3D,IAAM,IAAO,EAA+B;EAC5C,OAAO,OAAO,KAAQ,YAAY,aAAe;CACnD;CACA,OAAO;AACT;AAEA,SAAS,EAAW,GAAkC;CAEpD,IAAM,EAAE,UAAO,eAAY,EADZ,MAAM,QAAQ,EAAG,OAAO,MAAM,IAAK,EAAG,MAAM,SAAsB,CAAC,CACrC,GAEvC,IAAO,KAAK,IAAI,EAAG,eAAe,GAAG,CAAQ,GAC7C,IAAW,KAAK,IAAI,EAAG,YAAY,GAAG,CAAQ,GAE9C,IAAsB,CAAC,GACvB,IAAuB,CAAC;CAC9B,KAAK,IAAI,IAAI,GAAG,KAAK,GAAM,KAAK;EAC9B,IAAM,IAAM,EAAG,UAAU,CAAC;EAE1B,AADA,EAAU,KAAK,EAAa,GAAK,KAAK,CAAC,GACvC,EAAU,KAAK,CAAC,CAAC,GAAK,MAAM;CAC9B;CAEA,IAAM,IAAkB,CAAC;CACzB,KAAK,IAAI,IAAI,GAAG,KAAK,GAAU,KAAK;EAClC,IAAM,IAAM,EAAG,OAAO,CAAC,GACjB,IAAoB,CAAC;EAC3B,KAAK,IAAI,IAAI,GAAG,KAAK,GAAM,KAAK;GAC9B,IAAI,EAAQ,IAAI,GAAG,EAAE,GAAG,GAAG,GAAG;GAC9B,IAAM,IAAO,EAAI,QAAQ,CAAC,GACpB,IAAO,EAAM,IAAI,GAAG,EAAE,GAAG,GAAG,GAC5B,IAAO,EAAS,CAAI,GAItB,GACE,IAAK,EAAK;GAChB,IAAI,KAAM,OAAO,KAAO,UAAU;IAChC,IAAM,IAAI;IACV,AAAI,OAAO,EAAE,WAAY,YAAY,EAAE,UAAS,IAAU,EAAE,UACnD,OAAO,EAAE,iBAAkB,YAAY,EAAE,kBAAe,IAAU,EAAE;GAC/E;GAGA,IAAM,IAAO,EAAK,QAAQ,CAAC,GACrB,IAAQ,EAAK,aAAa,CAAC,GAC3B,IAAS,EAAK,UAAU,CAAC,GACzB,IACJ,EAAM,eAAe,YAAY,EAAM,eAAe,qBAClD,WACA,EAAM,eAAe,UACnB,UACA,EAAM,eAAe,SACnB,SACA,EAAa,EAAK,KAAK,IACrB,UACA,KAAA,GACN,IACJ,EAAM,aAAa,QACf,QACA,EAAM,aAAa,WACjB,WACA,EAAM,aAAa,WACjB,WACA,KAAA;GACV,EAAM,KAAK;IACT;IACA,KAAK;IACL,SAAS,GAAM,WAAW;IAC1B,SAAS,GAAM,WAAW;IAC1B,MAAM,EAAK,QAAQ,KAAA;IACnB,QAAQ,EAAK,UAAU,KAAA;IACvB,WAAW,CAAC,CAAC,EAAK,aAAa,KAAA;IAC/B,QAAQ,EAAK,UAAU,KAAA;IACvB,UAAU,EAAa,EAAK,IAAI;IAChC;IACA,OAAO,EAAW,EAAK,KAAK;IAC5B,IACE,EAAK,QAAQ,EAAK,KAAK,SAAS,YAC5B,EAAY,EAAK,KAA+B,OAAO,IACvD,KAAA;IACN,OAAO;IACP,QAAQ;IACR,MAAM,EAAM,YAAY,KAAA;IACxB,IAAI,CAAC,CAAC,EAAO,KAAK,SAAS,KAAA;IAC3B,IAAI,CAAC,CAAC,EAAO,OAAO,SAAS,KAAA;IAC7B,IAAI,CAAC,CAAC,EAAO,QAAQ,SAAS,KAAA;IAC9B,IAAI,CAAC,CAAC,EAAO,MAAM,SAAS,KAAA;GAC9B,CAAC;EACH;EACA,EAAK,KAAK;GACR,KAAK;GACL,QAAQ,EAAI,SAAS,KAAK,MAAO,EAAI,SAAS,IAAK,CAAC,IAAI,KAAA;GACxD,QAAQ,CAAC,CAAC,EAAI;GACd;EACF,CAAC;CACH;CAIA,IAAM,IAAO,MAAM,QAAQ,EAAG,KAAK,IAAI,EAAG,MAAM,KAAK,KAAA,GAC/C,IAAS,KAAS,EAA4B,UAAU,WAAW,IAAO,KAAA,GAC1E,IAAa,IACf,KAAK,IAAI,KAAK,IAAI,GAAI,EAA+B,UAAU,CAAC,GAAG,CAAI,IACvE,GACE,IAAa,IACf,KAAK,IAAI,KAAK,IAAI,GAAI,EAA+B,UAAU,CAAC,GAAG,CAAQ,IAC3E;CAEJ,OAAO;EAAE,MAAM,EAAG,QAAQ;EAAS;EAAW;EAAW;EAAM;EAAM;EAAY;CAAW;AAC9F;AAGA,eAAsB,EAAU,GAAsC;CACpE,IAAM,IAAK,IAAI,EAAQ,SAAS;CAChC,MAAM,EAAG,KAAK,KAAK,CAAG;CACtB,IAAM,IAAS,EAAG,WAEf,QAAQ,MAAO,KAAM,EAAG,UAAU,YAAY,EAAG,UAAU,YAAY,CAAC,CACxE,IAAI,CAAU;CACjB,IAAI,EAAO,WAAW,GAAG,MAAU,MAAM,eAAe;CACxD,OAAO,EAAE,UAAO;AAClB"}
@@ -150,3 +150,5 @@ async function v(e) {
150
150
  }
151
151
  //#endregion
152
152
  export { v as parseXlsxCharts };
153
+
154
+ //# sourceMappingURL=xlsxCharts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xlsxCharts.js","names":[],"sources":["../../src/lib/xlsxCharts.ts"],"sourcesContent":["/**\n * Extract embedded **charts** from an `.xlsx` for the spreadsheet preview.\n *\n * exceljs parses cells and styles but NOT charts (and a workbook can hold native line/bar/pie charts with no\n * raster image anywhere — `wb.model.media` is empty). So we read them ourselves: an `.xlsx` is a ZIP, and we\n * already have a dependency-free reader ({@link readZip}/{@link extractZipEntry}). We walk\n * worksheet → drawing → chart, parse the chart's cached series/categories straight out of the OOXML\n * (`<c:numCache>`/`<c:strCache>` — the values Excel last computed, so no recomputation needed), and hand the\n * viewer a small model it renders as SVG ({@link XlsxChart}). Browser-only (DOMParser + DecompressionStream);\n * charts simply don't appear under SSR.\n */\nimport { extractZipEntry, readZip, zipSupported, type ZipEntry } from '@/lib/zip'\n\nexport type ChartType = 'line' | 'bar' | 'barH' | 'pie' | 'area' | 'scatter' | 'unknown'\n\nexport interface ChartSeries {\n name: string\n /** Series line/fill colour as CSS `#RRGGBB`, when the chart specifies one. */\n color?: string\n /** Cached y-values, one per category (null = a gap/blank point). */\n values: (number | null)[]\n}\n\n/** Where a chart sits on the sheet — top-left cell + pixel size, converted from the drawing anchor's EMUs. */\nexport interface ChartAnchor {\n /** 0-based column / row of the anchor's top-left cell. */\n fromCol: number\n fromRow: number\n /** Pixel offset into that cell, and the chart's pixel width/height (from the frame's EMU extent). */\n offX: number\n offY: number\n wPx: number\n hPx: number\n}\n\nexport interface XlsxChart {\n type: ChartType\n title: string\n categories: string[]\n series: ChartSeries[]\n /** Explicit value-axis bounds, when the chart pins them (else the renderer auto-scales). */\n yMin?: number\n yMax?: number\n anchor: ChartAnchor\n}\n\nconst EMU_PER_PX = 9525 // 914400 EMU per inch / 96 px per inch\nconst emuToPx = (emu: number): number => Math.round(emu / EMU_PER_PX)\n\n// Descendants matching a localName, regardless of namespace prefix (xdr:/c:/a: vary by producer).\nfunction tags(el: Element | Document, localName: string): Element[] {\n return Array.from(el.getElementsByTagNameNS('*', localName))\n}\nfunction tag(el: Element | Document, localName: string): Element | undefined {\n return el.getElementsByTagNameNS('*', localName)[0]\n}\nfunction attrVal(el: Element | undefined): string | undefined {\n return el?.getAttribute('val') ?? undefined\n}\n\n// Resolve an OOXML relationship target (often \"../charts/chart3.xml\") against the part that referenced it.\nfunction resolvePath(baseDir: string, rel: string): string {\n const parts = (baseDir ? baseDir.split('/') : []).concat(rel.split('/'))\n const out: string[] = []\n for (const p of parts) {\n if (p === '' || p === '.') continue\n if (p === '..') out.pop()\n else out.push(p)\n }\n return out.join('/')\n}\nconst dirOf = (path: string): string => path.split('/').slice(0, -1).join('/')\n\n/** A loader bound to one workbook's ZIP: lazily inflate + XML-parse parts, cached by path. */\nfunction makeLoader(\n buf: ArrayBuffer,\n entries: ZipEntry[],\n): (path: string) => Promise<Document | null> {\n const byPath = new Map(entries.map((e) => [e.path, e]))\n const cache = new Map<string, Promise<Document | null>>()\n const decoder = new TextDecoder('utf-8')\n return (path: string) => {\n let p = cache.get(path)\n if (!p) {\n p = (async () => {\n const e = byPath.get(path)\n if (!e) return null\n const bytes = await extractZipEntry(buf, e)\n const doc = new DOMParser().parseFromString(decoder.decode(bytes), 'application/xml')\n return doc.querySelector('parsererror') ? null : doc\n })()\n cache.set(path, p)\n }\n return p\n }\n}\n\n// Parse a \"rels\" part into { relId → resolved absolute path }.\nfunction relsMap(doc: Document | null, baseDir: string): Map<string, string> {\n const m = new Map<string, string>()\n if (!doc) return m\n for (const r of tags(doc, 'Relationship')) {\n const id = r.getAttribute('Id')\n const target = r.getAttribute('Target')\n if (id && target && !/^[a-z]+:\\/\\//i.test(target)) m.set(id, resolvePath(baseDir, target))\n }\n return m\n}\n\n// Pull the ordered category labels (or numbers) out of a <c:cat>'s cached points.\nfunction readCacheStrings(parent: Element | undefined): string[] {\n if (!parent) return []\n const cache = tag(parent, 'strCache') || tag(parent, 'numCache')\n if (!cache) return []\n const count = parseInt(attrVal(tag(cache, 'ptCount')) || '0', 10) || 0\n const out: string[] = Array.from({ length: count }, () => '')\n for (const pt of tags(cache, 'pt')) {\n const idx = parseInt(pt.getAttribute('idx') || '-1', 10)\n const v = tag(pt, 'v')?.textContent ?? ''\n if (idx >= 0) {\n if (idx >= out.length) out.length = idx + 1\n out[idx] = v\n }\n }\n return out\n}\n\n// Pull cached numeric values out of a <c:val>'s numCache (blank/non-numeric → null).\nfunction readCacheNumbers(parent: Element | undefined): (number | null)[] {\n if (!parent) return []\n const cache = tag(parent, 'numCache') || tag(parent, 'strCache')\n if (!cache) return []\n const count = parseInt(attrVal(tag(cache, 'ptCount')) || '0', 10) || 0\n const out: (number | null)[] = Array.from({ length: count }, () => null)\n for (const pt of tags(cache, 'pt')) {\n const idx = parseInt(pt.getAttribute('idx') || '-1', 10)\n const raw = tag(pt, 'v')?.textContent\n const n = raw == null || raw === '' ? null : Number(raw)\n if (idx >= 0) {\n if (idx >= out.length) out.length = idx + 1\n out[idx] = n != null && Number.isFinite(n) ? n : null\n }\n }\n return out\n}\n\nfunction chartTypeOf(plot: Element): ChartType {\n if (tag(plot, 'lineChart')) return 'line'\n if (tag(plot, 'barChart')) {\n const dir = attrVal(tag(tag(plot, 'barChart')!, 'barDir'))\n return dir === 'bar' ? 'barH' : 'bar'\n }\n if (tag(plot, 'pieChart') || tag(plot, 'doughnutChart')) return 'pie'\n if (tag(plot, 'areaChart')) return 'area'\n if (tag(plot, 'scatterChart')) return 'scatter'\n return 'unknown'\n}\n\n// First explicit series colour: prefer the line stroke, else any solid fill in the series' shape props.\nfunction seriesColor(ser: Element): string | undefined {\n const spPr = tag(ser, 'spPr')\n if (!spPr) return undefined\n const ln = tag(spPr, 'ln')\n const clr = (ln && tag(ln, 'srgbClr')) || tag(spPr, 'srgbClr')\n const val = clr?.getAttribute('val')\n return val && /^[0-9a-fA-F]{6}$/.test(val) ? `#${val}` : undefined\n}\n\nfunction parseChart(doc: Document): Omit<XlsxChart, 'anchor'> | null {\n const plot = tag(doc, 'plotArea')\n if (!plot) return null\n const type = chartTypeOf(plot)\n // Title: concatenate the rich-text runs under <c:title>.\n const titleEl = tag(doc, 'title')\n const title = titleEl\n ? tags(titleEl, 't')\n .map((t) => t.textContent ?? '')\n .join('')\n .trim()\n : ''\n\n let categories: string[] = []\n const series: ChartSeries[] = []\n for (const ser of tags(plot, 'ser')) {\n const cats = readCacheStrings(tag(ser, 'cat'))\n if (cats.length > categories.length) categories = cats\n const txV = tag(tag(ser, 'tx') || ser, 'v')?.textContent\n series.push({\n name: (txV || `系列 ${series.length + 1}`).trim(),\n color: seriesColor(ser),\n values: readCacheNumbers(tag(ser, 'val')),\n })\n }\n\n // Value-axis explicit bounds, if any.\n let yMin: number | undefined\n let yMax: number | undefined\n for (const ax of tags(plot, 'valAx')) {\n const sc = tag(ax, 'scaling')\n if (!sc) continue\n const mx = attrVal(tag(sc, 'max'))\n const mn = attrVal(tag(sc, 'min'))\n if (mx != null && Number.isFinite(Number(mx))) yMax = Number(mx)\n if (mn != null && Number.isFinite(Number(mn))) yMin = Number(mn)\n }\n return { type, title, categories, series, yMin, yMax }\n}\n\n// Read a drawing's anchors, resolving each graphicFrame's chart part via the drawing's own rels.\nasync function parseDrawing(\n drawingPath: string,\n load: (path: string) => Promise<Document | null>,\n): Promise<XlsxChart[]> {\n const doc = await load(drawingPath)\n if (!doc) return []\n const rels = relsMap(\n await load(`${dirOf(drawingPath)}/_rels/${drawingPath.split('/').pop()}.rels`),\n dirOf(drawingPath),\n )\n const out: XlsxChart[] = []\n for (const anchor of [...tags(doc, 'twoCellAnchor'), ...tags(doc, 'oneCellAnchor')]) {\n const frame = tag(anchor, 'graphicFrame')\n if (!frame) continue\n const chartRef = tag(frame, 'chart') // <c:chart r:id=\"rIdN\"/>\n const rId =\n chartRef?.getAttributeNS(\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',\n 'id',\n ) || chartRef?.getAttribute('r:id')\n const chartPath = rId ? rels.get(rId) : undefined\n if (!chartPath) continue\n const chartDoc = await load(chartPath)\n if (!chartDoc) continue\n const parsed = parseChart(chartDoc)\n if (!parsed || !parsed.series.length) continue\n\n const from = tag(anchor, 'from')\n const fromCol = parseInt(tag(from!, 'col')?.textContent || '0', 10)\n const fromRow = parseInt(tag(from!, 'row')?.textContent || '0', 10)\n const offX = emuToPx(parseInt(tag(from!, 'colOff')?.textContent || '0', 10))\n const offY = emuToPx(parseInt(tag(from!, 'rowOff')?.textContent || '0', 10))\n const ext = tag(frame, 'ext') // <a:ext cx cy> in EMU\n const wPx = ext ? emuToPx(parseInt(ext.getAttribute('cx') || '0', 10)) : 384\n const hPx = ext ? emuToPx(parseInt(ext.getAttribute('cy') || '0', 10)) : 230\n out.push({ ...parsed, anchor: { fromCol, fromRow, offX, offY, wPx, hPx } })\n }\n return out\n}\n\n/**\n * Parse every chart in the workbook, grouped by worksheet **name** (matching {@link XlsxSheet.name}). Returns\n * an empty map under SSR or if the bytes can't be unzipped — charts are a best-effort enhancement, never fatal.\n */\nexport async function parseXlsxCharts(buf: ArrayBuffer): Promise<Map<string, XlsxChart[]>> {\n const result = new Map<string, XlsxChart[]>()\n if (!zipSupported() || typeof DOMParser === 'undefined') return result\n let entries: ZipEntry[]\n try {\n entries = readZip(buf)\n } catch {\n return result\n }\n const load = makeLoader(buf, entries)\n\n const wb = await load('xl/workbook.xml')\n if (!wb) return result\n const wbRels = relsMap(await load('xl/_rels/workbook.xml.rels'), 'xl')\n\n for (const sheetEl of tags(wb, 'sheet')) {\n const name = sheetEl.getAttribute('name') || ''\n const rId =\n sheetEl.getAttributeNS(\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',\n 'id',\n ) || sheetEl.getAttribute('r:id')\n const sheetPath = rId ? wbRels.get(rId) : undefined\n if (!sheetPath) continue\n const sheetRels = relsMap(\n await load(`${dirOf(sheetPath)}/_rels/${sheetPath.split('/').pop()}.rels`),\n dirOf(sheetPath),\n )\n // Find the worksheet's drawing relationship, then its charts.\n const sheetDoc = await load(sheetPath)\n const drawingEl = sheetDoc ? tag(sheetDoc, 'drawing') : undefined\n const drawRid =\n drawingEl?.getAttributeNS(\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',\n 'id',\n ) || drawingEl?.getAttribute('r:id')\n const drawingPath = drawRid ? sheetRels.get(drawRid) : undefined\n if (!drawingPath) continue\n const charts = await parseDrawing(drawingPath, load)\n if (charts.length) result.set(name, charts)\n }\n return result\n}\n"],"mappings":";;AA8CA,IAAM,IAAa,MACb,KAAW,MAAwB,KAAK,MAAM,IAAM,CAAU;AAGpE,SAAS,EAAK,GAAwB,GAA8B;CAClE,OAAO,MAAM,KAAK,EAAG,uBAAuB,KAAK,CAAS,CAAC;AAC7D;AACA,SAAS,EAAI,GAAwB,GAAwC;CAC3E,OAAO,EAAG,uBAAuB,KAAK,CAAS,CAAC,CAAC;AACnD;AACA,SAAS,EAAQ,GAA6C;CAC5D,OAAO,GAAI,aAAa,KAAK,KAAK,KAAA;AACpC;AAGA,SAAS,EAAY,GAAiB,GAAqB;CACzD,IAAM,KAAS,IAAU,EAAQ,MAAM,GAAG,IAAI,CAAC,EAAA,CAAG,OAAO,EAAI,MAAM,GAAG,CAAC,GACjE,IAAgB,CAAC;CACvB,KAAK,IAAM,KAAK,GACV,MAAM,MAAM,MAAM,QAClB,MAAM,OAAM,EAAI,IAAI,IACnB,EAAI,KAAK,CAAC;CAEjB,OAAO,EAAI,KAAK,GAAG;AACrB;AACA,IAAM,KAAS,MAAyB,EAAK,MAAM,GAAG,CAAC,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,KAAK,GAAG;AAG7E,SAAS,EACP,GACA,GAC4C;CAC5C,IAAM,IAAS,IAAI,IAAI,EAAQ,KAAK,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,GAChD,oBAAQ,IAAI,IAAsC,GAClD,IAAU,IAAI,YAAY,OAAO;CACvC,QAAQ,MAAiB;EACvB,IAAI,IAAI,EAAM,IAAI,CAAI;EAWtB,OAVK,MACH,KAAK,YAAY;GACf,IAAM,IAAI,EAAO,IAAI,CAAI;GACzB,IAAI,CAAC,GAAG,OAAO;GACf,IAAM,IAAQ,MAAM,EAAgB,GAAK,CAAC,GACpC,IAAM,IAAI,UAAU,CAAC,CAAC,gBAAgB,EAAQ,OAAO,CAAK,GAAG,iBAAiB;GACpF,OAAO,EAAI,cAAc,aAAa,IAAI,OAAO;EACnD,EAAA,CAAG,GACH,EAAM,IAAI,GAAM,CAAC,IAEZ;CACT;AACF;AAGA,SAAS,EAAQ,GAAsB,GAAsC;CAC3E,IAAM,oBAAI,IAAI,IAAoB;CAClC,IAAI,CAAC,GAAK,OAAO;CACjB,KAAK,IAAM,KAAK,EAAK,GAAK,cAAc,GAAG;EACzC,IAAM,IAAK,EAAE,aAAa,IAAI,GACxB,IAAS,EAAE,aAAa,QAAQ;EACtC,AAAI,KAAM,KAAU,CAAC,gBAAgB,KAAK,CAAM,KAAG,EAAE,IAAI,GAAI,EAAY,GAAS,CAAM,CAAC;CAC3F;CACA,OAAO;AACT;AAGA,SAAS,EAAiB,GAAuC;CAC/D,IAAI,CAAC,GAAQ,OAAO,CAAC;CACrB,IAAM,IAAQ,EAAI,GAAQ,UAAU,KAAK,EAAI,GAAQ,UAAU;CAC/D,IAAI,CAAC,GAAO,OAAO,CAAC;CACpB,IAAM,IAAQ,SAAS,EAAQ,EAAI,GAAO,SAAS,CAAC,KAAK,KAAK,EAAE,KAAK,GAC/D,IAAgB,MAAM,KAAK,EAAE,QAAQ,EAAM,SAAS,EAAE;CAC5D,KAAK,IAAM,KAAM,EAAK,GAAO,IAAI,GAAG;EAClC,IAAM,IAAM,SAAS,EAAG,aAAa,KAAK,KAAK,MAAM,EAAE,GACjD,IAAI,EAAI,GAAI,GAAG,CAAC,EAAE,eAAe;EACvC,AAAI,KAAO,MACL,KAAO,EAAI,WAAQ,EAAI,SAAS,IAAM,IAC1C,EAAI,KAAO;CAEf;CACA,OAAO;AACT;AAGA,SAAS,EAAiB,GAAgD;CACxE,IAAI,CAAC,GAAQ,OAAO,CAAC;CACrB,IAAM,IAAQ,EAAI,GAAQ,UAAU,KAAK,EAAI,GAAQ,UAAU;CAC/D,IAAI,CAAC,GAAO,OAAO,CAAC;CACpB,IAAM,IAAQ,SAAS,EAAQ,EAAI,GAAO,SAAS,CAAC,KAAK,KAAK,EAAE,KAAK,GAC/D,IAAyB,MAAM,KAAK,EAAE,QAAQ,EAAM,SAAS,IAAI;CACvE,KAAK,IAAM,KAAM,EAAK,GAAO,IAAI,GAAG;EAClC,IAAM,IAAM,SAAS,EAAG,aAAa,KAAK,KAAK,MAAM,EAAE,GACjD,IAAM,EAAI,GAAI,GAAG,CAAC,EAAE,aACpB,IAAI,KAAO,QAAQ,MAAQ,KAAK,OAAO,OAAO,CAAG;EACvD,AAAI,KAAO,MACL,KAAO,EAAI,WAAQ,EAAI,SAAS,IAAM,IAC1C,EAAI,KAAO,KAAK,QAAQ,OAAO,SAAS,CAAC,IAAI,IAAI;CAErD;CACA,OAAO;AACT;AAEA,SAAS,EAAY,GAA0B;CAS7C,OARI,EAAI,GAAM,WAAW,IAAU,SAC/B,EAAI,GAAM,UAAU,IACV,EAAQ,EAAI,EAAI,GAAM,UAAU,GAAI,QAAQ,CACjD,MAAQ,QAAQ,SAAS,QAE9B,EAAI,GAAM,UAAU,KAAK,EAAI,GAAM,eAAe,IAAU,QAC5D,EAAI,GAAM,WAAW,IAAU,SAC/B,EAAI,GAAM,cAAc,IAAU,YAC/B;AACT;AAGA,SAAS,EAAY,GAAkC;CACrD,IAAM,IAAO,EAAI,GAAK,MAAM;CAC5B,IAAI,CAAC,GAAM;CACX,IAAM,IAAK,EAAI,GAAM,IAAI,GAEnB,KADO,KAAM,EAAI,GAAI,SAAS,KAAM,EAAI,GAAM,SAAS,EAAA,EAC5C,aAAa,KAAK;CACnC,OAAO,KAAO,mBAAmB,KAAK,CAAG,IAAI,IAAI,MAAQ,KAAA;AAC3D;AAEA,SAAS,EAAW,GAAiD;CACnE,IAAM,IAAO,EAAI,GAAK,UAAU;CAChC,IAAI,CAAC,GAAM,OAAO;CAClB,IAAM,IAAO,EAAY,CAAI,GAEvB,IAAU,EAAI,GAAK,OAAO,GAC1B,IAAQ,IACV,EAAK,GAAS,GAAG,CAAC,CACf,KAAK,MAAM,EAAE,eAAe,EAAE,CAAC,CAC/B,KAAK,EAAE,CAAC,CACR,KAAK,IACR,IAEA,IAAuB,CAAC,GACtB,IAAwB,CAAC;CAC/B,KAAK,IAAM,KAAO,EAAK,GAAM,KAAK,GAAG;EACnC,IAAM,IAAO,EAAiB,EAAI,GAAK,KAAK,CAAC;EAC7C,AAAI,EAAK,SAAS,EAAW,WAAQ,IAAa;EAClD,IAAM,IAAM,EAAI,EAAI,GAAK,IAAI,KAAK,GAAK,GAAG,CAAC,EAAE;EAC7C,EAAO,KAAK;GACV,OAAO,KAAO,MAAM,EAAO,SAAS,IAAA,CAAK,KAAK;GAC9C,OAAO,EAAY,CAAG;GACtB,QAAQ,EAAiB,EAAI,GAAK,KAAK,CAAC;EAC1C,CAAC;CACH;CAGA,IAAI,GACA;CACJ,KAAK,IAAM,KAAM,EAAK,GAAM,OAAO,GAAG;EACpC,IAAM,IAAK,EAAI,GAAI,SAAS;EAC5B,IAAI,CAAC,GAAI;EACT,IAAM,IAAK,EAAQ,EAAI,GAAI,KAAK,CAAC,GAC3B,IAAK,EAAQ,EAAI,GAAI,KAAK,CAAC;EAEjC,AADI,KAAM,QAAQ,OAAO,SAAS,OAAO,CAAE,CAAC,MAAG,IAAO,OAAO,CAAE,IAC3D,KAAM,QAAQ,OAAO,SAAS,OAAO,CAAE,CAAC,MAAG,IAAO,OAAO,CAAE;CACjE;CACA,OAAO;EAAE;EAAM;EAAO;EAAY;EAAQ;EAAM;CAAK;AACvD;AAGA,eAAe,EACb,GACA,GACsB;CACtB,IAAM,IAAM,MAAM,EAAK,CAAW;CAClC,IAAI,CAAC,GAAK,OAAO,CAAC;CAClB,IAAM,IAAO,EACX,MAAM,EAAK,GAAG,EAAM,CAAW,EAAE,SAAS,EAAY,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,GAC7E,EAAM,CAAW,CACnB,GACM,IAAmB,CAAC;CAC1B,KAAK,IAAM,KAAU,CAAC,GAAG,EAAK,GAAK,eAAe,GAAG,GAAG,EAAK,GAAK,eAAe,CAAC,GAAG;EACnF,IAAM,IAAQ,EAAI,GAAQ,cAAc;EACxC,IAAI,CAAC,GAAO;EACZ,IAAM,IAAW,EAAI,GAAO,OAAO,GAC7B,IACJ,GAAU,eACR,uEACA,IACF,KAAK,GAAU,aAAa,MAAM,GAC9B,IAAY,IAAM,EAAK,IAAI,CAAG,IAAI,KAAA;EACxC,IAAI,CAAC,GAAW;EAChB,IAAM,IAAW,MAAM,EAAK,CAAS;EACrC,IAAI,CAAC,GAAU;EACf,IAAM,IAAS,EAAW,CAAQ;EAClC,IAAI,CAAC,KAAU,CAAC,EAAO,OAAO,QAAQ;EAEtC,IAAM,IAAO,EAAI,GAAQ,MAAM,GACzB,IAAU,SAAS,EAAI,GAAO,KAAK,CAAC,EAAE,eAAe,KAAK,EAAE,GAC5D,IAAU,SAAS,EAAI,GAAO,KAAK,CAAC,EAAE,eAAe,KAAK,EAAE,GAC5D,IAAO,EAAQ,SAAS,EAAI,GAAO,QAAQ,CAAC,EAAE,eAAe,KAAK,EAAE,CAAC,GACrE,IAAO,EAAQ,SAAS,EAAI,GAAO,QAAQ,CAAC,EAAE,eAAe,KAAK,EAAE,CAAC,GACrE,IAAM,EAAI,GAAO,KAAK,GACtB,IAAM,IAAM,EAAQ,SAAS,EAAI,aAAa,IAAI,KAAK,KAAK,EAAE,CAAC,IAAI,KACnE,IAAM,IAAM,EAAQ,SAAS,EAAI,aAAa,IAAI,KAAK,KAAK,EAAE,CAAC,IAAI;EACzE,EAAI,KAAK;GAAE,GAAG;GAAQ,QAAQ;IAAE;IAAS;IAAS;IAAM;IAAM;IAAK;GAAI;EAAE,CAAC;CAC5E;CACA,OAAO;AACT;AAMA,eAAsB,EAAgB,GAAqD;CACzF,IAAM,oBAAS,IAAI,IAAyB;CAC5C,IAAI,CAAC,EAAa,KAAK,OAAO,YAAc,KAAa,OAAO;CAChE,IAAI;CACJ,IAAI;EACF,IAAU,EAAQ,CAAG;CACvB,QAAQ;EACN,OAAO;CACT;CACA,IAAM,IAAO,EAAW,GAAK,CAAO,GAE9B,IAAK,MAAM,EAAK,iBAAiB;CACvC,IAAI,CAAC,GAAI,OAAO;CAChB,IAAM,IAAS,EAAQ,MAAM,EAAK,4BAA4B,GAAG,IAAI;CAErE,KAAK,IAAM,KAAW,EAAK,GAAI,OAAO,GAAG;EACvC,IAAM,IAAO,EAAQ,aAAa,MAAM,KAAK,IACvC,IACJ,EAAQ,eACN,uEACA,IACF,KAAK,EAAQ,aAAa,MAAM,GAC5B,IAAY,IAAM,EAAO,IAAI,CAAG,IAAI,KAAA;EAC1C,IAAI,CAAC,GAAW;EAChB,IAAM,IAAY,EAChB,MAAM,EAAK,GAAG,EAAM,CAAS,EAAE,SAAS,EAAU,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,GACzE,EAAM,CAAS,CACjB,GAEM,IAAW,MAAM,EAAK,CAAS,GAC/B,IAAY,IAAW,EAAI,GAAU,SAAS,IAAI,KAAA,GAClD,IACJ,GAAW,eACT,uEACA,IACF,KAAK,GAAW,aAAa,MAAM,GAC/B,IAAc,IAAU,EAAU,IAAI,CAAO,IAAI,KAAA;EACvD,IAAI,CAAC,GAAa;EAClB,IAAM,IAAS,MAAM,EAAa,GAAa,CAAI;EACnD,AAAI,EAAO,UAAQ,EAAO,IAAI,GAAM,CAAM;CAC5C;CACA,OAAO;AACT"}
package/dist/lib/xmind.js CHANGED
@@ -122,3 +122,5 @@ function p(e, t) {
122
122
  }
123
123
  //#endregion
124
124
  export { r as parseXmind };
125
+
126
+ //# sourceMappingURL=xmind.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xmind.js","names":[],"sources":["../../src/lib/xmind.ts"],"sourcesContent":["/**\n * In-browser XMind workbook reader — no dependency beyond the project's own ZIP reader.\n *\n * An `.xmind` file is a ZIP container (like docx / appx). Its content lives in one of two members:\n * - `content.json` — the modern format (XMind 2020+/Zen): a JSON array of sheets, each with a `rootTopic`\n * whose `children.attached` (and `children.detached`) nest sub-topics. A topic carries `title`, optional\n * `href` (hyperlink), `notes.plain.content` (or `notes.realHTML.content`), and `labels`.\n * - `content.xml` — the legacy format: `<xmap-content><sheet><topic><title/><children><topics\n * type=\"attached\"><topic>…</topic></topics></children></topic></sheet></xmap-content>`.\n *\n * We unzip just the content member with the project's ZIP reader (lib/zip.ts — browser-native DEFLATE) and\n * normalize it into the shared {@link MindMap} tree, so the existing MindMapView renders it exactly like an\n * OPML / FreeMind mind map (a single right-growing tree; multi-sheet workbooks get a synthetic root). The\n * structure was checked against a real XMind file (both content.json and content.xml present).\n *\n * Used by XmindViewer (the side viewer's XMind mode): the bytes come from the same download endpoint as any\n * other file, are unzipped + parsed entirely client-side, and never leave the browser.\n */\nimport { readZip, extractZipEntry, type ZipEntry } from '@/lib/zip'\nimport type { MindMap, MindNode } from '@/lib/mindmap'\n\n/** Thrown when the bytes aren't a readable XMind workbook (not a zip, or no content member inside). */\nexport class NotXmindError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'NotXmindError'\n }\n}\n\nexport async function parseXmind(buf: ArrayBuffer, fallbackTitle = ''): Promise<MindMap> {\n let entries: ZipEntry[]\n try {\n entries = readZip(buf)\n } catch {\n throw new NotXmindError('不是有效的 XMind 文件(无法读取 ZIP 容器)')\n }\n const find = (path: string): ZipEntry | undefined =>\n entries.find((e) => e.path.toLowerCase() === path.toLowerCase())\n\n const jsonEntry = find('content.json')\n if (jsonEntry) {\n const text = new TextDecoder('utf-8').decode(await extractZipEntry(buf, jsonEntry))\n return fromContentJson(text, fallbackTitle)\n }\n const xmlEntry = find('content.xml')\n if (xmlEntry) {\n const text = new TextDecoder('utf-8').decode(await extractZipEntry(buf, xmlEntry))\n return fromContentXml(text, fallbackTitle)\n }\n throw new NotXmindError('未找到 content.json / content.xml(不是 XMind 文件)')\n}\n\n// ── shared helpers ────────────────────────────────────────────────────────────────────────────\nfunction makeIdGen(): () => number {\n let n = 0\n return () => n++\n}\nfunction countNodes(n: MindNode): number {\n let c = 1\n for (const k of n.children) c += countNodes(k)\n return c\n}\nfunction flatten(s: string | null | undefined): string {\n return (s || '').replace(/\\s+/g, ' ').trim()\n}\nfunction stripTags(s: string): string {\n return s.replace(/<[^>]*>/g, ' ')\n}\n\n/** Fold a topic's note + labels into the single note string MindNode exposes (shown as a hover tooltip). */\nfunction noteOf(plain: string, labels: string[]): string | undefined {\n const parts: string[] = []\n if (plain) parts.push(plain)\n if (labels.length) parts.push(`标签: ${labels.join(', ')}`)\n return parts.length ? parts.join('\\n') : undefined\n}\n\n// ── content.json (modern) ───────────────────────────────────────────────────────────────────────\ninterface JsonTopic {\n title?: string\n href?: string\n notes?: { plain?: { content?: string }; realHTML?: { content?: string } }\n labels?: unknown\n children?: { attached?: JsonTopic[]; detached?: JsonTopic[] }\n}\ninterface JsonSheet {\n title?: string\n rootTopic?: JsonTopic\n}\n\nfunction jsonTopicToNode(t: JsonTopic, id: () => number): MindNode {\n const children: MindNode[] = []\n const att = t.children?.attached\n if (Array.isArray(att)) for (const c of att) children.push(jsonTopicToNode(c, id))\n const det = t.children?.detached\n if (Array.isArray(det)) for (const c of det) children.push(jsonTopicToNode(c, id))\n\n const plain =\n flatten(t.notes?.plain?.content) || flatten(stripTags(t.notes?.realHTML?.content || ''))\n const labels = Array.isArray(t.labels)\n ? t.labels.filter((l): l is string => typeof l === 'string')\n : []\n return {\n id: id(),\n text: flatten(t.title),\n note: noteOf(plain, labels),\n link: typeof t.href === 'string' && t.href ? t.href : undefined,\n children,\n }\n}\n\nfunction fromContentJson(text: string, fallbackTitle: string): MindMap {\n let data: unknown\n try {\n data = JSON.parse(text)\n } catch {\n throw new NotXmindError('content.json 解析失败(JSON 无效)')\n }\n // Modern content.json is an array of sheets; be tolerant of a single-sheet object.\n const sheets: JsonSheet[] = Array.isArray(data) ? (data as JsonSheet[]) : [data as JsonSheet]\n const valid = sheets.filter((s) => s && s.rootTopic)\n if (!valid.length) throw new NotXmindError('XMind 内容为空(无 rootTopic)')\n\n const id = makeIdGen()\n let root: MindNode\n if (valid.length === 1) {\n root = jsonTopicToNode(valid[0].rootTopic as JsonTopic, id)\n if (!root.text) root.text = flatten(valid[0].title) || fallbackTitle || 'XMind'\n } else {\n // Multi-sheet workbook → a synthetic root holding each sheet's tree.\n root = {\n id: id(),\n text: fallbackTitle || 'XMind 工作簿',\n children: valid.map((s) => {\n const n = jsonTopicToNode(s.rootTopic as JsonTopic, id)\n if (!n.text) n.text = flatten(s.title) || '画布'\n return n\n }),\n }\n }\n return { format: 'xmind', title: root.text, root, count: countNodes(root) }\n}\n\n// ── content.xml (legacy) ──────────────────────────────────────────────────────────────────────\nfunction childByTag(el: Element, tag: string): Element | null {\n for (const c of Array.from(el.children)) if (c.tagName.toLowerCase() === tag) return c\n return null\n}\n\nfunction xmlTopicToNode(topic: Element, id: () => number): MindNode {\n const title = childByTag(topic, 'title')\n const notesEl = childByTag(topic, 'notes')\n const plainEl = notesEl ? childByTag(notesEl, 'plain') : null\n const children: MindNode[] = []\n // <children><topics type=\"attached\"><topic>…</topic></topics></children>\n const childrenEl = childByTag(topic, 'children')\n if (childrenEl) {\n for (const topics of Array.from(childrenEl.children)) {\n if (topics.tagName.toLowerCase() !== 'topics') continue\n for (const c of Array.from(topics.children)) {\n if (c.tagName.toLowerCase() === 'topic') children.push(xmlTopicToNode(c, id))\n }\n }\n }\n return {\n id: id(),\n text: flatten(title?.textContent),\n note: noteOf(flatten(plainEl?.textContent), []),\n link: topic.getAttribute('xlink:href') || topic.getAttribute('href') || undefined,\n children,\n }\n}\n\nfunction fromContentXml(text: string, fallbackTitle: string): MindMap {\n if (typeof DOMParser === 'undefined') throw new NotXmindError('当前环境不支持解析 XMind XML')\n const doc = new DOMParser().parseFromString(text, 'application/xml')\n if (doc.getElementsByTagName('parsererror').length) {\n throw new NotXmindError('content.xml 解析失败(XML 无效)')\n }\n const sheets = Array.from(doc.getElementsByTagName('sheet'))\n const roots: { title: string; topic: Element }[] = []\n for (const sheet of sheets) {\n const topic = childByTag(sheet, 'topic')\n if (topic) roots.push({ title: flatten(childByTag(sheet, 'title')?.textContent), topic })\n }\n if (!roots.length) throw new NotXmindError('XMind 内容为空(无 topic)')\n\n const id = makeIdGen()\n let root: MindNode\n if (roots.length === 1) {\n root = xmlTopicToNode(roots[0].topic, id)\n if (!root.text) root.text = roots[0].title || fallbackTitle || 'XMind'\n } else {\n root = {\n id: id(),\n text: fallbackTitle || 'XMind 工作簿',\n children: roots.map((r) => {\n const n = xmlTopicToNode(r.topic, id)\n if (!n.text) n.text = r.title || '画布'\n return n\n }),\n }\n }\n return { format: 'xmind', title: root.text, root, count: countNodes(root) }\n}\n"],"mappings":";;AAsBA,IAAa,IAAb,cAAmC,MAAM;CACvC,YAAY,GAAiB;EAE3B,AADA,MAAM,CAAO,GACb,KAAK,OAAO;CACd;AACF;AAEA,eAAsB,EAAW,GAAkB,IAAgB,IAAsB;CACvF,IAAI;CACJ,IAAI;EACF,IAAU,EAAQ,CAAG;CACvB,QAAQ;EACN,MAAM,IAAI,EAAc,6BAA6B;CACvD;CACA,IAAM,KAAQ,MACZ,EAAQ,MAAM,MAAM,EAAE,KAAK,YAAY,MAAM,EAAK,YAAY,CAAC,GAE3D,IAAY,EAAK,cAAc;CACrC,IAAI,GAEF,OAAO,EADM,IAAI,YAAY,OAAO,CAAC,CAAC,OAAO,MAAM,EAAgB,GAAK,CAAS,CAC1D,GAAM,CAAa;CAE5C,IAAM,IAAW,EAAK,aAAa;CACnC,IAAI,GAEF,OAAO,EADM,IAAI,YAAY,OAAO,CAAC,CAAC,OAAO,MAAM,EAAgB,GAAK,CAAQ,CAC1D,GAAM,CAAa;CAE3C,MAAM,IAAI,EAAc,6CAA6C;AACvE;AAGA,SAAS,IAA0B;CACjC,IAAI,IAAI;CACR,aAAa;AACf;AACA,SAAS,EAAW,GAAqB;CACvC,IAAI,IAAI;CACR,KAAK,IAAM,KAAK,EAAE,UAAU,KAAK,EAAW,CAAC;CAC7C,OAAO;AACT;AACA,SAAS,EAAQ,GAAsC;CACrD,QAAQ,KAAK,GAAA,CAAI,QAAQ,QAAQ,GAAG,CAAC,CAAC,KAAK;AAC7C;AACA,SAAS,EAAU,GAAmB;CACpC,OAAO,EAAE,QAAQ,YAAY,GAAG;AAClC;AAGA,SAAS,EAAO,GAAe,GAAsC;CACnE,IAAM,IAAkB,CAAC;CAGzB,OAFI,KAAO,EAAM,KAAK,CAAK,GACvB,EAAO,UAAQ,EAAM,KAAK,OAAO,EAAO,KAAK,IAAI,GAAG,GACjD,EAAM,SAAS,EAAM,KAAK,IAAI,IAAI,KAAA;AAC3C;AAeA,SAAS,EAAgB,GAAc,GAA4B;CACjE,IAAM,IAAuB,CAAC,GACxB,IAAM,EAAE,UAAU;CACxB,IAAI,MAAM,QAAQ,CAAG,GAAG,KAAK,IAAM,KAAK,GAAK,EAAS,KAAK,EAAgB,GAAG,CAAE,CAAC;CACjF,IAAM,IAAM,EAAE,UAAU;CACxB,IAAI,MAAM,QAAQ,CAAG,GAAG,KAAK,IAAM,KAAK,GAAK,EAAS,KAAK,EAAgB,GAAG,CAAE,CAAC;CAEjF,IAAM,IACJ,EAAQ,EAAE,OAAO,OAAO,OAAO,KAAK,EAAQ,EAAU,EAAE,OAAO,UAAU,WAAW,EAAE,CAAC,GACnF,IAAS,MAAM,QAAQ,EAAE,MAAM,IACjC,EAAE,OAAO,QAAQ,MAAmB,OAAO,KAAM,QAAQ,IACzD,CAAC;CACL,OAAO;EACL,IAAI,EAAG;EACP,MAAM,EAAQ,EAAE,KAAK;EACrB,MAAM,EAAO,GAAO,CAAM;EAC1B,MAAM,OAAO,EAAE,QAAS,YAAY,EAAE,OAAO,EAAE,OAAO,KAAA;EACtD;CACF;AACF;AAEA,SAAS,EAAgB,GAAc,GAAgC;CACrE,IAAI;CACJ,IAAI;EACF,IAAO,KAAK,MAAM,CAAI;CACxB,QAAQ;EACN,MAAM,IAAI,EAAc,4BAA4B;CACtD;CAGA,IAAM,KADsB,MAAM,QAAQ,CAAI,IAAK,IAAuB,CAAC,CAAiB,EAAA,CACvE,QAAQ,MAAM,KAAK,EAAE,SAAS;CACnD,IAAI,CAAC,EAAM,QAAQ,MAAM,IAAI,EAAc,yBAAyB;CAEpE,IAAM,IAAK,EAAU,GACjB;CAgBJ,OAfI,EAAM,WAAW,KACnB,IAAO,EAAgB,EAAM,EAAE,CAAC,WAAwB,CAAE,GAC1D,AAAgB,EAAK,SAAO,EAAQ,EAAM,EAAE,CAAC,KAAK,KAAK,KAAiB,WAGxE,IAAO;EACL,IAAI,EAAG;EACP,MAAM,KAAiB;EACvB,UAAU,EAAM,KAAK,MAAM;GACzB,IAAM,IAAI,EAAgB,EAAE,WAAwB,CAAE;GAEtD,OADA,AAAa,EAAE,SAAO,EAAQ,EAAE,KAAK,KAAK,MACnC;EACT,CAAC;CACH,GAEK;EAAE,QAAQ;EAAS,OAAO,EAAK;EAAM;EAAM,OAAO,EAAW,CAAI;CAAE;AAC5E;AAGA,SAAS,EAAW,GAAa,GAA6B;CAC5D,KAAK,IAAM,KAAK,MAAM,KAAK,EAAG,QAAQ,GAAG,IAAI,EAAE,QAAQ,YAAY,MAAM,GAAK,OAAO;CACrF,OAAO;AACT;AAEA,SAAS,EAAe,GAAgB,GAA4B;CAClE,IAAM,IAAQ,EAAW,GAAO,OAAO,GACjC,IAAU,EAAW,GAAO,OAAO,GACnC,IAAU,IAAU,EAAW,GAAS,OAAO,IAAI,MACnD,IAAuB,CAAC,GAExB,IAAa,EAAW,GAAO,UAAU;CAC/C,IAAI,GACF;OAAK,IAAM,KAAU,MAAM,KAAK,EAAW,QAAQ,GAC7C,MAAO,QAAQ,YAAY,MAAM,UACrC,KAAK,IAAM,KAAK,MAAM,KAAK,EAAO,QAAQ,GACxC,AAAI,EAAE,QAAQ,YAAY,MAAM,WAAS,EAAS,KAAK,EAAe,GAAG,CAAE,CAAC;CAEhF;CAEF,OAAO;EACL,IAAI,EAAG;EACP,MAAM,EAAQ,GAAO,WAAW;EAChC,MAAM,EAAO,EAAQ,GAAS,WAAW,GAAG,CAAC,CAAC;EAC9C,MAAM,EAAM,aAAa,YAAY,KAAK,EAAM,aAAa,MAAM,KAAK,KAAA;EACxE;CACF;AACF;AAEA,SAAS,EAAe,GAAc,GAAgC;CACpE,IAAI,OAAO,YAAc,KAAa,MAAM,IAAI,EAAc,qBAAqB;CACnF,IAAM,IAAM,IAAI,UAAU,CAAC,CAAC,gBAAgB,GAAM,iBAAiB;CACnE,IAAI,EAAI,qBAAqB,aAAa,CAAC,CAAC,QAC1C,MAAM,IAAI,EAAc,0BAA0B;CAEpD,IAAM,IAAS,MAAM,KAAK,EAAI,qBAAqB,OAAO,CAAC,GACrD,IAA6C,CAAC;CACpD,KAAK,IAAM,KAAS,GAAQ;EAC1B,IAAM,IAAQ,EAAW,GAAO,OAAO;EACvC,AAAI,KAAO,EAAM,KAAK;GAAE,OAAO,EAAQ,EAAW,GAAO,OAAO,CAAC,EAAE,WAAW;GAAG;EAAM,CAAC;CAC1F;CACA,IAAI,CAAC,EAAM,QAAQ,MAAM,IAAI,EAAc,qBAAqB;CAEhE,IAAM,IAAK,EAAU,GACjB;CAeJ,OAdI,EAAM,WAAW,KACnB,IAAO,EAAe,EAAM,EAAE,CAAC,OAAO,CAAE,GACxC,AAAgB,EAAK,SAAO,EAAM,EAAE,CAAC,SAAS,KAAiB,WAE/D,IAAO;EACL,IAAI,EAAG;EACP,MAAM,KAAiB;EACvB,UAAU,EAAM,KAAK,MAAM;GACzB,IAAM,IAAI,EAAe,EAAE,OAAO,CAAE;GAEpC,OADA,AAAa,EAAE,SAAO,EAAE,SAAS,MAC1B;EACT,CAAC;CACH,GAEK;EAAE,QAAQ;EAAS,OAAO,EAAK;EAAM;EAAM,OAAO,EAAW,CAAI;CAAE;AAC5E"}
package/dist/lib/zip.js CHANGED
@@ -167,3 +167,5 @@ async function x(e, t, n) {
167
167
  }
168
168
  //#endregion
169
169
  export { s as ZipEncryptedError, c as ZipPasswordError, x as extractZipEntry, m as readZip, l as zipSupported };
170
+
171
+ //# sourceMappingURL=zip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zip.js","names":[],"sources":["../../src/lib/zip.ts"],"sourcesContent":["/**\n * Minimal in-browser ZIP reader — no dependency, no WASM.\n *\n * Parses the archive's central directory to list entries, then extracts them lazily using the\n * browser-native {@link DecompressionStream} for DEFLATE. Covers what conversation artifacts actually\n * ship: STORE (uncompressed) and DEFLATE, ASCII/UTF-8 names, and the ZIP64 size/offset extensions.\n * Encrypted entries and unusual compression methods are surfaced as errors rather than mis-read.\n *\n * Used by ZipBrowser (the side viewer's archive mode): the bytes come from the same download endpoint\n * as any other file, are decompressed here entirely client-side, and never leave the browser.\n */\n\nimport { aesCtrXor } from '@/lib/aes'\nimport { decodeFileNameBytes } from '@/lib/encoding'\n\nconst SIG_EOCD = 0x06054b50 // end of central directory record\nconst SIG_EOCD64 = 0x06064b50 // ZIP64 end of central directory record\nconst SIG_EOCD64_LOC = 0x07064b50 // ZIP64 EOCD locator\nconst SIG_CDH = 0x02014b50 // central directory file header\nconst SIG_LFH = 0x04034b50 // local file header\n\n/** How an entry is encrypted: none, legacy PKWARE ZipCrypto, or WinZip AES. */\nexport type ZipEncryption = 'none' | 'zipcrypto' | 'aes'\n\nexport interface ZipEntry {\n /** Full path within the archive, forward-slashed, e.g. \"src/app.ts\". */\n path: string\n /** Basename (last path segment). */\n name: string\n /** Uncompressed size in bytes. */\n size: number\n /** Compressed size in bytes (for encrypted entries this includes the crypto header/salt/trailer). */\n compressedSize: number\n /** EFFECTIVE compression method: 0 = stored, 8 = deflate (for AES this is the real method from the extra field, not 99). */\n method: number\n /** Directory entry (its path ends with \"/\"). */\n isDir: boolean\n /** Entry is encrypted (true when {@link encryption} !== 'none'). Kept for callers that only need the flag. */\n encrypted: boolean\n /** Encryption scheme — decrypt needs the password (see {@link extractZipEntry}). */\n encryption: ZipEncryption\n /** CRC-32 from the directory (the ZipCrypto password-check byte is its high byte). */\n crc32: number\n /** WinZip AES parameters (only when {@link encryption} === 'aes'). */\n aes?: { strength: 1 | 2 | 3 }\n /** Byte offset of the local file header (where the data lives). */\n localOffset: number\n}\n\n/** Thrown when an entry is encrypted and no password was supplied — the UI prompts for one. */\nexport class ZipEncryptedError extends Error {\n constructor(message = '该条目已加密,请输入密码') {\n super(message)\n this.name = 'ZipEncryptedError'\n }\n}\n/** Thrown when the supplied password fails the archive's verification (wrong password). */\nexport class ZipPasswordError extends Error {\n constructor(message = '密码错误') {\n super(message)\n this.name = 'ZipPasswordError'\n }\n}\n\n/** Is in-browser inflate available? (DecompressionStream — all current browsers; absent under SSR.) */\nexport function zipSupported(): boolean {\n return typeof DecompressionStream !== 'undefined'\n}\n\n/** Read a little-endian unsigned 64-bit value as a JS number (exact up to 2^53, plenty for our sizes). */\nfunction readU64(view: DataView, off: number): number {\n return view.getUint32(off + 4, true) * 0x100000000 + view.getUint32(off, true)\n}\n\n/** Scan backward from the tail for the EOCD signature (it sits before a variable-length comment). */\nfunction findEocd(view: DataView): number {\n const len = view.byteLength\n const min = Math.max(0, len - 22 - 0xffff)\n for (let i = len - 22; i >= min; i--) {\n if (view.getUint32(i, true) === SIG_EOCD) return i\n }\n throw new Error('不是有效的 ZIP 文件(找不到结尾记录)')\n}\n\n/** Patch any 0xFFFFFFFF sentinel size/offset from the ZIP64 extra field (tag 0x0001, fields in order). */\nfunction applyZip64Extra(\n view: DataView,\n start: number,\n len: number,\n cur: { size: number; compressedSize: number; localOffset: number },\n): void {\n const end = start + len\n let o = start\n while (o + 4 <= end) {\n const id = view.getUint16(o, true)\n const sz = view.getUint16(o + 2, true)\n if (id === 0x0001) {\n let f = o + 4\n if (cur.size === 0xffffffff) {\n cur.size = readU64(view, f)\n f += 8\n }\n if (cur.compressedSize === 0xffffffff) {\n cur.compressedSize = readU64(view, f)\n f += 8\n }\n if (cur.localOffset === 0xffffffff) {\n cur.localOffset = readU64(view, f)\n }\n return\n }\n o += 4 + sz\n }\n}\n\n/** Read the WinZip AES extra field (id 0x9901) from an entry's extra data: strength + real method. */\nfunction parseAesExtra(\n view: DataView,\n start: number,\n len: number,\n): { strength: 1 | 2 | 3; method: number } | null {\n const end = start + len\n let o = start\n while (o + 4 <= end) {\n const id = view.getUint16(o, true)\n const sz = view.getUint16(o + 2, true)\n if (id === 0x9901 && o + 11 <= end) {\n // data: [0-1] version, [2-3] vendor \"AE\", [4] strength (1/2/3), [5-6] actual compression method\n const strength = view.getUint8(o + 8)\n const method = view.getUint16(o + 9, true)\n if (strength >= 1 && strength <= 3) return { strength: strength as 1 | 2 | 3, method }\n }\n o += 4 + sz\n }\n return null\n}\n\n/** Parse the central directory into a flat entry list. Throws if the bytes aren't a readable ZIP. */\nexport function readZip(buf: ArrayBuffer): ZipEntry[] {\n const view = new DataView(buf)\n if (view.byteLength < 22) throw new Error('文件太小,不是有效的 ZIP')\n const eocd = findEocd(view)\n\n let cdCount = view.getUint16(eocd + 10, true)\n let cdOffset = view.getUint32(eocd + 16, true)\n\n // ZIP64: sentinels in the classic EOCD redirect to a 64-bit record via the locator just before it.\n if (cdCount === 0xffff || cdOffset === 0xffffffff) {\n const loc = eocd - 20\n if (loc >= 0 && view.getUint32(loc, true) === SIG_EOCD64_LOC) {\n const rec = readU64(view, loc + 8)\n if (rec >= 0 && rec + 56 <= view.byteLength && view.getUint32(rec, true) === SIG_EOCD64) {\n cdCount = readU64(view, rec + 32)\n cdOffset = readU64(view, rec + 48)\n }\n }\n }\n\n const bytes = new Uint8Array(buf)\n const entries: ZipEntry[] = []\n let p = cdOffset\n for (let i = 0; i < cdCount; i++) {\n if (p + 46 > view.byteLength || view.getUint32(p, true) !== SIG_CDH) break\n const flags = view.getUint16(p + 8, true)\n const method = view.getUint16(p + 10, true)\n const fnLen = view.getUint16(p + 28, true)\n const extraLen = view.getUint16(p + 30, true)\n const commentLen = view.getUint16(p + 32, true)\n const cur = {\n size: view.getUint32(p + 24, true),\n compressedSize: view.getUint32(p + 20, true),\n localOffset: view.getUint32(p + 42, true),\n }\n // bit 11 flags UTF-8 names, but legacy zips (esp. from Chinese Windows) store GBK without it — so we\n // sniff the encoding (UTF-8 → GBK → \\uXXXX escape) rather than force UTF-8. Backslashes normalize to '/'\n // (the spec mandates '/', but Windows' Compress-Archive emits '\\', which would flatten a nested tree).\n const path = decodeFileNameBytes(bytes.subarray(p + 46, p + 46 + fnLen), true)\n if (\n cur.size === 0xffffffff ||\n cur.compressedSize === 0xffffffff ||\n cur.localOffset === 0xffffffff\n ) {\n applyZip64Extra(view, p + 46 + fnLen, extraLen, cur)\n }\n // Encryption: AES (method 99 + the 0x9901 extra, which carries the REAL method) vs legacy ZipCrypto\n // (general-purpose flag bit 0). For AES the effective method becomes the real one from the extra.\n const crc32 = view.getUint32(p + 16, true)\n let encryption: ZipEncryption = 'none'\n let effMethod = method\n let aes: { strength: 1 | 2 | 3 } | undefined\n if (method === 99) {\n const info = parseAesExtra(view, p + 46 + fnLen, extraLen)\n if (info) {\n encryption = 'aes'\n effMethod = info.method\n aes = { strength: info.strength }\n }\n } else if ((flags & 0x1) !== 0) {\n encryption = 'zipcrypto'\n }\n entries.push({\n path,\n name: path.replace(/\\/+$/, '').split('/').pop() ?? path,\n size: cur.size,\n compressedSize: cur.compressedSize,\n method: effMethod,\n isDir: path.endsWith('/'),\n encrypted: encryption !== 'none',\n encryption,\n crc32,\n aes,\n localOffset: cur.localOffset,\n })\n p += 46 + fnLen + extraLen + commentLen\n }\n return entries\n}\n\n/** Inflate a raw DEFLATE stream via the browser. */\nasync function inflateRaw(data: Uint8Array): Promise<Uint8Array> {\n const stream = new Blob([data]).stream().pipeThrough(new DecompressionStream('deflate-raw'))\n return new Uint8Array(await new Response(stream).arrayBuffer())\n}\n\n// ── encryption ────────────────────────────────────────────────────────────────────────────────\n// Two schemes appear in the wild: legacy PKWARE \"ZipCrypto\" (a weak keystream cipher, still what most\n// \"password-protected zip\" tools default to) and WinZip AES (PBKDF2-HMAC-SHA1 → AES-CTR, used by 7-Zip/WinZip).\n// Both are decrypted here entirely client-side; the password never leaves the browser.\n\nconst CRC_TABLE = /* @__PURE__ */ (() => {\n const t = new Uint32Array(256)\n for (let n = 0; n < 256; n++) {\n let c = n\n for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1\n t[n] = c >>> 0\n }\n return t\n})()\nconst crc32Byte = (crc: number, b: number): number =>\n ((crc >>> 8) ^ CRC_TABLE[(crc ^ b) & 0xff]) >>> 0\n\n// PKWARE ZipCrypto: three 32-bit keys evolved one byte at a time.\nclass ZipCryptoState {\n private k0 = 0x12345678\n private k1 = 0x23456789\n private k2 = 0x34567890\n constructor(pw: Uint8Array) {\n for (const b of pw) this.update(b)\n }\n private update(b: number): void {\n this.k0 = crc32Byte(this.k0, b)\n this.k1 = (this.k1 + (this.k0 & 0xff)) >>> 0\n this.k1 = (Math.imul(this.k1, 134775813) + 1) >>> 0\n this.k2 = crc32Byte(this.k2, (this.k1 >>> 24) & 0xff)\n }\n decryptByte(cipher: number): number {\n const t = (this.k2 | 2) & 0xffff\n const plain = (cipher ^ ((Math.imul(t, t ^ 1) >>> 8) & 0xff)) & 0xff\n this.update(plain)\n return plain\n }\n}\n\n// Decrypt a ZipCrypto blob: the first 12 bytes are a header whose last byte must equal the CRC's high byte\n// (the password check); returns the remaining plaintext (still deflate-compressed / stored).\nfunction zipCryptoDecrypt(data: Uint8Array, pw: Uint8Array, checkByte: number): Uint8Array {\n if (data.length < 12) throw new ZipPasswordError()\n const st = new ZipCryptoState(pw)\n const out = new Uint8Array(data.length)\n for (let i = 0; i < data.length; i++) out[i] = st.decryptByte(data[i])\n if (out[11] !== (checkByte & 0xff)) throw new ZipPasswordError()\n return out.subarray(12)\n}\n\n// Decrypt a WinZip AES blob: [salt][pwVerify(2)][ciphertext][authCode(10)]. PBKDF2-HMAC-SHA1(1000) derives\n// encKey ‖ authKey ‖ pwVerify(2); we check pwVerify (wrong password) and CTR-decrypt (auth code not verified).\nasync function winzipAesDecrypt(\n data: Uint8Array,\n pw: Uint8Array,\n strength: 1 | 2 | 3,\n): Promise<Uint8Array> {\n const saltLen = [8, 12, 16][strength - 1]\n const keyLen = [16, 24, 32][strength - 1]\n if (data.length < saltLen + 2 + 10) throw new ZipPasswordError()\n if (typeof crypto === 'undefined' || !crypto.subtle) {\n throw new Error('当前环境不支持 AES 解密(缺少 WebCrypto)')\n }\n const salt = data.subarray(0, saltLen)\n const pwVerify = data.subarray(saltLen, saltLen + 2)\n const cipher = data.subarray(saltLen + 2, data.length - 10)\n const baseKey = await crypto.subtle.importKey('raw', pw, 'PBKDF2', false, ['deriveBits'])\n const derived = new Uint8Array(\n await crypto.subtle.deriveBits(\n { name: 'PBKDF2', hash: 'SHA-1', salt, iterations: 1000 },\n baseKey,\n (keyLen * 2 + 2) * 8,\n ),\n )\n if (derived[keyLen * 2] !== pwVerify[0] || derived[keyLen * 2 + 1] !== pwVerify[1]) {\n throw new ZipPasswordError()\n }\n return aesCtrXor(derived.subarray(0, keyLen), cipher)\n}\n\n/** Decompress one entry's bytes. Reads the local header (its name/extra lengths can differ from the central\n * directory's) to find the data, decrypts it first when encrypted (ZipCrypto / WinZip AES — needs `password`),\n * then STORE-copies or DEFLATE-inflates. Throws {@link ZipEncryptedError} if a password is required but missing,\n * and {@link ZipPasswordError} if the supplied password is wrong. */\nexport async function extractZipEntry(\n buf: ArrayBuffer,\n e: ZipEntry,\n password?: string,\n): Promise<Uint8Array> {\n if (e.isDir || e.size === 0) return new Uint8Array(0)\n\n const view = new DataView(buf)\n if (e.localOffset + 30 > view.byteLength || view.getUint32(e.localOffset, true) !== SIG_LFH) {\n throw new Error('本地文件头损坏')\n }\n const fnLen = view.getUint16(e.localOffset + 26, true)\n const extraLen = view.getUint16(e.localOffset + 28, true)\n const start = e.localOffset + 30 + fnLen + extraLen\n if (start + e.compressedSize > buf.byteLength) throw new Error('条目数据超出文件范围')\n\n // The raw local data; for an encrypted entry this is the crypto blob (header/salt + ciphertext + trailer).\n let data: Uint8Array = new Uint8Array(buf, start, e.compressedSize)\n\n if (e.encryption !== 'none') {\n if (!password) throw new ZipEncryptedError()\n const pw = new TextEncoder().encode(password)\n if (e.encryption === 'zipcrypto') {\n // ZipCrypto password-check byte: normally the CRC's high byte, but when a data descriptor is used\n // (flag bit 3, CRC unknown at write time) it's the high byte of the DOS mod-time instead.\n const lflags = view.getUint16(e.localOffset + 6, true)\n const ltime = view.getUint16(e.localOffset + 10, true)\n const checkByte = lflags & 0x8 ? (ltime >> 8) & 0xff : (e.crc32 >>> 24) & 0xff\n data = zipCryptoDecrypt(data, pw, checkByte)\n } else {\n data = await winzipAesDecrypt(data, pw, e.aes?.strength ?? 3)\n }\n }\n\n if (e.method === 0) return data.slice() // stored — copy out so callers own the bytes\n if (e.method === 8) {\n if (!zipSupported()) throw new Error('当前浏览器不支持在前端解压(DecompressionStream 缺失)')\n return inflateRaw(data) // deflate\n }\n throw new Error(`不支持的压缩方式(method ${e.method})`)\n}\n"],"mappings":"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"}