@l1yp/file-viewer 0.1.1 → 0.1.3

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 (440) hide show
  1. package/README.md +1 -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 +2 -0
  47. package/dist/components/DocxNavigationPane.js.map +1 -0
  48. package/dist/components/DocxNavigationPane.vue_vue_type_script_setup_true_lang.js +2 -0
  49. package/dist/components/DocxNavigationPane.vue_vue_type_script_setup_true_lang.js.map +1 -0
  50. package/dist/components/DocxViewer.js +2 -0
  51. package/dist/components/DocxViewer.js.map +1 -0
  52. package/dist/components/DocxViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  53. package/dist/components/DocxViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  54. package/dist/components/DrawioViewer.js +2 -0
  55. package/dist/components/DrawioViewer.js.map +1 -0
  56. package/dist/components/DrawioViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  57. package/dist/components/DrawioViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  58. package/dist/components/DxfViewer.js +2 -0
  59. package/dist/components/DxfViewer.js.map +1 -0
  60. package/dist/components/DxfViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  61. package/dist/components/DxfViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  62. package/dist/components/EbookViewer.js +2 -0
  63. package/dist/components/EbookViewer.js.map +1 -0
  64. package/dist/components/EbookViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  65. package/dist/components/EbookViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  66. package/dist/components/EmlViewer.js +2 -0
  67. package/dist/components/EmlViewer.js.map +1 -0
  68. package/dist/components/EmlViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  69. package/dist/components/EmlViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  70. package/dist/components/EplViewer.js +2 -0
  71. package/dist/components/EplViewer.js.map +1 -0
  72. package/dist/components/EplViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  73. package/dist/components/EplViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  74. package/dist/components/FileViewerBody.js +3 -1
  75. package/dist/components/FileViewerBody.js.map +1 -0
  76. package/dist/components/FileViewerBody.vue_vue_type_script_setup_true_lang.js +2 -0
  77. package/dist/components/FileViewerBody.vue_vue_type_script_setup_true_lang.js.map +1 -0
  78. package/dist/components/FileViewerPanel.js +2 -0
  79. package/dist/components/FileViewerPanel.js.map +1 -0
  80. package/dist/components/FileViewerPanel.vue_vue_type_script_setup_true_lang.js +2 -0
  81. package/dist/components/FileViewerPanel.vue_vue_type_script_setup_true_lang.js.map +1 -0
  82. package/dist/components/FontViewer.js +2 -0
  83. package/dist/components/FontViewer.js.map +1 -0
  84. package/dist/components/FontViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  85. package/dist/components/FontViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  86. package/dist/components/FrontmatterCard.js +2 -0
  87. package/dist/components/FrontmatterCard.js.map +1 -0
  88. package/dist/components/FrontmatterCard.vue_vue_type_script_setup_true_lang.js +2 -0
  89. package/dist/components/FrontmatterCard.vue_vue_type_script_setup_true_lang.js.map +1 -0
  90. package/dist/components/GeoViewer.js +2 -0
  91. package/dist/components/GeoViewer.js.map +1 -0
  92. package/dist/components/GeoViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  93. package/dist/components/GeoViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  94. package/dist/components/HarViewer.js +2 -0
  95. package/dist/components/HarViewer.js.map +1 -0
  96. package/dist/components/HarViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  97. package/dist/components/HarViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  98. package/dist/components/HexViewer.js +2 -0
  99. package/dist/components/HexViewer.js.map +1 -0
  100. package/dist/components/HexViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  101. package/dist/components/HexViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  102. package/dist/components/HprofViewer.js +2 -0
  103. package/dist/components/HprofViewer.js.map +1 -0
  104. package/dist/components/HprofViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  105. package/dist/components/HprofViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  106. package/dist/components/ImageLightbox.js +2 -0
  107. package/dist/components/ImageLightbox.js.map +1 -0
  108. package/dist/components/ImageLightbox.vue_vue_type_script_setup_true_lang.js +2 -0
  109. package/dist/components/ImageLightbox.vue_vue_type_script_setup_true_lang.js.map +1 -0
  110. package/dist/components/InlineText.js +2 -0
  111. package/dist/components/InlineText.js.map +1 -0
  112. package/dist/components/JksViewer.js +2 -0
  113. package/dist/components/JksViewer.js.map +1 -0
  114. package/dist/components/JksViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  115. package/dist/components/JksViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  116. package/dist/components/JsonlViewer.js +3 -1
  117. package/dist/components/JsonlViewer.js.map +1 -0
  118. package/dist/components/JsonlViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  119. package/dist/components/JsonlViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  120. package/dist/components/LogViewer.js +2 -0
  121. package/dist/components/LogViewer.js.map +1 -0
  122. package/dist/components/LogViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  123. package/dist/components/LogViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  124. package/dist/components/LrcViewer.js +2 -0
  125. package/dist/components/LrcViewer.js.map +1 -0
  126. package/dist/components/LrcViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  127. package/dist/components/LrcViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  128. package/dist/components/MarkdownTable.js +2 -0
  129. package/dist/components/MarkdownTable.js.map +1 -0
  130. package/dist/components/MarkdownTable.vue_vue_type_script_setup_true_lang.js +2 -0
  131. package/dist/components/MarkdownTable.vue_vue_type_script_setup_true_lang.js.map +1 -0
  132. package/dist/components/MarkdownText.js +2 -0
  133. package/dist/components/MarkdownText.js.map +1 -0
  134. package/dist/components/MhtViewer.js +2 -0
  135. package/dist/components/MhtViewer.js.map +1 -0
  136. package/dist/components/MhtViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  137. package/dist/components/MhtViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  138. package/dist/components/MindMapView.js +2 -0
  139. package/dist/components/MindMapView.js.map +1 -0
  140. package/dist/components/MindMapView.vue_vue_type_script_setup_true_lang.js +2 -0
  141. package/dist/components/MindMapView.vue_vue_type_script_setup_true_lang.js.map +1 -0
  142. package/dist/components/MissingDependency.js +2 -0
  143. package/dist/components/MissingDependency.js.map +1 -0
  144. package/dist/components/MissingDependency.vue_vue_type_script_setup_true_lang.js +2 -0
  145. package/dist/components/MissingDependency.vue_vue_type_script_setup_true_lang.js.map +1 -0
  146. package/dist/components/ModelViewer.js +2 -0
  147. package/dist/components/ModelViewer.js.map +1 -0
  148. package/dist/components/ModelViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  149. package/dist/components/ModelViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  150. package/dist/components/MsiViewer.js +2 -0
  151. package/dist/components/MsiViewer.js.map +1 -0
  152. package/dist/components/MsiViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  153. package/dist/components/MsiViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  154. package/dist/components/NotebookViewer.js +2 -0
  155. package/dist/components/NotebookViewer.js.map +1 -0
  156. package/dist/components/NotebookViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  157. package/dist/components/NotebookViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  158. package/dist/components/PdfNavigationPane.js +9 -0
  159. package/dist/components/PdfNavigationPane.js.map +1 -0
  160. package/dist/components/PdfNavigationPane.vue.d.ts +24 -0
  161. package/dist/components/PdfNavigationPane.vue_vue_type_script_setup_true_lang.js +149 -0
  162. package/dist/components/PdfNavigationPane.vue_vue_type_script_setup_true_lang.js.map +1 -0
  163. package/dist/components/PdfViewer.js +3 -1
  164. package/dist/components/PdfViewer.js.map +1 -0
  165. package/dist/components/PdfViewer.vue.d.ts +0 -11
  166. package/dist/components/PdfViewer.vue_vue_type_script_setup_true_lang.js +133 -69
  167. package/dist/components/PdfViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  168. package/dist/components/PptxNavigationPane.js +2 -0
  169. package/dist/components/PptxNavigationPane.js.map +1 -0
  170. package/dist/components/PptxNavigationPane.vue_vue_type_script_setup_true_lang.js +2 -0
  171. package/dist/components/PptxNavigationPane.vue_vue_type_script_setup_true_lang.js.map +1 -0
  172. package/dist/components/PptxViewer.js +3 -1
  173. package/dist/components/PptxViewer.js.map +1 -0
  174. package/dist/components/PptxViewer.vue_vue_type_script_setup_true_lang.js +55 -49
  175. package/dist/components/PptxViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  176. package/dist/components/PsdViewer.js +2 -0
  177. package/dist/components/PsdViewer.js.map +1 -0
  178. package/dist/components/PsdViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  179. package/dist/components/PsdViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  180. package/dist/components/QmcAudioViewer.js +2 -0
  181. package/dist/components/QmcAudioViewer.js.map +1 -0
  182. package/dist/components/QmcAudioViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  183. package/dist/components/QmcAudioViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  184. package/dist/components/RasterViewer.js +2 -0
  185. package/dist/components/RasterViewer.js.map +1 -0
  186. package/dist/components/RasterViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  187. package/dist/components/RasterViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  188. package/dist/components/RtfViewer.js +2 -0
  189. package/dist/components/RtfViewer.js.map +1 -0
  190. package/dist/components/RtfViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  191. package/dist/components/RtfViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  192. package/dist/components/SevenZipBrowser.js +2 -0
  193. package/dist/components/SevenZipBrowser.js.map +1 -0
  194. package/dist/components/SevenZipBrowser.vue_vue_type_script_setup_true_lang.js +2 -0
  195. package/dist/components/SevenZipBrowser.vue_vue_type_script_setup_true_lang.js.map +1 -0
  196. package/dist/components/SqliteViewer.js +2 -0
  197. package/dist/components/SqliteViewer.js.map +1 -0
  198. package/dist/components/SqliteViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  199. package/dist/components/SqliteViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  200. package/dist/components/SubtitleViewer.js +2 -0
  201. package/dist/components/SubtitleViewer.js.map +1 -0
  202. package/dist/components/SubtitleViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  203. package/dist/components/SubtitleViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  204. package/dist/components/XlsxChart.js +2 -0
  205. package/dist/components/XlsxChart.js.map +1 -0
  206. package/dist/components/XlsxChart.vue_vue_type_script_setup_true_lang.js +2 -0
  207. package/dist/components/XlsxChart.vue_vue_type_script_setup_true_lang.js.map +1 -0
  208. package/dist/components/XlsxViewer.js +2 -0
  209. package/dist/components/XlsxViewer.js.map +1 -0
  210. package/dist/components/XlsxViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  211. package/dist/components/XlsxViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  212. package/dist/components/XmindViewer.js +2 -0
  213. package/dist/components/XmindViewer.js.map +1 -0
  214. package/dist/components/XmindViewer.vue_vue_type_script_setup_true_lang.js +2 -0
  215. package/dist/components/XmindViewer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  216. package/dist/components/ZipBrowser.js +2 -0
  217. package/dist/components/ZipBrowser.js.map +1 -0
  218. package/dist/components/ZipBrowser.vue_vue_type_script_setup_true_lang.js +2 -0
  219. package/dist/components/ZipBrowser.vue_vue_type_script_setup_true_lang.js.map +1 -0
  220. package/dist/components/ZoomImage.js +3 -1
  221. package/dist/components/ZoomImage.js.map +1 -0
  222. package/dist/components/ZoomImage.vue_vue_type_script_setup_true_lang.js +82 -80
  223. package/dist/components/ZoomImage.vue_vue_type_script_setup_true_lang.js.map +1 -0
  224. package/dist/components/epl/EplCodeBlock.js +2 -0
  225. package/dist/components/epl/EplCodeBlock.js.map +1 -0
  226. package/dist/components/epl/EplCodeBlock.vue_vue_type_script_setup_true_lang.js +2 -0
  227. package/dist/components/epl/EplCodeBlock.vue_vue_type_script_setup_true_lang.js.map +1 -0
  228. package/dist/components/epl/EplDoc.js +2 -0
  229. package/dist/components/epl/EplDoc.js.map +1 -0
  230. package/dist/components/epl/EplDoc.vue_vue_type_script_setup_true_lang.js +2 -0
  231. package/dist/components/epl/EplDoc.vue_vue_type_script_setup_true_lang.js.map +1 -0
  232. package/dist/components/epl/EplMethod.js +2 -0
  233. package/dist/components/epl/EplMethod.js.map +1 -0
  234. package/dist/components/epl/EplMethod.vue_vue_type_script_setup_true_lang.js +2 -0
  235. package/dist/components/epl/EplMethod.vue_vue_type_script_setup_true_lang.js.map +1 -0
  236. package/dist/components/epl/EplResource.js +2 -0
  237. package/dist/components/epl/EplResource.js.map +1 -0
  238. package/dist/components/epl/EplResource.vue_vue_type_script_setup_true_lang.js +2 -0
  239. package/dist/components/epl/EplResource.vue_vue_type_script_setup_true_lang.js.map +1 -0
  240. package/dist/components/epl/EplTree.js +2 -0
  241. package/dist/components/epl/EplTree.js.map +1 -0
  242. package/dist/components/epl/EplTree.vue_vue_type_script_setup_true_lang.js +2 -0
  243. package/dist/components/epl/EplTree.vue_vue_type_script_setup_true_lang.js.map +1 -0
  244. package/dist/components/epl/EplVarTable.js +2 -0
  245. package/dist/components/epl/EplVarTable.js.map +1 -0
  246. package/dist/components/epl/EplVarTable.vue_vue_type_script_setup_true_lang.js +2 -0
  247. package/dist/components/epl/EplVarTable.vue_vue_type_script_setup_true_lang.js.map +1 -0
  248. package/dist/components/epl/numbering.js +2 -0
  249. package/dist/components/epl/numbering.js.map +1 -0
  250. package/dist/components/icons/Icon.js +2 -0
  251. package/dist/components/icons/Icon.js.map +1 -0
  252. package/dist/components/icons/Icon.vue_vue_type_script_setup_true_lang.js +2 -0
  253. package/dist/components/icons/Icon.vue_vue_type_script_setup_true_lang.js.map +1 -0
  254. package/dist/components/icons/iconPaths.js +2 -0
  255. package/dist/components/icons/iconPaths.js.map +1 -0
  256. package/dist/components/optionalViewer.js +2 -0
  257. package/dist/components/optionalViewer.js.map +1 -0
  258. package/dist/components/ui/ClampBlock.js +2 -0
  259. package/dist/components/ui/ClampBlock.js.map +1 -0
  260. package/dist/composables/useElementNavigation.js +2 -0
  261. package/dist/composables/useElementNavigation.js.map +1 -0
  262. package/dist/composables/useFileViewer.js +2 -0
  263. package/dist/composables/useFileViewer.js.map +1 -0
  264. package/dist/composables/useLightbox.js +2 -0
  265. package/dist/composables/useLightbox.js.map +1 -0
  266. package/dist/composables/useLogRules.js +2 -0
  267. package/dist/composables/useLogRules.js.map +1 -0
  268. package/dist/lib/aes.js +2 -0
  269. package/dist/lib/aes.js.map +1 -0
  270. package/dist/lib/appx.js +2 -0
  271. package/dist/lib/appx.js.map +1 -0
  272. package/dist/lib/archiveHtml.js +2 -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.js +2 -0
  303. package/dist/lib/docxNavigation.js.map +1 -0
  304. package/dist/lib/dxf.js +2 -0
  305. package/dist/lib/dxf.js.map +1 -0
  306. package/dist/lib/eml.js +2 -0
  307. package/dist/lib/eml.js.map +1 -0
  308. package/dist/lib/encoding.js +2 -0
  309. package/dist/lib/encoding.js.map +1 -0
  310. package/dist/lib/epl/code/codeDataParser.js +2 -0
  311. package/dist/lib/epl/code/codeDataParser.js.map +1 -0
  312. package/dist/lib/epl/code/codeLines.js +2 -0
  313. package/dist/lib/epl/code/codeLines.js.map +1 -0
  314. package/dist/lib/epl/code/textCode.js +2 -0
  315. package/dist/lib/epl/code/textCode.js.map +1 -0
  316. package/dist/lib/epl/eplDocument.js +2 -0
  317. package/dist/lib/epl/eplDocument.js.map +1 -0
  318. package/dist/lib/epl/imageList.js +2 -0
  319. package/dist/lib/epl/imageList.js.map +1 -0
  320. package/dist/lib/epl/index.js +2 -0
  321. package/dist/lib/epl/index.js.map +1 -0
  322. package/dist/lib/epl/io/binaryReader.js +2 -0
  323. package/dist/lib/epl/io/binaryReader.js.map +1 -0
  324. package/dist/lib/epl/io/encoding.js +2 -0
  325. package/dist/lib/epl/io/encoding.js.map +1 -0
  326. package/dist/lib/epl/model/eplSystemId.js +2 -0
  327. package/dist/lib/epl/model/eplSystemId.js.map +1 -0
  328. package/dist/lib/epl/names/eplLibData.js +2 -0
  329. package/dist/lib/epl/names/eplLibData.js.map +1 -0
  330. package/dist/lib/epl/names/idToNameMap.js +2 -0
  331. package/dist/lib/epl/names/idToNameMap.js.map +1 -0
  332. package/dist/lib/epl/names/libNameProvider.js +2 -0
  333. package/dist/lib/epl/names/libNameProvider.js.map +1 -0
  334. package/dist/lib/epl/program.js +2 -0
  335. package/dist/lib/epl/program.js.map +1 -0
  336. package/dist/lib/epl/projectFileReader.js +2 -0
  337. package/dist/lib/epl/projectFileReader.js.map +1 -0
  338. package/dist/lib/fb2.js +2 -0
  339. package/dist/lib/fb2.js.map +1 -0
  340. package/dist/lib/fileType.js +2 -0
  341. package/dist/lib/fileType.js.map +1 -0
  342. package/dist/lib/fonts.js +2 -0
  343. package/dist/lib/fonts.js.map +1 -0
  344. package/dist/lib/format.js +2 -0
  345. package/dist/lib/format.js.map +1 -0
  346. package/dist/lib/frontmatter.js +2 -0
  347. package/dist/lib/frontmatter.js.map +1 -0
  348. package/dist/lib/geo.js +2 -0
  349. package/dist/lib/geo.js.map +1 -0
  350. package/dist/lib/har.js +2 -0
  351. package/dist/lib/har.js.map +1 -0
  352. package/dist/lib/highlight.js +2 -0
  353. package/dist/lib/highlight.js.map +1 -0
  354. package/dist/lib/highlightLangs.js +2 -0
  355. package/dist/lib/highlightLangs.js.map +1 -0
  356. package/dist/lib/hprof.js +2 -0
  357. package/dist/lib/hprof.js.map +1 -0
  358. package/dist/lib/ipynb.js +2 -0
  359. package/dist/lib/ipynb.js.map +1 -0
  360. package/dist/lib/jks.js +2 -0
  361. package/dist/lib/jks.js.map +1 -0
  362. package/dist/lib/jsonl.js +2 -0
  363. package/dist/lib/jsonl.js.map +1 -0
  364. package/dist/lib/lrc.js +2 -0
  365. package/dist/lib/lrc.js.map +1 -0
  366. package/dist/lib/lzma.js +2 -0
  367. package/dist/lib/lzma.js.map +1 -0
  368. package/dist/lib/markdown/blocks.js +2 -0
  369. package/dist/lib/markdown/blocks.js.map +1 -0
  370. package/dist/lib/markdown/inline.js +2 -0
  371. package/dist/lib/markdown/inline.js.map +1 -0
  372. package/dist/lib/markdown/math.js +2 -0
  373. package/dist/lib/markdown/math.js.map +1 -0
  374. package/dist/lib/markdown/segmentize.js +2 -0
  375. package/dist/lib/markdown/segmentize.js.map +1 -0
  376. package/dist/lib/markdown/styles.js +2 -0
  377. package/dist/lib/markdown/styles.js.map +1 -0
  378. package/dist/lib/mht.js +2 -0
  379. package/dist/lib/mht.js.map +1 -0
  380. package/dist/lib/midi.js +2 -0
  381. package/dist/lib/midi.js.map +1 -0
  382. package/dist/lib/mime.js +2 -0
  383. package/dist/lib/mime.js.map +1 -0
  384. package/dist/lib/mindmap.js +2 -0
  385. package/dist/lib/mindmap.js.map +1 -0
  386. package/dist/lib/mobi.js +2 -0
  387. package/dist/lib/mobi.js.map +1 -0
  388. package/dist/lib/msi.js +2 -0
  389. package/dist/lib/msi.js.map +1 -0
  390. package/dist/lib/optionalDep.js +2 -0
  391. package/dist/lib/optionalDep.js.map +1 -0
  392. package/dist/lib/pdfNavigation.d.ts +11 -0
  393. package/dist/lib/pdfNavigation.js +32 -0
  394. package/dist/lib/pdfNavigation.js.map +1 -0
  395. package/dist/lib/pkcs12.js +2 -0
  396. package/dist/lib/pkcs12.js.map +1 -0
  397. package/dist/lib/pptxNavigation.js +2 -0
  398. package/dist/lib/pptxNavigation.js.map +1 -0
  399. package/dist/lib/qmc.js +2 -0
  400. package/dist/lib/qmc.js.map +1 -0
  401. package/dist/lib/rar.js +2 -0
  402. package/dist/lib/rar.js.map +1 -0
  403. package/dist/lib/rawPreview.js +2 -0
  404. package/dist/lib/rawPreview.js.map +1 -0
  405. package/dist/lib/rc2.js +2 -0
  406. package/dist/lib/rc2.js.map +1 -0
  407. package/dist/lib/resolveInput.js +2 -0
  408. package/dist/lib/resolveInput.js.map +1 -0
  409. package/dist/lib/rtf.js +2 -0
  410. package/dist/lib/rtf.js.map +1 -0
  411. package/dist/lib/sevenZip.js +2 -0
  412. package/dist/lib/sevenZip.js.map +1 -0
  413. package/dist/lib/sha1.js +2 -0
  414. package/dist/lib/sha1.js.map +1 -0
  415. package/dist/lib/sha256.js +2 -0
  416. package/dist/lib/sha256.js.map +1 -0
  417. package/dist/lib/speechAudio.js +2 -0
  418. package/dist/lib/speechAudio.js.map +1 -0
  419. package/dist/lib/sqlite.js +2 -0
  420. package/dist/lib/sqlite.js.map +1 -0
  421. package/dist/lib/subtitle.js +2 -0
  422. package/dist/lib/subtitle.js.map +1 -0
  423. package/dist/lib/tarball.js +2 -0
  424. package/dist/lib/tarball.js.map +1 -0
  425. package/dist/lib/viewerFormats.js +2 -0
  426. package/dist/lib/viewerFormats.js.map +1 -0
  427. package/dist/lib/viewerKind.js +2 -0
  428. package/dist/lib/viewerKind.js.map +1 -0
  429. package/dist/lib/x509.js +2 -0
  430. package/dist/lib/x509.js.map +1 -0
  431. package/dist/lib/xlsx.js +2 -0
  432. package/dist/lib/xlsx.js.map +1 -0
  433. package/dist/lib/xlsxCharts.js +2 -0
  434. package/dist/lib/xlsxCharts.js.map +1 -0
  435. package/dist/lib/xmind.js +2 -0
  436. package/dist/lib/xmind.js.map +1 -0
  437. package/dist/lib/zip.js +2 -0
  438. package/dist/lib/zip.js.map +1 -0
  439. package/dist/style.css +1 -1
  440. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter.js","names":[],"sources":["../../src/lib/frontmatter.ts"],"sourcesContent":["import { load as parseYaml } from 'js-yaml'\n\n/**\n * Split leading YAML frontmatter (a `---` … `---` block at the very top, as used by\n * SKILL.md and friends) from the markdown body.\n *\n * `data` is the parsed mapping (empty when there's no frontmatter or it's malformed /\n * not a mapping); `body` is the rest of the document with the block removed. On any\n * parse failure we fall back to `{ data: {}, body: <original text> }` so nothing is lost.\n */\nexport interface ParsedFrontmatter {\n data: Record<string, unknown>\n body: string\n}\n\n// Opening `---` must be the first line; the block ends at the next line that is exactly\n// `---`. Non-greedy so the *first* closing fence wins. (A leading BOM is stripped below.)\nconst FM_RE = /^---[ \\t]*\\r?\\n([\\s\\S]*?)\\r?\\n---[ \\t]*(?:\\r?\\n|$)/\n\nexport function parseFrontmatter(input: string): ParsedFrontmatter {\n // Tolerate a UTF-8 BOM so the opening fence still anchors to the start.\n const text = input.charCodeAt(0) === 0xfeff ? input.slice(1) : input\n const m = text.match(FM_RE)\n if (!m) return { data: {}, body: text }\n try {\n const parsed = parseYaml(m[1])\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n return { data: parsed as Record<string, unknown>, body: text.slice(m[0].length) }\n }\n } catch {\n /* malformed YAML — fall through and render the whole text untouched */\n }\n return { data: {}, body: text }\n}\n"],"mappings":";;AAiBA,IAAM,IAAQ;AAEd,SAAgB,EAAiB,GAAkC;CAEjE,IAAM,IAAO,EAAM,WAAW,CAAC,MAAM,QAAS,EAAM,MAAM,CAAC,IAAI,GACzD,IAAI,EAAK,MAAM,CAAK;CAC1B,IAAI,CAAC,GAAG,OAAO;EAAE,MAAM,CAAC;EAAG,MAAM;CAAK;CACtC,IAAI;EACF,IAAM,IAAS,EAAU,EAAE,EAAE;EAC7B,IAAI,KAAU,OAAO,KAAW,YAAY,CAAC,MAAM,QAAQ,CAAM,GAC/D,OAAO;GAAE,MAAM;GAAmC,MAAM,EAAK,MAAM,EAAE,EAAE,CAAC,MAAM;EAAE;CAEpF,QAAQ,CAER;CACA,OAAO;EAAE,MAAM,CAAC;EAAG,MAAM;CAAK;AAChC"}
package/dist/lib/geo.js CHANGED
@@ -233,3 +233,5 @@ function f(e, t) {
233
233
  }
234
234
  //#endregion
235
235
  export { f as parseGeo };
