@eternalheart/vue-file-preview 1.3.11 → 1.3.13
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/README.md +27 -0
- package/README.zh-CN.md +27 -0
- package/lib/FilePreviewContent.vue.d.ts.map +1 -1
- package/lib/chunks/{index-DLPnWmJm.mjs → index-B2lqsdp7.mjs} +2 -2
- package/lib/chunks/{index-DLPnWmJm.mjs.map → index-B2lqsdp7.mjs.map} +1 -1
- package/lib/chunks/{index-hRgOoqVw.mjs → index-BHi1WRQZ.mjs} +2 -2
- package/lib/chunks/{index-hRgOoqVw.mjs.map → index-BHi1WRQZ.mjs.map} +1 -1
- package/lib/chunks/{index-BHPmd4HF.mjs → index-BTW1xwB9.mjs} +2 -2
- package/lib/chunks/{index-BHPmd4HF.mjs.map → index-BTW1xwB9.mjs.map} +1 -1
- package/lib/chunks/{index-C0vSFXmh.mjs → index-BvegaxQF.mjs} +2 -2
- package/lib/chunks/{index-C0vSFXmh.mjs.map → index-BvegaxQF.mjs.map} +1 -1
- package/lib/chunks/{index-C65zV1vs.mjs → index-CYt6tpQC.mjs} +2 -2
- package/lib/chunks/{index-C65zV1vs.mjs.map → index-CYt6tpQC.mjs.map} +1 -1
- package/lib/chunks/{index-t1Plo3ud.mjs → index-Cjnw238n.mjs} +2 -2
- package/lib/chunks/{index-t1Plo3ud.mjs.map → index-Cjnw238n.mjs.map} +1 -1
- package/lib/chunks/{index-BT-U9HYI.mjs → index-Ctd0JQ6K.mjs} +2 -2
- package/lib/chunks/{index-BT-U9HYI.mjs.map → index-Ctd0JQ6K.mjs.map} +1 -1
- package/lib/chunks/index-CyrFxdIJ.mjs +318 -0
- package/lib/chunks/index-CyrFxdIJ.mjs.map +1 -0
- package/lib/chunks/{index-Cu1up6RM.mjs → index-DBw8tvyb.mjs} +2 -2
- package/lib/chunks/{index-Cu1up6RM.mjs.map → index-DBw8tvyb.mjs.map} +1 -1
- package/lib/chunks/{index-BKu5DkdG.mjs → index-DEoR7aDN.mjs} +2 -2
- package/lib/chunks/{index-BKu5DkdG.mjs.map → index-DEoR7aDN.mjs.map} +1 -1
- package/lib/chunks/{index-CMgtGmRN.mjs → index-DIe0vHlt.mjs} +9 -9
- package/lib/chunks/{index-CMgtGmRN.mjs.map → index-DIe0vHlt.mjs.map} +1 -1
- package/lib/chunks/index-DT9dPz8I.mjs +279 -0
- package/lib/chunks/index-DT9dPz8I.mjs.map +1 -0
- package/lib/chunks/{index-B9RAbllH.mjs → index-DTtHrdBl.mjs} +6 -6
- package/lib/chunks/{index-B9RAbllH.mjs.map → index-DTtHrdBl.mjs.map} +1 -1
- package/lib/chunks/{index-Dln8hyPZ.mjs → index-DX_NBPzS.mjs} +2 -2
- package/lib/chunks/{index-Dln8hyPZ.mjs.map → index-DX_NBPzS.mjs.map} +1 -1
- package/lib/chunks/{index-BA-SUKkf.mjs → index-Dw1U4YqT.mjs} +2 -2
- package/lib/chunks/{index-BA-SUKkf.mjs.map → index-Dw1U4YqT.mjs.map} +1 -1
- package/lib/chunks/{index-DNFQFaF3.mjs → index-DyipSoKh.mjs} +2 -2
- package/lib/chunks/{index-DNFQFaF3.mjs.map → index-DyipSoKh.mjs.map} +1 -1
- package/lib/chunks/{index-B3-ezDVJ.mjs → index-GGGDPwxX.mjs} +2 -2
- package/lib/chunks/{index-B3-ezDVJ.mjs.map → index-GGGDPwxX.mjs.map} +1 -1
- package/lib/chunks/{index-CQFN4h-t.mjs → index-Oxwizt6-.mjs} +609 -581
- package/lib/chunks/index-Oxwizt6-.mjs.map +1 -0
- package/lib/chunks/{index-CY2vJrBJ.mjs → index-Zwl5J-Uw.mjs} +2 -2
- package/lib/chunks/{index-CY2vJrBJ.mjs.map → index-Zwl5J-Uw.mjs.map} +1 -1
- package/lib/components/NavArrows.vue.d.ts +17 -0
- package/lib/components/NavArrows.vue.d.ts.map +1 -0
- package/lib/components/ResizableSplit.vue.d.ts +17 -2
- package/lib/components/ResizableSplit.vue.d.ts.map +1 -1
- package/lib/index.cjs +32 -32
- package/lib/index.cjs.map +1 -1
- package/lib/index.css +1 -1
- package/lib/index.mjs +1 -1
- package/lib/renderers/Image/index.vue.d.ts.map +1 -1
- package/lib/renderers/Text/index.vue.d.ts.map +1 -1
- package/lib/renderers/Xml/index.vue.d.ts.map +1 -1
- package/lib/renderers/Zip/index.vue.d.ts.map +1 -1
- package/package.json +1 -1
- package/lib/chunks/index-CQFN4h-t.mjs.map +0 -1
- package/lib/chunks/index-ijv9F2cZ.mjs +0 -280
- package/lib/chunks/index-ijv9F2cZ.mjs.map +0 -1
- package/lib/chunks/index-y7gaKu36.mjs +0 -234
- package/lib/chunks/index-y7gaKu36.mjs.map +0 -1
- package/lib/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/78-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/78-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/Add-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/Add-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
- package/lib/pdfjs/cmaps/B5-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/B5-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/B5pc-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/B5pc-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/CNS1-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/CNS1-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/CNS2-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/CNS2-V.bcmap +0 -3
- package/lib/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/ETenms-B5-H.bcmap +0 -3
- package/lib/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/EUC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/EUC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/Ext-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/Ext-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/GB-H.bcmap +0 -4
- package/lib/pdfjs/cmaps/GB-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBT-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBT-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/H.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/Hankaku.bcmap +0 -0
- package/lib/pdfjs/cmaps/Hiragana.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/Katakana.bcmap +0 -0
- package/lib/pdfjs/cmaps/LICENSE +0 -36
- package/lib/pdfjs/cmaps/NWP-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/NWP-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/Roman.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/V.bcmap +0 -0
- package/lib/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
- package/lib/pdfjs/pdf.worker.min.mjs +0 -21
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-
|
|
1
|
+
{"version":3,"file":"index-DIe0vHlt.mjs","sources":["../../src/renderers/Xml/index.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, watch } from 'vue';\nimport { fetchTextUtf8 } from '@eternalheart/file-preview-core';\nimport { codeToHtml } from 'shiki';\nimport { useTranslator } from '../../composables/useTranslator';\nimport { useFetcher } from '../../composables/useRequest';\nimport { useResolvedTheme } from '../../composables/useResolvedTheme';\nimport RendererError from '../RendererError.vue';\n\nconst props = defineProps<{\n url: string;\n fileName: string;\n}>();\n\nconst { t } = useTranslator();\nconst fetcher = useFetcher();\nconst resolvedTheme = useResolvedTheme();\n\nconst content = ref<string>('');\nconst highlighted = ref<string>('');\nconst loading = ref(true);\nconst error = ref<string | null>(null);\n\nconst indentXml = (xml: string): string => {\n const PADDING = ' ';\n const reg = /(>)(<)(\\/*)/g;\n const formatted = xml.replace(reg, '$1\\n$2$3');\n let pad = 0;\n return formatted\n .split('\\n')\n .map((line) => {\n let indent = 0;\n if (/^<\\/\\w/.test(line)) {\n pad = Math.max(pad - 1, 0);\n } else if (/^<\\w[^>]*[^/]>.*$/.test(line) && !/<.+<\\/.+>$/.test(line)) {\n indent = 1;\n }\n const padded = PADDING.repeat(pad) + line;\n pad += indent;\n return padded;\n })\n .join('\\n');\n};\n\nconst prettyPrintXml = (xml: string): string => {\n try {\n const parser = new DOMParser();\n const doc = parser.parseFromString(xml, 'application/xml');\n if (doc.querySelector('parsererror')) return xml;\n const serializer = new XMLSerializer();\n const serialized = serializer.serializeToString(doc);\n return indentXml(serialized);\n } catch {\n return xml;\n }\n};\n\nconst load = async () => {\n loading.value = true;\n error.value = null;\n try {\n const raw = await fetchTextUtf8(props.url, { fetcher: fetcher.value });\n content.value = prettyPrintXml(raw);\n try {\n highlighted.value = await codeToHtml(content.value, {\n lang: 'xml',\n theme: resolvedTheme.value === 'light' ? 'github-light' : 'dark-plus',\n });\n } catch {\n highlighted.value = '';\n }\n } catch (err) {\n console.error(err);\n error.value = t.value('xml.load_failed');\n } finally {\n loading.value = false;\n }\n};\n\nwatch(() => props.url, load, { immediate: true });\nwatch(resolvedTheme, () => {\n if (content.value) load();\n});\n</script>\n\n<template>\n <div v-if=\"loading\" class=\"vfp-flex vfp-items-center vfp-justify-center vfp-w-full vfp-h-full\">\n <div\n class=\"vfp-w-12 vfp-h-12 vfp-border-4 vfp-border-line-strong vfp-border-t-spinner-head vfp-rounded-full vfp-animate-spin\"\n />\n </div>\n\n <RendererError v-else-if=\"error\" :message=\"error\" />\n\n <div v-else class=\"vfp-w-full vfp-h-full vfp-overflow-auto\" style=\"background: var(--fp-code-bg);\">\n <pre\n v-if=\"!highlighted\"\n class=\"vfp-p-6 vfp-text-fg-primary vfp-font-mono vfp-text-sm vfp-whitespace-pre-wrap vfp-break-words\"\n >{{ content }}</pre\n >\n <div v-else class=\"shiki-wrapper\" v-html=\"highlighted\" />\n </div>\n</template>\n\n<style scoped>\n.shiki-wrapper :deep(pre) {\n margin: 0;\n padding: 1.5rem 1.5rem 1.5rem 0;\n background: transparent !important;\n font-size: 0.875rem;\n overflow-x: auto;\n}\n.shiki-wrapper :deep(code) {\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n counter-reset: line;\n}\n.shiki-wrapper :deep(code .line) {\n counter-increment: line;\n display: inline-block;\n width: 100%;\n padding-left: 4.5em;\n text-indent: -4.5em;\n}\n.shiki-wrapper :deep(code .line::before) {\n content: counter(line);\n display: inline-block;\n width: 3em;\n padding-right: 1em;\n margin-right: 0.5em;\n text-align: right;\n color: var(--fp-fg-disabled);\n user-select: none;\n border-right: 1px solid var(--fp-line);\n}\n</style>\n"],"names":["props","__props","t","useTranslator","fetcher","useFetcher","resolvedTheme","useResolvedTheme","content","ref","highlighted","loading","error","indentXml","xml","PADDING","reg","formatted","pad","line","indent","padded","prettyPrintXml","doc","serialized","load","raw","fetchTextUtf8","codeToHtml","err","watch","_openBlock","_createElementBlock","_hoisted_1","_cache","_createElementVNode","_createBlock","RendererError","_hoisted_2","_hoisted_3","_toDisplayString"],"mappings":";;;;;;;;;;;;;;;;;;;;;AASA,UAAMA,IAAQC,GAKR,EAAE,GAAAC,EAAA,IAAMC,EAAA,GACRC,IAAUC,EAAA,GACVC,IAAgBC,EAAA,GAEhBC,IAAUC,EAAY,EAAE,GACxBC,IAAcD,EAAY,EAAE,GAC5BE,IAAUF,EAAI,EAAI,GAClBG,IAAQH,EAAmB,IAAI,GAE/BI,IAAY,CAACC,MAAwB;AACzC,YAAMC,IAAU,MACVC,IAAM,gBACNC,IAAYH,EAAI,QAAQE,GAAK;AAAA,KAAU;AAC7C,UAAIE,IAAM;AACV,aAAOD,EACJ,MAAM;AAAA,CAAI,EACV,IAAI,CAACE,MAAS;AACb,YAAIC,IAAS;AACb,QAAI,SAAS,KAAKD,CAAI,IACpBD,IAAM,KAAK,IAAIA,IAAM,GAAG,CAAC,IAChB,oBAAoB,KAAKC,CAAI,KAAK,CAAC,aAAa,KAAKA,CAAI,MAClEC,IAAS;AAEX,cAAMC,IAASN,EAAQ,OAAOG,CAAG,IAAIC;AACrC,eAAAD,KAAOE,GACAC;AAAA,MACT,CAAC,EACA,KAAK;AAAA,CAAI;AAAA,IACd,GAEMC,IAAiB,CAACR,MAAwB;AAC9C,UAAI;AAEF,cAAMS,IADS,IAAI,UAAA,EACA,gBAAgBT,GAAK,iBAAiB;AACzD,YAAIS,EAAI,cAAc,aAAa,EAAG,QAAOT;AAE7C,cAAMU,IADa,IAAI,cAAA,EACO,kBAAkBD,CAAG;AACnD,eAAOV,EAAUW,CAAU;AAAA,MAC7B,QAAQ;AACN,eAAOV;AAAA,MACT;AAAA,IACF,GAEMW,IAAO,YAAY;AACvB,MAAAd,EAAQ,QAAQ,IAChBC,EAAM,QAAQ;AACd,UAAI;AACF,cAAMc,IAAM,MAAMC,EAAc3B,EAAM,KAAK,EAAE,SAASI,EAAQ,OAAO;AACrE,QAAAI,EAAQ,QAAQc,EAAeI,CAAG;AAClC,YAAI;AACF,UAAAhB,EAAY,QAAQ,MAAMkB,EAAWpB,EAAQ,OAAO;AAAA,YAClD,MAAM;AAAA,YACN,OAAOF,EAAc,UAAU,UAAU,iBAAiB;AAAA,UAAA,CAC3D;AAAA,QACH,QAAQ;AACN,UAAAI,EAAY,QAAQ;AAAA,QACtB;AAAA,MACF,SAASmB,GAAK;AACZ,gBAAQ,MAAMA,CAAG,GACjBjB,EAAM,QAAQV,EAAE,MAAM,iBAAiB;AAAA,MACzC,UAAA;AACE,QAAAS,EAAQ,QAAQ;AAAA,MAClB;AAAA,IACF;AAEA,WAAAmB,EAAM,MAAM9B,EAAM,KAAKyB,GAAM,EAAE,WAAW,IAAM,GAChDK,EAAMxB,GAAe,MAAM;AACzB,MAAIE,EAAQ,SAAOiB,EAAA;AAAA,IACrB,CAAC,aAIYd,EAAA,SAAXoB,EAAA,GAAAC,EAIM,OAJNC,GAIM,CAAA,GAAAC,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,MAHJC,EAEE,OAAA,EADA,OAAM,oHAAA,GAAmH,MAAA,EAAA;AAAA,IAAA,QAInGvB,EAAA,cAA1BwB,EAAoDC,GAAA;AAAA;MAAlB,SAASzB,EAAA;AAAA,IAAA,6BAE3CmB,KAAAC,EAOM,OAPNM,GAOM;AAAA,MALK5B,EAAA,cAITsB,EAAyD,OAAA;AAAA;QAA7C,OAAM;AAAA,QAAgB,WAAQtB,EAAA;AAAA,MAAA,wBAL1CsB,EAIC,OAJDO,GAICC,EADKhC,EAAA,KAAO,GAAA,CAAA;AAAA;;;"}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { defineComponent as de, ref as r, watch as H, onBeforeUnmount as Q, onMounted as pe, computed as I, openBlock as m, createElementBlock as _, normalizeStyle as J, createVNode as he, unref as ee, createElementVNode as S, createTextVNode as me, toDisplayString as Y, createCommentVNode as w, createBlock as te, normalizeClass as ge } from "vue";
|
|
2
|
+
import { Loader2 as ye } from "lucide-vue-next";
|
|
3
|
+
import { u as be, G as xe, q as we, C as Le } from "./index-Oxwizt6-.mjs";
|
|
4
|
+
import { _ as ae } from "./RendererError.vue_vue_type_script_setup_true_lang-CbgZBSDr.mjs";
|
|
5
|
+
const Ce = {
|
|
6
|
+
key: 0,
|
|
7
|
+
class: "vfp-absolute vfp-inset-0 vfp-flex vfp-flex-col vfp-items-center vfp-justify-center vfp-bg-surface-1/80 vfp-z-10"
|
|
8
|
+
}, Me = { class: "vfp-mt-4 vfp-text-fg-secondary" }, _e = { key: 0 }, ke = {
|
|
9
|
+
key: 2,
|
|
10
|
+
class: "vfp-flex vfp-items-center vfp-justify-center"
|
|
11
|
+
}, Re = ["src"], Ee = {
|
|
12
|
+
key: 5,
|
|
13
|
+
class: "vfp-absolute vfp-bottom-2 vfp-right-3 vfp-text-[10px] vfp-text-fg-disabled hover:vfp-text-fg-secondary vfp-transition-colors vfp-pointer-events-auto vfp-select-none vfp-cursor-default"
|
|
14
|
+
}, Ue = {
|
|
15
|
+
key: 6,
|
|
16
|
+
class: "vfp-absolute vfp-bottom-2 vfp-left-1/2 -vfp-translate-x-1/2 vfp-flex vfp-items-center vfp-gap-2 vfp-px-3 vfp-py-1.5 vfp-bg-surface-toolbar vfp-border vfp-border-line vfp-rounded-lg vfp-text-sm vfp-text-fg-primary vfp-shadow-md"
|
|
17
|
+
}, ze = ["disabled"], Ye = { class: "vfp-text-fg-secondary vfp-tabular-nums" }, Se = ["disabled"], je = /* @__PURE__ */ de({
|
|
18
|
+
__name: "index",
|
|
19
|
+
props: {
|
|
20
|
+
url: {},
|
|
21
|
+
zoom: {},
|
|
22
|
+
rotation: {},
|
|
23
|
+
resetKey: {},
|
|
24
|
+
fileSize: {},
|
|
25
|
+
file: {}
|
|
26
|
+
},
|
|
27
|
+
emits: ["zoomChange", "naturalWidthChange", "naturalHeightChange"],
|
|
28
|
+
setup(ne, { emit: le }) {
|
|
29
|
+
const u = ne, k = le, { t: N } = be(), L = r(!1), g = r(null), v = r(!1), X = r(0), y = r(null), b = r(""), x = r(1), R = r(1), V = r(!1), l = r({ x: 0, y: 0 }), p = r(!1);
|
|
30
|
+
let E = { x: 0, y: 0 };
|
|
31
|
+
const i = r(1), C = r({ width: 0, height: 0 }), oe = r(null), M = r(null);
|
|
32
|
+
let U = null, D = null, T = null;
|
|
33
|
+
const f = /* @__PURE__ */ new Map();
|
|
34
|
+
let B = !1, j = 0, K = 1, O = { x: 0, y: 0 }, Z = 0;
|
|
35
|
+
H(
|
|
36
|
+
() => [u.url, u.file],
|
|
37
|
+
async () => {
|
|
38
|
+
if (b.value = "", L.value = !1, g.value = null, v.value = !1, y.value = null, X.value = 0, l.value = { x: 0, y: 0 }, i.value = 1, x.value = 1, R.value = 1, V.value = !1, U && (URL.revokeObjectURL(U), U = null), f.forEach((e) => URL.revokeObjectURL(e)), f.clear(), D = null, T = null, !u.file) {
|
|
39
|
+
b.value = u.url;
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
const e = await xe(u.file), t = await we(e);
|
|
44
|
+
if (!t || !await t.needsDecode(e)) {
|
|
45
|
+
b.value = u.url;
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
v.value = !0;
|
|
49
|
+
let a;
|
|
50
|
+
if (u.file instanceof Blob)
|
|
51
|
+
a = u.file;
|
|
52
|
+
else {
|
|
53
|
+
const n = await fetch(u.url);
|
|
54
|
+
if (!n.ok) throw new Error("Failed to fetch file");
|
|
55
|
+
a = await n.blob();
|
|
56
|
+
}
|
|
57
|
+
if (D = a, T = t, e.startsWith("image/x-") && (V.value = !0), t.getMetadata)
|
|
58
|
+
try {
|
|
59
|
+
const n = await t.getMetadata(a);
|
|
60
|
+
n.pageCount && n.pageCount > 1 && (R.value = n.pageCount);
|
|
61
|
+
} catch {
|
|
62
|
+
}
|
|
63
|
+
const o = await t.decode(a, {
|
|
64
|
+
page: 1,
|
|
65
|
+
fullQuality: !1,
|
|
66
|
+
onProgress: (n) => {
|
|
67
|
+
X.value = n;
|
|
68
|
+
}
|
|
69
|
+
}), s = typeof o == "string" ? o : URL.createObjectURL(o);
|
|
70
|
+
U = s, f.set(1, s), b.value = s, v.value = !1;
|
|
71
|
+
} catch (e) {
|
|
72
|
+
y.value = (e == null ? void 0 : e.message) || "解码失败", v.value = !1;
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
{ immediate: !0 }
|
|
76
|
+
);
|
|
77
|
+
const q = async (e) => {
|
|
78
|
+
if (!D || !T || e < 1 || e > R.value) return;
|
|
79
|
+
const t = f.get(e);
|
|
80
|
+
if (t) {
|
|
81
|
+
x.value = e, b.value = t;
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
v.value = !0;
|
|
85
|
+
try {
|
|
86
|
+
const a = await T.decode(D, { page: e }), c = typeof a == "string" ? a : URL.createObjectURL(a);
|
|
87
|
+
if (f.size >= 10) {
|
|
88
|
+
const o = f.keys().next().value;
|
|
89
|
+
if (o !== void 0) {
|
|
90
|
+
const s = f.get(o);
|
|
91
|
+
s && URL.revokeObjectURL(s), f.delete(o);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
f.set(e, c), x.value = e, b.value = c, v.value = !1;
|
|
95
|
+
} catch (a) {
|
|
96
|
+
y.value = (a == null ? void 0 : a.message) || "翻页解码失败", v.value = !1;
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
Q(() => {
|
|
100
|
+
U && URL.revokeObjectURL(U), f.forEach((t) => URL.revokeObjectURL(t)), f.clear();
|
|
101
|
+
const e = M.value;
|
|
102
|
+
e && e.removeEventListener("wheel", $);
|
|
103
|
+
}), H(
|
|
104
|
+
() => u.zoom,
|
|
105
|
+
(e) => {
|
|
106
|
+
i.value = e;
|
|
107
|
+
}
|
|
108
|
+
), H(
|
|
109
|
+
() => u.resetKey,
|
|
110
|
+
() => {
|
|
111
|
+
l.value = { x: 0, y: 0 };
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
const P = (e, t) => {
|
|
115
|
+
const a = M.value;
|
|
116
|
+
if (!a || C.value.width === 0) return e;
|
|
117
|
+
const c = a.clientWidth, o = a.clientHeight, s = C.value.width * t, n = C.value.height * t, d = Math.min(80, c * 0.15, o * 0.15), h = (c + s) / 2 - d, z = (o + n) / 2 - d;
|
|
118
|
+
return {
|
|
119
|
+
x: h > 0 ? Math.max(-h, Math.min(h, e.x)) : 0,
|
|
120
|
+
y: z > 0 ? Math.max(-z, Math.min(z, e.y)) : 0
|
|
121
|
+
};
|
|
122
|
+
}, se = (e) => {
|
|
123
|
+
L.value = !0;
|
|
124
|
+
const t = e.currentTarget;
|
|
125
|
+
C.value = { width: t.naturalWidth, height: t.naturalHeight }, k("naturalWidthChange", t.naturalWidth), k("naturalHeightChange", t.naturalHeight);
|
|
126
|
+
}, re = () => {
|
|
127
|
+
g.value = N.value("image.load_failed"), L.value = !0;
|
|
128
|
+
}, ue = () => {
|
|
129
|
+
l.value = { x: 0, y: 0 }, i.value = 1, k("zoomChange", 1);
|
|
130
|
+
}, $ = (e) => {
|
|
131
|
+
e.preventDefault(), e.stopPropagation();
|
|
132
|
+
const t = M.value;
|
|
133
|
+
if (!t) return;
|
|
134
|
+
const a = t.getBoundingClientRect(), c = e.clientX - a.left - a.width / 2, o = e.clientY - a.top - a.height / 2, s = e.deltaY > 0 ? -0.05 : 0.05, n = i.value, d = Math.max(0.01, Math.min(10, n + s)), h = d / n;
|
|
135
|
+
l.value = P(
|
|
136
|
+
{
|
|
137
|
+
x: c - h * (c - l.value.x),
|
|
138
|
+
y: o - h * (o - l.value.y)
|
|
139
|
+
},
|
|
140
|
+
d
|
|
141
|
+
), i.value = d, k("zoomChange", d);
|
|
142
|
+
};
|
|
143
|
+
pe(() => {
|
|
144
|
+
const e = M.value;
|
|
145
|
+
e && (e.addEventListener("wheel", $, { passive: !1 }), e.addEventListener("touchstart", A, { passive: !1 }), e.addEventListener("touchmove", F, { passive: !1 }), e.addEventListener("touchend", W), e.addEventListener("touchcancel", W));
|
|
146
|
+
}), Q(() => {
|
|
147
|
+
const e = M.value;
|
|
148
|
+
e && (e.removeEventListener("wheel", $), e.removeEventListener("touchstart", A), e.removeEventListener("touchmove", F), e.removeEventListener("touchend", W), e.removeEventListener("touchcancel", W));
|
|
149
|
+
});
|
|
150
|
+
const ie = (e) => {
|
|
151
|
+
B || e.button === 0 && (p.value = !0, E = {
|
|
152
|
+
x: e.clientX - l.value.x,
|
|
153
|
+
y: e.clientY - l.value.y
|
|
154
|
+
});
|
|
155
|
+
}, ce = (e) => {
|
|
156
|
+
B || p.value && (l.value = P(
|
|
157
|
+
{
|
|
158
|
+
x: e.clientX - E.x,
|
|
159
|
+
y: e.clientY - E.y
|
|
160
|
+
},
|
|
161
|
+
i.value
|
|
162
|
+
));
|
|
163
|
+
}, G = () => {
|
|
164
|
+
B || (p.value = !1);
|
|
165
|
+
}, A = (e) => {
|
|
166
|
+
B = !0, e.preventDefault();
|
|
167
|
+
const t = e.touches;
|
|
168
|
+
if (t.length === 1) {
|
|
169
|
+
p.value = !0, E = {
|
|
170
|
+
x: t[0].clientX - l.value.x,
|
|
171
|
+
y: t[0].clientY - l.value.y
|
|
172
|
+
};
|
|
173
|
+
const a = Date.now();
|
|
174
|
+
a - Z < 300 && (l.value = { x: 0, y: 0 }, i.value = 1, k("zoomChange", 1)), Z = a;
|
|
175
|
+
} else t.length === 2 && (p.value = !1, j = Math.hypot(
|
|
176
|
+
t[1].clientX - t[0].clientX,
|
|
177
|
+
t[1].clientY - t[0].clientY
|
|
178
|
+
), K = i.value, O = { ...l.value });
|
|
179
|
+
}, F = (e) => {
|
|
180
|
+
e.preventDefault();
|
|
181
|
+
const t = e.touches;
|
|
182
|
+
if (t.length === 1 && p.value)
|
|
183
|
+
l.value = P(
|
|
184
|
+
{
|
|
185
|
+
x: t[0].clientX - E.x,
|
|
186
|
+
y: t[0].clientY - E.y
|
|
187
|
+
},
|
|
188
|
+
i.value
|
|
189
|
+
);
|
|
190
|
+
else if (t.length === 2) {
|
|
191
|
+
const a = M.value;
|
|
192
|
+
if (!a) return;
|
|
193
|
+
const c = Math.hypot(
|
|
194
|
+
t[1].clientX - t[0].clientX,
|
|
195
|
+
t[1].clientY - t[0].clientY
|
|
196
|
+
);
|
|
197
|
+
if (Math.abs(c - j) < 5) return;
|
|
198
|
+
const o = c / j, s = Math.max(0.01, Math.min(10, K * o)), n = a.getBoundingClientRect(), d = (t[0].clientX + t[1].clientX) / 2 - n.left - n.width / 2, h = (t[0].clientY + t[1].clientY) / 2 - n.top - n.height / 2, z = s / i.value;
|
|
199
|
+
l.value = P(
|
|
200
|
+
{
|
|
201
|
+
x: d - z * (d - O.x),
|
|
202
|
+
y: h - z * (h - O.y)
|
|
203
|
+
},
|
|
204
|
+
s
|
|
205
|
+
), i.value = s, k("zoomChange", s);
|
|
206
|
+
}
|
|
207
|
+
}, W = () => {
|
|
208
|
+
p.value = !1, j = 0;
|
|
209
|
+
}, ve = I(() => ({
|
|
210
|
+
transform: `translate(${l.value.x}px, ${l.value.y}px) scale(${i.value}) rotate(${u.rotation}deg)`,
|
|
211
|
+
transformOrigin: "center",
|
|
212
|
+
transition: p.value ? "none" : "transform 0.3s ease-out",
|
|
213
|
+
opacity: L.value && !g.value && !y.value ? 1 : 0
|
|
214
|
+
})), fe = I(() => u.fileSize == null ? "" : ` · ${Le(u.fileSize)}`);
|
|
215
|
+
return (e, t) => (m(), _("div", {
|
|
216
|
+
ref_key: "containerRef",
|
|
217
|
+
ref: M,
|
|
218
|
+
class: "vfp-relative vfp-flex vfp-items-center vfp-justify-center vfp-w-full vfp-h-full vfp-overflow-hidden",
|
|
219
|
+
style: J({ cursor: p.value ? "grabbing" : "grab", touchAction: "none" }),
|
|
220
|
+
onMousedown: ie,
|
|
221
|
+
onMousemove: ce,
|
|
222
|
+
onMouseup: G,
|
|
223
|
+
onMouseleave: G
|
|
224
|
+
}, [
|
|
225
|
+
v.value ? (m(), _("div", Ce, [
|
|
226
|
+
he(ee(ye), { class: "vfp-w-12 vfp-h-12 vfp-text-fg-primary vfp-animate-spin" }),
|
|
227
|
+
S("p", Me, [
|
|
228
|
+
t[2] || (t[2] = me(" 正在解码... ", -1)),
|
|
229
|
+
X.value > 0 ? (m(), _("span", _e, Y(Math.round(X.value)) + "%", 1)) : w("", !0)
|
|
230
|
+
])
|
|
231
|
+
])) : w("", !0),
|
|
232
|
+
y.value ? (m(), te(ae, {
|
|
233
|
+
key: 1,
|
|
234
|
+
message: ee(N)("image.decode_failed"),
|
|
235
|
+
detail: y.value
|
|
236
|
+
}, null, 8, ["message", "detail"])) : w("", !0),
|
|
237
|
+
!L.value && !g.value && !v.value && !y.value ? (m(), _("div", ke, [...t[3] || (t[3] = [
|
|
238
|
+
S("div", { class: "vfp-w-12 vfp-h-12 vfp-border-4 vfp-border-line-strong vfp-border-t-spinner-head vfp-rounded-full vfp-animate-spin" }, null, -1)
|
|
239
|
+
])])) : w("", !0),
|
|
240
|
+
g.value ? (m(), te(ae, {
|
|
241
|
+
key: 3,
|
|
242
|
+
message: g.value
|
|
243
|
+
}, null, 8, ["message"])) : w("", !0),
|
|
244
|
+
b.value ? (m(), _("img", {
|
|
245
|
+
key: 4,
|
|
246
|
+
ref_key: "imgRef",
|
|
247
|
+
ref: oe,
|
|
248
|
+
src: b.value,
|
|
249
|
+
alt: "Preview",
|
|
250
|
+
class: ge(["vfp-max-w-none vfp-select-none", (!L.value || g.value || y.value) && "vfp-hidden"]),
|
|
251
|
+
style: J(ve.value),
|
|
252
|
+
draggable: !1,
|
|
253
|
+
onLoad: se,
|
|
254
|
+
onError: re,
|
|
255
|
+
onDblclick: ue
|
|
256
|
+
}, null, 46, Re)) : w("", !0),
|
|
257
|
+
L.value && !g.value && C.value.width > 0 ? (m(), _("div", Ee, Y(C.value.width) + " × " + Y(C.value.height) + Y(fe.value), 1)) : w("", !0),
|
|
258
|
+
R.value > 1 ? (m(), _("div", Ue, [
|
|
259
|
+
S("button", {
|
|
260
|
+
type: "button",
|
|
261
|
+
disabled: x.value <= 1 || v.value,
|
|
262
|
+
class: "vfp-px-2 vfp-py-0.5 vfp-rounded hover:vfp-bg-surface-nav-hover disabled:vfp-opacity-40 disabled:vfp-cursor-not-allowed",
|
|
263
|
+
onClick: t[0] || (t[0] = (a) => q(x.value - 1))
|
|
264
|
+
}, " 上一页 ", 8, ze),
|
|
265
|
+
S("span", Ye, Y(x.value) + " / " + Y(R.value), 1),
|
|
266
|
+
S("button", {
|
|
267
|
+
type: "button",
|
|
268
|
+
disabled: x.value >= R.value || v.value,
|
|
269
|
+
class: "vfp-px-2 vfp-py-0.5 vfp-rounded hover:vfp-bg-surface-nav-hover disabled:vfp-opacity-40 disabled:vfp-cursor-not-allowed",
|
|
270
|
+
onClick: t[1] || (t[1] = (a) => q(x.value + 1))
|
|
271
|
+
}, " 下一页 ", 8, Se)
|
|
272
|
+
])) : w("", !0)
|
|
273
|
+
], 36));
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
export {
|
|
277
|
+
je as default
|
|
278
|
+
};
|
|
279
|
+
//# sourceMappingURL=index-DT9dPz8I.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-DT9dPz8I.mjs","sources":["../../src/renderers/Image/index.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, watch, onMounted, onBeforeUnmount, computed } from 'vue';\nimport { Loader2 } from 'lucide-vue-next';\nimport { formatFileSize, detectImageFormat, getLoaderForMimeType } from '@eternalheart/file-preview-core';\nimport type { PreviewFile } from '@eternalheart/file-preview-core';\nimport { useTranslator } from '../../composables/useTranslator';\nimport RendererError from '../RendererError.vue';\n\nconst props = defineProps<{\n url: string;\n zoom: number;\n rotation: number;\n resetKey?: number;\n fileSize?: number;\n file?: PreviewFile | File;\n}>();\n\nconst emit = defineEmits<{\n (e: 'zoomChange', zoom: number): void;\n (e: 'naturalWidthChange', width: number): void;\n (e: 'naturalHeightChange', height: number): void;\n}>();\n\nconst { t } = useTranslator();\n\nconst loaded = ref(false);\nconst error = ref<string | null>(null);\nconst decoding = ref(false);\nconst decodeProgress = ref(0);\nconst decodeError = ref<string | null>(null);\nconst imageSrc = ref<string>('');\nconst currentPage = ref(1);\nconst totalPages = ref(1);\nconst isRawThumbnail = ref(false);\nconst position = ref({ x: 0, y: 0 });\nconst isDragging = ref(false);\nlet dragStart = { x: 0, y: 0 };\nconst internalZoom = ref(1);\nconst naturalSize = ref({ width: 0, height: 0 });\n\nconst imgRef = ref<HTMLImageElement | null>(null);\nconst containerRef = ref<HTMLDivElement | null>(null);\nlet blobUrl: string | null = null;\nlet fileBlobCache: Blob | null = null;\nlet loaderCache: any = null;\nconst pageCache = new Map<number, string>();\n\nlet isTouchDevice = false;\nlet touchStartDistance = 0;\nlet touchStartZoom = 1;\nlet touchStartPos = { x: 0, y: 0 };\nlet lastTapTime = 0;\n\n// 解码逻辑\nwatch(\n () => [props.url, props.file] as const,\n async () => {\n // 重置状态:清空 src 以避免上一张图片的 onLoad/onError 误触发到新文件\n imageSrc.value = '';\n loaded.value = false;\n error.value = null;\n decoding.value = false;\n decodeError.value = null;\n decodeProgress.value = 0;\n position.value = { x: 0, y: 0 };\n internalZoom.value = 1;\n currentPage.value = 1;\n totalPages.value = 1;\n isRawThumbnail.value = false;\n\n // 清理旧的 blob URL 与缓存\n if (blobUrl) {\n URL.revokeObjectURL(blobUrl);\n blobUrl = null;\n }\n pageCache.forEach((url) => URL.revokeObjectURL(url));\n pageCache.clear();\n fileBlobCache = null;\n loaderCache = null;\n\n // 如果没有 file 对象,直接使用 url\n if (!props.file) {\n imageSrc.value = props.url;\n return;\n }\n\n try {\n // 检测图片格式\n const mimeType = await detectImageFormat(props.file);\n const loader = await getLoaderForMimeType(mimeType);\n\n // 如果不需要解码,直接使用原 URL\n if (!loader || !(await loader.needsDecode(mimeType))) {\n imageSrc.value = props.url;\n return;\n }\n\n // 需要解码\n decoding.value = true;\n\n // 获取文件 Blob\n let fileBlob: Blob;\n if (props.file instanceof Blob) {\n fileBlob = props.file;\n } else {\n const response = await fetch(props.url);\n if (!response.ok) throw new Error('Failed to fetch file');\n fileBlob = await response.blob();\n }\n\n // 缓存 Blob 与 loader\n fileBlobCache = fileBlob;\n loaderCache = loader;\n\n // 标记 RAW 缩略图模式\n const isRaw = mimeType.startsWith('image/x-');\n if (isRaw) {\n isRawThumbnail.value = true;\n }\n\n // 获取元数据(用于检测多页 TIFF)\n if (loader.getMetadata) {\n try {\n const metadata = await loader.getMetadata(fileBlob);\n if (metadata.pageCount && metadata.pageCount > 1) {\n totalPages.value = metadata.pageCount;\n }\n } catch {\n // 忽略元数据获取失败\n }\n }\n\n // 调用 loader 解码(第 1 页 / 缩略图模式)\n const decodedBlob = await loader.decode(fileBlob, {\n page: 1,\n fullQuality: false,\n onProgress: (percent: number) => {\n decodeProgress.value = percent;\n },\n });\n\n // 生成 blob URL\n const url = typeof decodedBlob === 'string'\n ? decodedBlob\n : URL.createObjectURL(decodedBlob);\n\n blobUrl = url;\n pageCache.set(1, url);\n imageSrc.value = url;\n decoding.value = false;\n } catch (err: any) {\n decodeError.value = err?.message || '解码失败';\n decoding.value = false;\n }\n },\n { immediate: true }\n);\n\n// 多页 TIFF 翻页\nconst handlePageChange = async (page: number) => {\n if (!fileBlobCache || !loaderCache) return;\n if (page < 1 || page > totalPages.value) return;\n\n // 命中缓存:直接切换\n const cached = pageCache.get(page);\n if (cached) {\n currentPage.value = page;\n imageSrc.value = cached;\n return;\n }\n\n // 解码新页面\n decoding.value = true;\n try {\n const decodedBlob = await loaderCache.decode(fileBlobCache, { page });\n const url = typeof decodedBlob === 'string'\n ? decodedBlob\n : URL.createObjectURL(decodedBlob);\n\n // LRU:缓存超过 10 页时删除最早的\n if (pageCache.size >= 10) {\n const firstKey = pageCache.keys().next().value;\n if (firstKey !== undefined) {\n const oldUrl = pageCache.get(firstKey);\n if (oldUrl) URL.revokeObjectURL(oldUrl);\n pageCache.delete(firstKey);\n }\n }\n\n pageCache.set(page, url);\n currentPage.value = page;\n imageSrc.value = url;\n decoding.value = false;\n } catch (err: any) {\n decodeError.value = err?.message || '翻页解码失败';\n decoding.value = false;\n }\n};\n\n// Cleanup on unmount\nonBeforeUnmount(() => {\n if (blobUrl) {\n URL.revokeObjectURL(blobUrl);\n }\n pageCache.forEach((url) => URL.revokeObjectURL(url));\n pageCache.clear();\n const container = containerRef.value;\n if (container) {\n container.removeEventListener('wheel', handleWheelNative);\n }\n});\n\nwatch(\n () => props.zoom,\n (z) => {\n internalZoom.value = z;\n }\n);\n\nwatch(\n () => props.resetKey,\n () => {\n position.value = { x: 0, y: 0 };\n }\n);\n\nconst clampPosition = (pos: { x: number; y: number }, currentZoom: number) => {\n const container = containerRef.value;\n if (!container || naturalSize.value.width === 0) return pos;\n\n const containerW = container.clientWidth;\n const containerH = container.clientHeight;\n const imgW = naturalSize.value.width * currentZoom;\n const imgH = naturalSize.value.height * currentZoom;\n\n const margin = Math.min(80, containerW * 0.15, containerH * 0.15);\n const rangeX = (containerW + imgW) / 2 - margin;\n const rangeY = (containerH + imgH) / 2 - margin;\n\n return {\n x: rangeX > 0 ? Math.max(-rangeX, Math.min(rangeX, pos.x)) : 0,\n y: rangeY > 0 ? Math.max(-rangeY, Math.min(rangeY, pos.y)) : 0,\n };\n};\n\nconst handleLoad = (e: Event) => {\n loaded.value = true;\n const img = e.currentTarget as HTMLImageElement;\n naturalSize.value = { width: img.naturalWidth, height: img.naturalHeight };\n emit('naturalWidthChange', img.naturalWidth);\n emit('naturalHeightChange', img.naturalHeight);\n};\n\nconst handleError = () => {\n error.value = t.value('image.load_failed');\n loaded.value = true;\n};\n\nconst handleDoubleClick = () => {\n position.value = { x: 0, y: 0 };\n internalZoom.value = 1;\n emit('zoomChange', 1);\n};\n\n// 鼠标滚轮缩放\nconst handleWheelNative = (e: WheelEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n const container = containerRef.value;\n if (!container) return;\n\n const rect = container.getBoundingClientRect();\n const mouseX = e.clientX - rect.left - rect.width / 2;\n const mouseY = e.clientY - rect.top - rect.height / 2;\n\n const delta = e.deltaY > 0 ? -0.05 : 0.05;\n const prev = internalZoom.value;\n const newZoom = Math.max(0.01, Math.min(10, prev + delta));\n const scale = newZoom / prev;\n\n position.value = clampPosition(\n {\n x: mouseX - scale * (mouseX - position.value.x),\n y: mouseY - scale * (mouseY - position.value.y),\n },\n newZoom\n );\n\n internalZoom.value = newZoom;\n emit('zoomChange', newZoom);\n};\n\nonMounted(() => {\n const container = containerRef.value;\n if (container) {\n container.addEventListener('wheel', handleWheelNative, { passive: false });\n container.addEventListener('touchstart', handleTouchStart, { passive: false });\n container.addEventListener('touchmove', handleTouchMove, { passive: false });\n container.addEventListener('touchend', handleTouchEnd);\n container.addEventListener('touchcancel', handleTouchEnd);\n }\n});\n\nonBeforeUnmount(() => {\n const container = containerRef.value;\n if (container) {\n container.removeEventListener('wheel', handleWheelNative);\n container.removeEventListener('touchstart', handleTouchStart);\n container.removeEventListener('touchmove', handleTouchMove);\n container.removeEventListener('touchend', handleTouchEnd);\n container.removeEventListener('touchcancel', handleTouchEnd);\n }\n});\n\nconst handleMouseDown = (e: MouseEvent) => {\n if (isTouchDevice) return;\n if (e.button !== 0) return;\n isDragging.value = true;\n dragStart = {\n x: e.clientX - position.value.x,\n y: e.clientY - position.value.y,\n };\n};\n\nconst handleMouseMove = (e: MouseEvent) => {\n if (isTouchDevice) return;\n if (!isDragging.value) return;\n position.value = clampPosition(\n {\n x: e.clientX - dragStart.x,\n y: e.clientY - dragStart.y,\n },\n internalZoom.value\n );\n};\n\nconst handleMouseUp = () => {\n if (isTouchDevice) return;\n isDragging.value = false;\n};\n\n// 触屏事件处理\nconst handleTouchStart = (e: TouchEvent) => {\n isTouchDevice = true;\n e.preventDefault();\n\n const touches = e.touches;\n if (touches.length === 1) {\n // 单指拖拽\n isDragging.value = true;\n dragStart = {\n x: touches[0].clientX - position.value.x,\n y: touches[0].clientY - position.value.y,\n };\n\n // 双击检测\n const now = Date.now();\n if (now - lastTapTime < 300) {\n // 双击复原:居中 + 缩放100%\n position.value = { x: 0, y: 0 };\n internalZoom.value = 1;\n emit('zoomChange', 1);\n }\n lastTapTime = now;\n } else if (touches.length === 2) {\n // 双指缩放初始化\n isDragging.value = false;\n const distance = Math.hypot(\n touches[1].clientX - touches[0].clientX,\n touches[1].clientY - touches[0].clientY\n );\n touchStartDistance = distance;\n touchStartZoom = internalZoom.value;\n touchStartPos = { ...position.value };\n }\n};\n\nconst handleTouchMove = (e: TouchEvent) => {\n e.preventDefault();\n\n const touches = e.touches;\n if (touches.length === 1 && isDragging.value) {\n // 单指拖拽\n position.value = clampPosition(\n {\n x: touches[0].clientX - dragStart.x,\n y: touches[0].clientY - dragStart.y,\n },\n internalZoom.value\n );\n } else if (touches.length === 2) {\n // 双指缩放\n const container = containerRef.value;\n if (!container) return;\n\n const distance = Math.hypot(\n touches[1].clientX - touches[0].clientX,\n touches[1].clientY - touches[0].clientY\n );\n\n // 最小距离变化阈值,防止抖动\n if (Math.abs(distance - touchStartDistance) < 5) return;\n\n const scale = distance / touchStartDistance;\n const newZoom = Math.max(0.01, Math.min(10, touchStartZoom * scale));\n\n // 双指中心点作为缩放原点\n const rect = container.getBoundingClientRect();\n const centerX = (touches[0].clientX + touches[1].clientX) / 2 - rect.left - rect.width / 2;\n const centerY = (touches[0].clientY + touches[1].clientY) / 2 - rect.top - rect.height / 2;\n\n const zoomScale = newZoom / internalZoom.value;\n position.value = clampPosition(\n {\n x: centerX - zoomScale * (centerX - touchStartPos.x),\n y: centerY - zoomScale * (centerY - touchStartPos.y),\n },\n newZoom\n );\n\n internalZoom.value = newZoom;\n emit('zoomChange', newZoom);\n }\n};\n\nconst handleTouchEnd = () => {\n isDragging.value = false;\n touchStartDistance = 0;\n};\n\nconst transformStyle = computed(() => ({\n transform: `translate(${position.value.x}px, ${position.value.y}px) scale(${internalZoom.value}) rotate(${props.rotation}deg)`,\n transformOrigin: 'center',\n transition: isDragging.value ? 'none' : 'transform 0.3s ease-out',\n opacity: loaded.value && !error.value && !decodeError.value ? 1 : 0,\n}));\n\nconst sizeText = computed(() => {\n if (props.fileSize == null) return '';\n return ` · ${formatFileSize(props.fileSize)}`;\n});\n</script>\n\n<template>\n <div\n ref=\"containerRef\"\n class=\"vfp-relative vfp-flex vfp-items-center vfp-justify-center vfp-w-full vfp-h-full vfp-overflow-hidden\"\n :style=\"{ cursor: isDragging ? 'grabbing' : 'grab', touchAction: 'none' }\"\n @mousedown=\"handleMouseDown\"\n @mousemove=\"handleMouseMove\"\n @mouseup=\"handleMouseUp\"\n @mouseleave=\"handleMouseUp\"\n >\n <!-- 解码中 -->\n <div\n v-if=\"decoding\"\n class=\"vfp-absolute vfp-inset-0 vfp-flex vfp-flex-col vfp-items-center vfp-justify-center vfp-bg-surface-1/80 vfp-z-10\"\n >\n <Loader2 class=\"vfp-w-12 vfp-h-12 vfp-text-fg-primary vfp-animate-spin\" />\n <p class=\"vfp-mt-4 vfp-text-fg-secondary\">\n 正在解码... <span v-if=\"decodeProgress > 0\">{{ Math.round(decodeProgress) }}%</span>\n </p>\n </div>\n\n <!-- 解码错误 -->\n <RendererError v-if=\"decodeError\" :message=\"t('image.decode_failed')\" :detail=\"decodeError\" />\n\n <div v-if=\"!loaded && !error && !decoding && !decodeError\" class=\"vfp-flex vfp-items-center vfp-justify-center\">\n <div\n class=\"vfp-w-12 vfp-h-12 vfp-border-4 vfp-border-line-strong vfp-border-t-spinner-head vfp-rounded-full vfp-animate-spin\"\n />\n </div>\n\n <RendererError v-if=\"error\" :message=\"error\" />\n\n <img\n v-if=\"imageSrc\"\n ref=\"imgRef\"\n :src=\"imageSrc\"\n alt=\"Preview\"\n :class=\"['vfp-max-w-none vfp-select-none', (!loaded || error || decodeError) && 'vfp-hidden']\"\n :style=\"transformStyle\"\n :draggable=\"false\"\n @load=\"handleLoad\"\n @error=\"handleError\"\n @dblclick=\"handleDoubleClick\"\n />\n\n <div\n v-if=\"loaded && !error && naturalSize.width > 0\"\n class=\"vfp-absolute vfp-bottom-2 vfp-right-3 vfp-text-[10px] vfp-text-fg-disabled hover:vfp-text-fg-secondary vfp-transition-colors vfp-pointer-events-auto vfp-select-none vfp-cursor-default\"\n >\n {{ naturalSize.width }} × {{ naturalSize.height }}{{ sizeText }}\n </div>\n\n <!-- 多页 TIFF 翻页器 -->\n <div\n v-if=\"totalPages > 1\"\n class=\"vfp-absolute vfp-bottom-2 vfp-left-1/2 -vfp-translate-x-1/2 vfp-flex vfp-items-center vfp-gap-2 vfp-px-3 vfp-py-1.5 vfp-bg-surface-toolbar vfp-border vfp-border-line vfp-rounded-lg vfp-text-sm vfp-text-fg-primary vfp-shadow-md\"\n >\n <button\n type=\"button\"\n :disabled=\"currentPage <= 1 || decoding\"\n class=\"vfp-px-2 vfp-py-0.5 vfp-rounded hover:vfp-bg-surface-nav-hover disabled:vfp-opacity-40 disabled:vfp-cursor-not-allowed\"\n @click=\"handlePageChange(currentPage - 1)\"\n >\n 上一页\n </button>\n <span class=\"vfp-text-fg-secondary vfp-tabular-nums\">\n {{ currentPage }} / {{ totalPages }}\n </span>\n <button\n type=\"button\"\n :disabled=\"currentPage >= totalPages || decoding\"\n class=\"vfp-px-2 vfp-py-0.5 vfp-rounded hover:vfp-bg-surface-nav-hover disabled:vfp-opacity-40 disabled:vfp-cursor-not-allowed\"\n @click=\"handlePageChange(currentPage + 1)\"\n >\n 下一页\n </button>\n </div>\n </div>\n</template>\n"],"names":["props","__props","emit","__emit","t","useTranslator","loaded","ref","error","decoding","decodeProgress","decodeError","imageSrc","currentPage","totalPages","isRawThumbnail","position","isDragging","dragStart","internalZoom","naturalSize","imgRef","containerRef","blobUrl","fileBlobCache","loaderCache","pageCache","isTouchDevice","touchStartDistance","touchStartZoom","touchStartPos","lastTapTime","watch","url","mimeType","detectImageFormat","loader","getLoaderForMimeType","fileBlob","response","metadata","decodedBlob","percent","err","handlePageChange","page","cached","firstKey","oldUrl","onBeforeUnmount","container","handleWheelNative","z","clampPosition","pos","currentZoom","containerW","containerH","imgW","imgH","margin","rangeX","rangeY","handleLoad","img","handleError","handleDoubleClick","rect","mouseX","mouseY","delta","prev","newZoom","scale","onMounted","handleTouchStart","handleTouchMove","handleTouchEnd","handleMouseDown","handleMouseMove","handleMouseUp","touches","now","distance","centerX","centerY","zoomScale","transformStyle","computed","sizeText","formatFileSize","_createElementBlock","_openBlock","_hoisted_1","_createVNode","_unref","Loader2","_createElementVNode","_hoisted_2","_createBlock","RendererError","_hoisted_4","_cache","_normalizeClass","_hoisted_6","_toDisplayString","_hoisted_7","$event","_hoisted_8","_hoisted_9","_hoisted_10"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { defineComponent as y, ref as n, computed as _, watch as d, openBlock as e, createElementBlock as o, createElementVNode as m, createBlock as x, normalizeClass as h, toDisplayString as
|
|
2
|
-
import { u as
|
|
1
|
+
import { defineComponent as y, ref as n, computed as _, watch as d, openBlock as e, createElementBlock as o, createElementVNode as m, createBlock as x, normalizeClass as h, toDisplayString as b } from "vue";
|
|
2
|
+
import { u as k, a as T, c as B, y as E, E as N, _ as H } from "./index-Oxwizt6-.mjs";
|
|
3
3
|
import { codeToHtml as W } from "shiki";
|
|
4
4
|
import { _ as C } from "./RendererError.vue_vue_type_script_setup_true_lang-CbgZBSDr.mjs";
|
|
5
5
|
const L = {
|
|
@@ -21,7 +21,7 @@ const L = {
|
|
|
21
21
|
htmlPreview: { type: Boolean, default: !1 }
|
|
22
22
|
},
|
|
23
23
|
setup(l) {
|
|
24
|
-
const u = l, { t: w } =
|
|
24
|
+
const u = l, { t: w } = k(), g = T(), c = B(), r = n(""), t = n(""), v = n(!0), s = n(null), f = _(() => E(u.fileName)), i = async () => {
|
|
25
25
|
v.value = !0, s.value = null;
|
|
26
26
|
try {
|
|
27
27
|
const a = await N(u.url, { fetcher: g.value });
|
|
@@ -64,11 +64,11 @@ const L = {
|
|
|
64
64
|
}, null, 10, z)) : (e(), o("pre", {
|
|
65
65
|
key: 0,
|
|
66
66
|
class: h(["vfp-p-6 vfp-text-fg-primary vfp-font-mono vfp-text-sm", l.wordWrap ? "vfp-whitespace-pre-wrap vfp-break-words" : "vfp-whitespace-pre"])
|
|
67
|
-
},
|
|
67
|
+
}, b(r.value), 3))
|
|
68
68
|
]));
|
|
69
69
|
}
|
|
70
|
-
}), V = /* @__PURE__ */ H(D, [["__scopeId", "data-v-
|
|
70
|
+
}), V = /* @__PURE__ */ H(D, [["__scopeId", "data-v-b5fe3bc0"]]);
|
|
71
71
|
export {
|
|
72
72
|
V as default
|
|
73
73
|
};
|
|
74
|
-
//# sourceMappingURL=index-
|
|
74
|
+
//# sourceMappingURL=index-DTtHrdBl.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-
|
|
1
|
+
{"version":3,"file":"index-DTtHrdBl.mjs","sources":["../../src/renderers/Text/index.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, watch } from 'vue';\nimport { getLanguageFromFileName, fetchTextUtf8 } from '@eternalheart/file-preview-core';\nimport { codeToHtml } from 'shiki';\nimport { useTranslator } from '../../composables/useTranslator';\nimport { useFetcher } from '../../composables/useRequest';\nimport { useResolvedTheme } from '../../composables/useResolvedTheme';\nimport RendererError from '../RendererError.vue';\n\nconst props = withDefaults(defineProps<{\n url: string;\n fileName: string;\n wordWrap?: boolean;\n htmlPreview?: boolean;\n}>(), {\n wordWrap: true,\n htmlPreview: false,\n});\n\nconst { t } = useTranslator();\nconst fetcher = useFetcher();\nconst resolvedTheme = useResolvedTheme();\n\nconst content = ref<string>('');\nconst highlighted = ref<string>('');\nconst loading = ref(true);\nconst error = ref<string | null>(null);\n\nconst language = computed(() => getLanguageFromFileName(props.fileName));\n\nconst loadText = async () => {\n loading.value = true;\n error.value = null;\n try {\n const text = await fetchTextUtf8(props.url, { fetcher: fetcher.value });\n content.value = text;\n\n if (language.value !== 'text') {\n try {\n highlighted.value = await codeToHtml(text, {\n lang: language.value,\n theme: resolvedTheme.value === 'light' ? 'github-light' : 'dark-plus',\n });\n } catch {\n highlighted.value = '';\n }\n } else {\n highlighted.value = '';\n }\n } catch (err) {\n console.error(err);\n error.value = t.value('text.load_failed');\n } finally {\n loading.value = false;\n }\n};\n\nwatch(() => props.url, loadText, { immediate: true });\nwatch(resolvedTheme, () => {\n // 主题切换时重新高亮\n if (content.value && language.value !== 'text') {\n loadText();\n }\n});\n</script>\n\n<template>\n <div v-if=\"loading\" class=\"vfp-flex vfp-items-center vfp-justify-center vfp-w-full vfp-h-full\">\n <div\n class=\"vfp-w-12 vfp-h-12 vfp-border-4 vfp-border-line-strong vfp-border-t-spinner-head vfp-rounded-full vfp-animate-spin\"\n />\n </div>\n\n <RendererError v-else-if=\"error\" :message=\"error\" />\n\n <!-- HTML 预览模式 -->\n <div v-else-if=\"htmlPreview && language === 'html'\" class=\"vfp-w-full vfp-h-full vfp-bg-surface-toolbar\">\n <iframe\n :srcdoc=\"content\"\n sandbox=\"allow-same-origin\"\n class=\"vfp-w-full vfp-h-full vfp-border-0\"\n :title=\"fileName\"\n />\n </div>\n\n <!-- 源码模式 -->\n <div v-else class=\"vfp-w-full vfp-h-full vfp-overflow-auto\" style=\"background: var(--fp-code-bg);\">\n <pre\n v-if=\"!highlighted\"\n class=\"vfp-p-6 vfp-text-fg-primary vfp-font-mono vfp-text-sm\"\n :class=\"wordWrap ? 'vfp-whitespace-pre-wrap vfp-break-words' : 'vfp-whitespace-pre'\"\n >{{ content }}</pre>\n <div v-else class=\"shiki-wrapper\" :class=\"{ 'no-wrap': !wordWrap }\" v-html=\"highlighted\" />\n </div>\n</template>\n\n<style scoped>\n.shiki-wrapper :deep(pre) {\n margin: 0;\n padding: 1.5rem 1.5rem 1.5rem 0;\n background: transparent !important;\n font-size: 0.875rem;\n overflow-x: auto;\n}\n.shiki-wrapper :deep(code) {\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n counter-reset: line;\n}\n.shiki-wrapper :deep(code .line) {\n counter-increment: line;\n display: inline-block;\n width: 100%;\n padding-left: 4.5em;\n text-indent: -4.5em;\n}\n.shiki-wrapper :deep(code .line::before) {\n content: counter(line);\n display: inline-block;\n width: 3em;\n padding-right: 1em;\n margin-right: 0.5em;\n text-align: right;\n color: var(--fp-fg-disabled);\n user-select: none;\n border-right: 1px solid var(--fp-line);\n}\n.shiki-wrapper.no-wrap :deep(code) {\n white-space: pre;\n word-break: normal;\n overflow-wrap: normal;\n}\n.shiki-wrapper:not(.no-wrap) :deep(code) {\n white-space: pre-wrap;\n word-break: break-word;\n overflow-wrap: break-word;\n}\n</style>\n"],"names":["props","__props","t","useTranslator","fetcher","useFetcher","resolvedTheme","useResolvedTheme","content","ref","highlighted","loading","error","language","computed","getLanguageFromFileName","loadText","text","fetchTextUtf8","codeToHtml","err","watch","_openBlock","_createElementBlock","_hoisted_1","_cache","_createElementVNode","_createBlock","RendererError","_hoisted_2","_hoisted_4","_normalizeClass"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AASA,UAAMA,IAAQC,GAUR,EAAE,GAAAC,EAAA,IAAMC,EAAA,GACRC,IAAUC,EAAA,GACVC,IAAgBC,EAAA,GAEhBC,IAAUC,EAAY,EAAE,GACxBC,IAAcD,EAAY,EAAE,GAC5BE,IAAUF,EAAI,EAAI,GAClBG,IAAQH,EAAmB,IAAI,GAE/BI,IAAWC,EAAS,MAAMC,EAAwBf,EAAM,QAAQ,CAAC,GAEjEgB,IAAW,YAAY;AAC3B,MAAAL,EAAQ,QAAQ,IAChBC,EAAM,QAAQ;AACd,UAAI;AACF,cAAMK,IAAO,MAAMC,EAAclB,EAAM,KAAK,EAAE,SAASI,EAAQ,OAAO;AAGtE,YAFAI,EAAQ,QAAQS,GAEZJ,EAAS,UAAU;AACrB,cAAI;AACF,YAAAH,EAAY,QAAQ,MAAMS,EAAWF,GAAM;AAAA,cACzC,MAAMJ,EAAS;AAAA,cACf,OAAOP,EAAc,UAAU,UAAU,iBAAiB;AAAA,YAAA,CAC3D;AAAA,UACH,QAAQ;AACN,YAAAI,EAAY,QAAQ;AAAA,UACtB;AAAA;AAEA,UAAAA,EAAY,QAAQ;AAAA,MAExB,SAASU,GAAK;AACZ,gBAAQ,MAAMA,CAAG,GACjBR,EAAM,QAAQV,EAAE,MAAM,kBAAkB;AAAA,MAC1C,UAAA;AACE,QAAAS,EAAQ,QAAQ;AAAA,MAClB;AAAA,IACF;AAEA,WAAAU,EAAM,MAAMrB,EAAM,KAAKgB,GAAU,EAAE,WAAW,IAAM,GACpDK,EAAMf,GAAe,MAAM;AAEzB,MAAIE,EAAQ,SAASK,EAAS,UAAU,UACtCG,EAAA;AAAA,IAEJ,CAAC,aAIYL,EAAA,SAAXW,EAAA,GAAAC,EAIM,OAJNC,GAIM,CAAA,GAAAC,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,MAHJC,EAEE,OAAA,EADA,OAAM,oHAAA,GAAmH,MAAA,EAAA;AAAA,IAAA,QAInGd,EAAA,cAA1Be,EAAoDC,GAAA;AAAA;MAAlB,SAAShB,EAAA;AAAA,IAAA,4BAG3BX,EAAA,eAAeY,EAAA,UAAQ,UAAvCS,EAAA,GAAAC,EAOM,OAPNM,GAOM;AAAA,MANJH,EAKE,UAAA;AAAA,QAJC,QAAQlB,EAAA;AAAA,QACT,SAAQ;AAAA,QACR,OAAM;AAAA,QACL,OAAOP,EAAA;AAAA,MAAA;WAKZqB,EAAA,GAAAC,EAOM,OAPNO,GAOM;AAAA,MALKpB,EAAA,cAITa,EAA2F,OAAA;AAAA;QAA/E,OAAKQ,EAAA,CAAC,iBAAe,EAAA,WAAA,CAAuB9B,EAAA,SAAA,CAAQ,CAAA;AAAA,QAAI,WAAQS,EAAA;AAAA,MAAA,yBAL5Ea,EAIoB,OAAA;AAAA;QAFlB,OAAKQ,EAAA,CAAC,yDACE9B,EAAA,WAAQ,4CAAA,oBAAA,CAAA;AAAA,MAAA,KACdO,EAAA,KAAO,GAAA,CAAA;AAAA;;;"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineComponent as ee, ref as h, onMounted as te, watch as oe, onBeforeUnmount as re, openBlock as c, createElementBlock as p, createBlock as ae, createCommentVNode as y, createElementVNode as v, normalizeStyle as b, toDisplayString as A, unref as X, createVNode as ne, Fragment as H, renderList as D } from "vue";
|
|
2
2
|
import le from "@likecoin/epub-ts";
|
|
3
3
|
import { X as se } from "lucide-vue-next";
|
|
4
|
-
import { u as ie, a as fe } from "./index-
|
|
4
|
+
import { u as ie, a as fe } from "./index-Oxwizt6-.mjs";
|
|
5
5
|
import { _ as ue } from "./RendererError.vue_vue_type_script_setup_true_lang-CbgZBSDr.mjs";
|
|
6
6
|
const ce = { class: "vfp-relative vfp-w-full vfp-h-full vfp-flex vfp-justify-center vfp-bg-surface-1 vfp-overflow-hidden" }, pe = {
|
|
7
7
|
key: 1,
|
|
@@ -245,4 +245,4 @@ const ce = { class: "vfp-relative vfp-w-full vfp-h-full vfp-flex vfp-justify-cen
|
|
|
245
245
|
export {
|
|
246
246
|
Ce as default
|
|
247
247
|
};
|
|
248
|
-
//# sourceMappingURL=index-
|
|
248
|
+
//# sourceMappingURL=index-DX_NBPzS.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-Dln8hyPZ.mjs","sources":["../../src/renderers/Epub/index.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, watch, onMounted, onBeforeUnmount } from 'vue';\nimport ePub from '@likecoin/epub-ts';\nimport { X } from 'lucide-vue-next';\nimport { useTranslator } from '../../composables/useTranslator';\nimport { useFetcher } from '../../composables/useRequest';\nimport RendererError from '../RendererError.vue';\n\ninterface TocItem {\n label: string;\n href: string;\n subitems?: TocItem[];\n}\n\ninterface RenditionLike {\n display: (target?: string) => Promise<unknown>;\n next: () => Promise<unknown>;\n prev: () => Promise<unknown>;\n on: (event: string, cb: (...args: unknown[]) => void) => void;\n resize: (width: number, height: number) => void;\n currentLocation: () => unknown;\n destroy?: () => void;\n themes: {\n register: (name: string, styles: Record<string, unknown>) => void;\n select: (name: string) => void;\n };\n}\n\ninterface BookLike {\n ready: Promise<unknown>;\n loaded: { navigation: Promise<unknown> };\n locations: {\n generate: (chars: number) => Promise<string[]>;\n length: () => number;\n locationFromCfi: (cfi: string) => number;\n };\n renderTo: (el: HTMLElement, opts: Record<string, unknown>) => RenditionLike;\n destroy: () => void;\n}\n\nconst A4_WIDTH = 794;\n\nconst props = defineProps<{ url: string }>();\n\nconst { t } = useTranslator();\nconst fetcher = useFetcher();\n\nconst emit = defineEmits<{\n (e: 'chapterChange', current: number, total: number): void;\n (e: 'fullWidthChange', isFullWidth: boolean): void;\n}>();\n\nconst viewerRef = ref<HTMLDivElement | null>(null);\nconst loading = ref(true);\nconst error = ref<string | null>(null);\nconst isFullWidth = ref(false);\nconst toc = ref<TocItem[]>([]);\nconst showToc = ref(false);\nconst activeTocHref = ref('');\n\nlet book: BookLike | null = null;\nlet rendition: RenditionLike | null = null;\nlet totalLocations = 0;\nlet lastCfi: string | null = null;\n\nconst cleanup = () => {\n try { rendition?.destroy?.(); } catch { /* ignore */ }\n try { book?.destroy(); } catch { /* ignore */ }\n rendition = null;\n book = null;\n totalLocations = 0;\n lastCfi = null;\n};\n\nconst prevPage = () => { rendition?.prev(); };\nconst nextPage = () => { rendition?.next(); };\nconst toggleFullWidth = () => {\n isFullWidth.value = !isFullWidth.value;\n emit('fullWidthChange', isFullWidth.value);\n setTimeout(() => {\n if (viewerRef.value && rendition) {\n rendition.resize(viewerRef.value.offsetWidth, viewerRef.value.offsetHeight);\n if (lastCfi) {\n rendition.display(lastCfi);\n }\n // resize/display 可能重建 .epub-container,需要重新绑定滚动监听\n reattachScrollListener();\n }\n }, 350);\n};\nconst toggleToc = () => { showToc.value = !showToc.value; };\nconst handleTocClick = (href: string) => {\n activeTocHref.value = href;\n rendition?.display(href);\n showToc.value = false;\n};\n\nconst isActive = (href: string) => {\n return href === activeTocHref.value;\n};\n\ndefineExpose({ prevPage, nextPage, toggleFullWidth, toggleToc });\n\nconst loadEpub = async () => {\n if (!viewerRef.value) return;\n\n loading.value = true;\n error.value = null;\n toc.value = [];\n showToc.value = false;\n viewerRef.value.innerHTML = '';\n cleanup();\n\n try {\n let bookInput: string | ArrayBuffer = props.url;\n if (props.url.startsWith('blob:')) {\n const resp = await fetcher.value(props.url);\n bookInput = await resp.arrayBuffer();\n }\n\n book = ePub(bookInput) as unknown as BookLike;\n\n rendition = book.renderTo(viewerRef.value, {\n manager: 'continuous',\n flow: 'scrolled',\n width: '100%',\n height: '100%',\n });\n\n rendition.themes.register('default', {\n body: {\n background: '#ffffff !important',\n color: '#1a1a1a !important',\n 'font-family': '\"Noto Serif SC\", \"Source Han Serif SC\", Georgia, \"Times New Roman\", serif !important',\n 'font-size': '16px !important',\n 'line-height': '2 !important',\n padding: '40px 60px !important',\n 'max-width': '100% !important',\n 'box-sizing': 'border-box !important',\n 'word-break': 'break-word !important',\n 'overflow-wrap': 'break-word !important',\n },\n p: { 'text-indent': '2em !important', margin: '0.8em 0 !important' },\n h1: { 'text-align': 'center !important', margin: '1.5em 0 1em !important' },\n h2: { margin: '1.2em 0 0.8em !important' },\n h3: { margin: '1em 0 0.6em !important' },\n img: { 'max-width': '100% !important', height: 'auto !important' },\n a: { color: '#2563eb !important', 'text-decoration': 'none !important' },\n });\n rendition.themes.select('default');\n\n await book.ready;\n\n // 异步生成 locations 索引\n book.locations.generate(1024).then(() => {\n if (!book) return;\n totalLocations = book.locations.length();\n const loc = rendition?.currentLocation() as { start?: { location?: number } } | undefined;\n const cur = loc?.start?.location ?? 0;\n emit('chapterChange', cur + 1, totalLocations);\n }).catch(() => { /* ignore */ });\n\n const nav = await book.loaded.navigation as { toc?: TocItem[] };\n if (Array.isArray(nav?.toc)) {\n toc.value = nav.toc;\n }\n\n await rendition.display();\n\n loading.value = false;\n emit('chapterChange', 1, totalLocations || 1);\n\n rendition.on('relocated', (location: unknown) => {\n const loc = location as { start?: { cfi?: string; location?: number; href?: string } };\n if (loc?.start?.cfi) {\n lastCfi = loc.start.cfi;\n }\n if (loc?.start?.href) {\n // 根据 spine href 查找匹配的 TOC 项\n const spineHref = loc.start.href;\n const matches: string[] = [];\n const collect = (items: TocItem[]) => {\n for (const item of items) {\n const base = item.href.split('#')[0];\n if (base && (spineHref === base || spineHref.endsWith('/' + base) || spineHref.endsWith(base))) {\n matches.push(item.href);\n }\n if (item.subitems) collect(item.subitems);\n }\n };\n collect(toc.value);\n if (matches.length === 1) {\n activeTocHref.value = matches[0];\n }\n // 多个匹配(同一文件不同 anchor)时保持当前选中(由点击设置)\n }\n const cur = loc?.start?.location;\n if (typeof cur === 'number' && totalLocations > 0) {\n emit('chapterChange', cur + 1, totalLocations);\n }\n });\n } catch (err) {\n console.error('EPUB 加载错误:', err);\n error.value = t.value('epub.load_failed');\n loading.value = false;\n }\n};\n\nconst onResize = () => {\n if (!viewerRef.value || !rendition) return;\n rendition.resize(viewerRef.value.offsetWidth, viewerRef.value.offsetHeight);\n};\n\n// 监听 epub-container 滚动,接近底部时强制加载后续 section\nlet scrollContainer: Element | null = null;\nconst onContainerScroll = () => {\n if (!scrollContainer) return;\n const el = scrollContainer as HTMLElement;\n if (el.scrollTop + el.clientHeight >= el.scrollHeight - 200) {\n try {\n const mgr = (rendition as unknown as { manager?: { check?: (t?: number, e?: number) => Promise<unknown> } })?.manager;\n // 传递垂直偏移量参数,让 check() 在接近底部时就触发加载下一节\n mgr?.check?.(500, 500);\n } catch { /* ignore */ }\n }\n};\n\nconst reattachScrollListener = () => {\n // 清理旧监听\n if (scrollContainer) {\n scrollContainer.removeEventListener('scroll', onContainerScroll);\n scrollContainer = null;\n }\n const tryAttach = () => {\n scrollContainer = viewerRef.value?.querySelector('.epub-container') ?? null;\n if (scrollContainer) {\n scrollContainer.addEventListener('scroll', onContainerScroll, { passive: true });\n } else {\n requestAnimationFrame(tryAttach);\n }\n };\n requestAnimationFrame(tryAttach);\n};\n\nonMounted(() => {\n loadEpub();\n window.addEventListener('resize', onResize);\n reattachScrollListener();\n});\n\nwatch(() => props.url, (newUrl) => {\n // 只有 URL 有效时才加载(避免空字符串或已 revoke 的 blob URL)\n if (newUrl) loadEpub();\n});\n\nonBeforeUnmount(() => {\n window.removeEventListener('resize', onResize);\n scrollContainer?.removeEventListener('scroll', onContainerScroll);\n cleanup();\n});\n</script>\n\n<template>\n <div class=\"vfp-relative vfp-w-full vfp-h-full vfp-flex vfp-justify-center vfp-bg-surface-1 vfp-overflow-hidden\">\n <RendererError v-if=\"error\" :message=\"error\" class=\"vfp-absolute vfp-inset-0\" />\n\n <div\n v-if=\"loading && !error\"\n class=\"vfp-absolute vfp-inset-0 vfp-flex vfp-items-center vfp-justify-center vfp-z-10\"\n >\n <div class=\"vfp-w-12 vfp-h-12 vfp-border-4 vfp-border-line-strong vfp-border-t-spinner-head vfp-rounded-full vfp-animate-spin\" />\n </div>\n\n <!-- 目录侧栏 - 滑入动画 -->\n <div\n v-if=\"toc.length > 0\"\n class=\"vfp-absolute vfp-inset-0 vfp-z-20 vfp-flex\"\n :style=\"{ opacity: showToc ? 1 : 0, pointerEvents: showToc ? 'auto' : 'none', transition: 'opacity 0.3s' }\"\n >\n <div\n class=\"vfp-w-72 vfp-h-full vfp-flex vfp-flex-col\"\n :style=\"{\n maxWidth: '80%',\n background: 'rgba(0,0,0,0.9)',\n backdropFilter: 'blur(12px)',\n borderRight: '1px solid rgba(255,255,255,0.1)',\n boxShadow: '0 25px 50px -12px rgba(0,0,0,0.25)',\n transform: showToc ? 'translateX(0)' : 'translateX(-100%)',\n transition: 'transform 0.3s ease',\n }\"\n >\n <div class=\"vfp-flex vfp-items-center vfp-justify-between vfp-flex-shrink-0\" style=\"padding: 12px 16px; border-bottom: 1px solid rgba(255,255,255,0.1)\">\n <span style=\"color: white; font-weight: 500; font-size: 14px\">{{ t('toolbar.toc') }}</span>\n <button style=\"color: rgba(255,255,255,0.6); background: none; border: none; cursor: pointer; padding: 4px\" @click=\"showToc = false\">\n <X style=\"width: 16px; height: 16px\" />\n </button>\n </div>\n <div class=\"vfp-flex-1 vfp-overflow-y-auto\" style=\"padding: 8px 4px\">\n <template v-for=\"(item, i) in toc\" :key=\"`${item.href}-${i}`\">\n <button\n :style=\"{\n width: '100%', textAlign: 'left', padding: '8px 12px', fontSize: '14px',\n color: isActive(item.href) ? 'white' : 'rgba(255,255,255,0.7)',\n fontWeight: isActive(item.href) ? '500' : '400',\n background: isActive(item.href) ? 'rgba(255,255,255,0.15)' : 'none',\n border: 'none', cursor: 'pointer', borderRadius: '4px',\n overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', display: 'block',\n transition: 'all 0.15s',\n }\"\n :title=\"item.label\"\n @click=\"handleTocClick(item.href)\"\n @mouseenter=\"!isActive(item.href) && (($event.target as HTMLElement).style.background = 'rgba(255,255,255,0.1)')\"\n @mouseleave=\"!isActive(item.href) && (($event.target as HTMLElement).style.background = 'none')\"\n >\n {{ item.label.trim() }}\n </button>\n <template v-if=\"item.subitems && item.subitems.length > 0\">\n <button\n v-for=\"(sub, j) in item.subitems\"\n :key=\"`${sub.href}-${j}`\"\n :style=\"{\n width: '100%', textAlign: 'left', padding: '8px 12px 8px 28px', fontSize: '13px',\n color: isActive(sub.href) ? 'white' : 'rgba(255,255,255,0.6)',\n fontWeight: isActive(sub.href) ? '500' : '400',\n background: isActive(sub.href) ? 'rgba(255,255,255,0.15)' : 'none',\n border: 'none', cursor: 'pointer', borderRadius: '4px',\n overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', display: 'block',\n transition: 'all 0.15s',\n }\"\n :title=\"sub.label\"\n @click=\"handleTocClick(sub.href)\"\n @mouseenter=\"!isActive(sub.href) && (($event.target as HTMLElement).style.background = 'rgba(255,255,255,0.1)')\"\n @mouseleave=\"!isActive(sub.href) && (($event.target as HTMLElement).style.background = 'none')\"\n >\n {{ sub.label.trim() }}\n </button>\n </template>\n </template>\n </div>\n </div>\n <div\n class=\"vfp-flex-1\"\n :style=\"{ background: showToc ? 'rgba(0,0,0,0.3)' : 'transparent', transition: 'background 0.3s' }\"\n @click=\"showToc = false\"\n />\n </div>\n\n <div\n v-if=\"!error\"\n ref=\"viewerRef\"\n class=\"vfp-h-full vfp-bg-surface-toolbar\"\n :style=\"{\n width: isFullWidth ? '100%' : `${A4_WIDTH}px`,\n maxWidth: '100%',\n transition: 'width 0.3s ease',\n boxShadow: '0 1px 3px rgba(0,0,0,0.12)',\n overflow: 'hidden',\n }\"\n />\n </div>\n</template>\n\n<style>\n.epub-container { overflow-y: auto !important; scrollbar-width: thin; }\n.epub-container::-webkit-scrollbar { width: 8px; }\n.epub-container::-webkit-scrollbar-track { background: transparent; }\n.epub-container::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.15); border-radius: 4px; }\n.epub-container::-webkit-scrollbar-thumb:hover { background: rgba(0,0,0,0.3); }\n.epub-view > iframe { background: white; }\n</style>\n"],"names":["A4_WIDTH","props","__props","t","useTranslator","fetcher","useFetcher","emit","__emit","viewerRef","ref","loading","error","isFullWidth","toc","showToc","activeTocHref","book","rendition","totalLocations","lastCfi","cleanup","_a","prevPage","nextPage","toggleFullWidth","reattachScrollListener","toggleToc","handleTocClick","href","isActive","__expose","loadEpub","bookInput","ePub","loc","cur","nav","location","_b","spineHref","matches","collect","items","item","base","_c","err","onResize","scrollContainer","onContainerScroll","el","mgr","tryAttach","onMounted","watch","newUrl","onBeforeUnmount","_openBlock","_createElementBlock","_hoisted_1","_createBlock","RendererError","_hoisted_2","_cache","_createElementVNode","_normalizeStyle","_hoisted_3","_hoisted_4","_toDisplayString","_unref","_createVNode","X","_hoisted_5","_Fragment","_renderList","i","$event","_hoisted_6","sub","j","_hoisted_7"],"mappings":";;;;;;;;;;;;;;yHAwCMA,KAAW;;;;;;;AAEjB,UAAMC,IAAQC,GAER,EAAE,GAAAC,EAAA,IAAMC,GAAA,GACRC,IAAUC,GAAA,GAEVC,IAAOC,GAKPC,IAAYC,EAA2B,IAAI,GAC3CC,IAAUD,EAAI,EAAI,GAClBE,IAAQF,EAAmB,IAAI,GAC/BG,IAAcH,EAAI,EAAK,GACvBI,IAAMJ,EAAe,EAAE,GACvBK,IAAUL,EAAI,EAAK,GACnBM,IAAgBN,EAAI,EAAE;AAE5B,QAAIO,IAAwB,MACxBC,IAAkC,MAClCC,IAAiB,GACjBC,IAAyB;AAE7B,UAAMC,IAAU,MAAM;;AACpB,UAAI;AAAE,SAAAC,IAAAJ,KAAA,gBAAAA,EAAW,YAAX,QAAAI,EAAA,KAAAJ;AAAA,MAAwB,QAAQ;AAAA,MAAe;AACrD,UAAI;AAAE,QAAAD,KAAA,QAAAA,EAAM;AAAA,MAAW,QAAQ;AAAA,MAAe;AAC9C,MAAAC,IAAY,MACZD,IAAO,MACPE,IAAiB,GACjBC,IAAU;AAAA,IACZ,GAEMG,IAAW,MAAM;AAAE,MAAAL,KAAA,QAAAA,EAAW;AAAA,IAAQ,GACtCM,IAAW,MAAM;AAAE,MAAAN,KAAA,QAAAA,EAAW;AAAA,IAAQ,GACtCO,IAAkB,MAAM;AAC5B,MAAAZ,EAAY,QAAQ,CAACA,EAAY,OACjCN,EAAK,mBAAmBM,EAAY,KAAK,GACzC,WAAW,MAAM;AACf,QAAIJ,EAAU,SAASS,MACrBA,EAAU,OAAOT,EAAU,MAAM,aAAaA,EAAU,MAAM,YAAY,GACtEW,KACFF,EAAU,QAAQE,CAAO,GAG3BM,EAAA;AAAA,MAEJ,GAAG,GAAG;AAAA,IACR,GACMC,IAAY,MAAM;AAAE,MAAAZ,EAAQ,QAAQ,CAACA,EAAQ;AAAA,IAAO,GACpDa,IAAiB,CAACC,MAAiB;AACvC,MAAAb,EAAc,QAAQa,GACtBX,KAAA,QAAAA,EAAW,QAAQW,IACnBd,EAAQ,QAAQ;AAAA,IAClB,GAEMe,IAAW,CAACD,MACTA,MAASb,EAAc;AAGhC,IAAAe,EAAa,EAAE,UAAAR,GAAU,UAAAC,GAAU,iBAAAC,GAAiB,WAAAE,GAAW;AAE/D,UAAMK,IAAW,YAAY;AAC3B,UAAKvB,EAAU,OAEf;AAAA,QAAAE,EAAQ,QAAQ,IAChBC,EAAM,QAAQ,MACdE,EAAI,QAAQ,CAAA,GACZC,EAAQ,QAAQ,IAChBN,EAAU,MAAM,YAAY,IAC5BY,EAAA;AAEA,YAAI;AACF,cAAIY,IAAkChC,EAAM;AAC5C,UAAIA,EAAM,IAAI,WAAW,OAAO,MAE9BgC,IAAY,OADC,MAAM5B,EAAQ,MAAMJ,EAAM,GAAG,GACnB,YAAA,IAGzBgB,IAAOiB,GAAKD,CAAS,GAErBf,IAAYD,EAAK,SAASR,EAAU,OAAO;AAAA,YACzC,SAAS;AAAA,YACT,MAAM;AAAA,YACN,OAAO;AAAA,YACP,QAAQ;AAAA,UAAA,CACT,GAEDS,EAAU,OAAO,SAAS,WAAW;AAAA,YACnC,MAAM;AAAA,cACJ,YAAY;AAAA,cACZ,OAAO;AAAA,cACP,eAAe;AAAA,cACf,aAAa;AAAA,cACb,eAAe;AAAA,cACf,SAAS;AAAA,cACT,aAAa;AAAA,cACb,cAAc;AAAA,cACd,cAAc;AAAA,cACd,iBAAiB;AAAA,YAAA;AAAA,YAEnB,GAAG,EAAE,eAAe,kBAAkB,QAAQ,qBAAA;AAAA,YAC9C,IAAI,EAAE,cAAc,qBAAqB,QAAQ,yBAAA;AAAA,YACjD,IAAI,EAAE,QAAQ,2BAAA;AAAA,YACd,IAAI,EAAE,QAAQ,yBAAA;AAAA,YACd,KAAK,EAAE,aAAa,mBAAmB,QAAQ,kBAAA;AAAA,YAC/C,GAAG,EAAE,OAAO,sBAAsB,mBAAmB,kBAAA;AAAA,UAAkB,CACxE,GACDA,EAAU,OAAO,OAAO,SAAS,GAEjC,MAAMD,EAAK,OAGXA,EAAK,UAAU,SAAS,IAAI,EAAE,KAAK,MAAM;;AACvC,gBAAI,CAACA,EAAM;AACX,YAAAE,IAAiBF,EAAK,UAAU,OAAA;AAChC,kBAAMkB,IAAMjB,KAAA,gBAAAA,EAAW,mBACjBkB,MAAMd,IAAAa,KAAA,gBAAAA,EAAK,UAAL,gBAAAb,EAAY,aAAY;AACpC,YAAAf,EAAK,iBAAiB6B,IAAM,GAAGjB,CAAc;AAAA,UAC/C,CAAC,EAAE,MAAM,MAAM;AAAA,UAAe,CAAC;AAE/B,gBAAMkB,IAAM,MAAMpB,EAAK,OAAO;AAC9B,UAAI,MAAM,QAAQoB,KAAA,gBAAAA,EAAK,GAAG,MACxBvB,EAAI,QAAQuB,EAAI,MAGlB,MAAMnB,EAAU,QAAA,GAEhBP,EAAQ,QAAQ,IAChBJ,EAAK,iBAAiB,GAAGY,KAAkB,CAAC,GAE5CD,EAAU,GAAG,aAAa,CAACoB,MAAsB;;AAC/C,kBAAMH,IAAMG;AAIZ,iBAHIhB,IAAAa,KAAA,gBAAAA,EAAK,UAAL,QAAAb,EAAY,QACdF,IAAUe,EAAI,MAAM,OAElBI,IAAAJ,KAAA,gBAAAA,EAAK,UAAL,QAAAI,EAAY,MAAM;AAEpB,oBAAMC,IAAYL,EAAI,MAAM,MACtBM,IAAoB,CAAA,GACpBC,IAAU,CAACC,MAAqB;AACpC,2BAAWC,KAAQD,GAAO;AACxB,wBAAME,IAAOD,EAAK,KAAK,MAAM,GAAG,EAAE,CAAC;AACnC,kBAAIC,MAASL,MAAcK,KAAQL,EAAU,SAAS,MAAMK,CAAI,KAAKL,EAAU,SAASK,CAAI,MAC1FJ,EAAQ,KAAKG,EAAK,IAAI,GAEpBA,EAAK,YAAUF,EAAQE,EAAK,QAAQ;AAAA,gBAC1C;AAAA,cACF;AACA,cAAAF,EAAQ5B,EAAI,KAAK,GACb2B,EAAQ,WAAW,MACrBzB,EAAc,QAAQyB,EAAQ,CAAC;AAAA,YAGnC;AACA,kBAAML,KAAMU,IAAAX,KAAA,gBAAAA,EAAK,UAAL,gBAAAW,EAAY;AACxB,YAAI,OAAOV,KAAQ,YAAYjB,IAAiB,KAC9CZ,EAAK,iBAAiB6B,IAAM,GAAGjB,CAAc;AAAA,UAEjD,CAAC;AAAA,QACH,SAAS4B,GAAK;AACZ,kBAAQ,MAAM,cAAcA,CAAG,GAC/BnC,EAAM,QAAQT,EAAE,MAAM,kBAAkB,GACxCQ,EAAQ,QAAQ;AAAA,QAClB;AAAA;AAAA,IACF,GAEMqC,IAAW,MAAM;AACrB,MAAI,CAACvC,EAAU,SAAS,CAACS,KACzBA,EAAU,OAAOT,EAAU,MAAM,aAAaA,EAAU,MAAM,YAAY;AAAA,IAC5E;AAGA,QAAIwC,IAAkC;AACtC,UAAMC,IAAoB,MAAM;;AAC9B,UAAI,CAACD,EAAiB;AACtB,YAAME,IAAKF;AACX,UAAIE,EAAG,YAAYA,EAAG,gBAAgBA,EAAG,eAAe;AACtD,YAAI;AACF,gBAAMC,IAAOlC,KAAA,gBAAAA,EAAiG;AAE9G,WAAAI,IAAA8B,KAAA,gBAAAA,EAAK,UAAL,QAAA9B,EAAA,KAAA8B,GAAa,KAAK;AAAA,QACpB,QAAQ;AAAA,QAAe;AAAA,IAE3B,GAEM1B,IAAyB,MAAM;AAEnC,MAAIuB,MACFA,EAAgB,oBAAoB,UAAUC,CAAiB,GAC/DD,IAAkB;AAEpB,YAAMI,IAAY,MAAM;;AACtB,QAAAJ,MAAkB3B,IAAAb,EAAU,UAAV,gBAAAa,EAAiB,cAAc,uBAAsB,MACnE2B,IACFA,EAAgB,iBAAiB,UAAUC,GAAmB,EAAE,SAAS,IAAM,IAE/E,sBAAsBG,CAAS;AAAA,MAEnC;AACA,4BAAsBA,CAAS;AAAA,IACjC;AAEA,WAAAC,GAAU,MAAM;AACd,MAAAtB,EAAA,GACA,OAAO,iBAAiB,UAAUgB,CAAQ,GAC1CtB,EAAA;AAAA,IACF,CAAC,GAED6B,GAAM,MAAMtD,EAAM,KAAK,CAACuD,MAAW;AAEjC,MAAIA,KAAQxB,EAAA;AAAA,IACd,CAAC,GAEDyB,GAAgB,MAAM;AACpB,aAAO,oBAAoB,UAAUT,CAAQ,GAC7CC,KAAA,QAAAA,EAAiB,oBAAoB,UAAUC,IAC/C7B,EAAA;AAAA,IACF,CAAC,cAICqC,EAAA,GAAAC,EAgGM,OAhGNC,IAgGM;AAAA,MA/FiBhD,EAAA,cAArBiD,GAAgFC,IAAA;AAAA;QAAnD,SAASlD,EAAA;AAAA,QAAO,OAAM;AAAA,MAAA;MAG3CD,EAAA,UAAYC,EAAA,SADpB8C,KAAAC,EAKM,OALNI,IAKM,CAAA,GAAAC,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,QADJC,EAAiI,OAAA,EAA5H,OAAM,oHAAA,GAAmH,MAAA,EAAA;AAAA,MAAA;MAKxHnD,EAAA,MAAI,SAAM,UADlB6C,EAuEM,OAAA;AAAA;QArEJ,OAAM;AAAA,QACL,OAAKO,EAAA,EAAA,SAAanD,EAAA,QAAO,IAAA,GAAA,eAAyBA,EAAA,QAAO,SAAA,QAAA,YAAA,gBAAA;AAAA,MAAA;QAE1DkD,EA4DM,OAAA;AAAA,UA3DJ,OAAM;AAAA,UACL,OAAKC,EAAA;AAAA;;;;;uBAA0PnD,EAAA,QAAO,kBAAA;AAAA;;;UAUvQkD,EAKM,OALNE,IAKM;AAAA,YAJJF,EAA2F,QAA3FG,IAA2FC,EAA1BC,EAAAnE,CAAA,EAAC,aAAA,CAAA,GAAA,CAAA;AAAA,YAClE8D,EAES,UAAA;AAAA,cAFD,OAAA,EAAA,OAAA,yBAAA,YAAA,QAAA,QAAA,QAAA,QAAA,WAAA,SAAA,MAAA;AAAA,cAAqG,gCAAOlD,EAAA,QAAO;AAAA,YAAA;cACzHwD,GAAuCD,EAAAE,EAAA,GAAA,EAApC,OAAA,EAAA,OAAA,QAAA,QAAA,SAAA,CAAiC;AAAA,YAAA;;UAGxCP,EAyCM,OAzCNQ,IAyCM;AAAA,aAxCJf,EAAA,EAAA,GAAAC,EAuCWe,GAAA,MAAAC,EAvCmB7D,EAAA,OAAG,CAAf8B,GAAMgC;sBAAoBhC,EAAK,IAAI,IAAIgC,CAAC;AAAA,YAAA;cACxDX,EAgBS,UAAA;AAAA,gBAfN,OAAKC,EAAA;AAAA;;;;yBAAoHpC,EAASc,EAAK,IAAI,IAAA,UAAA;AAAA,8BAAmEd,EAASc,EAAK,IAAI,IAAA,QAAA;AAAA,8BAA+Cd,EAASc,EAAK,IAAI,IAAA,2BAAA;AAAA;;;;;;;;;gBASjS,OAAOA,EAAK;AAAA,gBACZ,SAAK,CAAAiC,MAAEjD,EAAegB,EAAK,IAAI;AAAA,gBAC/B,cAAU,CAAAiC,MAAA,CAAG/C,EAASc,EAAK,IAAI,MAAOiC,EAAO,OAAuB,MAAM,aAAU;AAAA,gBACpF,cAAU,CAAAA,MAAA,CAAG/C,EAASc,EAAK,IAAI,MAAOiC,EAAO,OAAuB,MAAM,aAAU;AAAA,cAAA,KAElFjC,EAAK,MAAM,MAAI,GAAA,IAAAkC,EAAA;AAAA,cAEJlC,EAAK,YAAYA,EAAK,SAAS,SAAM,KACnDc,EAAA,EAAA,GAAAC,EAkBSe,iBAjBY9B,EAAK,UAAQ,CAAxBmC,GAAKC,YADfrB,EAkBS,UAAA;AAAA,gBAhBN,KAAG,GAAKoB,EAAI,IAAI,IAAIC,CAAC;AAAA,gBACrB,OAAKd,EAAA;AAAA;;;;yBAAiIpC,EAASiD,EAAI,IAAI,IAAA,UAAA;AAAA,8BAAqEjD,EAASiD,EAAI,IAAI,IAAA,QAAA;AAAA,8BAAiDjD,EAASiD,EAAI,IAAI,IAAA,2BAAA;AAAA;;;;;;;;;gBAS/S,OAAOA,EAAI;AAAA,gBACX,SAAK,CAAAF,MAAEjD,EAAemD,EAAI,IAAI;AAAA,gBAC9B,cAAU,CAAAF,MAAA,CAAG/C,EAASiD,EAAI,IAAI,MAAOF,EAAO,OAAuB,MAAM,aAAU;AAAA,gBACnF,cAAU,CAAAA,MAAA,CAAG/C,EAASiD,EAAI,IAAI,MAAOF,EAAO,OAAuB,MAAM,aAAU;AAAA,cAAA,KAEjFE,EAAI,MAAM,MAAI,GAAA,IAAAE,EAAA;;;;QAM3BhB,EAIE,OAAA;AAAA,UAHA,OAAM;AAAA,UACL,uBAAqBlD,EAAA,QAAO,oBAAA,eAAA,YAAA,mBAAA;AAAA,UAC5B,gCAAOA,EAAA,QAAO;AAAA,QAAA;;MAKVH,EAAA,0BADT+C,EAWE,OAAA;AAAA;iBATI;AAAA,QAAJ,KAAIlD;AAAA,QACJ,OAAM;AAAA,QACL,OAAKyD,EAAA;AAAA,UAAmB,OAAArD,EAAA,oBAA0Bb,EAAQ;AAAA;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"index-DX_NBPzS.mjs","sources":["../../src/renderers/Epub/index.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, watch, onMounted, onBeforeUnmount } from 'vue';\nimport ePub from '@likecoin/epub-ts';\nimport { X } from 'lucide-vue-next';\nimport { useTranslator } from '../../composables/useTranslator';\nimport { useFetcher } from '../../composables/useRequest';\nimport RendererError from '../RendererError.vue';\n\ninterface TocItem {\n label: string;\n href: string;\n subitems?: TocItem[];\n}\n\ninterface RenditionLike {\n display: (target?: string) => Promise<unknown>;\n next: () => Promise<unknown>;\n prev: () => Promise<unknown>;\n on: (event: string, cb: (...args: unknown[]) => void) => void;\n resize: (width: number, height: number) => void;\n currentLocation: () => unknown;\n destroy?: () => void;\n themes: {\n register: (name: string, styles: Record<string, unknown>) => void;\n select: (name: string) => void;\n };\n}\n\ninterface BookLike {\n ready: Promise<unknown>;\n loaded: { navigation: Promise<unknown> };\n locations: {\n generate: (chars: number) => Promise<string[]>;\n length: () => number;\n locationFromCfi: (cfi: string) => number;\n };\n renderTo: (el: HTMLElement, opts: Record<string, unknown>) => RenditionLike;\n destroy: () => void;\n}\n\nconst A4_WIDTH = 794;\n\nconst props = defineProps<{ url: string }>();\n\nconst { t } = useTranslator();\nconst fetcher = useFetcher();\n\nconst emit = defineEmits<{\n (e: 'chapterChange', current: number, total: number): void;\n (e: 'fullWidthChange', isFullWidth: boolean): void;\n}>();\n\nconst viewerRef = ref<HTMLDivElement | null>(null);\nconst loading = ref(true);\nconst error = ref<string | null>(null);\nconst isFullWidth = ref(false);\nconst toc = ref<TocItem[]>([]);\nconst showToc = ref(false);\nconst activeTocHref = ref('');\n\nlet book: BookLike | null = null;\nlet rendition: RenditionLike | null = null;\nlet totalLocations = 0;\nlet lastCfi: string | null = null;\n\nconst cleanup = () => {\n try { rendition?.destroy?.(); } catch { /* ignore */ }\n try { book?.destroy(); } catch { /* ignore */ }\n rendition = null;\n book = null;\n totalLocations = 0;\n lastCfi = null;\n};\n\nconst prevPage = () => { rendition?.prev(); };\nconst nextPage = () => { rendition?.next(); };\nconst toggleFullWidth = () => {\n isFullWidth.value = !isFullWidth.value;\n emit('fullWidthChange', isFullWidth.value);\n setTimeout(() => {\n if (viewerRef.value && rendition) {\n rendition.resize(viewerRef.value.offsetWidth, viewerRef.value.offsetHeight);\n if (lastCfi) {\n rendition.display(lastCfi);\n }\n // resize/display 可能重建 .epub-container,需要重新绑定滚动监听\n reattachScrollListener();\n }\n }, 350);\n};\nconst toggleToc = () => { showToc.value = !showToc.value; };\nconst handleTocClick = (href: string) => {\n activeTocHref.value = href;\n rendition?.display(href);\n showToc.value = false;\n};\n\nconst isActive = (href: string) => {\n return href === activeTocHref.value;\n};\n\ndefineExpose({ prevPage, nextPage, toggleFullWidth, toggleToc });\n\nconst loadEpub = async () => {\n if (!viewerRef.value) return;\n\n loading.value = true;\n error.value = null;\n toc.value = [];\n showToc.value = false;\n viewerRef.value.innerHTML = '';\n cleanup();\n\n try {\n let bookInput: string | ArrayBuffer = props.url;\n if (props.url.startsWith('blob:')) {\n const resp = await fetcher.value(props.url);\n bookInput = await resp.arrayBuffer();\n }\n\n book = ePub(bookInput) as unknown as BookLike;\n\n rendition = book.renderTo(viewerRef.value, {\n manager: 'continuous',\n flow: 'scrolled',\n width: '100%',\n height: '100%',\n });\n\n rendition.themes.register('default', {\n body: {\n background: '#ffffff !important',\n color: '#1a1a1a !important',\n 'font-family': '\"Noto Serif SC\", \"Source Han Serif SC\", Georgia, \"Times New Roman\", serif !important',\n 'font-size': '16px !important',\n 'line-height': '2 !important',\n padding: '40px 60px !important',\n 'max-width': '100% !important',\n 'box-sizing': 'border-box !important',\n 'word-break': 'break-word !important',\n 'overflow-wrap': 'break-word !important',\n },\n p: { 'text-indent': '2em !important', margin: '0.8em 0 !important' },\n h1: { 'text-align': 'center !important', margin: '1.5em 0 1em !important' },\n h2: { margin: '1.2em 0 0.8em !important' },\n h3: { margin: '1em 0 0.6em !important' },\n img: { 'max-width': '100% !important', height: 'auto !important' },\n a: { color: '#2563eb !important', 'text-decoration': 'none !important' },\n });\n rendition.themes.select('default');\n\n await book.ready;\n\n // 异步生成 locations 索引\n book.locations.generate(1024).then(() => {\n if (!book) return;\n totalLocations = book.locations.length();\n const loc = rendition?.currentLocation() as { start?: { location?: number } } | undefined;\n const cur = loc?.start?.location ?? 0;\n emit('chapterChange', cur + 1, totalLocations);\n }).catch(() => { /* ignore */ });\n\n const nav = await book.loaded.navigation as { toc?: TocItem[] };\n if (Array.isArray(nav?.toc)) {\n toc.value = nav.toc;\n }\n\n await rendition.display();\n\n loading.value = false;\n emit('chapterChange', 1, totalLocations || 1);\n\n rendition.on('relocated', (location: unknown) => {\n const loc = location as { start?: { cfi?: string; location?: number; href?: string } };\n if (loc?.start?.cfi) {\n lastCfi = loc.start.cfi;\n }\n if (loc?.start?.href) {\n // 根据 spine href 查找匹配的 TOC 项\n const spineHref = loc.start.href;\n const matches: string[] = [];\n const collect = (items: TocItem[]) => {\n for (const item of items) {\n const base = item.href.split('#')[0];\n if (base && (spineHref === base || spineHref.endsWith('/' + base) || spineHref.endsWith(base))) {\n matches.push(item.href);\n }\n if (item.subitems) collect(item.subitems);\n }\n };\n collect(toc.value);\n if (matches.length === 1) {\n activeTocHref.value = matches[0];\n }\n // 多个匹配(同一文件不同 anchor)时保持当前选中(由点击设置)\n }\n const cur = loc?.start?.location;\n if (typeof cur === 'number' && totalLocations > 0) {\n emit('chapterChange', cur + 1, totalLocations);\n }\n });\n } catch (err) {\n console.error('EPUB 加载错误:', err);\n error.value = t.value('epub.load_failed');\n loading.value = false;\n }\n};\n\nconst onResize = () => {\n if (!viewerRef.value || !rendition) return;\n rendition.resize(viewerRef.value.offsetWidth, viewerRef.value.offsetHeight);\n};\n\n// 监听 epub-container 滚动,接近底部时强制加载后续 section\nlet scrollContainer: Element | null = null;\nconst onContainerScroll = () => {\n if (!scrollContainer) return;\n const el = scrollContainer as HTMLElement;\n if (el.scrollTop + el.clientHeight >= el.scrollHeight - 200) {\n try {\n const mgr = (rendition as unknown as { manager?: { check?: (t?: number, e?: number) => Promise<unknown> } })?.manager;\n // 传递垂直偏移量参数,让 check() 在接近底部时就触发加载下一节\n mgr?.check?.(500, 500);\n } catch { /* ignore */ }\n }\n};\n\nconst reattachScrollListener = () => {\n // 清理旧监听\n if (scrollContainer) {\n scrollContainer.removeEventListener('scroll', onContainerScroll);\n scrollContainer = null;\n }\n const tryAttach = () => {\n scrollContainer = viewerRef.value?.querySelector('.epub-container') ?? null;\n if (scrollContainer) {\n scrollContainer.addEventListener('scroll', onContainerScroll, { passive: true });\n } else {\n requestAnimationFrame(tryAttach);\n }\n };\n requestAnimationFrame(tryAttach);\n};\n\nonMounted(() => {\n loadEpub();\n window.addEventListener('resize', onResize);\n reattachScrollListener();\n});\n\nwatch(() => props.url, (newUrl) => {\n // 只有 URL 有效时才加载(避免空字符串或已 revoke 的 blob URL)\n if (newUrl) loadEpub();\n});\n\nonBeforeUnmount(() => {\n window.removeEventListener('resize', onResize);\n scrollContainer?.removeEventListener('scroll', onContainerScroll);\n cleanup();\n});\n</script>\n\n<template>\n <div class=\"vfp-relative vfp-w-full vfp-h-full vfp-flex vfp-justify-center vfp-bg-surface-1 vfp-overflow-hidden\">\n <RendererError v-if=\"error\" :message=\"error\" class=\"vfp-absolute vfp-inset-0\" />\n\n <div\n v-if=\"loading && !error\"\n class=\"vfp-absolute vfp-inset-0 vfp-flex vfp-items-center vfp-justify-center vfp-z-10\"\n >\n <div class=\"vfp-w-12 vfp-h-12 vfp-border-4 vfp-border-line-strong vfp-border-t-spinner-head vfp-rounded-full vfp-animate-spin\" />\n </div>\n\n <!-- 目录侧栏 - 滑入动画 -->\n <div\n v-if=\"toc.length > 0\"\n class=\"vfp-absolute vfp-inset-0 vfp-z-20 vfp-flex\"\n :style=\"{ opacity: showToc ? 1 : 0, pointerEvents: showToc ? 'auto' : 'none', transition: 'opacity 0.3s' }\"\n >\n <div\n class=\"vfp-w-72 vfp-h-full vfp-flex vfp-flex-col\"\n :style=\"{\n maxWidth: '80%',\n background: 'rgba(0,0,0,0.9)',\n backdropFilter: 'blur(12px)',\n borderRight: '1px solid rgba(255,255,255,0.1)',\n boxShadow: '0 25px 50px -12px rgba(0,0,0,0.25)',\n transform: showToc ? 'translateX(0)' : 'translateX(-100%)',\n transition: 'transform 0.3s ease',\n }\"\n >\n <div class=\"vfp-flex vfp-items-center vfp-justify-between vfp-flex-shrink-0\" style=\"padding: 12px 16px; border-bottom: 1px solid rgba(255,255,255,0.1)\">\n <span style=\"color: white; font-weight: 500; font-size: 14px\">{{ t('toolbar.toc') }}</span>\n <button style=\"color: rgba(255,255,255,0.6); background: none; border: none; cursor: pointer; padding: 4px\" @click=\"showToc = false\">\n <X style=\"width: 16px; height: 16px\" />\n </button>\n </div>\n <div class=\"vfp-flex-1 vfp-overflow-y-auto\" style=\"padding: 8px 4px\">\n <template v-for=\"(item, i) in toc\" :key=\"`${item.href}-${i}`\">\n <button\n :style=\"{\n width: '100%', textAlign: 'left', padding: '8px 12px', fontSize: '14px',\n color: isActive(item.href) ? 'white' : 'rgba(255,255,255,0.7)',\n fontWeight: isActive(item.href) ? '500' : '400',\n background: isActive(item.href) ? 'rgba(255,255,255,0.15)' : 'none',\n border: 'none', cursor: 'pointer', borderRadius: '4px',\n overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', display: 'block',\n transition: 'all 0.15s',\n }\"\n :title=\"item.label\"\n @click=\"handleTocClick(item.href)\"\n @mouseenter=\"!isActive(item.href) && (($event.target as HTMLElement).style.background = 'rgba(255,255,255,0.1)')\"\n @mouseleave=\"!isActive(item.href) && (($event.target as HTMLElement).style.background = 'none')\"\n >\n {{ item.label.trim() }}\n </button>\n <template v-if=\"item.subitems && item.subitems.length > 0\">\n <button\n v-for=\"(sub, j) in item.subitems\"\n :key=\"`${sub.href}-${j}`\"\n :style=\"{\n width: '100%', textAlign: 'left', padding: '8px 12px 8px 28px', fontSize: '13px',\n color: isActive(sub.href) ? 'white' : 'rgba(255,255,255,0.6)',\n fontWeight: isActive(sub.href) ? '500' : '400',\n background: isActive(sub.href) ? 'rgba(255,255,255,0.15)' : 'none',\n border: 'none', cursor: 'pointer', borderRadius: '4px',\n overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', display: 'block',\n transition: 'all 0.15s',\n }\"\n :title=\"sub.label\"\n @click=\"handleTocClick(sub.href)\"\n @mouseenter=\"!isActive(sub.href) && (($event.target as HTMLElement).style.background = 'rgba(255,255,255,0.1)')\"\n @mouseleave=\"!isActive(sub.href) && (($event.target as HTMLElement).style.background = 'none')\"\n >\n {{ sub.label.trim() }}\n </button>\n </template>\n </template>\n </div>\n </div>\n <div\n class=\"vfp-flex-1\"\n :style=\"{ background: showToc ? 'rgba(0,0,0,0.3)' : 'transparent', transition: 'background 0.3s' }\"\n @click=\"showToc = false\"\n />\n </div>\n\n <div\n v-if=\"!error\"\n ref=\"viewerRef\"\n class=\"vfp-h-full vfp-bg-surface-toolbar\"\n :style=\"{\n width: isFullWidth ? '100%' : `${A4_WIDTH}px`,\n maxWidth: '100%',\n transition: 'width 0.3s ease',\n boxShadow: '0 1px 3px rgba(0,0,0,0.12)',\n overflow: 'hidden',\n }\"\n />\n </div>\n</template>\n\n<style>\n.epub-container { overflow-y: auto !important; scrollbar-width: thin; }\n.epub-container::-webkit-scrollbar { width: 8px; }\n.epub-container::-webkit-scrollbar-track { background: transparent; }\n.epub-container::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.15); border-radius: 4px; }\n.epub-container::-webkit-scrollbar-thumb:hover { background: rgba(0,0,0,0.3); }\n.epub-view > iframe { background: white; }\n</style>\n"],"names":["A4_WIDTH","props","__props","t","useTranslator","fetcher","useFetcher","emit","__emit","viewerRef","ref","loading","error","isFullWidth","toc","showToc","activeTocHref","book","rendition","totalLocations","lastCfi","cleanup","_a","prevPage","nextPage","toggleFullWidth","reattachScrollListener","toggleToc","handleTocClick","href","isActive","__expose","loadEpub","bookInput","ePub","loc","cur","nav","location","_b","spineHref","matches","collect","items","item","base","_c","err","onResize","scrollContainer","onContainerScroll","el","mgr","tryAttach","onMounted","watch","newUrl","onBeforeUnmount","_openBlock","_createElementBlock","_hoisted_1","_createBlock","RendererError","_hoisted_2","_cache","_createElementVNode","_normalizeStyle","_hoisted_3","_hoisted_4","_toDisplayString","_unref","_createVNode","X","_hoisted_5","_Fragment","_renderList","i","$event","_hoisted_6","sub","j","_hoisted_7"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import { defineComponent as A, computed as G, ref as s, watch as y, nextTick as
|
|
|
2
2
|
import K from "markdown-it";
|
|
3
3
|
import O from "@traptitech/markdown-it-katex";
|
|
4
4
|
import { codeToHtml as H } from "shiki";
|
|
5
|
-
import { u as R, a as N, c as Y, E as F, _ as W } from "./index-
|
|
5
|
+
import { u as R, a as N, c as Y, E as F, _ as W } from "./index-Oxwizt6-.mjs";
|
|
6
6
|
import { _ as z } from "./RendererError.vue_vue_type_script_setup_true_lang-CbgZBSDr.mjs";
|
|
7
7
|
const J = {
|
|
8
8
|
key: 0,
|
|
@@ -129,4 +129,4 @@ const J = {
|
|
|
129
129
|
export {
|
|
130
130
|
pe as default
|
|
131
131
|
};
|
|
132
|
-
//# sourceMappingURL=index-
|
|
132
|
+
//# sourceMappingURL=index-Dw1U4YqT.mjs.map
|