omni-viewer-core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (387) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +80 -0
  3. package/THIRD_PARTY_NOTICES.md +49 -0
  4. package/dist/assets/audio-engine/audio_engine.mjs +2 -0
  5. package/dist/assets/audio-engine/audio_engine.wasm +0 -0
  6. package/dist/assets/pdfjs/pdf.worker.min.mjs +21 -0
  7. package/dist/host/index.d.ts +133 -0
  8. package/dist/host/index.js +10 -0
  9. package/dist/i18n/catalog.en.d.ts +1 -0
  10. package/dist/i18n/catalog.en.js +411 -0
  11. package/dist/i18n/catalog.ko.d.ts +1 -0
  12. package/dist/i18n/catalog.ko.js +68 -0
  13. package/dist/i18n/index.d.ts +18 -0
  14. package/dist/i18n/index.js +41 -0
  15. package/dist/licenses/emscripten.txt +101 -0
  16. package/dist/licenses/kissfft.txt +28 -0
  17. package/dist/licenses/pdfjs-dist.txt +177 -0
  18. package/dist/parsers/a2l/index.d.ts +1 -0
  19. package/dist/parsers/a2l/index.js +1 -0
  20. package/dist/parsers/archive/index.d.ts +22 -0
  21. package/dist/parsers/archive/index.js +46 -0
  22. package/dist/parsers/archive/model.d.ts +29 -0
  23. package/dist/parsers/archive/model.js +1 -0
  24. package/dist/parsers/archive/worker.d.ts +21 -0
  25. package/dist/parsers/archive/worker.js +1 -0
  26. package/dist/parsers/arxml/index.d.ts +1 -0
  27. package/dist/parsers/arxml/index.js +1 -0
  28. package/dist/parsers/asc/index.d.ts +1 -0
  29. package/dist/parsers/asc/index.js +1 -0
  30. package/dist/parsers/audio/index.d.ts +9 -0
  31. package/dist/parsers/audio/index.js +46 -0
  32. package/dist/parsers/automotive/index.d.ts +33 -0
  33. package/dist/parsers/automotive/index.js +973 -0
  34. package/dist/parsers/blf/index.d.ts +1 -0
  35. package/dist/parsers/blf/index.js +1 -0
  36. package/dist/parsers/csv/delimiter.d.ts +31 -0
  37. package/dist/parsers/csv/delimiter.js +151 -0
  38. package/dist/parsers/csv/index.d.ts +30 -0
  39. package/dist/parsers/csv/index.js +108 -0
  40. package/dist/parsers/csv/parseText.d.ts +20 -0
  41. package/dist/parsers/csv/parseText.js +108 -0
  42. package/dist/parsers/csv/sort.d.ts +26 -0
  43. package/dist/parsers/csv/sort.js +224 -0
  44. package/dist/parsers/csv/statistics.d.ts +49 -0
  45. package/dist/parsers/csv/statistics.js +150 -0
  46. package/dist/parsers/dbc/index.d.ts +56 -0
  47. package/dist/parsers/dbc/index.js +94 -0
  48. package/dist/parsers/doc-binary/index.d.ts +35 -0
  49. package/dist/parsers/doc-binary/index.js +267 -0
  50. package/dist/parsers/doc-binary/vscode-parser.d.ts +142 -0
  51. package/dist/parsers/doc-binary/vscode-parser.js +3747 -0
  52. package/dist/parsers/excel/index.d.ts +17 -0
  53. package/dist/parsers/excel/index.js +406 -0
  54. package/dist/parsers/excel/model.d.ts +80 -0
  55. package/dist/parsers/excel/model.js +48 -0
  56. package/dist/parsers/excel/serialize.d.ts +3 -0
  57. package/dist/parsers/excel/serialize.js +78 -0
  58. package/dist/parsers/hdf5/index.d.ts +75 -0
  59. package/dist/parsers/hdf5/index.js +658 -0
  60. package/dist/parsers/hdf5/node.d.ts +21 -0
  61. package/dist/parsers/hdf5/node.js +95 -0
  62. package/dist/parsers/json/index.d.ts +15 -0
  63. package/dist/parsers/json/index.js +102 -0
  64. package/dist/parsers/json/model.d.ts +42 -0
  65. package/dist/parsers/json/model.js +140 -0
  66. package/dist/parsers/json/parse.d.ts +22 -0
  67. package/dist/parsers/json/parse.js +279 -0
  68. package/dist/parsers/json/tokenizer.d.ts +17 -0
  69. package/dist/parsers/json/tokenizer.js +175 -0
  70. package/dist/parsers/jsonl/index.d.ts +14 -0
  71. package/dist/parsers/jsonl/index.js +18 -0
  72. package/dist/parsers/jsonl/model.d.ts +23 -0
  73. package/dist/parsers/jsonl/model.js +1 -0
  74. package/dist/parsers/jsonl/parse.d.ts +7 -0
  75. package/dist/parsers/jsonl/parse.js +34 -0
  76. package/dist/parsers/markdown/index.d.ts +37 -0
  77. package/dist/parsers/markdown/index.js +59 -0
  78. package/dist/parsers/mat/index.d.ts +31 -0
  79. package/dist/parsers/mat/index.js +426 -0
  80. package/dist/parsers/mermaid/index.d.ts +5 -0
  81. package/dist/parsers/mermaid/index.js +3 -0
  82. package/dist/parsers/mf4/index.d.ts +1 -0
  83. package/dist/parsers/mf4/index.js +1 -0
  84. package/dist/parsers/parquet/index.d.ts +21 -0
  85. package/dist/parsers/parquet/index.js +68 -0
  86. package/dist/parsers/pcap/index.d.ts +1 -0
  87. package/dist/parsers/pcap/index.js +1 -0
  88. package/dist/parsers/pcapng/index.d.ts +1 -0
  89. package/dist/parsers/pcapng/index.js +1 -0
  90. package/dist/parsers/plantuml/index.d.ts +5 -0
  91. package/dist/parsers/plantuml/index.js +4 -0
  92. package/dist/parsers/ppt-binary/index.d.ts +5 -0
  93. package/dist/parsers/ppt-binary/index.js +62 -0
  94. package/dist/parsers/ppt-binary/pptBinaryBuildContext.d.ts +12 -0
  95. package/dist/parsers/ppt-binary/pptBinaryBuildContext.js +40 -0
  96. package/dist/parsers/ppt-binary/pptBinaryContainer.d.ts +4 -0
  97. package/dist/parsers/ppt-binary/pptBinaryContainer.js +174 -0
  98. package/dist/parsers/ppt-binary/pptBinaryTypes.d.ts +125 -0
  99. package/dist/parsers/ppt-binary/pptBinaryTypes.js +1 -0
  100. package/dist/parsers/ppt-binary/pptSlideLayouts.d.ts +9 -0
  101. package/dist/parsers/ppt-binary/pptSlideLayouts.js +510 -0
  102. package/dist/parsers/ppt-binary/vscode-parser.d.ts +116 -0
  103. package/dist/parsers/ppt-binary/vscode-parser.js +2853 -0
  104. package/dist/parsers/ppt-binary/vscode.d.ts +4 -0
  105. package/dist/parsers/ppt-binary/vscode.js +12 -0
  106. package/dist/parsers/pptx/index.d.ts +15 -0
  107. package/dist/parsers/pptx/index.js +88 -0
  108. package/dist/parsers/pptx/vscode-parser.d.ts +167 -0
  109. package/dist/parsers/pptx/vscode-parser.js +1503 -0
  110. package/dist/parsers/pptx/vscode.d.ts +4 -0
  111. package/dist/parsers/pptx/vscode.js +18 -0
  112. package/dist/parsers/pptx/zip-reader.d.ts +3 -0
  113. package/dist/parsers/pptx/zip-reader.js +20 -0
  114. package/dist/parsers/proto/index.d.ts +90 -0
  115. package/dist/parsers/proto/index.js +197 -0
  116. package/dist/parsers/psd/index.d.ts +16 -0
  117. package/dist/parsers/psd/index.js +10 -0
  118. package/dist/parsers/shapefile/dbf.d.ts +23 -0
  119. package/dist/parsers/shapefile/dbf.js +112 -0
  120. package/dist/parsers/shapefile/index.d.ts +44 -0
  121. package/dist/parsers/shapefile/index.js +119 -0
  122. package/dist/parsers/shapefile/reproject.d.ts +10 -0
  123. package/dist/parsers/shapefile/reproject.js +41 -0
  124. package/dist/parsers/slide-model.d.ts +106 -0
  125. package/dist/parsers/slide-model.js +1 -0
  126. package/dist/parsers/toml/index.d.ts +15 -0
  127. package/dist/parsers/toml/index.js +18 -0
  128. package/dist/parsers/toml/model.d.ts +15 -0
  129. package/dist/parsers/toml/model.js +1 -0
  130. package/dist/parsers/toml/parse.d.ts +16 -0
  131. package/dist/parsers/toml/parse.js +266 -0
  132. package/dist/parsers/types.d.ts +103 -0
  133. package/dist/parsers/types.js +106 -0
  134. package/dist/parsers/video/index.d.ts +6 -0
  135. package/dist/parsers/video/index.js +2 -0
  136. package/dist/parsers/yaml/index.d.ts +16 -0
  137. package/dist/parsers/yaml/index.js +58 -0
  138. package/dist/parsers/yaml/model.d.ts +22 -0
  139. package/dist/parsers/yaml/model.js +1 -0
  140. package/dist/parsers/yaml/self-loading.d.ts +3 -0
  141. package/dist/parsers/yaml/self-loading.js +19 -0
  142. package/dist/parsers/zip-scan.d.ts +8 -0
  143. package/dist/parsers/zip-scan.js +80 -0
  144. package/dist/registry/container.d.ts +17 -0
  145. package/dist/registry/container.js +49 -0
  146. package/dist/registry/index.d.ts +133 -0
  147. package/dist/registry/index.js +348 -0
  148. package/dist/registry/probe.d.ts +3 -0
  149. package/dist/registry/probe.js +177 -0
  150. package/dist/registry/sniff.d.ts +17 -0
  151. package/dist/registry/sniff.js +57 -0
  152. package/dist/styles/archive.css +10 -0
  153. package/dist/styles/audio.css +66 -0
  154. package/dist/styles/automotive.css +1 -0
  155. package/dist/styles/csv.css +262 -0
  156. package/dist/styles/excel.css +212 -0
  157. package/dist/styles/fallback.css +48 -0
  158. package/dist/styles/hdf5.css +3 -0
  159. package/dist/styles/hwp.css +12 -0
  160. package/dist/styles/image.css +115 -0
  161. package/dist/styles/json.css +342 -0
  162. package/dist/styles/jsonl.css +1 -0
  163. package/dist/styles/markdown.css +10 -0
  164. package/dist/styles/mat.css +2 -0
  165. package/dist/styles/mermaid.css +1 -0
  166. package/dist/styles/parquet.css +2 -0
  167. package/dist/styles/pdf.css +551 -0
  168. package/dist/styles/plantuml.css +1 -0
  169. package/dist/styles/ppt.css +1 -0
  170. package/dist/styles/proto.css +2 -0
  171. package/dist/styles/psd.css +1 -0
  172. package/dist/styles/shapefile.css +25 -0
  173. package/dist/styles/toml.css +1 -0
  174. package/dist/styles/video.css +74 -0
  175. package/dist/styles/word.css +685 -0
  176. package/dist/styles/yaml.css +1 -0
  177. package/dist/viewers/a2l/index.d.ts +15 -0
  178. package/dist/viewers/a2l/index.js +5 -0
  179. package/dist/viewers/archive/archive-preview-decoder.d.ts +4 -0
  180. package/dist/viewers/archive/archive-preview-decoder.js +223 -0
  181. package/dist/viewers/archive/controller.d.ts +24 -0
  182. package/dist/viewers/archive/controller.js +18 -0
  183. package/dist/viewers/archive/index.d.ts +25 -0
  184. package/dist/viewers/archive/index.js +230 -0
  185. package/dist/viewers/archive/preview.d.ts +2 -0
  186. package/dist/viewers/archive/preview.js +2 -0
  187. package/dist/viewers/archive/styles.d.ts +1 -0
  188. package/dist/viewers/archive/styles.js +11 -0
  189. package/dist/viewers/arxml/index.d.ts +15 -0
  190. package/dist/viewers/arxml/index.js +5 -0
  191. package/dist/viewers/asc/index.d.ts +15 -0
  192. package/dist/viewers/asc/index.js +5 -0
  193. package/dist/viewers/audio/controller.d.ts +33 -0
  194. package/dist/viewers/audio/controller.js +49 -0
  195. package/dist/viewers/audio/engine.d.ts +44 -0
  196. package/dist/viewers/audio/engine.js +108 -0
  197. package/dist/viewers/audio/index.d.ts +92 -0
  198. package/dist/viewers/audio/index.js +448 -0
  199. package/dist/viewers/audio/self-loading.d.ts +7 -0
  200. package/dist/viewers/audio/self-loading.js +42 -0
  201. package/dist/viewers/audio/styles.d.ts +1 -0
  202. package/dist/viewers/audio/styles.js +73 -0
  203. package/dist/viewers/automotive/index.d.ts +8 -0
  204. package/dist/viewers/automotive/index.js +152 -0
  205. package/dist/viewers/automotive/styles.d.ts +1 -0
  206. package/dist/viewers/automotive/styles.js +1 -0
  207. package/dist/viewers/avro/index.d.ts +15 -0
  208. package/dist/viewers/avro/index.js +5 -0
  209. package/dist/viewers/bag/index.d.ts +15 -0
  210. package/dist/viewers/bag/index.js +5 -0
  211. package/dist/viewers/blf/index.d.ts +15 -0
  212. package/dist/viewers/blf/index.js +5 -0
  213. package/dist/viewers/csv/controller.d.ts +126 -0
  214. package/dist/viewers/csv/controller.js +598 -0
  215. package/dist/viewers/csv/index.d.ts +48 -0
  216. package/dist/viewers/csv/index.js +846 -0
  217. package/dist/viewers/csv/styles.d.ts +1 -0
  218. package/dist/viewers/csv/styles.js +267 -0
  219. package/dist/viewers/db3/index.d.ts +15 -0
  220. package/dist/viewers/db3/index.js +5 -0
  221. package/dist/viewers/dbc/index.d.ts +15 -0
  222. package/dist/viewers/dbc/index.js +5 -0
  223. package/dist/viewers/diagram.d.ts +14 -0
  224. package/dist/viewers/diagram.js +95 -0
  225. package/dist/viewers/excel/controller.d.ts +108 -0
  226. package/dist/viewers/excel/controller.js +548 -0
  227. package/dist/viewers/excel/grid.d.ts +28 -0
  228. package/dist/viewers/excel/grid.js +99 -0
  229. package/dist/viewers/excel/index.d.ts +37 -0
  230. package/dist/viewers/excel/index.js +620 -0
  231. package/dist/viewers/excel/self-loading.d.ts +6 -0
  232. package/dist/viewers/excel/self-loading.js +13 -0
  233. package/dist/viewers/excel/styles.d.ts +1 -0
  234. package/dist/viewers/excel/styles.js +216 -0
  235. package/dist/viewers/fallback/index.d.ts +17 -0
  236. package/dist/viewers/fallback/index.js +130 -0
  237. package/dist/viewers/fallback/styles.d.ts +1 -0
  238. package/dist/viewers/fallback/styles.js +49 -0
  239. package/dist/viewers/hdf5/index.d.ts +19 -0
  240. package/dist/viewers/hdf5/index.js +170 -0
  241. package/dist/viewers/hdf5/styles.d.ts +1 -0
  242. package/dist/viewers/hdf5/styles.js +4 -0
  243. package/dist/viewers/hwp/controller.d.ts +19 -0
  244. package/dist/viewers/hwp/controller.js +22 -0
  245. package/dist/viewers/hwp/index.d.ts +39 -0
  246. package/dist/viewers/hwp/index.js +271 -0
  247. package/dist/viewers/hwp/self-loading.d.ts +2 -0
  248. package/dist/viewers/hwp/self-loading.js +6 -0
  249. package/dist/viewers/hwp/styles.d.ts +1 -0
  250. package/dist/viewers/hwp/styles.js +13 -0
  251. package/dist/viewers/image/controller.d.ts +210 -0
  252. package/dist/viewers/image/controller.js +336 -0
  253. package/dist/viewers/image/decode.d.ts +54 -0
  254. package/dist/viewers/image/decode.js +150 -0
  255. package/dist/viewers/image/index.d.ts +38 -0
  256. package/dist/viewers/image/index.js +749 -0
  257. package/dist/viewers/image/limits.d.ts +18 -0
  258. package/dist/viewers/image/limits.js +20 -0
  259. package/dist/viewers/image/styles.d.ts +1 -0
  260. package/dist/viewers/image/styles.js +119 -0
  261. package/dist/viewers/json/controller.d.ts +89 -0
  262. package/dist/viewers/json/controller.js +411 -0
  263. package/dist/viewers/json/index.d.ts +25 -0
  264. package/dist/viewers/json/index.js +503 -0
  265. package/dist/viewers/json/styles.d.ts +1 -0
  266. package/dist/viewers/json/styles.js +346 -0
  267. package/dist/viewers/json/transforms.d.ts +27 -0
  268. package/dist/viewers/json/transforms.js +253 -0
  269. package/dist/viewers/jsonl/controller.d.ts +48 -0
  270. package/dist/viewers/jsonl/controller.js +136 -0
  271. package/dist/viewers/jsonl/index.d.ts +22 -0
  272. package/dist/viewers/jsonl/index.js +184 -0
  273. package/dist/viewers/jsonl/styles.d.ts +1 -0
  274. package/dist/viewers/jsonl/styles.js +1 -0
  275. package/dist/viewers/markdown/controller.d.ts +50 -0
  276. package/dist/viewers/markdown/controller.js +62 -0
  277. package/dist/viewers/markdown/index.d.ts +64 -0
  278. package/dist/viewers/markdown/index.js +425 -0
  279. package/dist/viewers/markdown/math.d.ts +21 -0
  280. package/dist/viewers/markdown/math.js +100 -0
  281. package/dist/viewers/markdown/self-loading.d.ts +5 -0
  282. package/dist/viewers/markdown/self-loading.js +48 -0
  283. package/dist/viewers/markdown/styles.d.ts +1 -0
  284. package/dist/viewers/markdown/styles.js +11 -0
  285. package/dist/viewers/mat/index.d.ts +19 -0
  286. package/dist/viewers/mat/index.js +113 -0
  287. package/dist/viewers/mat/styles.d.ts +1 -0
  288. package/dist/viewers/mat/styles.js +3 -0
  289. package/dist/viewers/media.d.ts +9 -0
  290. package/dist/viewers/media.js +77 -0
  291. package/dist/viewers/mermaid/index.d.ts +17 -0
  292. package/dist/viewers/mermaid/index.js +6 -0
  293. package/dist/viewers/mermaid/self-loading.d.ts +2 -0
  294. package/dist/viewers/mermaid/self-loading.js +2 -0
  295. package/dist/viewers/mf4/index.d.ts +15 -0
  296. package/dist/viewers/mf4/index.js +5 -0
  297. package/dist/viewers/parquet/controller.d.ts +37 -0
  298. package/dist/viewers/parquet/controller.js +26 -0
  299. package/dist/viewers/parquet/index.d.ts +23 -0
  300. package/dist/viewers/parquet/index.js +134 -0
  301. package/dist/viewers/parquet/styles.d.ts +1 -0
  302. package/dist/viewers/parquet/styles.js +3 -0
  303. package/dist/viewers/pcap/index.d.ts +15 -0
  304. package/dist/viewers/pcap/index.js +5 -0
  305. package/dist/viewers/pcapng/index.d.ts +15 -0
  306. package/dist/viewers/pcapng/index.js +5 -0
  307. package/dist/viewers/pdf/controller.d.ts +120 -0
  308. package/dist/viewers/pdf/controller.js +191 -0
  309. package/dist/viewers/pdf/editing.d.ts +26 -0
  310. package/dist/viewers/pdf/editing.js +265 -0
  311. package/dist/viewers/pdf/index.d.ts +88 -0
  312. package/dist/viewers/pdf/index.js +1400 -0
  313. package/dist/viewers/pdf/self-loading.d.ts +6 -0
  314. package/dist/viewers/pdf/self-loading.js +14 -0
  315. package/dist/viewers/pdf/styles.d.ts +1 -0
  316. package/dist/viewers/pdf/styles.js +555 -0
  317. package/dist/viewers/plantuml/index.d.ts +17 -0
  318. package/dist/viewers/plantuml/index.js +6 -0
  319. package/dist/viewers/plantuml/self-loading.d.ts +2 -0
  320. package/dist/viewers/plantuml/self-loading.js +2 -0
  321. package/dist/viewers/ppt/chart.d.ts +8 -0
  322. package/dist/viewers/ppt/chart.js +83 -0
  323. package/dist/viewers/ppt/controller.d.ts +34 -0
  324. package/dist/viewers/ppt/controller.js +27 -0
  325. package/dist/viewers/ppt/index.d.ts +33 -0
  326. package/dist/viewers/ppt/index.js +101 -0
  327. package/dist/viewers/ppt/render.d.ts +5 -0
  328. package/dist/viewers/ppt/render.js +144 -0
  329. package/dist/viewers/ppt/self-loading.d.ts +9 -0
  330. package/dist/viewers/ppt/self-loading.js +4 -0
  331. package/dist/viewers/ppt/styles.d.ts +1 -0
  332. package/dist/viewers/ppt/styles.js +1 -0
  333. package/dist/viewers/proto/index.d.ts +17 -0
  334. package/dist/viewers/proto/index.js +170 -0
  335. package/dist/viewers/proto/styles.d.ts +1 -0
  336. package/dist/viewers/proto/styles.js +2 -0
  337. package/dist/viewers/psd/index.d.ts +27 -0
  338. package/dist/viewers/psd/index.js +39 -0
  339. package/dist/viewers/psd/self-loading.d.ts +10 -0
  340. package/dist/viewers/psd/self-loading.js +20 -0
  341. package/dist/viewers/psd/styles.d.ts +1 -0
  342. package/dist/viewers/psd/styles.js +1 -0
  343. package/dist/viewers/reqif/index.d.ts +15 -0
  344. package/dist/viewers/reqif/index.js +5 -0
  345. package/dist/viewers/shapefile/index.d.ts +35 -0
  346. package/dist/viewers/shapefile/index.js +336 -0
  347. package/dist/viewers/shapefile/self-loading.d.ts +7 -0
  348. package/dist/viewers/shapefile/self-loading.js +32 -0
  349. package/dist/viewers/shapefile/styles.d.ts +1 -0
  350. package/dist/viewers/shapefile/styles.js +28 -0
  351. package/dist/viewers/stp/index.d.ts +15 -0
  352. package/dist/viewers/stp/index.js +5 -0
  353. package/dist/viewers/structured-styles.d.ts +1 -0
  354. package/dist/viewers/structured-styles.js +1 -0
  355. package/dist/viewers/structured.d.ts +36 -0
  356. package/dist/viewers/structured.js +138 -0
  357. package/dist/viewers/toml/controller.d.ts +38 -0
  358. package/dist/viewers/toml/controller.js +61 -0
  359. package/dist/viewers/toml/index.d.ts +18 -0
  360. package/dist/viewers/toml/index.js +34 -0
  361. package/dist/viewers/types.d.ts +36 -0
  362. package/dist/viewers/types.js +9 -0
  363. package/dist/viewers/video/controller.d.ts +29 -0
  364. package/dist/viewers/video/controller.js +54 -0
  365. package/dist/viewers/video/index.d.ts +18 -0
  366. package/dist/viewers/video/index.js +305 -0
  367. package/dist/viewers/video/styles.d.ts +1 -0
  368. package/dist/viewers/video/styles.js +79 -0
  369. package/dist/viewers/word/controller.d.ts +19 -0
  370. package/dist/viewers/word/controller.js +22 -0
  371. package/dist/viewers/word/docx-preprocess.d.ts +63 -0
  372. package/dist/viewers/word/docx-preprocess.js +136 -0
  373. package/dist/viewers/word/index.d.ts +32 -0
  374. package/dist/viewers/word/index.js +187 -0
  375. package/dist/viewers/word/normalize-docx.d.ts +2 -0
  376. package/dist/viewers/word/normalize-docx.js +50 -0
  377. package/dist/viewers/word/paginate.d.ts +1 -0
  378. package/dist/viewers/word/paginate.js +1035 -0
  379. package/dist/viewers/word/self-loading.d.ts +2 -0
  380. package/dist/viewers/word/self-loading.js +7 -0
  381. package/dist/viewers/word/styles.d.ts +1 -0
  382. package/dist/viewers/word/styles.js +686 -0
  383. package/dist/viewers/yaml/controller.d.ts +42 -0
  384. package/dist/viewers/yaml/controller.js +41 -0
  385. package/dist/viewers/yaml/index.d.ts +21 -0
  386. package/dist/viewers/yaml/index.js +20 -0
  387. package/package.json +375 -0