236
+
237
+ //# sourceMappingURL=geo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geo.js","names":[],"sources":["../../src/lib/geo.ts"],"sourcesContent":["/**\n * Hand-rolled, zero-dependency parser for the three common geodata formats, normalized to a flat feature\n * list the side viewer can draw as an offline SVG map (no tile server — internal network):\n * - GeoJSON (.geojson/.json): FeatureCollection / Feature / bare geometry; all geometry types incl. Multi* +\n * GeometryCollection. Positions are [lon, lat(, alt)].\n * - KML (.kml): <Placemark> with Point / LineString / Polygon (incl. inside MultiGeometry); `lon,lat,alt`\n * whitespace-separated coordinate tuples.\n * - GPX (.gpx): <wpt> waypoints (points), <rte>/<rtept> routes and <trk>/<trkseg>/<trkpt> tracks (lines);\n * coordinates are `lat`/`lon` attributes.\n *\n * Each geometry is reduced to point / line / polygon primitives (polygon = outer ring only — holes are\n * dropped for the preview). Positions stay as [lon, lat]; the viewer owns the map projection.\n */\n\nexport type GeoKind = 'point' | 'line' | 'polygon'\n\nexport interface GeoGeom {\n kind: GeoKind\n /** [lon, lat] positions: point → 1, line → N, polygon → its outer ring. */\n coords: [number, number][]\n}\n\nexport interface GeoFeature {\n name: string\n geoms: GeoGeom[]\n props: Record<string, string>\n}\n\nexport interface ParsedGeo {\n format: 'geojson' | 'kml' | 'gpx'\n features: GeoFeature[]\n}\n\nfunction isFinitePair(v: unknown): v is [number, number] {\n return (\n Array.isArray(v) &&\n typeof v[0] === 'number' &&\n typeof v[1] === 'number' &&\n Number.isFinite(v[0]) &&\n Number.isFinite(v[1])\n )\n}\n\nfunction pos(v: unknown): [number, number] | null {\n return isFinitePair(v) ? [v[0], v[1]] : null\n}\n\nfunction ring(v: unknown): [number, number][] {\n if (!Array.isArray(v)) return []\n const out: [number, number][] = []\n for (const p of v) {\n const pp = pos(p)\n if (pp) out.push(pp)\n }\n return out\n}\n\n// ---- GeoJSON ------------------------------------------------------------------------------------\n\ntype AnyObj = Record<string, unknown>\n\nfunction geomToPrimitives(geometry: unknown, into: GeoGeom[]): void {\n if (typeof geometry !== 'object' || geometry === null) return\n const g = geometry as AnyObj\n const c = g.coordinates\n switch (g.type) {\n case 'Point': {\n const p = pos(c)\n if (p) into.push({ kind: 'point', coords: [p] })\n break\n }\n case 'MultiPoint':\n for (const p of ring(c)) into.push({ kind: 'point', coords: [p] })\n break\n case 'LineString': {\n const line = ring(c)\n if (line.length) into.push({ kind: 'line', coords: line })\n break\n }\n case 'MultiLineString':\n if (Array.isArray(c))\n for (const ln of c) {\n const line = ring(ln)\n if (line.length) into.push({ kind: 'line', coords: line })\n }\n break\n case 'Polygon': {\n const outer = Array.isArray(c) ? ring(c[0]) : []\n if (outer.length) into.push({ kind: 'polygon', coords: outer })\n break\n }\n case 'MultiPolygon':\n if (Array.isArray(c))\n for (const poly of c) {\n const outer = Array.isArray(poly) ? ring(poly[0]) : []\n if (outer.length) into.push({ kind: 'polygon', coords: outer })\n }\n break\n case 'GeometryCollection':\n if (Array.isArray(g.geometries)) for (const sub of g.geometries) geomToPrimitives(sub, into)\n break\n }\n}\n\nfunction propsToStrings(props: unknown): { name: string; props: Record<string, string> } {\n const out: Record<string, string> = {}\n let name = ''\n if (typeof props === 'object' && props !== null) {\n for (const [k, v] of Object.entries(props as AnyObj)) {\n if (v == null || typeof v === 'object') continue\n out[k] = String(v)\n }\n name = out.name || out.Name || out.NAME || out.title || out.Title || ''\n }\n return { name, props: out }\n}\n\nfunction fromGeoJson(text: string): GeoFeature[] {\n const root = JSON.parse(text) as unknown\n const features: GeoFeature[] = []\n const handle = (obj: unknown): void => {\n if (typeof obj !== 'object' || obj === null) return\n const o = obj as AnyObj\n if (o.type === 'FeatureCollection' && Array.isArray(o.features)) {\n for (const f of o.features) handle(f)\n } else if (o.type === 'Feature') {\n const geoms: GeoGeom[] = []\n geomToPrimitives(o.geometry, geoms)\n const { name, props } = propsToStrings(o.properties)\n if (geoms.length) features.push({ name, geoms, props })\n } else if (typeof o.type === 'string') {\n // A bare geometry object.\n const geoms: GeoGeom[] = []\n geomToPrimitives(o, geoms)\n if (geoms.length) features.push({ name: '', geoms, props: {} })\n }\n }\n handle(root)\n return features\n}\n\n// ---- XML helpers (KML / GPX) --------------------------------------------------------------------\n\nfunction parseXml(text: string): Document | null {\n if (typeof DOMParser === 'undefined') return null\n const doc = new DOMParser().parseFromString(text, 'application/xml')\n return doc.getElementsByTagName('parsererror').length ? null : doc\n}\n\nfunction childText(el: Element, tag: string): string {\n for (const c of Array.from(el.children)) {\n if (c.tagName.toLowerCase() === tag.toLowerCase()) return (c.textContent || '').trim()\n }\n return ''\n}\n\n// KML `lon,lat,alt lon,lat,alt …` (any whitespace between tuples) → [lon, lat] positions.\nfunction parseKmlCoords(text: string): [number, number][] {\n const out: [number, number][] = []\n for (const tuple of text.trim().split(/\\s+/)) {\n if (!tuple) continue\n const parts = tuple.split(',')\n const lon = parseFloat(parts[0])\n const lat = parseFloat(parts[1])\n if (Number.isFinite(lon) && Number.isFinite(lat)) out.push([lon, lat])\n }\n return out\n}\n\nfunction fromKml(text: string): GeoFeature[] {\n const doc = parseXml(text)\n if (!doc) return []\n const features: GeoFeature[] = []\n for (const pm of Array.from(doc.getElementsByTagName('Placemark'))) {\n const geoms: GeoGeom[] = []\n // getElementsByTagName recurses, so this also reaches geometry nested in <MultiGeometry>.\n for (const pt of Array.from(pm.getElementsByTagName('Point'))) {\n const c = parseKmlCoords(childText(pt, 'coordinates'))\n if (c[0]) geoms.push({ kind: 'point', coords: [c[0]] })\n }\n for (const ls of Array.from(pm.getElementsByTagName('LineString'))) {\n const c = parseKmlCoords(childText(ls, 'coordinates'))\n if (c.length) geoms.push({ kind: 'line', coords: c })\n }\n for (const pg of Array.from(pm.getElementsByTagName('Polygon'))) {\n // outer ring: the <coordinates> inside <outerBoundaryIs>; fall back to the first <coordinates>.\n const outer = pg.getElementsByTagName('outerBoundaryIs')[0] ?? pg\n const cEl = outer.getElementsByTagName('coordinates')[0]\n const c = parseKmlCoords(cEl?.textContent || '')\n if (c.length) geoms.push({ kind: 'polygon', coords: c })\n }\n if (geoms.length) {\n const name = childText(pm, 'name')\n const desc = childText(pm, 'description')\n const props: Record<string, string> = {}\n if (desc) props.description = desc\n features.push({ name, geoms, props })\n }\n }\n return features\n}\n\nfunction ptOf(el: Element): [number, number] | null {\n const lat = parseFloat(el.getAttribute('lat') || '')\n const lon = parseFloat(el.getAttribute('lon') || '')\n return Number.isFinite(lat) && Number.isFinite(lon) ? [lon, lat] : null\n}\n\nfunction fromGpx(text: string): GeoFeature[] {\n const doc = parseXml(text)\n if (!doc) return []\n const features: GeoFeature[] = []\n // Waypoints → points.\n for (const wpt of Array.from(doc.getElementsByTagName('wpt'))) {\n const p = ptOf(wpt)\n if (p)\n features.push({\n name: childText(wpt, 'name'),\n geoms: [{ kind: 'point', coords: [p] }],\n props: {},\n })\n }\n // Routes → a line of rtept.\n for (const rte of Array.from(doc.getElementsByTagName('rte'))) {\n const pts: [number, number][] = []\n for (const rp of Array.from(rte.getElementsByTagName('rtept'))) {\n const p = ptOf(rp)\n if (p) pts.push(p)\n }\n if (pts.length)\n features.push({\n name: childText(rte, 'name'),\n geoms: [{ kind: 'line', coords: pts }],\n props: {},\n })\n }\n // Tracks → one line per <trkseg>.\n for (const trk of Array.from(doc.getElementsByTagName('trk'))) {\n const geoms: GeoGeom[] = []\n for (const seg of Array.from(trk.getElementsByTagName('trkseg'))) {\n const pts: [number, number][] = []\n for (const tp of Array.from(seg.getElementsByTagName('trkpt'))) {\n const p = ptOf(tp)\n if (p) pts.push(p)\n }\n if (pts.length) geoms.push({ kind: 'line', coords: pts })\n }\n if (geoms.length) features.push({ name: childText(trk, 'name'), geoms, props: {} })\n }\n return features\n}\n\n/** Parse geodata source text into a normalized feature list. `ext` (when known) disambiguates the format. */\nexport function parseGeo(text: string, ext?: string): ParsedGeo {\n const e = (ext || '').toLowerCase()\n if (e === 'kml' || /<kml[\\s>]/i.test(text)) return { format: 'kml', features: fromKml(text) }\n if (e === 'gpx' || /<gpx[\\s>]/i.test(text)) return { format: 'gpx', features: fromGpx(text) }\n return { format: 'geojson', features: fromGeoJson(text) }\n}\n"],"mappings":"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"}
package/dist/lib/har.js CHANGED
@@ -395,3 +395,5 @@ function B(e) {
395
395
  }
396
396
  //#endregion
397
397
  export { M as decodeContent, N as decodePostData, z as fmtMs, R as fmtSize, b as parseHar, F as parseQuery, P as prettyBody, B as statusClass, L as toCurl };
398
+
399
+ //# sourceMappingURL=har.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"har.js","names":[],"sources":["../../src/lib/har.ts"],"sourcesContent":["/**\n * HAR (HTTP Archive 1.2) 解析与展示层 —— 纯逻辑,不依赖 Vue / DOM。\n *\n * 移植自 sqlite-viewer 项目(D:\\web-work\\sqlite-viewer\\src\\har\\har.ts),但做成**自包含**:原项目里\n * 依赖的 base64 / utf8 / hex / JSON 美化工具直接内联在本文件,避免引入第三方或跨模块依赖(与本仓库\n * lib/eml.ts、lib/mht.ts「手搓零依赖」的一致风格)。\n *\n * 职责:\n * 1) 把任意 HAR JSON 文本解析为规范化的 HarDoc / HarEntry(带预计算的展示字段);\n * 2) 解码请求/响应 body:标准 `encoding:\"base64\"` + 部分工具(Reqable 等)「body 被 Base64 编码但\n * 未声明」的情况自动识别;\n * 3) Header / Cookie / Query / 表单等格式化查看所需的工具函数;\n * 4) 导出 cURL。\n */\n\n/* ============ 内联字节工具(原 crypto/bytes.ts 子集) ============ */\n\nconst td = new TextDecoder('utf-8', { fatal: false })\n\nfunction bytesToUtf8(b: Uint8Array): string {\n return td.decode(b)\n}\n\nfunction bytesToHex(b: Uint8Array, sep = ' '): string {\n let s = ''\n for (let i = 0; i < b.length; i++) {\n s += (i && sep ? sep : '') + b[i].toString(16).padStart(2, '0')\n }\n return s.toUpperCase()\n}\n\n/** Base64 转字节,自动兼容 URL-safe(-_)与缺失的 padding。非法字符由 atob 抛错。 */\nfunction base64ToBytes(s: string): Uint8Array {\n let t = s\n .replace(/[\\r\\n\\t ]/g, '')\n .replace(/-/g, '+')\n .replace(/_/g, '/')\n const pad = t.length % 4\n if (pad) t += '='.repeat(4 - pad)\n const bin = atob(t)\n const out = new Uint8Array(bin.length)\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i)\n return out\n}\n\n/* ============ HAR 原始结构(1.2 子集,字段尽量宽松) ============ */\n\nexport interface HarNV {\n name: string\n value: string\n}\nexport interface HarCookie {\n name: string\n value: string\n path?: string\n domain?: string\n expires?: string | null\n httpOnly?: boolean\n secure?: boolean\n sameSite?: string\n}\nexport interface HarPostParam {\n name: string\n value?: string\n fileName?: string\n contentType?: string\n}\nexport interface HarPostData {\n mimeType?: string\n text?: string\n params?: HarPostParam[]\n encoding?: string // 非标准:部分工具用它标记 text 为 base64\n comment?: string\n}\nexport interface HarContent {\n size?: number\n compression?: number\n mimeType?: string\n text?: string\n encoding?: string // \"base64\" 时 text 为 base64\n}\nexport interface HarRequest {\n method: string\n url: string\n httpVersion?: string\n headers: HarNV[]\n queryString: HarNV[]\n cookies: HarCookie[]\n headersSize?: number\n bodySize?: number\n postData?: HarPostData\n}\nexport interface HarResponse {\n status: number\n statusText?: string\n httpVersion?: string\n headers: HarNV[]\n cookies: HarCookie[]\n content: HarContent\n redirectURL?: string\n headersSize?: number\n bodySize?: number\n}\nexport interface HarTimings {\n blocked?: number\n dns?: number\n connect?: number\n send?: number\n wait?: number\n receive?: number\n ssl?: number\n}\nexport interface HarEntryRaw {\n startedDateTime?: string\n time?: number\n request: HarRequest\n response: HarResponse\n timings?: HarTimings\n serverIPAddress?: string\n connection?: string\n resourceType?: string\n}\n\n/* ============ 规范化展示模型 ============ */\n\n/** 请求资源大类(用于颜色 / 快捷筛选) */\nexport type HarCategory = 'doc' | 'xhr' | 'js' | 'css' | 'img' | 'font' | 'media' | 'ws' | 'other'\n\nexport interface HarEntry {\n index: number // 原始顺序(稳定 id)\n method: string\n url: string\n scheme: string // http / https / ws / wss\n host: string\n path: string // pathname(含 query,用于列表展示)\n pathname: string // 仅路径\n status: number\n statusText: string\n category: HarCategory\n type: string // 短类型标签(json / html / png …)\n mime: string // 响应内容 mime(去掉 charset)\n size: number // 响应 body 字节数\n reqSize: number // 请求 body 字节数\n time: number // 总耗时 ms\n startedISO: string\n startedMs: number // epoch ms(排序用,无法解析则 0)\n serverIP: string\n raw: HarEntryRaw\n}\n\nexport interface HarDoc {\n entries: HarEntry[]\n creator: string\n version: string\n}\n\n/* ============ 小工具:安全读取 unknown ============ */\n\nfunction isObj(v: unknown): v is Record<string, unknown> {\n return !!v && typeof v === 'object'\n}\nfunction str(v: unknown, dflt = ''): string {\n return typeof v === 'string' ? v : dflt\n}\nfunction num(v: unknown, dflt = 0): number {\n return typeof v === 'number' && Number.isFinite(v) ? v : dflt\n}\nfunction bool(v: unknown): boolean {\n return v === true\n}\nfunction arr(v: unknown): unknown[] {\n return Array.isArray(v) ? v : []\n}\n\nfunction readNVs(v: unknown): HarNV[] {\n return arr(v)\n .filter(isObj)\n .map((o) => ({ name: str(o.name), value: str(o.value) }))\n}\nfunction readCookies(v: unknown): HarCookie[] {\n return arr(v)\n .filter(isObj)\n .map((o) => ({\n name: str(o.name),\n value: str(o.value),\n path: str(o.path) || undefined,\n domain: str(o.domain) || undefined,\n expires: typeof o.expires === 'string' ? o.expires : null,\n httpOnly: bool(o.httpOnly),\n secure: bool(o.secure),\n sameSite: str(o.sameSite) || undefined,\n }))\n}\nfunction readPostData(v: unknown): HarPostData | undefined {\n if (!isObj(v)) return undefined\n const params = arr(v.params)\n .filter(isObj)\n .map((o) => ({\n name: str(o.name),\n value: typeof o.value === 'string' ? o.value : undefined,\n fileName: str(o.fileName) || undefined,\n contentType: str(o.contentType) || undefined,\n }))\n return {\n mimeType: str(v.mimeType) || undefined,\n text: typeof v.text === 'string' ? v.text : undefined,\n params: params.length ? params : undefined,\n encoding: str(v.encoding) || undefined,\n comment: str(v.comment) || undefined,\n }\n}\n\n/* ============ URL / mime / 分类 ============ */\n\n/** 拆分 URL(容错:非法 URL 时退化为整串当 path) */\nexport function splitUrl(url: string): {\n scheme: string\n host: string\n pathname: string\n path: string\n} {\n try {\n const u = new URL(url)\n const scheme = u.protocol.replace(/:$/, '')\n return { scheme, host: u.host, pathname: u.pathname, path: u.pathname + u.search }\n } catch {\n return { scheme: '', host: '', pathname: url, path: url }\n }\n}\n\n/** 去掉 mime 的 charset/boundary 等参数,返回主类型 */\nexport function shortMime(mime: string): string {\n return (mime.split(';')[0] || '').trim().toLowerCase()\n}\n\nconst IMG_RE = /^image\\//\nconst FONT_RE = /font|woff/\nconst MEDIA_RE = /^(audio|video)\\//\n\n/** 由响应 mime + url + status 推断资源大类与短标签 */\nexport function categorize(\n mime: string,\n scheme: string,\n status: number,\n rt: string,\n): { category: HarCategory; type: string } {\n const m = shortMime(mime)\n const sub = m.includes('/') ? m.split('/')[1] : m\n const rtl = rt.toLowerCase()\n\n if (scheme === 'ws' || scheme === 'wss' || status === 101 || rtl === 'websocket') {\n return { category: 'ws', type: 'ws' }\n }\n if (IMG_RE.test(m)) return { category: 'img', type: sub === 'svg+xml' ? 'svg' : sub }\n if (FONT_RE.test(m)) return { category: 'font', type: sub.replace('x-', '') || 'font' }\n if (MEDIA_RE.test(m)) return { category: 'media', type: sub }\n if (m === 'text/css') return { category: 'css', type: 'css' }\n if (m.includes('javascript') || m.includes('ecmascript') || sub === 'json') {\n return {\n category: m.includes('json') || sub === 'json' ? 'xhr' : 'js',\n type: sub === 'json' ? 'json' : 'js',\n }\n }\n if (m === 'text/html' || m === 'application/xhtml+xml') return { category: 'doc', type: 'html' }\n if (m.includes('xml')) return { category: 'xhr', type: 'xml' }\n if (m === 'application/x-www-form-urlencoded') return { category: 'xhr', type: 'form' }\n if (m.startsWith('text/')) return { category: 'xhr', type: sub || 'text' }\n if (m) return { category: 'other', type: sub || 'bin' }\n return { category: 'other', type: '' }\n}\n\nfunction epochMs(iso: string): number {\n if (!iso) return 0\n const t = Date.parse(iso)\n return Number.isFinite(t) ? t : 0\n}\n\n/* ============ 解析入口 ============ */\n\nfunction normalizeEntry(raw: unknown, index: number): HarEntry | null {\n if (!isObj(raw)) return null\n const reqO = isObj(raw.request) ? raw.request : null\n const resO = isObj(raw.response) ? raw.response : null\n if (!reqO) return null\n\n const request: HarRequest = {\n method: str(reqO.method, 'GET').toUpperCase(),\n url: str(reqO.url),\n httpVersion: str(reqO.httpVersion) || undefined,\n headers: readNVs(reqO.headers),\n queryString: readNVs(reqO.queryString),\n cookies: readCookies(reqO.cookies),\n headersSize: num(reqO.headersSize, -1),\n bodySize: num(reqO.bodySize, -1),\n postData: readPostData(reqO.postData),\n }\n\n const contentO = resO && isObj(resO.content) ? resO.content : null\n const content: HarContent = {\n size: num(contentO?.size, -1),\n compression: num(contentO?.compression, 0),\n mimeType: str(contentO?.mimeType) || undefined,\n text: typeof contentO?.text === 'string' ? contentO.text : undefined,\n encoding: str(contentO?.encoding) || undefined,\n }\n const response: HarResponse = {\n status: num(resO?.status, 0),\n statusText: str(resO?.statusText) || undefined,\n httpVersion: str(resO?.httpVersion) || undefined,\n headers: readNVs(resO?.headers),\n cookies: readCookies(resO?.cookies),\n content,\n redirectURL: str(resO?.redirectURL) || undefined,\n headersSize: num(resO?.headersSize, -1),\n bodySize: num(resO?.bodySize, -1),\n }\n\n const timings: HarTimings | undefined = isObj(raw.timings)\n ? {\n blocked: num(raw.timings.blocked, -1),\n dns: num(raw.timings.dns, -1),\n connect: num(raw.timings.connect, -1),\n send: num(raw.timings.send, -1),\n wait: num(raw.timings.wait, -1),\n receive: num(raw.timings.receive, -1),\n ssl: num(raw.timings.ssl, -1),\n }\n : undefined\n\n const rt = str(raw.resourceType) || str((raw as Record<string, unknown>)._resourceType)\n const entryRaw: HarEntryRaw = {\n startedDateTime: str(raw.startedDateTime) || undefined,\n time: num(raw.time, -1),\n request,\n response,\n timings,\n serverIPAddress: str(raw.serverIPAddress) || undefined,\n connection: str(raw.connection) || undefined,\n resourceType: rt || undefined,\n }\n\n const { scheme, host, pathname, path } = splitUrl(request.url)\n const mime = shortMime(content.mimeType ?? '')\n const { category, type } = categorize(mime, scheme, response.status, rt)\n const size =\n content.size != null && content.size >= 0 ? content.size : Math.max(0, response.bodySize ?? 0)\n const reqSize = request.bodySize != null && request.bodySize >= 0 ? request.bodySize : 0\n const startedISO = entryRaw.startedDateTime ?? ''\n\n return {\n index,\n method: request.method,\n url: request.url,\n scheme,\n host,\n path: path || '/',\n pathname: pathname || '/',\n status: response.status,\n statusText: response.statusText ?? '',\n category,\n type,\n mime,\n size,\n reqSize,\n time: entryRaw.time != null && entryRaw.time >= 0 ? entryRaw.time : 0,\n startedISO,\n startedMs: epochMs(startedISO),\n serverIP: entryRaw.serverIPAddress ?? '',\n raw: entryRaw,\n }\n}\n\n/** 解析 HAR 文本。非法 / 无 log.entries 时抛错。 */\nexport function parseHar(text: string): HarDoc {\n let root: unknown\n try {\n root = JSON.parse(text)\n } catch (e) {\n throw new Error('不是合法的 JSON:' + (e instanceof Error ? e.message : String(e)))\n }\n const logO = isObj(root) && isObj(root.log) ? root.log : null\n if (!logO || !Array.isArray(logO.entries)) {\n throw new Error('不是有效的 HAR 文件(缺少 log.entries)')\n }\n const entries: HarEntry[] = []\n for (const raw of logO.entries) {\n const e = normalizeEntry(raw, entries.length)\n if (e) entries.push(e)\n }\n if (!entries.length) throw new Error('HAR 中没有可解析的请求条目')\n\n const creatorO = isObj(logO.creator) ? logO.creator : null\n const creator = creatorO ? `${str(creatorO.name, '?')} ${str(creatorO.version)}`.trim() : ''\n return { entries, creator, version: str(logO.version, '1.2') }\n}\n\n/* ============ body 解码(含 base64 自动识别) ============ */\n\nexport type BodyDecodeMode = 'auto' | 'raw' | 'base64'\n\nexport interface DecodedBody {\n kind: 'empty' | 'text' | 'binary' | 'form'\n text: string // 文本视图(binary 时为 hex 预览)\n mime: string\n size: number // 字节数(尽量真实)\n wasBase64: boolean // 是否做了 base64 解码\n isBase64Guess: boolean // 原文是否疑似 base64(供 UI 提示开关)\n isImage: boolean\n dataUri: string // 图片预览用(仅 image 且有字节时)\n form?: HarPostParam[] // 表单字段\n}\n\nconst EMPTY_BODY: DecodedBody = {\n kind: 'empty',\n text: '',\n mime: '',\n size: 0,\n wasBase64: false,\n isBase64Guess: false,\n isImage: false,\n dataUri: '',\n}\n\n/** 文本型 mime(可直接当字符串展示) */\nexport function isTextualMime(mime: string): boolean {\n const m = shortMime(mime)\n if (!m) return true // 未知按文本尝试\n if (m.startsWith('text/')) return true\n return (\n m.includes('json') ||\n m.includes('xml') ||\n m.includes('javascript') ||\n m.includes('ecmascript') ||\n m.includes('x-www-form-urlencoded') ||\n m.includes('graphql') ||\n m.includes('csv') ||\n m.includes('yaml')\n )\n}\nexport function isImageMime(mime: string): boolean {\n return IMG_RE.test(shortMime(mime))\n}\n\n/** 严格判断字符串是否「像」标准 base64(用于自动解码未声明编码的 body) */\nexport function looksLikeBase64(s: string): boolean {\n const t = s.trim()\n if (t.length < 8 || t.length % 4 !== 0) return false\n if (!/^[A-Za-z0-9+/]+={0,2}$/.test(t)) return false\n const eq = t.indexOf('=')\n if (eq !== -1 && eq < t.length - 2) return false\n return true\n}\n\n/** 含 U+FFFD 替换符即认为不是有效 UTF-8 文本(解码后判二进制) */\nfunction hasReplacement(s: string): boolean {\n return s.indexOf('�') !== -1\n}\n\nfunction hexPreview(bytes: Uint8Array, limit = 4096): string {\n const slice = bytes.length > limit ? bytes.subarray(0, limit) : bytes\n const hex = bytesToHex(slice)\n return bytes.length > limit ? hex + `\\n… (${bytes.length} bytes total)` : hex\n}\n\nfunction bytesToDataUri(bytes: Uint8Array, mime: string): string {\n let bin = ''\n const chunk = 0x8000\n for (let i = 0; i < bytes.length; i += chunk) {\n bin += String.fromCharCode(...bytes.subarray(i, i + chunk))\n }\n return `data:${shortMime(mime) || 'application/octet-stream'};base64,${btoa(bin)}`\n}\n\n/** 把已确定的字节按 mime 整理为 DecodedBody(文本/二进制/图片) */\nfunction bytesToBody(\n bytes: Uint8Array,\n mime: string,\n wasBase64: boolean,\n isBase64Guess: boolean,\n): DecodedBody {\n if (isImageMime(mime)) {\n return {\n kind: 'binary',\n text: hexPreview(bytes),\n mime,\n size: bytes.length,\n wasBase64,\n isBase64Guess,\n isImage: true,\n dataUri: bytesToDataUri(bytes, mime),\n }\n }\n const text = bytesToUtf8(bytes)\n const binary = hasReplacement(text) && !isTextualMime(mime)\n return {\n kind: binary ? 'binary' : 'text',\n text: binary ? hexPreview(bytes) : text,\n mime,\n size: bytes.length,\n wasBase64,\n isBase64Guess,\n isImage: false,\n dataUri: '',\n }\n}\n\nfunction utf8Size(s: string): number {\n let n = 0\n for (let i = 0; i < s.length; i++) {\n const c = s.charCodeAt(i)\n if (c < 0x80) n += 1\n else if (c < 0x800) n += 2\n else if (c >= 0xd800 && c <= 0xdbff) {\n n += 4\n i++\n } else n += 3\n }\n return n\n}\n\n/** SVG 文本 → 可供 <img> 预览的 data URI。用 utf8 + encodeURIComponent,避免 btoa 对非 latin1 报错。 */\nfunction svgDataUri(svgText: string): string {\n return 'data:image/svg+xml;utf8,' + encodeURIComponent(svgText)\n}\n\nfunction textBody(text: string, mime: string, guess: boolean): DecodedBody {\n const m = shortMime(mime)\n return {\n kind: 'text',\n text,\n mime: m,\n size: utf8Size(text),\n wasBase64: false,\n isBase64Guess: guess,\n isImage: false,\n dataUri: m === 'image/svg+xml' ? svgDataUri(text) : '',\n }\n}\n\n/** 解码响应内容 content。mode 控制是否对未声明编码的 body 做 base64 解码。 */\nexport function decodeContent(content: HarContent, mode: BodyDecodeMode = 'auto'): DecodedBody {\n const text = content.text ?? ''\n const mime = content.mimeType ?? ''\n if (!text) return { ...EMPTY_BODY, mime: shortMime(mime), size: Math.max(0, content.size ?? 0) }\n\n const declaredB64 = (content.encoding ?? '').toLowerCase() === 'base64'\n const guess = looksLikeBase64(text)\n const doDecode = mode === 'base64' || (mode !== 'raw' && (declaredB64 || guess))\n\n if (doDecode) {\n try {\n const bytes = base64ToBytes(text)\n const body = bytesToBody(bytes, mime, true, guess || declaredB64)\n // 自动模式下若解出来是带替换符的「文本」mime,说明大概率不是 base64,回退原文\n if (mode === 'auto' && !declaredB64 && body.kind === 'text' && hasReplacement(body.text)) {\n return textBody(text, mime, guess)\n }\n return body\n } catch {\n /* 解码失败 → 当作文本 */\n }\n }\n return textBody(text, mime, guess)\n}\n\n/** 解码请求体 postData。表单优先以字段表展示。 */\nexport function decodePostData(\n post: HarPostData | undefined,\n mode: BodyDecodeMode = 'auto',\n): DecodedBody {\n if (!post) return EMPTY_BODY\n const mime = post.mimeType ?? ''\n if (post.params && post.params.length) {\n return {\n ...EMPTY_BODY,\n kind: 'form',\n mime: shortMime(mime),\n form: post.params,\n size: post.params.reduce((a, p) => a + (p.value?.length ?? 0), 0),\n }\n }\n const text = post.text ?? ''\n if (!text) return { ...EMPTY_BODY, mime: shortMime(mime) }\n\n const declaredB64 = (post.encoding ?? '').toLowerCase() === 'base64'\n const guess = looksLikeBase64(text)\n const doDecode = mode === 'base64' || (mode !== 'raw' && (declaredB64 || guess))\n if (doDecode) {\n try {\n const bytes = base64ToBytes(text)\n const body = bytesToBody(bytes, mime, true, guess || declaredB64)\n if (mode === 'auto' && !declaredB64 && body.kind === 'text' && hasReplacement(body.text)) {\n return textBody(text, mime, guess)\n }\n return body\n } catch {\n /* ignore */\n }\n }\n return textBody(text, mime, guess)\n}\n\n/* ============ 格式化展示辅助 ============ */\n\n/** 若 body 是 JSON(或疑似 JSON)则美化,返回 {text, pretty} */\nexport function prettyBody(text: string, mime: string): { text: string; pretty: boolean } {\n const m = shortMime(mime)\n const trimmed = text.trim()\n const jsonish =\n m.includes('json') ||\n ((trimmed.startsWith('{') || trimmed.startsWith('[')) &&\n (trimmed.endsWith('}') || trimmed.endsWith(']')))\n if (jsonish) {\n try {\n return { text: JSON.stringify(JSON.parse(text), null, 2), pretty: true }\n } catch {\n /* 非法 JSON → 原样 */\n }\n }\n return { text, pretty: false }\n}\n\n/** body 高亮所用的语言(对齐 highlight.js / 本仓库 hljsLang)。注意 svg 含 \"xml\",须先于 xml 判定。 */\nexport function bodyLang(mime: string): string {\n const m = shortMime(mime)\n if (m.includes('javascript') || m.includes('ecmascript')) return 'javascript'\n if (m === 'text/css') return 'css'\n if (m === 'text/html' || m === 'application/xhtml+xml') return 'xml'\n if (m.includes('json')) return 'json'\n if (m.includes('svg') || m.includes('xml')) return 'xml'\n return ''\n}\n\n/** 解析 query string 为 K/V(容错,按 & 与 = 拆) */\nexport function parseQuery(search: string): HarNV[] {\n const s = search.startsWith('?') ? search.slice(1) : search\n if (!s) return []\n return s.split('&').map((pair) => {\n const i = pair.indexOf('=')\n const k = i === -1 ? pair : pair.slice(0, i)\n const v = i === -1 ? '' : pair.slice(i + 1)\n const dec = (x: string) => {\n try {\n return decodeURIComponent(x.replace(/\\+/g, ' '))\n } catch {\n return x\n }\n }\n return { name: dec(k), value: dec(v) }\n })\n}\n\n/** 取某个 header(大小写不敏感) */\nexport function header(list: HarNV[], name: string): string {\n const n = name.toLowerCase()\n const hit = list.find((h) => h.name.toLowerCase() === n)\n return hit ? hit.value : ''\n}\n\nconst SKIP_CURL_HEADERS = new Set(['content-length', 'host', 'connection'])\n\n/** 导出为 cURL 命令 */\nexport function toCurl(entry: HarEntry): string {\n const r = entry.raw.request\n const parts = [`curl '${entry.url}'`]\n if (r.method && r.method !== 'GET') parts.push(`-X ${r.method}`)\n for (const h of r.headers) {\n if (h.name.startsWith(':')) continue // http/2 伪头\n if (SKIP_CURL_HEADERS.has(h.name.toLowerCase())) continue\n parts.push(`-H '${h.name}: ${h.value.replace(/'/g, \"'\\\\''\")}'`)\n }\n const body = decodePostData(r.postData, 'auto')\n if (body.kind === 'form' && body.form) {\n for (const p of body.form) parts.push(`--data-urlencode '${p.name}=${p.value ?? ''}'`)\n } else if (body.text) {\n parts.push(`--data-raw '${body.text.replace(/'/g, \"'\\\\''\")}'`)\n }\n return parts.join(' \\\\\\n ')\n}\n\n/* ============ 通用格式化(大小 / 耗时 / 状态色) ============ */\n\nexport function fmtSize(n: number): string {\n if (n <= 0) return '0'\n if (n < 1024) return n + ' B'\n if (n < 1024 * 1024) return (n / 1024).toFixed(1) + ' KB'\n return (n / (1024 * 1024)).toFixed(2) + ' MB'\n}\nexport function fmtMs(n: number): string {\n if (n <= 0) return '0 ms'\n if (n < 1000) return Math.round(n) + ' ms'\n return (n / 1000).toFixed(2) + ' s'\n}\n/** 状态码颜色类:2xx 绿 / 3xx 蓝 / 4xx 橙 / 5xx 红 / 0 灰 */\nexport function statusClass(status: number): string {\n if (status === 0) return 's-pending'\n if (status < 300) return 's-2xx'\n if (status < 400) return 's-3xx'\n if (status < 500) return 's-4xx'\n return 's-5xx'\n}\n"],"mappings":"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"}
@@ -32,3 +32,5 @@ function i(t, i) {
32
32
  }
