@eternalheart/vue-file-preview 1.3.13 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/lib/FilePreviewContent.vue.d.ts +3 -0
  2. package/lib/FilePreviewContent.vue.d.ts.map +1 -1
  3. package/lib/FilePreviewEmbed.vue.d.ts +5 -0
  4. package/lib/FilePreviewEmbed.vue.d.ts.map +1 -1
  5. package/lib/FilePreviewModal.vue.d.ts.map +1 -1
  6. package/lib/chunks/{RendererError.vue_vue_type_script_setup_true_lang-CbgZBSDr.mjs → RendererError.vue_vue_type_script_setup_true_lang-BNoENOWX.mjs} +9 -9
  7. package/lib/chunks/RendererError.vue_vue_type_script_setup_true_lang-BNoENOWX.mjs.map +1 -0
  8. package/lib/chunks/index-8ETACZ6T.mjs +267 -0
  9. package/lib/chunks/index-8ETACZ6T.mjs.map +1 -0
  10. package/lib/chunks/{index-DyipSoKh.mjs → index-B-LW-GJO.mjs} +24 -21
  11. package/lib/chunks/index-B-LW-GJO.mjs.map +1 -0
  12. package/lib/chunks/{index-Cjnw238n.mjs → index-BT9hXA6r.mjs} +3 -3
  13. package/lib/chunks/{index-Cjnw238n.mjs.map → index-BT9hXA6r.mjs.map} +1 -1
  14. package/lib/chunks/{index-CyrFxdIJ.mjs → index-BcKI75RW.mjs} +4 -4
  15. package/lib/chunks/{index-CyrFxdIJ.mjs.map → index-BcKI75RW.mjs.map} +1 -1
  16. package/lib/chunks/{index-Ctd0JQ6K.mjs → index-By6vGdnK.mjs} +3 -3
  17. package/lib/chunks/{index-Ctd0JQ6K.mjs.map → index-By6vGdnK.mjs.map} +1 -1
  18. package/lib/chunks/{index-BHi1WRQZ.mjs → index-C-Mu0fvH.mjs} +3 -3
  19. package/lib/chunks/{index-BHi1WRQZ.mjs.map → index-C-Mu0fvH.mjs.map} +1 -1
  20. package/lib/chunks/{index-DT9dPz8I.mjs → index-CGSq7-Q-.mjs} +3 -3
  21. package/lib/chunks/{index-DT9dPz8I.mjs.map → index-CGSq7-Q-.mjs.map} +1 -1
  22. package/lib/chunks/{index-DTtHrdBl.mjs → index-CWpU8prZ.mjs} +11 -11
  23. package/lib/chunks/index-CWpU8prZ.mjs.map +1 -0
  24. package/lib/chunks/index-CYa_XneH.mjs +303 -0
  25. package/lib/chunks/index-CYa_XneH.mjs.map +1 -0
  26. package/lib/chunks/{index-CYt6tpQC.mjs → index-CbJkkdEB.mjs} +9 -9
  27. package/lib/chunks/index-CbJkkdEB.mjs.map +1 -0
  28. package/lib/chunks/{index-DEoR7aDN.mjs → index-CoITLoYL.mjs} +3 -3
  29. package/lib/chunks/{index-DEoR7aDN.mjs.map → index-CoITLoYL.mjs.map} +1 -1
  30. package/lib/chunks/{index-Oxwizt6-.mjs → index-D9QQL7U6.mjs} +605 -557
  31. package/lib/chunks/index-D9QQL7U6.mjs.map +1 -0
  32. package/lib/chunks/{index-BvegaxQF.mjs → index-DAdO2lkI.mjs} +32 -32
  33. package/lib/chunks/index-DAdO2lkI.mjs.map +1 -0
  34. package/lib/chunks/{index-GGGDPwxX.mjs → index-DGqDJMot.mjs} +3 -3
  35. package/lib/chunks/{index-GGGDPwxX.mjs.map → index-DGqDJMot.mjs.map} +1 -1
  36. package/lib/chunks/{index-DIe0vHlt.mjs → index-DTyG1Wzp.mjs} +8 -8
  37. package/lib/chunks/index-DTyG1Wzp.mjs.map +1 -0
  38. package/lib/chunks/{index-Dw1U4YqT.mjs → index-DglMeKJM.mjs} +36 -38
  39. package/lib/chunks/{index-Dw1U4YqT.mjs.map → index-DglMeKJM.mjs.map} +1 -1
  40. package/lib/chunks/{index-B2lqsdp7.mjs → index-OOoaYpkl.mjs} +3 -3
  41. package/lib/chunks/{index-B2lqsdp7.mjs.map → index-OOoaYpkl.mjs.map} +1 -1
  42. package/lib/chunks/{index-DBw8tvyb.mjs → index-jcgLzyDR.mjs} +4 -4
  43. package/lib/chunks/{index-DBw8tvyb.mjs.map → index-jcgLzyDR.mjs.map} +1 -1
  44. package/lib/chunks/{index-BTW1xwB9.mjs → index-nFIiu1lA.mjs} +3 -3
  45. package/lib/chunks/{index-BTW1xwB9.mjs.map → index-nFIiu1lA.mjs.map} +1 -1
  46. package/lib/index.cjs +40 -32
  47. package/lib/index.cjs.map +1 -1
  48. package/lib/index.css +1 -1
  49. package/lib/index.mjs +1 -1
  50. package/lib/renderers/Audio/index.vue.d.ts.map +1 -1
  51. package/lib/renderers/Docx/index.vue.d.ts.map +1 -1
  52. package/lib/renderers/Epub/index.vue.d.ts.map +1 -1
  53. package/lib/renderers/Markdown/index.vue.d.ts.map +1 -1
  54. package/lib/renderers/Pdf/index.vue.d.ts +3 -0
  55. package/lib/renderers/Pdf/index.vue.d.ts.map +1 -1
  56. package/lib/renderers/Pdf/toolbar.d.ts +5 -0
  57. package/lib/renderers/Pdf/toolbar.d.ts.map +1 -1
  58. package/lib/renderers/RendererError.vue.d.ts.map +1 -1
  59. package/lib/renderers/Subtitle/index.vue.d.ts.map +1 -1
  60. package/lib/renderers/Text/index.vue.d.ts.map +1 -1
  61. package/lib/renderers/Xml/index.vue.d.ts.map +1 -1
  62. package/package.json +1 -1
  63. package/lib/chunks/RendererError.vue_vue_type_script_setup_true_lang-CbgZBSDr.mjs.map +0 -1
  64. package/lib/chunks/index-BvegaxQF.mjs.map +0 -1
  65. package/lib/chunks/index-CYt6tpQC.mjs.map +0 -1
  66. package/lib/chunks/index-DIe0vHlt.mjs.map +0 -1
  67. package/lib/chunks/index-DTtHrdBl.mjs.map +0 -1
  68. package/lib/chunks/index-DX_NBPzS.mjs +0 -248
  69. package/lib/chunks/index-DX_NBPzS.mjs.map +0 -1
  70. package/lib/chunks/index-DyipSoKh.mjs.map +0 -1
  71. package/lib/chunks/index-Oxwizt6-.mjs.map +0 -1
  72. package/lib/chunks/index-Zwl5J-Uw.mjs +0 -166
  73. package/lib/chunks/index-Zwl5J-Uw.mjs.map +0 -1
@@ -1,7 +1,7 @@
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";
1
+ import { defineComponent as g, ref as n, computed as x, watch as d, openBlock as e, createElementBlock as o, createElementVNode as m, createBlock as _, normalizeClass as h, toDisplayString as k } from "vue";
2
+ import { u as b, a as T, c as B, y as E, E as N, _ as H } from "./index-D9QQL7U6.mjs";
3
3
  import { codeToHtml as W } from "shiki";
4
- import { _ as C } from "./RendererError.vue_vue_type_script_setup_true_lang-CbgZBSDr.mjs";
4
+ import { _ as C } from "./RendererError.vue_vue_type_script_setup_true_lang-BNoENOWX.mjs";
5
5
  const L = {
6
6
  key: 0,
7
7
  class: "vfp-flex vfp-items-center vfp-justify-center vfp-w-full vfp-h-full"
@@ -12,7 +12,7 @@ const L = {
12
12
  key: 3,
13
13
  class: "vfp-w-full vfp-h-full vfp-overflow-auto",
14
14
  style: { background: "var(--fp-code-bg)" }
15
- }, z = ["innerHTML"], D = /* @__PURE__ */ y({
15
+ }, z = ["innerHTML"], D = /* @__PURE__ */ g({
16
16
  __name: "index",
17
17
  props: {
18
18
  url: {},
@@ -21,10 +21,10 @@ const L = {
21
21
  htmlPreview: { type: Boolean, default: !1 }
22
22
  },
23
23
  setup(l) {
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 () => {
24
+ const u = l, { t: w } = b(), y = T(), c = B(), r = n(""), t = n(""), v = n(!0), s = n(null), f = x(() => E(u.fileName)), i = async () => {
25
25
  v.value = !0, s.value = null;
26
26
  try {
27
- const a = await N(u.url, { fetcher: g.value });
27
+ const a = await N(u.url, { fetcher: y.value });
28
28
  if (r.value = a, f.value !== "text")
29
29
  try {
30
30
  t.value = await W(a, {
@@ -46,7 +46,7 @@ const L = {
46
46
  r.value && f.value !== "text" && i();
47
47
  }), (a, p) => v.value ? (e(), o("div", L, [...p[0] || (p[0] = [
48
48
  m("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)
49
- ])])) : s.value ? (e(), x(C, {
49
+ ])])) : s.value ? (e(), _(C, {
50
50
  key: 1,
51
51
  message: s.value
52
52
  }, null, 8, ["message"])) : l.htmlPreview && f.value === "html" ? (e(), o("div", M, [
@@ -63,12 +63,12 @@ const L = {
63
63
  innerHTML: t.value
64
64
  }, null, 10, z)) : (e(), o("pre", {
65
65
  key: 0,
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
- }, b(r.value), 3))
66
+ class: h(["vfp-py-6 vfp-px-4 vfp-text-fg-primary vfp-font-mono vfp-text-sm", l.wordWrap ? "vfp-whitespace-pre-wrap vfp-break-words" : "vfp-whitespace-pre"])
67
+ }, k(r.value), 3))
68
68
  ]));
69
69
  }
70
- }), V = /* @__PURE__ */ H(D, [["__scopeId", "data-v-b5fe3bc0"]]);
70
+ }), V = /* @__PURE__ */ H(D, [["__scopeId", "data-v-e26ca32c"]]);
71
71
  export {
72
72
  V as default
73
73
  };
