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,120 @@
1
+ export declare const PDF_ZOOM_LEVELS: readonly [50, 75, 100, 125, 150, 200, 300];
2
+ export type PdfZoom = number;
3
+ export interface PdfTextAnnotation {
4
+ id: string;
5
+ kind: 'text';
6
+ page: number;
7
+ x: number;
8
+ y: number;
9
+ text: string;
10
+ size: number;
11
+ color: string;
12
+ /** Portable raster used when flattening text into an external PDF. */
13
+ rasterDataUrl?: string;
14
+ rasterWidth?: number;
15
+ rasterHeight?: number;
16
+ }
17
+ export interface PdfSignatureAnnotation {
18
+ id: string;
19
+ kind: 'signature';
20
+ page: number;
21
+ x: number;
22
+ y: number;
23
+ width: number;
24
+ height: number;
25
+ dataUrl: string;
26
+ }
27
+ /** One rectangle of a highlight, in unscaled page coordinates. */
28
+ export interface PdfHighlightRect {
29
+ x: number;
30
+ y: number;
31
+ width: number;
32
+ height: number;
33
+ }
34
+ /**
35
+ * PDF.js commonly returns one client rect per text span, even for a single
36
+ * continuous selection. Join neighbouring spans on the same text line so
37
+ * the highlight is rendered as one uninterrupted range (including spaces).
38
+ */
39
+ export declare function mergeHighlightRects(rects: readonly PdfHighlightRect[]): PdfHighlightRect[];
40
+ export interface PdfHighlightAnnotation {
41
+ id: string;
42
+ kind: 'highlight';
43
+ page: number;
44
+ /** A text selection can span several lines -> several rects. */
45
+ rects: PdfHighlightRect[];
46
+ color: string;
47
+ }
48
+ /** A text selection rendered as a horizontal strike through each line. */
49
+ export interface PdfStrikeoutAnnotation {
50
+ id: string;
51
+ kind: 'strikeout';
52
+ page: number;
53
+ rects: PdfHighlightRect[];
54
+ color: string;
55
+ }
56
+ /** A text selection rendered as an underline beneath each line. */
57
+ export interface PdfUnderlineAnnotation {
58
+ id: string;
59
+ kind: 'underline';
60
+ page: number;
61
+ rects: PdfHighlightRect[];
62
+ color: string;
63
+ }
64
+ export type PdfAnnotation = PdfTextAnnotation | PdfSignatureAnnotation | PdfHighlightAnnotation | PdfStrikeoutAnnotation | PdfUnderlineAnnotation;
65
+ export type PdfAnnotationInput = Omit<PdfTextAnnotation, 'id'> | Omit<PdfSignatureAnnotation, 'id'> | Omit<PdfHighlightAnnotation, 'id'> | Omit<PdfStrikeoutAnnotation, 'id'> | Omit<PdfUnderlineAnnotation, 'id'>;
66
+ export interface PdfViewState {
67
+ zoom: PdfZoom;
68
+ pageOrder: readonly number[];
69
+ annotations: readonly PdfAnnotation[];
70
+ selectedAnnotationId: string | null;
71
+ dirty: boolean;
72
+ }
73
+ export type PdfAction = {
74
+ type: 'zoom-in';
75
+ } | {
76
+ type: 'zoom-out';
77
+ } | {
78
+ type: 'set-zoom';
79
+ zoom: number;
80
+ } | {
81
+ type: 'reorder-pages';
82
+ from: number;
83
+ to: number;
84
+ } | {
85
+ type: 'delete-page';
86
+ page: number;
87
+ } | {
88
+ type: 'reset-pages';
89
+ } | {
90
+ type: 'add-annotation';
91
+ annotation: PdfAnnotationInput;
92
+ } | {
93
+ type: 'move-annotation';
94
+ id: string;
95
+ x: number;
96
+ y: number;
97
+ } | {
98
+ type: 'remove-annotation';
99
+ id: string;
100
+ } | {
101
+ type: 'select-annotation';
102
+ id: string | null;
103
+ } | {
104
+ type: 'undo';
105
+ } | {
106
+ type: 'redo';
107
+ } | {
108
+ type: 'mark-saved';
109
+ };
110
+ export interface PdfController {
111
+ readonly state: PdfViewState;
112
+ dispatch(action: PdfAction): void;
113
+ subscribe(listener: (state: PdfViewState) => void): () => void;
114
+ }
115
+ /** Persisted layer used to restore an editing session (sidecar rehydration). */
116
+ export interface PdfControllerSeed {
117
+ pageOrder?: readonly number[];
118
+ annotations?: readonly PdfAnnotation[];
119
+ }
120
+ export declare function createPdfController(pageCount: number, seed?: PdfControllerSeed): PdfController;
@@ -0,0 +1,191 @@
1
+ export const PDF_ZOOM_LEVELS = [50, 75, 100, 125, 150, 200, 300];
2
+ /**
3
+ * PDF.js commonly returns one client rect per text span, even for a single
4
+ * continuous selection. Join neighbouring spans on the same text line so
5
+ * the highlight is rendered as one uninterrupted range (including spaces).
6
+ */
7
+ export function mergeHighlightRects(rects) {
8
+ const rows = [];
9
+ for (const rect of [...rects].sort((a, b) => a.y - b.y || a.x - b.x)) {
10
+ const center = rect.y + rect.height / 2;
11
+ const row = rows.at(-1);
12
+ if (!row) {
13
+ rows.push([rect]);
14
+ continue;
15
+ }
16
+ const rowCenter = row.reduce((sum, item) => sum + item.y + item.height / 2, 0) / row.length;
17
+ const rowHeight = Math.max(...row.map((item) => item.height));
18
+ if (Math.abs(center - rowCenter) <= Math.max(2, Math.min(rect.height, rowHeight) / 2)) {
19
+ row.push(rect);
20
+ continue;
21
+ }
22
+ rows.push([rect]);
23
+ }
24
+ return rows.flatMap((row) => {
25
+ const merged = [];
26
+ for (const rect of row.sort((a, b) => a.x - b.x)) {
27
+ const previous = merged.at(-1);
28
+ const gap = Math.max(4, Math.min(16, rect.height * 0.9));
29
+ if (previous && rect.x <= previous.x + previous.width + gap) {
30
+ const right = Math.max(previous.x + previous.width, rect.x + rect.width);
31
+ const bottom = Math.max(previous.y + previous.height, rect.y + rect.height);
32
+ previous.x = Math.min(previous.x, rect.x);
33
+ previous.y = Math.min(previous.y, rect.y);
34
+ previous.width = right - previous.x;
35
+ previous.height = bottom - previous.y;
36
+ }
37
+ else {
38
+ merged.push({ ...rect });
39
+ }
40
+ }
41
+ return merged;
42
+ });
43
+ }
44
+ function nearestZoom(value) {
45
+ return PDF_ZOOM_LEVELS.reduce((best, candidate) => Math.abs(candidate - value) < Math.abs(best - value) ? candidate : best);
46
+ }
47
+ /** Highest `pdf-a<n>` suffix among seeded ids, so new ids never collide. */
48
+ function maxSequence(annotations) {
49
+ let max = 0;
50
+ for (const annotation of annotations) {
51
+ const n = /^pdf-a(\d+)$/.exec(annotation.id)?.[1];
52
+ if (n)
53
+ max = Math.max(max, Number(n));
54
+ }
55
+ return max;
56
+ }
57
+ function copyAnnotations(annotations) {
58
+ return annotations.map((annotation) => annotation.kind === 'highlight' || annotation.kind === 'strikeout' || annotation.kind === 'underline'
59
+ ? { ...annotation, rects: annotation.rects.map((rect) => ({ ...rect })) }
60
+ : { ...annotation });
61
+ }
62
+ export function createPdfController(pageCount, seed) {
63
+ const original = Array.from({ length: Math.max(0, Math.floor(pageCount)) }, (_, i) => i + 1);
64
+ const listeners = new Set();
65
+ let zoom = 100;
66
+ // A seeded order may only reference pages that still exist; an empty result
67
+ // falls back to the natural order so the document is never left blank.
68
+ const seededOrder = seed?.pageOrder?.filter((page) => page >= 1 && page <= original.length) ?? [];
69
+ let pageOrder = seededOrder.length > 0 ? seededOrder.slice() : original.slice();
70
+ let annotations = seed?.annotations
71
+ ? seed.annotations.filter((a) => pageOrder.includes(a.page)).map((a) => ({ ...a }))
72
+ : [];
73
+ let selectedAnnotationId = null;
74
+ let savedSignature = '';
75
+ let sequence = maxSequence(annotations);
76
+ const undoStack = [];
77
+ const redoStack = [];
78
+ const signature = () => JSON.stringify({ pageOrder, annotations });
79
+ const snapshot = () => ({
80
+ pageOrder: pageOrder.slice(),
81
+ annotations: copyAnnotations(annotations),
82
+ selectedAnnotationId
83
+ });
84
+ const restore = (value) => {
85
+ pageOrder = value.pageOrder.slice();
86
+ annotations = copyAnnotations(value.annotations);
87
+ selectedAnnotationId = value.selectedAnnotationId;
88
+ };
89
+ const state = () => ({
90
+ zoom, pageOrder: pageOrder.slice(), annotations: copyAnnotations(annotations),
91
+ selectedAnnotationId, dirty: signature() !== savedSignature
92
+ });
93
+ const emit = () => { const next = state(); for (const listener of listeners)
94
+ listener(next); };
95
+ savedSignature = signature();
96
+ return {
97
+ get state() { return state(); },
98
+ subscribe(listener) { listeners.add(listener); return () => listeners.delete(listener); },
99
+ dispatch(action) {
100
+ if (action.type === 'undo') {
101
+ const previous = undoStack.pop();
102
+ if (!previous)
103
+ return;
104
+ redoStack.push(snapshot());
105
+ restore(previous);
106
+ emit();
107
+ return;
108
+ }
109
+ if (action.type === 'redo') {
110
+ const next = redoStack.pop();
111
+ if (!next)
112
+ return;
113
+ undoStack.push(snapshot());
114
+ restore(next);
115
+ emit();
116
+ return;
117
+ }
118
+ const tracksHistory = action.type === 'reorder-pages'
119
+ || action.type === 'delete-page'
120
+ || action.type === 'reset-pages'
121
+ || action.type === 'add-annotation'
122
+ || action.type === 'move-annotation'
123
+ || action.type === 'remove-annotation';
124
+ const before = tracksHistory ? snapshot() : undefined;
125
+ const beforeSignature = tracksHistory ? signature() : undefined;
126
+ switch (action.type) {
127
+ case 'zoom-in': {
128
+ zoom = PDF_ZOOM_LEVELS.find((level) => level > zoom)
129
+ ?? PDF_ZOOM_LEVELS[PDF_ZOOM_LEVELS.length - 1];
130
+ break;
131
+ }
132
+ case 'zoom-out': {
133
+ zoom = [...PDF_ZOOM_LEVELS].reverse().find((level) => level < zoom)
134
+ ?? PDF_ZOOM_LEVELS[0];
135
+ break;
136
+ }
137
+ case 'set-zoom': {
138
+ if (!Number.isFinite(action.zoom))
139
+ return;
140
+ zoom = Math.max(25, Math.min(400, Math.round(action.zoom)));
141
+ break;
142
+ }
143
+ case 'reorder-pages': {
144
+ if (!Number.isInteger(action.from) || !Number.isInteger(action.to) || action.from < 0 || action.to < 0 || action.from >= pageOrder.length || action.to >= pageOrder.length)
145
+ return;
146
+ const [page] = pageOrder.splice(action.from, 1);
147
+ if (page !== undefined)
148
+ pageOrder.splice(action.to, 0, page);
149
+ break;
150
+ }
151
+ case 'delete-page':
152
+ if (pageOrder.length <= 1)
153
+ return;
154
+ pageOrder = pageOrder.filter((page) => page !== action.page);
155
+ annotations = annotations.filter((annotation) => annotation.page !== action.page);
156
+ break;
157
+ case 'reset-pages':
158
+ pageOrder = original.slice();
159
+ annotations = [];
160
+ selectedAnnotationId = null;
161
+ break;
162
+ case 'add-annotation': {
163
+ const annotation = action.annotation.kind === 'text'
164
+ ? { ...action.annotation, id: `pdf-a${++sequence}` }
165
+ : { ...action.annotation, id: `pdf-a${++sequence}` };
166
+ annotations = [...annotations, annotation];
167
+ break;
168
+ }
169
+ case 'move-annotation':
170
+ annotations = annotations.map((a) => a.id === action.id ? { ...a, x: action.x, y: action.y } : a);
171
+ break;
172
+ case 'remove-annotation':
173
+ annotations = annotations.filter((a) => a.id !== action.id);
174
+ if (selectedAnnotationId === action.id)
175
+ selectedAnnotationId = null;
176
+ break;
177
+ case 'select-annotation':
178
+ selectedAnnotationId = action.id;
179
+ break;
180
+ case 'mark-saved':
181
+ savedSignature = signature();
182
+ break;
183
+ }
184
+ if (before && beforeSignature !== signature()) {
185
+ undoStack.push(before);
186
+ redoStack.length = 0;
187
+ }
188
+ emit();
189
+ }
190
+ };
191
+ }
@@ -0,0 +1,26 @@
1
+ import { type PdfAnnotation, type PdfViewState } from './controller.js';
2
+ /** Type-only reference — erased at compile time. */
3
+ export type PdfLibModule = typeof import('pdf-lib');
4
+ export declare const SIDECAR_LAYER_NAME = "omni-viewer-layer.json";
5
+ export declare const SIDECAR_ORIGINAL_NAME = "omni-viewer-original.pdf";
6
+ /** Result of parsing a sidecar's layer JSON. */
7
+ export interface ParsedLayer {
8
+ pageOrder: number[];
9
+ annotations: PdfAnnotation[];
10
+ }
11
+ /** Persist reordered/deleted pages plus the text/signature overlays,
12
+ * flattened into the page content (portable, non-editable output). */
13
+ export declare function buildEditedPdf(pdfLib: PdfLibModule, source: Uint8Array, state: PdfViewState): Promise<Uint8Array>;
14
+ /**
15
+ * Like {@link buildEditedPdf}, but also embeds the hybrid sidecar so the
16
+ * omni viewer can rehydrate a removable overlay layer on reopen:
17
+ * - the pristine (unflattened) source, and
18
+ * - the layer JSON `{ version, pageOrder, annotations }`.
19
+ * External readers only ever see the flattened pages.
20
+ */
21
+ export declare function buildSavedPdf(pdfLib: PdfLibModule, pristine: Uint8Array, state: PdfViewState): Promise<Uint8Array>;
22
+ /** Parse and validate a sidecar layer JSON string; null if unusable. */
23
+ export declare function parseLayer(text: string): ParsedLayer | null;
24
+ /** Append every page of `second` after `first`. */
25
+ export declare function mergePdfBytes(pdfLib: PdfLibModule, first: Uint8Array, second: Uint8Array): Promise<Uint8Array>;
26
+ export declare function savedPdfName(name: string): string;
@@ -0,0 +1,265 @@
1
+ // PDF editing helpers built on pdf-lib.
2
+ //
3
+ // pdf-lib is an optional peer dependency: this module never imports it at
4
+ // runtime (ADR 14 — the base viewer entry must stay free of external
5
+ // imports). Callers inject the loaded module; `viewers/pdf/self-loading`
6
+ // provides the dynamic-import loader for platforms whose bundler resolves it.
7
+ import { mergeHighlightRects } from './controller.js';
8
+ // Hybrid sidecar: saved PDFs keep flattened (portable) pages while embedding
9
+ // the pristine source + a layer JSON, so the omni viewer can restore a
10
+ // removable overlay layer on reopen. External readers only see the flat pages.
11
+ export const SIDECAR_LAYER_NAME = 'omni-viewer-layer.json';
12
+ export const SIDECAR_ORIGINAL_NAME = 'omni-viewer-original.pdf';
13
+ /** Bumped when the sidecar shape changes; older/newer versions are ignored. */
14
+ const SIDECAR_VERSION = 1;
15
+ /** Defensive ceilings — the sidecar is untrusted input on reopen. */
16
+ const MAX_ANNOTATIONS = 2000;
17
+ const MAX_TEXT_LENGTH = 10_000;
18
+ const MAX_DATAURL_LENGTH = 4_000_000;
19
+ const MAX_HIGHLIGHT_RECTS = 500;
20
+ function parseColor(pdfLib, value) {
21
+ const hex = /^#?([0-9a-f]{6})$/i.exec(value)?.[1] ?? '000000';
22
+ return pdfLib.rgb(parseInt(hex.slice(0, 2), 16) / 255, parseInt(hex.slice(2, 4), 16) / 255, parseInt(hex.slice(4, 6), 16) / 255);
23
+ }
24
+ function pngBytes(dataUrl) {
25
+ const encoded = /^data:image\/png;base64,(.*)$/i.exec(dataUrl)?.[1];
26
+ if (!encoded)
27
+ return undefined;
28
+ const binary = atob(encoded);
29
+ return Uint8Array.from(binary, (c) => c.charCodeAt(0));
30
+ }
31
+ async function stamp(pdfLib, page, annotation) {
32
+ const { height } = page.getSize();
33
+ if (annotation.kind === 'text') {
34
+ if (annotation.rasterDataUrl && annotation.rasterWidth && annotation.rasterHeight) {
35
+ const bytes = pngBytes(annotation.rasterDataUrl);
36
+ if (bytes) {
37
+ const image = await page.doc.embedPng(bytes);
38
+ page.drawImage(image, {
39
+ x: annotation.x,
40
+ y: height - annotation.y - annotation.rasterHeight,
41
+ width: annotation.rasterWidth,
42
+ height: annotation.rasterHeight
43
+ });
44
+ return;
45
+ }
46
+ }
47
+ const font = await page.doc.embedFont(pdfLib.StandardFonts.Helvetica);
48
+ page.drawText(annotation.text, {
49
+ x: annotation.x,
50
+ y: height - annotation.y - annotation.size,
51
+ size: annotation.size,
52
+ font,
53
+ color: parseColor(pdfLib, annotation.color)
54
+ });
55
+ return;
56
+ }
57
+ if (annotation.kind === 'highlight') {
58
+ const color = parseColor(pdfLib, annotation.color);
59
+ for (const rect of mergeHighlightRects(annotation.rects)) {
60
+ page.drawRectangle({
61
+ x: rect.x,
62
+ y: height - rect.y - rect.height,
63
+ width: rect.width,
64
+ height: rect.height,
65
+ color,
66
+ // Multiply keeps the underlying text legible through the tint.
67
+ blendMode: pdfLib.BlendMode.Multiply
68
+ });
69
+ }
70
+ return;
71
+ }
72
+ if (annotation.kind === 'strikeout') {
73
+ const color = parseColor(pdfLib, annotation.color);
74
+ for (const rect of mergeHighlightRects(annotation.rects)) {
75
+ page.drawLine({
76
+ start: { x: rect.x, y: height - rect.y - rect.height / 2 },
77
+ end: { x: rect.x + rect.width, y: height - rect.y - rect.height / 2 },
78
+ thickness: Math.max(1, rect.height * 0.08),
79
+ color
80
+ });
81
+ }
82
+ return;
83
+ }
84
+ if (annotation.kind === 'underline') {
85
+ const color = parseColor(pdfLib, annotation.color);
86
+ for (const rect of mergeHighlightRects(annotation.rects)) {
87
+ page.drawLine({
88
+ start: { x: rect.x, y: height - rect.y - rect.height * 0.1 },
89
+ end: { x: rect.x + rect.width, y: height - rect.y - rect.height * 0.1 },
90
+ thickness: Math.max(1, rect.height * 0.08),
91
+ color
92
+ });
93
+ }
94
+ return;
95
+ }
96
+ const bytes = pngBytes(annotation.dataUrl);
97
+ if (!bytes)
98
+ return;
99
+ const image = await page.doc.embedPng(bytes);
100
+ page.drawImage(image, {
101
+ x: annotation.x,
102
+ y: height - annotation.y - annotation.height,
103
+ width: annotation.width,
104
+ height: annotation.height
105
+ });
106
+ }
107
+ /** Reorder/delete pages and stamp the overlays into a fresh (unsaved) doc. */
108
+ async function flattenInto(pdfLib, source, state) {
109
+ const original = await pdfLib.PDFDocument.load(source);
110
+ const output = await pdfLib.PDFDocument.create();
111
+ const indices = state.pageOrder
112
+ .map((page) => page - 1)
113
+ .filter((page) => page >= 0 && page < original.getPageCount());
114
+ const copied = await output.copyPages(original, indices);
115
+ copied.forEach((page) => output.addPage(page));
116
+ for (const annotation of state.annotations) {
117
+ const outputIndex = state.pageOrder.indexOf(annotation.page);
118
+ const page = output.getPages()[outputIndex];
119
+ if (page)
120
+ await stamp(pdfLib, page, annotation);
121
+ }
122
+ return output;
123
+ }
124
+ /** Persist reordered/deleted pages plus the text/signature overlays,
125
+ * flattened into the page content (portable, non-editable output). */
126
+ export async function buildEditedPdf(pdfLib, source, state) {
127
+ const output = await flattenInto(pdfLib, source, state);
128
+ return output.save();
129
+ }
130
+ /**
131
+ * Like {@link buildEditedPdf}, but also embeds the hybrid sidecar so the
132
+ * omni viewer can rehydrate a removable overlay layer on reopen:
133
+ * - the pristine (unflattened) source, and
134
+ * - the layer JSON `{ version, pageOrder, annotations }`.
135
+ * External readers only ever see the flattened pages.
136
+ */
137
+ export async function buildSavedPdf(pdfLib, pristine, state) {
138
+ const output = await flattenInto(pdfLib, pristine, state);
139
+ const layer = JSON.stringify({
140
+ version: SIDECAR_VERSION,
141
+ pageOrder: state.pageOrder,
142
+ annotations: state.annotations
143
+ });
144
+ await output.attach(new TextEncoder().encode(layer), SIDECAR_LAYER_NAME, {
145
+ mimeType: 'application/json'
146
+ });
147
+ await output.attach(pristine, SIDECAR_ORIGINAL_NAME, {
148
+ mimeType: 'application/pdf'
149
+ });
150
+ return output.save();
151
+ }
152
+ function toAnnotation(raw) {
153
+ if (!raw || typeof raw !== 'object')
154
+ return null;
155
+ const a = raw;
156
+ const num = (v) => typeof v === 'number' && Number.isFinite(v);
157
+ if (typeof a.id !== 'string' || !Number.isInteger(a.page) || a.page < 1)
158
+ return null;
159
+ if (a.kind === 'text') {
160
+ if (!num(a.x) || !num(a.y))
161
+ return null;
162
+ if (typeof a.text !== 'string' || a.text.length > MAX_TEXT_LENGTH)
163
+ return null;
164
+ if (!num(a.size) || typeof a.color !== 'string')
165
+ return null;
166
+ return {
167
+ id: a.id, kind: 'text', page: a.page,
168
+ x: a.x, y: a.y, text: a.text, size: a.size, color: a.color,
169
+ ...(typeof a.rasterDataUrl === 'string'
170
+ && /^data:image\/png;base64,/i.test(a.rasterDataUrl)
171
+ && num(a.rasterWidth) && num(a.rasterHeight)
172
+ ? {
173
+ rasterDataUrl: a.rasterDataUrl,
174
+ rasterWidth: a.rasterWidth,
175
+ rasterHeight: a.rasterHeight
176
+ }
177
+ : {})
178
+ };
179
+ }
180
+ if (a.kind === 'signature') {
181
+ if (!num(a.x) || !num(a.y))
182
+ return null;
183
+ if (typeof a.dataUrl !== 'string' || a.dataUrl.length > MAX_DATAURL_LENGTH)
184
+ return null;
185
+ if (!/^data:image\/png;base64,/i.test(a.dataUrl))
186
+ return null;
187
+ if (!num(a.width) || !num(a.height))
188
+ return null;
189
+ return {
190
+ id: a.id, kind: 'signature', page: a.page,
191
+ x: a.x, y: a.y, width: a.width, height: a.height, dataUrl: a.dataUrl
192
+ };
193
+ }
194
+ if (a.kind === 'highlight' || a.kind === 'strikeout' || a.kind === 'underline') {
195
+ if (typeof a.color !== 'string' || !Array.isArray(a.rects))
196
+ return null;
197
+ const rects = [];
198
+ for (const r of a.rects.slice(0, MAX_HIGHLIGHT_RECTS)) {
199
+ if (!r || typeof r !== 'object')
200
+ continue;
201
+ const rr = r;
202
+ if (num(rr.x) && num(rr.y) && num(rr.width) && num(rr.height)) {
203
+ rects.push({ x: rr.x, y: rr.y, width: rr.width, height: rr.height });
204
+ }
205
+ }
206
+ if (rects.length === 0)
207
+ return null;
208
+ return { id: a.id, kind: a.kind, page: a.page, rects, color: a.color };
209
+ }
210
+ return null;
211
+ }
212
+ /** Parse and validate a sidecar layer JSON string; null if unusable. */
213
+ export function parseLayer(text) {
214
+ let raw;
215
+ try {
216
+ raw = JSON.parse(text);
217
+ }
218
+ catch {
219
+ return null;
220
+ }
221
+ if (!raw || typeof raw !== 'object')
222
+ return null;
223
+ const obj = raw;
224
+ if (obj.version !== SIDECAR_VERSION)
225
+ return null;
226
+ const pageOrder = Array.isArray(obj.pageOrder)
227
+ ? obj.pageOrder.filter((n) => Number.isInteger(n) && n > 0)
228
+ : [];
229
+ const annotationsRaw = Array.isArray(obj.annotations)
230
+ ? obj.annotations.slice(0, MAX_ANNOTATIONS)
231
+ : [];
232
+ const annotations = [];
233
+ for (const entry of annotationsRaw) {
234
+ const parsed = toAnnotation(entry);
235
+ if (parsed)
236
+ annotations.push(parsed);
237
+ }
238
+ if (pageOrder.length === 0 && annotations.length === 0)
239
+ return null;
240
+ return { pageOrder, annotations };
241
+ }
242
+ /** Append every page of `second` after `first`. */
243
+ export async function mergePdfBytes(pdfLib, first, second) {
244
+ const [left, right] = await Promise.all([
245
+ pdfLib.PDFDocument.load(first),
246
+ pdfLib.PDFDocument.load(second)
247
+ ]);
248
+ const output = await pdfLib.PDFDocument.create();
249
+ for (const source of [left, right]) {
250
+ // pdf-lib's addPage takes a single page — spreading silently drops
251
+ // all but the first one.
252
+ for (const page of await output.copyPages(source, source.getPageIndices())) {
253
+ output.addPage(page);
254
+ }
255
+ }
256
+ return output.save();
257
+ }
258
+ export function savedPdfName(name) {
259
+ // The host can supply a page/URL-like name (for example `viewer.html`
260
+ // or `report.pdf?token=...`). Keep only the final path component and
261
+ // replace its extension, so Save As is always a real `.pdf` download.
262
+ const leaf = name.trim().split(/[\\/]/).pop()?.split(/[?#]/, 1)[0] ?? '';
263
+ const stem = leaf.replace(/\.[^.]*$/, '') || 'document';
264
+ return `${stem}-edited.pdf`;
265
+ }
@@ -0,0 +1,88 @@
1
+ import type { FilePickService, FileSaveService, FileWritebackService, HostContext } from '../../host/index.js';
2
+ import { type MountOptions, type ViewerHandle, type ViewerInput } from '../types.js';
3
+ import { type PdfController } from './controller.js';
4
+ import { type PdfLibModule } from './editing.js';
5
+ export { createPdfController, PDF_ZOOM_LEVELS } from './controller.js';
6
+ export type { PdfController, PdfAction, PdfViewState, PdfAnnotation } from './controller.js';
7
+ export { pdfViewerCss } from './styles.js';
8
+ export { buildEditedPdf, mergePdfBytes, savedPdfName } from './editing.js';
9
+ export type { PdfLibModule } from './editing.js';
10
+ /** Viewer metadata — single source for the registry codegen (DESIGN.md §7). */
11
+ export declare const PDF_VIEWER_META: {
12
+ id: string;
13
+ displayNameKey: string;
14
+ extensions: string[];
15
+ priority: number;
16
+ requiredServices: readonly [];
17
+ optionalServices: readonly ["save", "writeback", "filePick"];
18
+ inputOwnership: "borrows";
19
+ };
20
+ export type PdfViewerContext = HostContext & {
21
+ save?: FileSaveService;
22
+ writeback?: FileWritebackService;
23
+ filePick?: FilePickService;
24
+ };
25
+ /** Opaque pdf.js viewport — passed straight back to render()/TextLayer. */
26
+ export type PdfJsViewport = {
27
+ width: number;
28
+ height: number;
29
+ };
30
+ export interface PdfJsPage {
31
+ getViewport(options: {
32
+ scale: number;
33
+ }): PdfJsViewport;
34
+ render(options: {
35
+ canvasContext: CanvasRenderingContext2D;
36
+ viewport: unknown;
37
+ }): {
38
+ promise: Promise<void>;
39
+ cancel(): void;
40
+ };
41
+ /** Text runs + geometry, fed as-is into TextLayer as textContentSource. */
42
+ getTextContent(): Promise<unknown>;
43
+ }
44
+ /** pdf.js v4 TextLayer — positions transparent, selectable spans over canvas. */
45
+ export interface PdfJsTextLayer {
46
+ render(): Promise<void>;
47
+ cancel(): void;
48
+ }
49
+ export interface PdfJsDocument {
50
+ numPages: number;
51
+ getPage(n: number): Promise<PdfJsPage>;
52
+ destroy(): Promise<void>;
53
+ /** Embedded files keyed by name; used to read the hybrid sidecar. */
54
+ getAttachments?(): Promise<Record<string, {
55
+ filename: string;
56
+ content: Uint8Array;
57
+ }> | null>;
58
+ }
59
+ export interface PdfJsLoadingTask {
60
+ promise: Promise<PdfJsDocument>;
61
+ destroy(): void;
62
+ }
63
+ export interface PdfJsModule {
64
+ getDocument(options: {
65
+ data: Uint8Array;
66
+ password?: string;
67
+ }): PdfJsLoadingTask;
68
+ GlobalWorkerOptions: {
69
+ workerSrc: string;
70
+ };
71
+ TextLayer: new (options: {
72
+ textContentSource: unknown;
73
+ container: HTMLElement;
74
+ viewport: unknown;
75
+ }) => PdfJsTextLayer;
76
+ }
77
+ /** External modules the viewer needs, injected by the adapter (ADR 14). */
78
+ export interface PdfViewerDeps {
79
+ loadPdfjs(): Promise<PdfJsModule>;
80
+ /** Editing dependency (save / save-as / merge / annotation stamping).
81
+ * Absent -> editing controls disabled with a reason. */
82
+ loadPdfLib?(): Promise<PdfLibModule>;
83
+ }
84
+ export interface PdfViewerHandle extends ViewerHandle {
85
+ readonly controller: PdfController;
86
+ isDirty(): boolean;
87
+ }
88
+ export declare function mountPdfViewer(input: ViewerInput, container: HTMLElement, ctx: PdfViewerContext, deps: PdfViewerDeps, options?: MountOptions): Promise<PdfViewerHandle>;