33
33
  //#endregion
34
34
  export { r as escapeHtml, n as highlightCode, i as highlightLines };
35
+
36
+ //# sourceMappingURL=highlight.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"highlight.js","names":[],"sources":["../../src/lib/highlight.ts"],"sourcesContent":["import hljs from 'highlight.js'\n\nconst cache = new Map<string, string>()\n\n/**\n * Syntax-highlight `code` with highlight.js, returning escaped HTML.\n * Unlike the original (which polled for a CDN global and could return null),\n * highlight.js is bundled here so this always returns a string. Results are\n * memoized so re-renders / theme toggles don't re-tokenize.\n */\nexport function highlightCode(code: string, label?: string): string {\n const key = `${label ?? ''} ${code}`\n const hit = cache.get(key)\n if (hit !== undefined) return hit\n let out: string\n try {\n out =\n label && hljs.getLanguage(label)\n ? hljs.highlight(code, { language: label, ignoreIllegals: true }).value\n : hljs.highlightAuto(code).value\n } catch {\n out = escapeHtml(code)\n }\n cache.set(key, out)\n return out\n}\n\nexport function escapeHtml(s: string): string {\n return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')\n}\n\n/**\n * Highlight `code` and split the result into one balanced HTML string PER SOURCE LINE.\n *\n * highlight.js emits the whole block as HTML where a `<span>` can span several lines (a block comment, a\n * template literal). To render line-by-line — which the folding source view (CodeView.vue) needs — we walk\n * that HTML and, at every newline, close all currently-open spans, emit the line, and re-open them at the\n * start of the next, so each returned line is self-contained and valid HTML. With no / unknown language we\n * just escape each raw line. The returned array length always equals `code.split('\\n').length`.\n */\nexport function highlightLines(code: string, label?: string): string[] {\n if (!label || !hljs.getLanguage(label)) return code.split('\\n').map(escapeHtml)\n const html = highlightCode(code, label)\n const lines: string[] = []\n const open: string[] = [] // stack of currently-open `<span …>` opening tags\n let cur = ''\n let i = 0\n const n = html.length\n while (i < n) {\n const c = html[i]\n if (c === '<') {\n const gt = html.indexOf('>', i)\n const tag = gt === -1 ? html.slice(i) : html.slice(i, gt + 1)\n if (tag.startsWith('</')) open.pop()\n else if (!tag.endsWith('/>')) open.push(tag)\n cur += tag\n i += tag.length\n } else if (c === '\\n') {\n cur += '</span>'.repeat(open.length)\n lines.push(cur)\n cur = open.join('')\n i++\n } else {\n cur += c\n i++\n }\n }\n cur += '</span>'.repeat(open.length)\n lines.push(cur)\n return lines\n}\n"],"mappings":";;AAEA,IAAM,oBAAQ,IAAI,IAAoB;AAQtC,SAAgB,EAAc,GAAc,GAAwB;CAClE,IAAM,IAAM,GAAG,KAAS,GAAG,GAAG,KACxB,IAAM,EAAM,IAAI,CAAG;CACzB,IAAI,MAAQ,KAAA,GAAW,OAAO;CAC9B,IAAI;CACJ,IAAI;EACF,IACE,KAAS,EAAK,YAAY,CAAK,IAC3B,EAAK,UAAU,GAAM;GAAE,UAAU;GAAO,gBAAgB;EAAK,CAAC,CAAC,CAAC,QAChE,EAAK,cAAc,CAAI,CAAC,CAAC;CACjC,QAAQ;EACN,IAAM,EAAW,CAAI;CACvB;CAEA,OADA,EAAM,IAAI,GAAK,CAAG,GACX;AACT;AAEA,SAAgB,EAAW,GAAmB;CAC5C,OAAO,EAAE,QAAQ,MAAM,OAAO,CAAC,CAAC,QAAQ,MAAM,MAAM,CAAC,CAAC,QAAQ,MAAM,MAAM;AAC5E;AAWA,SAAgB,EAAe,GAAc,GAA0B;CACrE,IAAI,CAAC,KAAS,CAAC,EAAK,YAAY,CAAK,GAAG,OAAO,EAAK,MAAM,IAAI,CAAC,CAAC,IAAI,CAAU;CAC9E,IAAM,IAAO,EAAc,GAAM,CAAK,GAChC,IAAkB,CAAC,GACnB,IAAiB,CAAC,GACpB,IAAM,IACN,IAAI,GACF,IAAI,EAAK;CACf,OAAO,IAAI,IAAG;EACZ,IAAM,IAAI,EAAK;EACf,IAAI,MAAM,KAAK;GACb,IAAM,IAAK,EAAK,QAAQ,KAAK,CAAC,GACxB,IAAM,MAAO,KAAK,EAAK,MAAM,CAAC,IAAI,EAAK,MAAM,GAAG,IAAK,CAAC;GAI5D,AAHI,EAAI,WAAW,IAAI,IAAG,EAAK,IAAI,IACzB,EAAI,SAAS,IAAI,KAAG,EAAK,KAAK,CAAG,GAC3C,KAAO,GACP,KAAK,EAAI;EACX,OAAO,AAAI,MAAM,QACf,KAAO,UAAU,OAAO,EAAK,MAAM,GACnC,EAAM,KAAK,CAAG,GACd,IAAM,EAAK,KAAK,EAAE,GAClB,QAEA,KAAO,GACP;CAEJ;CAGA,OAFA,KAAO,UAAU,OAAO,EAAK,MAAM,GACnC,EAAM,KAAK,CAAG,GACP;AACT"}
@@ -91,3 +91,5 @@ function i(t) {
91
91
  }
92
92
  //#endregion
93
93
  export { n as langLabel, i as searchLangs };
94
+
95
+ //# sourceMappingURL=highlightLangs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"highlightLangs.js","names":[],"sources":["../../src/lib/highlightLangs.ts"],"sourcesContent":["/**\n * The highlight-language picker's data — the list + labels behind CodeView's \"语言\" control (the manual override\n * for which highlight.js grammar colorizes the source view).\n *\n * Auto-detection ({@link hljsLang}) maps extension/mime → a highlight.js language id, but that guess is often\n * empty (a `.txt` that's really JSON, an extension-less config) or simply wrong. The source view therefore lets\n * the user FORCE a language: {@link COMMON_LANGS} backs the default quick list, {@link searchLangs} filters the\n * FULL set of registered highlight.js grammars for anything else, and {@link langLabel} gives every id a nice\n * display name (also used to label the current selection). `''` is the sentinel for plain text / no highlight.\n *\n * highlight.js is already bundled (CodeView highlights through it), so listing its grammars here adds no weight.\n */\nimport hljs from 'highlight.js'\n\nexport interface LangOption {\n /** highlight.js language id ('' = plain text, no highlighting). */\n id: string\n /** Human label shown in the menu and on the selector button. */\n label: string\n}\n\n// Nice display names for the ids we special-case; everything else falls back to a capitalized id (see langLabel).\nconst LABELS: Record<string, string> = {\n '': '纯文本',\n plaintext: '纯文本',\n json: 'JSON',\n xml: 'XML / HTML',\n yaml: 'YAML',\n ini: 'INI / TOML',\n toml: 'TOML',\n markdown: 'Markdown',\n javascript: 'JavaScript',\n typescript: 'TypeScript',\n python: 'Python',\n java: 'Java',\n kotlin: 'Kotlin',\n go: 'Go',\n rust: 'Rust',\n c: 'C',\n cpp: 'C++',\n csharp: 'C#',\n php: 'PHP',\n ruby: 'Ruby',\n swift: 'Swift',\n sql: 'SQL',\n bash: 'Shell / Bash',\n shell: 'Shell',\n powershell: 'PowerShell',\n dos: 'Batch',\n css: 'CSS',\n scss: 'SCSS',\n less: 'Less',\n dockerfile: 'Dockerfile',\n makefile: 'Makefile',\n diff: 'Diff',\n properties: 'Properties',\n perl: 'Perl',\n lua: 'Lua',\n r: 'R',\n dart: 'Dart',\n scala: 'Scala',\n groovy: 'Groovy',\n objectivec: 'Objective-C',\n graphql: 'GraphQL',\n}\n\n/** Display name for a highlight.js language id — a curated label, else the capitalized id ('' → 纯文本). */\nexport function langLabel(id: string): string {\n if (id in LABELS) return LABELS[id]\n return id.charAt(0).toUpperCase() + id.slice(1)\n}\n\n// The quick list shown when the search box is empty — the languages people actually reach for, in a sensible\n// order (data/markup first, then the popular programming languages, then styling/misc).\nconst COMMON_IDS = [\n 'json',\n 'xml',\n 'yaml',\n 'ini',\n 'markdown',\n 'javascript',\n 'typescript',\n 'python',\n 'java',\n 'kotlin',\n 'go',\n 'rust',\n 'c',\n 'cpp',\n 'csharp',\n 'php',\n 'ruby',\n 'swift',\n 'sql',\n 'bash',\n 'powershell',\n 'css',\n 'scss',\n 'dockerfile',\n 'diff',\n]\n\n/** The default quick-pick list (shown when the search box is empty). */\nexport const COMMON_LANGS: LangOption[] = COMMON_IDS.map((id) => ({ id, label: langLabel(id) }))\n\n/**\n * Filter the FULL set of registered highlight.js grammars by a query (matched against both the id and its\n * label), capped so the menu stays manageable. An empty query returns {@link COMMON_LANGS} (the quick list).\n */\nexport function searchLangs(query: string): LangOption[] {\n const q = query.trim().toLowerCase()\n if (!q) return COMMON_LANGS\n const out: LangOption[] = []\n for (const id of hljs.listLanguages()) {\n const label = langLabel(id)\n if (id.includes(q) || label.toLowerCase().includes(q)) out.push({ id, label })\n if (out.length >= 60) break\n }\n return out\n}\n"],"mappings":";;AAsBA,IAAM,IAAiC;CACrC,IAAI;CACJ,WAAW;CACX,MAAM;CACN,KAAK;CACL,MAAM;CACN,KAAK;CACL,MAAM;CACN,UAAU;CACV,YAAY;CACZ,YAAY;CACZ,QAAQ;CACR,MAAM;CACN,QAAQ;CACR,IAAI;CACJ,MAAM;CACN,GAAG;CACH,KAAK;CACL,QAAQ;CACR,KAAK;CACL,MAAM;CACN,OAAO;CACP,KAAK;CACL,MAAM;CACN,OAAO;CACP,YAAY;CACZ,KAAK;CACL,KAAK;CACL,MAAM;CACN,MAAM;CACN,YAAY;CACZ,UAAU;CACV,MAAM;CACN,YAAY;CACZ,MAAM;CACN,KAAK;CACL,GAAG;CACH,MAAM;CACN,OAAO;CACP,QAAQ;CACR,YAAY;CACZ,SAAS;AACX;AAGA,SAAgB,EAAU,GAAoB;CAE5C,OADI,KAAM,IAAe,EAAO,KACzB,EAAG,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,EAAG,MAAM,CAAC;AAChD;AAiCA,IAAa,IAA6B;CA5BxC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AAIwC,CAAA,CAAW,KAAK,OAAQ;CAAE;CAAI,OAAO,EAAU,CAAE;AAAE,EAAE;AAM/F,SAAgB,EAAY,GAA6B;CACvD,IAAM,IAAI,EAAM,KAAK,CAAC,CAAC,YAAY;CACnC,IAAI,CAAC,GAAG,OAAO;CACf,IAAM,IAAoB,CAAC;CAC3B,KAAK,IAAM,KAAM,EAAK,cAAc,GAAG;EACrC,IAAM,IAAQ,EAAU,CAAE;EAE1B,KADI,EAAG,SAAS,CAAC,KAAK,EAAM,YAAY,CAAC,CAAC,SAAS,CAAC,MAAG,EAAI,KAAK;GAAE;GAAI;EAAM,CAAC,GACzE,EAAI,UAAU,IAAI;CACxB;CACA,OAAO;AACT"}
package/dist/lib/hprof.js CHANGED
@@ -707,3 +707,5 @@ function K(e, t) {
707
707
  }
708
708
  //#endregion
709
709
  export { G as Hprof, e as HprofParseError, W as decodeStringValue };
