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 CHANGED
@@ -1,12 +1,21 @@
1
- # vitepress-plugin-filelist
2
-
3
- [![npm](https://img.shields.io/npm/v/vitepress-plugin-filelist)](https://www.npmjs.com/package/vitepress-plugin-filelist)
4
- [![CI](https://github.com/nrjycyd/vitepress-plugin-filelist/actions/workflows/ci.yml/badge.svg)](https://github.com/nrjycyd/vitepress-plugin-filelist/actions/workflows/ci.yml)
5
- [![license](https://img.shields.io/npm/l/vitepress-plugin-filelist)](./LICENSE)
6
-
7
- 面向 VitePress 的 OpenList 文件浏览组件:在文档页里浏览、预览、批量下载 OpenList 上的文件。
8
-
9
- ![文件列表截图](https://raw.githubusercontent.com/nrjycyd/vitepress-plugin-filelist/main/demo/docs/public/screenshot.png)
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 { type FileKind, _default as FileList, _default as VPFileList, type FileListLabels, type FileListLocale, type FileListProps, type FileListSource, type IframePreview, type OpenListEntry, type PreviewKind, type SortKey, type SortableNode };
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, compareNodes, encodePath, enhanceAppWithFileList, extOf, fileKind, fileListLocales, fillPreviewUrl, formatDate, formatLabel, formatSize, iframePreviewsFor, joinPath, previewKind, resolveLabels, totalSize, uniqueEntryName, zipEntryName, zipSegment };
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 { type FileKind, _default as FileList, _default as VPFileList, type FileListLabels, type FileListLocale, type FileListProps, type FileListSource, type IframePreview, type OpenListEntry, type PreviewKind, type SortKey, type SortableNode };
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 _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, compareNodes, encodePath, enhanceAppWithFileList, extOf, fileKind, fileListLocales, fillPreviewUrl, formatDate, formatLabel, formatSize, iframePreviewsFor, joinPath, previewKind, resolveLabels, totalSize, uniqueEntryName, zipEntryName, zipSegment };
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.8.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.0.0 || ^2.0.0-alpha.0",
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"