vitepress-plugin-filelist 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -9
- package/dist/client/browser/index.d.ts +1 -82
- package/dist/client/browser/index.js +34 -11
- package/dist/client/ssr/index.d.ts +1 -82
- package/dist/client/ssr/index.js +34 -11
- package/package.json +15 -5
package/README.md
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
<h1 align="center">
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/nrjycyd/vitepress-plugin-filelist/main/demo/docs/public/wordmark-dark.svg?sanitize=true">
|
|
4
|
+
<img src="https://raw.githubusercontent.com/nrjycyd/vitepress-plugin-filelist/main/demo/docs/public/wordmark.svg?sanitize=true" alt="vitepress-plugin-filelist" width="420">
|
|
5
|
+
</picture>
|
|
6
|
+
</h1>
|
|
7
|
+
|
|
8
|
+
<p align="center">
|
|
9
|
+
<a href="https://www.npmjs.com/package/vitepress-plugin-filelist"><img src="https://img.shields.io/npm/v/vitepress-plugin-filelist" alt="npm"></a>
|
|
10
|
+
<a href="https://github.com/nrjycyd/vitepress-plugin-filelist/actions/workflows/ci.yml"><img src="https://github.com/nrjycyd/vitepress-plugin-filelist/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
11
|
+
<a href="https://github.com/nrjycyd/vitepress-plugin-filelist/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/vitepress-plugin-filelist" alt="license"></a>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
<p align="center">面向 VitePress 的 OpenList 文件浏览组件:在文档页里浏览、预览、批量下载 OpenList 上的文件。</p>
|
|
15
|
+
|
|
16
|
+
<p align="center">
|
|
17
|
+
<img src="https://raw.githubusercontent.com/nrjycyd/vitepress-plugin-filelist/main/demo/docs/public/screenshot.png" alt="文件列表截图" width="640">
|
|
18
|
+
</p>
|
|
10
19
|
|
|
11
20
|
## 功能
|
|
12
21
|
|
|
@@ -6,8 +6,6 @@ interface FileListLabels {
|
|
|
6
6
|
filter: string;
|
|
7
7
|
refresh: string;
|
|
8
8
|
batch: string;
|
|
9
|
-
/** @deprecated No longer shown; the selection count lives in the toolbar. */
|
|
10
|
-
batchCount: string;
|
|
11
9
|
batching: string;
|
|
12
10
|
passwordPrompt: string;
|
|
13
11
|
passwordPlaceholder: string;
|
|
@@ -27,15 +25,11 @@ interface FileListLabels {
|
|
|
27
25
|
download: string;
|
|
28
26
|
loaded: string;
|
|
29
27
|
selected: string;
|
|
30
|
-
/** @deprecated No longer shown; the footer only shows loaded files and size. */
|
|
31
|
-
unloaded: string;
|
|
32
28
|
folderFailed: string;
|
|
33
29
|
demoDownload: string;
|
|
34
30
|
demoPreview: string;
|
|
35
31
|
demoBatch: string;
|
|
36
32
|
downloadFailed: string;
|
|
37
|
-
/** @deprecated Preview errors are shown in the dialog (`previewUnavailable`). */
|
|
38
|
-
previewFailed: string;
|
|
39
33
|
batchFailed: string;
|
|
40
34
|
defaultZip: string;
|
|
41
35
|
/** Text button that clears the selection (wide layout). */
|
|
@@ -90,8 +84,6 @@ interface FileListLabels {
|
|
|
90
84
|
forgetPassword: string;
|
|
91
85
|
/** Lock button on a folder that needs a password. `{name}` */
|
|
92
86
|
unlockFolder: string;
|
|
93
|
-
/** @deprecated Network failures now append `corsHint`. */
|
|
94
|
-
networkHint: string;
|
|
95
87
|
/** Deep search: the row at the end of a filtered list. `{count}` where noted */
|
|
96
88
|
deepHint: string;
|
|
97
89
|
deepSearch: string;
|
|
@@ -146,8 +138,6 @@ interface FileListLabels {
|
|
|
146
138
|
showNext: string;
|
|
147
139
|
/** Show the next page, short form for narrow lists. `{count}` */
|
|
148
140
|
showNextShort: string;
|
|
149
|
-
/** No longer shown (“Show next” replaces it); kept for existing overrides. */
|
|
150
|
-
showMore: string;
|
|
151
141
|
showAll: string;
|
|
152
142
|
/** Fewer than a page left. `{count}` */
|
|
153
143
|
showRest: string;
|
|
@@ -216,17 +206,6 @@ interface FileListProps {
|
|
|
216
206
|
/** Per-key label overrides on top of the locale preset. */
|
|
217
207
|
labels?: Partial<FileListLabels>;
|
|
218
208
|
}
|
|
219
|
-
/** Shape of one entry returned by `POST /api/fs/list`. */
|
|
220
|
-
interface OpenListEntry {
|
|
221
|
-
name: string;
|
|
222
|
-
size: number;
|
|
223
|
-
is_dir: boolean;
|
|
224
|
-
modified: string;
|
|
225
|
-
created?: string;
|
|
226
|
-
sign?: string;
|
|
227
|
-
thumb?: string;
|
|
228
|
-
type?: number;
|
|
229
|
-
}
|
|
230
209
|
declare const _default: import("vue").DefineComponent<FileListProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FileListProps> & Readonly<{}>, {
|
|
231
210
|
base: string;
|
|
232
211
|
path: string;
|
|
@@ -318,66 +297,6 @@ declare global {
|
|
|
318
297
|
export declare const fileListLocales: Record<FileListLocale, FileListLabels>;
|
|
319
298
|
export declare function formatLabel(template: string, values?: Record<string, string | number>): string;
|
|
320
299
|
export declare function resolveLabels(locale?: FileListLocale, overrides?: Partial<FileListLabels>): FileListLabels;
|
|
321
|
-
interface SortableNode {
|
|
322
|
-
name: string;
|
|
323
|
-
size: number;
|
|
324
|
-
is_dir: boolean;
|
|
325
|
-
modified: string;
|
|
326
|
-
}
|
|
327
|
-
type SortKey = 'name' | 'size' | 'modified';
|
|
328
|
-
export declare function joinPath(parent: string, name: string): string;
|
|
329
|
-
export declare function encodePath(path: string): string;
|
|
330
|
-
/**
|
|
331
|
-
* Make one path segment safe as a ZIP entry segment: no separators,
|
|
332
|
-
* no `.` / `..` traversal, no empty names.
|
|
333
|
-
*/
|
|
334
|
-
export declare function zipSegment(name: string): string;
|
|
335
|
-
/** Join path segments into a ZIP entry name, sanitising each segment. */
|
|
336
|
-
export declare function zipEntryName(segments: string[]): string;
|
|
337
|
-
/**
|
|
338
|
-
* Return `name`, or `name (2)`, `name (3)`... when it is already in `used`.
|
|
339
|
-
* The suffix goes before the extension of the last segment. Adds the result to `used`.
|
|
340
|
-
*/
|
|
341
|
-
export declare function uniqueEntryName(name: string, used: Set<string>): string;
|
|
342
|
-
/** Human-readable size. `0` reads `0 B`; missing, negative or invalid sizes read `-`. */
|
|
343
|
-
export declare function formatSize(size: number): string;
|
|
344
|
-
export declare function formatDate(iso: string): string;
|
|
345
|
-
/** Upper-case extension for the type badge, e.g. `PDF`. */
|
|
346
|
-
export declare function extOf(name: string): string;
|
|
347
|
-
type FileKind = 'doc' | 'sheet' | 'slide' | 'pdf' | 'image' | 'media' | 'archive' | 'code' | 'other';
|
|
348
|
-
type PreviewKind = 'image' | 'video' | 'audio' | 'text' | 'pdf' | 'none';
|
|
349
|
-
/** Rough file family, used to colour the type badge. */
|
|
350
|
-
export declare function fileKind(name: string): FileKind;
|
|
351
|
-
/**
|
|
352
|
-
* How a file is shown in the preview dialog. Office documents and anything
|
|
353
|
-
* else the browser cannot render are `none` (info + download).
|
|
354
|
-
*/
|
|
355
|
-
export declare function previewKind(name: string): PreviewKind;
|
|
356
|
-
/** Sum of the `size` of the given entries, ignoring missing or invalid sizes. */
|
|
357
|
-
export declare function totalSize(items: Array<{
|
|
358
|
-
size?: number;
|
|
359
|
-
}>): number;
|
|
360
|
-
export declare function compareNodes(a: SortableNode, b: SortableNode, key: SortKey, ascending?: boolean, locale?: string): number;
|
|
361
|
-
interface IframePreview {
|
|
362
|
-
label: string;
|
|
363
|
-
scheme: string;
|
|
364
|
-
}
|
|
365
|
-
/**
|
|
366
|
-
* Viewers from OpenList's public `iframe_previews` setting that match a file,
|
|
367
|
-
* in the order OpenList lists them. Keys are comma-separated extensions or a
|
|
368
|
-
* `/regex/flags` tested against the extension, as in OpenList's frontend.
|
|
369
|
-
*/
|
|
370
|
-
export declare function iframePreviewsFor(name: string, setting: string | undefined): IframePreview[];
|
|
371
|
-
/**
|
|
372
|
-
* Fill an OpenList preview scheme: `$name`, `$url` (raw URL) and `$durl`
|
|
373
|
-
* (signed download URL), each optionally prefixed with `e` (URI-encode) or
|
|
374
|
-
* `b` (base64), e.g. `$e_url`, `$b_url`, `$e_durl`.
|
|
375
|
-
*/
|
|
376
|
-
export declare function fillPreviewUrl(scheme: string, args: {
|
|
377
|
-
name: string;
|
|
378
|
-
rawUrl: string;
|
|
379
|
-
downloadUrl: string;
|
|
380
|
-
}): string;
|
|
381
300
|
/**
|
|
382
301
|
* Register `<FileList>` and `<VPFileList>` globally.
|
|
383
302
|
*
|
|
@@ -395,4 +314,4 @@ export declare function fillPreviewUrl(scheme: string, args: {
|
|
|
395
314
|
* ```
|
|
396
315
|
*/
|
|
397
316
|
export declare function enhanceAppWithFileList({ app }: EnhanceAppContext): void;
|
|
398
|
-
export {
|
|
317
|
+
export { _default as FileList, _default as VPFileList, type FileListLabels, type FileListLocale, type FileListProps, type FileListSource };
|
|
@@ -615,6 +615,38 @@ function createDemoApi(delay = 220) {
|
|
|
615
615
|
}
|
|
616
616
|
/** Whether a demo file can really be previewed, downloaded and zipped. */
|
|
617
617
|
const isDemoFile = isSample;
|
|
618
|
+
// src/client/devWarnings.ts
|
|
619
|
+
const SECURITY_DOC = "https://nrjycyd.github.io/vitepress-plugin-filelist/guide/security";
|
|
620
|
+
/** Props a page wrote that end up, readable by anyone, in the built site. */
|
|
621
|
+
function publicSecrets(props) {
|
|
622
|
+
const found = [];
|
|
623
|
+
if (props.token) found.push("token");
|
|
624
|
+
if (props.password || props.sources?.some((source) => source.password)) found.push("password");
|
|
625
|
+
return found;
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Development builds only. The site's Vite replaces `import.meta.env` in
|
|
629
|
+
* dependencies too (`DEV` is true under `vitepress dev`, false in a build);
|
|
630
|
+
* without a bundler there is no `env` and this is not a development build.
|
|
631
|
+
*/
|
|
632
|
+
function isDevBuild() {
|
|
633
|
+
return import.meta.env?.DEV === true;
|
|
634
|
+
}
|
|
635
|
+
let warned = false;
|
|
636
|
+
/**
|
|
637
|
+
* While the site runs in development, say once per page load that `token` and
|
|
638
|
+
* `password` written in Markdown are public. Production builds stay silent.
|
|
639
|
+
* Returns whether it warned.
|
|
640
|
+
*/
|
|
641
|
+
function warnPublicSecrets(props, locale, dev = isDevBuild()) {
|
|
642
|
+
if (warned || !dev) return false;
|
|
643
|
+
const found = publicSecrets(props);
|
|
644
|
+
if (!found.length) return false;
|
|
645
|
+
warned = true;
|
|
646
|
+
const names = found.join(" / ");
|
|
647
|
+
console.warn(locale === "en-US" ? `[vitepress-plugin-filelist] This page sets ${names} on <FileList>. It is copied as is into the built site, where every visitor can read it. Prefer a guest account limited to a base path. ${SECURITY_DOC} (shown in development only)` : `[vitepress-plugin-filelist] 本页的 <FileList> 写了 ${names}:它会原样进入构建后的网页,所有访客都能看到。建议改用限定基础路径的 guest 账户。${SECURITY_DOC}(仅开发时提示)`);
|
|
648
|
+
return true;
|
|
649
|
+
}
|
|
618
650
|
// src/client/ConfirmDialog.vue
|
|
619
651
|
const _hoisted_1$3 = ["aria-label"];
|
|
620
652
|
const _hoisted_2$3 = {
|
|
@@ -944,7 +976,6 @@ const fileListLocales = {
|
|
|
944
976
|
filter: "筛选文件名",
|
|
945
977
|
refresh: "刷新",
|
|
946
978
|
batch: "下载 ZIP",
|
|
947
|
-
batchCount: "批量下载({count})",
|
|
948
979
|
batching: "打包中 {percent}%",
|
|
949
980
|
passwordPrompt: "该目录受密码保护:",
|
|
950
981
|
passwordPlaceholder: "输入密码",
|
|
@@ -962,13 +993,11 @@ const fileListLocales = {
|
|
|
962
993
|
download: "下载",
|
|
963
994
|
loaded: "{count} 个已加载文件",
|
|
964
995
|
selected: "已选 {count} 项",
|
|
965
|
-
unloaded: "{count} 个目录未展开,未计入全选",
|
|
966
996
|
folderFailed: "打开文件夹失败:{message}",
|
|
967
997
|
demoDownload: "演示模式:接入 OpenList 后会下载「{name}」",
|
|
968
998
|
demoPreview: "演示模式:接入 OpenList 后可预览「{name}」",
|
|
969
999
|
demoBatch: "演示模式:将打包已勾选的 {count} 个文件",
|
|
970
1000
|
downloadFailed: "下载失败:{message}",
|
|
971
|
-
previewFailed: "预览失败:{message}",
|
|
972
1001
|
batchFailed: "打包失败:{message}",
|
|
973
1002
|
defaultZip: "资源",
|
|
974
1003
|
clear: "清除",
|
|
@@ -999,7 +1028,6 @@ const fileListLocales = {
|
|
|
999
1028
|
remembered: "已记住",
|
|
1000
1029
|
forgetPassword: "忘记",
|
|
1001
1030
|
unlockFolder: "输入 {name} 的密码",
|
|
1002
|
-
networkHint: "可能被跨域拦截:请检查 OpenList 的 cors.allow_origins,或 OpenList-Worker 的 ALLOW_URLS。",
|
|
1003
1031
|
deepHint: "只筛选了已加载的内容,",
|
|
1004
1032
|
deepSearch: "尝试深度搜索",
|
|
1005
1033
|
deepRunning: "正在深度搜索 · 已查找 {count} 个文件夹",
|
|
@@ -1030,7 +1058,6 @@ const fileListLocales = {
|
|
|
1030
1058
|
zipBlockText: "当前浏览器一次最多打包 {limit},请分批勾选下载。",
|
|
1031
1059
|
gotIt: "知道了",
|
|
1032
1060
|
moreRemaining: "还有 {count} 项",
|
|
1033
|
-
showMore: "显示更多",
|
|
1034
1061
|
showAll: "全部显示",
|
|
1035
1062
|
showRest: "显示剩余 {count} 项",
|
|
1036
1063
|
showLess: "收起",
|
|
@@ -1046,7 +1073,6 @@ const fileListLocales = {
|
|
|
1046
1073
|
filter: "Filter files",
|
|
1047
1074
|
refresh: "Refresh",
|
|
1048
1075
|
batch: "Download ZIP",
|
|
1049
|
-
batchCount: "Download ZIP ({count})",
|
|
1050
1076
|
batching: "Zipping {percent}%",
|
|
1051
1077
|
passwordPrompt: "This folder is password protected:",
|
|
1052
1078
|
passwordPlaceholder: "Folder password",
|
|
@@ -1064,13 +1090,11 @@ const fileListLocales = {
|
|
|
1064
1090
|
download: "Download",
|
|
1065
1091
|
loaded: "{count} loaded file(s)",
|
|
1066
1092
|
selected: "{count} selected",
|
|
1067
|
-
unloaded: "{count} folder(s) not expanded, excluded from select-all",
|
|
1068
1093
|
folderFailed: "Failed to open folder: {message}",
|
|
1069
1094
|
demoDownload: "Demo mode: \"{name}\" will download once OpenList is connected.",
|
|
1070
1095
|
demoPreview: "Demo mode: \"{name}\" will preview once OpenList is connected.",
|
|
1071
1096
|
demoBatch: "Demo mode: {count} selected file(s) would be zipped.",
|
|
1072
1097
|
downloadFailed: "Download failed: {message}",
|
|
1073
|
-
previewFailed: "Preview failed: {message}",
|
|
1074
1098
|
batchFailed: "Failed to create ZIP: {message}",
|
|
1075
1099
|
defaultZip: "resources",
|
|
1076
1100
|
clear: "Clear",
|
|
@@ -1101,7 +1125,6 @@ const fileListLocales = {
|
|
|
1101
1125
|
remembered: "Remembered",
|
|
1102
1126
|
forgetPassword: "Forget",
|
|
1103
1127
|
unlockFolder: "Enter the password for {name}",
|
|
1104
|
-
networkHint: "Possibly blocked by CORS: check cors.allow_origins in OpenList, or ALLOW_URLS in OpenList-Worker.",
|
|
1105
1128
|
deepHint: "Only loaded folders are filtered. ",
|
|
1106
1129
|
deepSearch: "Try deep search",
|
|
1107
1130
|
deepRunning: "Searching · {count} folders checked",
|
|
@@ -1132,7 +1155,6 @@ const fileListLocales = {
|
|
|
1132
1155
|
zipBlockText: "This browser can zip at most {limit} at once. Select fewer files.",
|
|
1133
1156
|
gotIt: "OK",
|
|
1134
1157
|
moreRemaining: "{count} more",
|
|
1135
|
-
showMore: "Show more",
|
|
1136
1158
|
showAll: "Show all",
|
|
1137
1159
|
showRest: "Show the remaining {count}",
|
|
1138
1160
|
showLess: "Show less",
|
|
@@ -3049,6 +3071,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
3049
3071
|
stickyTop.value = top;
|
|
3050
3072
|
}
|
|
3051
3073
|
onMounted(() => {
|
|
3074
|
+
warnPublicSecrets(props, props.locale);
|
|
3052
3075
|
passwords.sync();
|
|
3053
3076
|
loadRoot();
|
|
3054
3077
|
loadSettings();
|
|
@@ -3571,4 +3594,4 @@ function enhanceAppWithFileList({ app }) {
|
|
|
3571
3594
|
if (!app._context.components.FileList) app.component("FileList", _sfc_main);
|
|
3572
3595
|
if (!app._context.components.VPFileList) app.component("VPFileList", _sfc_main);
|
|
3573
3596
|
}
|
|
3574
|
-
export { _sfc_main as FileList, _sfc_main as VPFileList,
|
|
3597
|
+
export { _sfc_main as FileList, _sfc_main as VPFileList, enhanceAppWithFileList, fileListLocales, formatLabel, resolveLabels };
|
|
@@ -6,8 +6,6 @@ interface FileListLabels {
|
|
|
6
6
|
filter: string;
|
|
7
7
|
refresh: string;
|
|
8
8
|
batch: string;
|
|
9
|
-
/** @deprecated No longer shown; the selection count lives in the toolbar. */
|
|
10
|
-
batchCount: string;
|
|
11
9
|
batching: string;
|
|
12
10
|
passwordPrompt: string;
|
|
13
11
|
passwordPlaceholder: string;
|
|
@@ -27,15 +25,11 @@ interface FileListLabels {
|
|
|
27
25
|
download: string;
|
|
28
26
|
loaded: string;
|
|
29
27
|
selected: string;
|
|
30
|
-
/** @deprecated No longer shown; the footer only shows loaded files and size. */
|
|
31
|
-
unloaded: string;
|
|
32
28
|
folderFailed: string;
|
|
33
29
|
demoDownload: string;
|
|
34
30
|
demoPreview: string;
|
|
35
31
|
demoBatch: string;
|
|
36
32
|
downloadFailed: string;
|
|
37
|
-
/** @deprecated Preview errors are shown in the dialog (`previewUnavailable`). */
|
|
38
|
-
previewFailed: string;
|
|
39
33
|
batchFailed: string;
|
|
40
34
|
defaultZip: string;
|
|
41
35
|
/** Text button that clears the selection (wide layout). */
|
|
@@ -90,8 +84,6 @@ interface FileListLabels {
|
|
|
90
84
|
forgetPassword: string;
|
|
91
85
|
/** Lock button on a folder that needs a password. `{name}` */
|
|
92
86
|
unlockFolder: string;
|
|
93
|
-
/** @deprecated Network failures now append `corsHint`. */
|
|
94
|
-
networkHint: string;
|
|
95
87
|
/** Deep search: the row at the end of a filtered list. `{count}` where noted */
|
|
96
88
|
deepHint: string;
|
|
97
89
|
deepSearch: string;
|
|
@@ -146,8 +138,6 @@ interface FileListLabels {
|
|
|
146
138
|
showNext: string;
|
|
147
139
|
/** Show the next page, short form for narrow lists. `{count}` */
|
|
148
140
|
showNextShort: string;
|
|
149
|
-
/** No longer shown (“Show next” replaces it); kept for existing overrides. */
|
|
150
|
-
showMore: string;
|
|
151
141
|
showAll: string;
|
|
152
142
|
/** Fewer than a page left. `{count}` */
|
|
153
143
|
showRest: string;
|
|
@@ -216,17 +206,6 @@ interface FileListProps {
|
|
|
216
206
|
/** Per-key label overrides on top of the locale preset. */
|
|
217
207
|
labels?: Partial<FileListLabels>;
|
|
218
208
|
}
|
|
219
|
-
/** Shape of one entry returned by `POST /api/fs/list`. */
|
|
220
|
-
interface OpenListEntry {
|
|
221
|
-
name: string;
|
|
222
|
-
size: number;
|
|
223
|
-
is_dir: boolean;
|
|
224
|
-
modified: string;
|
|
225
|
-
created?: string;
|
|
226
|
-
sign?: string;
|
|
227
|
-
thumb?: string;
|
|
228
|
-
type?: number;
|
|
229
|
-
}
|
|
230
209
|
declare const _default: import("vue").DefineComponent<FileListProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FileListProps> & Readonly<{}>, {
|
|
231
210
|
base: string;
|
|
232
211
|
path: string;
|
|
@@ -318,66 +297,6 @@ declare global {
|
|
|
318
297
|
export declare const fileListLocales: Record<FileListLocale, FileListLabels>;
|
|
319
298
|
export declare function formatLabel(template: string, values?: Record<string, string | number>): string;
|
|
320
299
|
export declare function resolveLabels(locale?: FileListLocale, overrides?: Partial<FileListLabels>): FileListLabels;
|
|
321
|
-
interface SortableNode {
|
|
322
|
-
name: string;
|
|
323
|
-
size: number;
|
|
324
|
-
is_dir: boolean;
|
|
325
|
-
modified: string;
|
|
326
|
-
}
|
|
327
|
-
type SortKey = 'name' | 'size' | 'modified';
|
|
328
|
-
export declare function joinPath(parent: string, name: string): string;
|
|
329
|
-
export declare function encodePath(path: string): string;
|
|
330
|
-
/**
|
|
331
|
-
* Make one path segment safe as a ZIP entry segment: no separators,
|
|
332
|
-
* no `.` / `..` traversal, no empty names.
|
|
333
|
-
*/
|
|
334
|
-
export declare function zipSegment(name: string): string;
|
|
335
|
-
/** Join path segments into a ZIP entry name, sanitising each segment. */
|
|
336
|
-
export declare function zipEntryName(segments: string[]): string;
|
|
337
|
-
/**
|
|
338
|
-
* Return `name`, or `name (2)`, `name (3)`... when it is already in `used`.
|
|
339
|
-
* The suffix goes before the extension of the last segment. Adds the result to `used`.
|
|
340
|
-
*/
|
|
341
|
-
export declare function uniqueEntryName(name: string, used: Set<string>): string;
|
|
342
|
-
/** Human-readable size. `0` reads `0 B`; missing, negative or invalid sizes read `-`. */
|
|
343
|
-
export declare function formatSize(size: number): string;
|
|
344
|
-
export declare function formatDate(iso: string): string;
|
|
345
|
-
/** Upper-case extension for the type badge, e.g. `PDF`. */
|
|
346
|
-
export declare function extOf(name: string): string;
|
|
347
|
-
type FileKind = 'doc' | 'sheet' | 'slide' | 'pdf' | 'image' | 'media' | 'archive' | 'code' | 'other';
|
|
348
|
-
type PreviewKind = 'image' | 'video' | 'audio' | 'text' | 'pdf' | 'none';
|
|
349
|
-
/** Rough file family, used to colour the type badge. */
|
|
350
|
-
export declare function fileKind(name: string): FileKind;
|
|
351
|
-
/**
|
|
352
|
-
* How a file is shown in the preview dialog. Office documents and anything
|
|
353
|
-
* else the browser cannot render are `none` (info + download).
|
|
354
|
-
*/
|
|
355
|
-
export declare function previewKind(name: string): PreviewKind;
|
|
356
|
-
/** Sum of the `size` of the given entries, ignoring missing or invalid sizes. */
|
|
357
|
-
export declare function totalSize(items: Array<{
|
|
358
|
-
size?: number;
|
|
359
|
-
}>): number;
|
|
360
|
-
export declare function compareNodes(a: SortableNode, b: SortableNode, key: SortKey, ascending?: boolean, locale?: string): number;
|
|
361
|
-
interface IframePreview {
|
|
362
|
-
label: string;
|
|
363
|
-
scheme: string;
|
|
364
|
-
}
|
|
365
|
-
/**
|
|
366
|
-
* Viewers from OpenList's public `iframe_previews` setting that match a file,
|
|
367
|
-
* in the order OpenList lists them. Keys are comma-separated extensions or a
|
|
368
|
-
* `/regex/flags` tested against the extension, as in OpenList's frontend.
|
|
369
|
-
*/
|
|
370
|
-
export declare function iframePreviewsFor(name: string, setting: string | undefined): IframePreview[];
|
|
371
|
-
/**
|
|
372
|
-
* Fill an OpenList preview scheme: `$name`, `$url` (raw URL) and `$durl`
|
|
373
|
-
* (signed download URL), each optionally prefixed with `e` (URI-encode) or
|
|
374
|
-
* `b` (base64), e.g. `$e_url`, `$b_url`, `$e_durl`.
|
|
375
|
-
*/
|
|
376
|
-
export declare function fillPreviewUrl(scheme: string, args: {
|
|
377
|
-
name: string;
|
|
378
|
-
rawUrl: string;
|
|
379
|
-
downloadUrl: string;
|
|
380
|
-
}): string;
|
|
381
300
|
/**
|
|
382
301
|
* Register `<FileList>` and `<VPFileList>` globally.
|
|
383
302
|
*
|
|
@@ -395,4 +314,4 @@ export declare function fillPreviewUrl(scheme: string, args: {
|
|
|
395
314
|
* ```
|
|
396
315
|
*/
|
|
397
316
|
export declare function enhanceAppWithFileList({ app }: EnhanceAppContext): void;
|
|
398
|
-
export {
|
|
317
|
+
export { _default as FileList, _default as VPFileList, type FileListLabels, type FileListLocale, type FileListProps, type FileListSource };
|
package/dist/client/ssr/index.js
CHANGED
|
@@ -615,6 +615,38 @@ function createDemoApi(delay = 220) {
|
|
|
615
615
|
}
|
|
616
616
|
/** Whether a demo file can really be previewed, downloaded and zipped. */
|
|
617
617
|
const isDemoFile = isSample;
|
|
618
|
+
// src/client/devWarnings.ts
|
|
619
|
+
const SECURITY_DOC = "https://nrjycyd.github.io/vitepress-plugin-filelist/guide/security";
|
|
620
|
+
/** Props a page wrote that end up, readable by anyone, in the built site. */
|
|
621
|
+
function publicSecrets(props) {
|
|
622
|
+
const found = [];
|
|
623
|
+
if (props.token) found.push("token");
|
|
624
|
+
if (props.password || props.sources?.some((source) => source.password)) found.push("password");
|
|
625
|
+
return found;
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Development builds only. The site's Vite replaces `import.meta.env` in
|
|
629
|
+
* dependencies too (`DEV` is true under `vitepress dev`, false in a build);
|
|
630
|
+
* without a bundler there is no `env` and this is not a development build.
|
|
631
|
+
*/
|
|
632
|
+
function isDevBuild() {
|
|
633
|
+
return import.meta.env?.DEV === true;
|
|
634
|
+
}
|
|
635
|
+
let warned = false;
|
|
636
|
+
/**
|
|
637
|
+
* While the site runs in development, say once per page load that `token` and
|
|
638
|
+
* `password` written in Markdown are public. Production builds stay silent.
|
|
639
|
+
* Returns whether it warned.
|
|
640
|
+
*/
|
|
641
|
+
function warnPublicSecrets(props, locale, dev = isDevBuild()) {
|
|
642
|
+
if (warned || !dev) return false;
|
|
643
|
+
const found = publicSecrets(props);
|
|
644
|
+
if (!found.length) return false;
|
|
645
|
+
warned = true;
|
|
646
|
+
const names = found.join(" / ");
|
|
647
|
+
console.warn(locale === "en-US" ? `[vitepress-plugin-filelist] This page sets ${names} on <FileList>. It is copied as is into the built site, where every visitor can read it. Prefer a guest account limited to a base path. ${SECURITY_DOC} (shown in development only)` : `[vitepress-plugin-filelist] 本页的 <FileList> 写了 ${names}:它会原样进入构建后的网页,所有访客都能看到。建议改用限定基础路径的 guest 账户。${SECURITY_DOC}(仅开发时提示)`);
|
|
648
|
+
return true;
|
|
649
|
+
}
|
|
618
650
|
// src/client/ConfirmDialog.vue
|
|
619
651
|
const _sfc_main$3 = /*@__PURE__*/ defineComponent({
|
|
620
652
|
__name: "ConfirmDialog",
|
|
@@ -897,7 +929,6 @@ const fileListLocales = {
|
|
|
897
929
|
filter: "筛选文件名",
|
|
898
930
|
refresh: "刷新",
|
|
899
931
|
batch: "下载 ZIP",
|
|
900
|
-
batchCount: "批量下载({count})",
|
|
901
932
|
batching: "打包中 {percent}%",
|
|
902
933
|
passwordPrompt: "该目录受密码保护:",
|
|
903
934
|
passwordPlaceholder: "输入密码",
|
|
@@ -915,13 +946,11 @@ const fileListLocales = {
|
|
|
915
946
|
download: "下载",
|
|
916
947
|
loaded: "{count} 个已加载文件",
|
|
917
948
|
selected: "已选 {count} 项",
|
|
918
|
-
unloaded: "{count} 个目录未展开,未计入全选",
|
|
919
949
|
folderFailed: "打开文件夹失败:{message}",
|
|
920
950
|
demoDownload: "演示模式:接入 OpenList 后会下载「{name}」",
|
|
921
951
|
demoPreview: "演示模式:接入 OpenList 后可预览「{name}」",
|
|
922
952
|
demoBatch: "演示模式:将打包已勾选的 {count} 个文件",
|
|
923
953
|
downloadFailed: "下载失败:{message}",
|
|
924
|
-
previewFailed: "预览失败:{message}",
|
|
925
954
|
batchFailed: "打包失败:{message}",
|
|
926
955
|
defaultZip: "资源",
|
|
927
956
|
clear: "清除",
|
|
@@ -952,7 +981,6 @@ const fileListLocales = {
|
|
|
952
981
|
remembered: "已记住",
|
|
953
982
|
forgetPassword: "忘记",
|
|
954
983
|
unlockFolder: "输入 {name} 的密码",
|
|
955
|
-
networkHint: "可能被跨域拦截:请检查 OpenList 的 cors.allow_origins,或 OpenList-Worker 的 ALLOW_URLS。",
|
|
956
984
|
deepHint: "只筛选了已加载的内容,",
|
|
957
985
|
deepSearch: "尝试深度搜索",
|
|
958
986
|
deepRunning: "正在深度搜索 · 已查找 {count} 个文件夹",
|
|
@@ -983,7 +1011,6 @@ const fileListLocales = {
|
|
|
983
1011
|
zipBlockText: "当前浏览器一次最多打包 {limit},请分批勾选下载。",
|
|
984
1012
|
gotIt: "知道了",
|
|
985
1013
|
moreRemaining: "还有 {count} 项",
|
|
986
|
-
showMore: "显示更多",
|
|
987
1014
|
showAll: "全部显示",
|
|
988
1015
|
showRest: "显示剩余 {count} 项",
|
|
989
1016
|
showLess: "收起",
|
|
@@ -999,7 +1026,6 @@ const fileListLocales = {
|
|
|
999
1026
|
filter: "Filter files",
|
|
1000
1027
|
refresh: "Refresh",
|
|
1001
1028
|
batch: "Download ZIP",
|
|
1002
|
-
batchCount: "Download ZIP ({count})",
|
|
1003
1029
|
batching: "Zipping {percent}%",
|
|
1004
1030
|
passwordPrompt: "This folder is password protected:",
|
|
1005
1031
|
passwordPlaceholder: "Folder password",
|
|
@@ -1017,13 +1043,11 @@ const fileListLocales = {
|
|
|
1017
1043
|
download: "Download",
|
|
1018
1044
|
loaded: "{count} loaded file(s)",
|
|
1019
1045
|
selected: "{count} selected",
|
|
1020
|
-
unloaded: "{count} folder(s) not expanded, excluded from select-all",
|
|
1021
1046
|
folderFailed: "Failed to open folder: {message}",
|
|
1022
1047
|
demoDownload: "Demo mode: \"{name}\" will download once OpenList is connected.",
|
|
1023
1048
|
demoPreview: "Demo mode: \"{name}\" will preview once OpenList is connected.",
|
|
1024
1049
|
demoBatch: "Demo mode: {count} selected file(s) would be zipped.",
|
|
1025
1050
|
downloadFailed: "Download failed: {message}",
|
|
1026
|
-
previewFailed: "Preview failed: {message}",
|
|
1027
1051
|
batchFailed: "Failed to create ZIP: {message}",
|
|
1028
1052
|
defaultZip: "resources",
|
|
1029
1053
|
clear: "Clear",
|
|
@@ -1054,7 +1078,6 @@ const fileListLocales = {
|
|
|
1054
1078
|
remembered: "Remembered",
|
|
1055
1079
|
forgetPassword: "Forget",
|
|
1056
1080
|
unlockFolder: "Enter the password for {name}",
|
|
1057
|
-
networkHint: "Possibly blocked by CORS: check cors.allow_origins in OpenList, or ALLOW_URLS in OpenList-Worker.",
|
|
1058
1081
|
deepHint: "Only loaded folders are filtered. ",
|
|
1059
1082
|
deepSearch: "Try deep search",
|
|
1060
1083
|
deepRunning: "Searching · {count} folders checked",
|
|
@@ -1085,7 +1108,6 @@ const fileListLocales = {
|
|
|
1085
1108
|
zipBlockText: "This browser can zip at most {limit} at once. Select fewer files.",
|
|
1086
1109
|
gotIt: "OK",
|
|
1087
1110
|
moreRemaining: "{count} more",
|
|
1088
|
-
showMore: "Show more",
|
|
1089
1111
|
showAll: "Show all",
|
|
1090
1112
|
showRest: "Show the remaining {count}",
|
|
1091
1113
|
showLess: "Show less",
|
|
@@ -2356,6 +2378,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
2356
2378
|
stickyTop.value = top;
|
|
2357
2379
|
}
|
|
2358
2380
|
onMounted(() => {
|
|
2381
|
+
warnPublicSecrets(props, props.locale);
|
|
2359
2382
|
passwords.sync();
|
|
2360
2383
|
loadRoot();
|
|
2361
2384
|
loadSettings();
|
|
@@ -2691,4 +2714,4 @@ function enhanceAppWithFileList({ app }) {
|
|
|
2691
2714
|
if (!app._context.components.FileList) app.component("FileList", _sfc_main);
|
|
2692
2715
|
if (!app._context.components.VPFileList) app.component("VPFileList", _sfc_main);
|
|
2693
2716
|
}
|
|
2694
|
-
export { _sfc_main as FileList, _sfc_main as VPFileList,
|
|
2717
|
+
export { _sfc_main as FileList, _sfc_main as VPFileList, enhanceAppWithFileList, fileListLocales, formatLabel, resolveLabels };
|
package/package.json
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vitepress-plugin-filelist",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"packageManager": "pnpm@11.25.0",
|
|
5
|
+
"engines": {
|
|
6
|
+
"node": "^20.19.0 || >=22.12.0"
|
|
7
|
+
},
|
|
5
8
|
"type": "module",
|
|
6
9
|
"description": "OpenList file browser for VitePress: tree view, batch ZIP download, i18n, password and token support.",
|
|
7
10
|
"author": "nrjycyd",
|
|
@@ -44,17 +47,23 @@
|
|
|
44
47
|
"test:watch": "vitest",
|
|
45
48
|
"pack:check": "npm pack --dry-run",
|
|
46
49
|
"test:e2e": "playwright test",
|
|
47
|
-
"e2e:site": "pnpm run build && pnpm --dir demo install --force && pnpm --dir demo run build:e2e"
|
|
50
|
+
"e2e:site": "pnpm run build && pnpm --dir demo install --force && pnpm --dir demo run build:e2e",
|
|
51
|
+
"test:compat": "node scripts/compat.mjs"
|
|
48
52
|
},
|
|
49
53
|
"peerDependencies": {
|
|
50
|
-
"vitepress": "^1.
|
|
54
|
+
"vitepress": "^1.6.0 || >=2.0.0-alpha.18",
|
|
55
|
+
"vitepress-tuck": ">=0.12.2",
|
|
51
56
|
"vue": "^3.5.0"
|
|
52
57
|
},
|
|
58
|
+
"peerDependenciesMeta": {
|
|
59
|
+
"vitepress-tuck": {
|
|
60
|
+
"optional": true
|
|
61
|
+
}
|
|
62
|
+
},
|
|
53
63
|
"dependencies": {
|
|
54
64
|
"client-zip": "^2.5.1",
|
|
55
65
|
"dompurify": "^3.4.17",
|
|
56
|
-
"markdown-it": "^14.3.3"
|
|
57
|
-
"vitepress-tuck": "^0.12.2"
|
|
66
|
+
"markdown-it": "^14.3.3"
|
|
58
67
|
},
|
|
59
68
|
"devDependencies": {
|
|
60
69
|
"@playwright/test": "1.63.0",
|
|
@@ -67,6 +76,7 @@
|
|
|
67
76
|
"unplugin-vue": "^8.0.1",
|
|
68
77
|
"unrun": "^0.3.1",
|
|
69
78
|
"vitepress": "^2.0.0-alpha.21",
|
|
79
|
+
"vitepress-tuck": "^0.12.2",
|
|
70
80
|
"vitest": "^5.1.0",
|
|
71
81
|
"vue": "^3.5.0",
|
|
72
82
|
"vue-tsc": "^2.2.0"
|