710
+
711
+ //# sourceMappingURL=hprof.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hprof.js","names":[],"sources":["../../src/lib/hprof.ts"],"sourcesContent":["/**\n * Streaming HPROF (JVM heap dump) parser — no dependency, no WASM, memory-bounded.\n *\n * An `.hprof` file is a header followed by self-describing top-level records; the big HEAP_DUMP /\n * HEAP_DUMP_SEGMENT records hold an inner stream of sub-records (CLASS_DUMP / INSTANCE_DUMP / ARRAY_DUMP /\n * GC roots) with NO length prefix, so those must be walked byte-exactly. Because a heap dump can be many GB,\n * we never load the whole file into the JS heap:\n *\n * - {@link ByteReader} pulls the file in 8 MB chunks off a {@link Blob} (the browser keeps the Blob itself,\n * possibly disk-backed); its `skip(n)` advances the cursor WITHOUT reading the skipped bytes into memory,\n * so the field data / array elements a preview never needs are never materialized.\n * - Pass A ({@link Hprof.parse}) makes ONE streaming sweep and keeps only *bounded* state: a per-class\n * histogram (instances + shallow bytes), the class → name / super / instance-field layout tables, and the\n * name string table. Nothing scales with the instance count.\n * - Pass B ({@link Hprof.collect}) answers \"show me the objects of THIS class\" with a second streaming sweep\n * that decodes only the target class's instances and collects at most {@link MAX_COLLECT} lightweight rows\n * (id + shallow size + decoded fields), skipping everything else. Memory stays ∝ the cap, independent of\n * how many instances the class actually has — the UI paginates the cap and, when a class overflows it,\n * re-runs Pass B with a field/id filter so search still spans the WHOLE file (see HprofViewer.vue).\n *\n * Shallow size only (field/element bytes + a ~2-pointer object-header estimate); retained size / dominator\n * trees need the full reference graph (a second indexing pass, à la Eclipse MAT) and are out of scope.\n *\n * The record layout follows the JDK HPROF \"binary dump format\" (agent header + 1.0.2 segmented heap dumps).\n */\n\n/** Thrown when the bytes aren't a recognizable HPROF file, or the stream ends mid-record. */\nexport class HprofParseError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'HprofParseError'\n }\n}\n\n// ── Type tags (basic-type ids used by CLASS_DUMP fields + PRIMITIVE_ARRAY_DUMP) ──────────────────\nconst T_OBJECT = 2\nconst T_BOOLEAN = 4\nconst T_CHAR = 5\nconst T_FLOAT = 6\nconst T_DOUBLE = 7\nconst T_BYTE = 8\nconst T_SHORT = 9\nconst T_INT = 10\nconst T_LONG = 11\n\n/** Byte width of a basic type. Object references are `idSize` wide; everything else is fixed. */\nfunction typeSize(type: number, idSize: number): number {\n switch (type) {\n case T_OBJECT:\n return idSize\n case T_BOOLEAN:\n case T_BYTE:\n return 1\n case T_CHAR:\n case T_SHORT:\n return 2\n case T_FLOAT:\n case T_INT:\n return 4\n case T_DOUBLE:\n case T_LONG:\n return 8\n default:\n throw new HprofParseError('未知的基础类型标记 0x' + type.toString(16))\n }\n}\n\nconst PRIM_NAME: Record<number, string> = {\n [T_BOOLEAN]: 'boolean',\n [T_CHAR]: 'char',\n [T_FLOAT]: 'float',\n [T_DOUBLE]: 'double',\n [T_BYTE]: 'byte',\n [T_SHORT]: 'short',\n [T_INT]: 'int',\n [T_LONG]: 'long',\n}\nfunction primTypeName(type: number): string {\n return PRIM_NAME[type] ?? 'type' + type\n}\n\n/**\n * Chunked, forward-only reader over a {@link Blob}. Buffers 8 MB at a time; multi-byte integers are big-endian\n * (HPROF is big-endian). Object ids / longs are read as {@link bigint} and stringified — a Map key that survives\n * the full 64-bit range (a JS number can't). {@link skip} moves the cursor past data WITHOUT reading it, the key\n * to bounded memory on huge dumps.\n */\nclass ByteReader {\n readonly size: number\n private buf: Uint8Array = new Uint8Array(0)\n private pos = 0 // consumed offset inside `buf`\n private fileCursor = 0 // file offset already pulled into `buf`\n globalPos = 0 // logical file position of the next unread byte\n\n constructor(\n private readonly blob: Blob,\n private readonly chunkSize = 8 * 1024 * 1024,\n ) {\n this.size = blob.size\n }\n\n private async ensure(n: number): Promise<void> {\n while (this.buf.length - this.pos < n) {\n if (this.fileCursor >= this.size) {\n throw new HprofParseError('文件在偏移 ' + this.globalPos + ' 处意外结束(可能已截断)')\n }\n const end = Math.min(this.fileCursor + this.chunkSize, this.size)\n const ab = await this.blob.slice(this.fileCursor, end).arrayBuffer()\n const chunk = new Uint8Array(ab)\n this.fileCursor = end\n if (this.pos > 0) {\n this.buf = this.buf.slice(this.pos)\n this.pos = 0\n }\n if (this.buf.length === 0) {\n this.buf = chunk\n } else {\n const merged = new Uint8Array(this.buf.length + chunk.length)\n merged.set(this.buf, 0)\n merged.set(chunk, this.buf.length)\n this.buf = merged\n }\n }\n }\n\n async u1(): Promise<number> {\n await this.ensure(1)\n const v = this.buf[this.pos]\n this.pos += 1\n this.globalPos += 1\n return v\n }\n async u2(): Promise<number> {\n await this.ensure(2)\n const p = this.pos\n const v = ((this.buf[p] << 8) | this.buf[p + 1]) >>> 0\n this.pos += 2\n this.globalPos += 2\n return v\n }\n async u4(): Promise<number> {\n await this.ensure(4)\n const b = this.buf\n const p = this.pos\n const v = ((b[p] << 24) | (b[p + 1] << 16) | (b[p + 2] << 8) | b[p + 3]) >>> 0\n this.pos += 4\n this.globalPos += 4\n return v\n }\n private async u8(): Promise<bigint> {\n await this.ensure(8)\n const dv = new DataView(this.buf.buffer, this.buf.byteOffset + this.pos, 8)\n const v = dv.getBigUint64(0, false)\n this.pos += 8\n this.globalPos += 8\n return v\n }\n /** An object id / reference of the file's `idSize`, returned as a decimal string (stable Map key). */\n async id(idSize: number): Promise<string> {\n if (idSize === 8) return (await this.u8()).toString()\n if (idSize === 4) return (await this.u4()).toString()\n if (idSize === 2) return (await this.u2()).toString()\n return (await this.u1()).toString()\n }\n /** Read exactly `n` bytes into a fresh array (used only for the target class's small field blobs). */\n async bytes(n: number): Promise<Uint8Array> {\n await this.ensure(n)\n const v = this.buf.slice(this.pos, this.pos + n)\n this.pos += n\n this.globalPos += n\n return v\n }\n /** NUL-terminated UTF-8 string (the HPROF magic). */\n async cstring(): Promise<string> {\n const arr: number[] = []\n for (;;) {\n const b = await this.u1()\n if (b === 0) break\n arr.push(b)\n }\n return new TextDecoder('utf-8').decode(new Uint8Array(arr))\n }\n /** Advance `n` bytes without materializing them — the memory-bounding primitive. */\n async skip(n: number): Promise<void> {\n if (n <= 0) return\n const avail = this.buf.length - this.pos\n if (n <= avail) {\n this.pos += n\n this.globalPos += n\n return\n }\n const remaining = n - avail\n this.pos = this.buf.length\n this.globalPos += avail\n this.buf = new Uint8Array(0)\n this.fileCursor += remaining // jump the file cursor; these bytes are never read\n this.globalPos += remaining\n if (this.fileCursor > this.size) {\n throw new HprofParseError('跳过范围超出文件末尾(文件可能已截断)')\n }\n }\n}\n\n// ── HPROF record tags ────────────────────────────────────────────────────────────────────────────\nconst TAG_STRING = 0x01\nconst TAG_LOAD_CLASS = 0x02\nconst TAG_HEAP_DUMP = 0x0c\nconst TAG_HEAP_DUMP_SEGMENT = 0x1c\n\n// Heap sub-record tags.\nconst SUB_CLASS_DUMP = 0x20\nconst SUB_INSTANCE_DUMP = 0x21\nconst SUB_OBJECT_ARRAY_DUMP = 0x22\nconst SUB_PRIMITIVE_ARRAY_DUMP = 0x23\n\n// GC-root sub-records carry no length; we only count them and skip their fixed payload (sizes relative to\n// idSize). Table keyed by sub-tag → extra bytes AFTER the leading object id already covered by `idSize`.\nconst GC_ROOT_EXTRA: Record<number, (idSize: number) => number> = {\n 0x01: (i) => i, // JNI global (id + global-ref id)\n 0x02: () => 8, // JNI local (+ thread serial + frame#)\n 0x03: () => 8, // java frame\n 0x04: () => 4, // native stack\n 0x05: () => 0, // sticky class\n 0x06: () => 4, // thread block\n 0x07: () => 0, // monitor used\n 0x08: () => 8, // thread object\n 0xff: () => 0, // unknown\n 0x89: () => 0, // interned string\n 0x8b: () => 0, // debugger\n 0x8d: () => 0, // vm internal\n 0x8e: () => 8, // JNI monitor\n 0x8a: () => 0, // obsolete roots\n 0x8c: () => 0,\n 0x90: () => 0,\n}\n\n/** A declared instance field of a class (name resolved lazily against the string table). */\ninterface RawField {\n nameId: string\n type: number\n}\ninterface ClassDumpInfo {\n superId: string\n instanceSize: number\n instFields: RawField[]\n}\n\n/** A resolved field slot in an instance's on-disk layout (this class's fields, then each superclass's). */\nexport interface HprofField {\n name: string\n type: number\n}\n\n/** One decoded field value of an instance. `kind` styles the display (a plain value, or an object reference). */\nexport interface HprofFieldValue {\n name: string\n /** Display string: the primitive value, `'A'` for char, `null` / `#<id>` for object references. */\n value: string\n kind: 'prim' | 'ref' | 'null'\n /** For `kind==='ref'` (non-null): the bare target object id, so the UI can jump to / dereference it. */\n refId?: string\n}\n\n/**\n * A best-effort content preview of an array object (bounded — at most {@link MAX_ARRAY_PREVIEW} elements /\n * {@link MAX_DEREF_BYTES} bytes are ever read). `char[]` / printable `byte[]` decode to `text`; `byte[]` also\n * carries `hex`; numeric arrays and object arrays list their elements (object elements are `#<id>` references).\n */\nexport interface HprofArrayPreview {\n /** Basic-type tag for a primitive array; undefined for an object array. */\n elemType?: number\n /** Element class name for an object array (e.g. `java/lang/String`). */\n elemClassName?: string\n /** True element count (the preview may be shorter). */\n length: number\n /** Decoded text (`char[]` big-endian UTF-16, or a printable `byte[]` as Latin-1). */\n text?: string\n /** First bytes of a `byte[]` as hex. */\n hex?: string\n /** Element renderings: numeric values, or `#<id>` object references (each may carry its own `refId`). */\n elements?: HprofFieldValue[]\n /** True when the preview is a prefix of the whole array. */\n truncated: boolean\n}\n\n/** One object of a class in the drill-in list. */\nexport interface HprofInstance {\n /** The instance's own object id (decimal string). */\n id: string\n /** Shallow size estimate (field bytes + object-header estimate), matching the histogram. */\n size: number\n /** Decoded instance fields in on-disk order; empty when the layout couldn't be resolved (or an array). */\n fields: HprofFieldValue[]\n /** Present when this \"object\" is actually an array — its bounded content preview. */\n array?: HprofArrayPreview\n}\n\n/** What {@link Hprof.collect} drills into: a real class, or an array pseudo-class keyed by element type/class. */\nexport type CollectTarget =\n | { kind: 'class'; classObjId: string }\n | { kind: 'primArray'; elemType: number }\n | { kind: 'objArray'; elemClassId: string }\n\n/** A class (or array pseudo-class) row of the histogram. */\nexport interface HprofClassRow {\n name: string\n count: number\n bytes: number\n /** Drill-in descriptor — present on every row (classes and arrays are both drillable). */\n target?: CollectTarget\n}\n\n/** The resolved view of a single object id, produced by {@link Hprof.resolveObjects} (jump / dereference). */\nexport type HprofObjectView =\n | { id: string; kind: 'instance'; className: string; size: number; fields: HprofFieldValue[] }\n | {\n id: string\n kind: 'primArray'\n className: string\n size: number\n length: number\n elemType: number\n /** Raw element bytes, capped at {@link MAX_DEREF_BYTES} — lets the caller decode with a String coder. */\n rawBytes: Uint8Array\n array: HprofArrayPreview\n }\n | {\n id: string\n kind: 'objArray'\n className: string\n size: number\n length: number\n array: HprofArrayPreview\n }\n | { id: string; kind: 'class'; className: string }\n\nexport interface HprofSummary {\n idSize: number\n /** Dump time — epoch milliseconds as a string (may exceed 2^53). */\n timestamp: string\n fileSize: number\n recordCount: number\n classCount: number\n instanceCount: number\n gcRoots: number\n stringCount: number\n /** Total shallow bytes across all objects + arrays. */\n heapBytes: number\n /** Histogram rows, sorted by shallow bytes descending. */\n rows: HprofClassRow[]\n}\n\n/** Result of a per-class object collection (Pass B). */\nexport interface HprofCollectResult {\n /** Collected rows (≤ {@link MAX_COLLECT}); when filtering, only matches. */\n rows: HprofInstance[]\n /** Total instances of the class in the file (or, when filtering, total matches). */\n total: number\n /** True when `total` exceeded the cap, so `rows` is a prefix — the UI should offer whole-file search. */\n truncated: boolean\n}\n\nexport interface HprofProgress {\n (pos: number, size: number): void\n}\n\ninterface CollectOptions {\n /** Max rows to keep (default {@link MAX_COLLECT}). */\n limit?: number\n /** Keep only instances whose id or any decoded field value contains this (case-insensitive) text. */\n filter?: string\n onProgress?: HprofProgress\n}\n\n/** Cap on rows Pass B keeps in memory for one class — bounds memory regardless of the real instance count. */\nexport const MAX_COLLECT = 10000\n/** Cap on array elements listed in one preview — bounds memory when an array (or String) is huge. */\nexport const MAX_ARRAY_PREVIEW = 256\n/** Cap on raw bytes read per array object when dereferencing (String text / byte[] hex) — bounds memory. */\nexport const MAX_DEREF_BYTES = 8192\n/** Cap on bytes shown in a `byte[]` hex preview. */\nconst MAX_HEX = 256\n\n// Yield to the event loop every N sub-records so a long parse never freezes the UI (an all-microtask await\n// chain never hits a macrotask boundary; the browser can't paint). Also drives the progress callback.\nconst YIELD_EVERY = 4000\nfunction nextTick(): Promise<void> {\n return new Promise((res) => setTimeout(res, 0))\n}\n\n/** Read + validate the header; leaves the cursor at the first top-level record. Returns idSize + dump time. */\nasync function readHeader(r: ByteReader): Promise<{ idSize: number; timestamp: string }> {\n const magic = await r.cstring()\n if (!magic.startsWith('JAVA PROFILE')) {\n throw new HprofParseError('不是有效的 HPROF 文件(magic: \"' + magic.slice(0, 32) + '\")')\n }\n const idSize = await r.u4()\n if (idSize !== 1 && idSize !== 2 && idSize !== 4 && idSize !== 8) {\n throw new HprofParseError('异常的 idSize:' + idSize)\n }\n const tsHi = await r.u4()\n const tsLo = await r.u4()\n const timestamp = ((BigInt(tsHi) << 32n) | BigInt(tsLo)).toString()\n return { idSize, timestamp }\n}\n\n/** Fully consume a CLASS_DUMP sub-record (cursor already past the sub-tag) and return its structural info. */\nasync function readClassDump(\n r: ByteReader,\n idSize: number,\n): Promise<{ classObjId: string; info: ClassDumpInfo }> {\n const classObjId = await r.id(idSize)\n await r.skip(4) // stack trace serial\n const superId = await r.id(idSize)\n await r.skip(idSize * 5) // class loader, signers, protection domain, reserved1, reserved2\n const instanceSize = await r.u4()\n\n const cpSize = await r.u2() // constant pool\n for (let i = 0; i < cpSize; i++) {\n await r.u2() // cp index\n const t = await r.u1()\n await r.skip(typeSize(t, idSize))\n }\n const staticCount = await r.u2() // static fields\n for (let i = 0; i < staticCount; i++) {\n await r.id(idSize) // name string id\n const t = await r.u1()\n await r.skip(typeSize(t, idSize))\n }\n const instCount = await r.u2() // instance fields (type only, no value)\n const instFields: RawField[] = []\n for (let i = 0; i < instCount; i++) {\n const nameId = await r.id(idSize)\n const type = await r.u1()\n instFields.push({ nameId, type })\n }\n return { classObjId, info: { superId, instanceSize, instFields } }\n}\n\n/**\n * Skip one heap sub-record given its tag, EXCEPT the ones the caller wants to handle. Returns a small descriptor\n * for CLASS_DUMP / INSTANCE_DUMP / arrays so each pass reacts (record layout, tally histogram, or collect), and\n * `null` for GC roots (already fully skipped here). Throws on an unknown tag — the byte stream can't be resynced.\n */\ntype SubEvent =\n | { kind: 'class'; classObjId: string; info: ClassDumpInfo }\n | { kind: 'instance'; id: string; classObjId: string; numBytes: number }\n | { kind: 'objArray'; elemClassId: string; numElements: number; shallow: number }\n | { kind: 'primArray'; elemType: number; numElements: number; shallow: number }\n\nasync function readSub(r: ByteReader, sub: number, idSize: number): Promise<SubEvent | null> {\n const rootExtra = GC_ROOT_EXTRA[sub]\n if (rootExtra) {\n await r.skip(idSize + rootExtra(idSize))\n return null\n }\n switch (sub) {\n case SUB_CLASS_DUMP: {\n const { classObjId, info } = await readClassDump(r, idSize)\n return { kind: 'class', classObjId, info }\n }\n case SUB_INSTANCE_DUMP: {\n const id = await r.id(idSize)\n await r.skip(4) // stack trace serial\n const classObjId = await r.id(idSize)\n const numBytes = await r.u4()\n // Leaves the cursor BEFORE the field bytes — the caller reads them (target class) or skips them.\n return { kind: 'instance', id, classObjId, numBytes }\n }\n case SUB_OBJECT_ARRAY_DUMP: {\n await r.id(idSize) // array object id\n await r.skip(4) // stack trace serial\n const numElements = await r.u4()\n const elemClassId = await r.id(idSize)\n await r.skip(numElements * idSize)\n const shallow = numElements * idSize + idSize * 2 + 4\n return { kind: 'objArray', elemClassId, numElements, shallow }\n }\n case SUB_PRIMITIVE_ARRAY_DUMP: {\n await r.id(idSize) // array object id\n await r.skip(4) // stack trace serial\n const numElements = await r.u4()\n const elemType = await r.u1()\n await r.skip(numElements * typeSize(elemType, idSize))\n const shallow = numElements * typeSize(elemType, idSize) + idSize * 2 + 4\n return { kind: 'primArray', elemType, numElements, shallow }\n }\n default:\n throw new HprofParseError(\n '未知的堆子记录标记 0x' + sub.toString(16) + '(偏移 ' + r.globalPos + ')',\n )\n }\n}\n\n/** Read one id-width big-endian reference out of an in-memory DataView (instance field decode). */\nfunction readIdAt(dv: DataView, off: number, idSize: number): string {\n if (idSize === 8) return dv.getBigUint64(off, false).toString()\n if (idSize === 4) return dv.getUint32(off, false).toString()\n if (idSize === 2) return dv.getUint16(off, false).toString()\n return dv.getUint8(off).toString()\n}\n\n/** Decode one instance's field bytes against a resolved layout into display values. */\nfunction decodeFields(data: Uint8Array, layout: HprofField[], idSize: number): HprofFieldValue[] {\n const dv = new DataView(data.buffer, data.byteOffset, data.byteLength)\n const out: HprofFieldValue[] = []\n let off = 0\n for (const f of layout) {\n switch (f.type) {\n case T_OBJECT: {\n const id = readIdAt(dv, off, idSize)\n off += idSize\n out.push(\n id === '0'\n ? { name: f.name, value: 'null', kind: 'null' }\n : { name: f.name, value: '#' + id, kind: 'ref', refId: id },\n )\n break\n }\n case T_BOOLEAN:\n out.push({ name: f.name, value: dv.getUint8(off) !== 0 ? 'true' : 'false', kind: 'prim' })\n off += 1\n break\n case T_BYTE:\n out.push({ name: f.name, value: String(dv.getInt8(off)), kind: 'prim' })\n off += 1\n break\n case T_CHAR: {\n const c = dv.getUint16(off, false)\n out.push({ name: f.name, value: charDisplay(c), kind: 'prim' })\n off += 2\n break\n }\n case T_SHORT:\n out.push({ name: f.name, value: String(dv.getInt16(off, false)), kind: 'prim' })\n off += 2\n break\n case T_FLOAT:\n out.push({ name: f.name, value: fmtNum(dv.getFloat32(off, false)), kind: 'prim' })\n off += 4\n break\n case T_INT:\n out.push({ name: f.name, value: String(dv.getInt32(off, false)), kind: 'prim' })\n off += 4\n break\n case T_DOUBLE:\n out.push({ name: f.name, value: fmtNum(dv.getFloat64(off, false)), kind: 'prim' })\n off += 8\n break\n case T_LONG:\n out.push({ name: f.name, value: dv.getBigInt64(off, false).toString(), kind: 'prim' })\n off += 8\n break\n default:\n off += typeSize(f.type, idSize)\n }\n }\n return out\n}\n\n// A printable char reads as `'A'`; a control/non-printable one as its \\uXXXX escape so the list stays legible.\nfunction charDisplay(code: number): string {\n if (code >= 0x20 && code !== 0x7f) return \"'\" + String.fromCharCode(code) + \"'\"\n return \"'\\\\u\" + code.toString(16).padStart(4, '0') + \"'\"\n}\nfunction fmtNum(n: number): string {\n if (Number.isNaN(n)) return 'NaN'\n if (!Number.isFinite(n)) return n > 0 ? 'Infinity' : '-Infinity'\n return String(n)\n}\n\n// ── Array content decoding (bounded previews + String dereference) ────────────────────────────────\n\n/** JVM array descriptor → readable name: `[Ljava/lang/String;` → `java/lang/String[]`, `[[I` → `int[][]`. */\nfunction arrayClassDisplay(desc: string | undefined): string {\n if (!desc) return 'Object[]'\n if (desc[0] !== '[') return desc + '[]'\n let dims = 0\n let i = 0\n while (i < desc.length && desc[i] === '[') {\n dims++\n i++\n }\n let base = desc.slice(i)\n const prim: Record<string, string> = {\n Z: 'boolean',\n B: 'byte',\n C: 'char',\n S: 'short',\n I: 'int',\n J: 'long',\n F: 'float',\n D: 'double',\n }\n if (base.startsWith('L') && base.endsWith(';')) base = base.slice(1, -1)\n else base = prim[base] ?? base\n return base + '[]'.repeat(dims)\n}\n/** Element type name of an object array = its array display minus one dimension (`java/lang/String[]` → `…String`). */\nfunction arrayElemDisplay(desc: string | undefined): string {\n const full = arrayClassDisplay(desc)\n return full.endsWith('[]') ? full.slice(0, -2) : full\n}\n\n/** One primitive value at an offset, as a display string (shared by field + array-element decoding). */\nfunction primValueAt(dv: DataView, off: number, type: number): string {\n switch (type) {\n case T_BOOLEAN:\n return dv.getUint8(off) !== 0 ? 'true' : 'false'\n case T_BYTE:\n return String(dv.getInt8(off))\n case T_CHAR:\n return charDisplay(dv.getUint16(off, false))\n case T_SHORT:\n return String(dv.getInt16(off, false))\n case T_FLOAT:\n return fmtNum(dv.getFloat32(off, false))\n case T_INT:\n return String(dv.getInt32(off, false))\n case T_DOUBLE:\n return fmtNum(dv.getFloat64(off, false))\n case T_LONG:\n return dv.getBigInt64(off, false).toString()\n default:\n return '?'\n }\n}\nfunction decodeNumericElements(raw: Uint8Array, elemType: number): HprofFieldValue[] {\n const dv = new DataView(raw.buffer, raw.byteOffset, raw.byteLength)\n const sz = typeSize(elemType, 8)\n const n = Math.min(Math.floor(raw.byteLength / sz), MAX_ARRAY_PREVIEW)\n const out: HprofFieldValue[] = []\n for (let i = 0; i < n; i++)\n out.push({ name: String(i), value: primValueAt(dv, i * sz, elemType), kind: 'prim' })\n return out\n}\n\n/** HPROF `char[]` elements are big-endian UTF-16 code units. */\nfunction charBytesToString(raw: Uint8Array): string {\n let s = ''\n const n = raw.byteLength & ~1\n for (let i = 0; i < n; i += 2) s += String.fromCharCode((raw[i] << 8) | raw[i + 1])\n return s\n}\n/** Java 9+ compact-String UTF-16 `byte[]` is in-memory order (little-endian on the usual platforms). */\nfunction utf16leBytesToString(raw: Uint8Array): string {\n let s = ''\n const n = raw.byteLength & ~1\n for (let i = 0; i < n; i += 2) s += String.fromCharCode(raw[i] | (raw[i + 1] << 8))\n return s\n}\nfunction latin1BytesToString(raw: Uint8Array): string {\n let s = ''\n for (let i = 0; i < raw.byteLength; i++) s += String.fromCharCode(raw[i])\n return s\n}\n/** A `byte[]` shown as text only when it's mostly printable Latin-1 (otherwise the caller falls back to hex). */\nfunction printableLatin1(raw: Uint8Array): string | undefined {\n if (raw.byteLength === 0) return ''\n let printable = 0\n for (let i = 0; i < raw.byteLength; i++) {\n const b = raw[i]\n if ((b >= 0x20 && b < 0x7f) || b === 9 || b === 10 || b === 13) printable++\n }\n return printable / raw.byteLength >= 0.85 ? latin1BytesToString(raw) : undefined\n}\nfunction toHex(raw: Uint8Array): string {\n const n = Math.min(raw.byteLength, MAX_HEX)\n let s = ''\n for (let i = 0; i < n; i++) s += raw[i].toString(16).padStart(2, '0') + (i < n - 1 ? ' ' : '')\n return raw.byteLength > n ? s + ' …' : s\n}\n\n/** Bounded content preview of a primitive array: `char[]`/printable `byte[]` → text, `byte[]` → hex, else values. */\nfunction buildPrimArrayPreview(\n elemType: number,\n raw: Uint8Array,\n length: number,\n): HprofArrayPreview {\n const p: HprofArrayPreview = { elemType, length, truncated: false }\n if (elemType === T_CHAR) {\n p.text = charBytesToString(raw)\n p.truncated = raw.byteLength < length * 2\n } else if (elemType === T_BYTE) {\n p.hex = toHex(raw)\n const t = printableLatin1(raw)\n if (t !== undefined) p.text = t\n p.truncated = raw.byteLength < length\n } else {\n p.elements = decodeNumericElements(raw, elemType)\n p.truncated = p.elements.length < length\n }\n return p\n}\n\n/**\n * Decode a `java.lang.String`'s backing array bytes to text. Legacy `char[]` (Java 8) is big-endian UTF-16;\n * Java 9+ `byte[]` is LATIN1 when `coder===0`, else in-memory UTF-16 (little-endian). `coder` comes from the\n * String instance's own decoded `coder` field (null for the char[] layout).\n */\nexport function decodeStringValue(raw: Uint8Array, elemType: number, coder: number | null): string {\n if (elemType === T_CHAR) return charBytesToString(raw)\n return coder === 1 ? utf16leBytesToString(raw) : latin1BytesToString(raw)\n}\n\n/**\n * A parsed heap dump. {@link parse} runs Pass A and returns this handle; {@link summary} feeds the histogram UI,\n * and {@link collect} runs Pass B on demand for one class. The originating Blob + the bounded class/name tables\n * are retained so drill-in needs no re-parse of Pass A.\n */\nexport class Hprof {\n readonly summary: HprofSummary\n private constructor(\n private readonly blob: Blob,\n summary: HprofSummary,\n private readonly idSize: number,\n private readonly classInfo: Map<string, ClassDumpInfo>,\n private readonly classNames: Map<string, string>,\n private readonly strings: Map<string, string>,\n private readonly layoutCache: Map<string, HprofField[] | null>,\n ) {\n this.summary = summary\n }\n\n /** Class name for an object id (falls back to a synthetic `<class#id>`). */\n classNameOf(classObjId: string): string {\n return this.classNames.get(classObjId) ?? '<class#' + classObjId + '>'\n }\n\n /**\n * Resolve the on-disk instance-field layout: this class's declared fields, then each superclass's, up the\n * chain (the order INSTANCE_DUMP lays field data out in). Cached. Returns null if a class in the chain has no\n * CLASS_DUMP (can't compute the layout) — the caller then shows id + size only.\n */\n private resolveLayout(classObjId: string): HprofField[] | null {\n const cached = this.layoutCache.get(classObjId)\n if (cached !== undefined) return cached\n const fields: HprofField[] = []\n let cur = classObjId\n const seen = new Set<string>()\n while (cur !== '0') {\n if (seen.has(cur)) break // defensive: a cyclic super chain shouldn't happen, but never loop forever\n seen.add(cur)\n const info = this.classInfo.get(cur)\n if (!info) {\n this.layoutCache.set(classObjId, null)\n return null\n }\n for (const f of info.instFields) {\n fields.push({\n name: this.strings.get(f.nameId) ?? '<field#' + f.nameId + '>',\n type: f.type,\n })\n }\n cur = info.superId\n }\n this.layoutCache.set(classObjId, fields)\n return fields\n }\n\n static async parse(blob: Blob, onProgress?: HprofProgress): Promise<Hprof> {\n const r = new ByteReader(blob)\n const { idSize, timestamp } = await readHeader(r)\n\n const strings = new Map<string, string>() // stringId -> name\n const classNameStrId = new Map<string, string>() // classObjId -> name stringId (LOAD_CLASS)\n const classInfo = new Map<string, ClassDumpInfo>() // classObjId -> layout/super/size (CLASS_DUMP)\n const perClass = new Map<string, { count: number; bytes: number }>()\n const objArrays = new Map<string, { count: number; bytes: number }>() // elemClassId -> tally\n const primArrays = new Map<number, { count: number; bytes: number }>() // elemType -> tally\n let gcRoots = 0\n let instanceCount = 0\n let recordCount = 0\n let classCount = 0\n let heapBytes = 0\n\n let iter = 0\n const tick = async (): Promise<void> => {\n if (++iter % YIELD_EVERY === 0) {\n onProgress?.(r.globalPos, r.size)\n await nextTick()\n }\n }\n\n while (r.globalPos < r.size) {\n const tag = await r.u1()\n await r.u4() // record time (ignored)\n const length = await r.u4()\n const recEnd = r.globalPos + length\n recordCount++\n\n if (tag === TAG_STRING) {\n const sid = await r.id(idSize)\n const strBytes = await r.bytes(length - idSize)\n strings.set(sid, new TextDecoder('utf-8').decode(strBytes))\n } else if (tag === TAG_LOAD_CLASS) {\n await r.u4() // class serial\n const classObjId = await r.id(idSize)\n await r.u4() // stack trace serial\n const nameId = await r.id(idSize)\n classNameStrId.set(classObjId, nameId)\n } else if (tag === TAG_HEAP_DUMP || tag === TAG_HEAP_DUMP_SEGMENT) {\n while (r.globalPos < recEnd) {\n const sub = await r.u1()\n const ev = await readSub(r, sub, idSize)\n if (ev) {\n if (ev.kind === 'class') {\n classInfo.set(ev.classObjId, ev.info)\n classCount++\n } else if (ev.kind === 'instance') {\n await r.skip(ev.numBytes) // Pass A never reads field data\n instanceCount++\n const shallow = ev.numBytes + idSize * 2\n heapBytes += shallow\n const e = perClass.get(ev.classObjId)\n if (e) {\n e.count++\n e.bytes += shallow\n } else {\n perClass.set(ev.classObjId, { count: 1, bytes: shallow })\n }\n } else if (ev.kind === 'objArray') {\n instanceCount++\n heapBytes += ev.shallow\n const e = objArrays.get(ev.elemClassId)\n if (e) {\n e.count++\n e.bytes += ev.shallow\n } else {\n objArrays.set(ev.elemClassId, { count: 1, bytes: ev.shallow })\n }\n } else {\n instanceCount++\n heapBytes += ev.shallow\n const e = primArrays.get(ev.elemType)\n if (e) {\n e.count++\n e.bytes += ev.shallow\n } else {\n primArrays.set(ev.elemType, { count: 1, bytes: ev.shallow })\n }\n }\n } else {\n gcRoots++\n }\n await tick()\n }\n } else {\n await r.skip(length) // unknown / uninteresting top-level record — self-describing length\n }\n\n // Guard: consume exactly to the record boundary so one mis-sized branch can't desync everything after it.\n if (r.globalPos < recEnd) await r.skip(recEnd - r.globalPos)\n else if (r.globalPos > recEnd) {\n throw new HprofParseError(\n '解析在标记 0x' +\n tag.toString(16) +\n ' 处越界(偏移 ' +\n r.globalPos +\n ',应止于 ' +\n recEnd +\n ')',\n )\n }\n await tick()\n }\n\n // Resolve class id → name now that every STRING / LOAD_CLASS has been seen (order isn't guaranteed).\n const classNames = new Map<string, string>()\n for (const [classObjId, nameId] of classNameStrId) {\n classNames.set(classObjId, strings.get(nameId) ?? '<class#' + classObjId + '>')\n }\n\n const rows: HprofClassRow[] = []\n for (const [classObjId, e] of perClass) {\n rows.push({\n name: classNames.get(classObjId) ?? '<class#' + classObjId + '>',\n count: e.count,\n bytes: e.bytes,\n target: { kind: 'class', classObjId },\n })\n }\n for (const [elemClassId, e] of objArrays) {\n rows.push({\n name: arrayClassDisplay(classNames.get(elemClassId)),\n count: e.count,\n bytes: e.bytes,\n target: { kind: 'objArray', elemClassId },\n })\n }\n for (const [elemType, e] of primArrays) {\n rows.push({\n name: primTypeName(elemType) + '[]',\n count: e.count,\n bytes: e.bytes,\n target: { kind: 'primArray', elemType },\n })\n }\n rows.sort((a, b) => b.bytes - a.bytes || b.count - a.count)\n\n onProgress?.(r.size, r.size)\n const summary: HprofSummary = {\n idSize,\n timestamp,\n fileSize: blob.size,\n recordCount,\n classCount,\n instanceCount,\n gcRoots,\n stringCount: strings.size,\n heapBytes,\n rows,\n }\n return new Hprof(blob, summary, idSize, classInfo, classNames, strings, new Map())\n }\n\n /**\n * Pass B: stream the file again and collect the objects of one drill-in target — a class (its instances), a\n * primitive-array type, or an object-array type. Decodes only matching objects (skipping everything else),\n * keeping at most `limit` rows; with `filter`, keeps only rows whose id / field value / array content contains\n * the (lower-cased) text — so a target that overflows the cap can still be searched across the WHOLE file.\n * `total` counts every matching object even beyond the cap.\n */\n async collect(target: CollectTarget, opts: CollectOptions = {}): Promise<HprofCollectResult> {\n const limit = opts.limit ?? MAX_COLLECT\n const needle = opts.filter?.trim().toLowerCase() ?? ''\n const idSize = this.idSize\n const layout = target.kind === 'class' ? this.resolveLayout(target.classObjId) : null\n\n const r = new ByteReader(this.blob)\n await readHeader(r)\n\n const rows: HprofInstance[] = []\n let total = 0\n let iter = 0\n const tick = async (): Promise<void> => {\n if (++iter % YIELD_EVERY === 0) {\n opts.onProgress?.(r.globalPos, r.size)\n await nextTick()\n }\n }\n // Keep a decoded row if it passes the filter and still fits the cap; count every match toward the total.\n const consider = (row: HprofInstance): void => {\n if (needle && !rowMatches(row, needle)) return\n total++\n if (rows.length < limit) rows.push(row)\n }\n\n while (r.globalPos < r.size) {\n const tag = await r.u1()\n await r.u4()\n const length = await r.u4()\n const recEnd = r.globalPos + length\n\n if (tag === TAG_HEAP_DUMP || tag === TAG_HEAP_DUMP_SEGMENT) {\n while (r.globalPos < recEnd) {\n const sub = await r.u1()\n if (target.kind === 'class' && sub === SUB_INSTANCE_DUMP) {\n const id = await r.id(idSize)\n await r.skip(4)\n const cls = await r.id(idSize)\n const numBytes = await r.u4()\n if (cls === target.classObjId) {\n const shallow = numBytes + idSize * 2\n // Decode only when the row can still matter (under cap, or filtering to find matches past it).\n if (needle || rows.length < limit) {\n const data = await r.bytes(numBytes)\n const fields = layout ? decodeFields(data, layout, idSize) : []\n consider({ id, size: shallow, fields })\n } else {\n await r.skip(numBytes)\n total++\n }\n } else {\n await r.skip(numBytes)\n }\n } else if (target.kind === 'primArray' && sub === SUB_PRIMITIVE_ARRAY_DUMP) {\n const id = await r.id(idSize)\n await r.skip(4)\n const num = await r.u4()\n const elemType = await r.u1()\n const nbytes = num * typeSize(elemType, idSize)\n if (elemType === target.elemType) {\n const shallow = nbytes + idSize * 2 + 4\n if (needle || rows.length < limit) {\n const take = Math.min(nbytes, MAX_DEREF_BYTES)\n const raw = await r.bytes(take)\n await r.skip(nbytes - take)\n consider({\n id,\n size: shallow,\n fields: [],\n array: buildPrimArrayPreview(elemType, raw, num),\n })\n } else {\n await r.skip(nbytes)\n total++\n }\n } else {\n await r.skip(nbytes)\n }\n } else if (target.kind === 'objArray' && sub === SUB_OBJECT_ARRAY_DUMP) {\n const id = await r.id(idSize)\n await r.skip(4)\n const num = await r.u4()\n const arrClassId = await r.id(idSize)\n if (arrClassId === target.elemClassId) {\n const shallow = num * idSize + idSize * 2 + 4\n if (needle || rows.length < limit) {\n const array = await this.readObjArrayPreview(r, num, arrClassId, idSize)\n consider({ id, size: shallow, fields: [], array })\n } else {\n await r.skip(num * idSize)\n total++\n }\n } else {\n await r.skip(num * idSize)\n }\n } else {\n // Not our target: consume for positioning. readSub fully skips arrays / classes / GC roots, but\n // leaves an INSTANCE_DUMP's field bytes for the caller — skip them so the sub is fully consumed.\n const ev = await readSub(r, sub, idSize)\n if (ev && ev.kind === 'instance') await r.skip(ev.numBytes)\n }\n await tick()\n }\n } else {\n await r.skip(length)\n }\n\n if (r.globalPos < recEnd) await r.skip(recEnd - r.globalPos)\n else if (r.globalPos > recEnd) {\n throw new HprofParseError('解析越界(偏移 ' + r.globalPos + ',应止于 ' + recEnd + ')')\n }\n await tick()\n }\n\n opts.onProgress?.(r.size, r.size)\n return { rows, total, truncated: total > rows.length }\n }\n\n /** Read a bounded element-id preview of an object array (cursor just past its array-class id). */\n private async readObjArrayPreview(\n r: ByteReader,\n num: number,\n arrClassId: string,\n idSize: number,\n ): Promise<HprofArrayPreview> {\n const take = Math.min(num, MAX_ARRAY_PREVIEW)\n const elements: HprofFieldValue[] = []\n for (let i = 0; i < take; i++) {\n const eid = await r.id(idSize)\n elements.push(\n eid === '0'\n ? { name: String(i), value: 'null', kind: 'null' }\n : { name: String(i), value: '#' + eid, kind: 'ref', refId: eid },\n )\n }\n await r.skip((num - take) * idSize)\n return {\n elemClassName: arrayElemDisplay(this.classNames.get(arrClassId)),\n length: num,\n elements,\n truncated: take < num,\n }\n }\n\n /**\n * Resolve a batch of object ids in ONE streaming sweep — the on-demand random access a preview needs to follow\n * a reference (jump to an object) or dereference a value (a String's backing `byte[]`/`char[]`). Class-object\n * ids resolve without scanning. Only ids actually found are returned (GC'd / unknown ids are absent). Bounded:\n * array content is capped (see {@link MAX_ARRAY_PREVIEW} / {@link MAX_DEREF_BYTES}), so memory stays ∝ the batch.\n */\n async resolveObjects(\n ids: Set<string>,\n onProgress?: HprofProgress,\n ): Promise<Map<string, HprofObjectView>> {\n const idSize = this.idSize\n const out = new Map<string, HprofObjectView>()\n let remaining = 0\n for (const id of ids) {\n const cn = this.classNames.get(id)\n if (cn) out.set(id, { id, kind: 'class', className: cn })\n else remaining++\n }\n if (remaining === 0) return out\n\n const r = new ByteReader(this.blob)\n await readHeader(r)\n let iter = 0\n const tick = async (): Promise<void> => {\n if (++iter % YIELD_EVERY === 0) {\n onProgress?.(r.globalPos, r.size)\n await nextTick()\n }\n }\n\n while (r.globalPos < r.size && remaining > 0) {\n const tag = await r.u1()\n await r.u4()\n const length = await r.u4()\n const recEnd = r.globalPos + length\n\n if (tag === TAG_HEAP_DUMP || tag === TAG_HEAP_DUMP_SEGMENT) {\n while (r.globalPos < recEnd && remaining > 0) {\n const sub = await r.u1()\n if (sub === SUB_INSTANCE_DUMP) {\n const id = await r.id(idSize)\n await r.skip(4)\n const cls = await r.id(idSize)\n const numBytes = await r.u4()\n if (ids.has(id) && !out.has(id)) {\n const data = await r.bytes(numBytes)\n const layout = this.resolveLayout(cls)\n out.set(id, {\n id,\n kind: 'instance',\n className: this.classNameOf(cls),\n size: numBytes + idSize * 2,\n fields: layout ? decodeFields(data, layout, idSize) : [],\n })\n remaining--\n } else {\n await r.skip(numBytes)\n }\n } else if (sub === SUB_PRIMITIVE_ARRAY_DUMP) {\n const id = await r.id(idSize)\n await r.skip(4)\n const num = await r.u4()\n const elemType = await r.u1()\n const nbytes = num * typeSize(elemType, idSize)\n if (ids.has(id) && !out.has(id)) {\n const take = Math.min(nbytes, MAX_DEREF_BYTES)\n const raw = await r.bytes(take)\n await r.skip(nbytes - take)\n out.set(id, {\n id,\n kind: 'primArray',\n className: primTypeName(elemType) + '[]',\n size: nbytes + idSize * 2 + 4,\n length: num,\n elemType,\n rawBytes: raw,\n array: buildPrimArrayPreview(elemType, raw, num),\n })\n remaining--\n } else {\n await r.skip(nbytes)\n }\n } else if (sub === SUB_OBJECT_ARRAY_DUMP) {\n const id = await r.id(idSize)\n await r.skip(4)\n const num = await r.u4()\n const arrClassId = await r.id(idSize)\n if (ids.has(id) && !out.has(id)) {\n const array = await this.readObjArrayPreview(r, num, arrClassId, idSize)\n out.set(id, {\n id,\n kind: 'objArray',\n className: arrayClassDisplay(this.classNames.get(arrClassId)),\n size: num * idSize + idSize * 2 + 4,\n length: num,\n array,\n })\n remaining--\n } else {\n await r.skip(num * idSize)\n }\n } else if (sub === SUB_CLASS_DUMP) {\n await readClassDump(r, idSize)\n } else {\n const rootExtra = GC_ROOT_EXTRA[sub]\n if (rootExtra) await r.skip(idSize + rootExtra(idSize))\n else\n throw new HprofParseError(\n '未知的堆子记录标记 0x' + sub.toString(16) + '(偏移 ' + r.globalPos + ')',\n )\n }\n await tick()\n }\n } else {\n await r.skip(length)\n }\n\n // Skip to the record boundary — also the fast path out when every id was found mid-segment.\n if (r.globalPos < recEnd) await r.skip(recEnd - r.globalPos)\n else if (r.globalPos > recEnd) {\n throw new HprofParseError('解析越界(偏移 ' + r.globalPos + ',应止于 ' + recEnd + ')')\n }\n await tick()\n }\n\n onProgress?.(r.size, r.size)\n return out\n }\n}\n\n/**\n * Case-insensitive match of a needle against a row's id, any field's `name=value` rendering, or its array\n * content (decoded text, hex, or element values) — the same text the preview shows, so `true`, `active`, and\n * `active=true` all match. `needle` is pre-lowercased.\n */\nfunction rowMatches(o: HprofInstance, needle: string): boolean {\n if (o.id.includes(needle)) return true\n for (const f of o.fields) {\n if ((f.name + '=' + f.value).toLowerCase().includes(needle)) return true\n }\n const a = o.array\n if (a) {\n if (a.text && a.text.toLowerCase().includes(needle)) return true\n if (a.hex && a.hex.includes(needle)) return true\n if (a.elements) {\n for (const e of a.elements) if (e.value.toLowerCase().includes(needle)) return true\n }\n }\n return false\n}\n"],"mappings":";AA2BA,IAAa,IAAb,cAAqC,MAAM;CACzC,YAAY,GAAiB;EAE3B,AADA,MAAM,CAAO,GACb,KAAK,OAAO;CACd;AACF,GAGM,IAAW,GACX,IAAY,GACZ,IAAS,GACT,IAAU,GACV,IAAW,GACX,IAAS,GACT,IAAU,GACV,IAAQ,IACR,IAAS;AAGf,SAAS,EAAS,GAAc,GAAwB;CACtD,QAAQ,GAAR;EACE,KAAK,GACH,OAAO;EACT,KAAK;EACL,KAAK,GACH,OAAO;EACT,KAAK;EACL,KAAK,GACH,OAAO;EACT,KAAK;EACL,KAAK,GACH,OAAO;EACT,KAAK;EACL,KAAK,GACH,OAAO;EACT,SACE,MAAM,IAAI,EAAgB,iBAAiB,EAAK,SAAS,EAAE,CAAC;CAChE;AACF;AAEA,IAAM,IAAoC;EACvC,IAAY;EACZ,IAAS;EACT,IAAU;EACV,IAAW;EACX,IAAS;EACT,IAAU;EACV,IAAQ;EACR,IAAS;AACZ;AACA,SAAS,EAAa,GAAsB;CAC1C,OAAO,EAAU,MAAS,SAAS;AACrC;AAQA,IAAM,IAAN,MAAiB;CAQI;CACA;CARnB;CACA,MAA0B,IAAI,WAAY;CAC1C,MAAc;CACd,aAAqB;CACrB,YAAY;CAEZ,YACE,GACA,IAA6B,IAAI,OAAO,MACxC;EACA,AAHiB,KAAA,OAAA,GACA,KAAA,YAAA,GAEjB,KAAK,OAAO,EAAK;CACnB;CAEA,MAAc,OAAO,GAA0B;EAC7C,OAAO,KAAK,IAAI,SAAS,KAAK,MAAM,IAAG;GACrC,IAAI,KAAK,cAAc,KAAK,MAC1B,MAAM,IAAI,EAAgB,WAAW,KAAK,YAAY,eAAe;GAEvE,IAAM,IAAM,KAAK,IAAI,KAAK,aAAa,KAAK,WAAW,KAAK,IAAI,GAC1D,IAAK,MAAM,KAAK,KAAK,MAAM,KAAK,YAAY,CAAG,CAAC,CAAC,YAAY,GAC7D,IAAQ,IAAI,WAAW,CAAE;GAM/B,IALA,KAAK,aAAa,GACd,KAAK,MAAM,MACb,KAAK,MAAM,KAAK,IAAI,MAAM,KAAK,GAAG,GAClC,KAAK,MAAM,IAET,KAAK,IAAI,WAAW,GACtB,KAAK,MAAM;QACN;IACL,IAAM,IAAS,IAAI,WAAW,KAAK,IAAI,SAAS,EAAM,MAAM;IAG5D,AAFA,EAAO,IAAI,KAAK,KAAK,CAAC,GACtB,EAAO,IAAI,GAAO,KAAK,IAAI,MAAM,GACjC,KAAK,MAAM;GACb;EACF;CACF;CAEA,MAAM,KAAsB;EAC1B,MAAM,KAAK,OAAO,CAAC;EACnB,IAAM,IAAI,KAAK,IAAI,KAAK;EAGxB,OAFA,KAAK,OAAO,GACZ,KAAK,aAAa,GACX;CACT;CACA,MAAM,KAAsB;EAC1B,MAAM,KAAK,OAAO,CAAC;EACnB,IAAM,IAAI,KAAK,KACT,KAAM,KAAK,IAAI,MAAM,IAAK,KAAK,IAAI,IAAI,QAAQ;EAGrD,OAFA,KAAK,OAAO,GACZ,KAAK,aAAa,GACX;CACT;CACA,MAAM,KAAsB;EAC1B,MAAM,KAAK,OAAO,CAAC;EACnB,IAAM,IAAI,KAAK,KACT,IAAI,KAAK,KACT,KAAM,EAAE,MAAM,KAAO,EAAE,IAAI,MAAM,KAAO,EAAE,IAAI,MAAM,IAAK,EAAE,IAAI,QAAQ;EAG7E,OAFA,KAAK,OAAO,GACZ,KAAK,aAAa,GACX;CACT;CACA,MAAc,KAAsB;EAClC,MAAM,KAAK,OAAO,CAAC;EAEnB,IAAM,IAAI,IADK,SAAS,KAAK,IAAI,QAAQ,KAAK,IAAI,aAAa,KAAK,KAAK,CAC/D,CAAA,CAAG,aAAa,GAAG,EAAK;EAGlC,OAFA,KAAK,OAAO,GACZ,KAAK,aAAa,GACX;CACT;CAEA,MAAM,GAAG,GAAiC;EAIxC,OAHI,MAAW,KAAW,MAAM,KAAK,GAAG,EAAA,CAAG,SAAS,IAChD,MAAW,KAAW,MAAM,KAAK,GAAG,EAAA,CAAG,SAAS,IAChD,MAAW,KAAW,MAAM,KAAK,GAAG,EAAA,CAAG,SAAS,KAC5C,MAAM,KAAK,GAAG,EAAA,CAAG,SAAS;CACpC;CAEA,MAAM,MAAM,GAAgC;EAC1C,MAAM,KAAK,OAAO,CAAC;EACnB,IAAM,IAAI,KAAK,IAAI,MAAM,KAAK,KAAK,KAAK,MAAM,CAAC;EAG/C,OAFA,KAAK,OAAO,GACZ,KAAK,aAAa,GACX;CACT;CAEA,MAAM,UAA2B;EAC/B,IAAM,IAAgB,CAAC;EACvB,SAAS;GACP,IAAM,IAAI,MAAM,KAAK,GAAG;GACxB,IAAI,MAAM,GAAG;GACb,EAAI,KAAK,CAAC;EACZ;EACA,OAAO,IAAI,YAAY,OAAO,CAAC,CAAC,OAAO,IAAI,WAAW,CAAG,CAAC;CAC5D;CAEA,MAAM,KAAK,GAA0B;EACnC,IAAI,KAAK,GAAG;EACZ,IAAM,IAAQ,KAAK,IAAI,SAAS,KAAK;EACrC,IAAI,KAAK,GAAO;GAEd,AADA,KAAK,OAAO,GACZ,KAAK,aAAa;GAClB;EACF;EACA,IAAM,IAAY,IAAI;EAMtB,IALA,KAAK,MAAM,KAAK,IAAI,QACpB,KAAK,aAAa,GAClB,KAAK,MAAM,IAAI,WAAY,GAC3B,KAAK,cAAc,GACnB,KAAK,aAAa,GACd,KAAK,aAAa,KAAK,MACzB,MAAM,IAAI,EAAgB,qBAAqB;CAEnD;AACF,GAGM,IAAa,GACb,IAAiB,GACjB,IAAgB,IAChB,IAAwB,IAGxB,IAAiB,IACjB,IAAoB,IACpB,IAAwB,IACxB,IAA2B,IAI3B,IAA4D;CAChE,IAAO,MAAM;CACb,SAAY;CACZ,SAAY;CACZ,SAAY;CACZ,SAAY;CACZ,SAAY;CACZ,SAAY;CACZ,SAAY;CACZ,WAAY;CACZ,WAAY;CACZ,WAAY;CACZ,WAAY;CACZ,WAAY;CACZ,WAAY;CACZ,WAAY;CACZ,WAAY;AACd,GAiJa,IAAkB,MAEzB,IAAU,KAIV,IAAc;AACpB,SAAS,IAA0B;CACjC,OAAO,IAAI,SAAS,MAAQ,WAAW,GAAK,CAAC,CAAC;AAChD;AAGA,eAAe,EAAW,GAA+D;CACvF,IAAM,IAAQ,MAAM,EAAE,QAAQ;CAC9B,IAAI,CAAC,EAAM,WAAW,cAAc,GAClC,MAAM,IAAI,EAAgB,6BAA4B,EAAM,MAAM,GAAG,EAAE,IAAI,KAAI;CAEjF,IAAM,IAAS,MAAM,EAAE,GAAG;CAC1B,IAAI,MAAW,KAAK,MAAW,KAAK,MAAW,KAAK,MAAW,GAC7D,MAAM,IAAI,EAAgB,gBAAgB,CAAM;CAElD,IAAM,IAAO,MAAM,EAAE,GAAG,GAClB,IAAO,MAAM,EAAE,GAAG;CAExB,OAAO;EAAE;EAAQ,YADG,OAAO,CAAI,KAAK,MAAO,OAAO,CAAI,EAAA,CAAG,SACxC;CAAU;AAC7B;AAGA,eAAe,EACb,GACA,GACsD;CACtD,IAAM,IAAa,MAAM,EAAE,GAAG,CAAM;CACpC,MAAM,EAAE,KAAK,CAAC;CACd,IAAM,IAAU,MAAM,EAAE,GAAG,CAAM;CACjC,MAAM,EAAE,KAAK,IAAS,CAAC;CACvB,IAAM,IAAe,MAAM,EAAE,GAAG,GAE1B,IAAS,MAAM,EAAE,GAAG;CAC1B,KAAK,IAAI,IAAI,GAAG,IAAI,GAAQ,KAAK;EAC/B,MAAM,EAAE,GAAG;EACX,IAAM,IAAI,MAAM,EAAE,GAAG;EACrB,MAAM,EAAE,KAAK,EAAS,GAAG,CAAM,CAAC;CAClC;CACA,IAAM,IAAc,MAAM,EAAE,GAAG;CAC/B,KAAK,IAAI,IAAI,GAAG,IAAI,GAAa,KAAK;EACpC,MAAM,EAAE,GAAG,CAAM;EACjB,IAAM,IAAI,MAAM,EAAE,GAAG;EACrB,MAAM,EAAE,KAAK,EAAS,GAAG,CAAM,CAAC;CAClC;CACA,IAAM,IAAY,MAAM,EAAE,GAAG,GACvB,IAAyB,CAAC;CAChC,KAAK,IAAI,IAAI,GAAG,IAAI,GAAW,KAAK;EAClC,IAAM,IAAS,MAAM,EAAE,GAAG,CAAM,GAC1B,IAAO,MAAM,EAAE,GAAG;EACxB,EAAW,KAAK;GAAE;GAAQ;EAAK,CAAC;CAClC;CACA,OAAO;EAAE;EAAY,MAAM;GAAE;GAAS;GAAc;EAAW;CAAE;AACnE;AAaA,eAAe,EAAQ,GAAe,GAAa,GAA0C;CAC3F,IAAM,IAAY,EAAc;CAChC,IAAI,GAEF,OADA,MAAM,EAAE,KAAK,IAAS,EAAU,CAAM,CAAC,GAChC;CAET,QAAQ,GAAR;EACE,KAAK,GAAgB;GACnB,IAAM,EAAE,eAAY,YAAS,MAAM,EAAc,GAAG,CAAM;GAC1D,OAAO;IAAE,MAAM;IAAS;IAAY;GAAK;EAC3C;EACA,KAAK,GAAmB;GACtB,IAAM,IAAK,MAAM,EAAE,GAAG,CAAM;GAK5B,OAJA,MAAM,EAAE,KAAK,CAAC,GAIP;IAAE,MAAM;IAAY;IAAI,YAAA,MAHN,EAAE,GAAG,CAAM;IAGO,UAAA,MAFpB,EAAE,GAAG;GAEwB;EACtD;EACA,KAAK,GAAuB;GAE1B,AADA,MAAM,EAAE,GAAG,CAAM,GACjB,MAAM,EAAE,KAAK,CAAC;GACd,IAAM,IAAc,MAAM,EAAE,GAAG,GACzB,IAAc,MAAM,EAAE,GAAG,CAAM;GAGrC,OAFA,MAAM,EAAE,KAAK,IAAc,CAAM,GAE1B;IAAE,MAAM;IAAY;IAAa;IAAa,SADrC,IAAc,IAAS,IAAS,IAAI;GACS;EAC/D;EACA,KAAK,GAA0B;GAE7B,AADA,MAAM,EAAE,GAAG,CAAM,GACjB,MAAM,EAAE,KAAK,CAAC;GACd,IAAM,IAAc,MAAM,EAAE,GAAG,GACzB,IAAW,MAAM,EAAE,GAAG;GAG5B,OAFA,MAAM,EAAE,KAAK,IAAc,EAAS,GAAU,CAAM,CAAC,GAE9C;IAAE,MAAM;IAAa;IAAU;IAAa,SADnC,IAAc,EAAS,GAAU,CAAM,IAAI,IAAS,IAAI;GACb;EAC7D;EACA,SACE,MAAM,IAAI,EACR,iBAAiB,EAAI,SAAS,EAAE,IAAI,SAAS,EAAE,YAAY,GAC7D;CACJ;AACF;AAGA,SAAS,EAAS,GAAc,GAAa,GAAwB;CAInE,OAHI,MAAW,IAAU,EAAG,aAAa,GAAK,EAAK,CAAC,CAAC,SAAS,IAC1D,MAAW,IAAU,EAAG,UAAU,GAAK,EAAK,CAAC,CAAC,SAAS,IACvD,MAAW,IAAU,EAAG,UAAU,GAAK,EAAK,CAAC,CAAC,SAAS,IACpD,EAAG,SAAS,CAAG,CAAC,CAAC,SAAS;AACnC;AAGA,SAAS,EAAa,GAAkB,GAAsB,GAAmC;CAC/F,IAAM,IAAK,IAAI,SAAS,EAAK,QAAQ,EAAK,YAAY,EAAK,UAAU,GAC/D,IAAyB,CAAC,GAC5B,IAAM;CACV,KAAK,IAAM,KAAK,GACd,QAAQ,EAAE,MAAV;EACE,KAAK,GAAU;GACb,IAAM,IAAK,EAAS,GAAI,GAAK,CAAM;GAEnC,AADA,KAAO,GACP,EAAI,KACF,MAAO,MACH;IAAE,MAAM,EAAE;IAAM,OAAO;IAAQ,MAAM;GAAO,IAC5C;IAAE,MAAM,EAAE;IAAM,OAAO,MAAM;IAAI,MAAM;IAAO,OAAO;GAAG,CAC9D;GACA;EACF;EACA,KAAK;GAEH,AADA,EAAI,KAAK;IAAE,MAAM,EAAE;IAAM,OAAO,EAAG,SAAS,CAAG,MAAM,IAAa,UAAT;IAAkB,MAAM;GAAO,CAAC,GACzF,KAAO;GACP;EACF,KAAK;GAEH,AADA,EAAI,KAAK;IAAE,MAAM,EAAE;IAAM,OAAO,OAAO,EAAG,QAAQ,CAAG,CAAC;IAAG,MAAM;GAAO,CAAC,GACvE,KAAO;GACP;EACF,KAAK,GAAQ;GACX,IAAM,IAAI,EAAG,UAAU,GAAK,EAAK;GAEjC,AADA,EAAI,KAAK;IAAE,MAAM,EAAE;IAAM,OAAO,EAAY,CAAC;IAAG,MAAM;GAAO,CAAC,GAC9D,KAAO;GACP;EACF;EACA,KAAK;GAEH,AADA,EAAI,KAAK;IAAE,MAAM,EAAE;IAAM,OAAO,OAAO,EAAG,SAAS,GAAK,EAAK,CAAC;IAAG,MAAM;GAAO,CAAC,GAC/E,KAAO;GACP;EACF,KAAK;GAEH,AADA,EAAI,KAAK;IAAE,MAAM,EAAE;IAAM,OAAO,EAAO,EAAG,WAAW,GAAK,EAAK,CAAC;IAAG,MAAM;GAAO,CAAC,GACjF,KAAO;GACP;EACF,KAAK;GAEH,AADA,EAAI,KAAK;IAAE,MAAM,EAAE;IAAM,OAAO,OAAO,EAAG,SAAS,GAAK,EAAK,CAAC;IAAG,MAAM;GAAO,CAAC,GAC/E,KAAO;GACP;EACF,KAAK;GAEH,AADA,EAAI,KAAK;IAAE,MAAM,EAAE;IAAM,OAAO,EAAO,EAAG,WAAW,GAAK,EAAK,CAAC;IAAG,MAAM;GAAO,CAAC,GACjF,KAAO;GACP;EACF,KAAK;GAEH,AADA,EAAI,KAAK;IAAE,MAAM,EAAE;IAAM,OAAO,EAAG,YAAY,GAAK,EAAK,CAAC,CAAC,SAAS;IAAG,MAAM;GAAO,CAAC,GACrF,KAAO;GACP;EACF,SACE,KAAO,EAAS,EAAE,MAAM,CAAM;CAClC;CAEF,OAAO;AACT;AAGA,SAAS,EAAY,GAAsB;CAEzC,OADI,KAAQ,MAAQ,MAAS,MAAa,MAAM,OAAO,aAAa,CAAI,IAAI,MACrE,SAAS,EAAK,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,IAAI;AACvD;AACA,SAAS,EAAO,GAAmB;CAGjC,OAFI,OAAO,MAAM,CAAC,IAAU,QACvB,OAAO,SAAS,CAAC,IACf,OAAO,CAAC,IADiB,IAAI,IAAI,aAAa;AAEvD;AAKA,SAAS,EAAkB,GAAkC;CAC3D,IAAI,CAAC,GAAM,OAAO;CAClB,IAAI,EAAK,OAAO,KAAK,OAAO,IAAO;CACnC,IAAI,IAAO,GACP,IAAI;CACR,OAAO,IAAI,EAAK,UAAU,EAAK,OAAO,MAEpC,AADA,KACA;CAEF,IAAI,IAAO,EAAK,MAAM,CAAC;CAavB,OAFA,AACK,IADD,EAAK,WAAW,GAAG,KAAK,EAAK,SAAS,GAAG,IAAU,EAAK,MAAM,GAAG,EAAE,IAC3D;EAVV,GAAG;EACH,GAAG;EACH,GAAG;EACH,GAAG;EACH,GAAG;EACH,GAAG;EACH,GAAG;EACH,GAAG;CAGO,EAAK,MAAS,GACnB,IAAO,KAAK,OAAO,CAAI;AAChC;AAEA,SAAS,EAAiB,GAAkC;CAC1D,IAAM,IAAO,EAAkB,CAAI;CACnC,OAAO,EAAK,SAAS,IAAI,IAAI,EAAK,MAAM,GAAG,EAAE,IAAI;AACnD;AAGA,SAAS,EAAY,GAAc,GAAa,GAAsB;CACpE,QAAQ,GAAR;EACE,KAAK,GACH,OAAO,EAAG,SAAS,CAAG,MAAM,IAAa,UAAT;EAClC,KAAK,GACH,OAAO,OAAO,EAAG,QAAQ,CAAG,CAAC;EAC/B,KAAK,GACH,OAAO,EAAY,EAAG,UAAU,GAAK,EAAK,CAAC;EAC7C,KAAK,GACH,OAAO,OAAO,EAAG,SAAS,GAAK,EAAK,CAAC;EACvC,KAAK,GACH,OAAO,EAAO,EAAG,WAAW,GAAK,EAAK,CAAC;EACzC,KAAK,GACH,OAAO,OAAO,EAAG,SAAS,GAAK,EAAK,CAAC;EACvC,KAAK,GACH,OAAO,EAAO,EAAG,WAAW,GAAK,EAAK,CAAC;EACzC,KAAK,GACH,OAAO,EAAG,YAAY,GAAK,EAAK,CAAC,CAAC,SAAS;EAC7C,SACE,OAAO;CACX;AACF;AACA,SAAS,EAAsB,GAAiB,GAAqC;CACnF,IAAM,IAAK,IAAI,SAAS,EAAI,QAAQ,EAAI,YAAY,EAAI,UAAU,GAC5D,IAAK,EAAS,GAAU,CAAC,GACzB,IAAI,KAAK,IAAI,KAAK,MAAM,EAAI,aAAa,CAAE,GAAA,GAAoB,GAC/D,IAAyB,CAAC;CAChC,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KACrB,EAAI,KAAK;EAAE,MAAM,OAAO,CAAC;EAAG,OAAO,EAAY,GAAI,IAAI,GAAI,CAAQ;EAAG,MAAM;CAAO,CAAC;CACtF,OAAO;AACT;AAGA,SAAS,EAAkB,GAAyB;CAClD,IAAI,IAAI,IACF,IAAI,EAAI,aAAa;CAC3B,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,OAAO,aAAc,EAAI,MAAM,IAAK,EAAI,IAAI,EAAE;CAClF,OAAO;AACT;AAEA,SAAS,EAAqB,GAAyB;CACrD,IAAI,IAAI,IACF,IAAI,EAAI,aAAa;CAC3B,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,OAAO,aAAa,EAAI,KAAM,EAAI,IAAI,MAAM,CAAE;CAClF,OAAO;AACT;AACA,SAAS,EAAoB,GAAyB;CACpD,IAAI,IAAI;CACR,KAAK,IAAI,IAAI,GAAG,IAAI,EAAI,YAAY,KAAK,KAAK,OAAO,aAAa,EAAI,EAAE;CACxE,OAAO;AACT;AAEA,SAAS,EAAgB,GAAqC;CAC5D,IAAI,EAAI,eAAe,GAAG,OAAO;CACjC,IAAI,IAAY;CAChB,KAAK,IAAI,IAAI,GAAG,IAAI,EAAI,YAAY,KAAK;EACvC,IAAM,IAAI,EAAI;EACd,CAAK,KAAK,MAAQ,IAAI,OAAS,MAAM,KAAK,MAAM,MAAM,MAAM,OAAI;CAClE;CACA,OAAO,IAAY,EAAI,cAAc,MAAO,EAAoB,CAAG,IAAI,KAAA;AACzE;AACA,SAAS,EAAM,GAAyB;CACtC,IAAM,IAAI,KAAK,IAAI,EAAI,YAAY,CAAO,GACtC,IAAI;CACR,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK,KAAK,EAAI,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,KAAK,IAAI,IAAI,IAAI,MAAM;CAC3F,OAAO,EAAI,aAAa,IAAI,IAAI,OAAO;AACzC;AAGA,SAAS,EACP,GACA,GACA,GACmB;CACnB,IAAM,IAAuB;EAAE;EAAU;EAAQ,WAAW;CAAM;CAClE,IAAI,MAAa,GAEf,AADA,EAAE,OAAO,EAAkB,CAAG,GAC9B,EAAE,YAAY,EAAI,aAAa,IAAS;MACnC,IAAI,MAAa,GAAQ;EAC9B,EAAE,MAAM,EAAM,CAAG;EACjB,IAAM,IAAI,EAAgB,CAAG;EAE7B,AADI,MAAM,KAAA,MAAW,EAAE,OAAO,IAC9B,EAAE,YAAY,EAAI,aAAa;CACjC,OAEE,AADA,EAAE,WAAW,EAAsB,GAAK,CAAQ,GAChD,EAAE,YAAY,EAAE,SAAS,SAAS;CAEpC,OAAO;AACT;AAOA,SAAgB,EAAkB,GAAiB,GAAkB,GAA8B;CAEjG,OADI,MAAa,IAAe,EAAkB,CAAG,IAC9C,MAAU,IAAI,EAAqB,CAAG,IAAI,EAAoB,CAAG;AAC1E;AAOA,IAAa,IAAb,MAAa,EAAM;CAGE;CAEA;CACA;CACA;CACA;CACA;CARnB;CACA,YACE,GACA,GACA,GACA,GACA,GACA,GACA,GACA;EACA,AARiB,KAAA,OAAA,GAEA,KAAA,SAAA,GACA,KAAA,YAAA,GACA,KAAA,aAAA,GACA,KAAA,UAAA,GACA,KAAA,cAAA,GAEjB,KAAK,UAAU;CACjB;CAGA,YAAY,GAA4B;EACtC,OAAO,KAAK,WAAW,IAAI,CAAU,KAAK,YAAY,IAAa;CACrE;CAOA,cAAsB,GAAyC;EAC7D,IAAM,IAAS,KAAK,YAAY,IAAI,CAAU;EAC9C,IAAI,MAAW,KAAA,GAAW,OAAO;EACjC,IAAM,IAAuB,CAAC,GAC1B,IAAM,GACJ,oBAAO,IAAI,IAAY;EAC7B,OAAO,MAAQ,OACT,GAAK,IAAI,CAAG,IADE;GAElB,EAAK,IAAI,CAAG;GACZ,IAAM,IAAO,KAAK,UAAU,IAAI,CAAG;GACnC,IAAI,CAAC,GAEH,OADA,KAAK,YAAY,IAAI,GAAY,IAAI,GAC9B;GAET,KAAK,IAAM,KAAK,EAAK,YACnB,EAAO,KAAK;IACV,MAAM,KAAK,QAAQ,IAAI,EAAE,MAAM,KAAK,YAAY,EAAE,SAAS;IAC3D,MAAM,EAAE;GACV,CAAC;GAEH,IAAM,EAAK;EACb;EAEA,OADA,KAAK,YAAY,IAAI,GAAY,CAAM,GAChC;CACT;CAEA,aAAa,MAAM,GAAY,GAA4C;EACzE,IAAM,IAAI,IAAI,EAAW,CAAI,GACvB,EAAE,WAAQ,iBAAc,MAAM,EAAW,CAAC,GAE1C,oBAAU,IAAI,IAAoB,GAClC,oBAAiB,IAAI,IAAoB,GACzC,oBAAY,IAAI,IAA2B,GAC3C,oBAAW,IAAI,IAA8C,GAC7D,oBAAY,IAAI,IAA8C,GAC9D,oBAAa,IAAI,IAA8C,GACjE,IAAU,GACV,IAAgB,GAChB,IAAc,GACd,IAAa,GACb,IAAY,GAEZ,IAAO,GACL,IAAO,YAA2B;GACtC,AAAI,EAAE,IAAO,MAAgB,MAC3B,IAAa,EAAE,WAAW,EAAE,IAAI,GAChC,MAAM,EAAS;EAEnB;EAEA,OAAO,EAAE,YAAY,EAAE,OAAM;GAC3B,IAAM,IAAM,MAAM,EAAE,GAAG;GACvB,MAAM,EAAE,GAAG;GACX,IAAM,IAAS,MAAM,EAAE,GAAG,GACpB,IAAS,EAAE,YAAY;GAG7B,IAFA,KAEI,MAAQ,GAAY;IACtB,IAAM,IAAM,MAAM,EAAE,GAAG,CAAM,GACvB,IAAW,MAAM,EAAE,MAAM,IAAS,CAAM;IAC9C,EAAQ,IAAI,GAAK,IAAI,YAAY,OAAO,CAAC,CAAC,OAAO,CAAQ,CAAC;GAC5D,OAAO,IAAI,MAAQ,GAAgB;IACjC,MAAM,EAAE,GAAG;IACX,IAAM,IAAa,MAAM,EAAE,GAAG,CAAM;IACpC,MAAM,EAAE,GAAG;IACX,IAAM,IAAS,MAAM,EAAE,GAAG,CAAM;IAChC,EAAe,IAAI,GAAY,CAAM;GACvC,OAAO,IAAI,MAAQ,KAAiB,MAAQ,GAC1C,OAAO,EAAE,YAAY,IAAQ;IAE3B,IAAM,IAAK,MAAM,EAAQ,GAAG,MADV,EAAE,GAAG,GACU,CAAM;IACvC,IAAI,GACF,IAAI,EAAG,SAAS,SAEd,AADA,EAAU,IAAI,EAAG,YAAY,EAAG,IAAI,GACpC;SACK,IAAI,EAAG,SAAS,YAAY;KAEjC,AADA,MAAM,EAAE,KAAK,EAAG,QAAQ,GACxB;KACA,IAAM,IAAU,EAAG,WAAW,IAAS;KACvC,KAAa;KACb,IAAM,IAAI,EAAS,IAAI,EAAG,UAAU;KACpC,AAAI,KACF,EAAE,SACF,EAAE,SAAS,KAEX,EAAS,IAAI,EAAG,YAAY;MAAE,OAAO;MAAG,OAAO;KAAQ,CAAC;IAE5D,OAAO,IAAI,EAAG,SAAS,YAAY;KAEjC,AADA,KACA,KAAa,EAAG;KAChB,IAAM,IAAI,EAAU,IAAI,EAAG,WAAW;KACtC,AAAI,KACF,EAAE,SACF,EAAE,SAAS,EAAG,WAEd,EAAU,IAAI,EAAG,aAAa;MAAE,OAAO;MAAG,OAAO,EAAG;KAAQ,CAAC;IAEjE,OAAO;KAEL,AADA,KACA,KAAa,EAAG;KAChB,IAAM,IAAI,EAAW,IAAI,EAAG,QAAQ;KACpC,AAAI,KACF,EAAE,SACF,EAAE,SAAS,EAAG,WAEd,EAAW,IAAI,EAAG,UAAU;MAAE,OAAO;MAAG,OAAO,EAAG;KAAQ,CAAC;IAE/D;SAEA;IAEF,MAAM,EAAK;GACb;QAEA,MAAM,EAAE,KAAK,CAAM;GAIrB,IAAI,EAAE,YAAY,GAAQ,MAAM,EAAE,KAAK,IAAS,EAAE,SAAS;QACtD,IAAI,EAAE,YAAY,GACrB,MAAM,IAAI,EACR,aACE,EAAI,SAAS,EAAE,IACf,aACA,EAAE,YACF,UACA,IACA,GACJ;GAEF,MAAM,EAAK;EACb;EAGA,IAAM,oBAAa,IAAI,IAAoB;EAC3C,KAAK,IAAM,CAAC,GAAY,MAAW,GACjC,EAAW,IAAI,GAAY,EAAQ,IAAI,CAAM,KAAK,YAAY,IAAa,GAAG;EAGhF,IAAM,IAAwB,CAAC;EAC/B,KAAK,IAAM,CAAC,GAAY,MAAM,GAC5B,EAAK,KAAK;GACR,MAAM,EAAW,IAAI,CAAU,KAAK,YAAY,IAAa;GAC7D,OAAO,EAAE;GACT,OAAO,EAAE;GACT,QAAQ;IAAE,MAAM;IAAS;GAAW;EACtC,CAAC;EAEH,KAAK,IAAM,CAAC,GAAa,MAAM,GAC7B,EAAK,KAAK;GACR,MAAM,EAAkB,EAAW,IAAI,CAAW,CAAC;GACnD,OAAO,EAAE;GACT,OAAO,EAAE;GACT,QAAQ;IAAE,MAAM;IAAY;GAAY;EAC1C,CAAC;EAEH,KAAK,IAAM,CAAC,GAAU,MAAM,GAC1B,EAAK,KAAK;GACR,MAAM,EAAa,CAAQ,IAAI;GAC/B,OAAO,EAAE;GACT,OAAO,EAAE;GACT,QAAQ;IAAE,MAAM;IAAa;GAAS;EACxC,CAAC;EAiBH,OAfA,EAAK,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,GAE1D,IAAa,EAAE,MAAM,EAAE,IAAI,GAapB,IAAI,EAAM,GAAM;GAXrB;GACA;GACA,UAAU,EAAK;GACf;GACA;GACA;GACA;GACA,aAAa,EAAQ;GACrB;GACA;EAEqB,GAAS,GAAQ,GAAW,GAAY,mBAAS,IAAI,IAAI,CAAC;CACnF;CASA,MAAM,QAAQ,GAAuB,IAAuB,CAAC,GAAgC;EAC3F,IAAM,IAAQ,EAAK,SAAA,KACb,IAAS,EAAK,QAAQ,KAAK,CAAC,CAAC,YAAY,KAAK,IAC9C,IAAS,KAAK,QACd,IAAS,EAAO,SAAS,UAAU,KAAK,cAAc,EAAO,UAAU,IAAI,MAE3E,IAAI,IAAI,EAAW,KAAK,IAAI;EAClC,MAAM,EAAW,CAAC;EAElB,IAAM,IAAwB,CAAC,GAC3B,IAAQ,GACR,IAAO,GACL,IAAO,YAA2B;GACtC,AAAI,EAAE,IAAO,MAAgB,MAC3B,EAAK,aAAa,EAAE,WAAW,EAAE,IAAI,GACrC,MAAM,EAAS;EAEnB,GAEM,KAAY,MAA6B;GACzC,KAAU,CAAC,EAAW,GAAK,CAAM,MACrC,KACI,EAAK,SAAS,KAAO,EAAK,KAAK,CAAG;EACxC;EAEA,OAAO,EAAE,YAAY,EAAE,OAAM;GAC3B,IAAM,IAAM,MAAM,EAAE,GAAG;GACvB,MAAM,EAAE,GAAG;GACX,IAAM,IAAS,MAAM,EAAE,GAAG,GACpB,IAAS,EAAE,YAAY;GAE7B,IAAI,MAAQ,KAAiB,MAAQ,GACnC,OAAO,EAAE,YAAY,IAAQ;IAC3B,IAAM,IAAM,MAAM,EAAE,GAAG;IACvB,IAAI,EAAO,SAAS,WAAW,MAAQ,GAAmB;KACxD,IAAM,IAAK,MAAM,EAAE,GAAG,CAAM;KAC5B,MAAM,EAAE,KAAK,CAAC;KACd,IAAM,IAAM,MAAM,EAAE,GAAG,CAAM,GACvB,IAAW,MAAM,EAAE,GAAG;KAC5B,IAAI,MAAQ,EAAO,YAAY;MAC7B,IAAM,IAAU,IAAW,IAAS;MAEpC,IAAI,KAAU,EAAK,SAAS,GAAO;OACjC,IAAM,IAAO,MAAM,EAAE,MAAM,CAAQ;OAEnC,EAAS;QAAE;QAAI,MAAM;QAAS,QADf,IAAS,EAAa,GAAM,GAAQ,CAAM,IAAI,CAAC;OACzB,CAAC;MACxC,OAEE,AADA,MAAM,EAAE,KAAK,CAAQ,GACrB;KAEJ,OACE,MAAM,EAAE,KAAK,CAAQ;IAEzB,OAAO,IAAI,EAAO,SAAS,eAAe,MAAQ,GAA0B;KAC1E,IAAM,IAAK,MAAM,EAAE,GAAG,CAAM;KAC5B,MAAM,EAAE,KAAK,CAAC;KACd,IAAM,IAAM,MAAM,EAAE,GAAG,GACjB,IAAW,MAAM,EAAE,GAAG,GACtB,IAAS,IAAM,EAAS,GAAU,CAAM;KAC9C,IAAI,MAAa,EAAO,UAAU;MAChC,IAAM,IAAU,IAAS,IAAS,IAAI;MACtC,IAAI,KAAU,EAAK,SAAS,GAAO;OACjC,IAAM,IAAO,KAAK,IAAI,GAAQ,CAAe,GACvC,IAAM,MAAM,EAAE,MAAM,CAAI;OAE9B,AADA,MAAM,EAAE,KAAK,IAAS,CAAI,GAC1B,EAAS;QACP;QACA,MAAM;QACN,QAAQ,CAAC;QACT,OAAO,EAAsB,GAAU,GAAK,CAAG;OACjD,CAAC;MACH,OAEE,AADA,MAAM,EAAE,KAAK,CAAM,GACnB;KAEJ,OACE,MAAM,EAAE,KAAK,CAAM;IAEvB,OAAO,IAAI,EAAO,SAAS,cAAc,MAAQ,GAAuB;KACtE,IAAM,IAAK,MAAM,EAAE,GAAG,CAAM;KAC5B,MAAM,EAAE,KAAK,CAAC;KACd,IAAM,IAAM,MAAM,EAAE,GAAG,GACjB,IAAa,MAAM,EAAE,GAAG,CAAM;KACpC,IAAI,MAAe,EAAO,aAAa;MACrC,IAAM,IAAU,IAAM,IAAS,IAAS,IAAI;MAC5C,AAAI,KAAU,EAAK,SAAS,IAE1B,EAAS;OAAE;OAAI,MAAM;OAAS,QAAQ,CAAC;OAAG,OAAA,MADtB,KAAK,oBAAoB,GAAG,GAAK,GAAY,CAAM;MACvB,CAAC,KAEjD,MAAM,EAAE,KAAK,IAAM,CAAM,GACzB;KAEJ,OACE,MAAM,EAAE,KAAK,IAAM,CAAM;IAE7B,OAAO;KAGL,IAAM,IAAK,MAAM,EAAQ,GAAG,GAAK,CAAM;KACvC,AAAI,KAAM,EAAG,SAAS,cAAY,MAAM,EAAE,KAAK,EAAG,QAAQ;IAC5D;IACA,MAAM,EAAK;GACb;QAEA,MAAM,EAAE,KAAK,CAAM;GAGrB,IAAI,EAAE,YAAY,GAAQ,MAAM,EAAE,KAAK,IAAS,EAAE,SAAS;QACtD,IAAI,EAAE,YAAY,GACrB,MAAM,IAAI,EAAgB,aAAa,EAAE,YAAY,UAAU,IAAS,GAAG;GAE7E,MAAM,EAAK;EACb;EAGA,OADA,EAAK,aAAa,EAAE,MAAM,EAAE,IAAI,GACzB;GAAE;GAAM;GAAO,WAAW,IAAQ,EAAK;EAAO;CACvD;CAGA,MAAc,oBACZ,GACA,GACA,GACA,GAC4B;EAC5B,IAAM,IAAO,KAAK,IAAI,GAAA,GAAsB,GACtC,IAA8B,CAAC;EACrC,KAAK,IAAI,IAAI,GAAG,IAAI,GAAM,KAAK;GAC7B,IAAM,IAAM,MAAM,EAAE,GAAG,CAAM;GAC7B,EAAS,KACP,MAAQ,MACJ;IAAE,MAAM,OAAO,CAAC;IAAG,OAAO;IAAQ,MAAM;GAAO,IAC/C;IAAE,MAAM,OAAO,CAAC;IAAG,OAAO,MAAM;IAAK,MAAM;IAAO,OAAO;GAAI,CACnE;EACF;EAEA,OADA,MAAM,EAAE,MAAM,IAAM,KAAQ,CAAM,GAC3B;GACL,eAAe,EAAiB,KAAK,WAAW,IAAI,CAAU,CAAC;GAC/D,QAAQ;GACR;GACA,WAAW,IAAO;EACpB;CACF;CAQA,MAAM,eACJ,GACA,GACuC;EACvC,IAAM,IAAS,KAAK,QACd,oBAAM,IAAI,IAA6B,GACzC,IAAY;EAChB,KAAK,IAAM,KAAM,GAAK;GACpB,IAAM,IAAK,KAAK,WAAW,IAAI,CAAE;GACjC,AAAI,IAAI,EAAI,IAAI,GAAI;IAAE;IAAI,MAAM;IAAS,WAAW;GAAG,CAAC,IACnD;EACP;EACA,IAAI,MAAc,GAAG,OAAO;EAE5B,IAAM,IAAI,IAAI,EAAW,KAAK,IAAI;EAClC,MAAM,EAAW,CAAC;EAClB,IAAI,IAAO,GACL,IAAO,YAA2B;GACtC,AAAI,EAAE,IAAO,MAAgB,MAC3B,IAAa,EAAE,WAAW,EAAE,IAAI,GAChC,MAAM,EAAS;EAEnB;EAEA,OAAO,EAAE,YAAY,EAAE,QAAQ,IAAY,IAAG;GAC5C,IAAM,IAAM,MAAM,EAAE,GAAG;GACvB,MAAM,EAAE,GAAG;GACX,IAAM,IAAS,MAAM,EAAE,GAAG,GACpB,IAAS,EAAE,YAAY;GAE7B,IAAI,MAAQ,KAAiB,MAAQ,GACnC,OAAO,EAAE,YAAY,KAAU,IAAY,IAAG;IAC5C,IAAM,IAAM,MAAM,EAAE,GAAG;IACvB,IAAI,MAAQ,GAAmB;KAC7B,IAAM,IAAK,MAAM,EAAE,GAAG,CAAM;KAC5B,MAAM,EAAE,KAAK,CAAC;KACd,IAAM,IAAM,MAAM,EAAE,GAAG,CAAM,GACvB,IAAW,MAAM,EAAE,GAAG;KAC5B,IAAI,EAAI,IAAI,CAAE,KAAK,CAAC,EAAI,IAAI,CAAE,GAAG;MAC/B,IAAM,IAAO,MAAM,EAAE,MAAM,CAAQ,GAC7B,IAAS,KAAK,cAAc,CAAG;MAQrC,AAPA,EAAI,IAAI,GAAI;OACV;OACA,MAAM;OACN,WAAW,KAAK,YAAY,CAAG;OAC/B,MAAM,IAAW,IAAS;OAC1B,QAAQ,IAAS,EAAa,GAAM,GAAQ,CAAM,IAAI,CAAC;MACzD,CAAC,GACD;KACF,OACE,MAAM,EAAE,KAAK,CAAQ;IAEzB,OAAO,IAAI,MAAQ,GAA0B;KAC3C,IAAM,IAAK,MAAM,EAAE,GAAG,CAAM;KAC5B,MAAM,EAAE,KAAK,CAAC;KACd,IAAM,IAAM,MAAM,EAAE,GAAG,GACjB,IAAW,MAAM,EAAE,GAAG,GACtB,IAAS,IAAM,EAAS,GAAU,CAAM;KAC9C,IAAI,EAAI,IAAI,CAAE,KAAK,CAAC,EAAI,IAAI,CAAE,GAAG;MAC/B,IAAM,IAAO,KAAK,IAAI,GAAQ,CAAe,GACvC,IAAM,MAAM,EAAE,MAAM,CAAI;MAY9B,AAXA,MAAM,EAAE,KAAK,IAAS,CAAI,GAC1B,EAAI,IAAI,GAAI;OACV;OACA,MAAM;OACN,WAAW,EAAa,CAAQ,IAAI;OACpC,MAAM,IAAS,IAAS,IAAI;OAC5B,QAAQ;OACR;OACA,UAAU;OACV,OAAO,EAAsB,GAAU,GAAK,CAAG;MACjD,CAAC,GACD;KACF,OACE,MAAM,EAAE,KAAK,CAAM;IAEvB,OAAO,IAAI,MAAQ,GAAuB;KACxC,IAAM,IAAK,MAAM,EAAE,GAAG,CAAM;KAC5B,MAAM,EAAE,KAAK,CAAC;KACd,IAAM,IAAM,MAAM,EAAE,GAAG,GACjB,IAAa,MAAM,EAAE,GAAG,CAAM;KACpC,IAAI,EAAI,IAAI,CAAE,KAAK,CAAC,EAAI,IAAI,CAAE,GAAG;MAC/B,IAAM,IAAQ,MAAM,KAAK,oBAAoB,GAAG,GAAK,GAAY,CAAM;MASvE,AARA,EAAI,IAAI,GAAI;OACV;OACA,MAAM;OACN,WAAW,EAAkB,KAAK,WAAW,IAAI,CAAU,CAAC;OAC5D,MAAM,IAAM,IAAS,IAAS,IAAI;OAClC,QAAQ;OACR;MACF,CAAC,GACD;KACF,OACE,MAAM,EAAE,KAAK,IAAM,CAAM;IAE7B,OAAO,IAAI,MAAQ,GACjB,MAAM,EAAc,GAAG,CAAM;SACxB;KACL,IAAM,IAAY,EAAc;KAChC,IAAI,GAAW,MAAM,EAAE,KAAK,IAAS,EAAU,CAAM,CAAC;UAEpD,MAAM,IAAI,EACR,iBAAiB,EAAI,SAAS,EAAE,IAAI,SAAS,EAAE,YAAY,GAC7D;IACJ;IACA,MAAM,EAAK;GACb;QAEA,MAAM,EAAE,KAAK,CAAM;GAIrB,IAAI,EAAE,YAAY,GAAQ,MAAM,EAAE,KAAK,IAAS,EAAE,SAAS;QACtD,IAAI,EAAE,YAAY,GACrB,MAAM,IAAI,EAAgB,aAAa,EAAE,YAAY,UAAU,IAAS,GAAG;GAE7E,MAAM,EAAK;EACb;EAGA,OADA,IAAa,EAAE,MAAM,EAAE,IAAI,GACpB;CACT;AACF;AAOA,SAAS,EAAW,GAAkB,GAAyB;CAC7D,IAAI,EAAE,GAAG,SAAS,CAAM,GAAG,OAAO;CAClC,KAAK,IAAM,KAAK,EAAE,QAChB,KAAK,EAAE,OAAO,MAAM,EAAE,MAAA,CAAO,YAAY,CAAC,CAAC,SAAS,CAAM,GAAG,OAAO;CAEtE,IAAM,IAAI,EAAE;CACZ,IAAI,GAAG;EAEL,IADI,EAAE,QAAQ,EAAE,KAAK,YAAY,CAAC,CAAC,SAAS,CAAM,KAC9C,EAAE,OAAO,EAAE,IAAI,SAAS,CAAM,GAAG,OAAO;EAC5C,IAAI,EAAE;QACC,IAAM,KAAK,EAAE,UAAU,IAAI,EAAE,MAAM,YAAY,CAAC,CAAC,SAAS,CAAM,GAAG,OAAO;EAAA;CAEnF;CACA,OAAO;AACT"}
package/dist/lib/ipynb.js CHANGED
@@ -128,3 +128,5 @@ function c(t) {
128
128
  }
