@eternalheart/react-file-preview 1.3.9 → 1.3.10
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 +10 -0
- package/README.zh-CN.md +10 -0
- package/lib/FilePreviewContent.d.ts.map +1 -1
- package/lib/chunks/{index-B-H9HQiI.mjs → index-B0JUZ5rS.mjs} +10 -10
- package/lib/chunks/{index-B-H9HQiI.mjs.map → index-B0JUZ5rS.mjs.map} +1 -1
- package/lib/chunks/{index-r3q2xCCI.mjs → index-BAYc4aBz.mjs} +2 -2
- package/lib/chunks/{index-r3q2xCCI.mjs.map → index-BAYc4aBz.mjs.map} +1 -1
- package/lib/chunks/{index-BNUiNUWa.mjs → index-BOQJNL71.mjs} +2 -2
- package/lib/chunks/{index-BNUiNUWa.mjs.map → index-BOQJNL71.mjs.map} +1 -1
- package/lib/chunks/{index-BdYkTSTt.mjs → index-BkU8rK-0.mjs} +3 -3
- package/lib/chunks/{index-BdYkTSTt.mjs.map → index-BkU8rK-0.mjs.map} +1 -1
- package/lib/chunks/{index-CgV8T0G5.mjs → index-BnDoXBnH.mjs} +2 -2
- package/lib/chunks/{index-CgV8T0G5.mjs.map → index-BnDoXBnH.mjs.map} +1 -1
- package/lib/chunks/index-C5YHI0Zs.mjs +160 -0
- package/lib/chunks/index-C5YHI0Zs.mjs.map +1 -0
- package/lib/chunks/{index-Bv93wiEK.mjs → index-CGNWXFy3.mjs} +716 -666
- package/lib/chunks/index-CGNWXFy3.mjs.map +1 -0
- package/lib/chunks/{index-DdOEWhrk.mjs → index-CwmZQ-JO.mjs} +16 -16
- package/lib/chunks/{index-DdOEWhrk.mjs.map → index-CwmZQ-JO.mjs.map} +1 -1
- package/lib/chunks/{index-CKirCT35.mjs → index-CzflrElZ.mjs} +5 -5
- package/lib/chunks/{index-CKirCT35.mjs.map → index-CzflrElZ.mjs.map} +1 -1
- package/lib/chunks/{index-D8GtNeDn.mjs → index-CztCCF7q.mjs} +2 -2
- package/lib/chunks/{index-D8GtNeDn.mjs.map → index-CztCCF7q.mjs.map} +1 -1
- package/lib/chunks/{index-BGeyzo6u.mjs → index-DKEcGewg.mjs} +2 -2
- package/lib/chunks/{index-BGeyzo6u.mjs.map → index-DKEcGewg.mjs.map} +1 -1
- package/lib/chunks/{index-DV5Jd7Qe.mjs → index-DN8BQIqo.mjs} +2 -2
- package/lib/chunks/{index-DV5Jd7Qe.mjs.map → index-DN8BQIqo.mjs.map} +1 -1
- package/lib/chunks/{index-zEVVgWCH.mjs → index-DPpUj8Yy.mjs} +2 -2
- package/lib/chunks/{index-zEVVgWCH.mjs.map → index-DPpUj8Yy.mjs.map} +1 -1
- package/lib/chunks/{index-BSD3w5eG.mjs → index-DSAXdrgU.mjs} +2 -2
- package/lib/chunks/{index-BSD3w5eG.mjs.map → index-DSAXdrgU.mjs.map} +1 -1
- package/lib/chunks/{index-DGuiWJr7.mjs → index-DveR0rOk.mjs} +15 -15
- package/lib/chunks/{index-DGuiWJr7.mjs.map → index-DveR0rOk.mjs.map} +1 -1
- package/lib/chunks/{index-BqEuP_8r.mjs → index-QfO-sASN.mjs} +2 -2
- package/lib/chunks/{index-BqEuP_8r.mjs.map → index-QfO-sASN.mjs.map} +1 -1
- package/lib/chunks/{index-BcBe6KW7.mjs → index-h9bO9wmq.mjs} +4 -4
- package/lib/chunks/{index-BcBe6KW7.mjs.map → index-h9bO9wmq.mjs.map} +1 -1
- package/lib/chunks/index-mvSVNKlQ.mjs +228 -0
- package/lib/chunks/index-mvSVNKlQ.mjs.map +1 -0
- package/lib/chunks/{index-U3w45GW8.mjs → index-tecGXW2S.mjs} +43 -43
- package/lib/chunks/{index-U3w45GW8.mjs.map → index-tecGXW2S.mjs.map} +1 -1
- package/lib/chunks/{useShikiHighlight-DzEAK0S7.mjs → useShikiHighlight-DHFYu0BU.mjs} +3 -3
- package/lib/chunks/{useShikiHighlight-DzEAK0S7.mjs.map → useShikiHighlight-DHFYu0BU.mjs.map} +1 -1
- package/lib/index.cjs +22 -18
- package/lib/index.cjs.map +1 -1
- package/lib/index.css +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.mjs +13 -12
- package/lib/renderers/Font/index.d.ts +6 -0
- package/lib/renderers/Font/index.d.ts.map +1 -0
- package/lib/renderers/Pdf/index.d.ts +0 -1
- package/lib/renderers/Pdf/index.d.ts.map +1 -1
- package/lib/renderers/lazy.d.ts +2 -0
- package/lib/renderers/lazy.d.ts.map +1 -1
- package/lib/utils/pdfConfig.d.ts +2 -2
- package/lib/utils/pdfConfig.d.ts.map +1 -1
- package/package.json +3 -2
- package/lib/chunks/index-Bv93wiEK.mjs.map +0 -1
- package/lib/chunks/index-DmepcY31.mjs +0 -96
- package/lib/chunks/index-DmepcY31.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -304,6 +304,10 @@ const files = [
|
|
|
304
304
|
- **Excel**: XLSX format support
|
|
305
305
|
- **PowerPoint**: PPTX/PPT format support, slide preview
|
|
306
306
|
|
|
307
|
+
### Fonts
|
|
308
|
+
- **Formats**: TTF, OTF, WOFF, WOFF2
|
|
309
|
+
- **Features**: Font metadata (family, designer, version), character set preview, custom text input, multi-size display
|
|
310
|
+
|
|
307
311
|
### Code & Text
|
|
308
312
|
- **Markdown**: GitHub Flavored Markdown, code highlighting
|
|
309
313
|
- **Code Files**: JS, TS, Python, Java, C++, Go, Rust, and 40+ languages
|
|
@@ -442,6 +446,12 @@ const files = [
|
|
|
442
446
|
#### Other Documents
|
|
443
447
|
- **PDF**: `application/pdf`
|
|
444
448
|
|
|
449
|
+
#### Fonts
|
|
450
|
+
- **TrueType**: `application/x-font-ttf`, `font/ttf` (.ttf)
|
|
451
|
+
- **OpenType**: `application/x-font-otf`, `font/otf` (.otf)
|
|
452
|
+
- **WOFF**: `application/font-woff`, `font/woff` (.woff)
|
|
453
|
+
- **WOFF2**: `application/font-woff2`, `font/woff2` (.woff2)
|
|
454
|
+
|
|
445
455
|
#### Media Files
|
|
446
456
|
- **Images**: `image/jpeg`, `image/png`, `image/gif`, `image/webp`, `image/svg+xml`, etc.
|
|
447
457
|
- **Videos**: `video/mp4`, `video/webm`, `video/ogg`, etc.
|
package/README.zh-CN.md
CHANGED
|
@@ -302,6 +302,10 @@ const files = [
|
|
|
302
302
|
- **Excel**: XLSX 格式支持
|
|
303
303
|
- **PowerPoint**: PPTX/PPT 格式支持、幻灯片预览
|
|
304
304
|
|
|
305
|
+
### 字体
|
|
306
|
+
- **格式**: TTF, OTF, WOFF, WOFF2
|
|
307
|
+
- **功能**: 字体元数据(字体家族、设计师、版本)、字符集预览、自定义文本输入、多字号展示
|
|
308
|
+
|
|
305
309
|
### 代码 & 文本
|
|
306
310
|
- **Markdown**: GitHub Flavored Markdown,代码高亮
|
|
307
311
|
- **代码文件**: JS, TS, Python, Java, C++, Go, Rust 等 40+ 种语言
|
|
@@ -440,6 +444,12 @@ const files = [
|
|
|
440
444
|
#### 其他文档
|
|
441
445
|
- **PDF**: `application/pdf`
|
|
442
446
|
|
|
447
|
+
#### 字体
|
|
448
|
+
- **TrueType**: `application/x-font-ttf`, `font/ttf` (.ttf)
|
|
449
|
+
- **OpenType**: `application/x-font-otf`, `font/otf` (.otf)
|
|
450
|
+
- **WOFF**: `application/font-woff`, `font/woff` (.woff)
|
|
451
|
+
- **WOFF2**: `application/font-woff2`, `font/woff2` (.woff2)
|
|
452
|
+
|
|
443
453
|
#### 媒体文件
|
|
444
454
|
- **图片**: `image/jpeg`, `image/png`, `image/gif`, `image/webp`, `image/svg+xml`, 等
|
|
445
455
|
- **视频**: `video/mp4`, `video/webm`, `video/ogg`, 等
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilePreviewContent.d.ts","sourceRoot":"","sources":["../src/FilePreviewContent.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsE,MAAM,OAAO,CAAC;AAG3F,OAAO,EAAiC,KAAK,MAAM,EAAE,KAAK,QAAQ,EAAmB,KAAK,KAAK,EAAE,MAAM,iCAAiC,CAAC;AAYzI,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAyB,MAAM,SAAS,CAAC;AAClF,OAAO,KAAK,EAAE,0BAA0B,EAAE,WAAW,EAAE,cAAc,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"FilePreviewContent.d.ts","sourceRoot":"","sources":["../src/FilePreviewContent.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsE,MAAM,OAAO,CAAC;AAG3F,OAAO,EAAiC,KAAK,MAAM,EAAE,KAAK,QAAQ,EAAmB,KAAK,KAAK,EAAE,MAAM,iCAAiC,CAAC;AAYzI,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAyB,MAAM,SAAS,CAAC;AAClF,OAAO,KAAK,EAAE,0BAA0B,EAAE,WAAW,EAAE,cAAc,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAiCtJ,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;IACnC,iCAAiC;IACjC,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IACzB,wBAAwB;IACxB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,qCAAqC;IACrC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtD,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,kDAAkD;IAClD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,0BAA0B,KAAK,IAAI,CAAC;IAC5D,qDAAqD;IACrD,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,oEAAoE;IACpE,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,kFAAkF;IAClF,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1D;AAED,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAWhE,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as r, jsxs as s, Fragment as N } from "react/jsx-runtime";
|
|
2
2
|
import { useMemo as j, useState as m, useEffect as v, useCallback as S } from "react";
|
|
3
3
|
import { ChevronDown as L, ChevronRight as $ } from "lucide-react";
|
|
4
|
-
import { u as k, a as C,
|
|
4
|
+
import { u as k, a as C, b as O, F as E } from "./index-CGNWXFy3.mjs";
|
|
5
5
|
const R = {
|
|
6
6
|
key: "#9cdcfe",
|
|
7
7
|
string: "#ce9178",
|
|
@@ -20,7 +20,7 @@ const R = {
|
|
|
20
20
|
colon: "rgb(23 23 23 / 0.6)",
|
|
21
21
|
collapsed: "rgb(23 23 23 / 0.45)",
|
|
22
22
|
arrow: "rgb(23 23 23 / 0.55)"
|
|
23
|
-
},
|
|
23
|
+
}, g = ({ keyName: e, value: n, depth: f, defaultExpanded: i, colors: t }) => {
|
|
24
24
|
const d = k(), [a, y] = m(i), p = f * 20, h = S(() => y((o) => !o), []);
|
|
25
25
|
if (n == null || typeof n != "object")
|
|
26
26
|
return /* @__PURE__ */ s("div", { className: "rfp-flex rfp-items-start rfp-py-px rfp-font-mono rfp-text-sm", style: { paddingLeft: `${p}px` }, children: [
|
|
@@ -33,7 +33,7 @@ const R = {
|
|
|
33
33
|
] }),
|
|
34
34
|
A(n, t)
|
|
35
35
|
] });
|
|
36
|
-
const l = Array.isArray(n), c = (l ? n : Object.entries(n)).length,
|
|
36
|
+
const l = Array.isArray(n), c = (l ? n : Object.entries(n)).length, b = l ? "[" : "{", u = l ? "]" : "}";
|
|
37
37
|
return c === 0 ? /* @__PURE__ */ s("div", { className: "rfp-flex rfp-items-start rfp-py-px rfp-font-mono rfp-text-sm", style: { paddingLeft: `${p}px` }, children: [
|
|
38
38
|
/* @__PURE__ */ r("span", { className: "rfp-w-4 rfp-h-5 rfp-flex-shrink-0" }),
|
|
39
39
|
e !== void 0 && /* @__PURE__ */ s("span", { className: "rfp-flex-shrink-0", style: { color: t.key }, children: [
|
|
@@ -43,7 +43,7 @@ const R = {
|
|
|
43
43
|
/* @__PURE__ */ r("span", { style: { color: t.colon }, children: ": " })
|
|
44
44
|
] }),
|
|
45
45
|
/* @__PURE__ */ s("span", { style: { color: t.bracket }, children: [
|
|
46
|
-
|
|
46
|
+
b,
|
|
47
47
|
u
|
|
48
48
|
] })
|
|
49
49
|
] }) : /* @__PURE__ */ s("div", { children: [
|
|
@@ -61,7 +61,7 @@ const R = {
|
|
|
61
61
|
'"',
|
|
62
62
|
/* @__PURE__ */ r("span", { style: { color: t.colon }, children: ": " })
|
|
63
63
|
] }),
|
|
64
|
-
/* @__PURE__ */ r("span", { style: { color: t.bracket }, children:
|
|
64
|
+
/* @__PURE__ */ r("span", { style: { color: t.bracket }, children: b }),
|
|
65
65
|
!a && /* @__PURE__ */ s("span", { className: "rfp-ml-1", style: { color: t.collapsed }, children: [
|
|
66
66
|
l ? `${c} ${d("json.items")}` : `${c} ${d("json.keys")}`,
|
|
67
67
|
/* @__PURE__ */ s("span", { style: { color: t.bracket }, children: [
|
|
@@ -73,7 +73,7 @@ const R = {
|
|
|
73
73
|
}
|
|
74
74
|
),
|
|
75
75
|
a && /* @__PURE__ */ s(N, { children: [
|
|
76
|
-
l ? n.map((o, x) => /* @__PURE__ */ r(
|
|
76
|
+
l ? n.map((o, x) => /* @__PURE__ */ r(g, { value: o, depth: f + 1, defaultExpanded: f < 1, colors: t }, x)) : Object.entries(n).map(([o, x]) => /* @__PURE__ */ r(g, { keyName: o, value: x, depth: f + 1, defaultExpanded: f < 1, colors: t }, o)),
|
|
77
77
|
/* @__PURE__ */ r("div", { className: "rfp-font-mono rfp-text-sm rfp-py-px", style: { paddingLeft: `${p + 20}px`, color: t.bracket }, children: u })
|
|
78
78
|
] })
|
|
79
79
|
] });
|
|
@@ -85,11 +85,11 @@ function A(e, n) {
|
|
|
85
85
|
'"'
|
|
86
86
|
] }) : /* @__PURE__ */ r("span", { style: { color: n.bracket }, children: String(e) });
|
|
87
87
|
}
|
|
88
|
-
function
|
|
88
|
+
function F(e) {
|
|
89
89
|
return e === "light" ? J : R;
|
|
90
90
|
}
|
|
91
91
|
const G = ({ url: e }) => {
|
|
92
|
-
const n = k(), f = C(), i = O(), t = j(() =>
|
|
92
|
+
const n = k(), f = C(), i = O(), t = j(() => F(i), [i]), [d, a] = m(null), [y, p] = m(!0), [h, l] = m(null);
|
|
93
93
|
return v(() => {
|
|
94
94
|
(async () => {
|
|
95
95
|
try {
|
|
@@ -102,9 +102,9 @@ const G = ({ url: e }) => {
|
|
|
102
102
|
p(!1);
|
|
103
103
|
}
|
|
104
104
|
})();
|
|
105
|
-
}, [e]), y ? /* @__PURE__ */ r("div", { className: "rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full", children: /* @__PURE__ */ r("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" }) }) : h ? /* @__PURE__ */ r("div", { className: "rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full", children: /* @__PURE__ */ r("div", { className: "rfp-text-fg-secondary rfp-text-center", children: /* @__PURE__ */ r("p", { className: "rfp-text-lg", children: h }) }) }) : /* @__PURE__ */ r("div", { className: "rfp-w-full rfp-h-full rfp-overflow-auto rfp-bg-code-bg rfp-py-3 rfp-pr-4", children: /* @__PURE__ */ r(
|
|
105
|
+
}, [e]), y ? /* @__PURE__ */ r("div", { className: "rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full", children: /* @__PURE__ */ r("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" }) }) : h ? /* @__PURE__ */ r("div", { className: "rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full", children: /* @__PURE__ */ r("div", { className: "rfp-text-fg-secondary rfp-text-center", children: /* @__PURE__ */ r("p", { className: "rfp-text-lg", children: h }) }) }) : /* @__PURE__ */ r("div", { className: "rfp-w-full rfp-h-full rfp-overflow-auto rfp-bg-code-bg rfp-py-3 rfp-pr-4", children: /* @__PURE__ */ r(g, { value: d, depth: 0, defaultExpanded: !0, colors: t }) });
|
|
106
106
|
};
|
|
107
107
|
export {
|
|
108
108
|
G as JsonRenderer
|
|
109
109
|
};
|
|
110
|
-
//# sourceMappingURL=index-
|
|
110
|
+
//# sourceMappingURL=index-B0JUZ5rS.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-B-H9HQiI.mjs","sources":["../../src/renderers/Json/index.tsx"],"sourcesContent":["import { useState, useEffect, useCallback, useMemo } from 'react';\nimport { ChevronRight, ChevronDown } from 'lucide-react';\nimport { fetchTextUtf8 } from '@eternalheart/file-preview-core';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\nimport { useResolvedTheme, type ResolvedTheme } from '../../ThemeContext';\n\ninterface JsonRendererProps {\n url: string;\n fileName: string;\n}\n\ninterface JsonColors {\n key: string;\n string: string;\n number: string;\n keyword: string;\n bracket: string; // { } [ ]\n colon: string; // :\n collapsed: string; // \"N items / N keys\" 折叠提示\n arrow: string; // 折叠箭头\n}\n\n// VSCode Dark Plus / GitHub Light 两套配色,与 react-syntax-highlighter 的 vscDarkPlus / vs 主题保持一致\nconst DARK_COLORS: JsonColors = {\n key: '#9cdcfe',\n string: '#ce9178',\n number: '#b5cea8',\n keyword: '#569cd6',\n bracket: '#d4d4d4',\n colon: 'rgb(255 255 255 / 0.6)',\n collapsed: 'rgb(255 255 255 / 0.4)',\n arrow: 'rgb(255 255 255 / 0.5)',\n};\n\nconst LIGHT_COLORS: JsonColors = {\n key: '#005cc5',\n string: '#032f62',\n number: '#005cc5',\n keyword: '#d73a49',\n bracket: '#24292e',\n colon: 'rgb(23 23 23 / 0.6)',\n collapsed: 'rgb(23 23 23 / 0.45)',\n arrow: 'rgb(23 23 23 / 0.55)',\n};\n\n// ---------- JSON 树节点 ----------\n\ninterface JsonNodeProps {\n keyName?: string;\n value: unknown;\n depth: number;\n defaultExpanded: boolean;\n colors: JsonColors;\n}\n\nconst JsonNode: React.FC<JsonNodeProps> = ({ keyName, value, depth, defaultExpanded, colors }) => {\n const t = useTranslator();\n const [expanded, setExpanded] = useState(defaultExpanded);\n const indent = depth * 20;\n\n const toggle = useCallback(() => setExpanded(prev => !prev), []);\n\n // 基本类型\n if (value === null || value === undefined || typeof value !== 'object') {\n return (\n <div className=\"rfp-flex rfp-items-start rfp-py-px rfp-font-mono rfp-text-sm\" style={{ paddingLeft: `${indent}px` }}>\n <span className=\"rfp-w-4 rfp-h-5 rfp-flex-shrink-0\" />\n {keyName !== undefined && (\n <span className=\"rfp-flex-shrink-0\" style={{ color: colors.key }}>\n \"{keyName}\"<span style={{ color: colors.colon }}>: </span>\n </span>\n )}\n {renderPrimitive(value, colors)}\n </div>\n );\n }\n\n const isArray = Array.isArray(value);\n const entries = isArray ? (value as unknown[]) : Object.entries(value as Record<string, unknown>);\n const count = entries.length;\n const openBracket = isArray ? '[' : '{';\n const closeBracket = isArray ? ']' : '}';\n\n // 空对象/数组\n if (count === 0) {\n return (\n <div className=\"rfp-flex rfp-items-start rfp-py-px rfp-font-mono rfp-text-sm\" style={{ paddingLeft: `${indent}px` }}>\n <span className=\"rfp-w-4 rfp-h-5 rfp-flex-shrink-0\" />\n {keyName !== undefined && (\n <span className=\"rfp-flex-shrink-0\" style={{ color: colors.key }}>\n \"{keyName}\"<span style={{ color: colors.colon }}>: </span>\n </span>\n )}\n <span style={{ color: colors.bracket }}>{openBracket}{closeBracket}</span>\n </div>\n );\n }\n\n return (\n <div>\n {/* 折叠行 */}\n <div\n className=\"rfp-flex rfp-items-start rfp-py-px rfp-font-mono rfp-text-sm rfp-cursor-pointer hover:rfp-bg-surface-1 rfp-select-none\"\n style={{ paddingLeft: `${indent}px` }}\n onClick={toggle}\n >\n <span className=\"rfp-w-4 rfp-h-5 rfp-flex-shrink-0 rfp-flex rfp-items-center rfp-justify-center\" style={{ color: colors.arrow }}>\n {expanded\n ? <ChevronDown className=\"rfp-w-3.5 rfp-h-3.5\" />\n : <ChevronRight className=\"rfp-w-3.5 rfp-h-3.5\" />\n }\n </span>\n {keyName !== undefined && (\n <span className=\"rfp-flex-shrink-0\" style={{ color: colors.key }}>\n \"{keyName}\"<span style={{ color: colors.colon }}>: </span>\n </span>\n )}\n <span style={{ color: colors.bracket }}>{openBracket}</span>\n {!expanded && (\n <span className=\"rfp-ml-1\" style={{ color: colors.collapsed }}>\n {isArray ? `${count} ${t('json.items')}` : `${count} ${t('json.keys')}`}\n <span style={{ color: colors.bracket }}> {closeBracket}</span>\n </span>\n )}\n </div>\n\n {/* 子节点 */}\n {expanded && (\n <>\n {isArray\n ? (value as unknown[]).map((item, i) => (\n <JsonNode key={i} value={item} depth={depth + 1} defaultExpanded={depth < 1} colors={colors} />\n ))\n : Object.entries(value as Record<string, unknown>).map(([k, v]) => (\n <JsonNode key={k} keyName={k} value={v} depth={depth + 1} defaultExpanded={depth < 1} colors={colors} />\n ))\n }\n <div className=\"rfp-font-mono rfp-text-sm rfp-py-px\" style={{ paddingLeft: `${indent + 20}px`, color: colors.bracket }}>\n {closeBracket}\n </div>\n </>\n )}\n </div>\n );\n};\n\nfunction renderPrimitive(value: unknown, colors: JsonColors) {\n if (value === null) return <span style={{ color: colors.keyword, fontStyle: 'italic' }}>null</span>;\n if (value === undefined) return <span style={{ color: colors.keyword, fontStyle: 'italic' }}>undefined</span>;\n if (typeof value === 'boolean') return <span style={{ color: colors.keyword }}>{String(value)}</span>;\n if (typeof value === 'number') return <span style={{ color: colors.number }}>{String(value)}</span>;\n if (typeof value === 'string') return <span style={{ color: colors.string }}>\"{value}\"</span>;\n return <span style={{ color: colors.bracket }}>{String(value)}</span>;\n}\n\nfunction pickColors(theme: ResolvedTheme): JsonColors {\n return theme === 'light' ? LIGHT_COLORS : DARK_COLORS;\n}\n\n// ---------- Main ----------\n\nexport const JsonRenderer: React.FC<JsonRendererProps> = ({ url }) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const resolvedTheme = useResolvedTheme();\n const colors = useMemo(() => pickColors(resolvedTheme), [resolvedTheme]);\n const [data, setData] = useState<unknown>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const loadJson = async () => {\n try {\n setLoading(true);\n setError(null);\n const text = await fetchTextUtf8(url, { fetcher });\n setData(JSON.parse(text));\n } catch (err) {\n setError(t('json.load_failed'));\n console.error(err);\n } finally {\n setLoading(false);\n }\n };\n loadJson();\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) {\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 return (\n <div className=\"rfp-w-full rfp-h-full rfp-overflow-auto rfp-bg-code-bg rfp-py-3 rfp-pr-4\">\n <JsonNode value={data} depth={0} defaultExpanded colors={colors} />\n </div>\n );\n};\n"],"names":["DARK_COLORS","LIGHT_COLORS","JsonNode","keyName","value","depth","defaultExpanded","colors","t","useTranslator","expanded","setExpanded","useState","indent","toggle","useCallback","prev","jsxs","jsx","renderPrimitive","isArray","count","openBracket","closeBracket","ChevronDown","ChevronRight","Fragment","item","i","k","v","pickColors","theme","JsonRenderer","url","fetcher","useFetcher","resolvedTheme","useResolvedTheme","useMemo","data","setData","loading","setLoading","error","setError","useEffect","text","fetchTextUtf8","err"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-B0JUZ5rS.mjs","sources":["../../src/renderers/Json/index.tsx"],"sourcesContent":["import { useState, useEffect, useCallback, useMemo } from 'react';\nimport { ChevronRight, ChevronDown } from 'lucide-react';\nimport { fetchTextUtf8 } from '@eternalheart/file-preview-core';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\nimport { useResolvedTheme, type ResolvedTheme } from '../../ThemeContext';\n\ninterface JsonRendererProps {\n url: string;\n fileName: string;\n}\n\ninterface JsonColors {\n key: string;\n string: string;\n number: string;\n keyword: string;\n bracket: string; // { } [ ]\n colon: string; // :\n collapsed: string; // \"N items / N keys\" 折叠提示\n arrow: string; // 折叠箭头\n}\n\n// VSCode Dark Plus / GitHub Light 两套配色,与 react-syntax-highlighter 的 vscDarkPlus / vs 主题保持一致\nconst DARK_COLORS: JsonColors = {\n key: '#9cdcfe',\n string: '#ce9178',\n number: '#b5cea8',\n keyword: '#569cd6',\n bracket: '#d4d4d4',\n colon: 'rgb(255 255 255 / 0.6)',\n collapsed: 'rgb(255 255 255 / 0.4)',\n arrow: 'rgb(255 255 255 / 0.5)',\n};\n\nconst LIGHT_COLORS: JsonColors = {\n key: '#005cc5',\n string: '#032f62',\n number: '#005cc5',\n keyword: '#d73a49',\n bracket: '#24292e',\n colon: 'rgb(23 23 23 / 0.6)',\n collapsed: 'rgb(23 23 23 / 0.45)',\n arrow: 'rgb(23 23 23 / 0.55)',\n};\n\n// ---------- JSON 树节点 ----------\n\ninterface JsonNodeProps {\n keyName?: string;\n value: unknown;\n depth: number;\n defaultExpanded: boolean;\n colors: JsonColors;\n}\n\nconst JsonNode: React.FC<JsonNodeProps> = ({ keyName, value, depth, defaultExpanded, colors }) => {\n const t = useTranslator();\n const [expanded, setExpanded] = useState(defaultExpanded);\n const indent = depth * 20;\n\n const toggle = useCallback(() => setExpanded(prev => !prev), []);\n\n // 基本类型\n if (value === null || value === undefined || typeof value !== 'object') {\n return (\n <div className=\"rfp-flex rfp-items-start rfp-py-px rfp-font-mono rfp-text-sm\" style={{ paddingLeft: `${indent}px` }}>\n <span className=\"rfp-w-4 rfp-h-5 rfp-flex-shrink-0\" />\n {keyName !== undefined && (\n <span className=\"rfp-flex-shrink-0\" style={{ color: colors.key }}>\n \"{keyName}\"<span style={{ color: colors.colon }}>: </span>\n </span>\n )}\n {renderPrimitive(value, colors)}\n </div>\n );\n }\n\n const isArray = Array.isArray(value);\n const entries = isArray ? (value as unknown[]) : Object.entries(value as Record<string, unknown>);\n const count = entries.length;\n const openBracket = isArray ? '[' : '{';\n const closeBracket = isArray ? ']' : '}';\n\n // 空对象/数组\n if (count === 0) {\n return (\n <div className=\"rfp-flex rfp-items-start rfp-py-px rfp-font-mono rfp-text-sm\" style={{ paddingLeft: `${indent}px` }}>\n <span className=\"rfp-w-4 rfp-h-5 rfp-flex-shrink-0\" />\n {keyName !== undefined && (\n <span className=\"rfp-flex-shrink-0\" style={{ color: colors.key }}>\n \"{keyName}\"<span style={{ color: colors.colon }}>: </span>\n </span>\n )}\n <span style={{ color: colors.bracket }}>{openBracket}{closeBracket}</span>\n </div>\n );\n }\n\n return (\n <div>\n {/* 折叠行 */}\n <div\n className=\"rfp-flex rfp-items-start rfp-py-px rfp-font-mono rfp-text-sm rfp-cursor-pointer hover:rfp-bg-surface-1 rfp-select-none\"\n style={{ paddingLeft: `${indent}px` }}\n onClick={toggle}\n >\n <span className=\"rfp-w-4 rfp-h-5 rfp-flex-shrink-0 rfp-flex rfp-items-center rfp-justify-center\" style={{ color: colors.arrow }}>\n {expanded\n ? <ChevronDown className=\"rfp-w-3.5 rfp-h-3.5\" />\n : <ChevronRight className=\"rfp-w-3.5 rfp-h-3.5\" />\n }\n </span>\n {keyName !== undefined && (\n <span className=\"rfp-flex-shrink-0\" style={{ color: colors.key }}>\n \"{keyName}\"<span style={{ color: colors.colon }}>: </span>\n </span>\n )}\n <span style={{ color: colors.bracket }}>{openBracket}</span>\n {!expanded && (\n <span className=\"rfp-ml-1\" style={{ color: colors.collapsed }}>\n {isArray ? `${count} ${t('json.items')}` : `${count} ${t('json.keys')}`}\n <span style={{ color: colors.bracket }}> {closeBracket}</span>\n </span>\n )}\n </div>\n\n {/* 子节点 */}\n {expanded && (\n <>\n {isArray\n ? (value as unknown[]).map((item, i) => (\n <JsonNode key={i} value={item} depth={depth + 1} defaultExpanded={depth < 1} colors={colors} />\n ))\n : Object.entries(value as Record<string, unknown>).map(([k, v]) => (\n <JsonNode key={k} keyName={k} value={v} depth={depth + 1} defaultExpanded={depth < 1} colors={colors} />\n ))\n }\n <div className=\"rfp-font-mono rfp-text-sm rfp-py-px\" style={{ paddingLeft: `${indent + 20}px`, color: colors.bracket }}>\n {closeBracket}\n </div>\n </>\n )}\n </div>\n );\n};\n\nfunction renderPrimitive(value: unknown, colors: JsonColors) {\n if (value === null) return <span style={{ color: colors.keyword, fontStyle: 'italic' }}>null</span>;\n if (value === undefined) return <span style={{ color: colors.keyword, fontStyle: 'italic' }}>undefined</span>;\n if (typeof value === 'boolean') return <span style={{ color: colors.keyword }}>{String(value)}</span>;\n if (typeof value === 'number') return <span style={{ color: colors.number }}>{String(value)}</span>;\n if (typeof value === 'string') return <span style={{ color: colors.string }}>\"{value}\"</span>;\n return <span style={{ color: colors.bracket }}>{String(value)}</span>;\n}\n\nfunction pickColors(theme: ResolvedTheme): JsonColors {\n return theme === 'light' ? LIGHT_COLORS : DARK_COLORS;\n}\n\n// ---------- Main ----------\n\nexport const JsonRenderer: React.FC<JsonRendererProps> = ({ url }) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const resolvedTheme = useResolvedTheme();\n const colors = useMemo(() => pickColors(resolvedTheme), [resolvedTheme]);\n const [data, setData] = useState<unknown>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const loadJson = async () => {\n try {\n setLoading(true);\n setError(null);\n const text = await fetchTextUtf8(url, { fetcher });\n setData(JSON.parse(text));\n } catch (err) {\n setError(t('json.load_failed'));\n console.error(err);\n } finally {\n setLoading(false);\n }\n };\n loadJson();\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) {\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 return (\n <div className=\"rfp-w-full rfp-h-full rfp-overflow-auto rfp-bg-code-bg rfp-py-3 rfp-pr-4\">\n <JsonNode value={data} depth={0} defaultExpanded colors={colors} />\n </div>\n );\n};\n"],"names":["DARK_COLORS","LIGHT_COLORS","JsonNode","keyName","value","depth","defaultExpanded","colors","t","useTranslator","expanded","setExpanded","useState","indent","toggle","useCallback","prev","jsxs","jsx","renderPrimitive","isArray","count","openBracket","closeBracket","ChevronDown","ChevronRight","Fragment","item","i","k","v","pickColors","theme","JsonRenderer","url","fetcher","useFetcher","resolvedTheme","useResolvedTheme","useMemo","data","setData","loading","setLoading","error","setError","useEffect","text","fetchTextUtf8","err"],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ import { FileSpreadsheet as M } from "lucide-react";
|
|
|
4
4
|
import z from "exceljs";
|
|
5
5
|
import W from "x-data-spreadsheet";
|
|
6
6
|
/* empty css */
|
|
7
|
-
import { u as j, a as L, z as S } from "./index-
|
|
7
|
+
import { u as j, a as L, z as S } from "./index-CGNWXFy3.mjs";
|
|
8
8
|
const A = ({ url: x }) => {
|
|
9
9
|
const a = j(), R = L(), [w, g] = k(!0), [b, N] = k(null), e = i(null), v = i(null), l = i(null), d = i(null), p = i(null), y = i({ width: 0, height: 0 }), c = E(() => {
|
|
10
10
|
if (!e.current) return { width: 800, height: 600 };
|
|
@@ -126,4 +126,4 @@ const A = ({ url: x }) => {
|
|
|
126
126
|
export {
|
|
127
127
|
A as XlsxRenderer
|
|
128
128
|
};
|
|
129
|
-
//# sourceMappingURL=index-
|
|
129
|
+
//# sourceMappingURL=index-BAYc4aBz.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-r3q2xCCI.mjs","sources":["../../src/renderers/Xlsx/index.tsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback } from 'react';\nimport { FileSpreadsheet } from 'lucide-react';\nimport ExcelJS from 'exceljs';\nimport Spreadsheet from 'x-data-spreadsheet';\nimport 'x-data-spreadsheet/dist/xspreadsheet.css';\nimport { convertWorkbookToSpreadsheetData } from '../../utils/excelDataConverter';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\n\ninterface XlsxRendererProps {\n url: string;\n}\n\nexport const XlsxRenderer: React.FC<XlsxRendererProps> = ({ 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 containerRef = useRef<HTMLDivElement>(null);\n const spreadsheetRef = useRef<Spreadsheet | null>(null);\n const sheetDataRef = useRef<Record<string, unknown>[] | null>(null);\n const resizeObserverRef = useRef<ResizeObserver | null>(null);\n const resizeTimeoutRef = useRef<number | null>(null);\n const lastDimensionsRef = useRef({ width: 0, height: 0 });\n\n const calculateDimensions = useCallback(() => {\n if (!containerRef.current) return { width: 800, height: 600 };\n const rawWidth = containerRef.current.clientWidth;\n const rawHeight = containerRef.current.clientHeight;\n const width = rawWidth > 100 ? rawWidth : 800;\n const height = rawHeight > 100 ? rawHeight : 600;\n return { width, height };\n }, []);\n\n const mountSpreadsheet = useCallback(() => {\n if (!containerRef.current || !sheetDataRef.current) return;\n\n // 清空容器\n containerRef.current.innerHTML = '';\n spreadsheetRef.current = null;\n\n const { width, height } = calculateDimensions();\n const isMobile = width < 640;\n\n const s = new Spreadsheet(containerRef.current, {\n mode: 'read',\n showToolbar: false,\n showContextmenu: false,\n showGrid: true,\n row: {\n len: 100,\n height: 25,\n },\n col: {\n len: 26,\n width: isMobile ? 80 : 100,\n indexWidth: isMobile ? 40 : 60,\n minWidth: isMobile ? 40 : 60,\n },\n view: {\n height: () => height,\n width: () => width,\n },\n });\n\n s.loadData(sheetDataRef.current as unknown as Record<string, unknown>);\n spreadsheetRef.current = s;\n }, [calculateDimensions]);\n\n // 监听容器尺寸变化\n useEffect(() => {\n if (!containerRef.current) return;\n\n let isInitialRender = true;\n\n const updateDimensions = () => {\n if (isInitialRender) {\n isInitialRender = false;\n lastDimensionsRef.current = calculateDimensions();\n return;\n }\n\n const newDimensions = calculateDimensions();\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) return;\n\n lastDimensionsRef.current = newDimensions;\n\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n\n resizeTimeoutRef.current = window.setTimeout(() => {\n if (sheetDataRef.current) {\n mountSpreadsheet();\n }\n }, 500);\n };\n\n resizeObserverRef.current = new ResizeObserver(() => {\n updateDimensions();\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, mountSpreadsheet]);\n\n useEffect(() => {\n let isMounted = true;\n\n const loadExcel = async () => {\n if (!containerRef.current) return;\n\n setLoading(true);\n setError(null);\n\n try {\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('xlsx.not_found'));\n } else if (response.status === 403) {\n throw new Error('无权限访问此文件');\n } else {\n throw new Error(`文件加载失败 (${response.status})`);\n }\n }\n\n const arrayBuffer = await response.arrayBuffer();\n\n if (arrayBuffer.byteLength === 0) {\n throw new Error('文件为空');\n }\n\n // 使用 exceljs 解析\n const workbook = new ExcelJS.Workbook();\n await workbook.xlsx.load(arrayBuffer);\n\n // 转换为 x-data-spreadsheet 数据格式\n const sheetData = convertWorkbookToSpreadsheetData(workbook);\n\n if (!isMounted) return;\n\n sheetDataRef.current = sheetData as unknown as Record<string, unknown>[];\n\n // 挂载 x-data-spreadsheet\n mountSpreadsheet();\n\n setLoading(false);\n } catch (err) {\n if (isMounted) {\n console.error('Excel 解析错误:', err);\n let errorMsg = t('xlsx.parse_failed');\n if (err instanceof Error) {\n errorMsg = err.message;\n }\n setError(errorMsg);\n setLoading(false);\n }\n }\n };\n\n const timer = setTimeout(() => {\n requestAnimationFrame(() => {\n loadExcel();\n });\n }, 100);\n\n return () => {\n isMounted = false;\n clearTimeout(timer);\n sheetDataRef.current = null;\n if (containerRef.current) {\n containerRef.current.innerHTML = '';\n }\n spreadsheetRef.current = null;\n };\n }, [url, mountSpreadsheet]);\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('xlsx.loading')}</p>\n </div>\n </div>\n )}\n\n {/* 错误状态 */}\n {error && !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 rfp-max-w-sm md:rfp-max-w-md rfp-px-4\">\n <div className=\"rfp-w-24 rfp-h-24 md:rfp-w-32 md:rfp-h-32 rfp-mx-auto rfp-mb-4 md:rfp-mb-6 rfp-rounded-2xl md:rfp-rounded-3xl rfp-bg-gradient-to-br rfp-from-green-500 rfp-via-emerald-500 rfp-to-teal-500 rfp-flex rfp-items-center rfp-justify-center rfp-shadow-2xl\">\n <FileSpreadsheet className=\"rfp-w-12 rfp-h-12 md:rfp-w-16 md:rfp-h-16 rfp-text-fg-primary\" />\n </div>\n <p className=\"rfp-text-lg md:rfp-text-xl rfp-text-fg-primary rfp-mb-2 md:rfp-mb-3 rfp-font-medium\">{t('xlsx.load_failed')}</p>\n <p className=\"rfp-text-xs md:rfp-text-sm rfp-text-fg-tertiary rfp-mb-4 md:rfp-mb-6\">\n {error}\n </p>\n <a\n href={url}\n download\n className=\"rfp-inline-flex rfp-items-center rfp-gap-2 rfp-px-4 rfp-py-2 md:rfp-px-6 md:rfp-py-3 rfp-bg-gradient-to-r rfp-from-purple-500 rfp-to-pink-500 rfp-text-fg-primary rfp-text-sm md:rfp-text-base rfp-rounded-lg md:rfp-rounded-xl hover:rfp-scale-105 rfp-transition-all rfp-shadow-lg\"\n >\n <svg className=\"rfp-w-4 rfp-h-4 md:rfp-w-5 md:rfp-h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\" />\n </svg>\n {t('common.download')}\n </a>\n <p className=\"rfp-text-xs rfp-text-fg-muted rfp-mt-3 md:rfp-mt-4\">\n 提示:可以使用 Microsoft Excel 或 WPS 打开\n </p>\n </div>\n </div>\n )}\n\n {/* Spreadsheet 容器 */}\n {!error && (\n <div\n ref={containerRef}\n className=\"xlsx-spreadsheet-container rfp-w-full rfp-h-full\"\n style={{ opacity: loading ? 0 : 1 }}\n />\n )}\n </div>\n );\n};\n"],"names":["XlsxRenderer","url","t","useTranslator","fetcher","useFetcher","loading","setLoading","useState","error","setError","containerRef","useRef","spreadsheetRef","sheetDataRef","resizeObserverRef","resizeTimeoutRef","lastDimensionsRef","calculateDimensions","useCallback","rawWidth","rawHeight","width","height","mountSpreadsheet","isMobile","s","Spreadsheet","useEffect","isInitialRender","updateDimensions","newDimensions","lastDimensions","widthDiff","heightDiff","isMounted","loadExcel","response","arrayBuffer","workbook","ExcelJS","sheetData","convertWorkbookToSpreadsheetData","err","errorMsg","timer","jsxs","jsx","FileSpreadsheet"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-BAYc4aBz.mjs","sources":["../../src/renderers/Xlsx/index.tsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback } from 'react';\nimport { FileSpreadsheet } from 'lucide-react';\nimport ExcelJS from 'exceljs';\nimport Spreadsheet from 'x-data-spreadsheet';\nimport 'x-data-spreadsheet/dist/xspreadsheet.css';\nimport { convertWorkbookToSpreadsheetData } from '../../utils/excelDataConverter';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\n\ninterface XlsxRendererProps {\n url: string;\n}\n\nexport const XlsxRenderer: React.FC<XlsxRendererProps> = ({ 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 containerRef = useRef<HTMLDivElement>(null);\n const spreadsheetRef = useRef<Spreadsheet | null>(null);\n const sheetDataRef = useRef<Record<string, unknown>[] | null>(null);\n const resizeObserverRef = useRef<ResizeObserver | null>(null);\n const resizeTimeoutRef = useRef<number | null>(null);\n const lastDimensionsRef = useRef({ width: 0, height: 0 });\n\n const calculateDimensions = useCallback(() => {\n if (!containerRef.current) return { width: 800, height: 600 };\n const rawWidth = containerRef.current.clientWidth;\n const rawHeight = containerRef.current.clientHeight;\n const width = rawWidth > 100 ? rawWidth : 800;\n const height = rawHeight > 100 ? rawHeight : 600;\n return { width, height };\n }, []);\n\n const mountSpreadsheet = useCallback(() => {\n if (!containerRef.current || !sheetDataRef.current) return;\n\n // 清空容器\n containerRef.current.innerHTML = '';\n spreadsheetRef.current = null;\n\n const { width, height } = calculateDimensions();\n const isMobile = width < 640;\n\n const s = new Spreadsheet(containerRef.current, {\n mode: 'read',\n showToolbar: false,\n showContextmenu: false,\n showGrid: true,\n row: {\n len: 100,\n height: 25,\n },\n col: {\n len: 26,\n width: isMobile ? 80 : 100,\n indexWidth: isMobile ? 40 : 60,\n minWidth: isMobile ? 40 : 60,\n },\n view: {\n height: () => height,\n width: () => width,\n },\n });\n\n s.loadData(sheetDataRef.current as unknown as Record<string, unknown>);\n spreadsheetRef.current = s;\n }, [calculateDimensions]);\n\n // 监听容器尺寸变化\n useEffect(() => {\n if (!containerRef.current) return;\n\n let isInitialRender = true;\n\n const updateDimensions = () => {\n if (isInitialRender) {\n isInitialRender = false;\n lastDimensionsRef.current = calculateDimensions();\n return;\n }\n\n const newDimensions = calculateDimensions();\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) return;\n\n lastDimensionsRef.current = newDimensions;\n\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n\n resizeTimeoutRef.current = window.setTimeout(() => {\n if (sheetDataRef.current) {\n mountSpreadsheet();\n }\n }, 500);\n };\n\n resizeObserverRef.current = new ResizeObserver(() => {\n updateDimensions();\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, mountSpreadsheet]);\n\n useEffect(() => {\n let isMounted = true;\n\n const loadExcel = async () => {\n if (!containerRef.current) return;\n\n setLoading(true);\n setError(null);\n\n try {\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('xlsx.not_found'));\n } else if (response.status === 403) {\n throw new Error('无权限访问此文件');\n } else {\n throw new Error(`文件加载失败 (${response.status})`);\n }\n }\n\n const arrayBuffer = await response.arrayBuffer();\n\n if (arrayBuffer.byteLength === 0) {\n throw new Error('文件为空');\n }\n\n // 使用 exceljs 解析\n const workbook = new ExcelJS.Workbook();\n await workbook.xlsx.load(arrayBuffer);\n\n // 转换为 x-data-spreadsheet 数据格式\n const sheetData = convertWorkbookToSpreadsheetData(workbook);\n\n if (!isMounted) return;\n\n sheetDataRef.current = sheetData as unknown as Record<string, unknown>[];\n\n // 挂载 x-data-spreadsheet\n mountSpreadsheet();\n\n setLoading(false);\n } catch (err) {\n if (isMounted) {\n console.error('Excel 解析错误:', err);\n let errorMsg = t('xlsx.parse_failed');\n if (err instanceof Error) {\n errorMsg = err.message;\n }\n setError(errorMsg);\n setLoading(false);\n }\n }\n };\n\n const timer = setTimeout(() => {\n requestAnimationFrame(() => {\n loadExcel();\n });\n }, 100);\n\n return () => {\n isMounted = false;\n clearTimeout(timer);\n sheetDataRef.current = null;\n if (containerRef.current) {\n containerRef.current.innerHTML = '';\n }\n spreadsheetRef.current = null;\n };\n }, [url, mountSpreadsheet]);\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('xlsx.loading')}</p>\n </div>\n </div>\n )}\n\n {/* 错误状态 */}\n {error && !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 rfp-max-w-sm md:rfp-max-w-md rfp-px-4\">\n <div className=\"rfp-w-24 rfp-h-24 md:rfp-w-32 md:rfp-h-32 rfp-mx-auto rfp-mb-4 md:rfp-mb-6 rfp-rounded-2xl md:rfp-rounded-3xl rfp-bg-gradient-to-br rfp-from-green-500 rfp-via-emerald-500 rfp-to-teal-500 rfp-flex rfp-items-center rfp-justify-center rfp-shadow-2xl\">\n <FileSpreadsheet className=\"rfp-w-12 rfp-h-12 md:rfp-w-16 md:rfp-h-16 rfp-text-fg-primary\" />\n </div>\n <p className=\"rfp-text-lg md:rfp-text-xl rfp-text-fg-primary rfp-mb-2 md:rfp-mb-3 rfp-font-medium\">{t('xlsx.load_failed')}</p>\n <p className=\"rfp-text-xs md:rfp-text-sm rfp-text-fg-tertiary rfp-mb-4 md:rfp-mb-6\">\n {error}\n </p>\n <a\n href={url}\n download\n className=\"rfp-inline-flex rfp-items-center rfp-gap-2 rfp-px-4 rfp-py-2 md:rfp-px-6 md:rfp-py-3 rfp-bg-gradient-to-r rfp-from-purple-500 rfp-to-pink-500 rfp-text-fg-primary rfp-text-sm md:rfp-text-base rfp-rounded-lg md:rfp-rounded-xl hover:rfp-scale-105 rfp-transition-all rfp-shadow-lg\"\n >\n <svg className=\"rfp-w-4 rfp-h-4 md:rfp-w-5 md:rfp-h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\" />\n </svg>\n {t('common.download')}\n </a>\n <p className=\"rfp-text-xs rfp-text-fg-muted rfp-mt-3 md:rfp-mt-4\">\n 提示:可以使用 Microsoft Excel 或 WPS 打开\n </p>\n </div>\n </div>\n )}\n\n {/* Spreadsheet 容器 */}\n {!error && (\n <div\n ref={containerRef}\n className=\"xlsx-spreadsheet-container rfp-w-full rfp-h-full\"\n style={{ opacity: loading ? 0 : 1 }}\n />\n )}\n </div>\n );\n};\n"],"names":["XlsxRenderer","url","t","useTranslator","fetcher","useFetcher","loading","setLoading","useState","error","setError","containerRef","useRef","spreadsheetRef","sheetDataRef","resizeObserverRef","resizeTimeoutRef","lastDimensionsRef","calculateDimensions","useCallback","rawWidth","rawHeight","width","height","mountSpreadsheet","isMobile","s","Spreadsheet","useEffect","isInitialRender","updateDimensions","newDimensions","lastDimensions","widthDiff","heightDiff","isMounted","loadExcel","response","arrayBuffer","workbook","ExcelJS","sheetData","convertWorkbookToSpreadsheetData","err","errorMsg","timer","jsxs","jsx","FileSpreadsheet"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as r, jsxs as A } from "react/jsx-runtime";
|
|
2
2
|
import { useState as f, useRef as G, useEffect as w, useCallback as P } from "react";
|
|
3
3
|
import T from "mammoth";
|
|
4
|
-
import { u as D, a as I } from "./index-
|
|
4
|
+
import { u as D, a as I } from "./index-CGNWXFy3.mjs";
|
|
5
5
|
const H = 1123, b = 60, _ = 50, S = H - b * 2, j = 24, E = {
|
|
6
6
|
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
7
7
|
lineHeight: "1.8",
|
|
@@ -100,4 +100,4 @@ const H = 1123, b = 60, _ = 50, S = H - b * 2, j = 24, E = {
|
|
|
100
100
|
export {
|
|
101
101
|
M as DocxRenderer
|
|
102
102
|
};
|
|
103
|
-
//# sourceMappingURL=index-
|
|
103
|
+
//# sourceMappingURL=index-BOQJNL71.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-
|
|
1
|
+
{"version":3,"file":"index-BOQJNL71.mjs","sources":["../../src/renderers/Docx/index.tsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback } from 'react';\nimport mammoth from 'mammoth';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\n\ninterface DocxRendererProps {\n url: string;\n}\n\n// A4 page dimensions (96dpi)\nconst PAGE_HEIGHT = 1123;\nconst PAGE_PADDING_Y = 60;\nconst PAGE_PADDING_X = 50;\nconst PAGE_CONTENT_HEIGHT = PAGE_HEIGHT - PAGE_PADDING_Y * 2;\nconst PAGE_GAP = 24;\n\nconst contentStyle: React.CSSProperties = {\n fontFamily: 'system-ui, -apple-system, sans-serif',\n lineHeight: '1.8',\n color: '#333',\n};\n\nexport const DocxRenderer: React.FC<DocxRendererProps> = ({ url }) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const [html, setHtml] = useState<string>('');\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [pages, setPages] = useState<string[]>([]);\n const measureRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const loadDocx = async () => {\n setLoading(true);\n setError(null);\n setHtml('');\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 result = await mammoth.convertToHtml({ arrayBuffer });\n setHtml(result.value);\n } catch (err) {\n console.error('Docx 解析错误:', err);\n setError(t('docx.parse_failed'));\n } finally {\n setLoading(false);\n }\n };\n\n loadDocx();\n }, [url, fetcher, t]);\n\n const paginate = useCallback(() => {\n const container = measureRef.current;\n if (!container || !html) return;\n\n const children = Array.from(container.children) as HTMLElement[];\n if (children.length === 0) {\n setPages([html]);\n return;\n }\n\n const result: string[][] = [[]];\n let currentPageUsed = 0;\n\n for (const child of children) {\n const h = child.offsetHeight;\n\n // If adding this block would exceed page content area and page isn't empty,\n // start a new page\n if (currentPageUsed > 0 && currentPageUsed + h > PAGE_CONTENT_HEIGHT) {\n result.push([]);\n currentPageUsed = 0;\n }\n\n result[result.length - 1].push(child.outerHTML);\n currentPageUsed += h;\n }\n\n // At least one page\n if (result.length === 0) result.push([]);\n\n setPages(result.map(blocks => blocks.join('')));\n }, [html]);\n\n useEffect(() => {\n if (!html || !measureRef.current) return;\n requestAnimationFrame(() => {\n paginate();\n });\n }, [html, paginate]);\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 return (\n <div\n className=\"rfp-w-full rfp-h-full rfp-overflow-auto\"\n style={{ background: 'rgba(0, 0, 0, 0.15)' }}\n >\n {/* Hidden measurement div — same width as page content area */}\n <div\n ref={measureRef}\n dangerouslySetInnerHTML={{ __html: html }}\n style={{\n ...contentStyle,\n position: 'absolute',\n visibility: 'hidden',\n width: `${794 - PAGE_PADDING_X * 2}px`,\n pointerEvents: 'none',\n }}\n />\n\n {/* Visible pages */}\n <div\n className=\"rfp-py-6 md:rfp-py-10 rfp-flex rfp-flex-col rfp-items-center\"\n style={{ gap: `${PAGE_GAP}px` }}\n >\n {(pages.length > 0 ? pages : ['']).map((pageHtml, i) => (\n <div\n key={i}\n style={{\n width: '100%',\n maxWidth: '794px',\n minHeight: `${PAGE_HEIGHT}px`,\n background: 'white',\n boxShadow: '0 2px 12px rgba(0, 0, 0, 0.15)',\n flexShrink: 0,\n padding: `${PAGE_PADDING_Y}px ${PAGE_PADDING_X}px`,\n }}\n >\n <div\n dangerouslySetInnerHTML={{ __html: pageHtml }}\n style={contentStyle}\n />\n </div>\n ))}\n </div>\n </div>\n );\n};\n"],"names":["PAGE_HEIGHT","PAGE_PADDING_Y","PAGE_PADDING_X","PAGE_CONTENT_HEIGHT","PAGE_GAP","contentStyle","DocxRenderer","url","t","useTranslator","fetcher","useFetcher","html","setHtml","useState","loading","setLoading","error","setError","pages","setPages","measureRef","useRef","useEffect","response","arrayBuffer","result","mammoth","err","paginate","useCallback","container","children","currentPageUsed","child","h","blocks","jsx","jsxs","pageHtml","i"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as t } from "react/jsx-runtime";
|
|
2
2
|
import { useState as p, useEffect as m } from "react";
|
|
3
|
-
import { u, a as h,
|
|
4
|
-
import { u as w } from "./useShikiHighlight-
|
|
3
|
+
import { u, a as h, F as g } from "./index-CGNWXFy3.mjs";
|
|
4
|
+
import { u as w } from "./useShikiHighlight-DHFYu0BU.mjs";
|
|
5
5
|
const x = (r) => {
|
|
6
6
|
try {
|
|
7
7
|
const n = new DOMParser().parseFromString(r, "application/xml");
|
|
@@ -48,4 +48,4 @@ $2$3`), s = 0;
|
|
|
48
48
|
export {
|
|
49
49
|
$ as XmlRenderer
|
|
50
50
|
};
|
|
51
|
-
//# sourceMappingURL=index-
|
|
51
|
+
//# sourceMappingURL=index-BkU8rK-0.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-
|
|
1
|
+
{"version":3,"file":"index-BkU8rK-0.mjs","sources":["../../src/renderers/Xml/index.tsx"],"sourcesContent":["import { useState, useEffect } from 'react';\nimport { fetchTextUtf8 } from '@eternalheart/file-preview-core';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\nimport { useShikiHighlight } from '../../hooks/useShikiHighlight';\n\ninterface XmlRendererProps {\n url: string;\n fileName: string;\n}\n\n/**\n * 用 DOMParser 美化 XML:失败则原样返回\n */\nconst prettyPrintXml = (xml: string): string => {\n try {\n const parser = new DOMParser();\n const doc = parser.parseFromString(xml, 'application/xml');\n // 检测解析错误\n const errNode = doc.querySelector('parsererror');\n if (errNode) return xml;\n // 使用 XSLT 或手动缩进:这里手动缩进更稳\n const serializer = new XMLSerializer();\n const serialized = serializer.serializeToString(doc);\n return indentXml(serialized);\n } catch {\n return xml;\n }\n};\n\nconst indentXml = (xml: string): string => {\n const PADDING = ' ';\n const reg = /(>)(<)(\\/*)/g;\n let formatted = xml.replace(reg, '$1\\n$2$3');\n // 自闭合和 CDATA 等不处理\n let pad = 0;\n return formatted\n .split('\\n')\n .map((line) => {\n let indent = 0;\n if (/^<\\/\\w/.test(line)) {\n pad = Math.max(pad - 1, 0);\n } else if (/^<\\w[^>]*[^/]>.*$/.test(line) && !/<.+<\\/.+>$/.test(line)) {\n indent = 1;\n }\n const padded = PADDING.repeat(pad) + line;\n pad += indent;\n return padded;\n })\n .join('\\n');\n};\n\nexport const XmlRenderer: React.FC<XmlRendererProps> = ({ url }) => {\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: highlighted } = useShikiHighlight(content, 'xml');\n\n useEffect(() => {\n const load = async () => {\n try {\n setLoading(true);\n setError(null);\n const raw = await fetchTextUtf8(url, { fetcher });\n setContent(prettyPrintXml(raw));\n } catch (err) {\n console.error(err);\n setError(t('xml.load_failed'));\n } finally {\n setLoading(false);\n }\n };\n load();\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) {\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 return (\n <div className=\"rfp-w-full rfp-h-full rfp-overflow-auto rfp-bg-code-bg\">\n {highlighted ? (\n <div\n className=\"rfp-shiki-wrapper with-line-numbers\"\n dangerouslySetInnerHTML={{ __html: highlighted }}\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"],"names":["prettyPrintXml","xml","doc","serialized","indentXml","PADDING","reg","formatted","pad","line","indent","padded","XmlRenderer","url","t","useTranslator","fetcher","useFetcher","content","setContent","useState","loading","setLoading","error","setError","highlighted","useShikiHighlight","useEffect","raw","fetchTextUtf8","err","jsx"],"mappings":";;;;AAcA,MAAMA,IAAiB,CAACC,MAAwB;AAC9C,MAAI;AAEF,UAAMC,IADS,IAAI,UAAA,EACA,gBAAgBD,GAAK,iBAAiB;AAGzD,QADgBC,EAAI,cAAc,aAAa,EAClC,QAAOD;AAGpB,UAAME,IADa,IAAI,cAAA,EACO,kBAAkBD,CAAG;AACnD,WAAOE,EAAUD,CAAU;AAAA,EAC7B,QAAQ;AACN,WAAOF;AAAA,EACT;AACF,GAEMG,IAAY,CAACH,MAAwB;AACzC,QAAMI,IAAU,MACVC,IAAM;AACZ,MAAIC,IAAYN,EAAI,QAAQK,GAAK;AAAA,KAAU,GAEvCE,IAAM;AACV,SAAOD,EACJ,MAAM;AAAA,CAAI,EACV,IAAI,CAACE,MAAS;AACb,QAAIC,IAAS;AACb,IAAI,SAAS,KAAKD,CAAI,IACpBD,IAAM,KAAK,IAAIA,IAAM,GAAG,CAAC,IAChB,oBAAoB,KAAKC,CAAI,KAAK,CAAC,aAAa,KAAKA,CAAI,MAClEC,IAAS;AAEX,UAAMC,IAASN,EAAQ,OAAOG,CAAG,IAAIC;AACrC,WAAAD,KAAOE,GACAC;AAAA,EACT,CAAC,EACA,KAAK;AAAA,CAAI;AACd,GAEaC,IAA0C,CAAC,EAAE,KAAAC,QAAU;AAClE,QAAMC,IAAIC,EAAA,GACJC,IAAUC,EAAA,GACV,CAACC,GAASC,CAAU,IAAIC,EAAiB,EAAE,GAC3C,CAACC,GAASC,CAAU,IAAIF,EAAS,EAAI,GACrC,CAACG,GAAOC,CAAQ,IAAIJ,EAAwB,IAAI,GAChD,EAAE,MAAMK,EAAA,IAAgBC,EAAkBR,GAAS,KAAK;AAmB9D,SAjBAS,EAAU,MAAM;AAcd,KAba,YAAY;AACvB,UAAI;AACF,QAAAL,EAAW,EAAI,GACfE,EAAS,IAAI;AACb,cAAMI,IAAM,MAAMC,EAAchB,GAAK,EAAE,SAAAG,GAAS;AAChD,QAAAG,EAAWnB,EAAe4B,CAAG,CAAC;AAAA,MAChC,SAASE,GAAK;AACZ,gBAAQ,MAAMA,CAAG,GACjBN,EAASV,EAAE,iBAAiB,CAAC;AAAA,MAC/B,UAAA;AACE,QAAAQ,EAAW,EAAK;AAAA,MAClB;AAAA,IACF,GACA;AAAA,EACF,GAAG,CAACT,CAAG,CAAC,GAEJQ,IAEA,gBAAAU,EAAC,SAAI,WAAU,sEACb,4BAAC,OAAA,EAAI,WAAU,qHAAoH,EAAA,CACrI,IAIAR,IAEA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,sEACb,4BAAC,OAAA,EAAI,WAAU,yCACb,UAAA,gBAAAA,EAAC,KAAA,EAAE,WAAU,eAAe,UAAAR,EAAA,CAAM,GACpC,GACF,IAKF,gBAAAQ,EAAC,OAAA,EAAI,WAAU,0DACZ,UAAAN,IACC,gBAAAM;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,yBAAyB,EAAE,QAAQN,EAAA;AAAA,IAAY;AAAA,EAAA,IAGjD,gBAAAM,EAAC,OAAA,EAAI,WAAU,iGACZ,aACH,GAEJ;AAEJ;"}
|
|
@@ -2,7 +2,7 @@ import { jsx as e, jsxs as t } from "react/jsx-runtime";
|
|
|
2
2
|
import { useState as D, useEffect as J } from "react";
|
|
3
3
|
import O from "@kenjiuno/msgreader";
|
|
4
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-
|
|
5
|
+
import { u as ee, a as te } from "./index-CGNWXFy3.mjs";
|
|
6
6
|
function P(l, d) {
|
|
7
7
|
return l ? l.filter((o) => o.recipType === d).map((o) => {
|
|
8
8
|
const f = o.name || "", p = o.smtpAddress || o.email || "";
|
|
@@ -254,4 +254,4 @@ const n = {
|
|
|
254
254
|
export {
|
|
255
255
|
oe as MsgRenderer
|
|
256
256
|
};
|
|
257
|
-
//# sourceMappingURL=index-
|
|
257
|
+
//# sourceMappingURL=index-BnDoXBnH.mjs.map
|
|
@@ -1 +1 @@
|
|
|
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, '&').replace(/\\x3c/g, '<').replace(/>/g, '>')\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
|
+
{"version":3,"file":"index-BnDoXBnH.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, '&').replace(/\\x3c/g, '<').replace(/>/g, '>')\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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"}
|