@eternalheart/react-file-preview 1.3.9 → 1.3.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/README.md +10 -0
  2. package/README.zh-CN.md +10 -0
  3. package/lib/FilePreviewContent.d.ts.map +1 -1
  4. package/lib/RequestContext.d.ts +1 -1
  5. package/lib/RequestContext.d.ts.map +1 -1
  6. package/lib/chunks/RendererError-BH6fzLrN.mjs +15 -0
  7. package/lib/chunks/RendererError-BH6fzLrN.mjs.map +1 -0
  8. package/lib/chunks/avifLoader-BP3fgcMm-BnpxLhxp.mjs +56 -0
  9. package/lib/chunks/avifLoader-BP3fgcMm-BnpxLhxp.mjs.map +1 -0
  10. package/lib/chunks/heicLoader-CH_raQNn-1fBLaICM.mjs +37 -0
  11. package/lib/chunks/heicLoader-CH_raQNn-1fBLaICM.mjs.map +1 -0
  12. package/lib/chunks/index-B57rEPin.mjs +54 -0
  13. package/lib/chunks/index-B57rEPin.mjs.map +1 -0
  14. package/lib/chunks/index-BCuRRLYt.mjs +222 -0
  15. package/lib/chunks/index-BCuRRLYt.mjs.map +1 -0
  16. package/lib/chunks/{index-BSD3w5eG.mjs → index-BJ6vTNxc.mjs} +76 -75
  17. package/lib/chunks/index-BJ6vTNxc.mjs.map +1 -0
  18. package/lib/chunks/index-BYdqrqnR.mjs +161 -0
  19. package/lib/chunks/index-BYdqrqnR.mjs.map +1 -0
  20. package/lib/chunks/index-BiyghBxu.mjs +136 -0
  21. package/lib/chunks/index-BiyghBxu.mjs.map +1 -0
  22. package/lib/chunks/{index-DdOEWhrk.mjs → index-C8CyS_sj.mjs} +66 -63
  23. package/lib/chunks/index-C8CyS_sj.mjs.map +1 -0
  24. package/lib/chunks/index-C8OrFLd5.mjs +594 -0
  25. package/lib/chunks/index-C8OrFLd5.mjs.map +1 -0
  26. package/lib/chunks/{index-DGuiWJr7.mjs → index-CCkHAeLh.mjs} +40 -37
  27. package/lib/chunks/index-CCkHAeLh.mjs.map +1 -0
  28. package/lib/chunks/index-CdmkF0CO.mjs +105 -0
  29. package/lib/chunks/index-CdmkF0CO.mjs.map +1 -0
  30. package/lib/chunks/index-CuAALtwC.mjs +2299 -0
  31. package/lib/chunks/index-CuAALtwC.mjs.map +1 -0
  32. package/lib/chunks/index-D660ENHx.mjs +114 -0
  33. package/lib/chunks/index-D660ENHx.mjs.map +1 -0
  34. package/lib/chunks/{index-DV5Jd7Qe.mjs → index-DBEG73K1.mjs} +79 -78
  35. package/lib/chunks/index-DBEG73K1.mjs.map +1 -0
  36. package/lib/chunks/index-DaFlk9dd.mjs +13097 -0
  37. package/lib/chunks/index-DaFlk9dd.mjs.map +1 -0
  38. package/lib/chunks/index-_mP0FkqE.mjs +113 -0
  39. package/lib/chunks/index-_mP0FkqE.mjs.map +1 -0
  40. package/lib/chunks/{index-U3w45GW8.mjs → index-nLTQXCV7.mjs} +84 -82
  41. package/lib/chunks/index-nLTQXCV7.mjs.map +1 -0
  42. package/lib/chunks/index-nVblatyi.mjs +55 -0
  43. package/lib/chunks/index-nVblatyi.mjs.map +1 -0
  44. package/lib/chunks/{index-zEVVgWCH.mjs → index-ow-nGpuu.mjs} +99 -98
  45. package/lib/chunks/index-ow-nGpuu.mjs.map +1 -0
  46. package/lib/chunks/index-qOC5xQyK.mjs +96 -0
  47. package/lib/chunks/index-qOC5xQyK.mjs.map +1 -0
  48. package/lib/chunks/index-rUfsiVR8.mjs +12335 -0
  49. package/lib/chunks/index-rUfsiVR8.mjs.map +1 -0
  50. package/lib/chunks/jp2Loader-Bn-qPMbD-Bn-qPMbD.mjs +122 -0
  51. package/lib/chunks/jp2Loader-Bn-qPMbD-Bn-qPMbD.mjs.map +1 -0
  52. package/lib/chunks/psdLoader-Doxw3mWm-DVOGFSlh.mjs +73 -0
  53. package/lib/chunks/psdLoader-Doxw3mWm-DVOGFSlh.mjs.map +1 -0
  54. package/lib/chunks/rawLoader-0mLvxCNp-CJmERiK7.mjs +82 -0
  55. package/lib/chunks/rawLoader-0mLvxCNp-CJmERiK7.mjs.map +1 -0
  56. package/lib/chunks/tiffLoader-CTFKVLqJ-B84NfwhR.mjs +60 -0
  57. package/lib/chunks/tiffLoader-CTFKVLqJ-B84NfwhR.mjs.map +1 -0
  58. package/lib/chunks/{useShikiHighlight-DzEAK0S7.mjs → useShikiHighlight-ClbUXJ2p.mjs} +3 -3
  59. package/lib/chunks/{useShikiHighlight-DzEAK0S7.mjs.map → useShikiHighlight-ClbUXJ2p.mjs.map} +1 -1
  60. package/lib/index.cjs +33 -20
  61. package/lib/index.cjs.map +1 -1
  62. package/lib/index.css +1 -1
  63. package/lib/index.d.ts +1 -0
  64. package/lib/index.d.ts.map +1 -1
  65. package/lib/index.mjs +14 -13
  66. package/lib/renderers/Audio/index.d.ts.map +1 -1
  67. package/lib/renderers/Csv/index.d.ts.map +1 -1
  68. package/lib/renderers/Docx/index.d.ts.map +1 -1
  69. package/lib/renderers/Epub/index.d.ts.map +1 -1
  70. package/lib/renderers/Font/index.d.ts +6 -0
  71. package/lib/renderers/Font/index.d.ts.map +1 -0
  72. package/lib/renderers/Image/index.d.ts +2 -0
  73. package/lib/renderers/Image/index.d.ts.map +1 -1
  74. package/lib/renderers/Json/index.d.ts.map +1 -1
  75. package/lib/renderers/Markdown/index.d.ts.map +1 -1
  76. package/lib/renderers/Mobi/index.d.ts.map +1 -1
  77. package/lib/renderers/Msg/index.d.ts.map +1 -1
  78. package/lib/renderers/Pdf/index.d.ts +0 -1
  79. package/lib/renderers/Pdf/index.d.ts.map +1 -1
  80. package/lib/renderers/Pptx/index.d.ts.map +1 -1
  81. package/lib/renderers/RendererError.d.ts +8 -0
  82. package/lib/renderers/RendererError.d.ts.map +1 -0
  83. package/lib/renderers/Subtitle/index.d.ts.map +1 -1
  84. package/lib/renderers/Text/index.d.ts.map +1 -1
  85. package/lib/renderers/Video/index.d.ts +1 -0
  86. package/lib/renderers/Video/index.d.ts.map +1 -1
  87. package/lib/renderers/Xlsx/index.d.ts.map +1 -1
  88. package/lib/renderers/Xml/index.d.ts.map +1 -1
  89. package/lib/renderers/Zip/index.d.ts.map +1 -1
  90. package/lib/renderers/lazy.d.ts +2 -0
  91. package/lib/renderers/lazy.d.ts.map +1 -1
  92. package/lib/utils/pdfConfig.d.ts +2 -2
  93. package/lib/utils/pdfConfig.d.ts.map +1 -1
  94. package/package.json +14 -5
  95. package/lib/chunks/index-B-H9HQiI.mjs +0 -110
  96. package/lib/chunks/index-B-H9HQiI.mjs.map +0 -1
  97. package/lib/chunks/index-BGeyzo6u.mjs +0 -96
  98. package/lib/chunks/index-BGeyzo6u.mjs.map +0 -1
  99. package/lib/chunks/index-BNUiNUWa.mjs +0 -103
  100. package/lib/chunks/index-BNUiNUWa.mjs.map +0 -1
  101. package/lib/chunks/index-BSD3w5eG.mjs.map +0 -1
  102. package/lib/chunks/index-BcBe6KW7.mjs +0 -99
  103. package/lib/chunks/index-BcBe6KW7.mjs.map +0 -1
  104. package/lib/chunks/index-BdYkTSTt.mjs +0 -51
  105. package/lib/chunks/index-BdYkTSTt.mjs.map +0 -1
  106. package/lib/chunks/index-BqEuP_8r.mjs +0 -152
  107. package/lib/chunks/index-BqEuP_8r.mjs.map +0 -1
  108. package/lib/chunks/index-Bv93wiEK.mjs +0 -2031
  109. package/lib/chunks/index-Bv93wiEK.mjs.map +0 -1
  110. package/lib/chunks/index-CKirCT35.mjs +0 -52
  111. package/lib/chunks/index-CKirCT35.mjs.map +0 -1
  112. package/lib/chunks/index-CgV8T0G5.mjs +0 -257
  113. package/lib/chunks/index-CgV8T0G5.mjs.map +0 -1
  114. package/lib/chunks/index-D8GtNeDn.mjs +0 -116
  115. package/lib/chunks/index-D8GtNeDn.mjs.map +0 -1
  116. package/lib/chunks/index-DGuiWJr7.mjs.map +0 -1
  117. package/lib/chunks/index-DV5Jd7Qe.mjs.map +0 -1
  118. package/lib/chunks/index-DdOEWhrk.mjs.map +0 -1
  119. package/lib/chunks/index-DmepcY31.mjs +0 -96
  120. package/lib/chunks/index-DmepcY31.mjs.map +0 -1
  121. package/lib/chunks/index-U3w45GW8.mjs.map +0 -1
  122. package/lib/chunks/index-r3q2xCCI.mjs +0 -129
  123. package/lib/chunks/index-r3q2xCCI.mjs.map +0 -1
  124. package/lib/chunks/index-zEVVgWCH.mjs.map +0 -1