129
129
  //#endregion
130
130
  export { c as parseNotebook };
131
+
132
+ //# sourceMappingURL=ipynb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ipynb.js","names":[],"sources":["../../src/lib/ipynb.ts"],"sourcesContent":["/**\n * Hand-rolled, zero-dependency Jupyter Notebook (.ipynb) parser for the side viewer.\n *\n * A notebook is JSON: a list of cells (markdown / code / raw), each code cell carrying its outputs. This\n * flattens that into a render-ready shape the viewer can walk — markdown reuses the app's markdown engine,\n * code reuses highlight.js, and each output is reduced to one best-fit representation (richest mime wins,\n * mirroring Jupyter's own display priority). nbformat 4 is the target; v3 (worksheets + inline output keys)\n * is tolerated as a best-effort fallback.\n *\n * Rich HTML output is hostile markup (it comes from arbitrary kernels) — the viewer renders it in a fully\n * sandboxed, script-disabled iframe, so this parser only carries the raw string; it never trusts it.\n */\n\nexport type NbOutput =\n | { kind: 'stream'; text: string; isError: boolean }\n | { kind: 'text'; text: string }\n | { kind: 'json'; text: string }\n | { kind: 'markdown'; text: string }\n | { kind: 'html'; html: string }\n | { kind: 'image'; src: string }\n | { kind: 'error'; text: string }\n\nexport interface NbCell {\n type: 'markdown' | 'code' | 'raw'\n source: string\n executionCount: number | null\n outputs: NbOutput[]\n}\n\nexport interface ParsedNotebook {\n cells: NbCell[]\n language: string\n nbformat: number\n}\n\ntype Dict = Record<string, unknown>\n\n// nbformat stores multi-line strings as an array of lines (each keeping its trailing \\n) OR a plain string.\nfunction joinSource(src: unknown): string {\n if (Array.isArray(src)) return src.map((s) => (typeof s === 'string' ? s : '')).join('')\n return typeof src === 'string' ? src : ''\n}\n\nconst ESC = String.fromCharCode(27)\n\n// Strip ANSI/VT escape sequences (IPython colorizes tracebacks). Hand-scanned to avoid a control char in the\n// source: on each ESC, skip a `[ … <final letter>` CSI run. Leaves the plain, readable text.\nfunction stripAnsi(s: string): string {\n let out = ''\n for (let i = 0; i < s.length; i++) {\n if (s[i] !== ESC) {\n out += s[i]\n continue\n }\n i++ // past ESC\n if (s[i] === '[') {\n i++\n while (i < s.length && !/[A-Za-z]/.test(s[i])) i++ // params/intermediates, up to the final byte\n }\n }\n return out\n}\n\nfunction isDict(v: unknown): v is Dict {\n return typeof v === 'object' && v !== null && !Array.isArray(v)\n}\n\n// The MIME bundle for a display_data / execute_result output, normalizing v3's inline keys (png/html/text…).\nfunction outputData(o: Dict): Dict {\n if (isDict(o.data)) return o.data\n const d: Dict = {}\n if (o.png) d['image/png'] = o.png\n if (o.jpeg) d['image/jpeg'] = o.jpeg\n if (o.gif) d['image/gif'] = o.gif\n if (o.svg) d['image/svg+xml'] = o.svg\n if (o.html) d['text/html'] = o.html\n if (o.latex) d['text/latex'] = o.latex\n if (o.text) d['text/plain'] = o.text\n return d\n}\n\n// Reduce a MIME bundle to one renderable output, richest representation first (Jupyter's display order).\nfunction pickRich(data: Dict): NbOutput {\n const has = (k: string) => data[k] != null\n const get = (k: string) => joinSource(data[k])\n if (has('text/html')) return { kind: 'html', html: get('text/html') }\n if (has('image/svg+xml')) {\n return { kind: 'image', src: `data:image/svg+xml,${encodeURIComponent(get('image/svg+xml'))}` }\n }\n for (const mime of ['image/png', 'image/jpeg', 'image/gif']) {\n if (has(mime))\n return { kind: 'image', src: `data:${mime};base64,${get(mime).replace(/\\s+/g, '')}` }\n }\n if (has('text/markdown')) return { kind: 'markdown', text: get('text/markdown') }\n if (has('text/latex')) return { kind: 'text', text: get('text/latex') }\n if (has('application/json')) {\n try {\n return { kind: 'json', text: JSON.stringify(data['application/json'], null, 2) }\n } catch {\n return { kind: 'text', text: get('application/json') }\n }\n }\n return { kind: 'text', text: get('text/plain') }\n}\n\nfunction parseOutput(o: Dict): NbOutput | null {\n // v3 uses pyout/pyerr; v4 execute_result/error. Normalize.\n const type = String(o.output_type ?? '')\n if (type === 'stream') {\n return { kind: 'stream', text: joinSource(o.text), isError: o.name === 'stderr' }\n }\n if (type === 'error' || type === 'pyerr') {\n const tb = Array.isArray(o.traceback) ? o.traceback.join('\\n') : ''\n const head = `${o.ename ?? 'Error'}: ${o.evalue ?? ''}`.trim()\n return { kind: 'error', text: stripAnsi(tb) || head }\n }\n if (type === 'execute_result' || type === 'display_data' || type === 'pyout') {\n return pickRich(outputData(o))\n }\n return null\n}\n\nfunction detectLanguage(meta: Dict): string {\n const info = isDict(meta.language_info) ? meta.language_info : {}\n const ks = isDict(meta.kernelspec) ? meta.kernelspec : {}\n const name = String(info.name ?? ks.language ?? '').toLowerCase()\n if (!name || name === 'ipython') return 'python'\n return name\n}\n\n/** Parse .ipynb source text into a flat, render-ready cell list. Throws on non-notebook JSON. */\nexport function parseNotebook(text: string): ParsedNotebook {\n const nb = JSON.parse(text) as Dict\n const meta = isDict(nb.metadata) ? nb.metadata : {}\n // v4: top-level cells. v3: cells nested under worksheets[].\n const rawCells: unknown[] = Array.isArray(nb.cells)\n ? nb.cells\n : Array.isArray(nb.worksheets)\n ? nb.worksheets.flatMap((w) => (isDict(w) && Array.isArray(w.cells) ? w.cells : []))\n : []\n if (!Array.isArray(nb.cells) && !Array.isArray(nb.worksheets)) {\n throw new Error('不是有效的 Jupyter Notebook(缺少 cells)')\n }\n\n const cells: NbCell[] = []\n for (const raw of rawCells) {\n if (!isDict(raw)) continue\n // v3 named code cells \"code\"; markdown/heading/raw otherwise.\n const ct = String(raw.cell_type ?? '')\n const source = joinSource(raw.source ?? raw.input)\n if (ct === 'code') {\n const outs = Array.isArray(raw.outputs) ? raw.outputs : []\n const outputs: NbOutput[] = []\n for (const o of outs) {\n if (!isDict(o)) continue\n const parsed = parseOutput(o)\n if (parsed) outputs.push(parsed)\n }\n const ec = raw.execution_count ?? raw.prompt_number\n cells.push({\n type: 'code',\n source,\n executionCount: typeof ec === 'number' ? ec : null,\n outputs,\n })\n } else if (ct === 'markdown' || ct === 'heading') {\n // v3 heading cells carry a level; render as a markdown heading.\n const level = typeof raw.level === 'number' ? '#'.repeat(Math.min(6, raw.level)) + ' ' : ''\n cells.push({ type: 'markdown', source: level + source, executionCount: null, outputs: [] })\n } else {\n cells.push({ type: 'raw', source, executionCount: null, outputs: [] })\n }\n }\n\n return {\n cells,\n language: detectLanguage(meta),\n nbformat: typeof nb.nbformat === 'number' ? nb.nbformat : 4,\n }\n}\n"],"mappings":"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"}
package/dist/lib/jks.js CHANGED
@@ -165,3 +165,5 @@ function _(i, a) {
165
165
  }