@@ -0,0 +1,425 @@
1
+ import { ALLOWED_LINK_SCHEMES } from '../../host/index.js';
2
+ import { parseMarkdown } from '../../parsers/markdown/index.js';
3
+ import { MountAbortedError, VIEWER_ROOT_CLASS } from '../types.js';
4
+ import { createMarkdownController } from './controller.js';
5
+ import { maskMathSegments, mathSegmentLiteral } from './math.js';
6
+ import { markdownViewerCss } from './styles.js';
7
+ export { parseMarkdown } from '../../parsers/markdown/index.js';
8
+ export { markdownViewerCss } from './styles.js';
9
+ export { createMarkdownController } from './controller.js';
10
+ export { maskMathSegments, mathSegmentLiteral } from './math.js';
11
+ export const MARKDOWN_VIEWER_META = {
12
+ id: 'markdown', displayNameKey: 'markdown.title',
13
+ extensions: ['md', 'markdown', 'mdown', 'mkdn', 'mkd'], priority: 10,
14
+ requiredServices: [],
15
+ optionalServices: ['clipboard', 'navigation', 'documentAssets', 'writeback'],
16
+ inputOwnership: 'borrows'
17
+ };
18
+ const SANITIZE = {
19
+ USE_PROFILES: { html: true }, ADD_ATTR: ['target', 'rel'],
20
+ FORBID_TAGS: ['style', 'script', 'iframe', 'object', 'embed', 'form', 'input', 'button', 'textarea', 'select'],
21
+ FORBID_ATTR: ['style', 'srcdoc'], ALLOW_UNKNOWN_PROTOCOLS: false
22
+ };
23
+ const SVG_SANITIZE = {
24
+ USE_PROFILES: { svg: true, svgFilters: true }, ADD_TAGS: ['foreignObject'],
25
+ ADD_ATTR: ['dominant-baseline', 'text-anchor', 'viewBox', 'xmlns', 'role', 'aria-roledescription']
26
+ };
27
+ // KaTeX htmlAndMathml output: spans positioned via inline style, a MathML
28
+ // twin for accessibility, and SVG for stretchy delimiters. `style` is allowed
29
+ // only inside these fragments — the outer document keeps FORBID_ATTR:style.
30
+ const MATH_SANITIZE = {
31
+ USE_PROFILES: { html: true, mathMl: true, svg: true },
32
+ ADD_ATTR: ['style', 'aria-hidden', 'encoding', 'definitionurl'],
33
+ FORBID_TAGS: ['script', 'iframe', 'object', 'embed', 'form', 'input', 'button', 'textarea', 'select', 'a', 'img']
34
+ };
35
+ export async function mountMarkdownViewer(input, container, ctx, deps, options = {}) {
36
+ if (options.signal?.aborted)
37
+ throw new MountAbortedError();
38
+ const parseOptions = {
39
+ ...(options.signal ? { signal: options.signal } : {}),
40
+ ...(options.limits ? { limits: options.limits } : {}),
41
+ ...(options.markdownLimits ? { markdownLimits: options.markdownLimits } : {})
42
+ };
43
+ const parsed = parseMarkdown(input.data, parseOptions);
44
+ if (parsed.result.status === 'failed')
45
+ throw new Error(parsed.result.failure.messageKey);
46
+ const doc = parsed.result.document;
47
+ const root = options.styleIsolation !== 'scoped' && typeof container.attachShadow === 'function'
48
+ ? (container.shadowRoot ?? container.attachShadow({ mode: 'open' })) : container;
49
+ if (root === container)
50
+ container.classList.add(VIEWER_ROOT_CLASS, 'omni-viewer--markdown');
51
+ else {
52
+ const style = document.createElement('style');
53
+ style.textContent = markdownViewerCss;
54
+ root.append(style);
55
+ }
56
+ const t = ctx.i18n.t.bind(ctx.i18n);
57
+ const controller = createMarkdownController(doc.text, doc.headings);
58
+ const disposers = [];
59
+ let assetReleases = new Set();
60
+ let disposed = false;
61
+ let renderVersion = 0;
62
+ let renderedHtml = '';
63
+ let diagramCount = 0;
64
+ const el = (tag, className, text) => {
65
+ const node = document.createElement(tag);
66
+ if (className)
67
+ node.className = className;
68
+ if (text !== undefined)
69
+ node.textContent = text;
70
+ return node;
71
+ };
72
+ const on = (node, type, listener) => {
73
+ node.addEventListener(type, listener);
74
+ disposers.push(() => node.removeEventListener(type, listener));
75
+ };
76
+ const button = (key, className = 'omni-markdown__button') => {
77
+ const node = el('button', className, t(key));
78
+ node.type = 'button';
79
+ return node;
80
+ };
81
+ const shell = el('section', `${VIEWER_ROOT_CLASS} omni-viewer--markdown omni-markdown`);
82
+ const header = el('header', 'omni-markdown__header');
83
+ const titleBox = el('div');
84
+ titleBox.append(el('div', 'omni-markdown__title', input.fileName), el('div', 'omni-markdown__summary'));
85
+ const status = el('div', 'omni-markdown__status', t('markdown.ready'));
86
+ header.append(titleBox, status);
87
+ const toolbar = el('div', 'omni-markdown__toolbar');
88
+ const modeGroup = el('div', 'omni-markdown__toolbar-group');
89
+ const modeButtons = new Map();
90
+ for (const [mode, key] of [['preview', 'markdown.preview'], ['split', 'markdown.split'], ['source', 'markdown.source']]) {
91
+ const node = button(key);
92
+ node.dataset.viewMode = mode;
93
+ modeButtons.set(mode, node);
94
+ modeGroup.append(node);
95
+ }
96
+ const actionGroup = el('div', 'omni-markdown__toolbar-group');
97
+ const renderButton = button('markdown.render', 'omni-markdown__button omni-markdown__button--primary');
98
+ const copyHtmlButton = button('markdown.copyHtml');
99
+ const copySourceButton = button('markdown.copySource');
100
+ const undoButton = button('markdown.undo');
101
+ const redoButton = button('markdown.redo');
102
+ actionGroup.append(renderButton, undoButton, redoButton, copyHtmlButton, copySourceButton);
103
+ toolbar.append(modeGroup, actionGroup);
104
+ const workspace = el('main', 'omni-markdown__workspace');
105
+ const previewPanel = el('section', 'omni-markdown__panel omni-markdown__preview-panel');
106
+ const previewHeader = el('div', 'omni-markdown__panel-header');
107
+ const previewCaption = el('span', 'omni-markdown__caption', t('markdown.rendering'));
108
+ previewHeader.append(el('span', undefined, t('markdown.preview')), previewCaption);
109
+ const preview = el('article', 'omni-markdown__preview');
110
+ previewPanel.append(previewHeader, preview);
111
+ const sourcePanel = el('section', 'omni-markdown__panel omni-markdown__source-panel');
112
+ const sourceHeader = el('div', 'omni-markdown__panel-header');
113
+ const sourceCaption = el('span', 'omni-markdown__caption', t('markdown.editable'));
114
+ sourceHeader.append(el('span', undefined, t('markdown.source')), sourceCaption);
115
+ const source = el('textarea', 'omni-markdown__source');
116
+ source.spellcheck = false;
117
+ source.value = doc.text;
118
+ sourcePanel.append(sourceHeader, source);
119
+ workspace.append(previewPanel, sourcePanel);
120
+ const message = el('div', 'omni-markdown__message');
121
+ message.hidden = true;
122
+ shell.append(header, toolbar, workspace, message);
123
+ root.append(shell);
124
+ const releaseAssets = () => { for (const release of assetReleases)
125
+ release(); assetReleases = new Set(); };
126
+ const setStatus = (key, kind = '') => {
127
+ status.textContent = t(key);
128
+ status.className = `omni-markdown__status${kind ? ` is-${kind}` : ''}`;
129
+ };
130
+ const showMessage = (text) => { message.textContent = text; message.hidden = !text; };
131
+ const syncState = () => {
132
+ const state = controller.state;
133
+ workspace.classList.toggle('is-split', state.mode === 'split');
134
+ previewPanel.hidden = state.mode === 'source';
135
+ sourcePanel.hidden = state.mode === 'preview';
136
+ for (const [mode, node] of modeButtons)
137
+ node.classList.toggle('is-active', mode === state.mode);
138
+ renderButton.classList.toggle('is-dirty', state.dirty);
139
+ undoButton.disabled = !state.canUndo;
140
+ redoButton.disabled = !state.canRedo;
141
+ sourceCaption.textContent = t(state.dirty ? 'markdown.edited' : 'markdown.editable');
142
+ if (state.dirty)
143
+ setStatus('markdown.modified');
144
+ };
145
+ const hardenContent = (version) => {
146
+ preview.querySelectorAll('a').forEach(anchor => {
147
+ const href = anchor.getAttribute('href') ?? '';
148
+ anchor.removeAttribute('href');
149
+ if (href.startsWith('#')) {
150
+ anchor.setAttribute('href', href);
151
+ return;
152
+ }
153
+ try {
154
+ const url = new URL(href);
155
+ if (!ALLOWED_LINK_SCHEMES.includes(url.protocol) || !ctx.navigation)
156
+ throw new Error('blocked');
157
+ anchor.setAttribute('role', 'link');
158
+ anchor.tabIndex = 0;
159
+ on(anchor, 'click', (() => void ctx.navigation.openExternalUrl(href)));
160
+ }
161
+ catch {
162
+ anchor.setAttribute('aria-disabled', 'true');
163
+ }
164
+ });
165
+ preview.querySelectorAll('img').forEach(image => {
166
+ const path = image.getAttribute('src') ?? '';
167
+ image.removeAttribute('src');
168
+ if (!validRelativeAsset(path) || !ctx.documentAssets) {
169
+ image.replaceWith(document.createTextNode(image.alt || t('markdown.assetUnavailable')));
170
+ return;
171
+ }
172
+ void ctx.documentAssets.resolve(path).then(asset => {
173
+ if (!asset) {
174
+ if (!disposed && version === renderVersion)
175
+ image.replaceWith(document.createTextNode(image.alt || t('markdown.assetUnavailable')));
176
+ return;
177
+ }
178
+ let released = false;
179
+ const release = () => { if (!released) {
180
+ released = true;
181
+ assetReleases.delete(release);
182
+ asset.dispose();
183
+ } };
184
+ if (disposed || version !== renderVersion) {
185
+ release();
186
+ return;
187
+ }
188
+ assetReleases.add(release);
189
+ image.src = asset.url;
190
+ image.addEventListener('load', release, { once: true });
191
+ image.addEventListener('error', release, { once: true });
192
+ }).catch(() => { if (!disposed && version === renderVersion)
193
+ image.replaceWith(document.createTextNode(image.alt || t('markdown.assetUnavailable'))); });
194
+ });
195
+ };
196
+ const renderEnhancements = async (version) => {
197
+ diagramCount = 0;
198
+ const purifier = deps.createDOMPurify(window);
199
+ const codes = [...preview.querySelectorAll('pre > code')];
200
+ for (const [index, code] of codes.entries()) {
201
+ const language = codeLanguage(code);
202
+ if (language === 'mermaid' && deps.diagrams?.renderMermaid) {
203
+ diagramCount++;
204
+ const frame = el('div', 'omni-markdown__diagram omni-markdown__diagram--mermaid');
205
+ frame.setAttribute('role', 'img');
206
+ try {
207
+ frame.innerHTML = purifier.sanitize(await deps.diagrams.renderMermaid(`omni-md-${version}-${index}`, code.textContent ?? ''), SVG_SANITIZE);
208
+ }
209
+ catch (error) {
210
+ frame.classList.add('is-invalid');
211
+ frame.textContent = errorText(error, t('markdown.diagramFailed'));
212
+ }
213
+ if (version === renderVersion)
214
+ code.closest('pre')?.replaceWith(frame);
215
+ }
216
+ else if (['plantuml', 'puml', 'uml'].includes(language) && deps.diagrams?.renderPlantUml) {
217
+ diagramCount++;
218
+ const frame = el('div', 'omni-markdown__diagram omni-markdown__diagram--plantuml');
219
+ frame.setAttribute('role', 'img');
220
+ try {
221
+ frame.innerHTML = purifier.sanitize(new XMLSerializer().serializeToString(deps.diagrams.renderPlantUml(code.textContent ?? '', document)), SVG_SANITIZE);
222
+ }
223
+ catch (error) {
224
+ frame.classList.add('is-invalid');
225
+ frame.textContent = errorText(error, t('markdown.diagramFailed'));
226
+ }
227
+ code.closest('pre')?.replaceWith(frame);
228
+ }
229
+ else if (deps.highlighter) {
230
+ const sourceText = code.textContent ?? '';
231
+ const result = language && deps.highlighter.getLanguage(language)
232
+ ? deps.highlighter.highlight(sourceText, { language, ignoreIllegals: true }) : deps.highlighter.highlightAuto(sourceText);
233
+ code.innerHTML = purifier.sanitize(result.value, { ALLOWED_TAGS: ['span'], ALLOWED_ATTR: ['class'] });
234
+ code.classList.add('hljs');
235
+ if (result.language)
236
+ code.dataset.language = result.language;
237
+ }
238
+ }
239
+ };
240
+ const applyMath = (segments) => {
241
+ if (!segments.length || !deps.math)
242
+ return;
243
+ const math = deps.math;
244
+ const purifier = deps.createDOMPurify(window);
245
+ const walker = document.createTreeWalker(preview, NodeFilter.SHOW_TEXT);
246
+ const textNodes = [];
247
+ while (walker.nextNode()) {
248
+ const node = walker.currentNode;
249
+ if (node.parentElement?.closest('pre, code, textarea'))
250
+ continue;
251
+ if (node.nodeValue?.includes('omni-math-token-'))
252
+ textNodes.push(node);
253
+ }
254
+ for (const node of textNodes) {
255
+ const fragment = document.createDocumentFragment();
256
+ for (const part of (node.nodeValue ?? '').split(/(%%omni-math-token-\d+%%)/)) {
257
+ const match = /^%%omni-math-token-(\d+)%%$/.exec(part);
258
+ const segment = match ? segments[Number(match[1])] : undefined;
259
+ if (!segment) {
260
+ if (part)
261
+ fragment.append(document.createTextNode(part));
262
+ continue;
263
+ }
264
+ const holder = el('span', `omni-markdown__math${segment.display ? ' omni-markdown__math--display' : ''}`);
265
+ try {
266
+ holder.innerHTML = purifier.sanitize(math.renderToHtml(segment.source, segment.display), MATH_SANITIZE);
267
+ }
268
+ catch {
269
+ holder.classList.add('is-invalid');
270
+ holder.textContent = mathSegmentLiteral(segment);
271
+ }
272
+ fragment.append(holder);
273
+ }
274
+ node.replaceWith(fragment);
275
+ }
276
+ };
277
+ const boundedRenderSource = (sourceText) => {
278
+ const outcome = parseMarkdown(new TextEncoder().encode(sourceText), parseOptions);
279
+ if (outcome.result.status === 'failed')
280
+ throw new Error(t(outcome.result.failure.messageKey));
281
+ return { source: outcome.result.document.renderText, partial: outcome.result.status === 'partial' };
282
+ };
283
+ const renderMarkdown = async (save) => {
284
+ const version = ++renderVersion;
285
+ releaseAssets();
286
+ setStatus('markdown.rendering');
287
+ showMessage('');
288
+ try {
289
+ // Re-apply the parser limits on every render: the editor may have
290
+ // changed since mount, and marked/DOM must never see an unbounded source.
291
+ const bounded = boundedRenderSource(controller.state.source);
292
+ // Math is lifted out before marked (emphasis would corrupt TeX)
293
+ // and re-inserted into the sanitized DOM afterwards.
294
+ const masked = deps.math ? maskMathSegments(bounded.source) : { masked: bounded.source, segments: [] };
295
+ const sanitizedHtml = deps.createDOMPurify(window).sanitize(deps.render.parse(masked.masked), SANITIZE);
296
+ renderedHtml = sanitizedHtml.replace(/%%omni-math-token-(\d+)%%/g, (whole, at) => { const segment = masked.segments[Number(at)]; return segment ? mathSegmentLiteral(segment) : whole; });
297
+ preview.replaceChildren();
298
+ const holder = new DOMParser().parseFromString(sanitizedHtml, 'text/html');
299
+ while (holder.body.firstChild)
300
+ preview.append(holder.body.firstChild);
301
+ preview.querySelectorAll('h1,h2,h3,h4,h5,h6').forEach((heading, index) => heading.id = `heading-${index}`);
302
+ hardenContent(version);
303
+ await renderEnhancements(version);
304
+ if (disposed || version !== renderVersion)
305
+ return;
306
+ applyMath(masked.segments);
307
+ const lines = controller.state.source ? controller.state.source.split(/\r?\n/).length : 0;
308
+ const words = controller.state.source.match(/\S+/g)?.length ?? 0;
309
+ titleBox.querySelector('.omni-markdown__summary').textContent = t('markdown.summary', { lines, words });
310
+ previewCaption.textContent = diagramCount ? t('markdown.renderedDiagrams', { count: diagramCount }) : t('markdown.rendered');
311
+ setStatus('markdown.rendered', 'valid');
312
+ if (bounded.partial)
313
+ showMessage(t('diag.markdown.limit-exceeded'));
314
+ if (save)
315
+ await saveSource();
316
+ }
317
+ catch (error) {
318
+ preview.replaceChildren();
319
+ renderedHtml = '';
320
+ previewCaption.textContent = t('markdown.renderFailed');
321
+ setStatus('markdown.invalid', 'invalid');
322
+ showMessage(errorText(error, t('markdown.renderFailed')));
323
+ }
324
+ };
325
+ const saveSource = async () => {
326
+ if (!ctx.writeback) {
327
+ showMessage(t('common.noWriteback'));
328
+ setStatus('common.saveFailed', 'invalid');
329
+ return;
330
+ }
331
+ try {
332
+ await ctx.writeback.write(new TextEncoder().encode(controller.state.source));
333
+ controller.dispatch({ type: 'mark-saved' });
334
+ setStatus('common.savedToOriginal', 'valid');
335
+ sourceCaption.textContent = t('common.savedToOriginal');
336
+ }
337
+ catch (error) {
338
+ ctx.logger.log('error', `markdown save failed: ${String(error)}`);
339
+ setStatus('common.saveFailed', 'invalid');
340
+ showMessage(errorText(error, t('common.saveFailed')));
341
+ }
342
+ };
343
+ const copy = async (value, successKey) => {
344
+ if (!ctx.clipboard)
345
+ return;
346
+ try {
347
+ await ctx.clipboard.writeText(value);
348
+ setStatus(successKey, 'valid');
349
+ }
350
+ catch (error) {
351
+ ctx.logger.log('error', `markdown copy failed: ${String(error)}`);
352
+ }
353
+ };
354
+ for (const [mode, node] of modeButtons)
355
+ on(node, 'click', (() => controller.dispatch({ type: 'set-mode', mode })));
356
+ on(source, 'input', (() => controller.dispatch({ type: 'edit-source', source: source.value })));
357
+ on(source, 'keydown', (event => {
358
+ const keyboard = event;
359
+ const key = keyboard.key.toLowerCase();
360
+ const command = keyboard.metaKey || keyboard.ctrlKey;
361
+ if (command && key === 'z') {
362
+ keyboard.preventDefault();
363
+ controller.dispatch({ type: keyboard.shiftKey ? 'redo' : 'undo' });
364
+ source.value = controller.state.source;
365
+ }
366
+ else if (command && key === 'y') {
367
+ keyboard.preventDefault();
368
+ controller.dispatch({ type: 'redo' });
369
+ source.value = controller.state.source;
370
+ }
371
+ else if (command && key === 's') {
372
+ keyboard.preventDefault();
373
+ if (ctx.writeback)
374
+ void renderMarkdown(true);
375
+ else
376
+ void saveSource();
377
+ }
378
+ else if (keyboard.shiftKey && keyboard.key === 'Enter') {
379
+ keyboard.preventDefault();
380
+ void renderMarkdown(Boolean(ctx.writeback));
381
+ }
382
+ }));
383
+ // Render remains useful in read-only adapters. Saving is coupled only when
384
+ // the host actually advertised and supplied writeback.
385
+ on(renderButton, 'click', (() => void renderMarkdown(Boolean(ctx.writeback))));
386
+ on(undoButton, 'click', (() => { controller.dispatch({ type: 'undo' }); source.value = controller.state.source; }));
387
+ on(redoButton, 'click', (() => { controller.dispatch({ type: 'redo' }); source.value = controller.state.source; }));
388
+ on(copyHtmlButton, 'click', (() => void copy(renderedHtml, 'markdown.htmlCopied')));
389
+ on(copySourceButton, 'click', (() => void copy(source.value, 'markdown.sourceCopied')));
390
+ if (!ctx.clipboard) {
391
+ for (const node of [copyHtmlButton, copySourceButton]) {
392
+ node.disabled = true;
393
+ node.title = t('common.noClipboard');
394
+ }
395
+ }
396
+ const off = controller.subscribe(syncState);
397
+ disposers.push(off);
398
+ syncState();
399
+ await renderMarkdown(false);
400
+ if (options.signal?.aborted) {
401
+ shell.remove();
402
+ releaseAssets();
403
+ throw new MountAbortedError();
404
+ }
405
+ return { dispose() { disposed = true; renderVersion++; releaseAssets(); for (const dispose of disposers.splice(0))
406
+ dispose(); shell.remove(); } };
407
+ }
408
+ function codeLanguage(block) {
409
+ for (const name of block.classList)
410
+ if (name.startsWith('language-'))
411
+ return name.slice(9).toLowerCase();
412
+ else if (name.startsWith('lang-'))
413
+ return name.slice(5).toLowerCase();
414
+ return '';
415
+ }
416
+ function errorText(error, fallback) { return error instanceof Error ? error.message : fallback; }
417
+ function validRelativeAsset(path) {
418
+ try {
419
+ const decoded = decodeURIComponent(path);
420
+ return !!decoded && !/^(?:[a-z][a-z0-9+.-]*:|[\\/])|(?:^|[\\/])\.\.(?:[\\/]|$)/i.test(decoded);
421
+ }
422
+ catch {
423
+ return false;
424
+ }
425
+ }
@@ -0,0 +1,21 @@
1
+ export interface MathSegment {
2
+ source: string;
3
+ display: boolean;
4
+ }
5
+ export interface MaskedMathSource {
6
+ masked: string;
7
+ segments: MathSegment[];
8
+ }
9
+ /** Deliberately free of `_`/`*`/`$` so markdown inline rules ignore it. */
10
+ export declare const MATH_TOKEN_PREFIX = "omni-math-token-";
11
+ export declare const MATH_TOKEN_PATTERN: RegExp;
12
+ /** Literal text a segment came from, for copy-HTML output and fallbacks. */
13
+ export declare function mathSegmentLiteral(segment: MathSegment): string;
14
+ /**
15
+ * Replace `$...$` (inline) and `$$...$$` (display) TeX spans with placeholder
16
+ * tokens. Fenced code blocks and inline code spans are left untouched.
17
+ * Inline rules follow KaTeX auto-render: content must not start or end with
18
+ * whitespace and the closing `$` must not be followed by a digit. Display
19
+ * math may span lines but not blank lines.
20
+ */
21
+ export declare function maskMathSegments(source: string): MaskedMathSource;
@@ -0,0 +1,100 @@
1
+ // TeX math extraction for the markdown viewer. Math must be lifted out of the
2
+ // source BEFORE marked runs: `$a_i + b_i$` would otherwise be mangled by
3
+ // emphasis parsing. Segments are replaced with inert placeholder tokens that
4
+ // survive marked and DOMPurify unchanged, then swapped for rendered math in
5
+ // the sanitized preview DOM (same post-sanitize slot pattern as diagrams).
6
+ /** Deliberately free of `_`/`*`/`$` so markdown inline rules ignore it. */
7
+ export const MATH_TOKEN_PREFIX = 'omni-math-token-';
8
+ const TOKEN = (index) => `%%${MATH_TOKEN_PREFIX}${index}%%`;
9
+ export const MATH_TOKEN_PATTERN = /%%omni-math-token-(\d+)%%/g;
10
+ /** Literal text a segment came from, for copy-HTML output and fallbacks. */
11
+ export function mathSegmentLiteral(segment) {
12
+ return segment.display ? `$$${segment.source}$$` : `$${segment.source}$`;
13
+ }
14
+ const FENCE = /^(`{3,}|~{3,})/;
15
+ const MAX_DISPLAY_MATH_LENGTH = 5000;
16
+ const MAX_INLINE_MATH_LENGTH = 1000;
17
+ /**
18
+ * Replace `$...$` (inline) and `$$...$$` (display) TeX spans with placeholder
19
+ * tokens. Fenced code blocks and inline code spans are left untouched.
20
+ * Inline rules follow KaTeX auto-render: content must not start or end with
21
+ * whitespace and the closing `$` must not be followed by a digit. Display
22
+ * math may span lines but not blank lines.
23
+ */
24
+ export function maskMathSegments(source) {
25
+ const segments = [];
26
+ let out = '';
27
+ let index = 0;
28
+ let atLineStart = true;
29
+ let fence = null;
30
+ const lineEnd = (from) => {
31
+ const at = source.indexOf('\n', from);
32
+ return at === -1 ? source.length : at;
33
+ };
34
+ while (index < source.length) {
35
+ if (atLineStart) {
36
+ const rest = source.slice(index, lineEnd(index));
37
+ const marker = FENCE.exec(rest)?.[1];
38
+ if (marker) {
39
+ if (!fence)
40
+ fence = marker[0].repeat(3);
41
+ else if (marker.startsWith(fence))
42
+ fence = null;
43
+ }
44
+ }
45
+ const char = source[index];
46
+ atLineStart = char === '\n';
47
+ if (fence) {
48
+ out += char;
49
+ index++;
50
+ continue;
51
+ }
52
+ if (char === '\\' && source[index + 1] === '$') {
53
+ out += '\\$';
54
+ index += 2;
55
+ continue;
56
+ }
57
+ if (char === '`') {
58
+ // Inline code span: copy verbatim through the matching backtick run.
59
+ let run = 1;
60
+ while (source[index + run] === '`')
61
+ run++;
62
+ const close = source.indexOf('`'.repeat(run), index + run);
63
+ const end = close === -1 ? index + run : close + run;
64
+ const span = source.slice(index, end);
65
+ out += span;
66
+ if (span.includes('\n'))
67
+ atLineStart = span.endsWith('\n');
68
+ index = end;
69
+ continue;
70
+ }
71
+ if (char === '$') {
72
+ if (source[index + 1] === '$') {
73
+ const close = source.indexOf('$$', index + 2);
74
+ const body = close === -1 ? '' : source.slice(index + 2, close);
75
+ if (close !== -1 && body.trim() && !/\n[ \t]*\n/.test(body) && body.length <= MAX_DISPLAY_MATH_LENGTH) {
76
+ segments.push({ source: body.trim(), display: true });
77
+ out += TOKEN(segments.length - 1);
78
+ atLineStart = false;
79
+ index = close + 2;
80
+ continue;
81
+ }
82
+ }
83
+ else {
84
+ const end = lineEnd(index);
85
+ const line = source.slice(index + 1, end);
86
+ const match = /^([^\s$](?:[^$]*[^\s$])?)\$(?!\d)/.exec(line);
87
+ if (match && match[1].length <= MAX_INLINE_MATH_LENGTH && !match[1].includes('`')) {
88
+ segments.push({ source: match[1], display: false });
89
+ out += TOKEN(segments.length - 1);
90
+ atLineStart = false;
91
+ index += 1 + match[0].length;
92
+ continue;
93
+ }
94
+ }
95
+ }
96
+ out += char;
97
+ index++;
98
+ }
99
+ return { masked: out, segments };
100
+ }
@@ -0,0 +1,5 @@
1
+ import type { MarkdownViewerDeps } from './index.js';
2
+ /** Convenience loader for web adapters. Markdown parsing and sanitizing are
3
+ * required; syntax highlighting and diagram engines enhance the viewer when
4
+ * their optional peer packages are installed. */
5
+ export declare function loadMarkdownViewerDeps(): Promise<MarkdownViewerDeps>;
@@ -0,0 +1,48 @@
1
+ /** Convenience loader for web adapters. Markdown parsing and sanitizing are
2
+ * required; syntax highlighting and diagram engines enhance the viewer when
3
+ * their optional peer packages are installed. */
4
+ export async function loadMarkdownViewerDeps() {
5
+ const [markedModule, purifierModule] = await Promise.all([
6
+ import('marked'), import('dompurify')
7
+ ]);
8
+ const marked = markedModule;
9
+ const create = purifierModule.default;
10
+ const deps = {
11
+ render: { parse: text => marked.marked.parse(text) },
12
+ createDOMPurify: window => create(window)
13
+ };
14
+ const [highlightResult, mermaidResult, plantUmlResult, katexResult] = await Promise.allSettled([
15
+ import('highlight.js'), import('mermaid'), import('puml-canvas-js'),
16
+ import('katex')
17
+ ]);
18
+ if (highlightResult.status === 'fulfilled') {
19
+ const module = highlightResult.value;
20
+ deps.highlighter = module.default ?? module;
21
+ }
22
+ const mermaid = mermaidResult.status === 'fulfilled'
23
+ ? mermaidResult.value.default
24
+ : undefined;
25
+ const plantUml = plantUmlResult.status === 'fulfilled'
26
+ ? plantUmlResult.value.render
27
+ : undefined;
28
+ if (mermaid || plantUml) {
29
+ if (mermaid)
30
+ mermaid.initialize({ startOnLoad: false, theme: 'base', securityLevel: 'strict', maxTextSize: 200000 });
31
+ deps.diagrams = {
32
+ ...(mermaid ? { renderMermaid: async (id, source) => (await mermaid.render(id, source)).svg } : {}),
33
+ ...(plantUml ? { renderPlantUml: (source, document) => plantUml(source, { document }) } : {})
34
+ };
35
+ }
36
+ if (katexResult.status === 'fulfilled') {
37
+ const module = katexResult.value;
38
+ const katex = module.default ?? (module.renderToString ? module : undefined);
39
+ if (katex) {
40
+ // KaTeX layout also needs katex.css (+fonts) — the adapter loads
41
+ // those into the page/shadow root alongside the core stylesheet.
42
+ deps.math = {
43
+ renderToHtml: (source, displayMode) => katex.renderToString(source, { displayMode, throwOnError: false, output: 'htmlAndMathml' })
44
+ };
45
+ }
46
+ }
47
+ return deps;
48
+ }
@@ -0,0 +1 @@
1
+ export declare const markdownViewerCss = "\n.omni-viewer--markdown{box-sizing:border-box;min-height:100%;padding:18px;display:flex;flex-direction:column;gap:14px;color:var(--omni-fg,#d4d4d4);background:var(--omni-bg,#1e1e1e);font:var(--omni-font-size,13px)/1.5 var(--omni-font-family,system-ui,sans-serif);--md-border:var(--omni-border,#454545);--md-muted:var(--omni-muted,#aaa);--md-panel:var(--omni-panel-bg,rgba(127,127,127,.05));--md-code:var(--omni-code-bg,rgba(127,127,127,.14));}\n.omni-markdown *{box-sizing:border-box}.omni-markdown__header,.omni-markdown__toolbar,.omni-markdown__toolbar-group,.omni-markdown__panel-header{display:flex;align-items:center;gap:10px}.omni-markdown__header{align-items:flex-start;justify-content:space-between;gap:16px}.omni-markdown__title{font-size:16px;font-weight:600;margin-bottom:4px;word-break:break-word}.omni-markdown__summary,.omni-markdown__caption{color:var(--md-muted);font-size:12px}.omni-markdown__status{padding:7px 10px;border-radius:999px;border:1px solid var(--md-border);background:rgba(79,193,255,.16);font-size:12px;font-weight:600;white-space:nowrap}.omni-markdown__status.is-valid{background:rgba(46,160,67,.16);color:var(--omni-success,#3fb950)}.omni-markdown__status.is-invalid{background:rgba(244,71,71,.14);color:var(--omni-error,#f44747)}\n.omni-markdown__toolbar{flex-wrap:wrap}.omni-markdown__toolbar-group{flex-wrap:wrap;padding:7px;border:1px solid var(--md-border);border-radius:8px;background:var(--md-panel)}.omni-markdown__button{cursor:pointer;border:1px solid var(--md-border);background:var(--omni-button-secondary-bg,rgba(127,127,127,.16));color:inherit;border-radius:6px;padding:7px 10px;font:inherit}.omni-markdown__button:hover:not(:disabled){background:rgba(127,127,127,.26)}.omni-markdown__button--primary{background:var(--omni-accent,#0e639c);color:var(--omni-accent-fg,#fff);border-color:var(--omni-accent,#0e639c)}.omni-markdown__button.is-active{border-color:var(--omni-focus,#007fd4);background:color-mix(in srgb,var(--omni-focus,#007fd4) 22%,transparent)}.omni-markdown__button.is-dirty{border-color:var(--omni-warning,#cca700)}.omni-markdown__button:disabled{cursor:default;opacity:.5}\n.omni-markdown__workspace{display:grid;grid-template-columns:minmax(360px,1fr);gap:14px;min-height:68vh}.omni-markdown__workspace.is-split{grid-template-columns:minmax(320px,1.1fr) minmax(300px,.9fr)}.omni-markdown__workspace.is-split .omni-markdown__source-panel{grid-column:1;grid-row:1}.omni-markdown__workspace.is-split .omni-markdown__preview-panel{grid-column:2;grid-row:1}.omni-markdown__panel{display:flex;flex-direction:column;min-height:0;border:1px solid var(--md-border);border-radius:8px;background:var(--md-panel);overflow:hidden}.omni-markdown__panel[hidden]{display:none}.omni-markdown__panel-header{justify-content:space-between;padding:12px 14px;border-bottom:1px solid var(--md-border)}\n.omni-markdown__preview{flex:1;min-height:0;overflow:auto;padding:22px;line-height:1.65}.omni-markdown__preview>:first-child{margin-top:0}.omni-markdown__preview>:last-child{margin-bottom:0}.omni-markdown__preview h1,.omni-markdown__preview h2,.omni-markdown__preview h3,.omni-markdown__preview h4{line-height:1.25;margin:1.35em 0 .65em}.omni-markdown__preview h1{font-size:28px;padding-bottom:8px;border-bottom:1px solid var(--md-border)}.omni-markdown__preview h2{font-size:22px;padding-bottom:6px;border-bottom:1px solid var(--md-border)}.omni-markdown__preview h3{font-size:18px}.omni-markdown__preview h4{font-size:15px}.omni-markdown__preview a{color:var(--omni-link,#4daafc)}.omni-markdown__preview p,.omni-markdown__preview ul,.omni-markdown__preview ol,.omni-markdown__preview blockquote,.omni-markdown__preview pre,.omni-markdown__preview table{margin:0 0 1em}.omni-markdown__preview blockquote{border-left:4px solid var(--md-border);padding:8px 14px;color:var(--md-muted)}.omni-markdown__preview code{font-family:var(--omni-mono,monospace);background:var(--md-code);border-radius:4px;padding:.15em .35em}.omni-markdown__preview pre{overflow:auto;background:var(--md-code);border-radius:8px;padding:14px}.omni-markdown__preview pre code{display:block;padding:0;background:transparent}.omni-markdown__preview table{width:100%;border-collapse:collapse;display:block;overflow:auto}.omni-markdown__preview th,.omni-markdown__preview td{border:1px solid var(--md-border);padding:7px 10px}.omni-markdown__preview img{max-width:100%;height:auto}\n.omni-markdown__source{flex:1;width:100%;min-height:62vh;resize:none;border:0;outline:0;padding:16px;background:var(--omni-editor-bg,var(--omni-bg,#1e1e1e));color:inherit;font:13px/1.55 var(--omni-mono,monospace);tab-size:4}.omni-markdown__message{padding:10px 12px;border:1px solid var(--omni-error,#f44747);border-radius:6px;color:var(--omni-error,#f44747);white-space:pre-wrap}.omni-markdown__diagram{overflow:auto;margin:0 0 1em;padding:16px;border:1px solid var(--md-border);border-radius:8px;background:#fff;color:#111}.omni-markdown__diagram svg{display:block;max-width:100%;height:auto;margin:0 auto}.omni-markdown__diagram.is-invalid{color:var(--omni-error,#f44747);background:rgba(244,71,71,.1);white-space:pre-wrap}\n.omni-markdown__math--display{display:block;margin:0 0 1em;text-align:center;overflow-x:auto}.omni-markdown__math.is-invalid{color:var(--omni-error,#f44747);font-family:var(--omni-mono,monospace);white-space:pre-wrap}\n.omni-markdown__preview .hljs-comment,.omni-markdown__preview .hljs-quote{color:#6a9955;font-style:italic}.omni-markdown__preview .hljs-keyword,.omni-markdown__preview .hljs-selector-tag{color:#c586c0}.omni-markdown__preview .hljs-string,.omni-markdown__preview .hljs-regexp{color:#ce9178}.omni-markdown__preview .hljs-number,.omni-markdown__preview .hljs-literal{color:#b5cea8}.omni-markdown__preview .hljs-title,.omni-markdown__preview .hljs-section{color:#dcdcaa}.omni-markdown__preview .hljs-type,.omni-markdown__preview .hljs-built_in{color:#4ec9b0}.omni-markdown__preview .hljs-attr,.omni-markdown__preview .hljs-name{color:#9cdcfe}.omni-markdown__preview .hljs-meta,.omni-markdown__preview .hljs-symbol{color:#d7ba7d}\n@media(max-width:760px){.omni-markdown__workspace.is-split{grid-template-columns:1fr}.omni-markdown__workspace.is-split .omni-markdown__source-panel,.omni-markdown__workspace.is-split .omni-markdown__preview-panel{grid-column:1;grid-row:auto}}\n";
@@ -0,0 +1,11 @@
1
+ export const markdownViewerCss = `
2
+ .omni-viewer--markdown{box-sizing:border-box;min-height:100%;padding:18px;display:flex;flex-direction:column;gap:14px;color:var(--omni-fg,#d4d4d4);background:var(--omni-bg,#1e1e1e);font:var(--omni-font-size,13px)/1.5 var(--omni-font-family,system-ui,sans-serif);--md-border:var(--omni-border,#454545);--md-muted:var(--omni-muted,#aaa);--md-panel:var(--omni-panel-bg,rgba(127,127,127,.05));--md-code:var(--omni-code-bg,rgba(127,127,127,.14));}
3
+ .omni-markdown *{box-sizing:border-box}.omni-markdown__header,.omni-markdown__toolbar,.omni-markdown__toolbar-group,.omni-markdown__panel-header{display:flex;align-items:center;gap:10px}.omni-markdown__header{align-items:flex-start;justify-content:space-between;gap:16px}.omni-markdown__title{font-size:16px;font-weight:600;margin-bottom:4px;word-break:break-word}.omni-markdown__summary,.omni-markdown__caption{color:var(--md-muted);font-size:12px}.omni-markdown__status{padding:7px 10px;border-radius:999px;border:1px solid var(--md-border);background:rgba(79,193,255,.16);font-size:12px;font-weight:600;white-space:nowrap}.omni-markdown__status.is-valid{background:rgba(46,160,67,.16);color:var(--omni-success,#3fb950)}.omni-markdown__status.is-invalid{background:rgba(244,71,71,.14);color:var(--omni-error,#f44747)}
4
+ .omni-markdown__toolbar{flex-wrap:wrap}.omni-markdown__toolbar-group{flex-wrap:wrap;padding:7px;border:1px solid var(--md-border);border-radius:8px;background:var(--md-panel)}.omni-markdown__button{cursor:pointer;border:1px solid var(--md-border);background:var(--omni-button-secondary-bg,rgba(127,127,127,.16));color:inherit;border-radius:6px;padding:7px 10px;font:inherit}.omni-markdown__button:hover:not(:disabled){background:rgba(127,127,127,.26)}.omni-markdown__button--primary{background:var(--omni-accent,#0e639c);color:var(--omni-accent-fg,#fff);border-color:var(--omni-accent,#0e639c)}.omni-markdown__button.is-active{border-color:var(--omni-focus,#007fd4);background:color-mix(in srgb,var(--omni-focus,#007fd4) 22%,transparent)}.omni-markdown__button.is-dirty{border-color:var(--omni-warning,#cca700)}.omni-markdown__button:disabled{cursor:default;opacity:.5}
5
+ .omni-markdown__workspace{display:grid;grid-template-columns:minmax(360px,1fr);gap:14px;min-height:68vh}.omni-markdown__workspace.is-split{grid-template-columns:minmax(320px,1.1fr) minmax(300px,.9fr)}.omni-markdown__workspace.is-split .omni-markdown__source-panel{grid-column:1;grid-row:1}.omni-markdown__workspace.is-split .omni-markdown__preview-panel{grid-column:2;grid-row:1}.omni-markdown__panel{display:flex;flex-direction:column;min-height:0;border:1px solid var(--md-border);border-radius:8px;background:var(--md-panel);overflow:hidden}.omni-markdown__panel[hidden]{display:none}.omni-markdown__panel-header{justify-content:space-between;padding:12px 14px;border-bottom:1px solid var(--md-border)}
6
+ .omni-markdown__preview{flex:1;min-height:0;overflow:auto;padding:22px;line-height:1.65}.omni-markdown__preview>:first-child{margin-top:0}.omni-markdown__preview>:last-child{margin-bottom:0}.omni-markdown__preview h1,.omni-markdown__preview h2,.omni-markdown__preview h3,.omni-markdown__preview h4{line-height:1.25;margin:1.35em 0 .65em}.omni-markdown__preview h1{font-size:28px;padding-bottom:8px;border-bottom:1px solid var(--md-border)}.omni-markdown__preview h2{font-size:22px;padding-bottom:6px;border-bottom:1px solid var(--md-border)}.omni-markdown__preview h3{font-size:18px}.omni-markdown__preview h4{font-size:15px}.omni-markdown__preview a{color:var(--omni-link,#4daafc)}.omni-markdown__preview p,.omni-markdown__preview ul,.omni-markdown__preview ol,.omni-markdown__preview blockquote,.omni-markdown__preview pre,.omni-markdown__preview table{margin:0 0 1em}.omni-markdown__preview blockquote{border-left:4px solid var(--md-border);padding:8px 14px;color:var(--md-muted)}.omni-markdown__preview code{font-family:var(--omni-mono,monospace);background:var(--md-code);border-radius:4px;padding:.15em .35em}.omni-markdown__preview pre{overflow:auto;background:var(--md-code);border-radius:8px;padding:14px}.omni-markdown__preview pre code{display:block;padding:0;background:transparent}.omni-markdown__preview table{width:100%;border-collapse:collapse;display:block;overflow:auto}.omni-markdown__preview th,.omni-markdown__preview td{border:1px solid var(--md-border);padding:7px 10px}.omni-markdown__preview img{max-width:100%;height:auto}
7
+ .omni-markdown__source{flex:1;width:100%;min-height:62vh;resize:none;border:0;outline:0;padding:16px;background:var(--omni-editor-bg,var(--omni-bg,#1e1e1e));color:inherit;font:13px/1.55 var(--omni-mono,monospace);tab-size:4}.omni-markdown__message{padding:10px 12px;border:1px solid var(--omni-error,#f44747);border-radius:6px;color:var(--omni-error,#f44747);white-space:pre-wrap}.omni-markdown__diagram{overflow:auto;margin:0 0 1em;padding:16px;border:1px solid var(--md-border);border-radius:8px;background:#fff;color:#111}.omni-markdown__diagram svg{display:block;max-width:100%;height:auto;margin:0 auto}.omni-markdown__diagram.is-invalid{color:var(--omni-error,#f44747);background:rgba(244,71,71,.1);white-space:pre-wrap}
8
+ .omni-markdown__math--display{display:block;margin:0 0 1em;text-align:center;overflow-x:auto}.omni-markdown__math.is-invalid{color:var(--omni-error,#f44747);font-family:var(--omni-mono,monospace);white-space:pre-wrap}
9
+ .omni-markdown__preview .hljs-comment,.omni-markdown__preview .hljs-quote{color:#6a9955;font-style:italic}.omni-markdown__preview .hljs-keyword,.omni-markdown__preview .hljs-selector-tag{color:#c586c0}.omni-markdown__preview .hljs-string,.omni-markdown__preview .hljs-regexp{color:#ce9178}.omni-markdown__preview .hljs-number,.omni-markdown__preview .hljs-literal{color:#b5cea8}.omni-markdown__preview .hljs-title,.omni-markdown__preview .hljs-section{color:#dcdcaa}.omni-markdown__preview .hljs-type,.omni-markdown__preview .hljs-built_in{color:#4ec9b0}.omni-markdown__preview .hljs-attr,.omni-markdown__preview .hljs-name{color:#9cdcfe}.omni-markdown__preview .hljs-meta,.omni-markdown__preview .hljs-symbol{color:#d7ba7d}
10
+ @media(max-width:760px){.omni-markdown__workspace.is-split{grid-template-columns:1fr}.omni-markdown__workspace.is-split .omni-markdown__source-panel,.omni-markdown__workspace.is-split .omni-markdown__preview-panel{grid-column:1;grid-row:auto}}
11
+ `;
@@ -0,0 +1,19 @@
1
+ import type { ClipboardService, HostContext } from '../../host/index.js';
2
+ import { type MountOptions, type ViewerHandle, type ViewerInput } from '../types.js';
3
+ export { parseMat } from '../../parsers/mat/index.js';
4
+ export type { MatDocument, MatTable, MatVariable } from '../../parsers/mat/index.js';
5
+ export { matViewerCss } from './styles.js';
6
+ export declare const MAT_VIEWER_META: {
7
+ id: string;
8
+ displayNameKey: string;
9
+ extensions: string[];
10
+ priority: number;
11
+ requiredServices: readonly [];
12
+ optionalServices: readonly ["clipboard"];
13
+ inputOwnership: "borrows";
14
+ };
15
+ export type MatViewerContext = HostContext & {
16
+ clipboard?: ClipboardService;
17
+ };
18
+ export declare const MAT_RENDER_ROW_LIMIT = 1000;
19
+ export declare function mountMatViewer(input: ViewerInput, container: HTMLElement, ctx: MatViewerContext, options?: MountOptions): Promise<ViewerHandle>;