74
- //# sourceMappingURL=index-DTtHrdBl.mjs.map
74
+ //# sourceMappingURL=index-CWpU8prZ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-CWpU8prZ.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-py-6 vfp-px-4 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,mEACE9B,EAAA,WAAQ,4CAAA,oBAAA,CAAA;AAAA,MAAA,KACdO,EAAA,KAAO,GAAA,CAAA;AAAA;;;"}
@@ -0,0 +1,303 @@
1
+ import { defineComponent as U, ref as w, watch as k, nextTick as L, onMounted as G, onBeforeUnmount as Q, openBlock as O, createElementBlock as A, normalizeStyle as B, createElementVNode as g, toDisplayString as Y, unref as z, createVNode as Z, createCommentVNode as I, createBlock as D } from "vue";
2
+ import { B as ee, u as te } from "./index-D9QQL7U6.mjs";
3
+ import * as N from "pdfjs-dist/build/pdf.mjs";
4
+ import { _ as ne } from "./RendererError.vue_vue_type_script_setup_true_lang-BNoENOWX.mjs";
5
+ import { X as re } from "lucide-vue-next";
6
+ const le = { class: "vfp-flex vfp-items-center vfp-justify-between vfp-px-4 vfp-py-3 vfp-border-b vfp-border-line-weak vfp-flex-shrink-0" }, ae = { class: "vfp-text-fg-primary vfp-font-medium vfp-text-sm" }, ie = ["innerHTML"], se = {
7
+ key: 1,
8
+ class: "vfp-flex vfp-items-center vfp-justify-center vfp-min-h-screen"
9
+ }, oe = {
10
+ key: 2,
11
+ class: "vfp-flex vfp-flex-col vfp-items-center"
12
+ }, pe = /* @__PURE__ */ U({
13
+ __name: "index",
14
+ props: {
15
+ url: {},
16
+ zoom: {},
17
+ currentPage: {},
18
+ showOutline: { type: Boolean }
19
+ },
20
+ emits: ["pageChange", "totalPagesChange", "pageWidthChange", "toggleOutline"],
21
+ setup(C, { emit: _ }) {
22
+ ee(N);
23
+ const y = C, h = _, { t: R } = te(), E = w(0), b = w(null), M = w(!0), v = w([]), T = w(null), P = w(null), f = w(null), S = /* @__PURE__ */ new Map();
24
+ let i = null;
25
+ const u = /* @__PURE__ */ new Map();
26
+ let c = null;
27
+ const q = async (t, e, n = 0) => {
28
+ var r, a, l;
29
+ for (let o = 0; o < t.length; o++) {
30
+ const s = t[o], p = `${s.title}-${o}-${n}`;
31
+ try {
32
+ let d = null;
33
+ const m = s.dest;
34
+ if (typeof m == "string") {
35
+ const x = await ((r = e.getDestination) == null ? void 0 : r.call(e, m));
36
+ x && x[0] && typeof x[0] == "object" && (d = await ((a = e.getPageIndex) == null ? void 0 : a.call(e, x[0])) + 1);
37
+ } else Array.isArray(m) && m[0] && typeof m[0] == "object" && (d = await ((l = e.getPageIndex) == null ? void 0 : l.call(e, m[0])) + 1);
38
+ d !== null && d > 0 && S.set(p, d), s.items && s.items.length > 0 && await q(s.items, e, n + 1);
39
+ } catch {
40
+ }
41
+ }
42
+ }, K = (t) => {
43
+ let e = null, n = 1 / 0;
44
+ S.forEach((r, a) => {
45
+ if (r <= t) {
46
+ const l = t - r;
47
+ l < n && (n = l, e = a);
48
+ }
49
+ }), e !== T.value && (T.value = e);
50
+ }, W = async (t, e) => {
51
+ var n, r, a;
52
+ if (!(!i || !f.value))
53
+ try {
54
+ let l;
55
+ if (typeof t == "string") {
56
+ const p = await ((n = i.getDestination) == null ? void 0 : n.call(i, t));
57
+ if (p && p[0])
58
+ l = await ((r = i.getPageIndex) == null ? void 0 : r.call(i, p[0])) + 1;
59
+ else
60
+ return;
61
+ } else if (Array.isArray(t) && t[0])
62
+ l = await ((a = i.getPageIndex) == null ? void 0 : a.call(i, t[0])) + 1;
63
+ else
64
+ return;
65
+ T.value = e;
66
+ const s = f.value.querySelectorAll("[data-page-number]")[l - 1];
67
+ s && s.scrollIntoView({ behavior: "smooth", block: "start" }), setTimeout(() => h("toggleOutline"), 300);
68
+ } catch (l) {
69
+ console.error("大纲跳转失败:", l);
70
+ }
71
+ }, $ = (t, e = 0) => t.map((n, r) => {
72
+ const a = `${n.title}-${r}-${e}`, o = T.value === a ? "vfp-bg-surface-2 vfp-text-fg-primary vfp-font-medium" : "vfp-text-fg-secondary hover:vfp-text-fg-primary hover:vfp-bg-surface-2";
73
+ let s = `<li style="margin-left: ${e > 0 ? 16 : 0}px;">
74
+ <button
75
+ data-outline-key="${a}"
76
+ data-outline-dest="${JSON.stringify(n.dest).replace(/"/g, "&quot;")}"
77
+ class="vfp-w-full vfp-text-left vfp-py-2 vfp-px-3 vfp-text-sm vfp-rounded vfp-transition-all vfp-truncate ${o}"
78
+ title="${n.title}"
79
+ >
80
+ ${n.title}
81
+ </button>`;
82
+ return n.items && n.items.length > 0 && (s += `<ul>${$(n.items, e + 1)}</ul>`), s += "</li>", s;
83
+ }).join(""), X = async (t, e) => {
84
+ if (!i) return;
85
+ const n = u.get(t);
86
+ if (!(!n || n.rendering)) {
87
+ n.rendering = !0;
88
+ try {
89
+ const r = await i.getPage(t), a = r.getViewport({ scale: e }), l = document.createElement("canvas");
90
+ l.width = a.width, l.height = a.height, l.style.maxWidth = "100%", l.style.height = "auto", l.style.borderRadius = "0", l.style.display = "block";
91
+ const o = l.getContext("2d");
92
+ if (!o) return;
93
+ const s = r.render({ canvasContext: o, viewport: a });
94
+ if (n.renderTask = s, await s.promise, t === 1) {
95
+ const p = r.getViewport({ scale: 1 });
96
+ h("pageWidthChange", p.width);
97
+ }
98
+ n.element.innerHTML = "", n.element.appendChild(l), n.rendered = !0;
99
+ } catch (r) {
100
+ (r == null ? void 0 : r.name) !== "RenderingCancelledException" && console.error(`渲染页面 ${t} 失败:`, r);
101
+ } finally {
102
+ n.rendering = !1, n.renderTask = null;
103
+ }
104
+ }
105
+ }, V = (t) => {
106
+ const e = u.get(t);
107
+ if (!e) return;
108
+ e.renderTask && (e.renderTask.cancel(), e.renderTask = null);
109
+ const n = e.element.querySelector("canvas");
110
+ if (n) {
111
+ const r = n.getContext("2d");
112
+ r && r.clearRect(0, 0, n.width, n.height);
113
+ }
114
+ e.element.innerHTML = "", e.rendered = !1, e.rendering = !1;
115
+ }, F = () => {
116
+ if (!i || !f.value) return;
117
+ const t = f.value.querySelector(".pdf-pages");
118
+ if (t) {
119
+ t.innerHTML = "", u.clear();
120
+ for (let e = 1; e <= E.value; e++) {
121
+ const n = document.createElement("div");
122
+ n.className = "vfp-relative vfp-flex vfp-justify-center vfp-min-h-[800px]", n.setAttribute("data-page-number", String(e)), t.appendChild(n), u.set(e, {
123
+ element: n,
124
+ rendered: !1,
125
+ rendering: !1,
126
+ renderTask: null
127
+ }), c && c.observe(n);
128
+ }
129
+ }
130
+ }, J = async () => {
131
+ if (b.value = null, M.value = !0, E.value = 0, i) {
132
+ try {
133
+ i.destroy();
134
+ } catch {
135
+ }
136
+ i = null;
137
+ }
138
+ try {
139
+ i = await N.getDocument({ url: y.url }).promise;
140
+ const e = i.numPages;
141
+ E.value = e, h("totalPagesChange", e), h("pageChange", 1);
142
+ try {
143
+ const n = await i.getOutline();
144
+ n && (v.value = n, S.clear(), await q(n, i));
145
+ } catch (n) {
146
+ console.warn("PDF 大纲提取失败:", n);
147
+ }
148
+ M.value = !1;
149
+ } catch (t) {
150
+ console.error("PDF 加载错误:", t), b.value = R.value("pdf.load_failed"), M.value = !1;
151
+ }
152
+ }, j = () => {
153
+ if (!f.value || u.size === 0) return;
154
+ const t = f.value, e = t.scrollTop, n = t.clientHeight, r = e + n / 2;
155
+ let a = 1, l = 1 / 0;
156
+ u.forEach((o, s) => {
157
+ const p = o.element.getBoundingClientRect(), d = t.getBoundingClientRect(), m = p.top - d.top + p.height / 2 + e, x = Math.abs(r - m);
158
+ x < l && (l = x, a = s);
159
+ }), a !== y.currentPage && h("pageChange", a);
160
+ }, H = () => {
161
+ L(() => {
162
+ var e;
163
+ const t = (e = P.value) == null ? void 0 : e.querySelector(".outline-items");
164
+ t && t.addEventListener("click", (n) => {
165
+ const a = n.target.closest("[data-outline-key]");
166
+ if (!a) return;
167
+ const l = a.getAttribute("data-outline-key"), o = a.getAttribute("data-outline-dest");
168
+ if (!(!l || !o))
169
+ try {
170
+ const s = JSON.parse(o);
171
+ W(s, l);
172
+ } catch (s) {
173
+ console.error("解析大纲目标失败:", s);
174
+ }
175
+ });
176
+ });
177
+ };
178
+ return k(() => y.url, () => {
179
+ y.url && J();
180
+ }, { immediate: !0 }), k(E, (t) => {
181
+ t > 0 && L(() => {
182
+ F();
183
+ });
184
+ }), k(() => y.zoom, () => {
185
+ u.forEach((t, e) => {
186
+ t.rendered && V(e);
187
+ }), setTimeout(() => {
188
+ c && f.value && u.forEach((t) => {
189
+ c == null || c.unobserve(t.element), c == null || c.observe(t.element);
190
+ });
191
+ }, 150);
192
+ }), k(() => y.currentPage, (t) => {
193
+ t > 0 && S.size > 0 && K(t);
194
+ }), k(T, () => {
195
+ L(() => {
196
+ var e;
197
+ const t = (e = P.value) == null ? void 0 : e.querySelector(".outline-items");
198
+ t && v.value.length > 0 && (t.innerHTML = `<ul>${$(v.value)}</ul>`, H());
199
+ });
200
+ }), k(v, () => {
201
+ L(() => {
202
+ var e;
203
+ const t = (e = P.value) == null ? void 0 : e.querySelector(".outline-items");
204
+ !t && v.value.length > 0 ? setTimeout(() => {
205
+ var r;
206
+ const n = (r = P.value) == null ? void 0 : r.querySelector(".outline-items");
207
+ n && (n.innerHTML = `<ul>${$(v.value)}</ul>`, H());
208
+ }, 100) : t && v.value.length > 0 && (t.innerHTML = `<ul>${$(v.value)}</ul>`, H());
209
+ });
210
+ }, { deep: !0 }), G(() => {
211
+ c = new IntersectionObserver(
212
+ (e) => {
213
+ e.forEach((n) => {
214
+ const r = Number(n.target.getAttribute("data-page-number"));
215
+ if (r)
216
+ if (n.isIntersecting)
217
+ X(r, y.zoom);
218
+ else {
219
+ const a = u.get(r);
220
+ a && a.rendered && V(r);
221
+ }
222
+ });
223
+ },
224
+ {
225
+ root: f.value,
226
+ rootMargin: "500px 0px",
227
+ threshold: 0
228
+ }
229
+ );
230
+ const t = f.value;
231
+ t && t.addEventListener("scroll", j);
232
+ }), Q(() => {
233
+ c && (c.disconnect(), c = null);
234
+ const t = f.value;
235
+ if (t && t.removeEventListener("scroll", j), u.forEach((e) => {
236
+ e.renderTask && e.renderTask.cancel();
237
+ }), u.clear(), i) {
238
+ try {
239
+ i.destroy();
240
+ } catch {
241
+ }
242
+ i = null;
243
+ }
244
+ }), (t, e) => (O(), A("div", {
245
+ ref_key: "containerRef",
246
+ ref: P,
247
+ class: "vfp-relative vfp-w-full vfp-h-full"
248
+ }, [
249
+ v.value.length > 0 ? (O(), A("div", {
250
+ key: 0,
251
+ class: "vfp-absolute vfp-inset-0 vfp-z-20 vfp-flex vfp-transition-opacity vfp-duration-300",
252
+ style: B({
253
+ opacity: C.showOutline ? 1 : 0,
254
+ pointerEvents: C.showOutline ? "auto" : "none"
255
+ })
256
+ }, [
257
+ g("div", {
258
+ class: "vfp-w-72 vfp-max-w-[80%] vfp-h-full vfp-bg-surface-overlay vfp-backdrop-blur-xl vfp-border-r vfp-border-line-weak vfp-flex vfp-flex-col vfp-shadow-2xl vfp-transition-transform vfp-duration-300",
259
+ style: B({ transform: C.showOutline ? "translateX(0)" : "translateX(-100%)" })
260
+ }, [
261
+ g("div", le, [
262
+ g("span", ae, Y(z(R)("toolbar.outline")), 1),
263
+ g("button", {
264
+ onClick: e[0] || (e[0] = (n) => h("toggleOutline")),
265
+ class: "vfp-text-fg-tertiary hover:vfp-text-fg-primary vfp-transition-colors"
266
+ }, [
267
+ Z(z(re), { class: "vfp-w-4 vfp-h-4" })
268
+ ])
269
+ ]),
270
+ g("div", {
271
+ class: "vfp-flex-1 vfp-overflow-y-auto vfp-py-4 vfp-px-1 outline-items",
272
+ innerHTML: $(v.value)
273
+ }, null, 8, ie)
274
+ ], 4),
275
+ g("div", {
276
+ class: "vfp-flex-1 vfp-transition-opacity vfp-duration-300",
277
+ style: B({ background: C.showOutline ? "rgba(0,0,0,0.3)" : "transparent" }),
278
+ onClick: e[1] || (e[1] = (n) => h("toggleOutline"))
279
+ }, null, 4)
280
+ ], 4)) : I("", !0),
281
+ g("div", {
282
+ ref_key: "scrollContainerRef",
283
+ ref: f,
284
+ class: "vfp-w-full vfp-h-full vfp-overflow-auto vfp-py-6 vfp-px-4"
285
+ }, [
286
+ b.value ? (O(), D(ne, {
287
+ key: 0,
288
+ message: b.value
289
+ }, null, 8, ["message"])) : I("", !0),
290
+ !b.value && M.value ? (O(), A("div", se, [...e[2] || (e[2] = [
291
+ g("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)
292
+ ])])) : I("", !0),
293
+ b.value ? I("", !0) : (O(), A("div", oe, [...e[3] || (e[3] = [
294
+ g("div", { class: "pdf-pages vfp-flex vfp-flex-col vfp-gap-4" }, null, -1)
295
+ ])]))
296
+ ], 512)
297
+ ], 512));
298
+ }
299
+ });
300
+ export {
301
+ pe as default
302
+ };
303
+ //# sourceMappingURL=index-CYa_XneH.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-CYa_XneH.mjs","sources":["../../src/renderers/Pdf/index.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, watch, onMounted, onBeforeUnmount, nextTick } from 'vue';\nimport { configurePdfWorker } from '@eternalheart/file-preview-core';\n// @ts-ignore - pdfjs-dist 类型路径\nimport * as pdfjsLib from 'pdfjs-dist/build/pdf.mjs';\nimport { useTranslator } from '../../composables/useTranslator';\nimport RendererError from '../RendererError.vue';\nimport { X } from 'lucide-vue-next';\n\n// 在模块加载时配置 PDF.js worker(默认走 CDN)\nconfigurePdfWorker(pdfjsLib);\n\ninterface PdfOutlineItem {\n title: string;\n dest: any;\n items?: PdfOutlineItem[];\n}\n\ninterface PdfPageProxy {\n getViewport(opts: { scale: number }): { width: number; height: number };\n render(opts: { canvasContext: CanvasRenderingContext2D; viewport: { width: number; height: number } }): {\n promise: Promise<void>;\n cancel(): void;\n };\n}\n\ninterface PdfDocumentProxy {\n numPages: number;\n getPage(pageNumber: number): Promise<PdfPageProxy>;\n getOutline(): Promise<PdfOutlineItem[] | null>;\n destroy(): void;\n}\n\ninterface PageState {\n element: HTMLDivElement;\n rendered: boolean;\n rendering: boolean;\n renderTask: any;\n}\n\nconst props = defineProps<{\n url: string;\n zoom: number;\n currentPage: number;\n showOutline?: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: 'pageChange', page: number): void;\n (e: 'totalPagesChange', total: number): void;\n (e: 'pageWidthChange', width: number): void;\n (e: 'toggleOutline'): void;\n}>();\n\nconst { t } = useTranslator();\n\nconst numPages = ref(0);\nconst error = ref<string | null>(null);\nconst isLoading = ref(true);\nconst outline = ref<PdfOutlineItem[]>([]);\nconst activeOutlineItem = ref<string | null>(null);\nconst containerRef = ref<HTMLDivElement | null>(null);\nconst scrollContainerRef = ref<HTMLDivElement | null>(null);\nconst outlinePageMap = new Map<string, number>();\nlet pdfDoc: PdfDocumentProxy | null = null;\nconst pageStates = new Map<number, PageState>();\nlet observer: IntersectionObserver | null = null;\n\n// 构建大纲-页码映射\nconst buildOutlinePageMap = async (items: PdfOutlineItem[], pdfDocument: PdfDocumentProxy, depth = 0) => {\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n const itemKey = `${item.title}-${i}-${depth}`;\n\n try {\n let pageNumber: number | null = null;\n const dest = item.dest;\n\n if (typeof dest === 'string') {\n const namedDest = await (pdfDocument as any).getDestination?.(dest);\n if (namedDest && namedDest[0] && typeof namedDest[0] === 'object') {\n pageNumber = await (pdfDocument as any).getPageIndex?.(namedDest[0]) + 1;\n }\n } else if (Array.isArray(dest) && dest[0] && typeof dest[0] === 'object') {\n pageNumber = await (pdfDocument as any).getPageIndex?.(dest[0]) + 1;\n }\n\n if (pageNumber !== null && pageNumber > 0) {\n outlinePageMap.set(itemKey, pageNumber);\n }\n\n if (item.items && item.items.length > 0) {\n await buildOutlinePageMap(item.items, pdfDocument, depth + 1);\n }\n } catch (err) {\n // 静默失败\n }\n }\n};\n\n// 根据当前页码更新激活的大纲项\nconst updateActiveOutlineByPage = (page: number) => {\n let closestItem: string | null = null;\n let closestDistance = Infinity;\n\n outlinePageMap.forEach((itemPage, itemKey) => {\n if (itemPage <= page) {\n const distance = page - itemPage;\n if (distance < closestDistance) {\n closestDistance = distance;\n closestItem = itemKey;\n }\n }\n });\n\n if (closestItem !== activeOutlineItem.value) {\n activeOutlineItem.value = closestItem;\n }\n};\n\n// 处理大纲点击跳转\nconst handleOutlineClick = async (dest: any, itemKey: string) => {\n if (!pdfDoc || !scrollContainerRef.value) return;\n\n try {\n let pageNumber: number;\n\n if (typeof dest === 'string') {\n const namedDest = await (pdfDoc as any).getDestination?.(dest);\n if (namedDest && namedDest[0]) {\n pageNumber = await (pdfDoc as any).getPageIndex?.(namedDest[0]) + 1;\n } else {\n return;\n }\n } else if (Array.isArray(dest) && dest[0]) {\n pageNumber = await (pdfDoc as any).getPageIndex?.(dest[0]) + 1;\n } else {\n return;\n }\n\n // 设置激活项\n activeOutlineItem.value = itemKey;\n\n // 滚动到目标页面\n const pages = scrollContainerRef.value.querySelectorAll('[data-page-number]');\n const targetPage = pages[pageNumber - 1];\n if (targetPage) {\n targetPage.scrollIntoView({ behavior: 'smooth', block: 'start' });\n }\n\n // 跳转后自动关闭侧边栏\n setTimeout(() => emit('toggleOutline'), 300);\n } catch (err) {\n console.error('大纲跳转失败:', err);\n }\n};\n\n// 渲染大纲项(递归组件会更复杂,这里用简单的方式)\nconst renderOutlineItemsHtml = (items: PdfOutlineItem[], depth = 0): string => {\n return items.map((item, i) => {\n const itemKey = `${item.title}-${i}-${depth}`;\n const isActive = activeOutlineItem.value === itemKey;\n const activeClass = isActive\n ? 'vfp-bg-surface-2 vfp-text-fg-primary vfp-font-medium'\n : 'vfp-text-fg-secondary hover:vfp-text-fg-primary hover:vfp-bg-surface-2';\n\n let html = `<li style=\"margin-left: ${depth > 0 ? 16 : 0}px;\">\n <button\n data-outline-key=\"${itemKey}\"\n data-outline-dest=\"${JSON.stringify(item.dest).replace(/\"/g, '&quot;')}\"\n class=\"vfp-w-full vfp-text-left vfp-py-2 vfp-px-3 vfp-text-sm vfp-rounded vfp-transition-all vfp-truncate ${activeClass}\"\n title=\"${item.title}\"\n >\n ${item.title}\n </button>`;\n\n if (item.items && item.items.length > 0) {\n html += `<ul>${renderOutlineItemsHtml(item.items, depth + 1)}</ul>`;\n }\n\n html += '</li>';\n return html;\n }).join('');\n};\n\nconst renderPage = async (pageNumber: number, scale: number) => {\n if (!pdfDoc) return;\n const state = pageStates.get(pageNumber);\n if (!state || state.rendering) return;\n\n state.rendering = true;\n\n try {\n const page = await pdfDoc.getPage(pageNumber);\n const viewport = page.getViewport({ scale });\n\n const canvas = document.createElement('canvas');\n canvas.width = viewport.width;\n canvas.height = viewport.height;\n canvas.style.maxWidth = '100%';\n canvas.style.height = 'auto';\n canvas.style.borderRadius = '0';\n canvas.style.display = 'block';\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n const renderTask = page.render({ canvasContext: ctx, viewport });\n state.renderTask = renderTask;\n await renderTask.promise;\n\n // 上报第一页原始宽度\n if (pageNumber === 1) {\n const baseViewport = page.getViewport({ scale: 1 });\n emit('pageWidthChange', baseViewport.width);\n }\n\n state.element.innerHTML = '';\n state.element.appendChild(canvas);\n\n state.rendered = true;\n } catch (err: any) {\n if (err?.name !== 'RenderingCancelledException') {\n console.error(`渲染页面 ${pageNumber} 失败:`, err);\n }\n } finally {\n state.rendering = false;\n state.renderTask = null;\n }\n};\n\nconst clearPageCanvas = (pageNumber: number) => {\n const state = pageStates.get(pageNumber);\n if (!state) return;\n\n if (state.renderTask) {\n state.renderTask.cancel();\n state.renderTask = null;\n }\n\n const canvas = state.element.querySelector('canvas');\n if (canvas) {\n const ctx = canvas.getContext('2d');\n if (ctx) {\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n }\n }\n\n state.element.innerHTML = '';\n state.rendered = false;\n state.rendering = false;\n};\n\nconst initPagePlaceholders = () => {\n if (!pdfDoc || !scrollContainerRef.value) return;\n\n const wrapper = scrollContainerRef.value.querySelector('.pdf-pages') as HTMLDivElement | null;\n if (!wrapper) return;\n\n wrapper.innerHTML = '';\n pageStates.clear();\n\n for (let i = 1; i <= numPages.value; i++) {\n const pageDiv = document.createElement('div');\n pageDiv.className = 'vfp-relative vfp-flex vfp-justify-center vfp-min-h-[800px]';\n pageDiv.setAttribute('data-page-number', String(i));\n wrapper.appendChild(pageDiv);\n\n pageStates.set(i, {\n element: pageDiv,\n rendered: false,\n rendering: false,\n renderTask: null,\n });\n\n if (observer) {\n observer.observe(pageDiv);\n }\n }\n};\n\nconst loadPdf = async () => {\n error.value = null;\n isLoading.value = true;\n numPages.value = 0;\n\n if (pdfDoc) {\n try {\n pdfDoc.destroy();\n } catch {\n // ignore\n }\n pdfDoc = null;\n }\n\n try {\n const loadingTask = pdfjsLib.getDocument({ url: props.url });\n pdfDoc = (await loadingTask.promise) as PdfDocumentProxy;\n const total = pdfDoc.numPages;\n\n numPages.value = total;\n emit('totalPagesChange', total);\n emit('pageChange', 1);\n\n // 提取大纲\n try {\n const outlineData = await pdfDoc.getOutline();\n if (outlineData) {\n outline.value = outlineData;\n // 构建大纲-页码映射\n outlinePageMap.clear();\n await buildOutlinePageMap(outlineData, pdfDoc);\n }\n } catch (err) {\n console.warn('PDF 大纲提取失败:', err);\n }\n\n isLoading.value = false;\n } catch (err) {\n console.error('PDF 加载错误:', err);\n error.value = t.value('pdf.load_failed');\n isLoading.value = false;\n }\n};\n\nconst handleScroll = () => {\n if (!scrollContainerRef.value || pageStates.size === 0) return;\n\n const container = scrollContainerRef.value;\n const scrollTop = container.scrollTop;\n const containerHeight = container.clientHeight;\n const scrollCenter = scrollTop + containerHeight / 2;\n\n let currentVisiblePage = 1;\n let minDistance = Infinity;\n\n pageStates.forEach((state, pageNumber) => {\n const rect = state.element.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n const pageCenter = rect.top - containerRect.top + rect.height / 2 + scrollTop;\n\n const distance = Math.abs(scrollCenter - pageCenter);\n if (distance < minDistance) {\n minDistance = distance;\n currentVisiblePage = pageNumber;\n }\n });\n\n if (currentVisiblePage !== props.currentPage) {\n emit('pageChange', currentVisiblePage);\n }\n};\n\n// 设置大纲点击事件代理\nconst setupOutlineEventDelegation = () => {\n nextTick(() => {\n const outlineContainer = containerRef.value?.querySelector('.outline-items');\n if (!outlineContainer) return;\n\n outlineContainer.addEventListener('click', (e: Event) => {\n const target = e.target as HTMLElement;\n const button = target.closest('[data-outline-key]');\n if (!button) return;\n\n const itemKey = button.getAttribute('data-outline-key');\n const destStr = button.getAttribute('data-outline-dest');\n if (!itemKey || !destStr) return;\n\n try {\n const dest = JSON.parse(destStr);\n handleOutlineClick(dest, itemKey);\n } catch (err) {\n console.error('解析大纲目标失败:', err);\n }\n });\n });\n};\n\n// 监听 URL 变化\nwatch(() => props.url, () => {\n if (props.url) {\n loadPdf();\n }\n}, { immediate: true });\n\n// 监听 numPages 变化,初始化占位符\nwatch(numPages, (val) => {\n if (val > 0) {\n nextTick(() => {\n initPagePlaceholders();\n });\n }\n});\n\n// 监听 zoom 变化\nwatch(() => props.zoom, () => {\n pageStates.forEach((state, pageNumber) => {\n if (state.rendered) {\n clearPageCanvas(pageNumber);\n }\n });\n\n setTimeout(() => {\n if (observer && scrollContainerRef.value) {\n pageStates.forEach((state) => {\n observer?.unobserve(state.element);\n observer?.observe(state.element);\n });\n }\n }, 150);\n});\n\n// 监听 currentPage 变化,更新大纲高亮\nwatch(() => props.currentPage, (page) => {\n if (page > 0 && outlinePageMap.size > 0) {\n updateActiveOutlineByPage(page);\n }\n});\n\n// 监听 activeOutlineItem 变化,更新大纲 UI\nwatch(activeOutlineItem, () => {\n nextTick(() => {\n const outlineContainer = containerRef.value?.querySelector('.outline-items');\n if (!outlineContainer) return;\n\n // 重新渲染大纲项\n if (outline.value.length > 0) {\n outlineContainer.innerHTML = `<ul>${renderOutlineItemsHtml(outline.value)}</ul>`;\n // 重新绑定事件\n setupOutlineEventDelegation();\n }\n });\n});\n\n// 监听 outline 变化,渲染大纲\nwatch(outline, () => {\n nextTick(() => {\n const outlineContainer = containerRef.value?.querySelector('.outline-items');\n if (!outlineContainer && outline.value.length > 0) {\n // 容器还没准备好,等待下一次\n setTimeout(() => {\n const container = containerRef.value?.querySelector('.outline-items');\n if (container) {\n container.innerHTML = `<ul>${renderOutlineItemsHtml(outline.value)}</ul>`;\n setupOutlineEventDelegation();\n }\n }, 100);\n } else if (outlineContainer && outline.value.length > 0) {\n outlineContainer.innerHTML = `<ul>${renderOutlineItemsHtml(outline.value)}</ul>`;\n setupOutlineEventDelegation();\n }\n });\n}, { deep: true });\n\nonMounted(() => {\n // 设置 IntersectionObserver\n observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n const pageNumber = Number(entry.target.getAttribute('data-page-number'));\n if (!pageNumber) return;\n\n if (entry.isIntersecting) {\n renderPage(pageNumber, props.zoom);\n } else {\n const state = pageStates.get(pageNumber);\n if (state && state.rendered) {\n clearPageCanvas(pageNumber);\n }\n }\n });\n },\n {\n root: scrollContainerRef.value,\n rootMargin: '500px 0px',\n threshold: 0,\n }\n );\n\n // 监听滚动\n const container = scrollContainerRef.value;\n if (container) {\n container.addEventListener('scroll', handleScroll);\n }\n});\n\nonBeforeUnmount(() => {\n // 清理\n if (observer) {\n observer.disconnect();\n observer = null;\n }\n\n const container = scrollContainerRef.value;\n if (container) {\n container.removeEventListener('scroll', handleScroll);\n }\n\n pageStates.forEach((state) => {\n if (state.renderTask) {\n state.renderTask.cancel();\n }\n });\n pageStates.clear();\n\n if (pdfDoc) {\n try {\n pdfDoc.destroy();\n } catch {\n // ignore\n }\n pdfDoc = null;\n }\n});\n</script>\n\n<template>\n <div ref=\"containerRef\" class=\"vfp-relative vfp-w-full vfp-h-full\">\n <!-- 大纲侧边栏 -->\n <div\n v-if=\"outline.length > 0\"\n class=\"vfp-absolute vfp-inset-0 vfp-z-20 vfp-flex vfp-transition-opacity vfp-duration-300\"\n :style=\"{\n opacity: showOutline ? 1 : 0,\n pointerEvents: showOutline ? 'auto' : 'none',\n }\"\n >\n <div\n class=\"vfp-w-72 vfp-max-w-[80%] vfp-h-full vfp-bg-surface-overlay vfp-backdrop-blur-xl vfp-border-r vfp-border-line-weak vfp-flex vfp-flex-col vfp-shadow-2xl vfp-transition-transform vfp-duration-300\"\n :style=\"{ transform: showOutline ? 'translateX(0)' : 'translateX(-100%)' }\"\n >\n <div class=\"vfp-flex vfp-items-center vfp-justify-between vfp-px-4 vfp-py-3 vfp-border-b vfp-border-line-weak vfp-flex-shrink-0\">\n <span class=\"vfp-text-fg-primary vfp-font-medium vfp-text-sm\">{{ t('toolbar.outline') }}</span>\n <button\n @click=\"emit('toggleOutline')\"\n class=\"vfp-text-fg-tertiary hover:vfp-text-fg-primary vfp-transition-colors\"\n >\n <X class=\"vfp-w-4 vfp-h-4\" />\n </button>\n </div>\n <div class=\"vfp-flex-1 vfp-overflow-y-auto vfp-py-4 vfp-px-1 outline-items\" v-html=\"renderOutlineItemsHtml(outline)\" />\n </div>\n <div\n class=\"vfp-flex-1 vfp-transition-opacity vfp-duration-300\"\n :style=\"{ background: showOutline ? 'rgba(0,0,0,0.3)' : 'transparent' }\"\n @click=\"emit('toggleOutline')\"\n />\n </div>\n\n <div\n ref=\"scrollContainerRef\"\n class=\"vfp-w-full vfp-h-full vfp-overflow-auto vfp-py-6 vfp-px-4\"\n >\n <RendererError v-if=\"error\" :message=\"error\" />\n\n <div v-if=\"!error && isLoading\" class=\"vfp-flex vfp-items-center vfp-justify-center vfp-min-h-screen\">\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 <div v-if=\"!error\" class=\"vfp-flex vfp-flex-col vfp-items-center\">\n <div class=\"pdf-pages vfp-flex vfp-flex-col vfp-gap-4\" />\n </div>\n </div>\n </div>\n</template>\n"],"names":["configurePdfWorker","pdfjsLib","props","__props","emit","__emit","t","useTranslator","numPages","ref","error","isLoading","outline","activeOutlineItem","containerRef","scrollContainerRef","outlinePageMap","pdfDoc","pageStates","observer","buildOutlinePageMap","items","pdfDocument","depth","i","item","itemKey","pageNumber","dest","namedDest","_a","_b","_c","updateActiveOutlineByPage","page","closestItem","closestDistance","itemPage","distance","handleOutlineClick","targetPage","err","renderOutlineItemsHtml","activeClass","html","renderPage","scale","state","viewport","canvas","ctx","renderTask","baseViewport","clearPageCanvas","initPagePlaceholders","wrapper","pageDiv","loadPdf","total","outlineData","handleScroll","container","scrollTop","containerHeight","scrollCenter","currentVisiblePage","minDistance","rect","containerRect","pageCenter","setupOutlineEventDelegation","nextTick","outlineContainer","e","button","destStr","watch","val","onMounted","entries","entry","onBeforeUnmount","_createElementBlock","_normalizeStyle","_createElementVNode","_hoisted_1","_hoisted_2","_toDisplayString","_unref","_createVNode","X","_createBlock","RendererError","_openBlock","_hoisted_4","_cache","_hoisted_5"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { defineComponent as P, ref as y, watch as S, computed as h, openBlock as a, createElementBlock as r, createElementVNode as e, createBlock as V, unref as c, normalizeClass as b, Fragment as w, renderList as k, toDisplayString as o, createCommentVNode as N } from "vue";
2
- import { u as j, a as z, P as A, N as d, E as D, _ as I } from "./index-Oxwizt6-.mjs";
3
- import { _ as M } from "./RendererError.vue_vue_type_script_setup_true_lang-CbgZBSDr.mjs";
1
+ import { defineComponent as P, ref as y, watch as S, computed as h, openBlock as a, createElementBlock as r, createElementVNode as e, createBlock as V, unref as c, normalizeClass as b, Fragment as w, renderList as k, toDisplayString as o, createCommentVNode as T } from "vue";
2
+ import { u as j, a as z, T as A, P as d, E as D, _ as I } from "./index-D9QQL7U6.mjs";
3
+ import { _ as M } from "./RendererError.vue_vue_type_script_setup_true_lang-BNoENOWX.mjs";
4
4
  const O = {
5
5
  key: 0,
6
6
  class: "vfp-flex vfp-items-center vfp-justify-center vfp-w-full vfp-h-full vfp-bg-[#0f0f12]"
@@ -54,7 +54,7 @@ const O = {
54
54
  }), g = h(() => {
55
55
  var s;
56
56
  return ((s = n.value) == null ? void 0 : s.metadata) ?? {};
57
- }), T = (s) => d(s).slice(3, 8);
57
+ }), N = (s) => d(s).slice(3, 8);
58
58
  return (s, t) => p.value ? (a(), r("div", O, [...t[0] || (t[0] = [
59
59
  e("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)
60
60
  ])])) : i.value || !n.value ? (a(), V(M, {
@@ -79,7 +79,7 @@ const O = {
79
79
  t[1] || (t[1] = e("span", { class: "cue-arrow" }, "→", -1)),
80
80
  e("span", G, o(c(d)(l.end)), 1),
81
81
  e("span", H, "#" + o(l.id ?? x + 1), 1),
82
- l.style ? (a(), r("span", J, o(l.style), 1)) : N("", !0)
82
+ l.style ? (a(), r("span", J, o(l.style), 1)) : T("", !0)
83
83
  ]),
84
84
  l.words && l.words.length > 0 ? (a(), r("div", K, [
85
85
  (a(!0), r(w, null, k(l.words, (_, L) => (a(), r("span", {
@@ -87,7 +87,7 @@ const O = {
87
87
  class: "cue-word",
88
88
  title: c(d)(_.start)
89
89
  }, [
90
- e("span", U, o(T(_.start)), 1),
90
+ e("span", U, o(N(_.start)), 1),
91
91
  e("span", W, o(_.text), 1)
92
92
  ], 8, Q))), 128))
93
93
  ])) : (a(), r("p", {
@@ -103,12 +103,12 @@ const O = {
103
103
  g.value.length ? (a(), r(w, { key: 0 }, [
104
104
  t[4] || (t[4] = e("span", { class: "dot" }, "·", -1)),
105
105
  e("span", null, o(g.value.length), 1)
106
- ], 64)) : N("", !0)
106
+ ], 64)) : T("", !0)
107
107
  ])
108
108
  ], 2));