166
166
  //#endregion
167
167
  export { a as JCEKS_MAGIC, i as JKS_MAGIC, d as JksError, _ as decryptPrivateKey, h as readJks, g as verifyStorePassword };
168
+
169
+ //# sourceMappingURL=jks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jks.js","names":[],"sources":["../../src/lib/jks.ts"],"sourcesContent":["/**\n * Zero-dependency reader for Java keystores — JKS (`0xFEEDFEED`) and JCEKS (`0xCECECECE`) — for the keystore\n * viewer (JksViewer.vue). It parses the proprietary Sun on-disk format (magic / version / entry list / trailing\n * SHA-1 MAC) into an inventory of aliases, entry kinds, creation dates and certificate chains, and — given the\n * password — verifies store integrity and decrypts JKS private keys.\n *\n * What it can do, entirely in-browser and READ-ONLY:\n * - list every entry (private-key / trusted-cert), its alias + creation time, and each entry's X.509 chain\n * (certificates are stored UNENCRYPTED, so they always parse — see lib/x509.ts for the field extraction);\n * - verify the store password via the format's keyed MAC — SHA1(passwordUtf16BE ‖ \"Mighty Aphrodite\" ‖ body);\n * - decrypt a JKS private key with Sun's KeyProtector (OID 1.3.6.1.4.1.42.2.17.1.1): a SHA-1 keystream XOR\n * with a trailing SHA-1 check digest that doubles as the password check. On success the plaintext is a DER\n * PKCS#8 PrivateKeyInfo, from which we surface the key algorithm / size.\n *\n * Scope: JCEKS trusted certs + integrity parse the same way, but JCEKS private keys use PBEWithMD5AndTripleDES\n * (a different, heavier scheme) — reported as unsupported rather than decrypted. A JCEKS *secret-key* entry is a\n * Java-serialized object with no length prefix we can skip, so hitting one stops the entry walk (already-parsed\n * entries are kept, with a note). PKCS#12 keystores (`.p12`/`.pfx`) are a different format entirely — handled by\n * the certificate viewer, not here.\n */\n\nimport { decodeAsn1, oidToString } from './asn1'\nimport { describePrivateKey } from './x509'\nimport { Sha1 } from './sha1'\n\nexport const JKS_MAGIC = 0xfeedfeed\nexport const JCEKS_MAGIC = 0xcececece\n\n// Sun's proprietary \"key protector\" (JKS private-key encryption). JCEKS keys instead use the PBE OID below.\nconst KEY_PROTECTOR_OID = '1.3.6.1.4.1.42.2.17.1.1'\nconst JCEKS_PBE_OID = '1.3.6.1.4.1.42.2.19.1' // PBEWithMD5AndTripleDES\n\n// The fixed salt string mixed into the store-integrity MAC (sun.security.provider.JavaKeyStore).\nconst MAC_SALT = /* @__PURE__ */ new TextEncoder().encode('Mighty Aphrodite')\n\nconst SALT_LEN = 20\nconst DIGEST_LEN = 20\n\nexport type JksStoreType = 'jks' | 'jceks'\nexport type JksEntryType = 'privateKey' | 'trustedCert' | 'secretKey'\n\nexport interface JksCertRef {\n /** Certificate type as stored (almost always `X.509`). */\n type: string\n der: Uint8Array\n}\n\nexport interface JksEntry {\n type: JksEntryType\n alias: string\n /** Creation time (epoch ms); 0 when unknown. */\n createdMs: number\n /** Trusted-cert: one cert. Private-key: the (possibly empty) chain. Secret-key: none. */\n certs: JksCertRef[]\n /** Private-key entries only: the DER EncryptedPrivateKeyInfo (decrypt with {@link decryptPrivateKey}). */\n encryptedKey?: Uint8Array\n}\n\nexport interface JksStore {\n storeType: JksStoreType\n version: number\n entries: JksEntry[]\n /** Bytes covered by the integrity MAC — everything except the trailing 20-byte digest. */\n macData: Uint8Array\n /** The trailing 20-byte stored SHA-1 digest (or empty if the file is too short to hold one). */\n storedDigest: Uint8Array\n /** Set when the entry walk stopped early (e.g. an unskippable JCEKS secret-key entry). */\n truncatedNote?: string\n}\n\nexport class JksError extends Error {}\n\n/** Java DataInput.readUTF uses \"modified UTF-8\": NUL as C0 80, supplementary chars as CESU-8 surrogate pairs. */\nfunction readModifiedUtf8(bytes: Uint8Array, start: number, len: number): string {\n let out = ''\n let i = start\n const end = start + len\n while (i < end) {\n const a = bytes[i]\n if (a < 0x80 && a !== 0) {\n out += String.fromCharCode(a)\n i += 1\n } else if ((a & 0xe0) === 0xc0) {\n const b = bytes[i + 1] ?? 0\n out += String.fromCharCode(((a & 0x1f) << 6) | (b & 0x3f))\n i += 2\n } else if ((a & 0xf0) === 0xe0) {\n const b = bytes[i + 1] ?? 0\n const c = bytes[i + 2] ?? 0\n out += String.fromCharCode(((a & 0x0f) << 12) | ((b & 0x3f) << 6) | (c & 0x3f))\n i += 3\n } else {\n // Malformed lead byte — emit it raw and advance so we never spin.\n out += String.fromCharCode(a)\n i += 1\n }\n }\n return out\n}\n\n/** Password → UTF-16BE bytes, the form Sun feeds to both the store MAC and the KeyProtector. */\nfunction passwordToUtf16(password: string): Uint8Array {\n const out = new Uint8Array(password.length * 2)\n for (let i = 0; i < password.length; i++) {\n const c = password.charCodeAt(i)\n out[2 * i] = (c >>> 8) & 0xff\n out[2 * i + 1] = c & 0xff\n }\n return out\n}\n\nfunction bytesEqual(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false\n return true\n}\n\n/**\n * Parse a JKS/JCEKS keystore from its raw bytes. Certificates and the entry inventory come out regardless of\n * any password (they're stored in the clear); use {@link verifyStorePassword} / {@link decryptPrivateKey} for\n * the password-gated parts. Throws {@link JksError} for a bad magic / version / truncated stream.\n */\nexport function readJks(buf: ArrayBuffer): JksStore {\n const bytes = new Uint8Array(buf)\n if (bytes.length < 8) throw new JksError('文件过小,不是有效的 keystore')\n const dv = new DataView(buf)\n let p = 0\n\n const magic = dv.getUint32(p)\n p += 4\n let storeType: JksStoreType\n if (magic === JKS_MAGIC) storeType = 'jks'\n else if (magic === JCEKS_MAGIC) storeType = 'jceks'\n else {\n throw new JksError(\n `文件头不匹配(magic=0x${magic.toString(16).padStart(8, '0')})—— 不是 JKS/JCEKS keystore` +\n '(PKCS#12 的 .p12/.pfx 请用证书查看器打开)',\n )\n }\n\n const version = dv.getUint32(p)\n p += 4\n if (version !== 1 && version !== 2) throw new JksError(`不支持的 keystore 版本 ${version}`)\n\n const count = dv.getUint32(p)\n p += 4\n if (count > 1_000_000) throw new JksError(`条目数异常(${count})`)\n\n const readUtf = (): string => {\n if (p + 2 > bytes.length) throw new JksError('数据被截断')\n const len = dv.getUint16(p)\n p += 2\n if (p + len > bytes.length) throw new JksError('数据被截断')\n const s = readModifiedUtf8(bytes, p, len)\n p += len\n return s\n }\n const readInt = (): number => {\n if (p + 4 > bytes.length) throw new JksError('数据被截断')\n const v = dv.getUint32(p)\n p += 4\n return v\n }\n const readLong = (): number => {\n if (p + 8 > bytes.length) throw new JksError('数据被截断')\n const v = Number(dv.getBigUint64(p))\n p += 8\n return v\n }\n // Copy out a slice so the returned bytes don't retain a view into the whole file buffer.\n const readBytes = (n: number): Uint8Array => {\n if (n < 0 || p + n > bytes.length) throw new JksError('数据被截断')\n const out = bytes.slice(p, p + n)\n p += n\n return out\n }\n\n const entries: JksEntry[] = []\n let truncatedNote: string | undefined\n\n for (let i = 0; i < count; i++) {\n const tag = readInt()\n if (tag === 1) {\n // Private-key entry: alias, date, EncryptedPrivateKeyInfo, then the certificate chain.\n const alias = readUtf()\n const createdMs = readLong()\n const keyLen = readInt()\n const encryptedKey = readBytes(keyLen)\n const chainLen = readInt()\n const certs: JksCertRef[] = []\n for (let j = 0; j < chainLen; j++) {\n const type = version === 2 ? readUtf() : 'X.509'\n const certLen = readInt()\n certs.push({ type, der: readBytes(certLen) })\n }\n entries.push({ type: 'privateKey', alias, createdMs, certs, encryptedKey })\n } else if (tag === 2) {\n // Trusted-certificate entry: alias, date, one certificate.\n const alias = readUtf()\n const createdMs = readLong()\n const type = version === 2 ? readUtf() : 'X.509'\n const certLen = readInt()\n const der = readBytes(certLen)\n entries.push({ type: 'trustedCert', alias, createdMs, certs: [{ type, der }] })\n } else if (tag === 3 && storeType === 'jceks') {\n // JCEKS secret-key entry: a Java-serialized SealedObject with no length prefix we can skip past — so we\n // record it and stop (the integrity MAC below is offset-independent, so it still works on the whole file).\n const alias = readUtf()\n entries.push({ type: 'secretKey', alias, createdMs: 0, certs: [] })\n truncatedNote =\n `含 JCEKS 密钥条目「${alias}」(Java 序列化对象,无法在浏览器内跳过其字节),` +\n '其后的条目未继续解析。'\n break\n } else {\n throw new JksError(`未知条目类型 tag=${tag}(第 ${i + 1} 项,偏移 ${p - 4})`)\n }\n }\n\n const n = bytes.length\n const hasDigest = n >= 20\n return {\n storeType,\n version,\n entries,\n macData: hasDigest ? bytes.slice(0, n - 20) : bytes.slice(),\n storedDigest: hasDigest ? bytes.slice(n - 20) : new Uint8Array(0),\n truncatedNote,\n }\n}\n\n/**\n * Verify the store-integrity MAC with a candidate password: SHA1(passwordUtf16BE ‖ \"Mighty Aphrodite\" ‖ body)\n * must equal the stored trailing digest. Also confirms the store password (keytool defaults it equal to each\n * key password). Returns false for an empty password or a store with no digest.\n */\nexport function verifyStorePassword(store: JksStore, password: string): boolean {\n if (!password || store.storedDigest.length !== DIGEST_LEN) return false\n const md = new Sha1()\n md.update(passwordToUtf16(password))\n md.update(MAC_SALT)\n md.update(store.macData)\n return bytesEqual(md.digest(), store.storedDigest)\n}\n\n/** Friendly description of a decrypted PKCS#8 private key. */\nexport interface KeyInfo {\n /** DER PKCS#8 PrivateKeyInfo (the decrypted plaintext). */\n pkcs8: Uint8Array\n algorithm: string\n bits?: number\n curve?: string\n}\n\nexport type KeyDecryptResult =\n | { ok: true; key: KeyInfo }\n | { ok: false; reason: 'wrong-password' | 'unsupported' | 'malformed'; detail?: string }\n\n/**\n * Decrypt a JKS private key (the DER EncryptedPrivateKeyInfo from {@link JksEntry.encryptedKey}) with Sun's\n * KeyProtector. The password is verified by the format's own trailing SHA-1 check digest, so a wrong password\n * yields `wrong-password` (never garbage). Non-JKS protection (e.g. JCEKS PBEWithMD5AndTripleDES) → `unsupported`.\n */\nexport function decryptPrivateKey(encryptedKey: Uint8Array, password: string): KeyDecryptResult {\n let algOid = ''\n let encrypted: Uint8Array | null = null\n try {\n // EncryptedPrivateKeyInfo ::= SEQUENCE { encryptionAlgorithm AlgorithmIdentifier, encryptedData OCTET STRING }\n const top = decodeAsn1(encryptedKey)[0]\n const algId = top?.children[0]\n const oidNode = algId?.children[0]\n algOid = oidNode ? oidToString(oidNode.content) : ''\n const octet = top?.children[1]\n if (octet) encrypted = octet.content\n } catch {\n return { ok: false, reason: 'malformed' }\n }\n if (!encrypted) return { ok: false, reason: 'malformed' }\n if (algOid !== KEY_PROTECTOR_OID) {\n return {\n ok: false,\n reason: 'unsupported',\n detail: algOid === JCEKS_PBE_OID ? 'PBEWithMD5AndTripleDES (JCEKS)' : algOid || '未知算法',\n }\n }\n if (encrypted.length < SALT_LEN + DIGEST_LEN) return { ok: false, reason: 'malformed' }\n\n const pwd = passwordToUtf16(password)\n const salt = encrypted.subarray(0, SALT_LEN)\n const encrKeyLen = encrypted.length - SALT_LEN - DIGEST_LEN\n const encrKey = encrypted.subarray(SALT_LEN, SALT_LEN + encrKeyLen)\n const check = encrypted.subarray(SALT_LEN + encrKeyLen)\n\n // Keystream: digest_0 = salt; digest_{i} = SHA1(password ‖ digest_{i-1}); concatenate 20 bytes per round.\n const xorKey = new Uint8Array(encrKeyLen)\n let digest = salt\n let off = 0\n const numRounds = Math.ceil(encrKeyLen / DIGEST_LEN)\n for (let i = 0; i < numRounds; i++) {\n const md = new Sha1()\n md.update(pwd)\n md.update(digest)\n digest = md.digest()\n xorKey.set(digest.subarray(0, Math.min(DIGEST_LEN, encrKeyLen - off)), off)\n off += DIGEST_LEN\n }\n const plain = new Uint8Array(encrKeyLen)\n for (let i = 0; i < encrKeyLen; i++) plain[i] = encrKey[i] ^ xorKey[i]\n\n // The format's integrity check IS the password check: SHA1(password ‖ plaintextKey) must match the trailer.\n const vmd = new Sha1()\n vmd.update(pwd)\n vmd.update(plain)\n if (!bytesEqual(vmd.digest(), check)) return { ok: false, reason: 'wrong-password' }\n\n return { ok: true, key: { pkcs8: plain, ...describePrivateKey(plain) } }\n}\n"],"mappings":"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"}
package/dist/lib/jsonl.js CHANGED
@@ -22,3 +22,5 @@ function e(e) {
22
22
  }
