@l1yp/file-viewer 0.1.0 → 0.1.1
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 +1 -0
- package/dist/components/DocxNavigationPane.js +7 -0
- package/dist/components/DocxNavigationPane.vue.d.ts +23 -0
- package/dist/components/DocxNavigationPane.vue_vue_type_script_setup_true_lang.js +96 -0
- package/dist/components/DocxViewer.js +1 -1
- package/dist/components/DocxViewer.vue_vue_type_script_setup_true_lang.js +70 -37
- package/dist/components/FileViewerBody.js +1 -1
- package/dist/components/FileViewerBody.vue.d.ts +5 -0
- package/dist/components/FileViewerBody.vue_vue_type_script_setup_true_lang.js +248 -247
- package/dist/components/PptxNavigationPane.js +7 -0
- package/dist/components/PptxNavigationPane.vue.d.ts +20 -0
- package/dist/components/PptxNavigationPane.vue_vue_type_script_setup_true_lang.js +118 -0
- package/dist/components/PptxViewer.js +1 -1
- package/dist/components/PptxViewer.vue_vue_type_script_setup_true_lang.js +64 -38
- package/dist/components/XlsxViewer.js +1 -1
- package/dist/components/XlsxViewer.vue_vue_type_script_setup_true_lang.js +299 -304
- package/dist/components/ZipBrowser.js +1 -1
- package/dist/components/ZipBrowser.vue.d.ts +3 -1
- package/dist/components/ZipBrowser.vue_vue_type_script_setup_true_lang.js +152 -122
- package/dist/composables/useElementNavigation.d.ts +21 -0
- package/dist/composables/useElementNavigation.js +61 -0
- package/dist/lib/archiveHtml.d.ts +49 -0
- package/dist/lib/archiveHtml.js +375 -0
- package/dist/lib/docxNavigation.d.ts +31 -0
- package/dist/lib/docxNavigation.js +63 -0
- package/dist/lib/pptxNavigation.d.ts +7 -0
- package/dist/lib/pptxNavigation.js +27 -0
- package/dist/style.css +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
## 特性
|
|
8
8
|
|
|
9
9
|
- **60+ 格式**:docx/xlsx/pptx/pdf、zip/7z/rar/tar、png/tiff/psd/heic/dcm、csv/jsonl/sqlite、markdown/代码高亮、eml/mht/har、字体/证书/密钥库、epub/mob、drawio/dxf/geojson、hprof/.class/.so/.dll、易语言 .e/.ec 等。
|
|
10
|
+
- **ZIP 网页预览**:打开压缩包里的 HTML 时,自动解析并加载同包的 JS、CSS、图片、字体等相对依赖;源码保持原样,脚本仍需用户主动开启后才会在不透明源沙箱中运行。
|
|
10
11
|
- **零后端**:上游字节只在浏览器解析;HTML/SVG 走沙箱 iframe、下载端点无法内联执行。
|
|
11
12
|
- **按需分包**:每个查看器是独立的懒加载 chunk,打开 PDF 才拉 PDF 引擎;用不到的格式零成本。
|
|
12
13
|
- **重型依赖可选**:只装你需要的格式的引擎;没装时显示「请安装 X」提示卡,不崩溃。
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import e from "../_virtual/_plugin-vue_export-helper.js";
|
|
2
|
+
import t from "./DocxNavigationPane.vue_vue_type_script_setup_true_lang.js";
|
|
3
|
+
/* empty css */
|
|
4
|
+
//#region src/components/DocxNavigationPane.vue
|
|
5
|
+
var n = /*#__PURE__*/ e(t, [["__scopeId", "data-v-82c26438"]]);
|
|
6
|
+
//#endregion
|
|
7
|
+
export { n as default };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ElementNavigationItem } from '@/composables/useElementNavigation';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
outlineItems: readonly ElementNavigationItem[];
|
|
4
|
+
pageItems: readonly ElementNavigationItem[];
|
|
5
|
+
activeOutlineId: string;
|
|
6
|
+
activePageId: string;
|
|
7
|
+
};
|
|
8
|
+
type __VLS_ModelProps = {
|
|
9
|
+
'collapsed'?: boolean;
|
|
10
|
+
'view'?: 'outline' | 'pages';
|
|
11
|
+
};
|
|
12
|
+
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
13
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
14
|
+
navigate: (item: ElementNavigationItem) => any;
|
|
15
|
+
"update:collapsed": (value: boolean) => any;
|
|
16
|
+
"update:view": (value: "outline" | "pages") => any;
|
|
17
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
18
|
+
onNavigate?: ((item: ElementNavigationItem) => any) | undefined;
|
|
19
|
+
"onUpdate:collapsed"?: ((value: boolean) => any) | undefined;
|
|
20
|
+
"onUpdate:view"?: ((value: "outline" | "pages") => any) | undefined;
|
|
21
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
22
|
+
declare const _default: typeof __VLS_export;
|
|
23
|
+
export default _default;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import e from "./icons/Icon.js";
|
|
2
|
+
import { Fragment as t, createCommentVNode as n, createElementBlock as r, createElementVNode as i, createVNode as a, defineComponent as o, mergeModels as s, normalizeClass as c, normalizeStyle as l, openBlock as u, renderList as d, toDisplayString as f, useModel as p } from "vue";
|
|
3
|
+
//#region src/components/DocxNavigationPane.vue?vue&type=script&setup=true&lang.ts
|
|
4
|
+
var m = { class: "dn__header" }, h = { class: "dn__count" }, g = {
|
|
5
|
+
class: "dn__tabs",
|
|
6
|
+
role: "tablist",
|
|
7
|
+
"aria-label": "导航方式"
|
|
8
|
+
}, _ = ["aria-selected"], v = ["aria-selected"], y = {
|
|
9
|
+
class: "dn__list",
|
|
10
|
+
"aria-label": "文档目录"
|
|
11
|
+
}, b = [
|
|
12
|
+
"aria-current",
|
|
13
|
+
"title",
|
|
14
|
+
"onClick"
|
|
15
|
+
], x = { class: "dn__label" }, S = {
|
|
16
|
+
key: 0,
|
|
17
|
+
class: "dn__empty"
|
|
18
|
+
}, C = ["aria-current", "onClick"], w = { class: "dn__page-sheet" }, T = { class: "dn__label" }, E = /*@__PURE__*/ o({
|
|
19
|
+
__name: "DocxNavigationPane",
|
|
20
|
+
props: /*@__PURE__*/ s({
|
|
21
|
+
outlineItems: {},
|
|
22
|
+
pageItems: {},
|
|
23
|
+
activeOutlineId: {},
|
|
24
|
+
activePageId: {}
|
|
25
|
+
}, {
|
|
26
|
+
collapsed: {
|
|
27
|
+
type: Boolean,
|
|
28
|
+
default: !1
|
|
29
|
+
},
|
|
30
|
+
collapsedModifiers: {},
|
|
31
|
+
view: { default: "outline" },
|
|
32
|
+
viewModifiers: {}
|
|
33
|
+
}),
|
|
34
|
+
emits: /*@__PURE__*/ s(["navigate"], ["update:collapsed", "update:view"]),
|
|
35
|
+
setup(o, { emit: s }) {
|
|
36
|
+
let E = o, D = s, O = p(o, "collapsed"), k = p(o, "view");
|
|
37
|
+
function A(e) {
|
|
38
|
+
return (k.value === "outline" ? E.activeOutlineId : E.activePageId) === e.id;
|
|
39
|
+
}
|
|
40
|
+
return (s, p) => (u(), r("aside", {
|
|
41
|
+
class: c(["dn", { "dn--collapsed": O.value }]),
|
|
42
|
+
"aria-label": "文档导航"
|
|
43
|
+
}, [O.value ? (u(), r("button", {
|
|
44
|
+
key: 0,
|
|
45
|
+
type: "button",
|
|
46
|
+
class: "dn__reopen",
|
|
47
|
+
"aria-label": "展开文档导航",
|
|
48
|
+
title: "展开文档导航",
|
|
49
|
+
onClick: p[0] ||= (e) => O.value = !1
|
|
50
|
+
}, [a(e, {
|
|
51
|
+
name: "chevronRight",
|
|
52
|
+
size: 15
|
|
53
|
+
})])) : (u(), r(t, { key: 1 }, [
|
|
54
|
+
i("header", m, [i("div", null, [p[4] ||= i("strong", { class: "dn__title" }, "导航", -1), i("span", h, f(o.pageItems.length) + " 页", 1)]), i("button", {
|
|
55
|
+
type: "button",
|
|
56
|
+
class: "dn__collapse",
|
|
57
|
+
"aria-label": "收起文档导航",
|
|
58
|
+
title: "收起文档导航",
|
|
59
|
+
onClick: p[1] ||= (e) => O.value = !0
|
|
60
|
+
}, [a(e, {
|
|
61
|
+
name: "chevronLeft",
|
|
62
|
+
size: 15
|
|
63
|
+
})])]),
|
|
64
|
+
i("div", g, [i("button", {
|
|
65
|
+
type: "button",
|
|
66
|
+
role: "tab",
|
|
67
|
+
class: c(["dn__tab", { "dn__tab--active": k.value === "outline" }]),
|
|
68
|
+
"aria-selected": k.value === "outline",
|
|
69
|
+
onClick: p[2] ||= (e) => k.value = "outline"
|
|
70
|
+
}, " 目录 ", 10, _), i("button", {
|
|
71
|
+
type: "button",
|
|
72
|
+
role: "tab",
|
|
73
|
+
class: c(["dn__tab", { "dn__tab--active": k.value === "pages" }]),
|
|
74
|
+
"aria-selected": k.value === "pages",
|
|
75
|
+
onClick: p[3] ||= (e) => k.value = "pages"
|
|
76
|
+
}, " 页面 ", 10, v)]),
|
|
77
|
+
i("nav", y, [k.value === "outline" ? (u(), r(t, { key: 0 }, [(u(!0), r(t, null, d(o.outlineItems, (e) => (u(), r("button", {
|
|
78
|
+
key: e.id,
|
|
79
|
+
type: "button",
|
|
80
|
+
class: c(["dn__outline-item", { "dn__item--active": A(e) }]),
|
|
81
|
+
style: l({ paddingLeft: `${10 + e.level * 12}px` }),
|
|
82
|
+
"aria-current": A(e) ? "location" : void 0,
|
|
83
|
+
title: e.title,
|
|
84
|
+
onClick: (t) => D("navigate", e)
|
|
85
|
+
}, [p[5] ||= i("span", { class: "dn__marker" }, null, -1), i("span", x, f(e.title), 1)], 14, b))), 128)), o.outlineItems.length ? n("", !0) : (u(), r("p", S, " 文档未设置标题层级,可切换到“页面”导航。 "))], 64)) : (u(!0), r(t, { key: 1 }, d(o.pageItems, (e, t) => (u(), r("button", {
|
|
86
|
+
key: e.id,
|
|
87
|
+
type: "button",
|
|
88
|
+
class: c(["dn__page-item", { "dn__item--active": A(e) }]),
|
|
89
|
+
"aria-current": A(e) ? "page" : void 0,
|
|
90
|
+
onClick: (t) => D("navigate", e)
|
|
91
|
+
}, [i("span", w, f(t + 1), 1), i("span", T, f(e.title), 1)], 10, C))), 128))])
|
|
92
|
+
], 64))], 2));
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
//#endregion
|
|
96
|
+
export { E as default };
|
|
@@ -2,6 +2,6 @@ import e from "../_virtual/_plugin-vue_export-helper.js";
|
|
|
2
2
|
import t from "./DocxViewer.vue_vue_type_script_setup_true_lang.js";
|
|
3
3
|
/* empty css */
|
|
4
4
|
//#region src/components/DocxViewer.vue
|
|
5
|
-
var n = /*#__PURE__*/ e(t, [["__scopeId", "data-v-
|
|
5
|
+
var n = /*#__PURE__*/ e(t, [["__scopeId", "data-v-5e8d92a6"]]);
|
|
6
6
|
//#endregion
|
|
7
7
|
export { n as default };
|
|
@@ -1,59 +1,92 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import e from "./DocxNavigationPane.js";
|
|
2
|
+
import { useElementNavigation as t } from "../composables/useElementNavigation.js";
|
|
3
|
+
import { buildDocxNavigation as n, buildDocxPageNavigation as r } from "../lib/docxNavigation.js";
|
|
4
|
+
import { createBlock as i, createCommentVNode as a, createElementBlock as o, createElementVNode as s, defineComponent as c, onBeforeUnmount as l, onMounted as u, openBlock as d, shallowRef as f, toDisplayString as p, unref as m, vShow as h, watch as g, withDirectives as _ } from "vue";
|
|
5
|
+
import { renderAsync as v } from "docx-preview";
|
|
3
6
|
//#region src/components/DocxViewer.vue?vue&type=script&setup=true&lang.ts
|
|
4
|
-
var
|
|
7
|
+
var y = { class: "dx" }, b = { class: "dx__stage" }, x = {
|
|
5
8
|
key: 0,
|
|
6
9
|
class: "dx__msg"
|
|
7
|
-
},
|
|
10
|
+
}, S = {
|
|
8
11
|
key: 1,
|
|
9
12
|
class: "dx__msg dx__msg--error"
|
|
10
|
-
},
|
|
13
|
+
}, C = /*@__PURE__*/ c({
|
|
11
14
|
__name: "DocxViewer",
|
|
12
15
|
props: {
|
|
13
16
|
url: {},
|
|
14
17
|
name: {},
|
|
15
18
|
size: {}
|
|
16
19
|
},
|
|
17
|
-
setup(
|
|
18
|
-
let
|
|
19
|
-
async function
|
|
20
|
-
let e =
|
|
21
|
-
if (!
|
|
22
|
-
|
|
20
|
+
setup(c) {
|
|
21
|
+
let C = c, w = f("loading"), T = f(""), E = f(null), D = f("outline"), O = f(!1), { outlineItems: k, pageItems: A, activeOutlineId: j, activePageId: M, setItems: N, navigate: P } = t(E);
|
|
22
|
+
async function F() {
|
|
23
|
+
let e = E.value;
|
|
24
|
+
if (!C.url || !e) return;
|
|
25
|
+
w.value = "loading", T.value = "", N([], []), e.innerHTML = "";
|
|
26
|
+
let t = C.url;
|
|
27
|
+
try {
|
|
28
|
+
let i = await fetch(t);
|
|
29
|
+
if (!i.ok) throw Error(`HTTP ${i.status}`);
|
|
30
|
+
let a = await i.arrayBuffer();
|
|
31
|
+
if (C.url !== t || E.value !== e) return;
|
|
32
|
+
let o = await v(a, e, void 0, {
|
|
33
|
+
className: "docx",
|
|
34
|
+
inWrapper: !0,
|
|
35
|
+
ignoreWidth: !0,
|
|
36
|
+
ignoreHeight: !0,
|
|
37
|
+
breakPages: !0,
|
|
38
|
+
renderHeaders: !0,
|
|
39
|
+
renderFooters: !0,
|
|
40
|
+
renderFootnotes: !0,
|
|
41
|
+
renderEndnotes: !0,
|
|
42
|
+
useBase64URL: !0
|
|
43
|
+
});
|
|
44
|
+
if (C.url !== t || E.value !== e) return;
|
|
45
|
+
let s;
|
|
23
46
|
try {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
ignoreWidth: !0,
|
|
31
|
-
ignoreHeight: !0,
|
|
32
|
-
breakPages: !0,
|
|
33
|
-
renderHeaders: !0,
|
|
34
|
-
renderFooters: !0,
|
|
35
|
-
renderFootnotes: !0,
|
|
36
|
-
renderEndnotes: !0,
|
|
37
|
-
useBase64URL: !0
|
|
38
|
-
}), y.value !== e)) return;
|
|
39
|
-
_.value = "ready";
|
|
40
|
-
} catch (e) {
|
|
41
|
-
v.value = e instanceof Error ? e.message : String(e), _.value = "error";
|
|
47
|
+
s = n(o, e);
|
|
48
|
+
} catch (t) {
|
|
49
|
+
console.warn("DOCX outline navigation unavailable:", t), s = {
|
|
50
|
+
outline: [],
|
|
51
|
+
pages: r(e)
|
|
52
|
+
};
|
|
42
53
|
}
|
|
54
|
+
N(s.outline, s.pages), D.value = s.outline.length ? "outline" : "pages", w.value = "ready";
|
|
55
|
+
} catch (e) {
|
|
56
|
+
T.value = e instanceof Error ? e.message : String(e), w.value = "error";
|
|
43
57
|
}
|
|
44
58
|
}
|
|
45
|
-
return
|
|
46
|
-
|
|
47
|
-
}), (
|
|
59
|
+
return u(F), g(() => C.url, F), l(() => {
|
|
60
|
+
E.value && (E.value.innerHTML = "");
|
|
61
|
+
}), (t, n) => (d(), o("div", y, [w.value === "ready" ? (d(), i(e, {
|
|
62
|
+
key: 0,
|
|
63
|
+
collapsed: O.value,
|
|
64
|
+
"onUpdate:collapsed": n[0] ||= (e) => O.value = e,
|
|
65
|
+
view: D.value,
|
|
66
|
+
"onUpdate:view": n[1] ||= (e) => D.value = e,
|
|
67
|
+
"outline-items": m(k),
|
|
68
|
+
"page-items": m(A),
|
|
69
|
+
"active-outline-id": m(j),
|
|
70
|
+
"active-page-id": m(M),
|
|
71
|
+
onNavigate: m(P)
|
|
72
|
+
}, null, 8, [
|
|
73
|
+
"collapsed",
|
|
74
|
+
"view",
|
|
75
|
+
"outline-items",
|
|
76
|
+
"page-items",
|
|
77
|
+
"active-outline-id",
|
|
78
|
+
"active-page-id",
|
|
79
|
+
"onNavigate"
|
|
80
|
+
])) : a("", !0), s("div", b, [w.value === "loading" ? (d(), o("p", x, "正在渲染 Word 文档…")) : w.value === "error" ? (d(), o("div", S, [s("p", null, "渲染失败:" + p(T.value), 1), s("button", {
|
|
48
81
|
type: "button",
|
|
49
82
|
class: "dx__retry",
|
|
50
|
-
onClick:
|
|
51
|
-
}, "重试")])) :
|
|
83
|
+
onClick: F
|
|
84
|
+
}, "重试")])) : a("", !0), _(s("div", {
|
|
52
85
|
ref_key: "docEl",
|
|
53
|
-
ref:
|
|
86
|
+
ref: E,
|
|
54
87
|
class: "dx__doc"
|
|
55
|
-
}, null, 512), [[
|
|
88
|
+
}, null, 512), [[h, w.value === "ready"]])])]));
|
|
56
89
|
}
|
|
57
90
|
});
|
|
58
91
|
//#endregion
|
|
59
|
-
export {
|
|
92
|
+
export { C as default };
|
|
@@ -2,6 +2,6 @@ import e from "../_virtual/_plugin-vue_export-helper.js";
|
|
|
2
2
|
import t from "./FileViewerBody.vue_vue_type_script_setup_true_lang.js";
|
|
3
3
|
/* empty css */
|
|
4
4
|
//#region src/components/FileViewerBody.vue
|
|
5
|
-
var n = /*#__PURE__*/ e(t, [["__scopeId", "data-v-
|
|
5
|
+
var n = /*#__PURE__*/ e(t, [["__scopeId", "data-v-af870145"]]);
|
|
6
6
|
//#endregion
|
|
7
7
|
export { n as default };
|
|
@@ -24,6 +24,11 @@ type __VLS_Props = {
|
|
|
24
24
|
file: ViewerFile;
|
|
25
25
|
mode?: 'render' | 'source';
|
|
26
26
|
hostChooser?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Render-only HTML whose archive-relative dependencies have already been rewritten. Source/copy continue to
|
|
29
|
+
* use `file.content` (or fetched text), so opening an HTML entry inside a ZIP still shows its original source.
|
|
30
|
+
*/
|
|
31
|
+
htmlPreview?: string;
|
|
27
32
|
};
|
|
28
33
|
declare function pickFormat(key: string): void;
|
|
29
34
|
declare function resetFormat(): void;
|