109
109
  }
110
- }), re = /* @__PURE__ */ I(ee, [["__scopeId", "data-v-190dfbd6"]]);
110
+ }), re = /* @__PURE__ */ I(ee, [["__scopeId", "data-v-a5bde9e5"]]);
111
111
  export {
112
112
  re as default
113
113
  };
114
- //# sourceMappingURL=index-CYt6tpQC.mjs.map
114
+ //# sourceMappingURL=index-CbJkkdEB.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-CbJkkdEB.mjs","sources":["../../src/renderers/Subtitle/index.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, watch } from 'vue';\nimport {\n parseSubtitle,\n formatSubtitleTime,\n fetchTextUtf8,\n type SubtitleParseResult,\n type SubtitleFormat,\n} from '@eternalheart/file-preview-core';\nimport { useTranslator } from '../../composables/useTranslator';\nimport { useFetcher } from '../../composables/useRequest';\nimport RendererError from '../RendererError.vue';\n\nconst props = defineProps<{\n url: string;\n fileName: string;\n}>();\n\nconst { t } = useTranslator();\nconst fetcher = useFetcher();\n\nconst text = ref<string>('');\nconst loading = ref(true);\nconst error = ref<string | null>(null);\n\nconst FORMAT_BY_EXT: Record<string, SubtitleFormat> = {\n srt: 'srt',\n vtt: 'vtt',\n lrc: 'lrc',\n elrc: 'elrc',\n ass: 'ass',\n ssa: 'ssa',\n ttml: 'ttml',\n dfxp: 'ttml',\n};\n\nconst getFormat = (fileName: string): SubtitleFormat | undefined => {\n const ext = fileName.split('.').pop()?.toLowerCase() || '';\n return FORMAT_BY_EXT[ext];\n};\n\nconst load = async () => {\n loading.value = true;\n error.value = null;\n try {\n text.value = await fetchTextUtf8(props.url, { fetcher: fetcher.value });\n } catch (err) {\n console.error(err);\n error.value = t.value('subtitle.load_failed');\n } finally {\n loading.value = false;\n }\n};\n\nwatch(() => props.url, load, { immediate: true });\n\nconst parsed = computed<SubtitleParseResult | null>(() => {\n if (!text.value) return null;\n try {\n return parseSubtitle(text.value, getFormat(props.fileName));\n } catch (err) {\n console.error(err);\n return null;\n }\n});\n\nconst isLyric = computed(() => parsed.value?.format === 'lrc' || parsed.value?.format === 'elrc');\n\nconst meta = computed<Record<string, string>>(() => parsed.value?.metadata ?? {});\n\nconst wordTimeShort = (t: number) => formatSubtitleTime(t).slice(3, 8);\n</script>\n\n<template>\n <div\n v-if=\"loading\"\n class=\"vfp-flex vfp-items-center vfp-justify-center vfp-w-full vfp-h-full vfp-bg-[#0f0f12]\"\n >\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\n v-else-if=\"error || !parsed\"\n :message=\"error || t('subtitle.parse_failed')\"\n class=\"vfp-bg-[#0f0f12]\"\n />\n\n <div\n v-else\n class=\"vfp-relative vfp-w-full vfp-h-full vfp-bg-[#0f0f12]\"\n :class=\"isLyric ? 'flavor-lyric' : 'flavor-subtitle'\"\n >\n <!-- 内容滚动区 -->\n <div class=\"content-scroll\">\n <div class=\"timeline\">\n <div class=\"timeline-line\" />\n <ol class=\"cues\">\n <li v-for=\"(cue, i) in parsed.cues\" :key=\"'cue-' + i\" class=\"cue-row\">\n <div class=\"cue-dot\" />\n <div class=\"cue-meta\">\n <span class=\"cue-time\">{{ formatSubtitleTime(cue.start) }}</span>\n <span class=\"cue-arrow\">→</span>\n <span class=\"cue-time\">{{ formatSubtitleTime(cue.end) }}</span>\n <span class=\"cue-id\">#{{ cue.id ?? i + 1 }}</span>\n <span v-if=\"cue.style\" class=\"cue-style\">{{ cue.style }}</span>\n </div>\n <div v-if=\"cue.words && cue.words.length > 0\" class=\"cue-words\">\n <span\n v-for=\"(word, wi) in cue.words\"\n :key=\"'w-' + wi\"\n class=\"cue-word\"\n :title=\"formatSubtitleTime(word.start)\"\n >\n <span class=\"cue-word-time\">{{ wordTimeShort(word.start) }}</span>\n <span class=\"cue-word-text\">{{ word.text }}</span>\n </span>\n </div>\n <p v-else class=\"cue-text\" :class=\"{ lyric: isLyric }\">{{ cue.text }}</p>\n </li>\n </ol>\n </div>\n </div>\n\n <!-- 右下角浮签 -->\n <div class=\"status-pill\">\n <span>{{ parsed.cues.length }} {{ isLyric ? t('subtitle.lines') : t('subtitle.cues') }}</span>\n <template v-if=\"meta.length\">\n <span class=\"dot\">·</span>\n <span>{{ meta.length }}</span>\n </template>\n </div>\n </div>\n</template>\n\n<style scoped>\n.content-scroll {\n width: 100%;\n height: 100%;\n overflow: auto;\n padding: 1.5rem 1rem 4rem;\n}\n.status-pill {\n pointer-events: none;\n position: absolute;\n bottom: 0.75rem;\n right: 0.75rem;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.25rem 0.625rem;\n border-radius: 9999px;\n background: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(8px);\n border: 1px solid var(--fp-line);\n font-size: 0.625rem;\n color: var(--fp-fg-tertiary);\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n font-variant-numeric: tabular-nums;\n}\n.dot {\n color: var(--fp-fg-disabled);\n}\n\n.timeline {\n position: relative;\n}\n.timeline-line {\n position: absolute;\n left: 5px;\n top: 0.5rem;\n bottom: 0.5rem;\n width: 1px;\n background: var(--fp-line-weak);\n}\n.cues {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 1.25rem;\n}\n.cue-row {\n position: relative;\n padding-left: 1.5rem;\n}\n.cue-dot {\n position: absolute;\n left: 0;\n top: 0.4rem;\n width: 0.75rem;\n height: 0.75rem;\n border-radius: 9999px;\n background: var(--fp-surface-3);\n border: 2px solid #0f0f12;\n transition: background-color 0.2s;\n}\n.flavor-lyric .cue-row:hover .cue-dot {\n background: rgb(167, 139, 250);\n}\n.flavor-subtitle .cue-row:hover .cue-dot {\n background: rgb(56, 189, 248);\n}\n.cue-meta {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: 0.25rem 0.75rem;\n margin-bottom: 0.375rem;\n}\n.cue-time {\n font-size: 0.6875rem;\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n color: var(--fp-fg-muted);\n font-variant-numeric: tabular-nums;\n}\n.cue-arrow {\n font-size: 0.6875rem;\n color: var(--fp-fg-disabled);\n}\n.cue-id {\n font-size: 0.625rem;\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n color: var(--fp-fg-disabled);\n font-variant-numeric: tabular-nums;\n}\n.cue-style {\n font-size: 0.5625rem;\n text-transform: uppercase;\n letter-spacing: 0.1em;\n color: var(--fp-fg-tertiary);\n padding: 0.125rem 0.375rem;\n border-radius: 0.25rem;\n background: var(--fp-line-weak);\n border: 1px solid var(--fp-line);\n}\n.cue-text {\n margin: 0;\n white-space: pre-wrap;\n word-break: break-word;\n line-height: 1.625;\n color: var(--fp-fg-primary);\n font-size: 0.875rem;\n min-height: 1.25rem;\n transition: color 0.2s;\n}\n.cue-text.lyric {\n font-size: 1rem;\n font-weight: 500;\n}\n.cue-row:hover .cue-text {\n color: #fff;\n}\n.cue-words {\n display: flex;\n flex-wrap: wrap;\n gap: 0.25rem 0.375rem;\n font-size: 1rem;\n color: var(--fp-fg-primary);\n line-height: 1.625;\n transition: color 0.2s;\n}\n.cue-row:hover .cue-words {\n color: #fff;\n}\n.cue-word {\n display: inline-flex;\n flex-direction: column;\n align-items: flex-start;\n}\n.cue-word-time {\n font-size: 0.5625rem;\n color: var(--fp-fg-disabled);\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n line-height: 1;\n font-variant-numeric: tabular-nums;\n}\n.cue-word-text {\n line-height: 1.4;\n}\n</style>\n"],"names":["props","__props","t","useTranslator","fetcher","useFetcher","text","ref","loading","error","FORMAT_BY_EXT","getFormat","fileName","ext","_a","watch","fetchTextUtf8","err","parsed","computed","parseSubtitle","isLyric","_b","meta","wordTimeShort","formatSubtitleTime","_openBlock","_createElementBlock","_hoisted_1","_cache","_createElementVNode","_createBlock","RendererError","_unref","_normalizeClass","_hoisted_2","_hoisted_3","_hoisted_4","_Fragment","cue","i","_hoisted_5","_hoisted_6","_toDisplayString","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","word","wi","_hoisted_12","_hoisted_13","_hoisted_14"],"mappings":"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"}
@@ -2,8 +2,8 @@ import { defineComponent as E, ref as p, onMounted as T, watch as D, onBeforeUnm
2
2
  import W from "exceljs";
3
3
  import H from "x-data-spreadsheet";
4
4
  /* empty css */
5
- import { u as R, a as C, I } from "./index-Oxwizt6-.mjs";
6
- import { _ as L } from "./RendererError.vue_vue_type_script_setup_true_lang-CbgZBSDr.mjs";
5
+ import { u as R, a as C, I } from "./index-D9QQL7U6.mjs";
6
+ import { _ as L } from "./RendererError.vue_vue_type_script_setup_true_lang-BNoENOWX.mjs";
7
7
  const F = { class: "vfp-relative vfp-flex vfp-flex-col vfp-items-center vfp-w-full vfp-h-full" }, N = {
8
8
  key: 0,
9
9
  class: "vfp-absolute vfp-inset-0 vfp-flex vfp-items-center vfp-justify-center vfp-bg-surface-toolbar vfp-backdrop-blur-sm vfp-z-10"
@@ -114,4 +114,4 @@ const F = { class: "vfp-relative vfp-flex vfp-flex-col vfp-items-center vfp-w-fu
114
114
  export {
115
115
  U as default
116
116
  };
117
- //# sourceMappingURL=index-DEoR7aDN.mjs.map
117
+ //# sourceMappingURL=index-CoITLoYL.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-DEoR7aDN.mjs","sources":["../../src/renderers/Xlsx/index.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, watch, onMounted, onBeforeUnmount } from 'vue';\nimport ExcelJS from 'exceljs';\nimport Spreadsheet from 'x-data-spreadsheet';\nimport 'x-data-spreadsheet/dist/xspreadsheet.css';\nimport { convertWorkbookToSpreadsheetData } from '@eternalheart/file-preview-core';\nimport { useTranslator } from '../../composables/useTranslator';\nimport { useFetcher } from '../../composables/useRequest';\nimport RendererError from '../RendererError.vue';\n\nconst props = defineProps<{\n url: string;\n}>();\n\nconst { t } = useTranslator();\nconst fetcher = useFetcher();\n\nconst loading = ref(true);\nconst error = ref<string | null>(null);\nconst containerRef = ref<HTMLDivElement | null>(null);\nlet sheetData: Record<string, unknown>[] | null = null;\nlet resizeObserver: ResizeObserver | null = null;\nlet resizeTimeout: number | null = null;\nlet lastDimensions = { width: 0, height: 0 };\n\nconst calculateDimensions = () => {\n if (!containerRef.value) return { width: 800, height: 600 };\n const rawWidth = containerRef.value.clientWidth;\n const rawHeight = containerRef.value.clientHeight;\n const width = rawWidth > 100 ? rawWidth : 800;\n const height = rawHeight > 100 ? rawHeight : 600;\n return { width, height };\n};\n\nconst mountSpreadsheet = () => {\n if (!containerRef.value || !sheetData) return;\n\n containerRef.value.innerHTML = '';\n\n const { width, height } = calculateDimensions();\n const isMobile = width < 640;\n\n const s = new Spreadsheet(containerRef.value, {\n mode: 'read',\n showToolbar: false,\n showContextmenu: false,\n showGrid: true,\n row: {\n len: 100,\n height: 25,\n },\n col: {\n len: 26,\n width: isMobile ? 80 : 100,\n indexWidth: isMobile ? 40 : 60,\n minWidth: isMobile ? 40 : 60,\n },\n view: {\n height: () => height,\n width: () => width,\n },\n });\n\n s.loadData(sheetData as unknown as Record<string, unknown>);\n};\n\nconst loadExcel = async () => {\n if (!containerRef.value) return;\n\n loading.value = true;\n error.value = null;\n\n try {\n const response = await fetcher.value(props.url, {\n mode: 'cors',\n credentials: 'omit',\n redirect: 'follow',\n });\n\n if (!response.ok) {\n if (response.status === 404) throw new Error(t.value('xlsx.not_found'));\n if (response.status === 403) throw new Error('无权限访问此文件');\n throw new Error(`文件加载失败 (${response.status})`);\n }\n\n const arrayBuffer = await response.arrayBuffer();\n\n if (arrayBuffer.byteLength === 0) {\n throw new Error('文件为空');\n }\n\n const workbook = new ExcelJS.Workbook();\n await workbook.xlsx.load(arrayBuffer);\n const data = convertWorkbookToSpreadsheetData(workbook);\n\n sheetData = data as unknown as Record<string, unknown>[];\n mountSpreadsheet();\n loading.value = false;\n } catch (err) {\n console.error('Excel 解析错误:', err);\n let errorMsg = t.value('xlsx.parse_failed');\n if (err instanceof Error) errorMsg = err.message;\n error.value = errorMsg;\n loading.value = false;\n }\n};\n\nonMounted(() => {\n if (!containerRef.value) return;\n\n let isInitialRender = true;\n\n resizeObserver = new ResizeObserver(() => {\n if (isInitialRender) {\n isInitialRender = false;\n lastDimensions = calculateDimensions();\n return;\n }\n\n const newDimensions = calculateDimensions();\n const widthDiff = Math.abs(lastDimensions.width - newDimensions.width);\n const heightDiff = Math.abs(lastDimensions.height - newDimensions.height);\n\n if (widthDiff < 10 && heightDiff < 10) return;\n\n lastDimensions = newDimensions;\n\n if (resizeTimeout !== null) clearTimeout(resizeTimeout);\n\n resizeTimeout = window.setTimeout(() => {\n if (sheetData) mountSpreadsheet();\n }, 500);\n });\n\n resizeObserver.observe(containerRef.value);\n\n setTimeout(() => {\n requestAnimationFrame(() => loadExcel());\n }, 100);\n});\n\nwatch(\n () => props.url,\n (newUrl) => {\n // 只有 URL 有效时才加载(避免空字符串或已 revoke 的 blob URL)\n if (newUrl) loadExcel();\n }\n);\n\nonBeforeUnmount(() => {\n if (resizeObserver) resizeObserver.disconnect();\n if (resizeTimeout !== null) clearTimeout(resizeTimeout);\n sheetData = null;\n if (containerRef.value) containerRef.value.innerHTML = '';\n});\n</script>\n\n<template>\n <div class=\"vfp-relative vfp-flex vfp-flex-col vfp-items-center vfp-w-full vfp-h-full\">\n <div\n v-if=\"loading\"\n class=\"vfp-absolute vfp-inset-0 vfp-flex vfp-items-center vfp-justify-center vfp-bg-surface-toolbar vfp-backdrop-blur-sm vfp-z-10\"\n >\n <div class=\"vfp-text-center\">\n <div\n class=\"vfp-w-10 vfp-h-10 md:vfp-w-12 md:vfp-h-12 vfp-mx-auto vfp-mb-3 vfp-border-4 vfp-border-line-strong vfp-border-t-spinner-head vfp-rounded-full vfp-animate-spin\"\n />\n <p class=\"vfp-text-xs md:vfp-text-sm vfp-text-fg-secondary vfp-font-medium\">{{ t('xlsx.loading') }}</p>\n </div>\n </div>\n\n <RendererError\n v-if=\"error && !loading\"\n :message=\"t('xlsx.load_failed')\"\n :detail=\"error\"\n class=\"vfp-absolute vfp-inset-0 vfp-bg-surface-toolbar vfp-backdrop-blur-sm vfp-z-10\"\n />\n\n <div\n v-if=\"!error\"\n ref=\"containerRef\"\n class=\"xlsx-spreadsheet-container vfp-w-full vfp-h-full\"\n :style=\"{ opacity: loading ? 0 : 1 }\"\n />\n </div>\n</template>\n"],"names":["props","__props","t","useTranslator","fetcher","useFetcher","loading","ref","error","containerRef","sheetData","resizeObserver","resizeTimeout","lastDimensions","calculateDimensions","rawWidth","rawHeight","width","height","mountSpreadsheet","isMobile","Spreadsheet","loadExcel","response","arrayBuffer","workbook","ExcelJS","convertWorkbookToSpreadsheetData","err","errorMsg","onMounted","isInitialRender","newDimensions","widthDiff","heightDiff","watch","newUrl","onBeforeUnmount","_openBlock","_createElementBlock","_hoisted_1","_hoisted_2","_createElementVNode","_hoisted_3","_hoisted_4","_toDisplayString","_unref","_createBlock","RendererError"],"mappings":"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"}
1
+ {"version":3,"file":"index-CoITLoYL.mjs","sources":["../../src/renderers/Xlsx/index.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, watch, onMounted, onBeforeUnmount } from 'vue';\nimport ExcelJS from 'exceljs';\nimport Spreadsheet from 'x-data-spreadsheet';\nimport 'x-data-spreadsheet/dist/xspreadsheet.css';\nimport { convertWorkbookToSpreadsheetData } from '@eternalheart/file-preview-core';\nimport { useTranslator } from '../../composables/useTranslator';\nimport { useFetcher } from '../../composables/useRequest';\nimport RendererError from '../RendererError.vue';\n\nconst props = defineProps<{\n url: string;\n}>();\n\nconst { t } = useTranslator();\nconst fetcher = useFetcher();\n\nconst loading = ref(true);\nconst error = ref<string | null>(null);\nconst containerRef = ref<HTMLDivElement | null>(null);\nlet sheetData: Record<string, unknown>[] | null = null;\nlet resizeObserver: ResizeObserver | null = null;\nlet resizeTimeout: number | null = null;\nlet lastDimensions = { width: 0, height: 0 };\n\nconst calculateDimensions = () => {\n if (!containerRef.value) return { width: 800, height: 600 };\n const rawWidth = containerRef.value.clientWidth;\n const rawHeight = containerRef.value.clientHeight;\n const width = rawWidth > 100 ? rawWidth : 800;\n const height = rawHeight > 100 ? rawHeight : 600;\n return { width, height };\n};\n\nconst mountSpreadsheet = () => {\n if (!containerRef.value || !sheetData) return;\n\n containerRef.value.innerHTML = '';\n\n const { width, height } = calculateDimensions();\n const isMobile = width < 640;\n\n const s = new Spreadsheet(containerRef.value, {\n mode: 'read',\n showToolbar: false,\n showContextmenu: false,\n showGrid: true,\n row: {\n len: 100,\n height: 25,\n },\n col: {\n len: 26,\n width: isMobile ? 80 : 100,\n indexWidth: isMobile ? 40 : 60,\n minWidth: isMobile ? 40 : 60,\n },\n view: {\n height: () => height,\n width: () => width,\n },\n });\n\n s.loadData(sheetData as unknown as Record<string, unknown>);\n};\n\nconst loadExcel = async () => {\n if (!containerRef.value) return;\n\n loading.value = true;\n error.value = null;\n\n try {\n const response = await fetcher.value(props.url, {\n mode: 'cors',\n credentials: 'omit',\n redirect: 'follow',\n });\n\n if (!response.ok) {\n if (response.status === 404) throw new Error(t.value('xlsx.not_found'));\n if (response.status === 403) throw new Error('无权限访问此文件');\n throw new Error(`文件加载失败 (${response.status})`);\n }\n\n const arrayBuffer = await response.arrayBuffer();\n\n if (arrayBuffer.byteLength === 0) {\n throw new Error('文件为空');\n }\n\n const workbook = new ExcelJS.Workbook();\n await workbook.xlsx.load(arrayBuffer);\n const data = convertWorkbookToSpreadsheetData(workbook);\n\n sheetData = data as unknown as Record<string, unknown>[];\n mountSpreadsheet();\n loading.value = false;\n } catch (err) {\n console.error('Excel 解析错误:', err);\n let errorMsg = t.value('xlsx.parse_failed');\n if (err instanceof Error) errorMsg = err.message;\n error.value = errorMsg;\n loading.value = false;\n }\n};\n\nonMounted(() => {\n if (!containerRef.value) return;\n\n let isInitialRender = true;\n\n resizeObserver = new ResizeObserver(() => {\n if (isInitialRender) {\n isInitialRender = false;\n lastDimensions = calculateDimensions();\n return;\n }\n\n const newDimensions = calculateDimensions();\n const widthDiff = Math.abs(lastDimensions.width - newDimensions.width);\n const heightDiff = Math.abs(lastDimensions.height - newDimensions.height);\n\n if (widthDiff < 10 && heightDiff < 10) return;\n\n lastDimensions = newDimensions;\n\n if (resizeTimeout !== null) clearTimeout(resizeTimeout);\n\n resizeTimeout = window.setTimeout(() => {\n if (sheetData) mountSpreadsheet();\n }, 500);\n });\n\n resizeObserver.observe(containerRef.value);\n\n setTimeout(() => {\n requestAnimationFrame(() => loadExcel());\n }, 100);\n});\n\nwatch(\n () => props.url,\n (newUrl) => {\n // 只有 URL 有效时才加载(避免空字符串或已 revoke 的 blob URL)\n if (newUrl) loadExcel();\n }\n);\n\nonBeforeUnmount(() => {\n if (resizeObserver) resizeObserver.disconnect();\n if (resizeTimeout !== null) clearTimeout(resizeTimeout);\n sheetData = null;\n if (containerRef.value) containerRef.value.innerHTML = '';\n});\n</script>\n\n<template>\n <div class=\"vfp-relative vfp-flex vfp-flex-col vfp-items-center vfp-w-full vfp-h-full\">\n <div\n v-if=\"loading\"\n class=\"vfp-absolute vfp-inset-0 vfp-flex vfp-items-center vfp-justify-center vfp-bg-surface-toolbar vfp-backdrop-blur-sm vfp-z-10\"\n >\n <div class=\"vfp-text-center\">\n <div\n class=\"vfp-w-10 vfp-h-10 md:vfp-w-12 md:vfp-h-12 vfp-mx-auto vfp-mb-3 vfp-border-4 vfp-border-line-strong vfp-border-t-spinner-head vfp-rounded-full vfp-animate-spin\"\n />\n <p class=\"vfp-text-xs md:vfp-text-sm vfp-text-fg-secondary vfp-font-medium\">{{ t('xlsx.loading') }}</p>\n </div>\n </div>\n\n <RendererError\n v-if=\"error && !loading\"\n :message=\"t('xlsx.load_failed')\"\n :detail=\"error\"\n class=\"vfp-absolute vfp-inset-0 vfp-bg-surface-toolbar vfp-backdrop-blur-sm vfp-z-10\"\n />\n\n <div\n v-if=\"!error\"\n ref=\"containerRef\"\n class=\"xlsx-spreadsheet-container vfp-w-full vfp-h-full\"\n :style=\"{ opacity: loading ? 0 : 1 }\"\n />\n </div>\n</template>\n"],"names":["props","__props","t","useTranslator","fetcher","useFetcher","loading","ref","error","containerRef","sheetData","resizeObserver","resizeTimeout","lastDimensions","calculateDimensions","rawWidth","rawHeight","width","height","mountSpreadsheet","isMobile","Spreadsheet","loadExcel","response","arrayBuffer","workbook","ExcelJS","convertWorkbookToSpreadsheetData","err","errorMsg","onMounted","isInitialRender","newDimensions","widthDiff","heightDiff","watch","newUrl","onBeforeUnmount","_openBlock","_createElementBlock","_hoisted_1","_hoisted_2","_createElementVNode","_hoisted_3","_hoisted_4","_toDisplayString","_unref","_createBlock","RendererError"],"mappings":"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"}