23
23
  //#endregion
24
24
  export { e as parseJsonl };
25
+
26
+ //# sourceMappingURL=jsonl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonl.js","names":[],"sources":["../../src/lib/jsonl.ts"],"sourcesContent":["/**\n * JSON Lines / NDJSON (`.jsonl` / `.ndjson`) parser — one JSON value per physical line.\n *\n * Hand-rolled (no dependency, like the other in-browser parsers): split on newlines, skip blank lines, and\n * `JSON.parse` each remaining line independently. A line that isn't valid JSON is kept as an error record\n * (with its raw text) rather than aborting the whole file — JSONL is often produced incrementally / by logs,\n * so a single malformed line shouldn't blank the preview.\n *\n * Used by JsonlViewer (the side viewer's render mode): the record LIST shows a truncated one-line preview per\n * row, and a row expands to its pretty-printed value on demand — so a huge file stays responsive (the full\n * value of a record is only built when that row is opened).\n */\n\nexport interface JsonlRecord {\n /** 1-based physical line number in the file (blank lines are skipped, so numbers may have gaps). */\n line: number\n /** The raw line text (trailing CR stripped) — shown verbatim for error rows. */\n raw: string\n /** Parsed JSON value when the line is valid JSON; undefined when {@link error} is set. */\n value?: unknown\n /** Parse error message when the line isn't valid JSON. */\n error?: string\n}\n\nexport interface JsonlDoc {\n records: JsonlRecord[]\n /** How many records failed to parse (valid + invalid = records.length). */\n errorCount: number\n}\n\n/** Parse JSONL/NDJSON text into per-line records. Blank/whitespace-only lines are skipped (not recorded). */\nexport function parseJsonl(text: string): JsonlDoc {\n const records: JsonlRecord[] = []\n let errorCount = 0\n const lines = text.split('\\n')\n for (let i = 0; i < lines.length; i++) {\n const raw = lines[i].replace(/\\r$/, '')\n if (raw.trim() === '') continue\n const rec: JsonlRecord = { line: i + 1, raw }\n try {\n rec.value = JSON.parse(raw)\n } catch (e) {\n rec.error = e instanceof Error ? e.message : String(e)\n errorCount++\n }\n records.push(rec)\n }\n return { records, errorCount }\n}\n"],"mappings":";AA+BA,SAAgB,EAAW,GAAwB;CACjD,IAAM,IAAyB,CAAC,GAC5B,IAAa,GACX,IAAQ,EAAK,MAAM,IAAI;CAC7B,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK;EACrC,IAAM,IAAM,EAAM,EAAE,CAAC,QAAQ,OAAO,EAAE;EACtC,IAAI,EAAI,KAAK,MAAM,IAAI;EACvB,IAAM,IAAmB;GAAE,MAAM,IAAI;GAAG;EAAI;EAC5C,IAAI;GACF,EAAI,QAAQ,KAAK,MAAM,CAAG;EAC5B,SAAS,GAAG;GAEV,AADA,EAAI,QAAQ,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,GACrD;EACF;EACA,EAAQ,KAAK,CAAG;CAClB;CACA,OAAO;EAAE;EAAS;CAAW;AAC/B"}
package/dist/lib/lrc.js CHANGED
@@ -82,3 +82,5 @@ function i(e) {
82
82
  }