@@ -1,257 +0,0 @@
1
- import { jsx as e, jsxs as t } from "react/jsx-runtime";
2
- import { useState as D, useEffect as J } from "react";
3
- import O from "@kenjiuno/msgreader";
4
- import { User as Q, Users as E, Calendar as q, Clock as U, Tag as G, Mail as V, Paperclip as Y, Hash as Z } from "lucide-react";
5
- import { u as ee, a as te } from "./index-Bv93wiEK.mjs";
6
- function P(l, d) {
7
- return l ? l.filter((o) => o.recipType === d).map((o) => {
8
- const f = o.name || "", p = o.smtpAddress || o.email || "";
9
- return f && p && f !== p ? `${f} <${p}>` : f || p;
10
- }).filter(Boolean).join("; ") : "";
11
- }
12
- function S(l) {
13
- if (!l) return "";
14
- try {
15
- const d = new Date(l);
16
- return isNaN(d.getTime()) ? l : d.toLocaleString();
17
- } catch {
18
- return l;
19
- }
20
- }
21
- function le(l, d) {
22
- if (l.bodyHtml)
23
- return l.bodyHtml;
24
- if (l.html)
25
- try {
26
- return new TextDecoder("utf-8").decode(l.html);
27
- } catch {
28
- }
29
- return l.body ? `<pre style="white-space: pre-wrap; word-wrap: break-word; font-family: system-ui, sans-serif;">${l.body.replace(/&/g, "&amp;").replace(/\x3c/g, "&lt;").replace(/>/g, "&gt;")}</pre>` : `<p style="color: #999;">${d}</p>`;
30
- }
31
- function se(l) {
32
- return l ? {
33
- "IPM.Note": "Email",
34
- "IPM.Note.SMIME": "Encrypted Email",
35
- "IPM.Note.SMIME.MultipartSigned": "Signed Email",
36
- "IPM.Appointment": "Appointment",
37
- "IPM.Schedule.Meeting.Request": "Meeting Request",
38
- "IPM.Schedule.Meeting.Canceled": "Meeting Cancellation",
39
- "IPM.Contact": "Contact",
40
- "IPM.Task": "Task",
41
- "IPM.StickyNote": "Sticky Note"
42
- }[l] || l : "";
43
- }
44
- const n = {
45
- flexShrink: 0,
46
- color: "#6b7280",
47
- fontWeight: 500,
48
- marginRight: "8px",
49
- whiteSpace: "nowrap"
50
- }, i = {
51
- display: "flex",
52
- alignItems: "flex-start",
53
- gap: "8px",
54
- padding: "6px 0"
55
- }, r = {
56
- flexShrink: 0,
57
- display: "flex",
58
- alignItems: "center",
59
- height: "1.4em"
60
- }, a = {
61
- flexShrink: 0,
62
- color: "#9ca3af"
63
- }, c = {
64
- color: "#111827",
65
- wordBreak: "break-word",
66
- flex: 1
67
- }, oe = ({ url: l }) => {
68
- const d = ee(), o = te(), [f, p] = D(!0), [H, B] = D(null), [s, R] = D(null);
69
- if (J(() => {
70
- (async () => {
71
- p(!0), B(null), R(null);
72
- try {
73
- const m = await o(l);
74
- if (!m.ok)
75
- throw new Error("文件加载失败");
76
- const k = await m.arrayBuffer(), M = new O(k).getFileData();
77
- R(M);
78
- } catch (m) {
79
- console.error("MSG 解析错误:", m), B(d("msg.parse_failed"));
80
- } finally {
81
- p(!1);
82
- }
83
- })();
84
- }, [l]), f)
85
- return /* @__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" }) });
86
- if (H || !s)
87
- return /* @__PURE__ */ e("div", { className: "rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full", children: /* @__PURE__ */ e("div", { className: "rfp-text-fg-secondary rfp-text-center", children: /* @__PURE__ */ e("p", { className: "rfp-text-lg", children: H || d("msg.parse_failed_short") }) }) });
88
- const C = P(s.recipients, "to"), L = P(s.recipients, "cc"), $ = P(s.recipients, "bcc"), g = s.senderName || "", v = s.senderSmtpAddress || s.senderEmail || "", F = g && v && g !== v ? `${g} <${v}>` : g || v, x = S(s.clientSubmitTime), u = S(s.messageDeliveryTime), j = S(s.creationTime), b = S(s.lastModificationTime), K = s.subject || "(无主题)", z = (s.attachments || []).filter((h) => !h.attachmentHidden), X = le(s, d("msg.empty_body")), T = se(s.messageClass), A = s.messageId || "", w = s, I = typeof w.importance == "number" ? w.importance : void 0, _ = I === 2 ? "High" : I === 0 ? "Low" : "", N = typeof w.sensitivity == "number" ? w.sensitivity : void 0, W = N !== void 0 && N !== 0 && {
89
- 0: "Normal",
90
- 1: "Personal",
91
- 2: "Private",
92
- 3: "Confidential"
93
- }[N] || "";
94
- return /* @__PURE__ */ e(
95
- "div",
96
- {
97
- className: "rfp-w-full rfp-h-full rfp-overflow-auto",
98
- style: { background: "white" },
99
- children: /* @__PURE__ */ t(
100
- "div",
101
- {
102
- style: {
103
- width: "100%",
104
- background: "white",
105
- minHeight: "100%"
106
- },
107
- children: [
108
- /* @__PURE__ */ t("div", { style: { borderBottom: "1px solid #e5e7eb", padding: "clamp(12px, 3vw, 24px) clamp(16px, 3vw, 28px)", background: "#f9fafb" }, children: [
109
- /* @__PURE__ */ e("h2", { style: { margin: "0 0 16px 0", fontSize: "clamp(16px, 2.5vw, 20px)", fontWeight: 600, color: "#111827", lineHeight: 1.4 }, children: K }),
110
- /* @__PURE__ */ t("div", { style: { display: "flex", flexDirection: "column", fontSize: "clamp(12px, 1.8vw, 14px)", color: "#4b5563" }, children: [
111
- F && /* @__PURE__ */ t("div", { style: i, children: [
112
- /* @__PURE__ */ e("span", { style: r, children: /* @__PURE__ */ e(Q, { size: 16, style: a }) }),
113
- /* @__PURE__ */ t("div", { style: { display: "flex", flex: 1 }, children: [
114
- /* @__PURE__ */ e("span", { style: n, children: "From" }),
115
- /* @__PURE__ */ e("span", { style: c, children: F })
116
- ] })
117
- ] }),
118
- C && /* @__PURE__ */ t("div", { style: i, children: [
119
- /* @__PURE__ */ e("span", { style: r, children: /* @__PURE__ */ e(E, { size: 16, style: a }) }),
120
- /* @__PURE__ */ t("div", { style: { display: "flex", flex: 1 }, children: [
121
- /* @__PURE__ */ e("span", { style: n, children: "To" }),
122
- /* @__PURE__ */ e("span", { style: c, children: C })
123
- ] })
124
- ] }),
125
- L && /* @__PURE__ */ t("div", { style: i, children: [
126
- /* @__PURE__ */ e("span", { style: r, children: /* @__PURE__ */ e(E, { size: 16, style: a }) }),
127
- /* @__PURE__ */ t("div", { style: { display: "flex", flex: 1 }, children: [
128
- /* @__PURE__ */ e("span", { style: n, children: "Cc" }),
129
- /* @__PURE__ */ e("span", { style: c, children: L })
130
- ] })
131
- ] }),
132
- $ && /* @__PURE__ */ t("div", { style: i, children: [
133
- /* @__PURE__ */ e("span", { style: r, children: /* @__PURE__ */ e(E, { size: 16, style: a }) }),
134
- /* @__PURE__ */ t("div", { style: { display: "flex", flex: 1 }, children: [
135
- /* @__PURE__ */ e("span", { style: n, children: "Bcc" }),
136
- /* @__PURE__ */ e("span", { style: c, children: $ })
137
- ] })
138
- ] }),
139
- x && /* @__PURE__ */ t("div", { style: i, children: [
140
- /* @__PURE__ */ e("span", { style: r, children: /* @__PURE__ */ e(q, { size: 16, style: a }) }),
141
- /* @__PURE__ */ t("div", { style: { display: "flex", flex: 1 }, children: [
142
- /* @__PURE__ */ e("span", { style: n, children: "Sent" }),
143
- /* @__PURE__ */ e("span", { style: c, children: x })
144
- ] })
145
- ] }),
146
- u && u !== x && /* @__PURE__ */ t("div", { style: i, children: [
147
- /* @__PURE__ */ e("span", { style: r, children: /* @__PURE__ */ e(U, { size: 16, style: a }) }),
148
- /* @__PURE__ */ t("div", { style: { display: "flex", flex: 1 }, children: [
149
- /* @__PURE__ */ e("span", { style: n, children: "Received" }),
150
- /* @__PURE__ */ e("span", { style: c, children: u })
151
- ] })
152
- ] }),
153
- !x && !u && j && /* @__PURE__ */ t("div", { style: i, children: [
154
- /* @__PURE__ */ e("span", { style: r, children: /* @__PURE__ */ e(q, { size: 16, style: a }) }),
155
- /* @__PURE__ */ t("div", { style: { display: "flex", flex: 1 }, children: [
156
- /* @__PURE__ */ e("span", { style: n, children: "Date" }),
157
- /* @__PURE__ */ e("span", { style: c, children: j })
158
- ] })
159
- ] }),
160
- _ && /* @__PURE__ */ t("div", { style: i, children: [
161
- /* @__PURE__ */ e("span", { style: r, children: /* @__PURE__ */ e(G, { size: 16, style: a }) }),
162
- /* @__PURE__ */ t("div", { style: { display: "flex", flex: 1 }, children: [
163
- /* @__PURE__ */ e("span", { style: n, children: "Importance" }),
164
- /* @__PURE__ */ e("span", { style: {
165
- ...c,
166
- color: I === 2 ? "#dc2626" : "#2563eb",
167
- fontWeight: 500
168
- }, children: _ })
169
- ] })
170
- ] }),
171
- W && /* @__PURE__ */ t("div", { style: i, children: [
172
- /* @__PURE__ */ e("span", { style: r, children: /* @__PURE__ */ e(G, { size: 16, style: a }) }),
173
- /* @__PURE__ */ t("div", { style: { display: "flex", flex: 1 }, children: [
174
- /* @__PURE__ */ e("span", { style: n, children: "Sensitivity" }),
175
- /* @__PURE__ */ e("span", { style: c, children: W })
176
- ] })
177
- ] }),
178
- T && T !== "Email" && /* @__PURE__ */ t("div", { style: i, children: [
179
- /* @__PURE__ */ e("span", { style: r, children: /* @__PURE__ */ e(V, { size: 16, style: a }) }),
180
- /* @__PURE__ */ t("div", { style: { display: "flex", flex: 1 }, children: [
181
- /* @__PURE__ */ e("span", { style: n, children: "Type" }),
182
- /* @__PURE__ */ e("span", { style: c, children: T })
183
- ] })
184
- ] }),
185
- z.length > 0 && /* @__PURE__ */ t("div", { style: { ...i, borderTop: "1px solid #e5e7eb", marginTop: "4px", paddingTop: "10px" }, children: [
186
- /* @__PURE__ */ e("span", { style: r, children: /* @__PURE__ */ e(Y, { size: 16, style: a }) }),
187
- /* @__PURE__ */ t("div", { style: { display: "flex", flex: 1 }, children: [
188
- /* @__PURE__ */ e("span", { style: n, children: "Attachments" }),
189
- /* @__PURE__ */ e("div", { style: { ...c, display: "flex", flexWrap: "wrap", gap: "6px" }, children: z.map((h, m) => {
190
- const k = h.fileName || h.name || "未知文件", y = h.contentLength, M = y ? y > 1048576 ? `${(y / 1048576).toFixed(1)} MB` : y > 1024 ? `${(y / 1024).toFixed(0)} KB` : `${y} B` : "";
191
- return /* @__PURE__ */ t(
192
- "span",
193
- {
194
- style: {
195
- display: "inline-flex",
196
- alignItems: "center",
197
- gap: "4px",
198
- padding: "2px 8px",
199
- background: "#f3f4f6",
200
- borderRadius: "4px",
201
- fontSize: "13px",
202
- color: "#374151",
203
- border: "1px solid #e5e7eb"
204
- },
205
- children: [
206
- k,
207
- M && /* @__PURE__ */ t("span", { style: { color: "#9ca3af", fontSize: "12px" }, children: [
208
- "(",
209
- M,
210
- ")"
211
- ] })
212
- ]
213
- },
214
- m
215
- );
216
- }) })
217
- ] })
218
- ] }),
219
- A && /* @__PURE__ */ t("div", { style: { ...i, borderTop: z.length > 0 ? "none" : "1px solid #e5e7eb", marginTop: "4px", paddingTop: "10px" }, children: [
220
- /* @__PURE__ */ e("span", { style: r, children: /* @__PURE__ */ e(Z, { size: 16, style: a }) }),
221
- /* @__PURE__ */ t("div", { style: { display: "flex", flex: 1 }, children: [
222
- /* @__PURE__ */ e("span", { style: n, children: "Message-ID" }),
223
- /* @__PURE__ */ e("span", { style: { ...c, fontSize: "12px", color: "#9ca3af", fontFamily: "monospace" }, children: A })
224
- ] })
225
- ] }),
226
- b && b !== x && b !== u && /* @__PURE__ */ t("div", { style: i, children: [
227
- /* @__PURE__ */ e("span", { style: r, children: /* @__PURE__ */ e(U, { size: 16, style: a }) }),
228
- /* @__PURE__ */ t("div", { style: { display: "flex", flex: 1 }, children: [
229
- /* @__PURE__ */ e("span", { style: n, children: "Modified" }),
230
- /* @__PURE__ */ e("span", { style: { ...c, fontSize: "12px", color: "#9ca3af" }, children: b })
231
- ] })
232
- ] })
233
- ] })
234
- ] }),
235
- /* @__PURE__ */ e(
236
- "div",
237
- {
238
- style: {
239
- padding: "clamp(12px, 3vw, 24px) clamp(16px, 3vw, 28px)",
240
- fontFamily: "system-ui, -apple-system, sans-serif",
241
- lineHeight: "1.6",
242
- color: "#333",
243
- overflowX: "auto"
244
- },
245
- dangerouslySetInnerHTML: { __html: X }
246
- }
247
- )
248
- ]
249
- }
250
- )
251
- }
252
- );
253
- };
254
- export {
255
- oe as MsgRenderer
256
- };
257
- //# sourceMappingURL=index-CgV8T0G5.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-CgV8T0G5.mjs","sources":["../../src/renderers/Msg/index.tsx"],"sourcesContent":["import { useState, useEffect } from 'react';\nimport MsgReader from '@kenjiuno/msgreader';\nimport type { FieldsData } from '@kenjiuno/msgreader';\nimport { User, Users, Paperclip, Calendar, Mail, Tag, Clock, Hash } from 'lucide-react';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\n\ninterface MsgRendererProps {\n url: string;\n}\n\nfunction formatRecipients(recipients: FieldsData[] | undefined, type: 'to' | 'cc' | 'bcc'): string {\n if (!recipients) return '';\n return recipients\n .filter((r) => r.recipType === type)\n .map((r) => {\n const name = r.name || '';\n const email = r.smtpAddress || r.email || '';\n if (name && email && name !== email) {\n return `${name} <${email}>`;\n }\n return name || email;\n })\n .filter(Boolean)\n .join('; ');\n}\n\nfunction formatDate(dateStr: string | undefined): string {\n if (!dateStr) return '';\n try {\n const date = new Date(dateStr);\n if (isNaN(date.getTime())) return dateStr;\n return date.toLocaleString();\n } catch {\n return dateStr;\n }\n}\n\nfunction decodeHtmlBody(fields: FieldsData, emptyBodyText: string): string {\n // 优先使用 bodyHtml (string 类型)\n if (fields.bodyHtml) {\n return fields.bodyHtml;\n }\n // 其次尝试 html (Uint8Array 类型)\n if (fields.html) {\n try {\n const decoder = new TextDecoder('utf-8');\n return decoder.decode(fields.html);\n } catch {\n // fallback\n }\n }\n // 最后使用纯文本,转换为简单 HTML\n if (fields.body) {\n return `<pre style=\"white-space: pre-wrap; word-wrap: break-word; font-family: system-ui, sans-serif;\">${fields.body.replace(/&/g, '&amp;').replace(/\\x3c/g, '&lt;').replace(/>/g, '&gt;')\n }</pre>`;\n }\n return `<p style=\"color: #999;\">${emptyBodyText}</p>`;\n}\n\nfunction formatMessageClass(messageClass: string | undefined): string {\n if (!messageClass) return '';\n const classMap: Record<string, string> = {\n 'IPM.Note': 'Email',\n 'IPM.Note.SMIME': 'Encrypted Email',\n 'IPM.Note.SMIME.MultipartSigned': 'Signed Email',\n 'IPM.Appointment': 'Appointment',\n 'IPM.Schedule.Meeting.Request': 'Meeting Request',\n 'IPM.Schedule.Meeting.Canceled': 'Meeting Cancellation',\n 'IPM.Contact': 'Contact',\n 'IPM.Task': 'Task',\n 'IPM.StickyNote': 'Sticky Note',\n };\n return classMap[messageClass] || messageClass;\n}\n\nconst labelStyle: React.CSSProperties = {\n flexShrink: 0,\n color: '#6b7280',\n fontWeight: 500,\n marginRight: '8px',\n whiteSpace: 'nowrap',\n};\n\nconst rowStyle: React.CSSProperties = {\n display: 'flex',\n alignItems: 'flex-start',\n gap: '8px',\n padding: '6px 0',\n};\n\nconst iconWrapStyle: React.CSSProperties = {\n flexShrink: 0,\n display: 'flex',\n alignItems: 'center',\n height: '1.4em',\n};\n\nconst iconStyle: React.CSSProperties = {\n flexShrink: 0,\n color: '#9ca3af',\n};\n\nconst valueStyle: React.CSSProperties = {\n color: '#111827',\n wordBreak: 'break-word' as const,\n flex: 1,\n};\n\nexport const MsgRenderer: React.FC<MsgRendererProps> = ({ url }) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [fields, setFields] = useState<FieldsData | null>(null);\n\n useEffect(() => {\n const loadMsg = async () => {\n setLoading(true);\n setError(null);\n setFields(null);\n\n try {\n const response = await fetcher(url);\n if (!response.ok) {\n throw new Error('文件加载失败');\n }\n\n const arrayBuffer = await response.arrayBuffer();\n const msgReader = new MsgReader(arrayBuffer);\n const fileData = msgReader.getFileData();\n setFields(fileData);\n } catch (err) {\n console.error('MSG 解析错误:', err);\n setError(t('msg.parse_failed'));\n } finally {\n setLoading(false);\n }\n };\n\n loadMsg();\n }, [url]);\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 || !fields) {\n return (\n <div className=\"rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full\">\n <div className=\"rfp-text-fg-secondary rfp-text-center\">\n <p className=\"rfp-text-lg\">{error || t('msg.parse_failed_short')}</p>\n </div>\n </div>\n );\n }\n\n const toStr = formatRecipients(fields.recipients, 'to');\n const ccStr = formatRecipients(fields.recipients, 'cc');\n const bccStr = formatRecipients(fields.recipients, 'bcc');\n const senderName = fields.senderName || '';\n const senderEmail = fields.senderSmtpAddress || fields.senderEmail || '';\n const sender = senderName && senderEmail && senderName !== senderEmail\n ? `${senderName} <${senderEmail}>`\n : senderName || senderEmail;\n const sentDate = formatDate(fields.clientSubmitTime);\n const receivedDate = formatDate(fields.messageDeliveryTime);\n const createdDate = formatDate(fields.creationTime);\n const lastModified = formatDate(fields.lastModificationTime);\n const subject = fields.subject || '(无主题)';\n const attachments = (fields.attachments || []).filter((a) => !a.attachmentHidden);\n const bodyHtml = decodeHtmlBody(fields, t('msg.empty_body'));\n const messageClass = formatMessageClass(fields.messageClass);\n const messageId = fields.messageId || '';\n const fieldsAny = fields as FieldsData & Record<string, unknown>;\n const importance = typeof fieldsAny.importance === 'number' ? fieldsAny.importance : undefined;\n const importanceLabel = importance === 2 ? 'High' : importance === 0 ? 'Low' : '';\n const sensitivity = typeof fieldsAny.sensitivity === 'number' ? fieldsAny.sensitivity : undefined;\n const sensitivityLabels: Record<number, string> = {\n 0: 'Normal',\n 1: 'Personal',\n 2: 'Private',\n 3: 'Confidential',\n };\n const sensitivityLabel = sensitivity !== undefined && sensitivity !== 0 ? sensitivityLabels[sensitivity] || '' : '';\n\n return (\n <div\n className=\"rfp-w-full rfp-h-full rfp-overflow-auto\"\n style={{ background: 'white' }}\n >\n <div\n style={{\n width: '100%',\n background: 'white',\n minHeight: '100%',\n }}\n >\n {/* 邮件头部 */}\n <div style={{ borderBottom: '1px solid #e5e7eb', padding: 'clamp(12px, 3vw, 24px) clamp(16px, 3vw, 28px)', background: '#f9fafb' }}>\n {/* 主题 */}\n <h2 style={{ margin: '0 0 16px 0', fontSize: 'clamp(16px, 2.5vw, 20px)', fontWeight: 600, color: '#111827', lineHeight: 1.4 }}>\n {subject}\n </h2>\n\n {/* 元信息 */}\n <div style={{ display: 'flex', flexDirection: 'column', fontSize: 'clamp(12px, 1.8vw, 14px)', color: '#4b5563' }}>\n {sender && (\n <div style={rowStyle}>\n <span style={iconWrapStyle}><User size={16} style={iconStyle} /></span>\n <div style={{ display: 'flex', flex: 1 }}>\n <span style={labelStyle}>From</span>\n <span style={valueStyle}>{sender}</span>\n </div>\n </div>\n )}\n\n {toStr && (\n <div style={rowStyle}>\n <span style={iconWrapStyle}><Users size={16} style={iconStyle} /></span>\n <div style={{ display: 'flex', flex: 1 }}>\n <span style={labelStyle}>To</span>\n <span style={valueStyle}>{toStr}</span>\n </div>\n </div>\n )}\n\n {ccStr && (\n <div style={rowStyle}>\n <span style={iconWrapStyle}><Users size={16} style={iconStyle} /></span>\n <div style={{ display: 'flex', flex: 1 }}>\n <span style={labelStyle}>Cc</span>\n <span style={valueStyle}>{ccStr}</span>\n </div>\n </div>\n )}\n\n {bccStr && (\n <div style={rowStyle}>\n <span style={iconWrapStyle}><Users size={16} style={iconStyle} /></span>\n <div style={{ display: 'flex', flex: 1 }}>\n <span style={labelStyle}>Bcc</span>\n <span style={valueStyle}>{bccStr}</span>\n </div>\n </div>\n )}\n\n {sentDate && (\n <div style={rowStyle}>\n <span style={iconWrapStyle}><Calendar size={16} style={iconStyle} /></span>\n <div style={{ display: 'flex', flex: 1 }}>\n <span style={labelStyle}>Sent</span>\n <span style={valueStyle}>{sentDate}</span>\n </div>\n </div>\n )}\n\n {receivedDate && receivedDate !== sentDate && (\n <div style={rowStyle}>\n <span style={iconWrapStyle}><Clock size={16} style={iconStyle} /></span>\n <div style={{ display: 'flex', flex: 1 }}>\n <span style={labelStyle}>Received</span>\n <span style={valueStyle}>{receivedDate}</span>\n </div>\n </div>\n )}\n\n {!sentDate && !receivedDate && createdDate && (\n <div style={rowStyle}>\n <span style={iconWrapStyle}><Calendar size={16} style={iconStyle} /></span>\n <div style={{ display: 'flex', flex: 1 }}>\n <span style={labelStyle}>Date</span>\n <span style={valueStyle}>{createdDate}</span>\n </div>\n </div>\n )}\n\n {importanceLabel && (\n <div style={rowStyle}>\n <span style={iconWrapStyle}><Tag size={16} style={iconStyle} /></span>\n <div style={{ display: 'flex', flex: 1 }}>\n <span style={labelStyle}>Importance</span>\n <span style={{\n ...valueStyle,\n color: importance === 2 ? '#dc2626' : '#2563eb',\n fontWeight: 500,\n }}>\n {importanceLabel}\n </span>\n </div>\n </div>\n )}\n\n {sensitivityLabel && (\n <div style={rowStyle}>\n <span style={iconWrapStyle}><Tag size={16} style={iconStyle} /></span>\n <div style={{ display: 'flex', flex: 1 }}>\n <span style={labelStyle}>Sensitivity</span>\n <span style={valueStyle}>{sensitivityLabel}</span>\n </div>\n </div>\n )}\n\n {messageClass && messageClass !== 'Email' && (\n <div style={rowStyle}>\n <span style={iconWrapStyle}><Mail size={16} style={iconStyle} /></span>\n <div style={{ display: 'flex', flex: 1 }}>\n <span style={labelStyle}>Type</span>\n <span style={valueStyle}>{messageClass}</span>\n </div>\n </div>\n )}\n\n {attachments.length > 0 && (\n <div style={{ ...rowStyle, borderTop: '1px solid #e5e7eb', marginTop: '4px', paddingTop: '10px' }}>\n <span style={iconWrapStyle}><Paperclip size={16} style={iconStyle} /></span>\n <div style={{ display: 'flex', flex: 1 }}>\n <span style={labelStyle}>Attachments</span>\n <div style={{ ...valueStyle, display: 'flex', flexWrap: 'wrap', gap: '6px' }}>\n {attachments.map((a, i) => {\n const name = a.fileName || a.name || '未知文件';\n const size = a.contentLength;\n const sizeStr = size\n ? size > 1048576\n ? `${(size / 1048576).toFixed(1)} MB`\n : size > 1024\n ? `${(size / 1024).toFixed(0)} KB`\n : `${size} B`\n : '';\n return (\n <span\n key={i}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: '4px',\n padding: '2px 8px',\n background: '#f3f4f6',\n borderRadius: '4px',\n fontSize: '13px',\n color: '#374151',\n border: '1px solid #e5e7eb',\n }}\n >\n {name}\n {sizeStr && (\n <span style={{ color: '#9ca3af', fontSize: '12px' }}>({sizeStr})</span>\n )}\n </span>\n );\n })}\n </div>\n </div>\n </div>\n )}\n\n {messageId && (\n <div style={{ ...rowStyle, borderTop: attachments.length > 0 ? 'none' : '1px solid #e5e7eb', marginTop: '4px', paddingTop: '10px' }}>\n <span style={iconWrapStyle}><Hash size={16} style={iconStyle} /></span>\n <div style={{ display: 'flex', flex: 1 }}>\n <span style={labelStyle}>Message-ID</span>\n <span style={{ ...valueStyle, fontSize: '12px', color: '#9ca3af', fontFamily: 'monospace' }}>{messageId}</span>\n </div>\n </div>\n )}\n\n {lastModified && lastModified !== sentDate && lastModified !== receivedDate && (\n <div style={rowStyle}>\n <span style={iconWrapStyle}><Clock size={16} style={iconStyle} /></span>\n <div style={{ display: 'flex', flex: 1 }}>\n <span style={labelStyle}>Modified</span>\n <span style={{ ...valueStyle, fontSize: '12px', color: '#9ca3af' }}>{lastModified}</span>\n </div>\n </div>\n )}\n </div>\n </div>\n\n {/* 邮件正文 */}\n <div\n style={{\n padding: 'clamp(12px, 3vw, 24px) clamp(16px, 3vw, 28px)',\n fontFamily: 'system-ui, -apple-system, sans-serif',\n lineHeight: '1.6',\n color: '#333',\n overflowX: 'auto',\n }}\n dangerouslySetInnerHTML={{ __html: bodyHtml }}\n />\n </div>\n </div>\n );\n};\n"],"names":["formatRecipients","recipients","type","r","name","email","formatDate","dateStr","date","decodeHtmlBody","fields","emptyBodyText","formatMessageClass","messageClass","labelStyle","rowStyle","iconWrapStyle","iconStyle","valueStyle","MsgRenderer","url","t","useTranslator","fetcher","useFetcher","loading","setLoading","useState","error","setError","setFields","useEffect","response","arrayBuffer","fileData","MsgReader","err","jsx","toStr","ccStr","bccStr","senderName","senderEmail","sender","sentDate","receivedDate","createdDate","lastModified","subject","attachments","a","bodyHtml","messageId","fieldsAny","importance","importanceLabel","sensitivity","sensitivityLabel","jsxs","User","Users","Calendar","Clock","Tag","Mail","Paperclip","i","size","sizeStr","Hash"],"mappings":"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"}
@@ -1,116 +0,0 @@
1
- import { jsxs as U, jsx as m } from "react/jsx-runtime";
2
- import { useState as a, useRef as W, useEffect as M, useCallback as b } from "react";
3
- import { motion as S } from "framer-motion";
4
- import { u as V } from "./index-Bv93wiEK.mjs";
5
- const et = ({
6
- url: j,
7
- zoom: B,
8
- rotation: H,
9
- resetKey: P,
10
- fileSize: c,
11
- onZoomChange: s,
12
- onNaturalWidthChange: $,
13
- onNaturalHeightChange: D
14
- }) => {
15
- const N = V(), [x, E] = a(!1), [h, k] = a(null), [f, d] = a({ x: 0, y: 0 }), [g, I] = a(!1), [L, O] = a({ x: 0, y: 0 }), [Y, y] = a(1), [i, _] = a({ width: 0, height: 0 }), q = W(null), R = W(null);
16
- M(() => {
17
- E(!1), k(null), d({ x: 0, y: 0 }), y(1);
18
- }, [j]), M(() => {
19
- y(B);
20
- }, [B]), M(() => {
21
- P !== void 0 && d({ x: 0, y: 0 });
22
- }, [P]);
23
- const A = (t) => {
24
- E(!0);
25
- const e = t.currentTarget;
26
- _({ width: e.naturalWidth, height: e.naturalHeight }), $ == null || $(e.naturalWidth), D == null || D(e.naturalHeight);
27
- }, v = b((t, e) => {
28
- const r = R.current;
29
- if (!r || i.width === 0) return t;
30
- const o = r.clientWidth, p = r.clientHeight, w = i.width * e, X = i.height * e, u = Math.min(80, o * 0.15, p * 0.15), n = (o + w) / 2 - u, l = (p + X) / 2 - u;
31
- return {
32
- x: n > 0 ? Math.max(-n, Math.min(n, t.x)) : 0,
33
- y: l > 0 ? Math.max(-l, Math.min(l, t.y)) : 0
34
- };
35
- }, [i]), G = () => {
36
- k(N("image.load_failed")), E(!0);
37
- }, J = () => {
38
- d({ x: 0, y: 0 }), y(1), s == null || s(1);
39
- };
40
- M(() => {
41
- const t = R.current;
42
- if (!t) return;
43
- const e = (r) => {
44
- r.preventDefault(), r.stopPropagation();
45
- const o = t.getBoundingClientRect(), p = r.clientX - o.left - o.width / 2, w = r.clientY - o.top - o.height / 2, X = r.deltaY > 0 ? -0.05 : 0.05;
46
- y((u) => {
47
- const n = Math.max(0.01, Math.min(10, u + X)), l = n / u;
48
- return d((T) => v({
49
- x: p - l * (p - T.x),
50
- y: w - l * (w - T.y)
51
- }, n)), s == null || s(n), n;
52
- });
53
- };
54
- return t.addEventListener("wheel", e, { passive: !1 }), () => t.removeEventListener("wheel", e);
55
- }, [s, v]);
56
- const K = b((t) => {
57
- t.button === 0 && (I(!0), O({
58
- x: t.clientX - f.x,
59
- y: t.clientY - f.y
60
- }));
61
- }, [f]), Q = b((t) => {
62
- g && d(v({
63
- x: t.clientX - L.x,
64
- y: t.clientY - L.y
65
- }, Y));
66
- }, [g, L, Y, v]), F = b(() => {
67
- I(!1);
68
- }, []);
69
- return /* @__PURE__ */ U(
70
- "div",
71
- {
72
- ref: R,
73
- className: "rfp-relative rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full rfp-overflow-hidden",
74
- onMouseDown: K,
75
- onMouseMove: Q,
76
- onMouseUp: F,
77
- onMouseLeave: F,
78
- style: { cursor: g ? "grabbing" : "grab" },
79
- children: [
80
- !x && !h && /* @__PURE__ */ m("div", { className: "rfp-flex rfp-items-center rfp-justify-center", children: /* @__PURE__ */ m("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" }) }),
81
- h && /* @__PURE__ */ m("div", { className: "rfp-text-fg-secondary rfp-text-center", children: /* @__PURE__ */ m("p", { className: "rfp-text-lg", children: h }) }),
82
- /* @__PURE__ */ m(
83
- S.img,
84
- {
85
- ref: q,
86
- src: j,
87
- alt: "Preview",
88
- className: `rfp-max-w-none rfp-select-none ${x ? "" : "rfp-hidden"}`,
89
- style: {
90
- transform: `translate(${f.x}px, ${f.y}px) scale(${Y}) rotate(${H}deg)`,
91
- transformOrigin: "center",
92
- transition: g ? "none" : "transform 0.3s ease-out"
93
- },
94
- onLoad: A,
95
- onError: G,
96
- onDoubleClick: J,
97
- initial: { opacity: 0 },
98
- animate: { opacity: x ? 1 : 0 },
99
- transition: { duration: 0.3 },
100
- draggable: !1
101
- }
102
- ),
103
- x && !h && i.width > 0 && /* @__PURE__ */ U("div", { className: "rfp-absolute rfp-bottom-2 rfp-right-3 rfp-text-[10px] rfp-text-fg-disabled hover:rfp-text-fg-secondary rfp-transition-colors rfp-pointer-events-auto rfp-select-none rfp-cursor-default", children: [
104
- i.width,
105
- " × ",
106
- i.height,
107
- c != null && ` · ${c < 1024 ? `${c} B` : c < 1024 * 1024 ? `${(c / 1024).toFixed(1)} KB` : `${(c / (1024 * 1024)).toFixed(1)} MB`}`
108
- ] })
109
- ]
110
- }
111
- );
112
- };
113
- export {
114
- et as ImageRenderer
115
- };
116
- //# sourceMappingURL=index-D8GtNeDn.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-D8GtNeDn.mjs","sources":["../../src/renderers/Image/index.tsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback } from 'react';\nimport { motion } from 'framer-motion';\nimport { useTranslator } from '../../i18n/LocaleContext';\n\ninterface ImageRendererProps {\n url: string;\n zoom: number;\n rotation: number;\n resetKey?: number;\n fileSize?: number;\n onZoomChange?: (zoom: number) => void;\n onNaturalWidthChange?: (width: number) => void;\n onNaturalHeightChange?: (height: number) => void;\n}\n\nexport const ImageRenderer: React.FC<ImageRendererProps> = ({\n url,\n zoom,\n rotation,\n resetKey,\n fileSize,\n onZoomChange,\n onNaturalWidthChange,\n onNaturalHeightChange\n}) => {\n const t = useTranslator();\n const [loaded, setLoaded] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [position, setPosition] = useState({ x: 0, y: 0 });\n const [isDragging, setIsDragging] = useState(false);\n const [dragStart, setDragStart] = useState({ x: 0, y: 0 });\n const [internalZoom, setInternalZoom] = useState(1);\n const [naturalSize, setNaturalSize] = useState({ width: 0, height: 0 });\n const imgRef = useRef<HTMLImageElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n setLoaded(false);\n setError(null);\n setPosition({ x: 0, y: 0 });\n setInternalZoom(1);\n }, [url]);\n\n // 当外部 zoom 改变时,同步内部 zoom\n useEffect(() => {\n setInternalZoom(zoom);\n }, [zoom]);\n\n // 适应窗口/原始尺寸等操作时重置位置居中\n useEffect(() => {\n if (resetKey !== undefined) {\n setPosition({ x: 0, y: 0 });\n }\n }, [resetKey]);\n\n const handleLoad = (e: React.SyntheticEvent<HTMLImageElement>) => {\n setLoaded(true);\n const img = e.currentTarget;\n setNaturalSize({ width: img.naturalWidth, height: img.naturalHeight });\n onNaturalWidthChange?.(img.naturalWidth);\n onNaturalHeightChange?.(img.naturalHeight);\n };\n\n // 边界限制:确保图片至少有一部分可见\n const clampPosition = useCallback((pos: { x: number; y: number }, currentZoom: number) => {\n const container = containerRef.current;\n if (!container || naturalSize.width === 0) return pos;\n\n const containerW = container.clientWidth;\n const containerH = container.clientHeight;\n const imgW = naturalSize.width * currentZoom;\n const imgH = naturalSize.height * currentZoom;\n\n // 至少保留 margin px 的图片在视口内\n const margin = Math.min(80, containerW * 0.15, containerH * 0.15);\n const rangeX = (containerW + imgW) / 2 - margin;\n const rangeY = (containerH + imgH) / 2 - margin;\n\n return {\n x: rangeX > 0 ? Math.max(-rangeX, Math.min(rangeX, pos.x)) : 0,\n y: rangeY > 0 ? Math.max(-rangeY, Math.min(rangeY, pos.y)) : 0,\n };\n }, [naturalSize]);\n\n const handleError = () => {\n setError(t('image.load_failed'));\n setLoaded(true);\n };\n\n // 双击复原:居中 + 缩放100%\n const handleDoubleClick = () => {\n setPosition({ x: 0, y: 0 });\n setInternalZoom(1);\n onZoomChange?.(1);\n };\n\n // 鼠标滚轮缩放 —— 以鼠标位置为缩放原点\n // 使用原生事件 + passive: false,确保 preventDefault 生效,\n // 避免滚轮事件冒泡触发外层(如嵌入模式下的页面滚动)\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const handleWheelNative = (e: WheelEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n const rect = container.getBoundingClientRect();\n const mouseX = e.clientX - rect.left - rect.width / 2;\n const mouseY = e.clientY - rect.top - rect.height / 2;\n\n const delta = e.deltaY > 0 ? -0.05 : 0.05;\n\n setInternalZoom(prev => {\n const newZoom = Math.max(0.01, Math.min(10, prev + delta));\n const scale = newZoom / prev;\n\n setPosition(pos => clampPosition({\n x: mouseX - scale * (mouseX - pos.x),\n y: mouseY - scale * (mouseY - pos.y),\n }, newZoom));\n\n onZoomChange?.(newZoom);\n return newZoom;\n });\n };\n\n container.addEventListener('wheel', handleWheelNative, { passive: false });\n return () => container.removeEventListener('wheel', handleWheelNative);\n }, [onZoomChange, clampPosition]);\n\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\n if (e.button !== 0) return;\n setIsDragging(true);\n setDragStart({\n x: e.clientX - position.x,\n y: e.clientY - position.y,\n });\n }, [position]);\n\n const handleMouseMove = useCallback((e: React.MouseEvent) => {\n if (!isDragging) return;\n setPosition(clampPosition({\n x: e.clientX - dragStart.x,\n y: e.clientY - dragStart.y,\n }, internalZoom));\n }, [isDragging, dragStart, internalZoom, clampPosition]);\n\n const handleMouseUp = useCallback(() => {\n setIsDragging(false);\n }, []);\n\n return (\n <div\n ref={containerRef}\n className=\"rfp-relative rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full rfp-overflow-hidden\"\n onMouseDown={handleMouseDown}\n onMouseMove={handleMouseMove}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseUp}\n style={{ cursor: isDragging ? 'grabbing' : 'grab' }}\n >\n {!loaded && !error && (\n <div className=\"rfp-flex rfp-items-center rfp-justify-center\">\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 {error && (\n <div className=\"rfp-text-fg-secondary rfp-text-center\">\n <p className=\"rfp-text-lg\">{error}</p>\n </div>\n )}\n\n <motion.img\n ref={imgRef}\n src={url}\n alt=\"Preview\"\n className={`rfp-max-w-none rfp-select-none ${!loaded ? 'rfp-hidden' : ''}`}\n style={{\n transform: `translate(${position.x}px, ${position.y}px) scale(${internalZoom}) rotate(${rotation}deg)`,\n transformOrigin: 'center',\n transition: isDragging ? 'none' : 'transform 0.3s ease-out',\n }}\n onLoad={handleLoad}\n onError={handleError}\n onDoubleClick={handleDoubleClick}\n initial={{ opacity: 0 }}\n animate={{ opacity: loaded ? 1 : 0 }}\n transition={{ duration: 0.3 }}\n draggable={false}\n />\n\n {/* 右下角分辨率 */}\n {loaded && !error && naturalSize.width > 0 && (\n <div className=\"rfp-absolute rfp-bottom-2 rfp-right-3 rfp-text-[10px] rfp-text-fg-disabled hover:rfp-text-fg-secondary rfp-transition-colors rfp-pointer-events-auto rfp-select-none rfp-cursor-default\">\n {naturalSize.width} × {naturalSize.height}{fileSize != null && ` · ${fileSize < 1024 ? `${fileSize} B` : fileSize < 1024 * 1024 ? `${(fileSize / 1024).toFixed(1)} KB` : `${(fileSize / (1024 * 1024)).toFixed(1)} MB`}`}\n </div>\n )}\n </div>\n );\n};\n"],"names":["ImageRenderer","url","zoom","rotation","resetKey","fileSize","onZoomChange","onNaturalWidthChange","onNaturalHeightChange","t","useTranslator","loaded","setLoaded","useState","error","setError","position","setPosition","isDragging","setIsDragging","dragStart","setDragStart","internalZoom","setInternalZoom","naturalSize","setNaturalSize","imgRef","useRef","containerRef","useEffect","handleLoad","e","img","clampPosition","useCallback","pos","currentZoom","container","containerW","containerH","imgW","imgH","margin","rangeX","rangeY","handleError","handleDoubleClick","handleWheelNative","rect","mouseX","mouseY","delta","prev","newZoom","scale","handleMouseDown","handleMouseMove","handleMouseUp","jsxs","jsx","motion"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-DGuiWJr7.mjs","sources":["../../src/renderers/Subtitle/index.tsx"],"sourcesContent":["import { useState, useEffect, useMemo } from 'react';\nimport {\n parseSubtitle,\n formatSubtitleTime,\n fetchTextUtf8,\n type SubtitleParseResult,\n type SubtitleFormat,\n} from '@eternalheart/file-preview-core';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\n\ninterface SubtitleRendererProps {\n url: string;\n fileName: string;\n}\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\nexport const SubtitleRenderer: React.FC<SubtitleRendererProps> = ({ url, fileName }) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const [text, setText] = useState<string>('');\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const load = async () => {\n try {\n setLoading(true);\n setError(null);\n setText(await fetchTextUtf8(url, { fetcher }));\n } catch (err) {\n console.error(err);\n setError(t('subtitle.load_failed'));\n } finally {\n setLoading(false);\n }\n };\n load();\n }, [url]);\n\n const parsed: SubtitleParseResult | null = useMemo(() => {\n if (!text) return null;\n try {\n return parseSubtitle(text, getFormat(fileName));\n } catch (err) {\n console.error(err);\n return null;\n }\n }, [text, fileName]);\n\n if (loading) {\n return (\n <div className=\"rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full rfp-bg-[#0f0f12]\">\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 || !parsed) {\n return (\n <div className=\"rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full rfp-bg-[#0f0f12]\">\n <div className=\"rfp-text-fg-secondary rfp-text-center\">\n <p className=\"rfp-text-lg\">{error || t('subtitle.parse_failed')}</p>\n </div>\n </div>\n );\n }\n\n const isLyric = parsed.format === 'lrc' || parsed.format === 'elrc';\n const meta = parsed.metadata ?? {};\n const dotHover = isLyric ? 'group-hover:rfp-bg-violet-400' : 'group-hover:rfp-bg-sky-400';\n\n return (\n <div className=\"rfp-relative rfp-w-full rfp-h-full rfp-bg-[#0f0f12]\">\n {/* 内容滚动区 */}\n <div className=\"rfp-w-full rfp-h-full rfp-overflow-auto rfp-px-6 md:rfp-px-10 rfp-pt-6 rfp-pb-16 md:rfp-pb-20\">\n <div className=\"rfp-relative rfp-max-w-5xl rfp-mx-auto\">\n {/* vertical line */}\n <div className=\"rfp-absolute rfp-left-[5px] md:rfp-left-[7px] rfp-top-2 rfp-bottom-2 rfp-w-px rfp-bg-surface-1\" />\n\n <ol className=\"rfp-space-y-5 md:rfp-space-y-6\">\n {parsed.cues.map((cue, i) => (\n <li key={`cue-${i}`} className=\"rfp-relative rfp-pl-6 md:rfp-pl-8 rfp-group\">\n {/* dot */}\n <div\n className={`rfp-absolute rfp-left-0 rfp-top-2 rfp-w-3 rfp-h-3 rfp-rounded-full rfp-bg-surface-3 rfp-border-2 rfp-border-[#0f0f12] rfp-transition-colors ${dotHover}`}\n />\n\n <div className=\"rfp-flex rfp-flex-wrap rfp-items-baseline rfp-gap-x-3 rfp-gap-y-1 rfp-mb-1.5\">\n <span className=\"rfp-text-[11px] rfp-font-mono rfp-text-fg-muted rfp-tabular-nums\">\n {formatSubtitleTime(cue.start)}\n </span>\n <span className=\"rfp-text-[11px] rfp-text-fg-disabled\">→</span>\n <span className=\"rfp-text-[11px] rfp-font-mono rfp-text-fg-muted rfp-tabular-nums\">\n {formatSubtitleTime(cue.end)}\n </span>\n <span className=\"rfp-text-[10px] rfp-font-mono rfp-text-fg-disabled rfp-tabular-nums\">\n #{cue.id ?? i + 1}\n </span>\n {cue.style && (\n <span className=\"rfp-text-[9px] rfp-uppercase rfp-tracking-widest rfp-text-fg-tertiary rfp-px-1.5 rfp-py-0.5 rfp-rounded rfp-bg-surface-1 rfp-border rfp-border-line-weak\">\n {cue.style}\n </span>\n )}\n </div>\n\n {cue.words && cue.words.length > 0 ? (\n <div className=\"rfp-flex rfp-flex-wrap rfp-gap-x-1.5 rfp-gap-y-1 rfp-text-base md:rfp-text-lg rfp-text-fg-primary rfp-leading-relaxed group-hover:rfp-text-fg-primary rfp-transition-colors\">\n {cue.words.map((word, wi) => (\n <span\n key={`w-${wi}`}\n className=\"rfp-inline-flex rfp-flex-col rfp-items-start\"\n title={formatSubtitleTime(word.start)}\n >\n <span className=\"rfp-text-[9px] rfp-text-fg-disabled rfp-font-mono rfp-leading-none rfp-tabular-nums\">\n {formatSubtitleTime(word.start).slice(3, 8)}\n </span>\n <span className=\"rfp-leading-snug\">{word.text}</span>\n </span>\n ))}\n </div>\n ) : (\n <p\n className={`rfp-whitespace-pre-wrap rfp-break-words rfp-leading-relaxed group-hover:rfp-text-fg-primary rfp-transition-colors rfp-text-fg-primary ${\n isLyric ? 'rfp-text-base md:rfp-text-xl rfp-font-medium' : 'rfp-text-sm md:rfp-text-base'\n }`}\n >\n {cue.text}\n </p>\n )}\n </li>\n ))}\n </ol>\n </div>\n </div>\n\n {/* 底部状态栏 */}\n <div className=\"rfp-pointer-events-none rfp-absolute rfp-bottom-3 rfp-right-3 md:rfp-bottom-4 md:rfp-right-4 rfp-flex rfp-items-center rfp-gap-2 rfp-px-2.5 rfp-py-1 rfp-rounded-full rfp-bg-surface-nav rfp-backdrop-blur rfp-border rfp-border-line-weak rfp-text-[10px] rfp-text-fg-tertiary rfp-font-mono rfp-tabular-nums\">\n <span>{parsed.cues.length} {isLyric ? t('subtitle.lines') : t('subtitle.cues')}</span>\n {meta.length && (\n <>\n <span className=\"rfp-text-fg-disabled\">·</span>\n <span>{meta.length}</span>\n </>\n )}\n </div>\n </div>\n );\n};\n"],"names":["FORMAT_BY_EXT","getFormat","fileName","ext","_a","SubtitleRenderer","url","t","useTranslator","fetcher","useFetcher","text","setText","useState","loading","setLoading","error","setError","useEffect","fetchTextUtf8","err","parsed","useMemo","parseSubtitle","jsx","isLyric","meta","dotHover","jsxs","cue","i","formatSubtitleTime","word","wi","Fragment"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-DV5Jd7Qe.mjs","sources":["../../src/renderers/Mobi/index.tsx"],"sourcesContent":["import {\n useEffect,\n useRef,\n useState,\n useCallback,\n useImperativeHandle,\n forwardRef,\n} from 'react';\nimport { X } from 'lucide-react';\nimport 'foliate-js/view.js';\nimport type { FoliateView, TocItem } from 'foliate-js/view.js';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\n\nconst READER_CSS = `\n @namespace epub \"http://www.idpf.org/2007/ops\";\n html { color-scheme: light; }\n body {\n background: #ffffff !important;\n color: #1a1a1a !important;\n font-family: \"Noto Serif SC\", \"Source Han Serif SC\", Georgia, \"Times New Roman\", serif !important;\n font-size: 16px !important;\n line-height: 2 !important;\n max-width: 100% !important;\n box-sizing: border-box !important;\n word-break: break-word !important;\n overflow-wrap: break-word !important;\n }\n p, li, blockquote, dd { line-height: 2; text-align: justify; }\n p { text-indent: 2em; margin: 0.8em 0; }\n h1 { text-align: center; margin: 1.5em 0 1em; }\n h2 { margin: 1.2em 0 0.8em; }\n h3 { margin: 1em 0 0.6em; }\n img { max-width: 100% !important; height: auto !important; }\n a { color: #2563eb; text-decoration: none; }\n pre { white-space: pre-wrap !important; }\n`;\n\nconst A4_WIDTH = 794;\n\nexport interface MobiRendererHandle {\n prevPage: () => void;\n nextPage: () => void;\n toggleFullWidth: () => void;\n toggleToc: () => void;\n}\n\ninterface MobiRendererProps {\n url: string;\n onChapterChange?: (current: number, total: number) => void;\n onFullWidthChange?: (isFullWidth: boolean) => void;\n}\n\nexport const MobiRenderer = forwardRef<MobiRendererHandle, MobiRendererProps>(\n ({ url, onChapterChange, onFullWidthChange }, ref) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const hostRef = useRef<HTMLDivElement>(null);\n const viewRef = useRef<FoliateView | null>(null);\n const onChapterChangeRef = useRef(onChapterChange);\n const onFullWidthChangeRef = useRef(onFullWidthChange);\n onChapterChangeRef.current = onChapterChange;\n onFullWidthChangeRef.current = onFullWidthChange;\n\n // 模拟 epub.js 的 locations 显示\n const totalLocationsRef = useRef(1);\n\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [toc, setToc] = useState<TocItem[]>([]);\n const [showToc, setShowToc] = useState(false);\n const [activeTocHref, setActiveTocHref] = useState<string>('');\n const [isFullWidth, setIsFullWidth] = useState(false);\n const isFullWidthRef = useRef(false);\n isFullWidthRef.current = isFullWidth;\n\n const reportProgress = useCallback((current: number, total: number) => {\n if (total > 0) totalLocationsRef.current = total;\n onChapterChangeRef.current?.(Math.max(1, current + 1), totalLocationsRef.current);\n }, []);\n\n const handlePrev = useCallback(() => {\n const view = viewRef.current;\n if (!view) return;\n view.prev().catch(() => {});\n }, []);\n\n const handleNext = useCallback(() => {\n const view = viewRef.current;\n if (!view) return;\n view.next().catch(() => {});\n }, []);\n\n const toggleToc = useCallback(() => setShowToc((prev) => !prev), []);\n\n const toggleFullWidth = useCallback(() => {\n const newVal = !isFullWidthRef.current;\n setIsFullWidth(newVal);\n onFullWidthChangeRef.current?.(newVal);\n // 宽度改变后 paginator 需要重新分页\n const view = viewRef.current;\n if (!view) return;\n const renderer = (view as unknown as { renderer?: HTMLElement }).renderer;\n if (renderer) {\n renderer.setAttribute('max-inline-size', newVal ? '9999' : '720');\n }\n }, []);\n\n const handleTocClick = useCallback((href: string) => {\n setActiveTocHref(href);\n setShowToc(false);\n viewRef.current?.goTo(href).catch(() => {});\n }, []);\n\n useImperativeHandle(ref, () => ({\n prevPage: handlePrev,\n nextPage: handleNext,\n toggleFullWidth,\n toggleToc,\n }), [handlePrev, handleNext, toggleFullWidth, toggleToc]);\n\n useEffect(() => {\n const host = hostRef.current;\n if (!host) return;\n\n setLoading(true);\n setError(null);\n setToc([]);\n setShowToc(false);\n setActiveTocHref('');\n host.replaceChildren();\n\n let cancelled = false;\n let view: FoliateView | null = null;\n\n const load = async () => {\n try {\n if (cancelled) return;\n\n view = document.createElement('foliate-view') as FoliateView;\n host.appendChild(view);\n viewRef.current = view;\n\n // 先注册事件\n view.addEventListener('relocate', (e: Event) => {\n const detail = (e as CustomEvent).detail;\n if (!detail) return;\n // SectionProgress 返回的 location 对象: { current, next, total }\n const loc = detail.location as { current?: number; total?: number } | undefined;\n if (loc && typeof loc.current === 'number' && typeof loc.total === 'number') {\n reportProgress(loc.current, loc.total);\n } else {\n // fallback:用 section 级别估算\n const sections = viewRef.current?.book?.sections ?? [];\n const idx = detail.index ?? 0;\n const frac = detail.fraction ?? 0;\n const total = Math.max(sections.length, 1);\n const current = Math.round((idx + frac) / total * total);\n reportProgress(current, total);\n }\n const tocItem = detail.tocItem as { href?: string } | undefined;\n if (tocItem?.href) {\n setActiveTocHref(tocItem.href);\n }\n });\n\n const res = await fetcher(url);\n if (!res.ok) throw new Error(`请求失败: ${res.status}`);\n const blob = await res.blob();\n let name = 'book.mobi';\n try {\n const u = new URL(url, window.location.href);\n const base = u.pathname.split('/').pop();\n if (base) name = decodeURIComponent(base);\n } catch { /* blob: URL */ }\n const file = new File([blob], name);\n\n await view.open(file);\n if (cancelled) { view.book?.destroy?.(); return; }\n\n // 配置 paginator:paginated 模式(默认),带动画\n const renderer = (view as unknown as { renderer: HTMLElement & {\n setStyles?: (css: string) => void;\n next?: () => Promise<void>;\n } }).renderer;\n\n if (renderer) {\n // flow=\"paginated\" 是默认值,不需要显式设置\n renderer.setAttribute('animated', '');\n renderer.setAttribute('max-inline-size', '720');\n renderer.setAttribute('margin', '48');\n renderer.setAttribute('gap', '5%');\n renderer.setStyles?.(READER_CSS);\n // 必须调 next() 渲染首页\n await renderer.next?.();\n }\n\n setToc(view.book?.toc ?? []);\n setLoading(false);\n reportProgress(0, view.book?.sections.length ?? 1);\n } catch (err) {\n console.error('MOBI/AZW3 加载错误:', err);\n if (!cancelled) {\n setError(t('mobi.load_failed'));\n setLoading(false);\n }\n }\n };\n\n load();\n\n return () => {\n cancelled = true;\n try { viewRef.current?.book?.destroy?.(); } catch { /* ignore */ }\n viewRef.current = null;\n host.replaceChildren();\n };\n }, [url, reportProgress]);\n\n const isActive = useCallback(\n (href: string | undefined) => !!href && href === activeTocHref,\n [activeTocHref]\n );\n\n const renderTocItems = (items: TocItem[], depth = 0) => (\n <ul style={{ listStyle: 'none', padding: 0, margin: depth > 0 ? '0 0 0 16px' : 0 }}>\n {items.map((item, i) => (\n <li key={`${item.href ?? item.label}-${i}`}>\n {item.href ? (\n <button\n onClick={() => handleTocClick(item.href!)}\n className={`rfp-w-full rfp-text-left rfp-py-2 rfp-px-3 rfp-text-sm rfp-rounded rfp-transition-all rfp-truncate ${\n isActive(item.href)\n ? 'rfp-text-fg-primary rfp-bg-surface-3 rfp-font-medium'\n : 'rfp-text-fg-secondary hover:rfp-text-fg-primary hover:rfp-bg-surface-2'\n }`}\n title={item.label}\n >\n {item.label?.trim()}\n </button>\n ) : (\n <div className=\"rfp-w-full rfp-py-2 rfp-px-3 rfp-text-sm rfp-text-fg-tertiary rfp-truncate\">\n {item.label?.trim()}\n </div>\n )}\n {item.subitems && item.subitems.length > 0 && renderTocItems(item.subitems, depth + 1)}\n </li>\n ))}\n </ul>\n );\n\n return (\n <div className=\"rfp-relative rfp-w-full rfp-h-full rfp-flex rfp-justify-center rfp-bg-[#f5f5f0] rfp-overflow-hidden\">\n {error && (\n <div className=\"rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-text-fg-secondary rfp-text-center rfp-p-6\">\n <p className=\"rfp-text-lg\">{error}</p>\n </div>\n )}\n\n {loading && !error && (\n <div className=\"rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-z-10\">\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 {toc.length > 0 && (\n <div\n className=\"rfp-absolute rfp-inset-0 rfp-z-20 rfp-flex rfp-transition-opacity rfp-duration-300\"\n style={{ opacity: showToc ? 1 : 0, pointerEvents: showToc ? 'auto' : 'none' }}\n >\n <div\n className=\"rfp-w-72 rfp-max-w-[80%] rfp-h-full rfp-bg-surface-overlay rfp-backdrop-blur-xl rfp-border-r rfp-border-line-weak rfp-flex rfp-flex-col rfp-shadow-2xl rfp-transition-transform rfp-duration-300\"\n style={{ transform: showToc ? 'translateX(0)' : 'translateX(-100%)' }}\n >\n <div className=\"rfp-flex rfp-items-center rfp-justify-between rfp-px-4 rfp-py-3 rfp-border-b rfp-border-line-weak rfp-flex-shrink-0\">\n <span className=\"rfp-text-fg-primary rfp-font-medium rfp-text-sm\">{t('toolbar.toc')}</span>\n <button\n onClick={() => setShowToc(false)}\n className=\"rfp-text-fg-tertiary hover:rfp-text-fg-primary rfp-transition-colors\"\n >\n <X className=\"rfp-w-4 rfp-h-4\" />\n </button>\n </div>\n <div className=\"rfp-flex-1 rfp-overflow-y-auto rfp-py-4 rfp-px-1\">\n {renderTocItems(toc)}\n </div>\n </div>\n <div\n className=\"rfp-flex-1 rfp-transition-opacity rfp-duration-300\"\n style={{ background: showToc ? 'rgba(0,0,0,0.3)' : 'transparent' }}\n onClick={() => setShowToc(false)}\n />\n </div>\n )}\n\n {!error && (\n <div\n ref={hostRef}\n className=\"rfp-h-full rfp-bg-surface-toolbar rfp-shadow-lg\"\n style={{\n width: isFullWidth ? '100%' : `${A4_WIDTH}px`,\n maxWidth: '100%',\n transition: 'width 0.3s ease',\n }}\n />\n )}\n </div>\n );\n }\n);\n\nMobiRenderer.displayName = 'MobiRenderer';\n"],"names":["READER_CSS","A4_WIDTH","MobiRenderer","forwardRef","url","onChapterChange","onFullWidthChange","ref","t","useTranslator","fetcher","useFetcher","hostRef","useRef","viewRef","onChapterChangeRef","onFullWidthChangeRef","totalLocationsRef","loading","setLoading","useState","error","setError","toc","setToc","showToc","setShowToc","activeTocHref","setActiveTocHref","isFullWidth","setIsFullWidth","isFullWidthRef","reportProgress","useCallback","current","total","_a","handlePrev","view","handleNext","toggleToc","prev","toggleFullWidth","newVal","renderer","handleTocClick","href","useImperativeHandle","useEffect","host","cancelled","e","detail","loc","sections","_b","idx","frac","tocItem","res","blob","name","base","file","_c","_d","_e","_f","err","isActive","renderTocItems","items","depth","item","i","jsxs","jsx","X"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-DdOEWhrk.mjs","sources":["../../src/renderers/Markdown/index.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } 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 } 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 'katex/dist/katex.min.css';\n\ninterface MarkdownRendererProps {\n url: string;\n viewMode?: 'preview' | 'source';\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: React.FC<MarkdownRendererProps> = ({ url, viewMode = 'preview' }) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const [content, setContent] = useState<string>('');\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const { html: sourceHtml } = useShikiHighlight(\n viewMode === 'source' ? content : '',\n 'markdown',\n );\n\n useEffect(() => {\n const loadMarkdown = async () => {\n try {\n setLoading(true);\n setError(null);\n const text = await fetchTextUtf8(url, { fetcher });\n setContent(text);\n } catch (err) {\n setError(t('markdown.load_failed'));\n console.error(err);\n } finally {\n setLoading(false);\n }\n };\n\n loadMarkdown();\n }, [url, fetcher, t]);\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 (\n <div className=\"rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full\">\n <div className=\"rfp-text-fg-secondary rfp-text-center\">\n <p className=\"rfp-text-lg\">{error}</p>\n </div>\n </div>\n );\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-p-6 md:rfp-p-10\">\n <div className=\"rfp-max-w-full md:rfp-max-w-4xl rfp-mx-auto\">\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 if (!inline && match) {\n // 有语言标注的代码块 - shiki 高亮\n return <ShikiCodeBlock code={codeString} lang={match[1]} />;\n }\n if (!inline) {\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 // 行内代码\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 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 </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","url","viewMode","fetcher","useFetcher","content","setContent","loading","setLoading","error","setError","sourceHtml","useEffect","fetchTextUtf8","err","ReactMarkdown","remarkGfm","remarkMath","rehypeRaw","rehypeKatex","node","inline","className","children","props","match","codeString","href","src","alt","type","checked"],"mappings":"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"}