web-doc 0.3.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.
- package/LICENSE-APACHE +201 -0
- package/LICENSE-MIT +21 -0
- package/README.md +148 -0
- package/THIRD_PARTY_NOTICES.md +20 -0
- package/bin/copy-assets.mjs +27 -0
- package/dist/abort.d.ts +1 -0
- package/dist/abort.js +18 -0
- package/dist/adapters/bitmap.d.ts +9 -0
- package/dist/adapters/bitmap.js +63 -0
- package/dist/adapters/csv-parser.d.ts +7 -0
- package/dist/adapters/csv-parser.js +124 -0
- package/dist/adapters/csv.d.ts +26 -0
- package/dist/adapters/csv.js +231 -0
- package/dist/adapters/image.d.ts +41 -0
- package/dist/adapters/image.js +198 -0
- package/dist/adapters/office.d.ts +211 -0
- package/dist/adapters/office.js +672 -0
- package/dist/adapters/pdf.d.ts +32 -0
- package/dist/adapters/pdf.js +429 -0
- package/dist/adapters/svg.d.ts +17 -0
- package/dist/adapters/svg.js +123 -0
- package/dist/assets/image/index.d.ts +75 -0
- package/dist/assets/image/index.js +289 -0
- package/dist/assets/image/index_bg.wasm +0 -0
- package/dist/assets/image/index_bg.wasm.d.ts +12 -0
- package/dist/assets/legacy/index.d.ts +54 -0
- package/dist/assets/legacy/index.js +306 -0
- package/dist/assets/legacy/index_bg.wasm +0 -0
- package/dist/assets/legacy/index_bg.wasm.d.ts +9 -0
- package/dist/assets/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/78-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/78-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Add-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Add-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/B5-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/B5-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/B5pc-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/B5pc-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/CNS1-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/CNS1-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/CNS2-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/CNS2-V.bcmap +3 -0
- package/dist/assets/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/ETenms-B5-H.bcmap +3 -0
- package/dist/assets/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/EUC-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/EUC-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Ext-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Ext-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/GB-H.bcmap +4 -0
- package/dist/assets/pdfjs/cmaps/GB-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/GBT-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/GBT-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Hankaku.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Hiragana.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/KSC-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/KSC-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Katakana.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/LICENSE +36 -0
- package/dist/assets/pdfjs/cmaps/NWP-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/NWP-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/Roman.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/V.bcmap +0 -0
- package/dist/assets/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
- package/dist/assets/pdfjs/iccs/CGATS001Compat-v2-micro.icc +0 -0
- package/dist/assets/pdfjs/iccs/LICENSE +116 -0
- package/dist/assets/pdfjs/standard_fonts/FoxitDingbats.pfb +0 -0
- package/dist/assets/pdfjs/standard_fonts/FoxitFixed.pfb +0 -0
- package/dist/assets/pdfjs/standard_fonts/FoxitFixedBold.pfb +0 -0
- package/dist/assets/pdfjs/standard_fonts/FoxitFixedBoldItalic.pfb +0 -0
- package/dist/assets/pdfjs/standard_fonts/FoxitFixedItalic.pfb +0 -0
- package/dist/assets/pdfjs/standard_fonts/FoxitSerif.pfb +0 -0
- package/dist/assets/pdfjs/standard_fonts/FoxitSerifBold.pfb +0 -0
- package/dist/assets/pdfjs/standard_fonts/FoxitSerifBoldItalic.pfb +0 -0
- package/dist/assets/pdfjs/standard_fonts/FoxitSerifItalic.pfb +0 -0
- package/dist/assets/pdfjs/standard_fonts/FoxitSymbol.pfb +0 -0
- package/dist/assets/pdfjs/standard_fonts/LICENSE_FOXIT +27 -0
- package/dist/assets/pdfjs/standard_fonts/LICENSE_LIBERATION +102 -0
- package/dist/assets/pdfjs/standard_fonts/LiberationSans-Bold.ttf +0 -0
- package/dist/assets/pdfjs/standard_fonts/LiberationSans-BoldItalic.ttf +0 -0
- package/dist/assets/pdfjs/standard_fonts/LiberationSans-Italic.ttf +0 -0
- package/dist/assets/pdfjs/standard_fonts/LiberationSans-Regular.ttf +0 -0
- package/dist/assets/pdfjs/wasm/LICENSE_JBIG2 +196 -0
- package/dist/assets/pdfjs/wasm/LICENSE_OPENJPEG +39 -0
- package/dist/assets/pdfjs/wasm/LICENSE_PDFJS_JBIG2 +13 -0
- package/dist/assets/pdfjs/wasm/LICENSE_PDFJS_OPENJPEG +22 -0
- package/dist/assets/pdfjs/wasm/LICENSE_PDFJS_QCMS +22 -0
- package/dist/assets/pdfjs/wasm/LICENSE_QCMS +21 -0
- package/dist/assets/pdfjs/wasm/jbig2.wasm +0 -0
- package/dist/assets/pdfjs/wasm/jbig2_nowasm_fallback.js +15 -0
- package/dist/assets/pdfjs/wasm/openjpeg.wasm +0 -0
- package/dist/assets/pdfjs/wasm/openjpeg_nowasm_fallback.js +17 -0
- package/dist/assets/pdfjs/wasm/qcms_bg.wasm +0 -0
- package/dist/assets/pdfjs/wasm/quickjs-eval.js +16 -0
- package/dist/assets/pdfjs/wasm/quickjs-eval.wasm +0 -0
- package/dist/client.d.ts +20 -0
- package/dist/client.js +82 -0
- package/dist/contracts.d.ts +379 -0
- package/dist/contracts.js +22 -0
- package/dist/csv-worker.d.ts +1 -0
- package/dist/csv-worker.js +17 -0
- package/dist/detect.d.ts +15 -0
- package/dist/detect.js +290 -0
- package/dist/errors.d.ts +14 -0
- package/dist/errors.js +40 -0
- package/dist/font-manifest.d.ts +11 -0
- package/dist/font-manifest.js +31 -0
- package/dist/fonts/OFL-1.1.txt +88 -0
- package/dist/fonts/THIRD_PARTY_NOTICES.md +10 -0
- package/dist/fonts/manifest.json +83 -0
- package/dist/fonts/noto-sans-arabic.woff2 +0 -0
- package/dist/fonts/noto-sans-bengali.woff2 +0 -0
- package/dist/fonts/noto-sans-cjk.woff2 +0 -0
- package/dist/fonts/noto-sans-devanagari.woff2 +0 -0
- package/dist/fonts/noto-sans-gujarati.woff2 +0 -0
- package/dist/fonts/noto-sans-gurmukhi.woff2 +0 -0
- package/dist/fonts/noto-sans-japanese.woff2 +0 -0
- package/dist/fonts/noto-sans-kannada.woff2 +0 -0
- package/dist/fonts/noto-sans-korean.woff2 +0 -0
- package/dist/fonts/noto-sans-latin-cyrillic.woff2 +0 -0
- package/dist/fonts/noto-sans-malayalam.woff2 +0 -0
- package/dist/fonts/noto-sans-odia.woff2 +0 -0
- package/dist/fonts/noto-sans-tamil.woff2 +0 -0
- package/dist/fonts/noto-sans-telugu.woff2 +0 -0
- package/dist/fonts.d.ts +20 -0
- package/dist/fonts.js +238 -0
- package/dist/format.d.ts +1 -0
- package/dist/format.js +1 -0
- package/dist/headless.d.ts +18 -0
- package/dist/headless.js +18 -0
- package/dist/i18n.d.ts +4 -0
- package/dist/i18n.js +55 -0
- package/dist/image-worker.d.ts +1 -0
- package/dist/image-worker.js +41 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +29 -0
- package/dist/interaction.d.ts +24 -0
- package/dist/interaction.js +183 -0
- package/dist/legacy-converter-worker.d.ts +1 -0
- package/dist/legacy-converter-worker.js +19 -0
- package/dist/limits.d.ts +4 -0
- package/dist/limits.js +162 -0
- package/dist/registry.d.ts +8 -0
- package/dist/registry.js +35 -0
- package/dist/render-scheduler.d.ts +8 -0
- package/dist/render-scheduler.js +63 -0
- package/dist/source.d.ts +14 -0
- package/dist/source.js +116 -0
- package/dist/spreadsheet-viewport.d.ts +34 -0
- package/dist/spreadsheet-viewport.js +1035 -0
- package/dist/styles.css +137 -0
- package/dist/ui-styles.d.ts +1 -0
- package/dist/ui-styles.js +139 -0
- package/dist/ui.d.ts +8 -0
- package/dist/ui.js +390 -0
- package/dist/viewer.d.ts +52 -0
- package/dist/viewer.js +901 -0
- package/dist/viewport.d.ts +54 -0
- package/dist/viewport.js +907 -0
- package/dist/worker-adapter.d.ts +24 -0
- package/dist/worker-adapter.js +97 -0
- package/dist/worker-client.d.ts +23 -0
- package/dist/worker-client.js +105 -0
- package/dist/worker-endpoint.d.ts +13 -0
- package/dist/worker-endpoint.js +57 -0
- package/dist/worker-protocol.d.ts +48 -0
- package/dist/worker-protocol.js +14 -0
- package/dist/worker.d.ts +4 -0
- package/dist/worker.js +4 -0
- package/dist/workers/csv-worker.js +160 -0
- package/dist/workers/image-worker.js +41 -0
- package/dist/workers/legacy-converter-worker.js +19 -0
- package/dist/workers/pdf.worker.min.mjs +28 -0
- package/package.json +74 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { AdapterOpenContext, DocumentAdapter, DocumentInfo, PageSize, RenderViewport, TextRun } from "../contracts.js";
|
|
2
|
+
export interface PdfBackend {
|
|
3
|
+
readonly pageCount: number;
|
|
4
|
+
pageSize?(pageIndex: number, signal?: AbortSignal): PageSize | Promise<PageSize>;
|
|
5
|
+
renderPage(target: HTMLCanvasElement | OffscreenCanvas, pageIndex: number, zoom: number, devicePixelRatio: number, signal?: AbortSignal): Promise<void>;
|
|
6
|
+
pageText(pageIndex: number, signal?: AbortSignal): Promise<readonly TextRun[]>;
|
|
7
|
+
close(): void | Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export interface PdfAdapterOptions {
|
|
10
|
+
readonly workerUrl?: string | URL;
|
|
11
|
+
readonly cMapUrl?: string | URL;
|
|
12
|
+
readonly standardFontDataUrl?: string | URL;
|
|
13
|
+
readonly wasmUrl?: string | URL;
|
|
14
|
+
readonly iccUrl?: string | URL;
|
|
15
|
+
readonly open?: (data: Uint8Array, context: AdapterOpenContext) => Promise<PdfBackend>;
|
|
16
|
+
}
|
|
17
|
+
interface PdfHandle {
|
|
18
|
+
readonly backend: PdfBackend;
|
|
19
|
+
}
|
|
20
|
+
export declare class PdfDocumentAdapter implements DocumentAdapter<PdfHandle> {
|
|
21
|
+
#private;
|
|
22
|
+
readonly id = "pdf";
|
|
23
|
+
readonly formats: readonly ["pdf"];
|
|
24
|
+
constructor(options?: PdfAdapterOptions);
|
|
25
|
+
open(data: Uint8Array, context: AdapterOpenContext): Promise<PdfHandle>;
|
|
26
|
+
getInfo(handle: PdfHandle): Promise<DocumentInfo>;
|
|
27
|
+
render(handle: PdfHandle, target: HTMLCanvasElement | OffscreenCanvas, viewport: RenderViewport, signal?: AbortSignal): Promise<void>;
|
|
28
|
+
getTextMap(handle: PdfHandle, pageIndex: number, signal?: AbortSignal): Promise<readonly TextRun[]>;
|
|
29
|
+
close(handle: PdfHandle): Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
export declare function createPdfAdapter(options?: PdfAdapterOptions): PdfDocumentAdapter;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
import { abortError, ViewerError } from "../errors.js";
|
|
2
|
+
// Preserve the public zoom=1 contract: one PDF point maps to one renderer CSS
|
|
3
|
+
// pixel. Per-page geometry still prevents the viewport from coercing pages to
|
|
4
|
+
// A4 or changing their width while virtualizing.
|
|
5
|
+
const CSS_UNITS = 1;
|
|
6
|
+
export class PdfDocumentAdapter {
|
|
7
|
+
id = "pdf";
|
|
8
|
+
formats = ["pdf"];
|
|
9
|
+
#options;
|
|
10
|
+
constructor(options = {}) {
|
|
11
|
+
this.#options = options;
|
|
12
|
+
}
|
|
13
|
+
async open(data, context) {
|
|
14
|
+
context.reportProgress({ phase: "parsing", loaded: 0, total: 1 });
|
|
15
|
+
try {
|
|
16
|
+
const backend = this.#options.open
|
|
17
|
+
? await this.#options.open(data, context)
|
|
18
|
+
: await PdfJsBackend.open(data, context, this.#options);
|
|
19
|
+
if (context.signal.aborted) {
|
|
20
|
+
await backend.close();
|
|
21
|
+
throw abortError();
|
|
22
|
+
}
|
|
23
|
+
if (backend.pageCount < 1) {
|
|
24
|
+
await backend.close();
|
|
25
|
+
throw new ViewerError("invalid-file", "PDF contains no pages");
|
|
26
|
+
}
|
|
27
|
+
context.reportProgress({
|
|
28
|
+
phase: "parsing",
|
|
29
|
+
loaded: 1,
|
|
30
|
+
total: 1,
|
|
31
|
+
ratio: 1,
|
|
32
|
+
});
|
|
33
|
+
return { backend };
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
if (context.signal.aborted)
|
|
37
|
+
throw abortError();
|
|
38
|
+
if (error instanceof ViewerError)
|
|
39
|
+
throw error;
|
|
40
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
41
|
+
throw new ViewerError(isPasswordError(error, message) ? "encrypted-document" : "invalid-file", isPasswordError(error, message)
|
|
42
|
+
? "Password-protected PDF documents are not supported"
|
|
43
|
+
: message, { cause: error });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async getInfo(handle) {
|
|
47
|
+
const pageSizes = handle.backend.pageSize
|
|
48
|
+
? await Promise.all(Array.from({ length: handle.backend.pageCount }, (_, pageIndex) => handle.backend.pageSize(pageIndex)))
|
|
49
|
+
: undefined;
|
|
50
|
+
return {
|
|
51
|
+
format: "pdf",
|
|
52
|
+
unit: "page",
|
|
53
|
+
pageCount: handle.backend.pageCount,
|
|
54
|
+
...(pageSizes ? { pageSizes } : {}),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
async render(handle, target, viewport, signal) {
|
|
58
|
+
assertPage(viewport.pageIndex, handle.backend.pageCount);
|
|
59
|
+
if (signal?.aborted)
|
|
60
|
+
throw abortError();
|
|
61
|
+
await handle.backend.renderPage(target, viewport.pageIndex, viewport.zoom, viewport.devicePixelRatio, signal);
|
|
62
|
+
if (signal?.aborted)
|
|
63
|
+
throw abortError();
|
|
64
|
+
}
|
|
65
|
+
async getTextMap(handle, pageIndex, signal) {
|
|
66
|
+
assertPage(pageIndex, handle.backend.pageCount);
|
|
67
|
+
if (signal?.aborted)
|
|
68
|
+
throw abortError();
|
|
69
|
+
return handle.backend.pageText(pageIndex, signal);
|
|
70
|
+
}
|
|
71
|
+
async close(handle) {
|
|
72
|
+
await handle.backend.close();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
export function createPdfAdapter(options = {}) {
|
|
76
|
+
return new PdfDocumentAdapter(options);
|
|
77
|
+
}
|
|
78
|
+
class PdfJsBackend {
|
|
79
|
+
pageCount;
|
|
80
|
+
#module;
|
|
81
|
+
#document;
|
|
82
|
+
#worker;
|
|
83
|
+
#loadingTask;
|
|
84
|
+
#maxPixels;
|
|
85
|
+
#pages = new Map();
|
|
86
|
+
#closed = false;
|
|
87
|
+
constructor(module, document, worker, loadingTask, maxPixels) {
|
|
88
|
+
this.#module = module;
|
|
89
|
+
this.#document = document;
|
|
90
|
+
this.#worker = worker;
|
|
91
|
+
this.#loadingTask = loadingTask;
|
|
92
|
+
this.#maxPixels = maxPixels;
|
|
93
|
+
this.pageCount = document.numPages;
|
|
94
|
+
}
|
|
95
|
+
static async open(data, context, options) {
|
|
96
|
+
if (typeof Worker === "undefined")
|
|
97
|
+
throw new ViewerError("internal", "PDF.js requires a browser module Worker");
|
|
98
|
+
// PDF.js' modern build targets browsers with very recent JavaScript
|
|
99
|
+
// intrinsics (for example Math.sumPrecise). The legacy build keeps the
|
|
100
|
+
// same API while installing the required polyfills in both the main
|
|
101
|
+
// realm and its matching worker, which is necessary for our supported
|
|
102
|
+
// browser matrix.
|
|
103
|
+
const module = (await import("pdfjs-dist/legacy/build/pdf.mjs"));
|
|
104
|
+
const assetRoot = context.assetBaseUrl
|
|
105
|
+
? new URL("assets/pdfjs/", context.assetBaseUrl)
|
|
106
|
+
: packageRelativeUrl(["..", "assets", "pdfjs", ""]);
|
|
107
|
+
const defaultWorkerUrl = context.assetBaseUrl
|
|
108
|
+
? new URL("workers/pdf.worker.min.mjs", context.assetBaseUrl)
|
|
109
|
+
: packageRelativeUrl(["..", "workers", "pdf.worker.min.mjs"]);
|
|
110
|
+
// The worker filename is intentionally stable for package consumers, so
|
|
111
|
+
// attach the PDF.js version to avoid reusing an incompatible cached worker
|
|
112
|
+
// after a dependency upgrade.
|
|
113
|
+
defaultWorkerUrl.searchParams.set("v", module.version);
|
|
114
|
+
const workerUrl = resolveAssetUrl(options.workerUrl, context.assetBaseUrl, defaultWorkerUrl);
|
|
115
|
+
const workerPort = new Worker(workerUrl, {
|
|
116
|
+
type: "module",
|
|
117
|
+
name: `pdfjs-${module.version}`,
|
|
118
|
+
});
|
|
119
|
+
const worker = new module.PDFWorker({ port: workerPort });
|
|
120
|
+
const loadingTask = module.getDocument({
|
|
121
|
+
data: data.slice(),
|
|
122
|
+
worker,
|
|
123
|
+
cMapUrl: directoryUrl(options.cMapUrl, context, assetRoot, "cmaps/"),
|
|
124
|
+
cMapPacked: true,
|
|
125
|
+
standardFontDataUrl: directoryUrl(options.standardFontDataUrl, context, assetRoot, "standard_fonts/"),
|
|
126
|
+
wasmUrl: directoryUrl(options.wasmUrl, context, assetRoot, "wasm/"),
|
|
127
|
+
iccUrl: directoryUrl(options.iccUrl, context, assetRoot, "iccs/"),
|
|
128
|
+
useWorkerFetch: true,
|
|
129
|
+
useWasm: true,
|
|
130
|
+
useSystemFonts: false,
|
|
131
|
+
disableFontFace: false,
|
|
132
|
+
isEvalSupported: false,
|
|
133
|
+
enableXfa: false,
|
|
134
|
+
stopAtErrors: false,
|
|
135
|
+
maxImageSize: context.limits.maxDecodedPixels,
|
|
136
|
+
canvasMaxAreaInBytes: context.limits.maxDecodedPixels * 4,
|
|
137
|
+
});
|
|
138
|
+
const onAbort = () => {
|
|
139
|
+
void loadingTask.destroy();
|
|
140
|
+
worker.destroy();
|
|
141
|
+
workerPort.terminate();
|
|
142
|
+
};
|
|
143
|
+
context.signal.addEventListener("abort", onAbort, { once: true });
|
|
144
|
+
try {
|
|
145
|
+
const document = await withTimeout(loadingTask.promise, context.limits.maxOperationMs, "PDF parsing");
|
|
146
|
+
if (context.signal.aborted)
|
|
147
|
+
throw abortError();
|
|
148
|
+
return new PdfJsBackend(module, document, worker, loadingTask, context.limits.maxDecodedPixels);
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
await loadingTask.destroy().catch(() => undefined);
|
|
152
|
+
worker.destroy();
|
|
153
|
+
workerPort.terminate();
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
finally {
|
|
157
|
+
context.signal.removeEventListener("abort", onAbort);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
async renderPage(target, pageIndex, zoom, devicePixelRatio, signal) {
|
|
161
|
+
this.#assertOpen();
|
|
162
|
+
const page = await this.#page(pageIndex);
|
|
163
|
+
if (signal?.aborted)
|
|
164
|
+
throw abortError();
|
|
165
|
+
const viewport = page.getViewport({ scale: CSS_UNITS * zoom });
|
|
166
|
+
const dpr = Math.max(1, devicePixelRatio);
|
|
167
|
+
const width = Math.max(1, viewport.width);
|
|
168
|
+
const height = Math.max(1, viewport.height);
|
|
169
|
+
const pixels = Math.ceil(width * dpr) * Math.ceil(height * dpr);
|
|
170
|
+
if (!Number.isSafeInteger(pixels) || pixels > this.#maxPixels)
|
|
171
|
+
throw new ViewerError("resource-limit", "Rendered PDF page exceeds pixel limit", { details: { pixels, limit: this.#maxPixels } });
|
|
172
|
+
target.width = Math.max(1, Math.ceil(width * dpr));
|
|
173
|
+
target.height = Math.max(1, Math.ceil(height * dpr));
|
|
174
|
+
if ("style" in target) {
|
|
175
|
+
target.style.width = `${width}px`;
|
|
176
|
+
target.style.height = `${height}px`;
|
|
177
|
+
}
|
|
178
|
+
const context = target.getContext("2d");
|
|
179
|
+
if (!context)
|
|
180
|
+
throw new ViewerError("render-failed", "Canvas 2D context is unavailable");
|
|
181
|
+
const renderTask = page.render({
|
|
182
|
+
canvas: null,
|
|
183
|
+
canvasContext: context,
|
|
184
|
+
viewport,
|
|
185
|
+
transform: dpr === 1 ? undefined : [dpr, 0, 0, dpr, 0, 0],
|
|
186
|
+
background: "rgb(255,255,255)",
|
|
187
|
+
intent: "display",
|
|
188
|
+
});
|
|
189
|
+
const onAbort = () => renderTask.cancel(0);
|
|
190
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
191
|
+
try {
|
|
192
|
+
await renderTask.promise;
|
|
193
|
+
if (signal?.aborted)
|
|
194
|
+
throw abortError();
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
if (signal?.aborted ||
|
|
198
|
+
error instanceof this.#module.RenderingCancelledException ||
|
|
199
|
+
(error instanceof Error && error.name === "RenderingCancelledException"))
|
|
200
|
+
throw abortError();
|
|
201
|
+
throw new ViewerError("render-failed", "PDF.js page rendering failed", {
|
|
202
|
+
cause: error,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
finally {
|
|
206
|
+
signal?.removeEventListener("abort", onAbort);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
async pageSize(pageIndex, signal) {
|
|
210
|
+
this.#assertOpen();
|
|
211
|
+
const page = await raceAbort(this.#page(pageIndex), signal);
|
|
212
|
+
const viewport = page.getViewport({ scale: CSS_UNITS });
|
|
213
|
+
return { width: viewport.width, height: viewport.height };
|
|
214
|
+
}
|
|
215
|
+
async pageText(pageIndex, signal) {
|
|
216
|
+
this.#assertOpen();
|
|
217
|
+
const page = await this.#page(pageIndex);
|
|
218
|
+
if (signal?.aborted)
|
|
219
|
+
throw abortError();
|
|
220
|
+
const viewport = page.getViewport({ scale: CSS_UNITS });
|
|
221
|
+
const [content, annotations] = await Promise.all([
|
|
222
|
+
raceAbort(page.getTextContent(), signal),
|
|
223
|
+
raceAbort(page.getAnnotations({ intent: "display" }), signal),
|
|
224
|
+
]);
|
|
225
|
+
const links = await this.#links(annotations, viewport, signal);
|
|
226
|
+
const runs = [];
|
|
227
|
+
let logicalOffset = 0;
|
|
228
|
+
for (const item of content.items) {
|
|
229
|
+
if (!("str" in item) || item.str.length === 0)
|
|
230
|
+
continue;
|
|
231
|
+
const style = content.styles[item.fontName] ?? {};
|
|
232
|
+
const run = textItemToRun(item, style, viewport, links, logicalOffset);
|
|
233
|
+
logicalOffset = run.logicalEnd ?? logicalOffset + item.str.length;
|
|
234
|
+
runs.push(run);
|
|
235
|
+
}
|
|
236
|
+
return runs;
|
|
237
|
+
}
|
|
238
|
+
async close() {
|
|
239
|
+
if (this.#closed)
|
|
240
|
+
return;
|
|
241
|
+
this.#closed = true;
|
|
242
|
+
this.#pages.clear();
|
|
243
|
+
try {
|
|
244
|
+
await this.#document.cleanup();
|
|
245
|
+
await this.#loadingTask.destroy();
|
|
246
|
+
}
|
|
247
|
+
finally {
|
|
248
|
+
this.#worker.destroy();
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
#page(pageIndex) {
|
|
252
|
+
let page = this.#pages.get(pageIndex);
|
|
253
|
+
if (!page) {
|
|
254
|
+
page = this.#document.getPage(pageIndex + 1);
|
|
255
|
+
this.#pages.set(pageIndex, page);
|
|
256
|
+
}
|
|
257
|
+
return page;
|
|
258
|
+
}
|
|
259
|
+
async #links(annotations, viewport, signal) {
|
|
260
|
+
const result = [];
|
|
261
|
+
for (const annotation of annotations) {
|
|
262
|
+
if (annotation.subtype !== "Link" ||
|
|
263
|
+
!annotation.rect ||
|
|
264
|
+
annotation.rect.length < 4)
|
|
265
|
+
continue;
|
|
266
|
+
const target = await this.#linkTarget(annotation, signal);
|
|
267
|
+
if (!target)
|
|
268
|
+
continue;
|
|
269
|
+
const first = viewport.convertToViewportPoint(annotation.rect[0], annotation.rect[1]);
|
|
270
|
+
const second = viewport.convertToViewportPoint(annotation.rect[2], annotation.rect[3]);
|
|
271
|
+
result.push({
|
|
272
|
+
left: Math.min(first[0], second[0]),
|
|
273
|
+
top: Math.min(first[1], second[1]),
|
|
274
|
+
right: Math.max(first[0], second[0]),
|
|
275
|
+
bottom: Math.max(first[1], second[1]),
|
|
276
|
+
target,
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
return result;
|
|
280
|
+
}
|
|
281
|
+
async #linkTarget(annotation, signal) {
|
|
282
|
+
const external = safeExternalUrl(annotation.url ?? annotation.unsafeUrl);
|
|
283
|
+
if (external)
|
|
284
|
+
return external;
|
|
285
|
+
if (!annotation.dest)
|
|
286
|
+
return undefined;
|
|
287
|
+
const reference = typeof annotation.dest === "string"
|
|
288
|
+
? await raceAbort(this.#document.getDestination(annotation.dest), signal)
|
|
289
|
+
: annotation.dest;
|
|
290
|
+
if (!reference || reference.length === 0)
|
|
291
|
+
return undefined;
|
|
292
|
+
let pageIndex;
|
|
293
|
+
try {
|
|
294
|
+
pageIndex = await raceAbort(this.#document.getPageIndex(reference[0]), signal);
|
|
295
|
+
}
|
|
296
|
+
catch {
|
|
297
|
+
// A malformed destination remains a typed internal link without a page.
|
|
298
|
+
}
|
|
299
|
+
return {
|
|
300
|
+
kind: "internal",
|
|
301
|
+
ref: typeof annotation.dest === "string" ? annotation.dest : "pdf-dest",
|
|
302
|
+
...(pageIndex === undefined ? {} : { pageIndex }),
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
#assertOpen() {
|
|
306
|
+
if (this.#closed)
|
|
307
|
+
throw new ViewerError("lifecycle-error", "PDF backend is closed");
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
function textItemToRun(item, style, viewport, links, logicalStart) {
|
|
311
|
+
const transform = multiplyTransform(viewport.transform, item.transform);
|
|
312
|
+
let angle = Math.atan2(transform[1], transform[0]);
|
|
313
|
+
if (style.vertical)
|
|
314
|
+
angle += Math.PI / 2;
|
|
315
|
+
const fontHeight = Math.max(1, Math.hypot(transform[2], transform[3]));
|
|
316
|
+
const ascent = style.ascent !== undefined
|
|
317
|
+
? style.ascent * fontHeight
|
|
318
|
+
: style.descent !== undefined
|
|
319
|
+
? (1 + style.descent) * fontHeight
|
|
320
|
+
: fontHeight;
|
|
321
|
+
const left = transform[4] + fontHeight * Math.sin(angle) * (ascent / fontHeight);
|
|
322
|
+
const top = transform[5] - fontHeight * Math.cos(angle) * (ascent / fontHeight);
|
|
323
|
+
const width = Math.max(1, item.width * viewport.scale);
|
|
324
|
+
const height = Math.max(1, item.height * viewport.scale, fontHeight);
|
|
325
|
+
const hyperlink = links.find((link) => rectanglesOverlap({ left, top, right: left + width, bottom: top + height }, link))?.target;
|
|
326
|
+
const fontFamily = style.fontFamily ?? "sans-serif";
|
|
327
|
+
return {
|
|
328
|
+
text: item.str,
|
|
329
|
+
x: left,
|
|
330
|
+
y: top,
|
|
331
|
+
width,
|
|
332
|
+
height,
|
|
333
|
+
direction: item.dir === "rtl" ? "rtl" : "ltr",
|
|
334
|
+
fontFamily,
|
|
335
|
+
fontSize: fontHeight,
|
|
336
|
+
font: `${fontHeight}px ${fontFamily}`,
|
|
337
|
+
...(Math.abs(angle) < 0.000_001
|
|
338
|
+
? {}
|
|
339
|
+
: { transform: `rotate(${angle}rad)` }),
|
|
340
|
+
textLayer: "pdf",
|
|
341
|
+
coordinateWidth: viewport.width,
|
|
342
|
+
coordinateHeight: viewport.height,
|
|
343
|
+
logicalStart,
|
|
344
|
+
logicalEnd: logicalStart + item.str.length,
|
|
345
|
+
...(hyperlink ? { hyperlink } : {}),
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
function multiplyTransform(first, second) {
|
|
349
|
+
return [
|
|
350
|
+
first[0] * second[0] + first[2] * second[1],
|
|
351
|
+
first[1] * second[0] + first[3] * second[1],
|
|
352
|
+
first[0] * second[2] + first[2] * second[3],
|
|
353
|
+
first[1] * second[2] + first[3] * second[3],
|
|
354
|
+
first[0] * second[4] + first[2] * second[5] + first[4],
|
|
355
|
+
first[1] * second[4] + first[3] * second[5] + first[5],
|
|
356
|
+
];
|
|
357
|
+
}
|
|
358
|
+
function rectanglesOverlap(left, right) {
|
|
359
|
+
return !(left.right < right.left ||
|
|
360
|
+
left.left > right.right ||
|
|
361
|
+
left.bottom < right.top ||
|
|
362
|
+
left.top > right.bottom);
|
|
363
|
+
}
|
|
364
|
+
function safeExternalUrl(value) {
|
|
365
|
+
if (!value)
|
|
366
|
+
return undefined;
|
|
367
|
+
try {
|
|
368
|
+
const url = new URL(value);
|
|
369
|
+
return ["http:", "https:", "mailto:", "tel:"].includes(url.protocol)
|
|
370
|
+
? { kind: "external", url: url.href }
|
|
371
|
+
: undefined;
|
|
372
|
+
}
|
|
373
|
+
catch {
|
|
374
|
+
return undefined;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
function resolveAssetUrl(value, base, fallback) {
|
|
378
|
+
return value === undefined ? fallback : new URL(value, base);
|
|
379
|
+
}
|
|
380
|
+
function packageRelativeUrl(segments) {
|
|
381
|
+
// Keeping the path data-driven prevents application bundlers from treating
|
|
382
|
+
// the package-owned directory as an import to hash or inline. Hosts that
|
|
383
|
+
// bundle the facade should normally provide assetBaseUrl.
|
|
384
|
+
const moduleUrl = import.meta.url;
|
|
385
|
+
return new URL(segments.join("/"), moduleUrl);
|
|
386
|
+
}
|
|
387
|
+
function directoryUrl(value, context, assetRoot, directory) {
|
|
388
|
+
const url = resolveAssetUrl(value, context.assetBaseUrl, new URL(directory, assetRoot));
|
|
389
|
+
return url.href.endsWith("/") ? url.href : `${url.href}/`;
|
|
390
|
+
}
|
|
391
|
+
function raceAbort(promise, signal) {
|
|
392
|
+
if (!signal)
|
|
393
|
+
return promise;
|
|
394
|
+
if (signal.aborted)
|
|
395
|
+
return Promise.reject(abortError());
|
|
396
|
+
return new Promise((resolve, reject) => {
|
|
397
|
+
const onAbort = () => reject(abortError());
|
|
398
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
399
|
+
promise.then((value) => {
|
|
400
|
+
signal.removeEventListener("abort", onAbort);
|
|
401
|
+
resolve(value);
|
|
402
|
+
}, (error) => {
|
|
403
|
+
signal.removeEventListener("abort", onAbort);
|
|
404
|
+
reject(error);
|
|
405
|
+
});
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
function withTimeout(promise, timeoutMs, operation) {
|
|
409
|
+
return new Promise((resolve, reject) => {
|
|
410
|
+
const timeout = setTimeout(() => reject(new ViewerError("resource-limit", `${operation} exceeded maxOperationMs`, { details: { timeoutMs } })), timeoutMs);
|
|
411
|
+
promise.then((value) => {
|
|
412
|
+
clearTimeout(timeout);
|
|
413
|
+
resolve(value);
|
|
414
|
+
}, (error) => {
|
|
415
|
+
clearTimeout(timeout);
|
|
416
|
+
reject(error);
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
function isPasswordError(error, message) {
|
|
421
|
+
return ((error instanceof Error && error.name === "PasswordException") ||
|
|
422
|
+
/password|encrypted/i.test(message));
|
|
423
|
+
}
|
|
424
|
+
function assertPage(pageIndex, pageCount) {
|
|
425
|
+
if (!Number.isInteger(pageIndex) || pageIndex < 0 || pageIndex >= pageCount)
|
|
426
|
+
throw new ViewerError("render-failed", "PDF page index is out of range", {
|
|
427
|
+
details: { pageIndex, pageCount },
|
|
428
|
+
});
|
|
429
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AdapterOpenContext, DocumentAdapter, DocumentInfo, RenderViewport, ViewerWarning } from "../contracts.js";
|
|
2
|
+
interface SvgHandle {
|
|
3
|
+
readonly data: Uint8Array;
|
|
4
|
+
readonly warnings: readonly ViewerWarning[];
|
|
5
|
+
}
|
|
6
|
+
export declare class SvgDocumentAdapter implements DocumentAdapter<SvgHandle> {
|
|
7
|
+
readonly id = "svg";
|
|
8
|
+
readonly formats: readonly ["svg"];
|
|
9
|
+
open(data: Uint8Array, context: AdapterOpenContext): Promise<SvgHandle>;
|
|
10
|
+
getInfo(handle: SvgHandle): Promise<DocumentInfo>;
|
|
11
|
+
render(handle: SvgHandle, target: HTMLCanvasElement | OffscreenCanvas, viewport: RenderViewport, signal?: AbortSignal): Promise<void>;
|
|
12
|
+
getTextMap(): Promise<readonly []>;
|
|
13
|
+
close(): void;
|
|
14
|
+
}
|
|
15
|
+
export declare function sanitizeSvg(source: string): string;
|
|
16
|
+
export declare function createSvgAdapter(): SvgDocumentAdapter;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { abortError, ViewerError } from "../errors.js";
|
|
2
|
+
import { drawEncodedImage } from "./bitmap.js";
|
|
3
|
+
export class SvgDocumentAdapter {
|
|
4
|
+
id = "svg";
|
|
5
|
+
formats = ["svg"];
|
|
6
|
+
async open(data, context) {
|
|
7
|
+
if (context.signal.aborted)
|
|
8
|
+
throw abortError();
|
|
9
|
+
let source;
|
|
10
|
+
try {
|
|
11
|
+
source = new TextDecoder("utf-8", { fatal: true }).decode(data);
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
throw new ViewerError("invalid-file", "SVG must be valid UTF-8", {
|
|
15
|
+
cause: error,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
const sanitized = sanitizeSvg(source);
|
|
19
|
+
const changed = sanitized !== source;
|
|
20
|
+
return {
|
|
21
|
+
data: new TextEncoder().encode(sanitized),
|
|
22
|
+
warnings: changed
|
|
23
|
+
? [
|
|
24
|
+
{
|
|
25
|
+
code: "external-resource-blocked",
|
|
26
|
+
message: "Active SVG content or external resources were removed",
|
|
27
|
+
},
|
|
28
|
+
]
|
|
29
|
+
: [],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
async getInfo(handle) {
|
|
33
|
+
return {
|
|
34
|
+
format: "svg",
|
|
35
|
+
unit: "image",
|
|
36
|
+
pageCount: 1,
|
|
37
|
+
warnings: handle.warnings,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
async render(handle, target, viewport, signal) {
|
|
41
|
+
if (viewport.pageIndex !== 0)
|
|
42
|
+
throw new ViewerError("render-failed", "SVG page index is out of range");
|
|
43
|
+
if (signal?.aborted)
|
|
44
|
+
throw abortError();
|
|
45
|
+
await drawEncodedImage(handle.data, "image/svg+xml", target, {
|
|
46
|
+
dpr: viewport.devicePixelRatio,
|
|
47
|
+
scale: viewport.zoom,
|
|
48
|
+
...(viewport.width === undefined ? {} : { cssWidth: viewport.width }),
|
|
49
|
+
...(viewport.height === undefined ? {} : { cssHeight: viewport.height }),
|
|
50
|
+
});
|
|
51
|
+
if (signal?.aborted)
|
|
52
|
+
throw abortError();
|
|
53
|
+
}
|
|
54
|
+
async getTextMap() {
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
close() { }
|
|
58
|
+
}
|
|
59
|
+
export function sanitizeSvg(source) {
|
|
60
|
+
const withoutDoctype = source.replace(/<!DOCTYPE[\s\S]*?>/gi, "");
|
|
61
|
+
if (typeof DOMParser === "undefined")
|
|
62
|
+
return sanitizeSvgFallback(withoutDoctype);
|
|
63
|
+
const document = new DOMParser().parseFromString(withoutDoctype, "image/svg+xml");
|
|
64
|
+
if (document.querySelector("parsererror") ||
|
|
65
|
+
document.documentElement.localName !== "svg")
|
|
66
|
+
throw new ViewerError("invalid-file", "Malformed SVG document");
|
|
67
|
+
const blocked = new Set([
|
|
68
|
+
"script",
|
|
69
|
+
"style",
|
|
70
|
+
"foreignobject",
|
|
71
|
+
"iframe",
|
|
72
|
+
"object",
|
|
73
|
+
"embed",
|
|
74
|
+
"audio",
|
|
75
|
+
"video",
|
|
76
|
+
"canvas",
|
|
77
|
+
]);
|
|
78
|
+
for (const element of [...document.querySelectorAll("*")]) {
|
|
79
|
+
if (blocked.has(element.localName.toLowerCase())) {
|
|
80
|
+
element.remove();
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
for (const attribute of [...element.attributes]) {
|
|
84
|
+
const name = attribute.name.toLowerCase();
|
|
85
|
+
const value = attribute.value.trim();
|
|
86
|
+
if (name.startsWith("on") ||
|
|
87
|
+
((name === "href" || name === "xlink:href" || name === "src") &&
|
|
88
|
+
!value.startsWith("#")) ||
|
|
89
|
+
(/url\s*\(/i.test(value) && !/url\s*\(\s*['"]?#/i.test(value)) ||
|
|
90
|
+
/expression\s*\(|@import/i.test(value))
|
|
91
|
+
element.removeAttribute(attribute.name);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return new XMLSerializer().serializeToString(document.documentElement);
|
|
95
|
+
}
|
|
96
|
+
export function createSvgAdapter() {
|
|
97
|
+
return new SvgDocumentAdapter();
|
|
98
|
+
}
|
|
99
|
+
function sanitizeSvgFallback(source) {
|
|
100
|
+
let result = source;
|
|
101
|
+
for (const tag of [
|
|
102
|
+
"script",
|
|
103
|
+
"style",
|
|
104
|
+
"foreignObject",
|
|
105
|
+
"iframe",
|
|
106
|
+
"object",
|
|
107
|
+
"embed",
|
|
108
|
+
"audio",
|
|
109
|
+
"video",
|
|
110
|
+
"canvas",
|
|
111
|
+
]) {
|
|
112
|
+
const paired = new RegExp(`<${tag}\\b[\\s\\S]*?<\\/${tag}\\s*>`, "gi");
|
|
113
|
+
const single = new RegExp(`<${tag}\\b[^>]*\\/?>`, "gi");
|
|
114
|
+
result = result.replace(paired, "").replace(single, "");
|
|
115
|
+
}
|
|
116
|
+
result = result
|
|
117
|
+
.replace(/\s+on[\w:-]+\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/gi, "")
|
|
118
|
+
.replace(/\s+(?:href|xlink:href|src)\s*=\s*(?:"(?!#)[^"]*"|'(?!#)[^']*'|(?!#)[^\s>"']+)/gi, "")
|
|
119
|
+
.replace(/\s+style\s*=\s*(?:"[^"]*(?:url|expression|@import)[^"]*"|'[^']*(?:url|expression|@import)[^']*')/gi, "");
|
|
120
|
+
if (!/<svg(?:\s|>)/i.test(result))
|
|
121
|
+
throw new ViewerError("invalid-file", "Malformed SVG document");
|
|
122
|
+
return result;
|
|
123
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Parsed, bounded multi-page TIFF document.
|
|
6
|
+
*/
|
|
7
|
+
export class TiffViewerDocument {
|
|
8
|
+
free(): void;
|
|
9
|
+
[Symbol.dispose](): void;
|
|
10
|
+
/**
|
|
11
|
+
* Decode all TIFF IFDs and retain compressed PNG pages.
|
|
12
|
+
*
|
|
13
|
+
* # Errors
|
|
14
|
+
*
|
|
15
|
+
* Returns an error for malformed/unsupported TIFF data or a pixel-limit breach.
|
|
16
|
+
*/
|
|
17
|
+
constructor(data: Uint8Array, max_decoded_pixels: number);
|
|
18
|
+
/**
|
|
19
|
+
* Number of image directories/pages.
|
|
20
|
+
*/
|
|
21
|
+
pageCount(): number;
|
|
22
|
+
/**
|
|
23
|
+
* Height of one page in pixels.
|
|
24
|
+
*/
|
|
25
|
+
pageHeight(page_index: number): number;
|
|
26
|
+
/**
|
|
27
|
+
* Width of one page in pixels.
|
|
28
|
+
*/
|
|
29
|
+
pageWidth(page_index: number): number;
|
|
30
|
+
/**
|
|
31
|
+
* Return a decoded page as PNG bytes.
|
|
32
|
+
*
|
|
33
|
+
* # Errors
|
|
34
|
+
*
|
|
35
|
+
* Returns an error when `page_index` is outside the document.
|
|
36
|
+
*/
|
|
37
|
+
renderPagePng(page_index: number): Uint8Array;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
|
41
|
+
|
|
42
|
+
export interface InitOutput {
|
|
43
|
+
readonly memory: WebAssembly.Memory;
|
|
44
|
+
readonly __wbg_tiffviewerdocument_free: (a: number, b: number) => void;
|
|
45
|
+
readonly tiffviewerdocument_new: (a: number, b: number, c: number, d: number) => void;
|
|
46
|
+
readonly tiffviewerdocument_pageCount: (a: number) => number;
|
|
47
|
+
readonly tiffviewerdocument_pageHeight: (a: number, b: number) => number;
|
|
48
|
+
readonly tiffviewerdocument_pageWidth: (a: number, b: number) => number;
|
|
49
|
+
readonly tiffviewerdocument_renderPagePng: (a: number, b: number, c: number) => void;
|
|
50
|
+
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
|
|
51
|
+
readonly __wbindgen_export: (a: number, b: number) => number;
|
|
52
|
+
readonly __wbindgen_export2: (a: number, b: number, c: number) => void;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export type SyncInitInput = BufferSource | WebAssembly.Module;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Instantiates the given `module`, which can either be bytes or
|
|
59
|
+
* a precompiled `WebAssembly.Module`.
|
|
60
|
+
*
|
|
61
|
+
* @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
|
|
62
|
+
*
|
|
63
|
+
* @returns {InitOutput}
|
|
64
|
+
*/
|
|
65
|
+
export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
|
|
69
|
+
* for everything else, calls `WebAssembly.instantiate` directly.
|
|
70
|
+
*
|
|
71
|
+
* @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
|
|
72
|
+
*
|
|
73
|
+
* @returns {Promise<InitOutput>}
|
|
74
|
+
*/
|
|
75
|
+
export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;
|