83
83
  //#endregion
84
84
  export { i as parseLrc };
85
+
86
+ //# sourceMappingURL=lrc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lrc.js","names":[],"sources":["../../src/lib/lrc.ts"],"sourcesContent":["/**\n * LRC 歌词解析(手写、零依赖)。\n *\n * LRC 是行式歌词格式:元信息标签 `[ti:标题] [ar:歌手] [al:专辑] [by:制作] [offset:毫秒]`,加上带时间戳的\n * 正文行 `[mm:ss.xx]歌词`。一行可带多个时间戳(`[t1][t2]同一句`),表示这句在多处重复出现。\n *\n * QQ 音乐导出的 .lrc 常见两个坑,这里都处理:\n * - 文本里混入 HTML 数字实体(如 `&#52572;` 表示某个 Unicode 码点),需要解码还原;\n * - 文件多为 **GBK** 编码(解码交由 {@link decodeTextSniff} 在读盘时完成,本模块只吃已解码的字符串)。\n *\n * 仅做解析,渲染在 LrcViewer.vue。无时间戳的纯文本歌词也能正常显示(hasTimings=false)。\n */\n\nexport interface LrcLine {\n /** 该行时间戳(毫秒),已叠加全局 offset;纯文本行为 null。 */\n timeMs: number | null\n text: string\n}\n\nexport interface ParsedLrc {\n tags: Record<string, string>\n title?: string\n artist?: string\n album?: string\n by?: string\n /** `[offset:n]` 毫秒(正值表示歌词提前),已并入每行 timeMs。 */\n offsetMs: number\n /** 按时间升序的歌词行(含解析出的纯文本行,timeMs=null 排在最前、保持原序)。 */\n lines: LrcLine[]\n /** 是否解析到任何带时间戳的行。 */\n hasTimings: boolean\n}\n\nconst NAMED_ENTITIES: Record<string, string> = {\n amp: '&',\n lt: '<',\n gt: '>',\n quot: '\"',\n apos: \"'\",\n nbsp: ' ',\n}\n\n/** 解码 HTML 实体:数字 `&#1234;` / 十六进制 `&#x4a;` / 常见命名实体。 */\nfunction decodeEntities(s: string): string {\n if (!s.includes('&')) return s\n return s.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z]+);/g, (m, body: string) => {\n if (body[0] === '#') {\n const code =\n body[1] === 'x' || body[1] === 'X'\n ? parseInt(body.slice(2), 16)\n : parseInt(body.slice(1), 10)\n if (Number.isFinite(code) && code >= 0 && code <= 0x10ffff) {\n try {\n return String.fromCodePoint(code)\n } catch {\n return m\n }\n }\n return m\n }\n return NAMED_ENTITIES[body.toLowerCase()] ?? m\n })\n}\n\n// 元信息标签里这些是「非时间」键。\nconst META_KEYS = new Set(['ti', 'ar', 'al', 'by', 'offset', 'length', 're', 've', 'au', 'la'])\n\n// 时间戳:[mm:ss]、[mm:ss.xx]、[mm:ss.xxx],分隔符 . 或 :。\nconst TIME_RE = /\\[(\\d{1,3}):(\\d{1,2})(?:[.:](\\d{1,3}))?\\]/g\n\n/** 解析 LRC 文本(已是正确编码的字符串)。 */\nexport function parseLrc(text: string): ParsedLrc {\n const tags: Record<string, string> = {}\n const timed: LrcLine[] = []\n const plain: LrcLine[] = []\n let offsetMs = 0\n\n for (const rawLine of text.split(/\\r\\n|\\r|\\n/)) {\n const line = rawLine\n // 先抽出行首的所有时间戳。\n TIME_RE.lastIndex = 0\n const stamps: number[] = []\n let lastEnd = 0\n let m: RegExpExecArray | null\n while ((m = TIME_RE.exec(line)) !== null) {\n // 仅接受连续位于行首/紧挨着的时间戳串(中间不夹其它字符)。\n if (m.index !== lastEnd) break\n const mm = parseInt(m[1], 10)\n const ss = parseInt(m[2], 10)\n const frac = m[3] ? m[3] : ''\n // 毫秒:两位当百分秒(*10),三位即毫秒,一位*100。\n let ms = 0\n if (frac.length === 1) ms = parseInt(frac, 10) * 100\n else if (frac.length === 2) ms = parseInt(frac, 10) * 10\n else if (frac.length >= 3) ms = parseInt(frac.slice(0, 3), 10)\n stamps.push(mm * 60000 + ss * 1000 + ms)\n lastEnd = m.index + m[0].length\n }\n\n if (stamps.length > 0) {\n const content = decodeEntities(line.slice(lastEnd).trim())\n for (const t of stamps) timed.push({ timeMs: t, text: content })\n continue\n }\n\n // 非时间戳行:可能是元信息标签 [key:value],或纯文本。\n const tag = /^\\[([a-zA-Z]+):(.*)\\]\\s*$/.exec(line.trim())\n if (tag && META_KEYS.has(tag[1].toLowerCase())) {\n const key = tag[1].toLowerCase()\n const val = decodeEntities(tag[2].trim())\n tags[key] = val\n if (key === 'offset') {\n const n = parseInt(val, 10)\n if (Number.isFinite(n)) offsetMs = n\n }\n continue\n }\n\n const txt = decodeEntities(line.trim())\n if (txt) plain.push({ timeMs: null, text: txt })\n }\n\n // offset 语义:正值表示歌词整体提前,故从时间里减去。\n if (offsetMs !== 0) for (const l of timed) if (l.timeMs != null) l.timeMs -= offsetMs\n\n timed.sort((a, b) => (a.timeMs ?? 0) - (b.timeMs ?? 0))\n\n const lines = timed.length > 0 ? timed : plain\n return {\n tags,\n title: tags.ti,\n artist: tags.ar,\n album: tags.al,\n by: tags.by,\n offsetMs,\n lines,\n hasTimings: timed.length > 0,\n }\n}\n"],"mappings":"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"}
package/dist/lib/lzma.js CHANGED
@@ -202,3 +202,5 @@ function E(e, t = 0) {
202
202
  }
203
203
  //#endregion
204
204
  export { E as bcjX86Decode, S as lzma2Decode, x as lzmaDecode };
205
+
206
+ //# sourceMappingURL=lzma.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lzma.js","names":[],"sources":["../../src/lib/lzma.ts"],"sourcesContent":["/**\n * Minimal in-browser LZMA / LZMA2 decoder — no dependency, no WASM.\n *\n * Browsers ship a native inflate (DecompressionStream) for ZIP's DEFLATE, but nothing for LZMA — the\n * codec 7z archives use. So unlike {@link lib/zip.ts}, the 7z reader ({@link lib/sevenZip.ts}) has to\n * carry its own decompressor. This is a straight port of Igor Pavlov's reference LZMA decoder (the one\n * in the LZMA SDK / the format spec): a range decoder, the bit-tree / length / distance sub-decoders,\n * and the literal/match main loop. It decodes into a caller-provided linear output buffer (the total\n * unpacked size is always known up front from the 7z folder metadata), which doubles as the LZ window.\n *\n * Three entry points, all synchronous (pure arithmetic, no async primitive needed):\n * - {@link lzmaDecode} raw LZMA1 stream (7z coder 03 01 01), 5-byte props.\n * - {@link lzma2Decode} LZMA2 chunk stream (7z coder 21), 1-byte props.\n * - {@link bcjX86Decode} the x86 BCJ branch filter's decode pass (7z coder 03 03 01 03).\n *\n * Encrypted / unusual coders are the 7z reader's concern; here we only fail (throw) on a malformed\n * stream or an unsupported LZMA2 control byte.\n */\n\nconst K_NUM_BIT_MODEL_TOTAL_BITS = 11\nconst K_BIT_MODEL_TOTAL = 1 << K_NUM_BIT_MODEL_TOTAL_BITS // 2048\nconst K_NUM_MOVE_BITS = 5\nconst PROB_INIT = K_BIT_MODEL_TOTAL >> 1 // 1024\nconst K_TOP_VALUE = 1 << 24\n\nconst K_NUM_POS_BITS_MAX = 4\nconst K_NUM_STATES = 12\nconst K_NUM_LEN_TO_POS_STATES = 4\nconst K_NUM_ALIGN_BITS = 4\nconst K_END_POS_MODEL_INDEX = 14\nconst K_NUM_FULL_DISTANCES = 1 << (K_END_POS_MODEL_INDEX >> 1) // 128\nconst K_MATCH_MIN_LEN = 2\n\n// Length-decoder array layout (one flat Uint16Array of 514 probs, reused for the match- and rep-length\n// coders): choice(1) + choice2(1) + low[16][8] + mid[16][8] + high[256].\nconst LEN_LOW = 2\nconst LEN_MID = LEN_LOW + (1 << K_NUM_POS_BITS_MAX) * 8 // 130\nconst LEN_HIGH = LEN_MID + (1 << K_NUM_POS_BITS_MAX) * 8 // 258\nconst LEN_SIZE = LEN_HIGH + 256 // 514\n\n/** A byte-at-a-time range decoder over a slice of the packed stream (reads past the end as zero). */\nclass RangeDecoder {\n private code = 0\n private range = 0xffffffff\n private pos: number\n constructor(\n private readonly buf: Uint8Array,\n start: number,\n ) {\n this.pos = start\n this.pos++ // first byte is always 0 (ignored)\n for (let i = 0; i < 4; i++) this.code = ((this.code << 8) | this.nextByte()) >>> 0\n }\n\n private nextByte(): number {\n return this.pos < this.buf.length ? this.buf[this.pos++] : (this.pos++, 0)\n }\n\n private normalize(): void {\n if (this.range >>> 0 < K_TOP_VALUE) {\n this.range = (this.range * 256) >>> 0\n this.code = (this.code * 256 + this.nextByte()) >>> 0\n }\n }\n\n /** Decode one bit under probability model `probs[i]`, adapting the model in place. */\n decodeBit(probs: Uint16Array, i: number): number {\n const prob = probs[i]\n const bound = (this.range >>> K_NUM_BIT_MODEL_TOTAL_BITS) * prob\n let symbol: number\n if (this.code >>> 0 < bound) {\n this.range = bound\n probs[i] = prob + ((K_BIT_MODEL_TOTAL - prob) >> K_NUM_MOVE_BITS)\n symbol = 0\n } else {\n this.range = (this.range - bound) >>> 0\n this.code = (this.code - bound) >>> 0\n probs[i] = prob - (prob >> K_NUM_MOVE_BITS)\n symbol = 1\n }\n this.normalize()\n return symbol\n }\n\n /** Decode `numBits` equiprobable bits (used for high distance bits). */\n decodeDirectBits(numBits: number): number {\n let result = 0\n do {\n this.range = this.range >>> 1\n this.code = (this.code - this.range) >>> 0\n const t = 0 - (this.code >>> 31) // 0 or -1\n this.code = (this.code + (this.range & t)) >>> 0\n this.normalize()\n result = result * 2 + (t + 1)\n } while (--numBits)\n return result\n }\n}\n\nfunction bitTreeDecode(\n rc: RangeDecoder,\n probs: Uint16Array,\n base: number,\n numBits: number,\n): number {\n let m = 1\n for (let i = 0; i < numBits; i++) m = (m << 1) + rc.decodeBit(probs, base + m)\n return m - (1 << numBits)\n}\n\nfunction bitTreeReverseDecode(\n rc: RangeDecoder,\n probs: Uint16Array,\n base: number,\n numBits: number,\n): number {\n let m = 1\n let sym = 0\n for (let i = 0; i < numBits; i++) {\n const bit = rc.decodeBit(probs, base + m)\n m = (m << 1) + bit\n sym |= bit << i\n }\n return sym\n}\n\nfunction decodeLen(rc: RangeDecoder, len: Uint16Array, posState: number): number {\n if (rc.decodeBit(len, 0) === 0) return bitTreeDecode(rc, len, LEN_LOW + posState * 8, 3)\n if (rc.decodeBit(len, 1) === 0) return 8 + bitTreeDecode(rc, len, LEN_MID + posState * 8, 3)\n return 16 + bitTreeDecode(rc, len, LEN_HIGH, 8)\n}\n\n/**\n * The LZMA decoder state. Holds the adaptive probability models, the `state` machine value and the four\n * recent match distances — all of which LZMA2 keeps alive (and selectively resets) across chunks, so this\n * is a reusable object rather than a one-shot function.\n */\nexport class LzmaState {\n lc = 0\n lp = 0\n pb = 0\n private literal = new Uint16Array(0)\n private readonly isMatch = new Uint16Array(K_NUM_STATES << K_NUM_POS_BITS_MAX)\n private readonly isRep = new Uint16Array(K_NUM_STATES)\n private readonly isRepG0 = new Uint16Array(K_NUM_STATES)\n private readonly isRepG1 = new Uint16Array(K_NUM_STATES)\n private readonly isRepG2 = new Uint16Array(K_NUM_STATES)\n private readonly isRep0Long = new Uint16Array(K_NUM_STATES << K_NUM_POS_BITS_MAX)\n private readonly posSlot = new Uint16Array(K_NUM_LEN_TO_POS_STATES << 6)\n private readonly specPos = new Uint16Array(K_NUM_FULL_DISTANCES - K_END_POS_MODEL_INDEX)\n private readonly align = new Uint16Array(1 << K_NUM_ALIGN_BITS)\n private readonly lenCoder = new Uint16Array(LEN_SIZE)\n private readonly repLenCoder = new Uint16Array(LEN_SIZE)\n\n state = 0\n rep0 = 0\n rep1 = 0\n rep2 = 0\n rep3 = 0\n\n /** Apply the lc/lp/pb properties byte (0..224) and size the literal table accordingly. */\n setProps(d: number): void {\n if (d >= 9 * 5 * 5) throw new Error('LZMA 属性非法')\n this.lc = d % 9\n d = (d / 9) | 0\n this.lp = d % 5\n this.pb = (d / 5) | 0\n const litSize = 0x300 << (this.lc + this.lp)\n if (this.literal.length !== litSize) this.literal = new Uint16Array(litSize)\n }\n\n /** Reset all probability models and the state machine (a \"reset state\" in LZMA2 terms). */\n resetState(): void {\n this.literal.fill(PROB_INIT)\n this.isMatch.fill(PROB_INIT)\n this.isRep.fill(PROB_INIT)\n this.isRepG0.fill(PROB_INIT)\n this.isRepG1.fill(PROB_INIT)\n this.isRepG2.fill(PROB_INIT)\n this.isRep0Long.fill(PROB_INIT)\n this.posSlot.fill(PROB_INIT)\n this.specPos.fill(PROB_INIT)\n this.align.fill(PROB_INIT)\n this.lenCoder.fill(PROB_INIT)\n this.repLenCoder.fill(PROB_INIT)\n this.state = 0\n this.rep0 = this.rep1 = this.rep2 = this.rep3 = 0\n }\n\n /**\n * Decode bytes into `out[outPos .. limit)` using `input` as the range-coded source. `dictStart` is the\n * output offset of the current dictionary's start (for LZMA1 it's `outPos`; for LZMA2 it moves on a dict\n * reset) — it anchors the position counter that drives posState and bounds back-references. Returns the\n * new output position (== limit on success).\n */\n decode(\n input: Uint8Array,\n inStart: number,\n out: Uint8Array,\n outPos: number,\n limit: number,\n dictStart: number,\n ): number {\n const rc = new RangeDecoder(input, inStart)\n const posMask = (1 << this.pb) - 1\n const litPosMask = (1 << this.lp) - 1\n const lc = this.lc\n let { state, rep0, rep1, rep2, rep3 } = this\n\n while (outPos < limit) {\n const processedPos = outPos - dictStart\n const posState = processedPos & posMask\n if (rc.decodeBit(this.isMatch, (state << K_NUM_POS_BITS_MAX) + posState) === 0) {\n // ── literal ──\n const prevByte = outPos > dictStart ? out[outPos - 1] : 0\n const litState = ((processedPos & litPosMask) << lc) + (prevByte >> (8 - lc))\n const probBase = 0x300 * litState\n let symbol = 1\n if (state >= 7) {\n let matchByte = out[outPos - rep0 - 1]\n do {\n const matchBit = (matchByte >> 7) & 1\n matchByte = (matchByte << 1) & 0xff\n const bit = rc.decodeBit(this.literal, probBase + ((1 + matchBit) << 8) + symbol)\n symbol = (symbol << 1) | bit\n if (matchBit !== bit) break\n } while (symbol < 0x100)\n }\n while (symbol < 0x100)\n symbol = (symbol << 1) | rc.decodeBit(this.literal, probBase + symbol)\n out[outPos++] = symbol & 0xff\n state = state < 4 ? 0 : state < 10 ? state - 3 : state - 6\n continue\n }\n\n // ── match ──\n let len: number\n if (rc.decodeBit(this.isRep, state) !== 0) {\n // rep match\n if (rc.decodeBit(this.isRepG0, state) === 0) {\n if (rc.decodeBit(this.isRep0Long, (state << K_NUM_POS_BITS_MAX) + posState) === 0) {\n // short rep: copy one byte at distance rep0\n state = state < 7 ? 9 : 11\n out[outPos] = out[outPos - rep0 - 1]\n outPos++\n continue\n }\n } else {\n let dist: number\n if (rc.decodeBit(this.isRepG1, state) === 0) {\n dist = rep1\n } else {\n if (rc.decodeBit(this.isRepG2, state) === 0) {\n dist = rep2\n } else {\n dist = rep3\n rep3 = rep2\n }\n rep2 = rep1\n }\n rep1 = rep0\n rep0 = dist\n }\n len = decodeLen(rc, this.repLenCoder, posState)\n state = state < 7 ? 8 : 11\n } else {\n // new match: shift the recent-distance history and decode a fresh distance\n rep3 = rep2\n rep2 = rep1\n rep1 = rep0\n len = decodeLen(rc, this.lenCoder, posState)\n state = state < 7 ? 7 : 10\n const lenToPosState = len < K_NUM_LEN_TO_POS_STATES ? len : K_NUM_LEN_TO_POS_STATES - 1\n const posSlot = bitTreeDecode(rc, this.posSlot, lenToPosState << 6, 6)\n if (posSlot < 4) {\n rep0 = posSlot\n } else {\n const numDirectBits = (posSlot >> 1) - 1\n rep0 = (2 | (posSlot & 1)) << numDirectBits\n if (posSlot < K_END_POS_MODEL_INDEX) {\n rep0 += bitTreeReverseDecode(rc, this.specPos, rep0 - posSlot - 1, numDirectBits)\n } else {\n rep0 += rc.decodeDirectBits(numDirectBits - K_NUM_ALIGN_BITS) * (1 << K_NUM_ALIGN_BITS)\n rep0 += bitTreeReverseDecode(rc, this.align, 0, K_NUM_ALIGN_BITS)\n if (rep0 >>> 0 === 0xffffffff) break // end-of-stream marker\n }\n }\n }\n\n // copy `len + K_MATCH_MIN_LEN` bytes from distance rep0\n len += K_MATCH_MIN_LEN\n let src = outPos - rep0 - 1\n for (let i = 0; i < len && outPos < limit; i++) out[outPos++] = out[src++]\n }\n\n this.state = state\n this.rep0 = rep0\n this.rep1 = rep1\n this.rep2 = rep2\n this.rep3 = rep3\n return outPos\n }\n}\n\n/**\n * Decode a raw LZMA1 stream (7z coder 03 01 01). `props` is the 5-byte property block (lc/lp/pb byte +\n * little-endian dict size, which we ignore — the linear output buffer is the window). Decodes exactly\n * `outSize` bytes.\n */\nexport function lzmaDecode(input: Uint8Array, props: Uint8Array, outSize: number): Uint8Array {\n if (props.length < 5) throw new Error('LZMA 属性长度不足')\n const st = new LzmaState()\n st.setProps(props[0])\n st.resetState()\n const out = new Uint8Array(outSize)\n st.decode(input, 0, out, 0, outSize, 0)\n return out\n}\n\n/**\n * Decode an LZMA2 stream (7z coder 21). LZMA2 frames a sequence of chunks — each either an uncompressed\n * block or an independently range-coded LZMA block — over a shared, selectively-reset dictionary and\n * decoder state. `props` (1 byte, dict-size code) is unused here. Decodes exactly `outSize` bytes.\n */\nexport function lzma2Decode(input: Uint8Array, _props: Uint8Array, outSize: number): Uint8Array {\n const out = new Uint8Array(outSize)\n const st = new LzmaState()\n let ip = 0\n let pos = 0\n let dictStart = 0\n let needProps = true\n\n while (ip < input.length) {\n const control = input[ip++]\n if (control === 0) break // end of LZMA2 stream\n\n if (control >= 0x80) {\n // LZMA chunk\n const unpackSize = ((control & 0x1f) << 16) + (input[ip] << 8) + input[ip + 1] + 1\n ip += 2\n const packSize = (input[ip] << 8) + input[ip + 1] + 1\n ip += 2\n const reset = (control >> 5) & 3 // 0 none · 1 state · 2 state+props · 3 state+props+dict\n if (reset >= 2) {\n st.setProps(input[ip++])\n needProps = false\n } else if (needProps) {\n throw new Error('LZMA2 缺少属性的块')\n }\n // reset ≥ 1 resets the adaptive state; reset 0 deliberately CONTINUES it from the previous chunk —\n // valid LZMA2, e.g. an LZMA chunk right after an uncompressed chunk that kept the dictionary. Don't\n // force a reset here: 7-Zip / xz only require a state reset after a *dictionary* reset (which is\n // gated below by needProps, since a dict reset re-sends props via a reset-2/3 chunk).\n if (reset >= 1) st.resetState()\n if (reset === 3) dictStart = pos\n st.decode(input, ip, out, pos, pos + unpackSize, dictStart)\n ip += packSize\n pos += unpackSize\n } else {\n // uncompressed chunk: 1 = reset dict, 2 = keep dict\n if (control > 2) throw new Error(`LZMA2 非法控制字节 0x${control.toString(16)}`)\n const size = (input[ip] << 8) + input[ip + 1] + 1\n ip += 2\n if (control === 1) {\n dictStart = pos\n needProps = true // a dict reset starts fresh → the next LZMA chunk must re-send props (reset 2/3)\n }\n out.set(input.subarray(ip, ip + size), pos)\n ip += size\n pos += size\n }\n if (pos >= outSize) break\n }\n return out\n}\n\n// The x86 BCJ filter rewrites the operands of E8/E9 (CALL/JMP rel32) instructions from absolute back to\n// relative form. Decode tables and algorithm follow the reference (xz / 7-Zip `x86_code`, encoding=false).\nconst MASK_TO_ALLOWED: ReadonlyArray<boolean> = [true, true, true, false, true, false, false, false]\nconst MASK_TO_BIT: ReadonlyArray<number> = [0, 1, 2, 2, 3, 3, 3, 3]\nconst test86 = (b: number): boolean => b === 0x00 || b === 0xff\n\n/** Apply the x86 BCJ decode pass in place (7z coder 03 03 01 03), with `ip` the stream start address (0). */\nexport function bcjX86Decode(data: Uint8Array, ip = 0): void {\n const size = data.length\n if (size < 5) return\n const limit = size - 5\n let prevMask = 0\n let prevPos = -1\n let i = 0\n while (i <= limit) {\n if ((data[i] & 0xfe) !== 0xe8) {\n i++\n continue\n }\n const off = i - prevPos\n prevPos = i\n if (off > 3) {\n prevMask = 0\n } else {\n prevMask = (prevMask << (off - 1)) & 7\n if (prevMask !== 0) {\n const b = data[i + 4 - MASK_TO_BIT[prevMask]]\n if (!MASK_TO_ALLOWED[prevMask] || test86(b)) {\n prevMask = ((prevMask << 1) & 7) | 1\n i++\n continue\n }\n }\n }\n if (test86(data[i + 4])) {\n let src = (data[i + 1] | (data[i + 2] << 8) | (data[i + 3] << 16) | (data[i + 4] << 24)) >>> 0\n let dest = 0\n for (;;) {\n dest = (src - (ip + i + 5)) >>> 0\n if (prevMask === 0) break\n const idx = MASK_TO_BIT[prevMask] * 8\n const b = (dest >>> (24 - idx)) & 0xff\n if (!test86(b)) break\n src = (dest ^ ((1 << (32 - idx)) - 1)) >>> 0\n }\n data[i + 4] = ~(((dest >>> 24) & 1) - 1) & 0xff\n data[i + 3] = (dest >>> 16) & 0xff\n data[i + 2] = (dest >>> 8) & 0xff\n data[i + 1] = dest & 0xff\n i += 5\n prevMask = 0\n } else {\n prevMask = ((prevMask << 1) & 7) | 1\n i++\n }\n }\n}\n"],"mappings":"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"}
@@ -219,3 +219,5 @@ function h(e, t) {
219
219
  }
220
220
  //#endregion
221
221
  export { h as md, m as mdNodes };
222
+
223
+ //# sourceMappingURL=blocks.js.map