@eternalheart/vue-file-preview 1.3.7 → 1.3.9
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/lib/FilePreviewContent.vue.d.ts +13 -1
- package/lib/FilePreviewContent.vue.d.ts.map +1 -1
- package/lib/FilePreviewEmbed.vue.d.ts +13 -1
- package/lib/FilePreviewEmbed.vue.d.ts.map +1 -1
- package/lib/FilePreviewModal.vue.d.ts +13 -1
- package/lib/FilePreviewModal.vue.d.ts.map +1 -1
- package/lib/chunks/{index-CcJ5NmY1.mjs → index-1khRVlUa.mjs} +25 -25
- package/lib/chunks/index-1khRVlUa.mjs.map +1 -0
- package/lib/chunks/{index-C8ZF84WX.mjs → index-B9Xz5bUB.mjs} +2 -2
- package/lib/chunks/{index-C8ZF84WX.mjs.map → index-B9Xz5bUB.mjs.map} +1 -1
- package/lib/chunks/{index-DpAxU2JM.mjs → index-BA-bP8P6.mjs} +789 -649
- package/lib/chunks/index-BA-bP8P6.mjs.map +1 -0
- package/lib/chunks/{index-DTLDLOGO.mjs → index-BP_8GjEV.mjs} +28 -28
- package/lib/chunks/index-BP_8GjEV.mjs.map +1 -0
- package/lib/chunks/{index-Doy0FvQW.mjs → index-BVdw1Cc8.mjs} +32 -32
- package/lib/chunks/index-BVdw1Cc8.mjs.map +1 -0
- package/lib/chunks/{index-yMb1JUC4.mjs → index-BqSPk90T.mjs} +30 -30
- package/lib/chunks/index-BqSPk90T.mjs.map +1 -0
- package/lib/chunks/index-BrCSk7CK.mjs +116 -0
- package/lib/chunks/index-BrCSk7CK.mjs.map +1 -0
- package/lib/chunks/{index-BI0dSTSM.mjs → index-Bu8GH1aq.mjs} +27 -27
- package/lib/chunks/index-Bu8GH1aq.mjs.map +1 -0
- package/lib/chunks/{index-ClxBxmPR.mjs → index-CYvPRxHK.mjs} +53 -53
- package/lib/chunks/index-CYvPRxHK.mjs.map +1 -0
- package/lib/chunks/{index-CbKSdAt_.mjs → index-Cfm88ItA.mjs} +2 -2
- package/lib/chunks/{index-CbKSdAt_.mjs.map → index-Cfm88ItA.mjs.map} +1 -1
- package/lib/chunks/{index-kBPb_OKm.mjs → index-CxKVonec.mjs} +52 -52
- package/lib/chunks/index-CxKVonec.mjs.map +1 -0
- package/lib/chunks/index-D6RuC1es.mjs +111 -0
- package/lib/chunks/index-D6RuC1es.mjs.map +1 -0
- package/lib/chunks/{index-CB0zCxJb.mjs → index-DEyjEp-i.mjs} +106 -106
- package/lib/chunks/index-DEyjEp-i.mjs.map +1 -0
- package/lib/chunks/{index-DsznjwsH.mjs → index-DFEd3JaR.mjs} +35 -35
- package/lib/chunks/index-DFEd3JaR.mjs.map +1 -0
- package/lib/chunks/index-DjvWRo53.mjs +281 -0
- package/lib/chunks/index-DjvWRo53.mjs.map +1 -0
- package/lib/chunks/{index-DUUsS_T4.mjs → index-H-QlBdbJ.mjs} +2 -2
- package/lib/chunks/{index-DUUsS_T4.mjs.map → index-H-QlBdbJ.mjs.map} +1 -1
- package/lib/chunks/{index-S_kGRh6H.mjs → index-_llF_WTY.mjs} +46 -46
- package/lib/chunks/index-_llF_WTY.mjs.map +1 -0
- package/lib/chunks/{index-D9lByoJw.mjs → index-oQRFKvtz.mjs} +13 -13
- package/lib/chunks/{index-D9lByoJw.mjs.map → index-oQRFKvtz.mjs.map} +1 -1
- package/lib/composables/useRequest.d.ts +24 -0
- package/lib/composables/useRequest.d.ts.map +1 -0
- package/lib/index.cjs +23 -23
- package/lib/index.cjs.map +1 -1
- package/lib/index.css +1 -1
- package/lib/index.mjs +6 -6
- package/lib/renderers/Csv/index.vue.d.ts.map +1 -1
- package/lib/renderers/Docx/index.vue.d.ts.map +1 -1
- package/lib/renderers/Epub/index.vue.d.ts.map +1 -1
- package/lib/renderers/Json/index.vue.d.ts.map +1 -1
- package/lib/renderers/Markdown/index.vue.d.ts.map +1 -1
- package/lib/renderers/Mobi/index.vue.d.ts.map +1 -1
- package/lib/renderers/Msg/index.vue.d.ts.map +1 -1
- package/lib/renderers/Pptx/index.vue.d.ts.map +1 -1
- package/lib/renderers/Subtitle/index.vue.d.ts.map +1 -1
- package/lib/renderers/Text/index.vue.d.ts.map +1 -1
- package/lib/renderers/Xlsx/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/lib/types.d.ts +1 -1
- package/lib/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/lib/chunks/index-BI0dSTSM.mjs.map +0 -1
- package/lib/chunks/index-BW61ZRev.mjs +0 -111
- package/lib/chunks/index-BW61ZRev.mjs.map +0 -1
- package/lib/chunks/index-CB0zCxJb.mjs.map +0 -1
- package/lib/chunks/index-CBCQs1ZC.mjs +0 -116
- package/lib/chunks/index-CBCQs1ZC.mjs.map +0 -1
- package/lib/chunks/index-CcJ5NmY1.mjs.map +0 -1
- package/lib/chunks/index-ClxBxmPR.mjs.map +0 -1
- package/lib/chunks/index-DTLDLOGO.mjs.map +0 -1
- package/lib/chunks/index-Doy0FvQW.mjs.map +0 -1
- package/lib/chunks/index-DpAxU2JM.mjs.map +0 -1
- package/lib/chunks/index-DsznjwsH.mjs.map +0 -1
- package/lib/chunks/index-SAfVQyNJ.mjs +0 -281
- package/lib/chunks/index-SAfVQyNJ.mjs.map +0 -1
- package/lib/chunks/index-S_kGRh6H.mjs.map +0 -1
- package/lib/chunks/index-kBPb_OKm.mjs.map +0 -1
- package/lib/chunks/index-yMb1JUC4.mjs.map +0 -1
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
import { defineComponent as
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import { defineComponent as G, computed as I, ref as c, watch as _, nextTick as P, openBlock as a, createElementBlock as d, createElementVNode as i, toDisplayString as H } from "vue";
|
|
2
|
+
import D from "markdown-it";
|
|
3
|
+
import K from "@traptitech/markdown-it-katex";
|
|
4
4
|
import { codeToHtml as E } from "shiki";
|
|
5
|
-
import { u as
|
|
5
|
+
import { u as O, a as R, b as N, c as Y, _ as F } from "./index-BA-bP8P6.mjs";
|
|
6
6
|
import "katex/dist/katex.min.css";
|
|
7
|
-
const
|
|
7
|
+
const W = {
|
|
8
8
|
key: 0,
|
|
9
9
|
class: "vfp-flex vfp-items-center vfp-justify-center vfp-w-full vfp-h-full"
|
|
10
|
-
},
|
|
10
|
+
}, z = {
|
|
11
11
|
key: 1,
|
|
12
12
|
class: "vfp-flex vfp-items-center vfp-justify-center vfp-w-full vfp-h-full"
|
|
13
|
-
},
|
|
13
|
+
}, J = { class: "vfp-text-fg-secondary vfp-text-center" }, Q = { class: "vfp-text-lg" }, U = {
|
|
14
14
|
key: 2,
|
|
15
15
|
class: "vfp-w-full vfp-h-full vfp-overflow-auto",
|
|
16
16
|
style: { background: "var(--fp-code-bg)" }
|
|
17
|
-
},
|
|
17
|
+
}, X = {
|
|
18
18
|
key: 0,
|
|
19
19
|
class: "vfp-p-6 vfp-text-fg-primary vfp-font-mono vfp-text-sm vfp-whitespace-pre-wrap vfp-break-words"
|
|
20
|
-
},
|
|
20
|
+
}, Z = ["innerHTML"], ee = {
|
|
21
21
|
key: 3,
|
|
22
22
|
class: "vfp-w-full vfp-h-full vfp-overflow-auto vfp-p-6 md:vfp-p-10"
|
|
23
|
-
},
|
|
23
|
+
}, te = { class: "vfp-max-w-full md:vfp-max-w-4xl vfp-mx-auto" }, oe = ["innerHTML"], L = '<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>', B = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>', re = '<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>', ne = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>', le = /* @__PURE__ */ G({
|
|
24
24
|
__name: "index",
|
|
25
25
|
props: {
|
|
26
26
|
url: {},
|
|
27
27
|
viewMode: {}
|
|
28
28
|
},
|
|
29
29
|
setup(b) {
|
|
30
|
-
const x = b, { t: p } =
|
|
30
|
+
const x = b, { t: p } = O(), j = R(), q = N(), g = I(() => q.value === "light" ? "github-light" : "github-dark"), y = c(""), u = c(""), v = c(""), f = c(!0), h = c(null), m = c(null), l = new D({
|
|
31
31
|
html: !0,
|
|
32
32
|
linkify: !0,
|
|
33
33
|
typographer: !1,
|
|
34
34
|
breaks: !1
|
|
35
35
|
});
|
|
36
|
-
l.use(
|
|
36
|
+
l.use(K), l.renderer.rules.fence = (o, r) => {
|
|
37
37
|
const e = o[r], n = e.info ? e.info.trim() : "", t = e.content;
|
|
38
38
|
return n ? `<div class="code-block-wrapper">
|
|
39
39
|
<div class="code-block-header">
|
|
@@ -49,14 +49,14 @@ const Y = {
|
|
|
49
49
|
<pre class="no-lang-pre"><code>${l.utils.escapeHtml(e)}</code></pre>
|
|
50
50
|
</div>`;
|
|
51
51
|
};
|
|
52
|
-
const
|
|
53
|
-
l.renderer.rules.table_open = (o, r, e, n, t) => '<div class="table-wrapper">' +
|
|
54
|
-
const
|
|
55
|
-
l.renderer.rules.table_close = (o, r, e, n, t) =>
|
|
52
|
+
const V = l.renderer.rules.table_open || ((o, r, e, n, t) => t.renderToken(o, r, e));
|
|
53
|
+
l.renderer.rules.table_open = (o, r, e, n, t) => '<div class="table-wrapper">' + V(o, r, e, n, t);
|
|
54
|
+
const A = l.renderer.rules.table_close || ((o, r, e, n, t) => t.renderToken(o, r, e));
|
|
55
|
+
l.renderer.rules.table_close = (o, r, e, n, t) => A(o, r, e, n, t) + "</div>";
|
|
56
56
|
const C = async () => {
|
|
57
57
|
f.value = !0, h.value = null;
|
|
58
58
|
try {
|
|
59
|
-
const o = await
|
|
59
|
+
const o = await Y(x.url, { fetcher: j.value });
|
|
60
60
|
y.value = o, u.value = l.render(o), f.value = !1;
|
|
61
61
|
try {
|
|
62
62
|
v.value = await E(o, { lang: "markdown", theme: g.value });
|
|
@@ -76,11 +76,11 @@ const Y = {
|
|
|
76
76
|
const t = document.createElement("textarea");
|
|
77
77
|
t.value = o, document.body.appendChild(t), t.select(), document.execCommand("copy"), document.body.removeChild(t);
|
|
78
78
|
}
|
|
79
|
-
e.innerHTML = r ?
|
|
79
|
+
e.innerHTML = r ? re : ne, e.title = p.value("markdown.copied"), setTimeout(() => {
|
|
80
80
|
e.innerHTML = r ? L : B, e.title = p.value("markdown.copy_code");
|
|
81
81
|
}, 2e3);
|
|
82
82
|
}), e;
|
|
83
|
-
},
|
|
83
|
+
}, $ = async () => {
|
|
84
84
|
var e, n;
|
|
85
85
|
if (!m.value) return;
|
|
86
86
|
const o = m.value.querySelectorAll('pre[data-shiki-pending="1"]');
|
|
@@ -103,34 +103,34 @@ const Y = {
|
|
|
103
103
|
}
|
|
104
104
|
};
|
|
105
105
|
return _(() => x.url, C, { immediate: !0 }), _(u, async () => {
|
|
106
|
-
u.value && (await
|
|
106
|
+
u.value && (await P(), $());
|
|
107
107
|
}), _(g, () => {
|
|
108
108
|
y.value && C();
|
|
109
|
-
}), (o, r) => f.value ? (a(), d("div",
|
|
109
|
+
}), (o, r) => f.value ? (a(), d("div", W, [...r[0] || (r[0] = [
|
|
110
110
|
i("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)
|
|
111
|
-
])])) : h.value ? (a(), d("div",
|
|
112
|
-
i("div",
|
|
113
|
-
i("p",
|
|
111
|
+
])])) : h.value ? (a(), d("div", z, [
|
|
112
|
+
i("div", J, [
|
|
113
|
+
i("p", Q, H(h.value), 1)
|
|
114
114
|
])
|
|
115
|
-
])) : b.viewMode === "source" ? (a(), d("div",
|
|
115
|
+
])) : b.viewMode === "source" ? (a(), d("div", U, [
|
|
116
116
|
v.value ? (a(), d("div", {
|
|
117
117
|
key: 1,
|
|
118
118
|
class: "shiki-wrapper",
|
|
119
119
|
innerHTML: v.value
|
|
120
|
-
}, null, 8,
|
|
121
|
-
])) : (a(), d("div",
|
|
122
|
-
i("div",
|
|
120
|
+
}, null, 8, Z)) : (a(), d("pre", X, H(y.value), 1))
|
|
121
|
+
])) : (a(), d("div", ee, [
|
|
122
|
+
i("div", te, [
|
|
123
123
|
i("div", {
|
|
124
124
|
ref_key: "containerRef",
|
|
125
125
|
ref: m,
|
|
126
126
|
class: "markdown-body",
|
|
127
127
|
innerHTML: u.value
|
|
128
|
-
}, null, 8,
|
|
128
|
+
}, null, 8, oe)
|
|
129
129
|
])
|
|
130
130
|
]));
|
|
131
131
|
}
|
|
132
|
-
}),
|
|
132
|
+
}), ue = /* @__PURE__ */ F(le, [["__scopeId", "data-v-addd6fb8"]]);
|
|
133
133
|
export {
|
|
134
|
-
|
|
134
|
+
ue as default
|
|
135
135
|
};
|
|
136
|
-
//# sourceMappingURL=index-
|
|
136
|
+
//# sourceMappingURL=index-BVdw1Cc8.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-BVdw1Cc8.mjs","sources":["../../src/renderers/Markdown/index.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, watch, nextTick } from 'vue';\nimport MarkdownIt from 'markdown-it';\nimport MarkdownItKatex from '@traptitech/markdown-it-katex';\nimport { codeToHtml } from 'shiki';\nimport { fetchTextUtf8 } from '@eternalheart/file-preview-core';\nimport { useTranslator } from '../../composables/useTranslator';\nimport { useFetcher } from '../../composables/useRequest';\nimport { useResolvedTheme } from '../../composables/useResolvedTheme';\nimport 'katex/dist/katex.min.css';\n\nconst props = defineProps<{\n url: string;\n viewMode?: 'preview' | 'source';\n}>();\n\nconst { t } = useTranslator();\nconst fetcher = useFetcher();\nconst resolvedTheme = useResolvedTheme();\nconst shikiTheme = computed(() => (resolvedTheme.value === 'light' ? 'github-light' : 'github-dark'));\n\nconst content = ref('');\nconst html = ref('');\nconst highlightedSource = ref('');\nconst loading = ref(true);\nconst error = ref<string | null>(null);\nconst containerRef = ref<HTMLDivElement | null>(null);\n\n// 创建 markdown-it 实例(支持 GFM 表格、删除线、任务列表、HTML、数学公式)\nconst md = new MarkdownIt({\n html: true,\n linkify: true,\n typographer: false,\n breaks: false,\n});\nmd.use(MarkdownItKatex);\n\n// 自定义代码块渲染:包裹 code-block-wrapper + header(不含复制按钮,由 JS 动态注入)\nmd.renderer.rules.fence = (tokens, idx) => {\n const token = tokens[idx];\n const info = token.info ? token.info.trim() : '';\n const code = token.content;\n\n if (!info) {\n return `<div class=\"code-block-wrapper\">\n <pre class=\"no-lang-pre\"><code>${md.utils.escapeHtml(code)}</code></pre>\n </div>`;\n }\n\n return `<div class=\"code-block-wrapper\">\n <div class=\"code-block-header\">\n <span>${info}</span>\n </div>\n <pre data-shiki-pending=\"1\" data-lang=\"${info}\"><code>${md.utils.escapeHtml(code)}</code></pre>\n </div>`;\n};\n\n// 4-space 缩进代码块:同样包裹 code-block-wrapper(无头,注入浮动复制按钮)\nmd.renderer.rules.code_block = (tokens, idx) => {\n const code = tokens[idx].content;\n return `<div class=\"code-block-wrapper\">\n <pre class=\"no-lang-pre\"><code>${md.utils.escapeHtml(code)}</code></pre>\n </div>`;\n};\n\n// 表格添加包裹层(用于横向滚动)\nconst defaultTableOpen =\n md.renderer.rules.table_open ||\n ((tokens, idx, options, _env, self) => self.renderToken(tokens, idx, options));\nmd.renderer.rules.table_open = (tokens, idx, options, env, self) => {\n return '<div class=\"table-wrapper\">' + defaultTableOpen(tokens, idx, options, env, self);\n};\nconst defaultTableClose =\n md.renderer.rules.table_close ||\n ((tokens, idx, options, _env, self) => self.renderToken(tokens, idx, options));\nmd.renderer.rules.table_close = (tokens, idx, options, env, self) => {\n return defaultTableClose(tokens, idx, options, env, self) + '</div>';\n};\n\nconst loadMarkdown = 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 html.value = md.render(text);\n loading.value = false;\n // 异步生成源码高亮(不阻塞预览渲染)\n try {\n highlightedSource.value = await codeToHtml(text, { lang: 'markdown', theme: shikiTheme.value });\n } catch {\n highlightedSource.value = '';\n }\n } catch (err) {\n console.error(err);\n error.value = t.value('markdown.load_failed');\n loading.value = false;\n }\n};\n\nconst COPY_SVG_SM = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg>`;\nconst COPY_SVG_MD = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg>`;\nconst CHECK_SVG_SM = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M20 6 9 17l-5-5\"/></svg>`;\nconst CHECK_SVG_MD = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M20 6 9 17l-5-5\"/></svg>`;\n\nconst createCopyButton = (code: string, inline: boolean): HTMLButtonElement => {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = inline ? 'code-copy-btn' : 'code-copy-btn code-copy-float';\n btn.title = t.value('markdown.copy_code');\n btn.innerHTML = inline ? COPY_SVG_SM : COPY_SVG_MD;\n btn.addEventListener('click', async (e) => {\n e.stopPropagation();\n try {\n await navigator.clipboard.writeText(code);\n } catch {\n const ta = document.createElement('textarea');\n ta.value = code;\n document.body.appendChild(ta);\n ta.select();\n document.execCommand('copy');\n document.body.removeChild(ta);\n }\n btn.innerHTML = inline ? CHECK_SVG_SM : CHECK_SVG_MD;\n btn.title = t.value('markdown.copied');\n setTimeout(() => {\n btn.innerHTML = inline ? COPY_SVG_SM : COPY_SVG_MD;\n btn.title = t.value('markdown.copy_code');\n }, 2000);\n });\n return btn;\n};\n\nconst highlightAndInjectCopyButtons = async () => {\n if (!containerRef.value) return;\n\n // 1. shiki 高亮有语言的代码块\n const pending = containerRef.value.querySelectorAll<HTMLPreElement>('pre[data-shiki-pending=\"1\"]');\n for (const pre of pending) {\n const lang = pre.getAttribute('data-lang') || 'text';\n const code = pre.querySelector('code')?.textContent || '';\n try {\n const highlighted = await codeToHtml(code, { lang, theme: shikiTheme.value });\n const tmp = document.createElement('div');\n tmp.innerHTML = highlighted;\n const newPre = tmp.firstElementChild as HTMLElement;\n if (newPre) pre.replaceWith(newPre);\n } catch {\n pre.style.backgroundColor = 'var(--fp-code-bg)';\n pre.removeAttribute('data-shiki-pending');\n }\n }\n\n // 2. 为所有代码块注入复制按钮(避免重复注入)\n const wrappers = containerRef.value.querySelectorAll<HTMLElement>('.code-block-wrapper');\n for (const wrapper of wrappers) {\n if (wrapper.querySelector('.code-copy-btn')) continue;\n const header = wrapper.querySelector('.code-block-header');\n const pre = wrapper.querySelector('pre');\n const code = pre?.querySelector('code')?.textContent ?? pre?.textContent ?? '';\n if (header) {\n // 有语言:按钮放入 header 右侧\n header.appendChild(createCopyButton(code, true));\n } else {\n // 无语言:浮动按钮\n wrapper.appendChild(createCopyButton(code, false));\n }\n }\n};\n\nwatch(() => props.url, loadMarkdown, { immediate: true });\n\nwatch(html, async () => {\n if (!html.value) return;\n await nextTick();\n highlightAndInjectCopyButtons();\n});\n\n// 主题切换时重新加载(让 shiki 用新主题重新高亮)\nwatch(shikiTheme, () => {\n if (content.value) loadMarkdown();\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 <div v-else-if=\"error\" class=\"vfp-flex vfp-items-center vfp-justify-center vfp-w-full vfp-h-full\">\n <div class=\"vfp-text-fg-secondary vfp-text-center\">\n <p class=\"vfp-text-lg\">{{ error }}</p>\n </div>\n </div>\n\n <!-- 源码视图 -->\n <div v-else-if=\"viewMode === 'source'\" class=\"vfp-w-full vfp-h-full vfp-overflow-auto\" style=\"background: var(--fp-code-bg);\">\n <pre\n v-if=\"!highlightedSource\"\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=\"highlightedSource\" />\n </div>\n\n <!-- 预览视图 -->\n <div v-else class=\"vfp-w-full vfp-h-full vfp-overflow-auto vfp-p-6 md:vfp-p-10\">\n <div class=\"vfp-max-w-full md:vfp-max-w-4xl vfp-mx-auto\">\n <div ref=\"containerRef\" class=\"markdown-body\" v-html=\"html\" />\n </div>\n </div>\n</template>\n\n<style scoped>\n.markdown-body :deep(.table-wrapper) {\n overflow-x: auto;\n margin: 1rem 0;\n border-radius: 0.375rem;\n border: 1px solid var(--fp-surface-3);\n}\n.markdown-body :deep(.table-wrapper > table) {\n margin: 0;\n border: 0;\n border-radius: 0;\n}\n/* shiki 生成的 pre:修正在 code-block-wrapper 内的边距与圆角 */\n.markdown-body :deep(.code-block-wrapper pre.shiki) {\n margin: 0;\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n border-top: 0;\n}\n/* 无语言代码块:pre 不裁剪,让浮动按钮可见 */\n.markdown-body :deep(.code-block-wrapper) {\n overflow: visible;\n}\n.markdown-body :deep(.code-block-wrapper pre) {\n overflow: visible;\n}\n/* 无语言代码块纯文本样式 */\n.markdown-body :deep(.no-lang-pre) {\n margin: 0;\n padding: 1rem;\n background: var(--fp-code-bg);\n border-radius: 0.375rem;\n border: 1px solid var(--fp-line);\n}\n.markdown-body :deep(.no-lang-pre code) {\n display: block;\n font-size: 0.8125rem;\n line-height: 1.5;\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n color: var(--fp-fg-primary);\n white-space: pre;\n overflow-x: auto;\n}\n/* shiki 生成的 code:补充 padding,使代码有适当内边距 */\n.markdown-body :deep(pre.shiki code) {\n display: block;\n padding: 1rem;\n font-size: 0.8125rem;\n line-height: 1.5;\n overflow-x: auto;\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n}\n/* KaTeX 公式颜色适配暗色背景 */\n.markdown-body :deep(.katex) {\n color: var(--fp-fg-primary);\n}\n.markdown-body :deep(.katex-display) {\n margin: 1.25rem 0;\n overflow-x: auto;\n overflow-y: hidden;\n}\n/* 源码视图 shiki */\n.shiki-wrapper :deep(pre) {\n margin: 0;\n padding: 1.5rem;\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}\n</style>\n"],"names":["COPY_SVG_SM","COPY_SVG_MD","CHECK_SVG_SM","CHECK_SVG_MD","props","__props","t","useTranslator","fetcher","useFetcher","resolvedTheme","useResolvedTheme","shikiTheme","computed","content","ref","html","highlightedSource","loading","error","containerRef","md","MarkdownIt","MarkdownItKatex","tokens","idx","token","info","code","defaultTableOpen","options","_env","self","env","defaultTableClose","loadMarkdown","text","fetchTextUtf8","codeToHtml","err","createCopyButton","inline","btn","e","ta","highlightAndInjectCopyButtons","pending","pre","lang","_a","highlighted","tmp","newPre","wrappers","wrapper","header","_b","watch","nextTick","_openBlock","_createElementBlock","_hoisted_1","_cache","_createElementVNode","_hoisted_2","_hoisted_3","_hoisted_4","_toDisplayString","_hoisted_5","_hoisted_6","_hoisted_8","_hoisted_9"],"mappings":";;;;;;;;;;;;;;;;;;;;;;sFAoGMA,IAAc,0TACdC,IAAc,0TACdC,KAAe,0NACfC,KAAe;;;;;;;AA5FrB,UAAMC,IAAQC,GAKR,EAAE,GAAAC,EAAA,IAAMC,EAAA,GACRC,IAAUC,EAAA,GACVC,IAAgBC,EAAA,GAChBC,IAAaC,EAAS,MAAOH,EAAc,UAAU,UAAU,iBAAiB,aAAc,GAE9FI,IAAUC,EAAI,EAAE,GAChBC,IAAOD,EAAI,EAAE,GACbE,IAAoBF,EAAI,EAAE,GAC1BG,IAAUH,EAAI,EAAI,GAClBI,IAAQJ,EAAmB,IAAI,GAC/BK,IAAeL,EAA2B,IAAI,GAG9CM,IAAK,IAAIC,EAAW;AAAA,MACxB,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa;AAAA,MACb,QAAQ;AAAA,IAAA,CACT;AACD,IAAAD,EAAG,IAAIE,CAAe,GAGtBF,EAAG,SAAS,MAAM,QAAQ,CAACG,GAAQC,MAAQ;AACzC,YAAMC,IAAQF,EAAOC,CAAG,GAClBE,IAAOD,EAAM,OAAOA,EAAM,KAAK,SAAS,IACxCE,IAAOF,EAAM;AAEnB,aAAKC,IAME;AAAA;AAAA,cAEKA,CAAI;AAAA;AAAA,6CAE2BA,CAAI,WAAWN,EAAG,MAAM,WAAWO,CAAI,CAAC;AAAA,YAT1E;AAAA,qCAC0BP,EAAG,MAAM,WAAWO,CAAI,CAAC;AAAA;AAAA,IAU9D,GAGAP,EAAG,SAAS,MAAM,aAAa,CAACG,GAAQC,MAAQ;AAC9C,YAAMG,IAAOJ,EAAOC,CAAG,EAAE;AACzB,aAAO;AAAA,qCAC4BJ,EAAG,MAAM,WAAWO,CAAI,CAAC;AAAA;AAAA,IAE9D;AAGA,UAAMC,IACJR,EAAG,SAAS,MAAM,eACjB,CAACG,GAAQC,GAAKK,GAASC,GAAMC,MAASA,EAAK,YAAYR,GAAQC,GAAKK,CAAO;AAC9E,IAAAT,EAAG,SAAS,MAAM,aAAa,CAACG,GAAQC,GAAKK,GAASG,GAAKD,MAClD,gCAAgCH,EAAiBL,GAAQC,GAAKK,GAASG,GAAKD,CAAI;AAEzF,UAAME,IACJb,EAAG,SAAS,MAAM,gBACjB,CAACG,GAAQC,GAAKK,GAASC,GAAMC,MAASA,EAAK,YAAYR,GAAQC,GAAKK,CAAO;AAC9E,IAAAT,EAAG,SAAS,MAAM,cAAc,CAACG,GAAQC,GAAKK,GAASG,GAAKD,MACnDE,EAAkBV,GAAQC,GAAKK,GAASG,GAAKD,CAAI,IAAI;AAG9D,UAAMG,IAAe,YAAY;AAC/B,MAAAjB,EAAQ,QAAQ,IAChBC,EAAM,QAAQ;AACd,UAAI;AACF,cAAMiB,IAAO,MAAMC,EAAcjC,EAAM,KAAK,EAAE,SAASI,EAAQ,OAAO;AACtE,QAAAM,EAAQ,QAAQsB,GAChBpB,EAAK,QAAQK,EAAG,OAAOe,CAAI,GAC3BlB,EAAQ,QAAQ;AAEhB,YAAI;AACF,UAAAD,EAAkB,QAAQ,MAAMqB,EAAWF,GAAM,EAAE,MAAM,YAAY,OAAOxB,EAAW,OAAO;AAAA,QAChG,QAAQ;AACN,UAAAK,EAAkB,QAAQ;AAAA,QAC5B;AAAA,MACF,SAASsB,GAAK;AACZ,gBAAQ,MAAMA,CAAG,GACjBpB,EAAM,QAAQb,EAAE,MAAM,sBAAsB,GAC5CY,EAAQ,QAAQ;AAAA,MAClB;AAAA,IACF,GAOMsB,IAAmB,CAACZ,GAAca,MAAuC;AAC7E,YAAMC,IAAM,SAAS,cAAc,QAAQ;AAC3C,aAAAA,EAAI,OAAO,UACXA,EAAI,YAAYD,IAAS,kBAAkB,iCAC3CC,EAAI,QAAQpC,EAAE,MAAM,oBAAoB,GACxCoC,EAAI,YAAYD,IAASzC,IAAcC,GACvCyC,EAAI,iBAAiB,SAAS,OAAOC,MAAM;AACzC,QAAAA,EAAE,gBAAA;AACF,YAAI;AACF,gBAAM,UAAU,UAAU,UAAUf,CAAI;AAAA,QAC1C,QAAQ;AACN,gBAAMgB,IAAK,SAAS,cAAc,UAAU;AAC5C,UAAAA,EAAG,QAAQhB,GACX,SAAS,KAAK,YAAYgB,CAAE,GAC5BA,EAAG,OAAA,GACH,SAAS,YAAY,MAAM,GAC3B,SAAS,KAAK,YAAYA,CAAE;AAAA,QAC9B;AACA,QAAAF,EAAI,YAAYD,IAASvC,KAAeC,IACxCuC,EAAI,QAAQpC,EAAE,MAAM,iBAAiB,GACrC,WAAW,MAAM;AACf,UAAAoC,EAAI,YAAYD,IAASzC,IAAcC,GACvCyC,EAAI,QAAQpC,EAAE,MAAM,oBAAoB;AAAA,QAC1C,GAAG,GAAI;AAAA,MACT,CAAC,GACMoC;AAAA,IACT,GAEMG,IAAgC,YAAY;;AAChD,UAAI,CAACzB,EAAa,MAAO;AAGzB,YAAM0B,IAAU1B,EAAa,MAAM,iBAAiC,6BAA6B;AACjG,iBAAW2B,KAAOD,GAAS;AACzB,cAAME,IAAOD,EAAI,aAAa,WAAW,KAAK,QACxCnB,MAAOqB,IAAAF,EAAI,cAAc,MAAM,MAAxB,gBAAAE,EAA2B,gBAAe;AACvD,YAAI;AACF,gBAAMC,IAAc,MAAMZ,EAAWV,GAAM,EAAE,MAAAoB,GAAM,OAAOpC,EAAW,OAAO,GACtEuC,IAAM,SAAS,cAAc,KAAK;AACxC,UAAAA,EAAI,YAAYD;AAChB,gBAAME,IAASD,EAAI;AACnB,UAAIC,KAAQL,EAAI,YAAYK,CAAM;AAAA,QACpC,QAAQ;AACN,UAAAL,EAAI,MAAM,kBAAkB,qBAC5BA,EAAI,gBAAgB,oBAAoB;AAAA,QAC1C;AAAA,MACF;AAGA,YAAMM,IAAWjC,EAAa,MAAM,iBAA8B,qBAAqB;AACvF,iBAAWkC,KAAWD,GAAU;AAC9B,YAAIC,EAAQ,cAAc,gBAAgB,EAAG;AAC7C,cAAMC,IAASD,EAAQ,cAAc,oBAAoB,GACnDP,IAAMO,EAAQ,cAAc,KAAK,GACjC1B,MAAO4B,IAAAT,KAAA,gBAAAA,EAAK,cAAc,YAAnB,gBAAAS,EAA4B,iBAAeT,KAAA,gBAAAA,EAAK,gBAAe;AAC5E,QAAIQ,IAEFA,EAAO,YAAYf,EAAiBZ,GAAM,EAAI,CAAC,IAG/C0B,EAAQ,YAAYd,EAAiBZ,GAAM,EAAK,CAAC;AAAA,MAErD;AAAA,IACF;AAEA,WAAA6B,EAAM,MAAMrD,EAAM,KAAK+B,GAAc,EAAE,WAAW,IAAM,GAExDsB,EAAMzC,GAAM,YAAY;AACtB,MAAKA,EAAK,UACV,MAAM0C,EAAA,GACNb,EAAA;AAAA,IACF,CAAC,GAGDY,EAAM7C,GAAY,MAAM;AACtB,MAAIE,EAAQ,SAAOqB,EAAA;AAAA,IACrB,CAAC,aAIYjB,EAAA,SAAXyC,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,QAI7G5C,EAAA,SAAhBwC,EAAA,GAAAC,EAIM,OAJNI,GAIM;AAAA,MAHJD,EAEM,OAFNE,GAEM;AAAA,QADJF,EAAsC,KAAtCG,GAAsCC,EAAZhD,EAAA,KAAK,GAAA,CAAA;AAAA,MAAA;UAKnBd,EAAA,aAAQ,YAAxBsD,EAAA,GAAAC,EAOM,OAPNQ,GAOM;AAAA,MALKnD,EAAA,cAIT2C,EAA+D,OAAA;AAAA;QAAnD,OAAM;AAAA,QAAgB,WAAQ3C,EAAA;AAAA,MAAA,wBAL1C2C,EAIC,OAJDS,GAICF,EADKrD,EAAA,KAAO,GAAA,CAAA;AAAA,WAMf6C,EAAA,GAAAC,EAIM,OAJNU,IAIM;AAAA,MAHJP,EAEM,OAFNQ,IAEM;AAAA,QADJR,EAA8D,OAAA;AAAA,mBAArD;AAAA,UAAJ,KAAI3C;AAAA,UAAe,OAAM;AAAA,UAAgB,WAAQJ,EAAA;AAAA,QAAA;;;;;"}
|
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
import { defineComponent as
|
|
2
|
-
import { u as
|
|
3
|
-
import { codeToHtml as
|
|
4
|
-
const
|
|
1
|
+
import { defineComponent as M, ref as p, watch as g, openBlock as s, createElementBlock as a, createElementVNode as v, toDisplayString as y } from "vue";
|
|
2
|
+
import { u as S, a as $, b as D, c as j, _ as H } from "./index-BA-bP8P6.mjs";
|
|
3
|
+
import { codeToHtml as L } from "shiki";
|
|
4
|
+
const N = {
|
|
5
5
|
key: 0,
|
|
6
6
|
class: "vfp-flex vfp-items-center vfp-justify-center vfp-w-full vfp-h-full"
|
|
7
|
-
},
|
|
7
|
+
}, P = {
|
|
8
8
|
key: 1,
|
|
9
9
|
class: "vfp-flex vfp-items-center vfp-justify-center vfp-w-full vfp-h-full"
|
|
10
|
-
},
|
|
10
|
+
}, X = { class: "vfp-text-fg-secondary vfp-text-center" }, B = { class: "vfp-text-lg" }, E = {
|
|
11
11
|
key: 2,
|
|
12
12
|
class: "vfp-w-full vfp-h-full vfp-overflow-auto",
|
|
13
13
|
style: { background: "var(--fp-code-bg)" }
|
|
14
|
-
},
|
|
14
|
+
}, F = {
|
|
15
15
|
key: 0,
|
|
16
16
|
class: "vfp-p-6 vfp-text-fg-primary vfp-font-mono vfp-text-sm vfp-whitespace-pre-wrap vfp-break-words"
|
|
17
|
-
},
|
|
17
|
+
}, I = ["innerHTML"], q = /* @__PURE__ */ M({
|
|
18
18
|
__name: "index",
|
|
19
19
|
props: {
|
|
20
20
|
url: {},
|
|
21
21
|
fileName: {}
|
|
22
22
|
},
|
|
23
23
|
setup(w) {
|
|
24
|
-
const u = w, { t: x } =
|
|
25
|
-
const r = " ",
|
|
24
|
+
const u = w, { t: x } = S(), b = $(), d = D(), l = p(""), n = p(""), f = p(!0), o = p(null), k = (e) => {
|
|
25
|
+
const r = " ", c = /(>)(<)(\/*)/g, h = e.replace(c, `$1
|
|
26
26
|
$2$3`);
|
|
27
27
|
let t = 0;
|
|
28
28
|
return h.split(`
|
|
29
|
-
`).map((
|
|
29
|
+
`).map((i) => {
|
|
30
30
|
let _ = 0;
|
|
31
|
-
/^<\/\w/.test(
|
|
32
|
-
const
|
|
33
|
-
return t += _,
|
|
31
|
+
/^<\/\w/.test(i) ? t = Math.max(t - 1, 0) : /^<\w[^>]*[^/]>.*$/.test(i) && !/<.+<\/.+>$/.test(i) && (_ = 1);
|
|
32
|
+
const z = r.repeat(t) + i;
|
|
33
|
+
return t += _, z;
|
|
34
34
|
}).join(`
|
|
35
35
|
`);
|
|
36
|
-
},
|
|
36
|
+
}, T = (e) => {
|
|
37
37
|
try {
|
|
38
|
-
const
|
|
39
|
-
if (
|
|
40
|
-
const t = new XMLSerializer().serializeToString(
|
|
38
|
+
const c = new DOMParser().parseFromString(e, "application/xml");
|
|
39
|
+
if (c.querySelector("parsererror")) return e;
|
|
40
|
+
const t = new XMLSerializer().serializeToString(c);
|
|
41
41
|
return k(t);
|
|
42
42
|
} catch {
|
|
43
43
|
return e;
|
|
@@ -45,10 +45,10 @@ $2$3`);
|
|
|
45
45
|
}, m = async () => {
|
|
46
46
|
f.value = !0, o.value = null;
|
|
47
47
|
try {
|
|
48
|
-
const e = await
|
|
49
|
-
l.value =
|
|
48
|
+
const e = await j(u.url, { fetcher: b.value });
|
|
49
|
+
l.value = T(e);
|
|
50
50
|
try {
|
|
51
|
-
n.value = await
|
|
51
|
+
n.value = await L(l.value, {
|
|
52
52
|
lang: "xml",
|
|
53
53
|
theme: d.value === "light" ? "github-light" : "dark-plus"
|
|
54
54
|
});
|
|
@@ -63,22 +63,22 @@ $2$3`);
|
|
|
63
63
|
};
|
|
64
64
|
return g(() => u.url, m, { immediate: !0 }), g(d, () => {
|
|
65
65
|
l.value && m();
|
|
66
|
-
}), (e, r) => f.value ? (s(), a("div",
|
|
66
|
+
}), (e, r) => f.value ? (s(), a("div", N, [...r[0] || (r[0] = [
|
|
67
67
|
v("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)
|
|
68
|
-
])])) : o.value ? (s(), a("div",
|
|
69
|
-
v("div",
|
|
70
|
-
v("p",
|
|
68
|
+
])])) : o.value ? (s(), a("div", P, [
|
|
69
|
+
v("div", X, [
|
|
70
|
+
v("p", B, y(o.value), 1)
|
|
71
71
|
])
|
|
72
|
-
])) : (s(), a("div",
|
|
72
|
+
])) : (s(), a("div", E, [
|
|
73
73
|
n.value ? (s(), a("div", {
|
|
74
74
|
key: 1,
|
|
75
75
|
class: "shiki-wrapper",
|
|
76
76
|
innerHTML: n.value
|
|
77
|
-
}, null, 8,
|
|
77
|
+
}, null, 8, I)) : (s(), a("pre", F, y(l.value), 1))
|
|
78
78
|
]));
|
|
79
79
|
}
|
|
80
|
-
}),
|
|
80
|
+
}), O = /* @__PURE__ */ H(q, [["__scopeId", "data-v-0b9adbcc"]]);
|
|
81
81
|
export {
|
|
82
|
-
|
|
82
|
+
O as default
|
|
83
83
|
};
|
|
84
|
-
//# sourceMappingURL=index-
|
|
84
|
+
//# sourceMappingURL=index-BqSPk90T.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-BqSPk90T.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';\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 <div v-else-if=\"error\" class=\"vfp-flex vfp-items-center vfp-justify-center vfp-w-full vfp-h-full\">\n <div class=\"vfp-text-fg-secondary vfp-text-center\">\n <p class=\"vfp-text-lg\">{{ error }}</p>\n </div>\n </div>\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;\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}\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","_hoisted_2","_hoisted_3","_hoisted_4","_toDisplayString","_hoisted_5","_hoisted_6"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAQA,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,QAI7GvB,EAAA,SAAhBmB,EAAA,GAAAC,EAIM,OAJNI,GAIM;AAAA,MAHJD,EAEM,OAFNE,GAEM;AAAA,QADJF,EAAsC,KAAtCG,GAAsCC,EAAZ3B,EAAA,KAAK,GAAA,CAAA;AAAA,MAAA;WAInCmB,EAAA,GAAAC,EAOM,OAPNQ,GAOM;AAAA,MALK9B,EAAA,cAITsB,EAAyD,OAAA;AAAA;QAA7C,OAAM;AAAA,QAAgB,WAAQtB,EAAA;AAAA,MAAA,wBAL1CsB,EAIC,OAJDS,GAICF,EADK/B,EAAA,KAAO,GAAA,CAAA;AAAA;;;"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { defineComponent as j, ref as y, watch as S, computed as h, openBlock as a, createElementBlock as r, createElementVNode as e, toDisplayString as o, unref as c, normalizeClass as b, Fragment as x, renderList as k, createCommentVNode as C } from "vue";
|
|
2
|
+
import { u as V, a as z, e as A, y as d, c as D, _ as I } from "./index-BA-bP8P6.mjs";
|
|
3
|
+
const M = {
|
|
4
|
+
key: 0,
|
|
5
|
+
class: "vfp-flex vfp-items-center vfp-justify-center vfp-w-full vfp-h-full vfp-bg-[#0f0f12]"
|
|
6
|
+
}, O = {
|
|
7
|
+
key: 1,
|
|
8
|
+
class: "vfp-flex vfp-items-center vfp-justify-center vfp-w-full vfp-h-full vfp-bg-[#0f0f12]"
|
|
9
|
+
}, R = { class: "vfp-text-fg-secondary vfp-text-center" }, X = { class: "vfp-text-lg" }, Y = { class: "content-scroll" }, q = { class: "timeline" }, G = { class: "cues" }, H = { class: "cue-meta" }, J = { class: "cue-time" }, K = { class: "cue-time" }, P = { class: "cue-id" }, Q = {
|
|
10
|
+
key: 0,
|
|
11
|
+
class: "cue-style"
|
|
12
|
+
}, U = {
|
|
13
|
+
key: 0,
|
|
14
|
+
class: "cue-words"
|
|
15
|
+
}, W = ["title"], Z = { class: "cue-word-time" }, $ = { class: "cue-word-text" }, ee = { class: "status-pill" }, te = /* @__PURE__ */ j({
|
|
16
|
+
__name: "index",
|
|
17
|
+
props: {
|
|
18
|
+
url: {},
|
|
19
|
+
fileName: {}
|
|
20
|
+
},
|
|
21
|
+
setup(F) {
|
|
22
|
+
const v = F, { t: u } = V(), N = z(), f = y(""), p = y(!0), i = y(null), T = {
|
|
23
|
+
srt: "srt",
|
|
24
|
+
vtt: "vtt",
|
|
25
|
+
lrc: "lrc",
|
|
26
|
+
elrc: "elrc",
|
|
27
|
+
ass: "ass",
|
|
28
|
+
ssa: "ssa",
|
|
29
|
+
ttml: "ttml",
|
|
30
|
+
dfxp: "ttml"
|
|
31
|
+
}, B = (s) => {
|
|
32
|
+
var l;
|
|
33
|
+
const t = ((l = s.split(".").pop()) == null ? void 0 : l.toLowerCase()) || "";
|
|
34
|
+
return T[t];
|
|
35
|
+
};
|
|
36
|
+
S(() => v.url, async () => {
|
|
37
|
+
p.value = !0, i.value = null;
|
|
38
|
+
try {
|
|
39
|
+
f.value = await D(v.url, { fetcher: N.value });
|
|
40
|
+
} catch (s) {
|
|
41
|
+
console.error(s), i.value = u.value("subtitle.load_failed");
|
|
42
|
+
} finally {
|
|
43
|
+
p.value = !1;
|
|
44
|
+
}
|
|
45
|
+
}, { immediate: !0 });
|
|
46
|
+
const n = h(() => {
|
|
47
|
+
if (!f.value) return null;
|
|
48
|
+
try {
|
|
49
|
+
return A(f.value, B(v.fileName));
|
|
50
|
+
} catch (s) {
|
|
51
|
+
return console.error(s), null;
|
|
52
|
+
}
|
|
53
|
+
}), _ = h(() => {
|
|
54
|
+
var s, t;
|
|
55
|
+
return ((s = n.value) == null ? void 0 : s.format) === "lrc" || ((t = n.value) == null ? void 0 : t.format) === "elrc";
|
|
56
|
+
}), w = h(() => {
|
|
57
|
+
var s;
|
|
58
|
+
return ((s = n.value) == null ? void 0 : s.metadata) ?? {};
|
|
59
|
+
}), E = (s) => d(s).slice(3, 8);
|
|
60
|
+
return (s, t) => p.value ? (a(), r("div", M, [...t[0] || (t[0] = [
|
|
61
|
+
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)
|
|
62
|
+
])])) : i.value || !n.value ? (a(), r("div", O, [
|
|
63
|
+
e("div", R, [
|
|
64
|
+
e("p", X, o(i.value || c(u)("subtitle.parse_failed")), 1)
|
|
65
|
+
])
|
|
66
|
+
])) : (a(), r("div", {
|
|
67
|
+
key: 2,
|
|
68
|
+
class: b(["vfp-relative vfp-w-full vfp-h-full vfp-bg-[#0f0f12]", _.value ? "flavor-lyric" : "flavor-subtitle"])
|
|
69
|
+
}, [
|
|
70
|
+
e("div", Y, [
|
|
71
|
+
e("div", q, [
|
|
72
|
+
t[3] || (t[3] = e("div", { class: "timeline-line" }, null, -1)),
|
|
73
|
+
e("ol", G, [
|
|
74
|
+
(a(!0), r(x, null, k(n.value.cues, (l, g) => (a(), r("li", {
|
|
75
|
+
key: "cue-" + g,
|
|
76
|
+
class: "cue-row"
|
|
77
|
+
}, [
|
|
78
|
+
t[2] || (t[2] = e("div", { class: "cue-dot" }, null, -1)),
|
|
79
|
+
e("div", H, [
|
|
80
|
+
e("span", J, o(c(d)(l.start)), 1),
|
|
81
|
+
t[1] || (t[1] = e("span", { class: "cue-arrow" }, "→", -1)),
|
|
82
|
+
e("span", K, o(c(d)(l.end)), 1),
|
|
83
|
+
e("span", P, "#" + o(l.id ?? g + 1), 1),
|
|
84
|
+
l.style ? (a(), r("span", Q, o(l.style), 1)) : C("", !0)
|
|
85
|
+
]),
|
|
86
|
+
l.words && l.words.length > 0 ? (a(), r("div", U, [
|
|
87
|
+
(a(!0), r(x, null, k(l.words, (m, L) => (a(), r("span", {
|
|
88
|
+
key: "w-" + L,
|
|
89
|
+
class: "cue-word",
|
|
90
|
+
title: c(d)(m.start)
|
|
91
|
+
}, [
|
|
92
|
+
e("span", Z, o(E(m.start)), 1),
|
|
93
|
+
e("span", $, o(m.text), 1)
|
|
94
|
+
], 8, W))), 128))
|
|
95
|
+
])) : (a(), r("p", {
|
|
96
|
+
key: 1,
|
|
97
|
+
class: b(["cue-text", { lyric: _.value }])
|
|
98
|
+
}, o(l.text), 3))
|
|
99
|
+
]))), 128))
|
|
100
|
+
])
|
|
101
|
+
])
|
|
102
|
+
]),
|
|
103
|
+
e("div", ee, [
|
|
104
|
+
e("span", null, o(n.value.cues.length) + " " + o(_.value ? c(u)("subtitle.lines") : c(u)("subtitle.cues")), 1),
|
|
105
|
+
w.value.length ? (a(), r(x, { key: 0 }, [
|
|
106
|
+
t[4] || (t[4] = e("span", { class: "dot" }, "·", -1)),
|
|
107
|
+
e("span", null, o(w.value.length), 1)
|
|
108
|
+
], 64)) : C("", !0)
|
|
109
|
+
])
|
|
110
|
+
], 2));
|
|
111
|
+
}
|
|
112
|
+
}), re = /* @__PURE__ */ I(te, [["__scopeId", "data-v-20d6aab5"]]);
|
|
113
|
+
export {
|
|
114
|
+
re as default
|
|
115
|
+
};
|
|
116
|
+
//# sourceMappingURL=index-BrCSk7CK.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-BrCSk7CK.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';\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 <div\n v-else-if=\"error || !parsed\"\n class=\"vfp-flex vfp-items-center vfp-justify-center vfp-w-full vfp-h-full vfp-bg-[#0f0f12]\"\n >\n <div class=\"vfp-text-fg-secondary vfp-text-center\">\n <p class=\"vfp-text-lg\">{{ error || t('subtitle.parse_failed') }}</p>\n </div>\n </div>\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 1.5rem 4rem;\n}\n@media (min-width: 768px) {\n .content-scroll {\n padding: 1.5rem 2.5rem 5rem;\n }\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@media (min-width: 768px) {\n .status-pill {\n bottom: 1rem;\n right: 1rem;\n }\n}\n.dot {\n color: var(--fp-fg-disabled);\n}\n\n.timeline {\n position: relative;\n max-width: 64rem;\n margin: 0 auto;\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@media (min-width: 768px) {\n .timeline-line {\n left: 7px;\n }\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@media (min-width: 768px) {\n .cues {\n gap: 1.5rem;\n }\n}\n.cue-row {\n position: relative;\n padding-left: 1.5rem;\n}\n@media (min-width: 768px) {\n .cue-row {\n padding-left: 2rem;\n }\n}\n.cue-dot {\n position: absolute;\n left: 0;\n top: 0.5rem;\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 transition: color 0.2s;\n}\n@media (min-width: 768px) {\n .cue-text {\n font-size: 1rem;\n }\n}\n.cue-text.lyric {\n font-size: 1rem;\n font-weight: 500;\n}\n@media (min-width: 768px) {\n .cue-text.lyric {\n font-size: 1.25rem;\n }\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@media (min-width: 768px) {\n .cue-words {\n font-size: 1.125rem;\n }\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","_hoisted_2","_hoisted_3","_hoisted_4","_toDisplayString","_unref","_normalizeClass","_hoisted_5","_hoisted_6","_hoisted_7","_Fragment","cue","i","_hoisted_8","_hoisted_9","_hoisted_10","_hoisted_11","_hoisted_12","_hoisted_13","word","wi","_hoisted_15","_hoisted_16","_hoisted_17"],"mappings":"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"}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import { defineComponent as
|
|
2
|
-
import { u as
|
|
3
|
-
import { codeToHtml as
|
|
4
|
-
const
|
|
1
|
+
import { defineComponent as y, ref as n, computed as _, watch as h, openBlock as e, createElementBlock as t, createElementVNode as v, toDisplayString as m, normalizeClass as w } from "vue";
|
|
2
|
+
import { u as b, a as k, b as T, j as B, c as N, _ as j } from "./index-BA-bP8P6.mjs";
|
|
3
|
+
import { codeToHtml as H } from "shiki";
|
|
4
|
+
const W = {
|
|
5
5
|
key: 0,
|
|
6
6
|
class: "vfp-flex vfp-items-center vfp-justify-center vfp-w-full vfp-h-full"
|
|
7
|
-
},
|
|
7
|
+
}, C = {
|
|
8
8
|
key: 1,
|
|
9
9
|
class: "vfp-flex vfp-items-center vfp-justify-center vfp-w-full vfp-h-full"
|
|
10
|
-
},
|
|
10
|
+
}, E = { class: "vfp-text-fg-secondary vfp-text-center" }, L = { class: "vfp-text-lg" }, M = {
|
|
11
11
|
key: 2,
|
|
12
12
|
class: "vfp-w-full vfp-h-full vfp-bg-surface-toolbar"
|
|
13
|
-
},
|
|
13
|
+
}, P = ["srcdoc", "title"], z = {
|
|
14
14
|
key: 3,
|
|
15
15
|
class: "vfp-w-full vfp-h-full vfp-overflow-auto",
|
|
16
16
|
style: { background: "var(--fp-code-bg)" }
|
|
17
|
-
},
|
|
17
|
+
}, D = ["innerHTML"], F = /* @__PURE__ */ y({
|
|
18
18
|
__name: "index",
|
|
19
19
|
props: {
|
|
20
20
|
url: {},
|
|
@@ -23,15 +23,15 @@ const j = {
|
|
|
23
23
|
htmlPreview: { type: Boolean, default: !1 }
|
|
24
24
|
},
|
|
25
25
|
setup(l) {
|
|
26
|
-
const
|
|
27
|
-
|
|
26
|
+
const c = l, { t: g } = b(), x = k(), i = T(), o = n(""), a = n(""), u = n(!0), r = n(null), f = _(() => B(c.fileName)), p = async () => {
|
|
27
|
+
u.value = !0, r.value = null;
|
|
28
28
|
try {
|
|
29
|
-
const s = await
|
|
29
|
+
const s = await N(c.url, { fetcher: x.value });
|
|
30
30
|
if (o.value = s, f.value !== "text")
|
|
31
31
|
try {
|
|
32
|
-
a.value = await
|
|
32
|
+
a.value = await H(s, {
|
|
33
33
|
lang: f.value,
|
|
34
|
-
theme:
|
|
34
|
+
theme: i.value === "light" ? "github-light" : "dark-plus"
|
|
35
35
|
});
|
|
36
36
|
} catch {
|
|
37
37
|
a.value = "";
|
|
@@ -41,37 +41,37 @@ const j = {
|
|
|
41
41
|
} catch (s) {
|
|
42
42
|
console.error(s), r.value = g.value("text.load_failed");
|
|
43
43
|
} finally {
|
|
44
|
-
|
|
44
|
+
u.value = !1;
|
|
45
45
|
}
|
|
46
46
|
};
|
|
47
|
-
return h(() =>
|
|
48
|
-
o.value && f.value !== "text" &&
|
|
49
|
-
}), (s, d) =>
|
|
47
|
+
return h(() => c.url, p, { immediate: !0 }), h(i, () => {
|
|
48
|
+
o.value && f.value !== "text" && p();
|
|
49
|
+
}), (s, d) => u.value ? (e(), t("div", W, [...d[0] || (d[0] = [
|
|
50
50
|
v("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)
|
|
51
|
-
])])) : r.value ? (e(), t("div",
|
|
52
|
-
v("div",
|
|
53
|
-
v("p",
|
|
51
|
+
])])) : r.value ? (e(), t("div", C, [
|
|
52
|
+
v("div", E, [
|
|
53
|
+
v("p", L, m(r.value), 1)
|
|
54
54
|
])
|
|
55
|
-
])) : l.htmlPreview && f.value === "html" ? (e(), t("div",
|
|
55
|
+
])) : l.htmlPreview && f.value === "html" ? (e(), t("div", M, [
|
|
56
56
|
v("iframe", {
|
|
57
57
|
srcdoc: o.value,
|
|
58
58
|
sandbox: "allow-same-origin",
|
|
59
59
|
class: "vfp-w-full vfp-h-full vfp-border-0",
|
|
60
60
|
title: l.fileName
|
|
61
|
-
}, null, 8,
|
|
62
|
-
])) : (e(), t("div",
|
|
61
|
+
}, null, 8, P)
|
|
62
|
+
])) : (e(), t("div", z, [
|
|
63
63
|
a.value ? (e(), t("div", {
|
|
64
64
|
key: 1,
|
|
65
65
|
class: w(["shiki-wrapper", { "no-wrap": !l.wordWrap }]),
|
|
66
66
|
innerHTML: a.value
|
|
67
|
-
}, null, 10,
|
|
67
|
+
}, null, 10, D)) : (e(), t("pre", {
|
|
68
68
|
key: 0,
|
|
69
69
|
class: w(["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"])
|
|
70
70
|
}, m(o.value), 3))
|
|
71
71
|
]));
|
|
72
72
|
}
|
|
73
|
-
}),
|
|
73
|
+
}), V = /* @__PURE__ */ j(F, [["__scopeId", "data-v-7c646170"]]);
|
|
74
74
|
export {
|
|
75
|
-
|
|
75
|
+
V as default
|
|
76
76
|
};
|
|
77
|
-
//# sourceMappingURL=index-
|
|
77
|
+
//# sourceMappingURL=index-Bu8GH1aq.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-Bu8GH1aq.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';\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 <div v-else-if=\"error\" class=\"vfp-flex vfp-items-center vfp-justify-center vfp-w-full vfp-h-full\">\n <div class=\"vfp-text-fg-secondary vfp-text-center\">\n <p class=\"vfp-text-lg\">{{ error }}</p>\n </div>\n </div>\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}\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","_hoisted_2","_hoisted_3","_hoisted_4","_toDisplayString","_hoisted_5","_hoisted_7","_normalizeClass"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAQA,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,QAI7Gd,EAAA,SAAhBU,EAAA,GAAAC,EAIM,OAJNI,GAIM;AAAA,MAHJD,EAEM,OAFNE,GAEM;AAAA,QADJF,EAAsC,KAAtCG,GAAsCC,EAAZlB,EAAA,KAAK,GAAA,CAAA;AAAA,MAAA;UAKnBX,EAAA,eAAeY,EAAA,UAAQ,UAAvCS,KAAAC,EAOM,OAPNQ,GAOM;AAAA,MANJL,EAKE,UAAA;AAAA,QAJC,QAAQlB,EAAA;AAAA,QACT,SAAQ;AAAA,QACR,OAAM;AAAA,QACL,OAAOP,EAAA;AAAA,MAAA;WAKZqB,EAAA,GAAAC,EAOM,OAPNS,GAOM;AAAA,MALKtB,EAAA,cAITa,EAA2F,OAAA;AAAA;QAA/E,OAAKU,EAAA,CAAC,iBAAe,EAAA,WAAA,CAAuBhC,EAAA,SAAA,CAAQ,CAAA;AAAA,QAAI,WAAQS,EAAA;AAAA,MAAA,yBAL5Ea,EAIoB,OAAA;AAAA;QAFlB,OAAKU,EAAA,CAAC,yDACEhC,EAAA,WAAQ,4CAAA,oBAAA,CAAA;AAAA,MAAA,KACdO,EAAA,KAAO,GAAA,CAAA;AAAA;;;"}
|