@eternalheart/react-file-preview 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +437 -60
- package/README.zh-CN.md +437 -60
- package/lib/FilePreviewContent.d.ts +1 -0
- package/lib/FilePreviewContent.d.ts.map +1 -1
- package/lib/FilePreviewEmbed.d.ts +2 -0
- package/lib/FilePreviewEmbed.d.ts.map +1 -1
- package/lib/FilePreviewModal.d.ts +2 -0
- package/lib/FilePreviewModal.d.ts.map +1 -1
- package/lib/chunks/index-2sX2d4iv.mjs +291 -0
- package/lib/chunks/index-2sX2d4iv.mjs.map +1 -0
- package/lib/chunks/index-Bdj8_B80.mjs +120 -0
- package/lib/chunks/index-Bdj8_B80.mjs.map +1 -0
- package/lib/chunks/index-CCcZzLUM.mjs +107 -0
- package/lib/chunks/index-CCcZzLUM.mjs.map +1 -0
- package/lib/chunks/{index-CzM2mxrD.mjs → index-CKdQL1Bk.mjs} +130 -128
- package/lib/chunks/{index-CzM2mxrD.mjs.map → index-CKdQL1Bk.mjs.map} +1 -1
- package/lib/chunks/index-CQYrhe7Z.mjs +275 -0
- package/lib/chunks/index-CQYrhe7Z.mjs.map +1 -0
- package/lib/chunks/{index-DuP0Tlpo.mjs → index-CRZqNMQ7.mjs} +43 -41
- package/lib/chunks/index-CRZqNMQ7.mjs.map +1 -0
- package/lib/chunks/{index-Cp68OevR.mjs → index-CTghYlSh.mjs} +1299 -1297
- package/lib/chunks/{index-Cp68OevR.mjs.map → index-CTghYlSh.mjs.map} +1 -1
- package/lib/chunks/index-CuTz7dbd.mjs +313 -0
- package/lib/chunks/index-CuTz7dbd.mjs.map +1 -0
- package/lib/chunks/index-CuWzRQZw.mjs +116 -0
- package/lib/chunks/index-CuWzRQZw.mjs.map +1 -0
- package/lib/chunks/index-Cz23v-TW.mjs +2409 -0
- package/lib/chunks/index-Cz23v-TW.mjs.map +1 -0
- package/lib/chunks/{index-kALp0tqz.mjs → index-D-Is8qvU.mjs} +22 -20
- package/lib/chunks/index-D-Is8qvU.mjs.map +1 -0
- package/lib/chunks/index-Da3FN2-3.mjs +359 -0
- package/lib/chunks/index-Da3FN2-3.mjs.map +1 -0
- package/lib/chunks/index-Dc6q1OKl.mjs +78 -0
- package/lib/chunks/index-Dc6q1OKl.mjs.map +1 -0
- package/lib/chunks/{index-10O8tfTH.mjs → index-DoGKcq9y.mjs} +194 -192
- package/lib/chunks/index-DoGKcq9y.mjs.map +1 -0
- package/lib/chunks/{index-C_BJatqr.mjs → index-DzCLf1Db.mjs} +42 -40
- package/lib/chunks/index-DzCLf1Db.mjs.map +1 -0
- package/lib/chunks/index-FomaQSaL.mjs +329 -0
- package/lib/chunks/index-FomaQSaL.mjs.map +1 -0
- package/lib/chunks/{index-DaAXRBWL.mjs → index-OXjOFggq.mjs} +864 -862
- package/lib/chunks/{index-DaAXRBWL.mjs.map → index-OXjOFggq.mjs.map} +1 -1
- package/lib/chunks/index-WLepq2g2.mjs +200 -0
- package/lib/chunks/index-WLepq2g2.mjs.map +1 -0
- package/lib/chunks/{index-DoFsoBKL.mjs → index-_B5marES.mjs} +27 -25
- package/lib/chunks/index-_B5marES.mjs.map +1 -0
- package/lib/chunks/useShikiHighlight-Bbs8Fbqs.mjs +36 -0
- package/lib/chunks/useShikiHighlight-Bbs8Fbqs.mjs.map +1 -0
- package/lib/components/preview/FilePreviewToolbar.d.ts +1 -0
- package/lib/components/preview/FilePreviewToolbar.d.ts.map +1 -1
- package/lib/components/preview/ToolbarButton.d.ts +3 -1
- package/lib/components/preview/ToolbarButton.d.ts.map +1 -1
- package/lib/hooks/index.d.ts +0 -6
- package/lib/hooks/index.d.ts.map +1 -1
- package/lib/hooks/useShikiHighlight.d.ts +3 -1
- package/lib/hooks/useShikiHighlight.d.ts.map +1 -1
- package/lib/index.cjs +32 -30
- package/lib/index.cjs.map +1 -1
- package/lib/index.css +1 -1
- package/lib/index.mjs +1 -1
- package/lib/renderers/Audio/index.d.ts +2 -1
- package/lib/renderers/Audio/index.d.ts.map +1 -1
- package/lib/renderers/Csv/index.d.ts +2 -1
- package/lib/renderers/Csv/index.d.ts.map +1 -1
- package/lib/renderers/Docx/index.d.ts +2 -1
- package/lib/renderers/Docx/index.d.ts.map +1 -1
- package/lib/renderers/Epub/index.d.ts +2 -3
- package/lib/renderers/Epub/index.d.ts.map +1 -1
- package/lib/renderers/Font/index.d.ts +2 -1
- package/lib/renderers/Font/index.d.ts.map +1 -1
- package/lib/renderers/Image/index.d.ts +6 -7
- package/lib/renderers/Image/index.d.ts.map +1 -1
- package/lib/renderers/Json/index.d.ts +2 -1
- package/lib/renderers/Json/index.d.ts.map +1 -1
- package/lib/renderers/Markdown/index.d.ts +2 -2
- package/lib/renderers/Markdown/index.d.ts.map +1 -1
- package/lib/renderers/Mobi/index.d.ts +2 -3
- package/lib/renderers/Mobi/index.d.ts.map +1 -1
- package/lib/renderers/Msg/index.d.ts +2 -1
- package/lib/renderers/Msg/index.d.ts.map +1 -1
- package/lib/renderers/Pdf/index.d.ts +4 -8
- package/lib/renderers/Pdf/index.d.ts.map +1 -1
- package/lib/renderers/Pptx/index.d.ts +2 -1
- package/lib/renderers/Pptx/index.d.ts.map +1 -1
- package/lib/renderers/Subtitle/index.d.ts +2 -1
- package/lib/renderers/Subtitle/index.d.ts.map +1 -1
- package/lib/renderers/Text/index.d.ts +2 -3
- package/lib/renderers/Text/index.d.ts.map +1 -1
- package/lib/renderers/Video/index.d.ts +2 -1
- package/lib/renderers/Video/index.d.ts.map +1 -1
- package/lib/renderers/Xlsx/index.d.ts +2 -1
- package/lib/renderers/Xlsx/index.d.ts.map +1 -1
- package/lib/renderers/Xml/index.d.ts +2 -1
- package/lib/renderers/Xml/index.d.ts.map +1 -1
- package/lib/renderers/Zip/index.d.ts +7 -2
- package/lib/renderers/Zip/index.d.ts.map +1 -1
- package/lib/renderers/base.types.d.ts +38 -0
- package/lib/renderers/base.types.d.ts.map +1 -0
- package/lib/renderers/registry.d.ts +36 -0
- package/lib/renderers/registry.d.ts.map +1 -0
- package/lib/renderers/toolbar.types.d.ts +2 -0
- package/lib/renderers/toolbar.types.d.ts.map +1 -1
- package/lib/toolbar/renderItems.d.ts.map +1 -1
- package/package.json +3 -3
- package/lib/chunks/index-0v5STX5f.mjs +0 -105
- package/lib/chunks/index-0v5STX5f.mjs.map +0 -1
- package/lib/chunks/index-10O8tfTH.mjs.map +0 -1
- package/lib/chunks/index-BCyv1HM9.mjs +0 -175
- package/lib/chunks/index-BCyv1HM9.mjs.map +0 -1
- package/lib/chunks/index-Bo90aGhy.mjs +0 -114
- package/lib/chunks/index-Bo90aGhy.mjs.map +0 -1
- package/lib/chunks/index-CEeKt7L3.mjs +0 -2808
- package/lib/chunks/index-CEeKt7L3.mjs.map +0 -1
- package/lib/chunks/index-CWKbnvW6.mjs +0 -270
- package/lib/chunks/index-CWKbnvW6.mjs.map +0 -1
- package/lib/chunks/index-C_BJatqr.mjs.map +0 -1
- package/lib/chunks/index-Cbz5Z6ZK.mjs +0 -263
- package/lib/chunks/index-Cbz5Z6ZK.mjs.map +0 -1
- package/lib/chunks/index-DTYBFuAH.mjs +0 -357
- package/lib/chunks/index-DTYBFuAH.mjs.map +0 -1
- package/lib/chunks/index-DoFsoBKL.mjs.map +0 -1
- package/lib/chunks/index-DuP0Tlpo.mjs.map +0 -1
- package/lib/chunks/index-Dv3RQz86.mjs +0 -270
- package/lib/chunks/index-Dv3RQz86.mjs.map +0 -1
- package/lib/chunks/index-QfpHck8N.mjs +0 -55
- package/lib/chunks/index-QfpHck8N.mjs.map +0 -1
- package/lib/chunks/index-gjSQeou7.mjs +0 -194
- package/lib/chunks/index-gjSQeou7.mjs.map +0 -1
- package/lib/chunks/index-kALp0tqz.mjs.map +0 -1
- package/lib/chunks/index-kCeSnFs-.mjs +0 -54
- package/lib/chunks/index-kCeSnFs-.mjs.map +0 -1
- package/lib/chunks/useShikiHighlight-BA9qgdGA.mjs +0 -23
- package/lib/chunks/useShikiHighlight-BA9qgdGA.mjs.map +0 -1
- package/lib/hooks/rendererReducer.d.ts +0 -10
- package/lib/hooks/rendererReducer.d.ts.map +0 -1
- package/lib/hooks/types.d.ts +0 -152
- package/lib/hooks/types.d.ts.map +0 -1
- package/lib/hooks/useBookRenderer.d.ts +0 -14
- package/lib/hooks/useBookRenderer.d.ts.map +0 -1
- package/lib/hooks/useFilePreviewState.d.ts +0 -10
- package/lib/hooks/useFilePreviewState.d.ts.map +0 -1
- package/lib/hooks/useImageAutoFit.d.ts +0 -13
- package/lib/hooks/useImageAutoFit.d.ts.map +0 -1
- package/lib/hooks/useToolbarConfig.d.ts +0 -25
- package/lib/hooks/useToolbarConfig.d.ts.map +0 -1
- package/lib/renderers/Epub/toolbar.d.ts +0 -13
- package/lib/renderers/Epub/toolbar.d.ts.map +0 -1
- package/lib/renderers/Image/toolbar.d.ts +0 -15
- package/lib/renderers/Image/toolbar.d.ts.map +0 -1
- package/lib/renderers/Markdown/toolbar.d.ts +0 -9
- package/lib/renderers/Markdown/toolbar.d.ts.map +0 -1
- package/lib/renderers/Mobi/toolbar.d.ts +0 -13
- package/lib/renderers/Mobi/toolbar.d.ts.map +0 -1
- package/lib/renderers/Pdf/toolbar.d.ts +0 -16
- package/lib/renderers/Pdf/toolbar.d.ts.map +0 -1
- package/lib/renderers/Text/toolbar.d.ts +0 -12
- package/lib/renderers/Text/toolbar.d.ts.map +0 -1
- package/lib/renderers/Zip/toolbar.d.ts +0 -13
- package/lib/renderers/Zip/toolbar.d.ts.map +0 -1
- package/lib/toolbar/registry.d.ts +0 -51
- package/lib/toolbar/registry.d.ts.map +0 -1
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { jsx as e, jsxs as h } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as j, useState as i, useEffect as M, useRef as B, useCallback as c, useImperativeHandle as L } from "react";
|
|
3
|
+
import q from "react-markdown";
|
|
4
|
+
import A from "remark-gfm";
|
|
5
|
+
import F from "remark-math";
|
|
6
|
+
import G from "rehype-katex";
|
|
7
|
+
import P from "rehype-raw";
|
|
8
|
+
import { Code as V, Eye as K, Check as S, Copy as z } from "lucide-react";
|
|
9
|
+
import { u as g, a as O, z as $ } from "./index-Cz23v-TW.mjs";
|
|
10
|
+
import { u as R } from "./useShikiHighlight-Bbs8Fbqs.mjs";
|
|
11
|
+
import { R as D } from "./RendererError-D5i8eSpN.mjs";
|
|
12
|
+
const T = (o) => {
|
|
13
|
+
const [p, t] = i(!1), a = c(async () => {
|
|
14
|
+
try {
|
|
15
|
+
await navigator.clipboard.writeText(o);
|
|
16
|
+
} catch {
|
|
17
|
+
const n = document.createElement("textarea");
|
|
18
|
+
n.value = o, document.body.appendChild(n), n.select(), document.execCommand("copy"), document.body.removeChild(n);
|
|
19
|
+
}
|
|
20
|
+
t(!0), setTimeout(() => t(!1), 2e3);
|
|
21
|
+
}, [o]);
|
|
22
|
+
return { copied: p, handleCopy: a };
|
|
23
|
+
}, J = ({ text: o }) => {
|
|
24
|
+
const p = g(), { copied: t, handleCopy: a } = T(o);
|
|
25
|
+
return /* @__PURE__ */ e(
|
|
26
|
+
"button",
|
|
27
|
+
{
|
|
28
|
+
onClick: a,
|
|
29
|
+
className: "rfp-p-1 rfp-rounded rfp-text-fg-muted hover:rfp-text-fg-secondary rfp-transition-colors rfp-flex rfp-items-center rfp-gap-1",
|
|
30
|
+
title: p(t ? "markdown.copied" : "markdown.copy_code"),
|
|
31
|
+
children: t ? /* @__PURE__ */ e(S, { size: 13 }) : /* @__PURE__ */ e(z, { size: 13 })
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
}, Q = ({ text: o }) => {
|
|
35
|
+
const p = g(), { copied: t, handleCopy: a } = T(o);
|
|
36
|
+
return /* @__PURE__ */ e(
|
|
37
|
+
"button",
|
|
38
|
+
{
|
|
39
|
+
onClick: a,
|
|
40
|
+
className: "rfp-absolute rfp-top-2 rfp-right-2 rfp-p-1.5 rfp-rounded-md rfp-bg-surface-2 hover:rfp-bg-surface-3 rfp-text-fg-tertiary hover:rfp-text-fg-secondary rfp-transition-colors rfp-opacity-0 group-hover:rfp-opacity-100 rfp-border rfp-border-line",
|
|
41
|
+
title: p(t ? "markdown.copied" : "markdown.copy_code"),
|
|
42
|
+
children: t ? /* @__PURE__ */ e(S, { size: 14 }) : /* @__PURE__ */ e(z, { size: 14 })
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
}, U = ({ code: o, lang: p }) => {
|
|
46
|
+
const { html: t } = R(o, p);
|
|
47
|
+
return /* @__PURE__ */ h("div", { className: "rfp-relative rfp-group rfp-my-4", children: [
|
|
48
|
+
/* @__PURE__ */ h("div", { className: "rfp-flex rfp-items-center rfp-justify-between rfp-px-4 rfp-py-1.5 rfp-bg-surface-1 rfp-border rfp-border-line-weak rfp-rounded-t-md rfp-border-b-0", children: [
|
|
49
|
+
/* @__PURE__ */ e("span", { className: "rfp-text-xs rfp-text-fg-secondary rfp-font-mono rfp-select-none", children: p }),
|
|
50
|
+
/* @__PURE__ */ e(J, { text: o })
|
|
51
|
+
] }),
|
|
52
|
+
t ? /* @__PURE__ */ e(
|
|
53
|
+
"div",
|
|
54
|
+
{
|
|
55
|
+
className: "rfp-shiki-wrapper rfp-rounded-b-md rfp-border rfp-border-line-weak rfp-border-t-0 rfp-overflow-x-auto",
|
|
56
|
+
dangerouslySetInnerHTML: { __html: t }
|
|
57
|
+
}
|
|
58
|
+
) : /* @__PURE__ */ e(
|
|
59
|
+
"pre",
|
|
60
|
+
{
|
|
61
|
+
className: "rfp-m-0 rfp-rounded-b-md rfp-border rfp-border-line-weak rfp-border-t-0 rfp-overflow-x-auto rfp-p-4 rfp-bg-code-bg",
|
|
62
|
+
style: { fontSize: "13px", lineHeight: "1.5" },
|
|
63
|
+
children: /* @__PURE__ */ e("code", { className: "rfp-font-mono rfp-text-code-fg rfp-text-sm", children: o })
|
|
64
|
+
}
|
|
65
|
+
)
|
|
66
|
+
] });
|
|
67
|
+
}, sr = j(({ url: o }, p) => {
|
|
68
|
+
const t = g(), a = O(), [n, _] = i(""), [E, x] = i(!0), [y, w] = i(null), [l, H] = i("preview"), { html: v } = R(
|
|
69
|
+
l === "source" ? n : "",
|
|
70
|
+
"markdown"
|
|
71
|
+
);
|
|
72
|
+
M(() => {
|
|
73
|
+
const r = new AbortController();
|
|
74
|
+
return (async () => {
|
|
75
|
+
try {
|
|
76
|
+
x(!0), w(null);
|
|
77
|
+
const f = await $(o, { fetcher: a, signal: r.signal });
|
|
78
|
+
_(f);
|
|
79
|
+
} catch (f) {
|
|
80
|
+
if (f.name === "AbortError") return;
|
|
81
|
+
w(t("markdown.load_failed")), console.error(f);
|
|
82
|
+
} finally {
|
|
83
|
+
x(!1);
|
|
84
|
+
}
|
|
85
|
+
})(), () => r.abort();
|
|
86
|
+
}, [o, a, t]);
|
|
87
|
+
const d = B(/* @__PURE__ */ new Set()), N = c(() => {
|
|
88
|
+
d.current.forEach((r) => r());
|
|
89
|
+
}, []);
|
|
90
|
+
M(() => {
|
|
91
|
+
N();
|
|
92
|
+
}, [l, N]);
|
|
93
|
+
const k = c(() => {
|
|
94
|
+
H((r) => r === "preview" ? "source" : "preview");
|
|
95
|
+
}, []), C = c(() => [
|
|
96
|
+
{
|
|
97
|
+
items: [
|
|
98
|
+
{
|
|
99
|
+
type: "button",
|
|
100
|
+
icon: l === "preview" ? /* @__PURE__ */ e(V, { className: "rfp-w-4 rfp-h-4" }) : /* @__PURE__ */ e(K, { className: "rfp-w-4 rfp-h-4" }),
|
|
101
|
+
tooltip: t(l === "preview" ? "toolbar.source" : "toolbar.preview"),
|
|
102
|
+
action: k,
|
|
103
|
+
active: l === "source"
|
|
104
|
+
}
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
], [l, t, k]);
|
|
108
|
+
return L(p, () => ({
|
|
109
|
+
getToolbarGroups: C,
|
|
110
|
+
onToolbarChange: (r) => (d.current.add(r), () => d.current.delete(r))
|
|
111
|
+
}), [C]), E ? /* @__PURE__ */ e("div", { className: "rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full", children: /* @__PURE__ */ e("div", { className: "rfp-w-12 rfp-h-12 rfp-border-4 rfp-border-line-strong rfp-border-t-spinner-head rfp-rounded-full rfp-animate-spin" }) }) : y ? /* @__PURE__ */ e(D, { message: y }) : l === "source" ? /* @__PURE__ */ e("div", { className: "rfp-w-full rfp-h-full rfp-overflow-auto rfp-bg-code-bg", children: v ? /* @__PURE__ */ e(
|
|
112
|
+
"div",
|
|
113
|
+
{
|
|
114
|
+
className: "rfp-shiki-wrapper with-line-numbers",
|
|
115
|
+
dangerouslySetInnerHTML: { __html: v }
|
|
116
|
+
}
|
|
117
|
+
) : /* @__PURE__ */ e("pre", { className: "rfp-p-6 rfp-text-fg-primary rfp-font-mono rfp-text-sm rfp-whitespace-pre-wrap rfp-break-words", children: n }) }) : /* @__PURE__ */ e("div", { className: "rfp-w-full rfp-h-full rfp-overflow-auto rfp-py-6 rfp-px-4", children: /* @__PURE__ */ e(
|
|
118
|
+
q,
|
|
119
|
+
{
|
|
120
|
+
remarkPlugins: [A, F],
|
|
121
|
+
rehypePlugins: [P, G],
|
|
122
|
+
components: {
|
|
123
|
+
code({ node: r, inline: s, className: f, children: m, ...I }) {
|
|
124
|
+
const u = /language-(\w+)/.exec(f || ""), b = String(m).replace(/\n$/, "");
|
|
125
|
+
return s ?? (!u && !b.includes(`
|
|
126
|
+
`)) ? /* @__PURE__ */ e(
|
|
127
|
+
"code",
|
|
128
|
+
{
|
|
129
|
+
className: "rfp-bg-surface-2 rfp-px-1.5 rfp-py-0.5 rfp-rounded rfp-text-sm rfp-font-mono rfp-text-fg-primary rfp-border rfp-border-line-weak",
|
|
130
|
+
...I,
|
|
131
|
+
children: m
|
|
132
|
+
}
|
|
133
|
+
) : u ? /* @__PURE__ */ e(U, { code: b, lang: u[1] }) : /* @__PURE__ */ h("div", { className: "rfp-relative rfp-group rfp-my-4", children: [
|
|
134
|
+
/* @__PURE__ */ e(Q, { text: b }),
|
|
135
|
+
/* @__PURE__ */ e(
|
|
136
|
+
"pre",
|
|
137
|
+
{
|
|
138
|
+
className: "rfp-m-0 rfp-rounded-md rfp-border rfp-border-line-weak rfp-overflow-x-auto rfp-p-4 rfp-bg-code-bg",
|
|
139
|
+
style: { fontSize: "13px", lineHeight: "1.5" },
|
|
140
|
+
children: /* @__PURE__ */ e("code", { className: "rfp-font-mono rfp-text-code-fg rfp-text-sm", children: m })
|
|
141
|
+
}
|
|
142
|
+
)
|
|
143
|
+
] });
|
|
144
|
+
},
|
|
145
|
+
h1: ({ children: r }) => /* @__PURE__ */ e("h1", { className: "rfp-text-3xl rfp-font-semibold rfp-mb-4 rfp-mt-6 rfp-text-fg-primary first:rfp-mt-0", children: r }),
|
|
146
|
+
h2: ({ children: r }) => /* @__PURE__ */ e("h2", { className: "rfp-text-2xl rfp-font-semibold rfp-mb-3 rfp-mt-8 rfp-text-fg-primary", children: r }),
|
|
147
|
+
h3: ({ children: r }) => /* @__PURE__ */ e("h3", { className: "rfp-text-xl rfp-font-semibold rfp-mb-2 rfp-mt-6 rfp-text-fg-primary", children: r }),
|
|
148
|
+
h4: ({ children: r }) => /* @__PURE__ */ e("h4", { className: "rfp-text-lg rfp-font-semibold rfp-mb-2 rfp-mt-4 rfp-text-fg-primary", children: r }),
|
|
149
|
+
p: ({ children: r }) => /* @__PURE__ */ e("p", { className: "rfp-text-fg-secondary rfp-mb-4 rfp-leading-7 rfp-text-base", children: r }),
|
|
150
|
+
a: ({ href: r, children: s }) => /* @__PURE__ */ e(
|
|
151
|
+
"a",
|
|
152
|
+
{
|
|
153
|
+
href: r,
|
|
154
|
+
className: "rfp-text-indigo-400 hover:rfp-text-indigo-300 rfp-underline rfp-decoration-indigo-600 hover:rfp-decoration-indigo-400",
|
|
155
|
+
target: "_blank",
|
|
156
|
+
rel: "noopener noreferrer",
|
|
157
|
+
children: s
|
|
158
|
+
}
|
|
159
|
+
),
|
|
160
|
+
ul: ({ children: r }) => /* @__PURE__ */ e("ul", { className: "rfp-list-disc rfp-pl-6 rfp-mb-4 rfp-text-fg-secondary rfp-space-y-1", children: r }),
|
|
161
|
+
ol: ({ children: r }) => /* @__PURE__ */ e("ol", { className: "rfp-list-decimal rfp-pl-6 rfp-mb-4 rfp-text-fg-secondary rfp-space-y-1", children: r }),
|
|
162
|
+
li: ({ children: r }) => /* @__PURE__ */ e("li", { className: "rfp-leading-7", children: r }),
|
|
163
|
+
blockquote: ({ children: r }) => /* @__PURE__ */ e("blockquote", { className: "rfp-border-l-4 rfp-border-line-strong rfp-pl-4 rfp-text-fg-tertiary rfp-my-4 rfp-italic", children: r }),
|
|
164
|
+
table: ({ children: r }) => /* @__PURE__ */ e("div", { className: "rfp-overflow-x-auto rfp-my-4 rfp-rounded-md rfp-border rfp-border-line", children: /* @__PURE__ */ e("table", { className: "rfp-min-w-full rfp-divide-y rfp-divide-divide", children: r }) }),
|
|
165
|
+
thead: ({ children: r }) => /* @__PURE__ */ e("thead", { className: "rfp-bg-surface-1", children: r }),
|
|
166
|
+
tbody: ({ children: r }) => /* @__PURE__ */ e("tbody", { className: "rfp-divide-y rfp-divide-divide rfp-bg-transparent", children: r }),
|
|
167
|
+
tr: ({ children: r }) => /* @__PURE__ */ e("tr", { className: "hover:rfp-bg-surface-1 rfp-transition-colors", children: r }),
|
|
168
|
+
th: ({ children: r }) => /* @__PURE__ */ e("th", { className: "rfp-px-4 rfp-py-3 rfp-text-left rfp-text-xs rfp-font-semibold rfp-text-fg-tertiary rfp-uppercase rfp-tracking-wider", children: r }),
|
|
169
|
+
td: ({ children: r }) => /* @__PURE__ */ e("td", { className: "rfp-px-4 rfp-py-3 rfp-text-sm rfp-text-fg-secondary", children: r }),
|
|
170
|
+
hr: () => /* @__PURE__ */ e("hr", { className: "rfp-border-line rfp-my-6" }),
|
|
171
|
+
img: ({ src: r, alt: s }) => /* @__PURE__ */ e(
|
|
172
|
+
"img",
|
|
173
|
+
{
|
|
174
|
+
src: r,
|
|
175
|
+
alt: s,
|
|
176
|
+
className: "rfp-rounded-md rfp-max-w-full rfp-h-auto rfp-my-4 rfp-mx-auto rfp-block rfp-shadow-sm"
|
|
177
|
+
}
|
|
178
|
+
),
|
|
179
|
+
input: ({ type: r, checked: s, ...f }) => r === "checkbox" ? /* @__PURE__ */ e(
|
|
180
|
+
"input",
|
|
181
|
+
{
|
|
182
|
+
type: "checkbox",
|
|
183
|
+
checked: s,
|
|
184
|
+
readOnly: !0,
|
|
185
|
+
className: "rfp-mr-2 rfp-rounded rfp-border-line",
|
|
186
|
+
...f
|
|
187
|
+
}
|
|
188
|
+
) : /* @__PURE__ */ e("input", { type: r, ...f }),
|
|
189
|
+
strong: ({ children: r }) => /* @__PURE__ */ e("strong", { className: "rfp-font-semibold rfp-text-fg-primary", children: r }),
|
|
190
|
+
em: ({ children: r }) => /* @__PURE__ */ e("em", { className: "rfp-italic", children: r }),
|
|
191
|
+
del: ({ children: r }) => /* @__PURE__ */ e("del", { className: "rfp-text-fg-muted rfp-line-through", children: r })
|
|
192
|
+
},
|
|
193
|
+
children: n
|
|
194
|
+
}
|
|
195
|
+
) });
|
|
196
|
+
});
|
|
197
|
+
export {
|
|
198
|
+
sr as MarkdownRenderer
|
|
199
|
+
};
|
|
200
|
+
//# sourceMappingURL=index-WLepq2g2.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-WLepq2g2.mjs","sources":["../../src/renderers/Markdown/index.tsx"],"sourcesContent":["import { useState, useEffect, useCallback, forwardRef, useImperativeHandle, useRef } from 'react';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport remarkMath from 'remark-math';\nimport rehypeKatex from 'rehype-katex';\nimport rehypeRaw from 'rehype-raw';\nimport { Copy, Check, Eye, Code } from 'lucide-react';\nimport { fetchTextUtf8 } from '@eternalheart/file-preview-core';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\nimport { useShikiHighlight } from '../../hooks/useShikiHighlight';\nimport { RendererError } from '../RendererError';\nimport type { RendererHandle } from '../base.types';\nimport type { ToolbarGroup } from '../toolbar.types';\nimport 'katex/dist/katex.min.css';\n\ninterface MarkdownRendererProps {\n url: string;\n}\n\nconst useCopy = (text: string) => {\n const [copied, setCopied] = useState(false);\n const handleCopy = useCallback(async () => {\n try {\n await navigator.clipboard.writeText(text);\n } catch {\n const textarea = document.createElement('textarea');\n textarea.value = text;\n document.body.appendChild(textarea);\n textarea.select();\n document.execCommand('copy');\n document.body.removeChild(textarea);\n }\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }, [text]);\n return { copied, handleCopy };\n};\n\n/** 内联版复制按钮:放在代码块 header 行内,始终可见 */\nconst InlineCopyButton = ({ text }: { text: string }) => {\n const t = useTranslator();\n const { copied, handleCopy } = useCopy(text);\n return (\n <button\n onClick={handleCopy}\n className=\"rfp-p-1 rfp-rounded rfp-text-fg-muted hover:rfp-text-fg-secondary rfp-transition-colors rfp-flex rfp-items-center rfp-gap-1\"\n title={copied ? t('markdown.copied') : t('markdown.copy_code')}\n >\n {copied ? <Check size={13} /> : <Copy size={13} />}\n </button>\n );\n};\n\n/** 浮动版复制按钮:无 header 时绝对定位于代码块右上角(hover 显示) */\nconst FloatingCopyButton = ({ text }: { text: string }) => {\n const t = useTranslator();\n const { copied, handleCopy } = useCopy(text);\n return (\n <button\n onClick={handleCopy}\n className=\"rfp-absolute rfp-top-2 rfp-right-2 rfp-p-1.5 rfp-rounded-md rfp-bg-surface-2 hover:rfp-bg-surface-3 rfp-text-fg-tertiary hover:rfp-text-fg-secondary rfp-transition-colors rfp-opacity-0 group-hover:rfp-opacity-100 rfp-border rfp-border-line\"\n title={copied ? t('markdown.copied') : t('markdown.copy_code')}\n >\n {copied ? <Check size={14} /> : <Copy size={14} />}\n </button>\n );\n};\n\n/** 带语言标注的代码块:shiki 高亮 + header + 复制按钮 */\nconst ShikiCodeBlock = ({ code, lang }: { code: string; lang: string }) => {\n const { html } = useShikiHighlight(code, lang);\n return (\n <div className=\"rfp-relative rfp-group rfp-my-4\">\n <div className=\"rfp-flex rfp-items-center rfp-justify-between rfp-px-4 rfp-py-1.5 rfp-bg-surface-1 rfp-border rfp-border-line-weak rfp-rounded-t-md rfp-border-b-0\">\n <span className=\"rfp-text-xs rfp-text-fg-secondary rfp-font-mono rfp-select-none\">{lang}</span>\n <InlineCopyButton text={code} />\n </div>\n {html ? (\n <div\n className=\"rfp-shiki-wrapper rfp-rounded-b-md rfp-border rfp-border-line-weak rfp-border-t-0 rfp-overflow-x-auto\"\n dangerouslySetInnerHTML={{ __html: html }}\n />\n ) : (\n <pre\n className=\"rfp-m-0 rfp-rounded-b-md rfp-border rfp-border-line-weak rfp-border-t-0 rfp-overflow-x-auto rfp-p-4 rfp-bg-code-bg\"\n style={{ fontSize: '13px', lineHeight: '1.5' }}\n >\n <code className=\"rfp-font-mono rfp-text-code-fg rfp-text-sm\">{code}</code>\n </pre>\n )}\n </div>\n );\n};\n\nexport const MarkdownRenderer = forwardRef<RendererHandle, MarkdownRendererProps>(({ url }, ref) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n\n // 内部状态管理\n const [content, setContent] = useState<string>('');\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [viewMode, setViewMode] = useState<'preview' | 'source'>('preview');\n\n const { html: sourceHtml } = useShikiHighlight(\n viewMode === 'source' ? content : '',\n 'markdown',\n );\n\n useEffect(() => {\n const controller = new AbortController();\n const loadMarkdown = async () => {\n try {\n setLoading(true);\n setError(null);\n const text = await fetchTextUtf8(url, { fetcher, signal: controller.signal });\n setContent(text);\n } catch (err: any) {\n if (err.name === 'AbortError') return;\n setError(t('markdown.load_failed'));\n console.error(err);\n } finally {\n setLoading(false);\n }\n };\n\n loadMarkdown();\n return () => controller.abort();\n }, [url, fetcher, t]);\n\n // 事件发射器:用于通知主组件工具栏状态变化\n const listenersRef = useRef<Set<() => void>>(new Set());\n const notifyToolbarChange = useCallback(() => {\n listenersRef.current.forEach(listener => listener());\n }, []);\n\n // 监听影响工具栏的状态变化\n useEffect(() => {\n notifyToolbarChange();\n }, [viewMode, notifyToolbarChange]);\n\n // 切换视图模式\n const toggleViewMode = useCallback(() => {\n setViewMode(prev => prev === 'preview' ? 'source' : 'preview');\n }, []);\n\n // 工具栏配置\n const getToolbarGroups = useCallback((): ToolbarGroup[] => [\n {\n items: [\n {\n type: 'button',\n icon: viewMode === 'preview' ? <Code className=\"rfp-w-4 rfp-h-4\" /> : <Eye className=\"rfp-w-4 rfp-h-4\" />,\n tooltip: viewMode === 'preview' ? t('toolbar.source') : t('toolbar.preview'),\n action: toggleViewMode,\n active: viewMode === 'source',\n },\n ],\n },\n ], [viewMode, t, toggleViewMode]);\n\n // 暴露接口给父组件\n useImperativeHandle(ref, () => ({\n getToolbarGroups,\n onToolbarChange: (listener: () => void) => {\n listenersRef.current.add(listener);\n return () => listenersRef.current.delete(listener);\n },\n }), [getToolbarGroups]);\n\n if (loading) {\n return (\n <div className=\"rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full\">\n <div className=\"rfp-w-12 rfp-h-12 rfp-border-4 rfp-border-line-strong rfp-border-t-spinner-head rfp-rounded-full rfp-animate-spin\" />\n </div>\n );\n }\n\n if (error) {\n return <RendererError message={error} />;\n }\n\n // 源码视图\n if (viewMode === 'source') {\n return (\n <div className=\"rfp-w-full rfp-h-full rfp-overflow-auto rfp-bg-code-bg\">\n {sourceHtml ? (\n <div\n className=\"rfp-shiki-wrapper with-line-numbers\"\n dangerouslySetInnerHTML={{ __html: sourceHtml }}\n />\n ) : (\n <pre className=\"rfp-p-6 rfp-text-fg-primary rfp-font-mono rfp-text-sm rfp-whitespace-pre-wrap rfp-break-words\">\n {content}\n </pre>\n )}\n </div>\n );\n }\n\n // 预览视图\n return (\n <div className=\"rfp-w-full rfp-h-full rfp-overflow-auto rfp-py-6 rfp-px-4\">\n <ReactMarkdown\n remarkPlugins={[remarkGfm, remarkMath]}\n rehypePlugins={[rehypeRaw, rehypeKatex]}\n components={{\n code({ node, inline, className, children, ...props }: any) {\n const match = /language-(\\w+)/.exec(className || '');\n const codeString = String(children).replace(/\\n$/, '');\n // react-markdown v9 不再传 inline,需要兜底判断:\n // 无语言 className 且不含换行视为内联代码\n const isInline = inline ?? (!match && !codeString.includes('\\n'));\n\n // 行内代码 - 返回纯 <code>\n if (isInline) {\n return (\n <code\n className=\"rfp-bg-surface-2 rfp-px-1.5 rfp-py-0.5 rfp-rounded rfp-text-sm rfp-font-mono rfp-text-fg-primary rfp-border rfp-border-line-weak\"\n {...props}\n >\n {children}\n </code>\n );\n }\n\n // 代码块 - 有语言标注\n if (match) {\n return <ShikiCodeBlock code={codeString} lang={match[1]} />;\n }\n\n // 代码块 - 无语言标注\n return (\n <div className=\"rfp-relative rfp-group rfp-my-4\">\n <FloatingCopyButton text={codeString} />\n <pre\n className=\"rfp-m-0 rfp-rounded-md rfp-border rfp-border-line-weak rfp-overflow-x-auto rfp-p-4 rfp-bg-code-bg\"\n style={{ fontSize: '13px', lineHeight: '1.5' }}\n >\n <code className=\"rfp-font-mono rfp-text-code-fg rfp-text-sm\">{children}</code>\n </pre>\n </div>\n );\n },\n h1: ({ children }) => (\n <h1 className=\"rfp-text-3xl rfp-font-semibold rfp-mb-4 rfp-mt-6 rfp-text-fg-primary first:rfp-mt-0\">\n {children}\n </h1>\n ),\n h2: ({ children }) => (\n <h2 className=\"rfp-text-2xl rfp-font-semibold rfp-mb-3 rfp-mt-8 rfp-text-fg-primary\">\n {children}\n </h2>\n ),\n h3: ({ children }) => (\n <h3 className=\"rfp-text-xl rfp-font-semibold rfp-mb-2 rfp-mt-6 rfp-text-fg-primary\">{children}</h3>\n ),\n h4: ({ children }) => (\n <h4 className=\"rfp-text-lg rfp-font-semibold rfp-mb-2 rfp-mt-4 rfp-text-fg-primary\">{children}</h4>\n ),\n p: ({ children }) => (\n <p className=\"rfp-text-fg-secondary rfp-mb-4 rfp-leading-7 rfp-text-base\">{children}</p>\n ),\n a: ({ href, children }) => (\n <a\n href={href}\n className=\"rfp-text-indigo-400 hover:rfp-text-indigo-300 rfp-underline rfp-decoration-indigo-600 hover:rfp-decoration-indigo-400\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {children}\n </a>\n ),\n ul: ({ children }) => (\n <ul className=\"rfp-list-disc rfp-pl-6 rfp-mb-4 rfp-text-fg-secondary rfp-space-y-1\">{children}</ul>\n ),\n ol: ({ children }) => (\n <ol className=\"rfp-list-decimal rfp-pl-6 rfp-mb-4 rfp-text-fg-secondary rfp-space-y-1\">{children}</ol>\n ),\n li: ({ children }) => <li className=\"rfp-leading-7\">{children}</li>,\n blockquote: ({ children }) => (\n <blockquote className=\"rfp-border-l-4 rfp-border-line-strong rfp-pl-4 rfp-text-fg-tertiary rfp-my-4 rfp-italic\">\n {children}\n </blockquote>\n ),\n table: ({ children }) => (\n <div className=\"rfp-overflow-x-auto rfp-my-4 rfp-rounded-md rfp-border rfp-border-line\">\n <table className=\"rfp-min-w-full rfp-divide-y rfp-divide-divide\">{children}</table>\n </div>\n ),\n thead: ({ children }) => <thead className=\"rfp-bg-surface-1\">{children}</thead>,\n tbody: ({ children }) => (\n <tbody className=\"rfp-divide-y rfp-divide-divide rfp-bg-transparent\">{children}</tbody>\n ),\n tr: ({ children }) => (\n <tr className=\"hover:rfp-bg-surface-1 rfp-transition-colors\">{children}</tr>\n ),\n th: ({ children }) => (\n <th className=\"rfp-px-4 rfp-py-3 rfp-text-left rfp-text-xs rfp-font-semibold rfp-text-fg-tertiary rfp-uppercase rfp-tracking-wider\">\n {children}\n </th>\n ),\n td: ({ children }) => (\n <td className=\"rfp-px-4 rfp-py-3 rfp-text-sm rfp-text-fg-secondary\">{children}</td>\n ),\n hr: () => <hr className=\"rfp-border-line rfp-my-6\" />,\n img: ({ src, alt }) => (\n <img\n src={src}\n alt={alt}\n className=\"rfp-rounded-md rfp-max-w-full rfp-h-auto rfp-my-4 rfp-mx-auto rfp-block rfp-shadow-sm\"\n />\n ),\n input: ({ type, checked, ...props }) => {\n if (type === 'checkbox') {\n return (\n <input\n type=\"checkbox\"\n checked={checked}\n readOnly\n className=\"rfp-mr-2 rfp-rounded rfp-border-line\"\n {...props}\n />\n );\n }\n return <input type={type} {...props} />;\n },\n strong: ({ children }) => (\n <strong className=\"rfp-font-semibold rfp-text-fg-primary\">{children}</strong>\n ),\n em: ({ children }) => <em className=\"rfp-italic\">{children}</em>,\n del: ({ children }) => (\n <del className=\"rfp-text-fg-muted rfp-line-through\">{children}</del>\n ),\n }}\n >\n {content}\n </ReactMarkdown>\n </div>\n );\n});\n"],"names":["useCopy","text","copied","setCopied","useState","handleCopy","useCallback","textarea","InlineCopyButton","t","useTranslator","jsx","Check","Copy","FloatingCopyButton","ShikiCodeBlock","code","lang","html","useShikiHighlight","jsxs","MarkdownRenderer","forwardRef","url","ref","fetcher","useFetcher","content","setContent","loading","setLoading","error","setError","viewMode","setViewMode","sourceHtml","useEffect","controller","fetchTextUtf8","err","listenersRef","useRef","notifyToolbarChange","listener","toggleViewMode","prev","getToolbarGroups","Code","Eye","useImperativeHandle","RendererError","ReactMarkdown","remarkGfm","remarkMath","rehypeRaw","rehypeKatex","node","inline","className","children","props","match","codeString","href","src","alt","type","checked"],"mappings":";;;;;;;;;;;AAoBA,MAAMA,IAAU,CAACC,MAAiB;AAChC,QAAM,CAACC,GAAQC,CAAS,IAAIC,EAAS,EAAK,GACpCC,IAAaC,EAAY,YAAY;AACzC,QAAI;AACF,YAAM,UAAU,UAAU,UAAUL,CAAI;AAAA,IAC1C,QAAQ;AACN,YAAMM,IAAW,SAAS,cAAc,UAAU;AAClD,MAAAA,EAAS,QAAQN,GACjB,SAAS,KAAK,YAAYM,CAAQ,GAClCA,EAAS,OAAA,GACT,SAAS,YAAY,MAAM,GAC3B,SAAS,KAAK,YAAYA,CAAQ;AAAA,IACpC;AACA,IAAAJ,EAAU,EAAI,GACd,WAAW,MAAMA,EAAU,EAAK,GAAG,GAAI;AAAA,EACzC,GAAG,CAACF,CAAI,CAAC;AACT,SAAO,EAAE,QAAAC,GAAQ,YAAAG,EAAA;AACnB,GAGMG,IAAmB,CAAC,EAAE,MAAAP,QAA6B;AACvD,QAAMQ,IAAIC,EAAA,GACJ,EAAE,QAAAR,GAAQ,YAAAG,MAAeL,EAAQC,CAAI;AAC3C,SACE,gBAAAU;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,SAASN;AAAA,MACT,WAAU;AAAA,MACV,OAAgBI,EAATP,IAAW,oBAAuB,oBAAN;AAAA,MAElC,UAAAA,sBAAUU,GAAA,EAAM,MAAM,IAAI,IAAK,gBAAAD,EAACE,GAAA,EAAK,MAAM,GAAA,CAAI;AAAA,IAAA;AAAA,EAAA;AAGtD,GAGMC,IAAqB,CAAC,EAAE,MAAAb,QAA6B;AACzD,QAAMQ,IAAIC,EAAA,GACJ,EAAE,QAAAR,GAAQ,YAAAG,MAAeL,EAAQC,CAAI;AAC3C,SACE,gBAAAU;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,SAASN;AAAA,MACT,WAAU;AAAA,MACV,OAAgBI,EAATP,IAAW,oBAAuB,oBAAN;AAAA,MAElC,UAAAA,sBAAUU,GAAA,EAAM,MAAM,IAAI,IAAK,gBAAAD,EAACE,GAAA,EAAK,MAAM,GAAA,CAAI;AAAA,IAAA;AAAA,EAAA;AAGtD,GAGME,IAAiB,CAAC,EAAE,MAAAC,GAAM,MAAAC,QAA2C;AACzE,QAAM,EAAE,MAAAC,EAAA,IAASC,EAAkBH,GAAMC,CAAI;AAC7C,SACE,gBAAAG,EAAC,OAAA,EAAI,WAAU,mCACb,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,sJACb,UAAA;AAAA,MAAA,gBAAAT,EAAC,QAAA,EAAK,WAAU,mEAAmE,UAAAM,GAAK;AAAA,MACxF,gBAAAN,EAACH,GAAA,EAAiB,MAAMQ,EAAA,CAAM;AAAA,IAAA,GAChC;AAAA,IACCE,IACC,gBAAAP;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,yBAAyB,EAAE,QAAQO,EAAA;AAAA,MAAK;AAAA,IAAA,IAG1C,gBAAAP;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,OAAO,EAAE,UAAU,QAAQ,YAAY,MAAA;AAAA,QAEvC,UAAA,gBAAAA,EAAC,QAAA,EAAK,WAAU,8CAA8C,UAAAK,EAAA,CAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EACrE,GAEJ;AAEJ,GAEaK,KAAmBC,EAAkD,CAAC,EAAE,KAAAC,EAAA,GAAOC,MAAQ;AAClG,QAAM,IAAId,EAAA,GACJe,IAAUC,EAAA,GAGV,CAACC,GAASC,CAAU,IAAIxB,EAAiB,EAAE,GAC3C,CAACyB,GAASC,CAAU,IAAI1B,EAAS,EAAI,GACrC,CAAC2B,GAAOC,CAAQ,IAAI5B,EAAwB,IAAI,GAChD,CAAC6B,GAAUC,CAAW,IAAI9B,EAA+B,SAAS,GAElE,EAAE,MAAM+B,EAAA,IAAehB;AAAA,IAC3Bc,MAAa,WAAWN,IAAU;AAAA,IAClC;AAAA,EAAA;AAGF,EAAAS,EAAU,MAAM;AACd,UAAMC,IAAa,IAAI,gBAAA;AAgBvB,YAfqB,YAAY;AAC/B,UAAI;AACF,QAAAP,EAAW,EAAI,GACfE,EAAS,IAAI;AACb,cAAM/B,IAAO,MAAMqC,EAAcf,GAAK,EAAE,SAAAE,GAAS,QAAQY,EAAW,QAAQ;AAC5E,QAAAT,EAAW3B,CAAI;AAAA,MACjB,SAASsC,GAAU;AACjB,YAAIA,EAAI,SAAS,aAAc;AAC/B,QAAAP,EAAS,EAAE,sBAAsB,CAAC,GAClC,QAAQ,MAAMO,CAAG;AAAA,MACnB,UAAA;AACE,QAAAT,EAAW,EAAK;AAAA,MAClB;AAAA,IACF,GAEA,GACO,MAAMO,EAAW,MAAA;AAAA,EAC1B,GAAG,CAACd,GAAKE,GAAS,CAAC,CAAC;AAGpB,QAAMe,IAAeC,EAAwB,oBAAI,KAAK,GAChDC,IAAsBpC,EAAY,MAAM;AAC5C,IAAAkC,EAAa,QAAQ,QAAQ,CAAAG,MAAYA,EAAA,CAAU;AAAA,EACrD,GAAG,CAAA,CAAE;AAGL,EAAAP,EAAU,MAAM;AACd,IAAAM,EAAA;AAAA,EACF,GAAG,CAACT,GAAUS,CAAmB,CAAC;AAGlC,QAAME,IAAiBtC,EAAY,MAAM;AACvC,IAAA4B,EAAY,CAAAW,MAAQA,MAAS,YAAY,WAAW,SAAS;AAAA,EAC/D,GAAG,CAAA,CAAE,GAGCC,IAAmBxC,EAAY,MAAsB;AAAA,IACzD;AAAA,MACE,OAAO;AAAA,QACL;AAAA,UACE,MAAM;AAAA,UACN,MAAM2B,MAAa,YAAY,gBAAAtB,EAACoC,GAAA,EAAK,WAAU,kBAAA,CAAkB,IAAK,gBAAApC,EAACqC,GAAA,EAAI,WAAU,kBAAA,CAAkB;AAAA,UACvG,SAAkC,EAAzBf,MAAa,YAAc,mBAAsB,iBAAN;AAAA,UACpD,QAAQW;AAAA,UACR,QAAQX,MAAa;AAAA,QAAA;AAAA,MACvB;AAAA,IACF;AAAA,EACF,GACC,CAACA,GAAU,GAAGW,CAAc,CAAC;AAWhC,SARAK,EAAoBzB,GAAK,OAAO;AAAA,IAC9B,kBAAAsB;AAAA,IACA,iBAAiB,CAACH,OAChBH,EAAa,QAAQ,IAAIG,CAAQ,GAC1B,MAAMH,EAAa,QAAQ,OAAOG,CAAQ;AAAA,EACnD,IACE,CAACG,CAAgB,CAAC,GAElBjB,IAEA,gBAAAlB,EAAC,SAAI,WAAU,sEACb,4BAAC,OAAA,EAAI,WAAU,qHAAoH,EAAA,CACrI,IAIAoB,IACK,gBAAApB,EAACuC,GAAA,EAAc,SAASnB,EAAA,CAAO,IAIpCE,MAAa,WAEb,gBAAAtB,EAAC,OAAA,EAAI,WAAU,0DACZ,UAAAwB,IACC,gBAAAxB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,yBAAyB,EAAE,QAAQwB,EAAA;AAAA,IAAW;AAAA,EAAA,IAGhD,gBAAAxB,EAAC,OAAA,EAAI,WAAU,iGACZ,aACH,GAEJ,IAMF,gBAAAA,EAAC,OAAA,EAAI,WAAU,6DACb,UAAA,gBAAAA;AAAA,IAACwC;AAAA,IAAA;AAAA,MACK,eAAe,CAACC,GAAWC,CAAU;AAAA,MACrC,eAAe,CAACC,GAAWC,CAAW;AAAA,MACtC,YAAY;AAAA,QACV,KAAK,EAAE,MAAAC,GAAM,QAAAC,GAAQ,WAAAC,GAAW,UAAAC,GAAU,GAAGC,KAAc;AACzD,gBAAMC,IAAQ,iBAAiB,KAAKH,KAAa,EAAE,GAC7CI,IAAa,OAAOH,CAAQ,EAAE,QAAQ,OAAO,EAAE;AAMrD,iBAHiBF,MAAW,CAACI,KAAS,CAACC,EAAW,SAAS;AAAA,CAAI,KAK3D,gBAAAnD;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACT,GAAGiD;AAAA,cAEH,UAAAD;AAAA,YAAA;AAAA,UAAA,IAMHE,sBACM9C,GAAA,EAAe,MAAM+C,GAAY,MAAMD,EAAM,CAAC,GAAG,IAKzD,gBAAAzC,EAAC,OAAA,EAAI,WAAU,mCACb,UAAA;AAAA,YAAA,gBAAAT,EAACG,GAAA,EAAmB,MAAMgD,EAAA,CAAY;AAAA,YACtC,gBAAAnD;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO,EAAE,UAAU,QAAQ,YAAY,MAAA;AAAA,gBAEvC,UAAA,gBAAAA,EAAC,QAAA,EAAK,WAAU,8CAA8C,UAAAgD,EAAA,CAAS;AAAA,cAAA;AAAA,YAAA;AAAA,UACzE,GACF;AAAA,QAEJ;AAAA,QACA,IAAI,CAAC,EAAE,UAAAA,EAAA,MACL,gBAAAhD,EAAC,MAAA,EAAG,WAAU,uFACX,UAAAgD,GACH;AAAA,QAEF,IAAI,CAAC,EAAE,UAAAA,EAAA,MACL,gBAAAhD,EAAC,MAAA,EAAG,WAAU,wEACX,UAAAgD,GACH;AAAA,QAEF,IAAI,CAAC,EAAE,UAAAA,EAAA,MACL,gBAAAhD,EAAC,MAAA,EAAG,WAAU,uEAAuE,UAAAgD,GAAS;AAAA,QAEhG,IAAI,CAAC,EAAE,UAAAA,EAAA,MACL,gBAAAhD,EAAC,MAAA,EAAG,WAAU,uEAAuE,UAAAgD,GAAS;AAAA,QAEhG,GAAG,CAAC,EAAE,UAAAA,EAAA,MACJ,gBAAAhD,EAAC,KAAA,EAAE,WAAU,8DAA8D,UAAAgD,GAAS;AAAA,QAEtF,GAAG,CAAC,EAAE,MAAAI,GAAM,UAAAJ,QACV,gBAAAhD;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAAoD;AAAA,YACA,WAAU;AAAA,YACV,QAAO;AAAA,YACP,KAAI;AAAA,YAEH,UAAAJ;AAAA,UAAA;AAAA,QAAA;AAAA,QAGL,IAAI,CAAC,EAAE,UAAAA,EAAA,MACL,gBAAAhD,EAAC,MAAA,EAAG,WAAU,uEAAuE,UAAAgD,GAAS;AAAA,QAEhG,IAAI,CAAC,EAAE,UAAAA,EAAA,MACL,gBAAAhD,EAAC,MAAA,EAAG,WAAU,0EAA0E,UAAAgD,GAAS;AAAA,QAEnG,IAAI,CAAC,EAAE,UAAAA,EAAA,MAAe,gBAAAhD,EAAC,MAAA,EAAG,WAAU,iBAAiB,UAAAgD,GAAS;AAAA,QAC9D,YAAY,CAAC,EAAE,UAAAA,EAAA,MACb,gBAAAhD,EAAC,cAAA,EAAW,WAAU,2FACnB,UAAAgD,GACH;AAAA,QAEF,OAAO,CAAC,EAAE,UAAAA,EAAA,MACR,gBAAAhD,EAAC,OAAA,EAAI,WAAU,0EACb,UAAA,gBAAAA,EAAC,SAAA,EAAM,WAAU,iDAAiD,UAAAgD,GAAS,GAC7E;AAAA,QAEF,OAAO,CAAC,EAAE,UAAAA,EAAA,MAAe,gBAAAhD,EAAC,SAAA,EAAM,WAAU,oBAAoB,UAAAgD,GAAS;AAAA,QACvE,OAAO,CAAC,EAAE,UAAAA,EAAA,MACR,gBAAAhD,EAAC,SAAA,EAAM,WAAU,qDAAqD,UAAAgD,GAAS;AAAA,QAEjF,IAAI,CAAC,EAAE,UAAAA,EAAA,MACL,gBAAAhD,EAAC,MAAA,EAAG,WAAU,gDAAgD,UAAAgD,GAAS;AAAA,QAEzE,IAAI,CAAC,EAAE,UAAAA,EAAA,MACL,gBAAAhD,EAAC,MAAA,EAAG,WAAU,uHACX,UAAAgD,GACH;AAAA,QAEF,IAAI,CAAC,EAAE,UAAAA,EAAA,MACL,gBAAAhD,EAAC,MAAA,EAAG,WAAU,uDAAuD,UAAAgD,GAAS;AAAA,QAEhF,IAAI,MAAM,gBAAAhD,EAAC,MAAA,EAAG,WAAU,2BAAA,CAA2B;AAAA,QACnD,KAAK,CAAC,EAAE,KAAAqD,GAAK,KAAAC,QACX,gBAAAtD;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,KAAAqD;AAAA,YACA,KAAAC;AAAA,YACA,WAAU;AAAA,UAAA;AAAA,QAAA;AAAA,QAGd,OAAO,CAAC,EAAE,MAAAC,GAAM,SAAAC,GAAS,GAAGP,QACtBM,MAAS,aAET,gBAAAvD;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAAwD;AAAA,YACA,UAAQ;AAAA,YACR,WAAU;AAAA,YACT,GAAGP;AAAA,UAAA;AAAA,QAAA,IAIH,gBAAAjD,EAAC,SAAA,EAAM,MAAAuD,GAAa,GAAGN,EAAA,CAAO;AAAA,QAEvC,QAAQ,CAAC,EAAE,UAAAD,EAAA,MACT,gBAAAhD,EAAC,UAAA,EAAO,WAAU,yCAAyC,UAAAgD,GAAS;AAAA,QAEtE,IAAI,CAAC,EAAE,UAAAA,EAAA,MAAe,gBAAAhD,EAAC,MAAA,EAAG,WAAU,cAAc,UAAAgD,GAAS;AAAA,QAC3D,KAAK,CAAC,EAAE,UAAAA,QACN,gBAAAhD,EAAC,OAAA,EAAI,WAAU,sCAAsC,UAAAgD,EAAA,CAAS;AAAA,MAAA;AAAA,MAIjE,UAAAhC;AAAA,IAAA;AAAA,EAAA,GAET;AAEJ,CAAC;"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { jsxs as L, jsx as m } from "react/jsx-runtime";
|
|
2
|
-
import { useState as M, useRef as l, useCallback as P, useEffect as j } from "react";
|
|
2
|
+
import { forwardRef as F, useState as M, useRef as l, useCallback as P, useEffect as j, useImperativeHandle as H } from "react";
|
|
3
3
|
import { init as N } from "pptx-preview";
|
|
4
|
-
import { u as
|
|
5
|
-
import { R as
|
|
6
|
-
const
|
|
7
|
-
const c =
|
|
4
|
+
import { u as I, a as q } from "./index-Cz23v-TW.mjs";
|
|
5
|
+
import { R as A } from "./RendererError-D5i8eSpN.mjs";
|
|
6
|
+
const K = F(({ url: y, tiled: a = !0 }, k) => {
|
|
7
|
+
const c = I(), B = q(), [b, w] = M(!0), [v, T] = M(null), [E, z] = M(0), n = l(null), s = l(null), x = l(null), p = l(null), d = l(null), R = l({ width: 0, height: 0 }), u = P(() => {
|
|
8
8
|
var t;
|
|
9
9
|
if (!n.current) return { width: 960, height: 540 };
|
|
10
|
-
const r = n.current.clientWidth, e = ((t = n.current.parentElement) == null ? void 0 : t.clientWidth) || 0, o = r > 100 ? r : e > 100 ? e : 300,
|
|
11
|
-
return { width: o, height:
|
|
10
|
+
const r = n.current.clientWidth, e = ((t = n.current.parentElement) == null ? void 0 : t.clientWidth) || 0, o = r > 100 ? r : e > 100 ? e : 300, f = Math.floor(o * 9 / 16);
|
|
11
|
+
return { width: o, height: f };
|
|
12
12
|
}, []), W = P(async () => {
|
|
13
13
|
if (!(!n.current || !p.current || E === 0))
|
|
14
14
|
try {
|
|
@@ -20,13 +20,13 @@ const $ = ({ url: g, tiled: f = !0 }) => {
|
|
|
20
20
|
n.current.innerHTML = "";
|
|
21
21
|
const r = u(), e = N(n.current, {
|
|
22
22
|
width: r.width,
|
|
23
|
-
height:
|
|
24
|
-
mode:
|
|
23
|
+
height: a ? r.height * E : r.height,
|
|
24
|
+
mode: a ? "list" : "slide"
|
|
25
25
|
});
|
|
26
26
|
s.current = e, await e.preview(p.current);
|
|
27
27
|
} catch {
|
|
28
28
|
}
|
|
29
|
-
}, [u,
|
|
29
|
+
}, [u, a, E]);
|
|
30
30
|
return j(() => {
|
|
31
31
|
if (!n.current) return;
|
|
32
32
|
let r = !0;
|
|
@@ -35,7 +35,7 @@ const $ = ({ url: g, tiled: f = !0 }) => {
|
|
|
35
35
|
r = !1, R.current = u();
|
|
36
36
|
return;
|
|
37
37
|
}
|
|
38
|
-
const o = u(),
|
|
38
|
+
const o = u(), f = R.current, t = Math.abs(f.width - o.width), i = Math.abs(f.height - o.height);
|
|
39
39
|
t < 10 && i < 10 || (R.current = o, d.current && clearTimeout(d.current), d.current = window.setTimeout(() => {
|
|
40
40
|
s.current && p.current && W();
|
|
41
41
|
}, 800));
|
|
@@ -46,7 +46,7 @@ const $ = ({ url: g, tiled: f = !0 }) => {
|
|
|
46
46
|
x.current && x.current.disconnect(), d.current && clearTimeout(d.current);
|
|
47
47
|
};
|
|
48
48
|
}, [u, W]), j(() => {
|
|
49
|
-
if (!
|
|
49
|
+
if (!y) return;
|
|
50
50
|
let r = !0, e = null;
|
|
51
51
|
const o = async () => {
|
|
52
52
|
if (n.current) {
|
|
@@ -54,7 +54,7 @@ const $ = ({ url: g, tiled: f = !0 }) => {
|
|
|
54
54
|
r && (T(c("pptx.timeout")), w(!1));
|
|
55
55
|
}, 3e4);
|
|
56
56
|
try {
|
|
57
|
-
const t = await
|
|
57
|
+
const t = await B(y, {
|
|
58
58
|
mode: "cors",
|
|
59
59
|
credentials: "omit",
|
|
60
60
|
redirect: "follow"
|
|
@@ -78,15 +78,15 @@ const $ = ({ url: g, tiled: f = !0 }) => {
|
|
|
78
78
|
} catch {
|
|
79
79
|
throw new Error(c("pptx.invalid_format"));
|
|
80
80
|
}
|
|
81
|
-
const
|
|
82
|
-
if (!
|
|
81
|
+
const g = D.slideCount;
|
|
82
|
+
if (!g || g === 0)
|
|
83
83
|
throw new Error(c("pptx.no_pages"));
|
|
84
84
|
if (D.destroy(), !r) return;
|
|
85
|
-
z(
|
|
85
|
+
z(g), n.current && (n.current.innerHTML = "");
|
|
86
86
|
const C = u(), _ = N(n.current, {
|
|
87
87
|
width: C.width,
|
|
88
|
-
height:
|
|
89
|
-
mode:
|
|
88
|
+
height: a ? C.height * g : C.height,
|
|
89
|
+
mode: a ? "list" : "slide"
|
|
90
90
|
});
|
|
91
91
|
s.current = _, await _.preview(i), e && (clearTimeout(e), e = null), r && w(!1);
|
|
92
92
|
} finally {
|
|
@@ -99,7 +99,7 @@ const $ = ({ url: g, tiled: f = !0 }) => {
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
|
-
},
|
|
102
|
+
}, f = setTimeout(() => {
|
|
103
103
|
requestAnimationFrame(() => {
|
|
104
104
|
requestAnimationFrame(() => {
|
|
105
105
|
o();
|
|
@@ -107,19 +107,21 @@ const $ = ({ url: g, tiled: f = !0 }) => {
|
|
|
107
107
|
});
|
|
108
108
|
}, 150);
|
|
109
109
|
return () => {
|
|
110
|
-
if (r = !1, clearTimeout(
|
|
110
|
+
if (r = !1, clearTimeout(f), e && clearTimeout(e), p.current = null, z(0), s.current)
|
|
111
111
|
try {
|
|
112
112
|
s.current.destroy();
|
|
113
113
|
} catch {
|
|
114
114
|
}
|
|
115
115
|
s.current = null;
|
|
116
116
|
};
|
|
117
|
-
}, [
|
|
117
|
+
}, [y, u, a]), H(k, () => ({
|
|
118
|
+
getToolbarGroups: () => []
|
|
119
|
+
}), []), /* @__PURE__ */ L("div", { className: "rfp-relative rfp-flex rfp-flex-col rfp-items-center rfp-w-full rfp-h-full", children: [
|
|
118
120
|
b && /* @__PURE__ */ m("div", { className: "rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-bg-surface-toolbar rfp-backdrop-blur-sm rfp-z-10", children: /* @__PURE__ */ L("div", { className: "rfp-text-center", children: [
|
|
119
121
|
/* @__PURE__ */ m("div", { className: "rfp-w-10 rfp-h-10 md:rfp-w-12 md:rfp-h-12 rfp-mx-auto rfp-mb-3 rfp-border-4 rfp-border-line-strong rfp-border-t-spinner-head rfp-rounded-full rfp-animate-spin" }),
|
|
120
122
|
/* @__PURE__ */ m("p", { className: "rfp-text-xs md:rfp-text-sm rfp-text-fg-secondary rfp-font-medium", children: c("pptx.loading") })
|
|
121
123
|
] }) }),
|
|
122
|
-
v && !b && /* @__PURE__ */ m(
|
|
124
|
+
v && !b && /* @__PURE__ */ m(A, { message: c("pptx.load_failed"), detail: v }),
|
|
123
125
|
!v && /* @__PURE__ */ m(
|
|
124
126
|
"div",
|
|
125
127
|
{
|
|
@@ -129,8 +131,8 @@ const $ = ({ url: g, tiled: f = !0 }) => {
|
|
|
129
131
|
}
|
|
130
132
|
)
|
|
131
133
|
] });
|
|
132
|
-
};
|
|
134
|
+
});
|
|
133
135
|
export {
|
|
134
|
-
|
|
136
|
+
K as PptxRenderer
|
|
135
137
|
};
|
|
136
|
-
//# sourceMappingURL=index-
|
|
138
|
+
//# sourceMappingURL=index-_B5marES.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-_B5marES.mjs","sources":["../../src/renderers/Pptx/index.tsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback, forwardRef, useImperativeHandle } from 'react';\nimport { init } from 'pptx-preview';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\nimport { RendererError } from '../RendererError';\nimport type { RendererHandle } from '../base.types';\n\ninterface PptxRendererProps {\n url: string;\n /** 是否平铺展示所有页面,默认 true */\n tiled?: boolean;\n}\n\nexport const PptxRenderer = forwardRef<RendererHandle, PptxRendererProps>(({ url, tiled = true }, ref) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [slideCount, setSlideCount] = useState(0);\n const containerRef = useRef<HTMLDivElement>(null);\n const previewerRef = useRef<ReturnType<typeof init> | null>(null);\n const resizeObserverRef = useRef<ResizeObserver | null>(null);\n const arrayBufferRef = useRef<ArrayBuffer | null>(null);\n const resizeTimeoutRef = useRef<number | null>(null);\n const lastDimensionsRef = useRef({ width: 0, height: 0 });\n\n // 计算容器尺寸,带回退逻辑\n const calculateDimensions = useCallback(() => {\n if (!containerRef.current) return { width: 960, height: 540 };\n const rawWidth = containerRef.current.clientWidth;\n const parentWidth = containerRef.current.parentElement?.clientWidth || 0;\n // 如果容器宽度太小,回退到父容器宽度或默认最小值\n const containerWidth = rawWidth > 100 ? rawWidth : (parentWidth > 100 ? parentWidth : 300);\n // 16:9 比例\n const height = Math.floor(containerWidth * 9 / 16);\n return { width: containerWidth, height };\n }, []);\n\n // 重新初始化预览器\n const reinitializePreviewer = useCallback(async () => {\n if (!containerRef.current || !arrayBufferRef.current || slideCount === 0) return;\n\n try {\n // 销毁旧的预览器\n if (previewerRef.current) {\n try {\n previewerRef.current.destroy();\n } catch {\n // 忽略销毁错误\n }\n }\n\n // 清空容器\n containerRef.current.innerHTML = '';\n\n // 获取当前容器尺寸\n const currentDimensions = calculateDimensions();\n\n // 初始化新的预览器,平铺模式下高度按页数计算\n const previewer = init(containerRef.current, {\n width: currentDimensions.width,\n height: tiled ? currentDimensions.height * slideCount : currentDimensions.height,\n mode: tiled ? 'list' : 'slide',\n });\n previewerRef.current = previewer;\n\n // 重新预览\n await previewer.preview(arrayBufferRef.current);\n } catch {\n // 重新初始化失败,静默处理\n }\n }, [calculateDimensions, tiled, slideCount]);\n\n // 监听容器尺寸变化\n useEffect(() => {\n if (!containerRef.current) return;\n\n let isInitialRender = true;\n\n const updateDimensions = () => {\n // 跳过初始渲染时的尺寸检查\n if (isInitialRender) {\n isInitialRender = false;\n lastDimensionsRef.current = calculateDimensions();\n return;\n }\n\n const newDimensions = calculateDimensions();\n\n // 检查尺寸是否真正变化(至少变化10px才触发)\n const lastDimensions = lastDimensionsRef.current;\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) {\n return;\n }\n\n // 更新最后的尺寸\n lastDimensionsRef.current = newDimensions;\n\n // 清除之前的定时器\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n\n // 防抖:800ms 后重新初始化预览器\n resizeTimeoutRef.current = window.setTimeout(() => {\n if (previewerRef.current && arrayBufferRef.current) {\n reinitializePreviewer();\n }\n }, 800);\n };\n\n // 创建 ResizeObserver\n resizeObserverRef.current = new ResizeObserver(() => {\n updateDimensions();\n });\n\n // 开始观察容器\n resizeObserverRef.current.observe(containerRef.current);\n\n return () => {\n if (resizeObserverRef.current) {\n resizeObserverRef.current.disconnect();\n }\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n };\n }, [calculateDimensions, reinitializePreviewer]);\n\n useEffect(() => {\n // 只有 URL 有效时才加载(避免空字符串或已 revoke 的 blob URL)\n if (!url) return;\n\n let isMounted = true;\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const loadPptx = async () => {\n if (!containerRef.current) return;\n\n setLoading(true);\n setError(null);\n\n // 设置30秒超时\n timeoutId = setTimeout(() => {\n if (isMounted) {\n setError(t('pptx.timeout'));\n setLoading(false);\n }\n }, 30000);\n\n try {\n // 获取文件,处理 CORS 和重定向\n const response = await fetcher(url, {\n mode: 'cors',\n credentials: 'omit',\n redirect: 'follow',\n });\n\n if (!response.ok) {\n if (response.status === 404) {\n throw new Error(t('pptx.not_found'));\n } else if (response.status === 403) {\n throw new Error('无权限访问此文件');\n } else if (response.status >= 500) {\n throw new Error('服务器错误,请稍后重试');\n } else {\n throw new Error(`文件加载失败 (${response.status})`);\n }\n }\n\n const arrayBuffer = await response.arrayBuffer();\n\n // 验证文件大小\n if (arrayBuffer.byteLength === 0) {\n throw new Error('文件为空');\n }\n\n arrayBufferRef.current = arrayBuffer;\n\n if (!isMounted) return;\n\n // 步骤 1: 创建隐藏容器,预处理获取 slideCount\n const hiddenContainer = document.createElement('div');\n hiddenContainer.style.cssText = 'position:absolute;left:-9999px;top:-9999px;visibility:hidden';\n document.body.appendChild(hiddenContainer);\n\n try {\n // 在隐藏容器中初始化临时预览器获取页数\n const tempPreviewer = init(hiddenContainer, {\n width: 100,\n height: 100,\n mode: 'slide',\n });\n\n try {\n await tempPreviewer.preview(arrayBuffer);\n } catch {\n throw new Error(t('pptx.invalid_format'));\n }\n\n const count = tempPreviewer.slideCount;\n\n if (!count || count === 0) {\n throw new Error(t('pptx.no_pages'));\n }\n\n // 销毁临时预览器\n tempPreviewer.destroy();\n\n if (!isMounted) return;\n\n // 保存 slideCount\n setSlideCount(count);\n\n // 步骤 2: 清空真实容器并初始化\n if (containerRef.current) {\n containerRef.current.innerHTML = '';\n }\n\n const currentDimensions = calculateDimensions();\n\n // 步骤 3: 初始化真实预览器,平铺模式下使用正确的总高度\n const previewer = init(containerRef.current, {\n width: currentDimensions.width,\n height: tiled ? currentDimensions.height * count : currentDimensions.height,\n mode: tiled ? 'list' : 'slide',\n });\n previewerRef.current = previewer;\n\n // 步骤 4: 预览 PPTX\n await previewer.preview(arrayBuffer);\n\n // 清除超时定时器\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n if (isMounted) {\n setLoading(false);\n }\n } finally {\n // 移除隐藏容器\n if (document.body.contains(hiddenContainer)) {\n document.body.removeChild(hiddenContainer);\n }\n }\n } catch (err) {\n // 清除超时定时器\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n if (isMounted) {\n let errorMsg = t('pptx.parse_failed');\n if (err instanceof Error) {\n errorMsg = err.message;\n } else if (typeof err === 'string') {\n errorMsg = err;\n }\n setError(errorMsg);\n setLoading(false);\n }\n }\n };\n\n // 延迟执行,使用 requestAnimationFrame 确保 DOM 已准备好\n const timer = setTimeout(() => {\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n loadPptx();\n });\n });\n }, 150);\n\n // 清理函数\n return () => {\n isMounted = false;\n clearTimeout(timer);\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n arrayBufferRef.current = null;\n setSlideCount(0);\n if (previewerRef.current) {\n try {\n previewerRef.current.destroy();\n } catch {\n // 忽略销毁错误\n }\n }\n previewerRef.current = null;\n };\n }, [url, calculateDimensions, tiled]);\n\n // 暴露接口给父组件\n useImperativeHandle(ref, () => ({\n getToolbarGroups: () => [],\n }), []);\n\n return (\n <div className=\"rfp-relative rfp-flex rfp-flex-col rfp-items-center rfp-w-full rfp-h-full\">\n {/* 加载状态 - 绝对定位覆盖 */}\n {loading && (\n <div className=\"rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-bg-surface-toolbar rfp-backdrop-blur-sm rfp-z-10\">\n <div className=\"rfp-text-center\">\n <div className=\"rfp-w-10 rfp-h-10 md:rfp-w-12 md:rfp-h-12 rfp-mx-auto rfp-mb-3 rfp-border-4 rfp-border-line-strong rfp-border-t-spinner-head rfp-rounded-full rfp-animate-spin\" />\n <p className=\"rfp-text-xs md:rfp-text-sm rfp-text-fg-secondary rfp-font-medium\">{t('pptx.loading')}</p>\n </div>\n </div>\n )}\n\n {/* 错误状态 - 绝对定位覆盖 */}\n {error && !loading && (\n <RendererError message={t('pptx.load_failed')} detail={error} />\n )}\n\n {/* PPT 容器 - 仅在非错误状态下渲染 */}\n {!error && (\n <div\n ref={containerRef}\n className=\"pptx-wrapper rfp-w-full rfp-max-w-full md:rfp-max-w-6xl\"\n style={{ opacity: loading ? 0 : 1 }}\n />\n )}\n </div>\n );\n});\n"],"names":["PptxRenderer","forwardRef","url","tiled","ref","t","useTranslator","fetcher","useFetcher","loading","setLoading","useState","error","setError","slideCount","setSlideCount","containerRef","useRef","previewerRef","resizeObserverRef","arrayBufferRef","resizeTimeoutRef","lastDimensionsRef","calculateDimensions","useCallback","rawWidth","parentWidth","_a","containerWidth","height","reinitializePreviewer","currentDimensions","previewer","init","useEffect","isInitialRender","updateDimensions","newDimensions","lastDimensions","widthDiff","heightDiff","isMounted","timeoutId","loadPptx","response","arrayBuffer","hiddenContainer","tempPreviewer","count","err","errorMsg","timer","useImperativeHandle","jsxs","jsx","RendererError"],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { useState as m, useEffect as d } from "react";
|
|
2
|
+
import { codeToHtml as h } from "shiki";
|
|
3
|
+
import { b as p } from "./index-Cz23v-TW.mjs";
|
|
4
|
+
function y(e, s) {
|
|
5
|
+
const o = p(), [r, n] = m(""), [i, c] = m([]), [u, l] = m(!0);
|
|
6
|
+
return d(() => {
|
|
7
|
+
let a = !1;
|
|
8
|
+
return l(!0), h(e, {
|
|
9
|
+
lang: s,
|
|
10
|
+
theme: o === "light" ? "github-light" : "dark-plus",
|
|
11
|
+
transformers: [{
|
|
12
|
+
name: "line-numbers",
|
|
13
|
+
line(t, f) {
|
|
14
|
+
t.properties["data-line"] = f, this.addClassToHast(t, "line");
|
|
15
|
+
}
|
|
16
|
+
}]
|
|
17
|
+
}).then((t) => {
|
|
18
|
+
a || (n(t), c(g(t)), l(!1));
|
|
19
|
+
}).catch(() => {
|
|
20
|
+
a || (n(""), c([]), l(!1));
|
|
21
|
+
}), () => {
|
|
22
|
+
a = !0;
|
|
23
|
+
};
|
|
24
|
+
}, [e, s, o]), { html: r, lineHtmls: i, loading: u };
|
|
25
|
+
}
|
|
26
|
+
function g(e) {
|
|
27
|
+
if (typeof window > "u" || !e) return [];
|
|
28
|
+
const r = new DOMParser().parseFromString(e, "text/html").querySelector("code");
|
|
29
|
+
if (!r) return [];
|
|
30
|
+
const n = r.querySelectorAll(".line");
|
|
31
|
+
return Array.from(n).map((i) => i.innerHTML);
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
y as u
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=useShikiHighlight-Bbs8Fbqs.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useShikiHighlight-Bbs8Fbqs.mjs","sources":["../../src/hooks/useShikiHighlight.ts"],"sourcesContent":["import { useState, useEffect } from 'react';\nimport { codeToHtml, type ShikiTransformer } from 'shiki';\nimport { useResolvedTheme } from '../ThemeContext';\n\n/**\n * 用 shiki 把代码高亮成 HTML(与 vue-file-preview 同引擎、同主题,保证两端视觉一致)。\n *\n * - dark 主题用 `dark-plus`(VSCode Dark Plus)\n * - light 主题用 `github-light`(GitHub Light)\n *\n * shiki 输出的 <pre> 自带 inline 背景/前景色,主题切换时必须重新高亮,\n * 因此 resolvedTheme 进入依赖数组。\n *\n * @returns\n * - `html`: 完整的 shiki 输出 HTML(含 pre/code 包裹),markdown 等场景使用\n * - `lineHtmls`: 拆分后的每一行 HTML(用于双列行号布局)\n * - `loading`: 是否正在高亮\n */\nexport function useShikiHighlight(\n code: string,\n lang: string,\n): { html: string; lineHtmls: string[]; loading: boolean } {\n const resolvedTheme = useResolvedTheme();\n const [html, setHtml] = useState('');\n const [lineHtmls, setLineHtmls] = useState<string[]>([]);\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n let cancelled = false;\n setLoading(true);\n\n const lineNumbersTransformer: ShikiTransformer = {\n name: 'line-numbers',\n line(node, line) {\n node.properties['data-line'] = line;\n this.addClassToHast(node, 'line');\n },\n };\n\n codeToHtml(code, {\n lang,\n theme: resolvedTheme === 'light' ? 'github-light' : 'dark-plus',\n transformers: [lineNumbersTransformer],\n })\n .then((out) => {\n if (!cancelled) {\n setHtml(out);\n setLineHtmls(extractLines(out));\n setLoading(false);\n }\n })\n .catch(() => {\n if (!cancelled) {\n setHtml('');\n setLineHtmls([]);\n setLoading(false);\n }\n });\n return () => {\n cancelled = true;\n };\n }, [code, lang, resolvedTheme]);\n\n return { html, lineHtmls, loading };\n}\n\n/**\n * 从 shiki 输出的 HTML 中提取每一行的内容(保留高亮标签)\n */\nfunction extractLines(html: string): string[] {\n if (typeof window === 'undefined' || !html) return [];\n const parser = new DOMParser();\n const doc = parser.parseFromString(html, 'text/html');\n const codeElement = doc.querySelector('code');\n if (!codeElement) return [];\n const lineElements = codeElement.querySelectorAll('.line');\n return Array.from(lineElements).map((line) => line.innerHTML);\n}\n"],"names":["useShikiHighlight","code","lang","resolvedTheme","useResolvedTheme","html","setHtml","useState","lineHtmls","setLineHtmls","loading","setLoading","useEffect","cancelled","codeToHtml","node","line","out","extractLines","codeElement","lineElements"],"mappings":";;;AAkBO,SAASA,EACdC,GACAC,GACyD;AACzD,QAAMC,IAAgBC,EAAA,GAChB,CAACC,GAAMC,CAAO,IAAIC,EAAS,EAAE,GAC7B,CAACC,GAAWC,CAAY,IAAIF,EAAmB,CAAA,CAAE,GACjD,CAACG,GAASC,CAAU,IAAIJ,EAAS,EAAI;AAE3C,SAAAK,EAAU,MAAM;AACd,QAAIC,IAAY;AAChB,WAAAF,EAAW,EAAI,GAUfG,EAAWb,GAAM;AAAA,MACf,MAAAC;AAAA,MACA,OAAOC,MAAkB,UAAU,iBAAiB;AAAA,MACpD,cAAc,CAXiC;AAAA,QAC/C,MAAM;AAAA,QACN,KAAKY,GAAMC,GAAM;AACf,UAAAD,EAAK,WAAW,WAAW,IAAIC,GAC/B,KAAK,eAAeD,GAAM,MAAM;AAAA,QAClC;AAAA,MAAA,CAMqC;AAAA,IAAA,CACtC,EACE,KAAK,CAACE,MAAQ;AACb,MAAKJ,MACHP,EAAQW,CAAG,GACXR,EAAaS,EAAaD,CAAG,CAAC,GAC9BN,EAAW,EAAK;AAAA,IAEpB,CAAC,EACA,MAAM,MAAM;AACX,MAAKE,MACHP,EAAQ,EAAE,GACVG,EAAa,CAAA,CAAE,GACfE,EAAW,EAAK;AAAA,IAEpB,CAAC,GACI,MAAM;AACX,MAAAE,IAAY;AAAA,IACd;AAAA,EACF,GAAG,CAACZ,GAAMC,GAAMC,CAAa,CAAC,GAEvB,EAAE,MAAAE,GAAM,WAAAG,GAAW,SAAAE,EAAA;AAC5B;AAKA,SAASQ,EAAab,GAAwB;AAC5C,MAAI,OAAO,SAAW,OAAe,CAACA,UAAa,CAAA;AAGnD,QAAMc,IAFS,IAAI,UAAA,EACA,gBAAgBd,GAAM,WAAW,EAC5B,cAAc,MAAM;AAC5C,MAAI,CAACc,EAAa,QAAO,CAAA;AACzB,QAAMC,IAAeD,EAAY,iBAAiB,OAAO;AACzD,SAAO,MAAM,KAAKC,CAAY,EAAE,IAAI,CAACJ,MAASA,EAAK,SAAS;AAC9D;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilePreviewToolbar.d.ts","sourceRoot":"","sources":["../../../src/components/preview/FilePreviewToolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAGlE,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,YAAY,EAAE,CAAC;IAC3B,CAAC,EAAE,UAAU,CAAC;IACd,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"FilePreviewToolbar.d.ts","sourceRoot":"","sources":["../../../src/components/preview/FilePreviewToolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAGlE,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,YAAY,EAAE,CAAC;IAC3B,CAAC,EAAE,UAAU,CAAC;IACd,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CA4FhE,CAAC"}
|
|
@@ -4,11 +4,13 @@ export interface ToolbarButtonProps {
|
|
|
4
4
|
label: string;
|
|
5
5
|
onClick: () => void;
|
|
6
6
|
disabled?: boolean;
|
|
7
|
+
/** 激活状态:true 时按钮显示高亮样式 */
|
|
8
|
+
active?: boolean;
|
|
7
9
|
ariaKeyshortcuts?: string;
|
|
8
10
|
}
|
|
9
11
|
/**
|
|
10
12
|
* 工具栏按钮组件
|
|
11
|
-
* 支持 tooltip、disabled
|
|
13
|
+
* 支持 tooltip、disabled 状态、active 高亮和 aria 属性
|
|
12
14
|
*/
|
|
13
15
|
export declare const ToolbarButton: React.FC<ToolbarButtonProps>;
|
|
14
16
|
//# sourceMappingURL=ToolbarButton.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolbarButton.d.ts","sourceRoot":"","sources":["../../../src/components/preview/ToolbarButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,
|
|
1
|
+
{"version":3,"file":"ToolbarButton.d.ts","sourceRoot":"","sources":["../../../src/components/preview/ToolbarButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAkCtD,CAAC"}
|
package/lib/hooks/index.d.ts
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
export * from './types';
|
|
2
|
-
export * from './rendererReducer';
|
|
3
|
-
export * from './useFilePreviewState';
|
|
4
1
|
export * from './useKeyboardNavigation';
|
|
5
|
-
export * from './useBookRenderer';
|
|
6
2
|
export * from './useThemeMode';
|
|
7
|
-
export * from './useImageAutoFit';
|
|
8
|
-
export * from './useToolbarConfig';
|
|
9
3
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/hooks/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,gBAAgB,CAAC"}
|
|
@@ -8,11 +8,13 @@
|
|
|
8
8
|
* 因此 resolvedTheme 进入依赖数组。
|
|
9
9
|
*
|
|
10
10
|
* @returns
|
|
11
|
-
* - `html`:
|
|
11
|
+
* - `html`: 完整的 shiki 输出 HTML(含 pre/code 包裹),markdown 等场景使用
|
|
12
|
+
* - `lineHtmls`: 拆分后的每一行 HTML(用于双列行号布局)
|
|
12
13
|
* - `loading`: 是否正在高亮
|
|
13
14
|
*/
|
|
14
15
|
export declare function useShikiHighlight(code: string, lang: string): {
|
|
15
16
|
html: string;
|
|
17
|
+
lineHtmls: string[];
|
|
16
18
|
loading: boolean;
|
|
17
19
|
};
|
|
18
20
|
//# sourceMappingURL=useShikiHighlight.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useShikiHighlight.d.ts","sourceRoot":"","sources":["../../src/hooks/useShikiHighlight.ts"],"names":[],"mappings":"AAIA
|
|
1
|
+
{"version":3,"file":"useShikiHighlight.d.ts","sourceRoot":"","sources":["../../src/hooks/useShikiHighlight.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CA2CzD"}
|