vite-plugin-files-server 1.0.3 → 1.1.2

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/plugin/index.js CHANGED
@@ -1,337 +1,762 @@
1
- // src/index.ts
1
+ // src/v1_1_0_theme/index.ts
2
2
  import fs from "fs";
3
3
  import path from "path";
4
4
 
5
- // src/temp.html?raw
6
- var temp_default = `<!DOCTYPE html>\r
7
- <html>\r
5
+ // src/v1_1_0_theme/tempFolderDark.html?raw
6
+ var tempFolderDark_default = `<!doctype html>\r
7
+ <html lang="en">\r
8
8
  <head>\r
9
9
  <meta charset="UTF-8" />\r
10
- <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />\r
11
- <title>listing directory {{url}}</title>\r
10
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />\r
11
+ <title>Demo List {{pageTitle}}</title>\r
12
12
  <style>\r
13
- /* body {\r
14
- font-family: system-ui;\r
15
- padding: 2rem;\r
16
- max-width: 800px;\r
17
- margin: 0 auto;\r
13
+ /* \u6697\u8272\u4E3B\u9898 - \u53EA\u4FEE\u6539\u989C\u8272\uFF0C\u4FDD\u6301\u4E0E\u4EAE\u8272\u4E3B\u9898\u76F8\u540C\u7684\u5E03\u5C40\u548C\u5C3A\u5BF8 */\r
14
+ body {\r
15
+ background-color: #1a1a1a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #f8f9fa \u2192 \u6697\u8272 #1a1a1a */\r
16
+ color: #e0e0e0; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #212529 \u2192 \u6697\u8272 #e0e0e0 */\r
17
+ font-family:\r
18
+ -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif;\r
19
+ margin: 0;\r
20
+ padding: 20px;\r
21
+ font-size: 14px;\r
22
+ line-height: 1.5;\r
18
23
  }\r
19
- h2 {\r
20
- border-bottom: 1px solid #eee;\r
21
- padding-bottom: 10px;\r
24
+ \r
25
+ /* \u9762\u5305\u5C51\u5BFC\u822A - \u6697\u8272 */\r
26
+ .breadcrumb {\r
27
+ color: #a0a0a0; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #6c757d \u2192 \u6697\u8272 #a0a0a0 */\r
28
+ margin-bottom: 20px;\r
29
+ font-size: 13px;\r
30
+ background-color: #2a2a2a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #ffffff \u2192 \u6697\u8272 #2a2a2a */\r
31
+ padding: 12px 16px;\r
32
+ border-radius: 8px;\r
33
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); /* \u4FEE\u6539\uFF1A\u9634\u5F71\u52A0\u6DF1 */\r
34
+ border: 1px solid #3a3a3a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #e9ecef \u2192 \u6697\u8272 #3a3a3a */\r
35
+ }\r
36
+ .breadcrumb-link {\r
37
+ color: #4dabf7; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #0d6efd \u2192 \u6697\u8272 #4dabf7 */\r
38
+ text-decoration: none;\r
39
+ font-weight: 500;\r
40
+ transition: all 0.2s;\r
41
+ padding: 4px 8px;\r
42
+ border-radius: 4px;\r
43
+ }\r
44
+ .breadcrumb-link:hover {\r
45
+ background-color: #3a3a3a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #e7f1ff \u2192 \u6697\u8272 #3a3a3a */\r
46
+ color: #74c0fc; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #0a58ca \u2192 \u6697\u8272 #74c0fc */\r
47
+ text-decoration: none;\r
22
48
  }\r
23
- table {\r
24
- width: 100%;\r
25
- border-collapse: collapse;\r
49
+ \r
50
+ /* \u5185\u5BB9\u533A\u57DF */\r
51
+ .content-area {\r
52
+ margin-top: 20px;\r
26
53
  }\r
27
- td {\r
28
- padding: 8px;\r
29
- border-bottom: 1px solid #f5f5f5;\r
54
+ \r
55
+ /* gallery\u6811\u5F62\u89C6\u56FE - \u6697\u8272 */\r
56
+ .gallery-tree {\r
57
+ font-family: 'SF Mono', 'Monaco', 'Consolas', 'Liberation Mono', monospace;\r
58
+ line-height: 1.6;\r
59
+ color: #e0e0e0; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #212529 \u2192 \u6697\u8272 #e0e0e0 */\r
30
60
  }\r
31
- a {\r
61
+ \r
62
+ /* \u6587\u4EF6\u5939\u9879 - \u6697\u8272\u4E3B\u9898 */\r
63
+ .folder-item {\r
64
+ cursor: default;\r
65
+ margin: 6px 0;\r
66
+ padding-left: 20px;\r
67
+ position: relative;\r
68
+ }\r
69
+ /* .folder-item:hover {\r
70
+ background-color: #2a2a2a; \r
71
+ } */\r
72
+ .folder-name {\r
73
+ color: #4dabf7; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #0d6efd \u2192 \u6697\u8272 #4dabf7 */\r
32
74
  text-decoration: none;\r
33
- color: #646cff;\r
75
+ display: inline-block;\r
76
+ padding: 6px 12px;\r
77
+ border-radius: 6px;\r
78
+ font-weight: 500;\r
79
+ background-color: #525252; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #e7f1ff \u2192 \u6697\u8272 #2a2a2a */\r
80
+ border: 1px solid #3a3a3a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #cfe2ff \u2192 \u6697\u8272 #3a3a3a */\r
81
+ transition: all 0.2s;\r
34
82
  }\r
35
- a:hover {\r
36
- text-decoration: underline;\r
83
+ .folder-name::before {\r
84
+ content: '\u{1F5C2}\uFE0F';\r
85
+ margin-right: 8px;\r
37
86
  }\r
38
- ul,\r
39
- li {\r
40
- list-style: none;\r
41
- margin: 0;\r
42
- padding: 0;\r
43
- } */\r
44
- * {\r
45
- margin: 0;\r
46
- padding: 0;\r
47
- outline: 0;\r
87
+ .level-sub {\r
88
+ background-color: #2a2a2a;\r
89
+ padding: 1px 12px;\r
90
+ }\r
91
+ .level-sub::before {\r
92
+ content: '\u{1F4C1}';\r
93
+ margin-right: 8px;\r
48
94
  }\r
49
95
  \r
50
- body {\r
51
- padding: 80px 100px;\r
52
- font: 13px 'Helvetica Neue', 'Lucida Grande', 'Arial';\r
53
- background: #ece9e9 -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ece9e9));\r
54
- background: #ece9e9 -moz-linear-gradient(top, #fff, #ece9e9);\r
55
- background-repeat: no-repeat;\r
56
- color: #555;\r
57
- -webkit-font-smoothing: antialiased;\r
58
- }\r
59
- h1,\r
60
- h2,\r
61
- h3 {\r
62
- padding-left: 10px;\r
63
- font-size: 22px;\r
64
- color: #343434;\r
65
- }\r
66
- h1 em,\r
67
- h2 em {\r
68
- padding: 0 5px;\r
69
- font-weight: normal;\r
70
- }\r
71
- h1 {\r
72
- font-size: 60px;\r
73
- }\r
74
- h2 {\r
75
- margin-top: 10px;\r
76
- }\r
77
- h3 {\r
78
- margin: 5px 0 10px 0;\r
79
- padding-bottom: 5px;\r
80
- border-bottom: 1px solid #eee;\r
81
- font-size: 18px;\r
82
- }\r
83
- ul li {\r
96
+ /* \u6587\u4EF6\u7F51\u683C\u5E03\u5C40 - \u4E09\u5217 */\r
97
+ .file-grid {\r
98
+ margin: 12px 0 20px 0;\r
99
+ display: block;\r
100
+ }\r
101
+ .file-row {\r
102
+ display: flex;\r
103
+ margin: 8px 0;\r
104
+ }\r
105
+ .file-column {\r
106
+ flex: 1;\r
107
+ min-width: 0;\r
108
+ margin: 0 6px;\r
109
+ padding: 8px 12px;\r
110
+ border-radius: 8px;\r
111
+ transition: all 0.2s;\r
112
+ background-color: #2a2a2a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #ffffff \u2192 \u6697\u8272 #2a2a2a */\r
113
+ border: 1px solid #3a3a3a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #dee2e6 \u2192 \u6697\u8272 #3a3a3a */\r
114
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); /* \u4FEE\u6539\uFF1A\u9634\u5F71\u52A0\u6DF1 */\r
115
+ }\r
116
+ .file-column:hover {\r
117
+ background-color: #3a3a3a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #f8f9fa \u2192 \u6697\u8272 #3a3a3a */\r
118
+ transform: translateY(-2px);\r
119
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); /* \u4FEE\u6539\uFF1A\u9634\u5F71\u52A0\u6DF1 */\r
120
+ border-color: #4dabf7; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #0d6efd \u2192 \u6697\u8272 #4dabf7 */\r
121
+ }\r
122
+ .empty-column {\r
123
+ background-color: transparent;\r
124
+ border: 1px solid transparent;\r
125
+ box-shadow: none;\r
126
+ }\r
127
+ .empty-column:hover {\r
128
+ background-color: transparent;\r
129
+ transform: none;\r
130
+ box-shadow: none;\r
131
+ border-color: transparent;\r
132
+ }\r
133
+ .html-file-link {\r
134
+ color: #e0e0e0; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #212529 \u2192 \u6697\u8272 #e0e0e0 */\r
135
+ text-decoration: none;\r
136
+ display: block;\r
137
+ white-space: nowrap;\r
138
+ overflow: hidden;\r
139
+ text-overflow: ellipsis;\r
140
+ padding-left: 24px;\r
141
+ position: relative;\r
142
+ font-size: 13px;\r
143
+ }\r
144
+ .html-file-link:hover {\r
145
+ color: #ffffff; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #0d6efd \u2192 \u6697\u8272 #ffffff */\r
146
+ }\r
147
+ .html-file-link::before {\r
148
+ content: '\u{1F4C4}';\r
149
+ position: absolute;\r
150
+ left: 0;\r
151
+ top: 0;\r
152
+ color: #a0a0a0; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #6c757d \u2192 \u6697\u8272 #a0a0a0 */\r
153
+ }\r
154
+ \r
155
+ .back-all-link {\r
156
+ font-family:\r
157
+ -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif;\r
158
+ }\r
159
+ .back-all-link a {\r
160
+ text-decoration: none;\r
161
+ padding: 10px 16px;\r
162
+ display: block;\r
163
+ border-radius: 8px;\r
164
+ transition: all 0.2s;\r
165
+ background-color: #2a2a2a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #ffffff \u2192 \u6697\u8272 #2a2a2a */\r
166
+ border: 1px solid #3a3a3a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #dee2e6 \u2192 \u6697\u8272 #3a3a3a */\r
167
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); /* \u4FEE\u6539\uFF1A\u9634\u5F71\u52A0\u6DF1 */\r
168
+ }\r
169
+ .back-all-link a:hover {\r
170
+ transform: translateY(-2px);\r
171
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); /* \u4FEE\u6539\uFF1A\u9634\u5F71\u52A0\u6DF1 */\r
172
+ }\r
173
+ .back-all-link a.back-link {\r
174
+ color: #4dabf7; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #0d6efd \u2192 \u6697\u8272 #4dabf7 */\r
175
+ background-color: #2a2a2a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #ffffff \u2192 \u6697\u8272 #2a2a2a */\r
176
+ border: 1px solid #3a3a3a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #cfe2ff \u2192 \u6697\u8272 #3a3a3a */\r
177
+ padding-left: 48px;\r
178
+ position: relative;\r
179
+ color: #a0a0a0; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #6c757d \u2192 \u6697\u8272 #a0a0a0 */\r
180
+ background-color: #2a2a2a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #f8f9fa \u2192 \u6697\u8272 #2a2a2a */\r
181
+ border: 1px solid #3a3a3a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #e9ecef \u2192 \u6697\u8272 #3a3a3a */\r
182
+ }\r
183
+ .back-all-link a.back-link:hover {\r
184
+ background-color: #3a3a3a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #f8f9fa \u2192 \u6697\u8272 #3a3a3a */\r
185
+ border-color: #4dabf7; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #0d6efd \u2192 \u6697\u8272 #4dabf7 */\r
186
+ background-color: #3a3a3a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #e9ecef \u2192 \u6697\u8272 #3a3a3a */\r
187
+ border-color: #4dabf7; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #dee2e6 \u2192 \u6697\u8272 #4dabf7 */\r
188
+ }\r
189
+ .back-all-link a.back-link::before {\r
190
+ content: '\u{1F4C1}';\r
191
+ position: absolute;\r
192
+ left: 16px;\r
193
+ top: 50%;\r
194
+ transform: translateY(-50%);\r
195
+ font-size: 16px;\r
196
+ content: '\u2190';\r
197
+ margin-right: 8px;\r
198
+ }\r
199
+ \r
200
+ /* \u6587\u4EF6\u5217\u8868\u89C6\u56FE - \u6697\u8272\u4E3B\u9898 */\r
201
+ .file-list {\r
84
202
  list-style: none;\r
203
+ padding: 0;\r
204
+ margin: 0;\r
85
205
  }\r
86
- ul li:hover {\r
87
- cursor: pointer;\r
88
- color: #2e2e2e;\r
206
+ .file-list li {\r
207
+ margin: 6px 0;\r
89
208
  }\r
90
- ul li .path {\r
91
- padding-left: 5px;\r
92
- font-weight: bold;\r
209
+ .file-list a {\r
210
+ text-decoration: none;\r
211
+ padding: 10px 16px;\r
212
+ display: block;\r
213
+ border-radius: 8px;\r
214
+ transition: all 0.2s;\r
215
+ background-color: #2a2a2a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #ffffff \u2192 \u6697\u8272 #2a2a2a */\r
216
+ border: 1px solid #3a3a3a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #dee2e6 \u2192 \u6697\u8272 #3a3a3a */\r
217
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); /* \u4FEE\u6539\uFF1A\u9634\u5F71\u52A0\u6DF1 */\r
218
+ }\r
219
+ .file-list a:hover {\r
220
+ transform: translateY(-2px);\r
221
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); /* \u4FEE\u6539\uFF1A\u9634\u5F71\u52A0\u6DF1 */\r
222
+ }\r
223
+ .file-list a.folder-link {\r
224
+ color: #4dabf7; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #0d6efd \u2192 \u6697\u8272 #4dabf7 */\r
225
+ background-color: #2a2a2a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #ffffff \u2192 \u6697\u8272 #2a2a2a */\r
226
+ border: 1px solid #3a3a3a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #cfe2ff \u2192 \u6697\u8272 #3a3a3a */\r
227
+ padding-left: 48px;\r
228
+ position: relative;\r
229
+ }\r
230
+ .file-list a.folder-link:hover {\r
231
+ background-color: #3a3a3a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #f8f9fa \u2192 \u6697\u8272 #3a3a3a */\r
232
+ border-color: #4dabf7; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #0d6efd \u2192 \u6697\u8272 #4dabf7 */\r
233
+ }\r
234
+ .file-list a.folder-link::before {\r
235
+ content: '\u{1F4C1}';\r
236
+ position: absolute;\r
237
+ left: 16px;\r
238
+ top: 50%;\r
239
+ transform: translateY(-50%);\r
240
+ font-size: 16px;\r
241
+ }\r
242
+ .file-list a.back-link {\r
243
+ color: #a0a0a0; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #6c757d \u2192 \u6697\u8272 #a0a0a0 */\r
244
+ background-color: #2a2a2a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #f8f9fa \u2192 \u6697\u8272 #2a2a2a */\r
245
+ border: 1px solid #3a3a3a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #e9ecef \u2192 \u6697\u8272 #3a3a3a */\r
246
+ }\r
247
+ .file-list a.back-link:hover {\r
248
+ background-color: #3a3a3a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #e9ecef \u2192 \u6697\u8272 #3a3a3a */\r
249
+ border-color: #4dabf7; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #dee2e6 \u2192 \u6697\u8272 #4dabf7 */\r
250
+ }\r
251
+ .file-list a.back-link::before {\r
252
+ content: '\u2190';\r
253
+ margin-right: 8px;\r
254
+ }\r
255
+ .file-list a.file-link {\r
256
+ color: #e0e0e0; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #212529 \u2192 \u6697\u8272 #e0e0e0 */\r
257
+ background-color: #2a2a2a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #ffffff \u2192 \u6697\u8272 #2a2a2a */\r
258
+ border: 1px solid #3a3a3a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #dee2e6 \u2192 \u6697\u8272 #3a3a3a */\r
259
+ padding-left: 48px;\r
260
+ position: relative;\r
261
+ }\r
262
+ .file-list a.file-link:hover {\r
263
+ background-color: #3a3a3a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #f8f9fa \u2192 \u6697\u8272 #3a3a3a */\r
264
+ border-color: #4dabf7; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #0d6efd \u2192 \u6697\u8272 #4dabf7 */\r
265
+ }\r
266
+ .file-list a.file-link::before {\r
267
+ content: '\u{1F4C4}';\r
268
+ position: absolute;\r
269
+ left: 16px;\r
270
+ top: 50%;\r
271
+ transform: translateY(-50%);\r
272
+ font-size: 16px;\r
273
+ color: #a0a0a0; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #6c757d \u2192 \u6697\u8272 #a0a0a0 */\r
93
274
  }\r
94
- ul li .line {\r
95
- padding-right: 5px;\r
275
+ \r
276
+ /* \u7A7A\u72B6\u6001 - \u6697\u8272 */\r
277
+ .empty-message {\r
278
+ color: #a0a0a0; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #6c757d \u2192 \u6697\u8272 #a0a0a0 */\r
96
279
  font-style: italic;\r
280
+ text-align: center;\r
281
+ padding: 32px;\r
282
+ background-color: #2a2a2a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #ffffff \u2192 \u6697\u8272 #2a2a2a */\r
283
+ border-radius: 8px;\r
284
+ border: 1px dashed #3a3a3a; /* \u4FEE\u6539\uFF1A\u4EAE\u8272 #dee2e6 \u2192 \u6697\u8272 #3a3a3a */\r
285
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); /* \u4FEE\u6539\uFF1A\u9634\u5F71\u52A0\u6DF1 */\r
97
286
  }\r
98
- ul li:first-child .path {\r
99
- padding-left: 0;\r
287
+ \r
288
+ /* \u54CD\u5E94\u5F0F\u8BBE\u8BA1 */\r
289
+ @media (max-width: 768px) {\r
290
+ body {\r
291
+ padding: 12px;\r
292
+ }\r
293
+ .file-row {\r
294
+ flex-direction: column;\r
295
+ }\r
296
+ .file-column {\r
297
+ margin: 4px 0;\r
298
+ }\r
100
299
  }\r
101
- p {\r
300
+ </style>\r
301
+ </head>\r
302
+ <body>\r
303
+ <div class="breadcrumb">{{breadcrumb}}</div>\r
304
+ <div class="content-area">{{list}}</div>\r
305
+ </body>\r
306
+ </html>\r
307
+ `;
308
+
309
+ // src/v1_1_0_theme/tempFolderLight.html?raw
310
+ var tempFolderLight_default = `<!doctype html>\r
311
+ <html lang="en">\r
312
+ <head>\r
313
+ <meta charset="UTF-8" />\r
314
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />\r
315
+ <title>Demo List {{pageTitle}}</title>\r
316
+ <style>\r
317
+ /* \u4EAE\u8272\u4E3B\u9898 - \u6574\u4F53\u660E\u4EAE\u98CE\u683C */\r
318
+ body {\r
319
+ background-color: #f8f9fa;\r
320
+ color: #212529;\r
321
+ font-family:\r
322
+ -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif;\r
323
+ margin: 0;\r
324
+ padding: 20px;\r
325
+ font-size: 14px;\r
102
326
  line-height: 1.5;\r
103
327
  }\r
104
- a {\r
105
- color: #555;\r
328
+ \r
329
+ /* \u9762\u5305\u5C51\u5BFC\u822A - \u4EAE\u8272 */\r
330
+ .breadcrumb {\r
331
+ color: #6c757d;\r
332
+ margin-bottom: 20px;\r
333
+ font-size: 13px;\r
334
+ background-color: #ffffff;\r
335
+ padding: 12px 16px;\r
336
+ border-radius: 8px;\r
337
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\r
338
+ border: 1px solid #e9ecef;\r
339
+ }\r
340
+ .breadcrumb-link {\r
341
+ color: #0d6efd;\r
342
+ text-decoration: none;\r
343
+ font-weight: 500;\r
344
+ transition: all 0.2s;\r
345
+ padding: 4px 8px;\r
346
+ border-radius: 4px;\r
347
+ }\r
348
+ .breadcrumb-link:hover {\r
349
+ background-color: #e7f1ff;\r
350
+ color: #0a58ca;\r
106
351
  text-decoration: none;\r
107
352
  }\r
108
- a:hover {\r
109
- color: #303030;\r
353
+ \r
354
+ /* \u5185\u5BB9\u533A\u57DF */\r
355
+ .content-area {\r
356
+ margin-top: 20px;\r
110
357
  }\r
111
- #stacktrace {\r
112
- margin-top: 15px;\r
358
+ \r
359
+ /* gallery\u6811\u5F62\u89C6\u56FE - \u4EAE\u8272 */\r
360
+ .gallery-tree {\r
361
+ font-family: 'SF Mono', 'Monaco', 'Consolas', 'Liberation Mono', monospace;\r
362
+ line-height: 1.6;\r
363
+ color: #212529;\r
113
364
  }\r
114
- .directory h1 {\r
115
- margin-bottom: 15px;\r
116
- font-size: 18px;\r
365
+ \r
366
+ /* \u6587\u4EF6\u5939\u9879 - \u4EAE\u8272\u4E3B\u9898 */\r
367
+ .folder-item {\r
368
+ cursor: default;\r
369
+ margin: 6px 0;\r
370
+ padding-left: 20px;\r
371
+ position: relative;\r
372
+ }\r
373
+ .folder-item:hover {\r
374
+ background-color: #f8f9fa;\r
375
+ }\r
376
+ .folder-name {\r
377
+ color: #0d6efd;\r
378
+ text-decoration: none;\r
379
+ display: inline-block;\r
380
+ padding: 6px 12px;\r
381
+ border-radius: 6px;\r
382
+ font-weight: 500;\r
383
+ background-color: #a8ccff;\r
384
+ border: 1px solid #cfe2ff;\r
385
+ transition: all 0.2s;\r
117
386
  }\r
118
- ul#files {\r
119
- width: 100%;\r
120
- height: 100%;\r
121
- overflow: hidden;\r
387
+ .folder-name::before {\r
388
+ content: '\u{1F5C2}\uFE0F';\r
389
+ margin-right: 8px;\r
122
390
  }\r
123
- ul#files li {\r
124
- float: left;\r
125
- width: 30%;\r
126
- line-height: 25px;\r
127
- margin: 1px;\r
391
+ .level-sub {\r
392
+ background-color: #e7f1ff;\r
393
+ padding: 1px 12px;\r
128
394
  }\r
129
- ul#files li a {\r
395
+ .level-sub::before {\r
396
+ content: '\u{1F4C1}';\r
397
+ margin-right: 8px;\r
398
+ }\r
399
+ \r
400
+ /* \u6587\u4EF6\u7F51\u683C\u5E03\u5C40 - \u4E09\u5217 */\r
401
+ .file-grid {\r
402
+ margin: 12px 0 20px 0;\r
130
403
  display: block;\r
131
- height: 25px;\r
132
- border: 1px solid transparent;\r
133
- -webkit-border-radius: 5px;\r
134
- -moz-border-radius: 5px;\r
135
- border-radius: 5px;\r
136
- overflow: hidden;\r
137
- white-space: nowrap;\r
138
404
  }\r
139
- ul#files li a:focus,\r
140
- ul#files li a:hover {\r
141
- background: rgba(255, 255, 255, 0.65);\r
142
- border: 1px solid #ececec;\r
405
+ .file-row {\r
406
+ display: flex;\r
407
+ margin: 8px 0;\r
408
+ }\r
409
+ .file-column {\r
410
+ flex: 1;\r
411
+ min-width: 0;\r
412
+ margin: 0 6px;\r
413
+ padding: 8px 12px;\r
414
+ border-radius: 8px;\r
415
+ transition: all 0.2s;\r
416
+ background-color: #ffffff;\r
417
+ border: 1px solid #dee2e6;\r
418
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\r
419
+ }\r
420
+ .file-column:hover {\r
421
+ background-color: #f8f9fa;\r
422
+ transform: translateY(-2px);\r
423
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\r
424
+ border-color: #0d6efd;\r
425
+ }\r
426
+ .empty-column {\r
427
+ background-color: transparent;\r
428
+ border: 1px solid transparent;\r
429
+ box-shadow: none;\r
143
430
  }\r
144
- ul#files li a.highlight {\r
145
- -webkit-transition: background 0.4s ease-in-out;\r
146
- background: #ffff4f;\r
147
- border-color: #e9dc51;\r
431
+ .empty-column:hover {\r
432
+ background-color: transparent;\r
433
+ transform: none;\r
434
+ box-shadow: none;\r
435
+ border-color: transparent;\r
148
436
  }\r
149
- #search {\r
437
+ .html-file-link {\r
438
+ color: #212529;\r
439
+ text-decoration: none;\r
150
440
  display: block;\r
151
- position: fixed;\r
152
- top: 20px;\r
153
- right: 20px;\r
154
- width: 90px;\r
155
- -webkit-transition: width ease 0.2s, opacity ease 0.4s;\r
156
- -moz-transition: width ease 0.2s, opacity ease 0.4s;\r
157
- -webkit-border-radius: 32px;\r
158
- -moz-border-radius: 32px;\r
159
- -webkit-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7),\r
160
- 0px 1px 0px rgba(255, 255, 255, 0.03);\r
161
- -moz-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7),\r
162
- 0px 1px 0px rgba(255, 255, 255, 0.03);\r
163
- -webkit-font-smoothing: antialiased;\r
164
- text-align: left;\r
165
- font: 13px 'Helvetica Neue', Arial, sans-serif;\r
166
- padding: 4px 10px;\r
167
- border: none;\r
168
- background: transparent;\r
169
- margin-bottom: 0;\r
170
- outline: none;\r
171
- opacity: 0.7;\r
172
- color: #888;\r
173
- }\r
174
- #search:focus {\r
175
- width: 120px;\r
176
- opacity: 1;\r
177
- }\r
178
- \r
179
- /*views*/\r
180
- #files span {\r
181
- display: inline-block;\r
441
+ white-space: nowrap;\r
182
442
  overflow: hidden;\r
183
443
  text-overflow: ellipsis;\r
184
- text-indent: 10px;\r
444
+ padding-left: 24px;\r
445
+ position: relative;\r
446
+ font-size: 13px;\r
185
447
  }\r
186
- #files .name {\r
187
- background-repeat: no-repeat;\r
448
+ .html-file-link:hover {\r
449
+ color: #0d6efd;\r
188
450
  }\r
189
- #files .icon .name {\r
190
- text-indent: 28px;\r
451
+ .html-file-link::before {\r
452
+ content: '\u{1F4C4}';\r
453
+ position: absolute;\r
454
+ left: 0;\r
455
+ top: 0;\r
456
+ color: #6c757d;\r
191
457
  }\r
192
458
  \r
193
- /*tiles*/\r
194
- .view-tiles .name {\r
195
- width: 100%;\r
196
- background-position: 8px 5px;\r
197
- }\r
198
- .view-tiles .size,\r
199
- .view-tiles .date {\r
200
- display: none;\r
459
+ .back-all-link {\r
460
+ font-family:\r
461
+ -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif;\r
201
462
  }\r
202
- \r
203
- /*details*/\r
204
- ul#files.view-details li {\r
205
- float: none;\r
463
+ .back-all-link a {\r
464
+ text-decoration: none;\r
465
+ padding: 10px 16px;\r
206
466
  display: block;\r
207
- width: 90%;\r
208
- }\r
209
- ul#files.view-details li.header {\r
210
- height: 25px;\r
211
- background: #000;\r
212
- color: #fff;\r
213
- font-weight: bold;\r
214
- }\r
215
- .view-details .header {\r
216
- border-radius: 5px;\r
467
+ border-radius: 8px;\r
468
+ transition: all 0.2s;\r
469
+ background-color: #ffffff;\r
470
+ border: 1px solid #dee2e6;\r
471
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\r
472
+ }\r
473
+ .back-all-link a:hover {\r
474
+ transform: translateY(-2px);\r
475
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\r
476
+ }\r
477
+ .back-all-link a.back-link {\r
478
+ color: #0d6efd;\r
479
+ background-color: #ffffff;\r
480
+ border: 1px solid #cfe2ff;\r
481
+ padding-left: 48px;\r
482
+ position: relative;\r
483
+ color: #6c757d;\r
484
+ background-color: #f8f9fa;\r
485
+ border: 1px solid #e9ecef;\r
486
+ }\r
487
+ .back-all-link a.back-link:hover {\r
488
+ background-color: #e9ecef;\r
489
+ border-color: #dee2e6;\r
490
+ background-color: #f8f9fa;\r
491
+ border-color: #0d6efd;\r
492
+ }\r
493
+ .back-all-link a.back-link::before {\r
494
+ content: '\u{1F4C1}';\r
495
+ position: absolute;\r
496
+ left: 16px;\r
497
+ top: 50%;\r
498
+ transform: translateY(-50%);\r
499
+ font-size: 16px;\r
500
+ content: '\u2190';\r
501
+ margin-right: 8px;\r
217
502
  }\r
218
- .view-details .name {\r
219
- width: 60%;\r
220
- background-position: 8px 5px;\r
503
+ \r
504
+ /* \u6587\u4EF6\u5217\u8868\u89C6\u56FE - \u4EAE\u8272\u4E3B\u9898 */\r
505
+ .file-list {\r
506
+ list-style: none;\r
507
+ padding: 0;\r
508
+ margin: 0;\r
221
509
  }\r
222
- .view-details .size {\r
223
- width: 10%;\r
510
+ .file-list li {\r
511
+ margin: 6px 0;\r
224
512
  }\r
225
- .view-details .date {\r
226
- width: 30%;\r
513
+ .file-list a {\r
514
+ text-decoration: none;\r
515
+ padding: 10px 16px;\r
516
+ display: block;\r
517
+ border-radius: 8px;\r
518
+ transition: all 0.2s;\r
519
+ background-color: #ffffff;\r
520
+ border: 1px solid #dee2e6;\r
521
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\r
522
+ }\r
523
+ .file-list a:hover {\r
524
+ transform: translateY(-2px);\r
525
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\r
526
+ }\r
527
+ .file-list a.folder-link {\r
528
+ color: #0d6efd;\r
529
+ background-color: #ffffff;\r
530
+ border: 1px solid #cfe2ff;\r
531
+ padding-left: 48px;\r
532
+ position: relative;\r
533
+ }\r
534
+ .file-list a.folder-link:hover {\r
535
+ background-color: #f8f9fa;\r
536
+ border-color: #0d6efd;\r
537
+ }\r
538
+ .file-list a.folder-link::before {\r
539
+ content: '\u{1F4C1}';\r
540
+ position: absolute;\r
541
+ left: 16px;\r
542
+ top: 50%;\r
543
+ transform: translateY(-50%);\r
544
+ font-size: 16px;\r
545
+ }\r
546
+ .file-list a.back-link {\r
547
+ color: #6c757d;\r
548
+ background-color: #f8f9fa;\r
549
+ border: 1px solid #e9ecef;\r
550
+ }\r
551
+ .file-list a.back-link:hover {\r
552
+ background-color: #e9ecef;\r
553
+ border-color: #dee2e6;\r
554
+ }\r
555
+ .file-list a.back-link::before {\r
556
+ content: '\u2190';\r
557
+ margin-right: 8px;\r
558
+ }\r
559
+ .file-list a.file-link {\r
560
+ color: #212529;\r
561
+ background-color: #ffffff;\r
562
+ border: 1px solid #dee2e6;\r
563
+ padding-left: 48px;\r
564
+ position: relative;\r
565
+ }\r
566
+ .file-list a.file-link:hover {\r
567
+ background-color: #f8f9fa;\r
568
+ border-color: #0d6efd;\r
569
+ }\r
570
+ .file-list a.file-link::before {\r
571
+ content: '\u{1F4C4}';\r
572
+ position: absolute;\r
573
+ left: 16px;\r
574
+ top: 50%;\r
575
+ transform: translateY(-50%);\r
576
+ font-size: 16px;\r
577
+ color: #6c757d;\r
227
578
  }\r
228
- .view-details .size,\r
229
- .view-details .date {\r
230
- text-align: right;\r
231
- direction: rtl;\r
579
+ \r
580
+ /* \u7A7A\u72B6\u6001 - \u4EAE\u8272 */\r
581
+ .empty-message {\r
582
+ color: #6c757d;\r
583
+ font-style: italic;\r
584
+ text-align: center;\r
585
+ padding: 32px;\r
586
+ background-color: #ffffff;\r
587
+ border-radius: 8px;\r
588
+ border: 1px dashed #dee2e6;\r
589
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\r
232
590
  }\r
233
591
  \r
234
- /*mobile*/\r
592
+ /* \u54CD\u5E94\u5F0F\u8BBE\u8BA1 */\r
235
593
  @media (max-width: 768px) {\r
236
594
  body {\r
237
- font-size: 13px;\r
238
- line-height: 16px;\r
239
- padding: 0;\r
240
- }\r
241
- #search {\r
242
- position: static;\r
243
- width: 100%;\r
244
- font-size: 2em;\r
245
- line-height: 1.8em;\r
246
- text-indent: 10px;\r
247
- border: 0;\r
248
- border-radius: 0;\r
249
- padding: 10px 0;\r
250
- margin: 0;\r
251
- }\r
252
- #search:focus {\r
253
- width: 100%;\r
254
- border: 0;\r
255
- opacity: 1;\r
256
- }\r
257
- .directory h1 {\r
258
- font-size: 2em;\r
259
- line-height: 1.5em;\r
260
- color: #fff;\r
261
- background: #000;\r
262
- padding: 15px 10px;\r
263
- margin: 0;\r
264
- }\r
265
- ul#files {\r
266
- border-top: 1px solid #cacaca;\r
595
+ padding: 12px;\r
267
596
  }\r
268
- ul#files li {\r
269
- float: none;\r
270
- width: auto !important;\r
271
- display: block;\r
272
- border-bottom: 1px solid #cacaca;\r
273
- font-size: 2em;\r
274
- line-height: 1.2em;\r
275
- text-indent: 0;\r
276
- margin: 0;\r
597
+ .file-row {\r
598
+ flex-direction: column;\r
277
599
  }\r
278
- ul#files li:nth-child(odd) {\r
279
- background: #e0e0e0;\r
600
+ .file-column {\r
601
+ margin: 4px 0;\r
280
602
  }\r
281
- ul#files li a {\r
282
- height: auto;\r
283
- border: 0;\r
284
- border-radius: 0;\r
285
- padding: 15px 10px;\r
286
- }\r
287
- ul#files li a:focus,\r
288
- ul#files li a:hover {\r
289
- border: 0;\r
290
- }\r
291
- #files .header,\r
292
- #files .size,\r
293
- #files .date {\r
294
- display: none !important;\r
295
- }\r
296
- #files .name {\r
297
- float: none;\r
298
- display: inline-block;\r
299
- width: 100%;\r
300
- text-indent: 0;\r
301
- background-position: 0 50%;\r
302
- }\r
303
- #files .icon .name {\r
304
- text-indent: 41px;\r
305
- }\r
306
- }\r
307
- #files .icon-directory .name {\r
308
- background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAAWtQTFRFAAAA/PPQ9Nhc2q402qQ12qs2/PTX2pg12p81+/LM89NE9dto2q82+/fp2rM22qY39d6U+/bo2qo2/frx/vz32q812qs12qE279SU8c4w9NZP+/LK//367s9y7s925cp0/vzw9t92//342po2/vz25s1579B6+OSO2bQ0/v799NyT8tE79dld8Msm+OrC/vzx79KA2IYs7s6I9d6R4cJe9+OF/PLI/fry79OF/v30//328tWB89RJ8c9p8c0u9eCf//7+9txs6sts5Mdr+++5+u2z/vrv+/fq6cFz8dBs8tA57cpq+OaU9uGs27Y8//799NdX/PbY9uB89unJ//z14sNf+emh+emk+vDc+uys9+OL8dJy89NH+eic8tN5+OaV+OWR9N2n9dtl9t529+KF9+GB9Nue9NdU8tR/9t5y89qW9dpj89iO89eG/vvu2pQ12Y4z/vzy2Ict/vvv48dr/vzz4sNg///+2Igty3PqwQAAAAF0Uk5TAEDm2GYAAACtSURBVBjTY2AgA2iYlJWVhfohBPg0yx38y92dS0pKVOVBAqIi6sb2vsWWpfrFeTI8QAEhYQEta28nCwM1OVleZqCAmKCEkUdwYWmhQnFeOStQgL9cySqkNNDHVJGbiY0FKCCuYuYSGRsV5KgjxcXIARRQNncNj09JTgqw0ZbkZAcK5LuFJaRmZqfHeNnpSucDBQoiEtOycnIz4qI9bfUKQA6pKKqAgqIKQyK8BgAZ5yfODmnHrQAAAABJRU5ErkJggg==);\r
309
- }\r
310
- #files .icon-text-html .name {\r
311
- background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHtSURBVDjLjZM9T9tQFIYpQ5eOMBKlW6eWIQipa8RfQKQghEAKqZgKFQgmFn5AWyVDCipVQZC2EqBWlEqdO2RCpAssQBRsx1+1ndix8wFvfW6wcUhQsfTI0j33PD7n+N4uAF2E+/S5RFwG/8Njl24/LyCIOI6j1+v1y0ajgU64cSSTybdBSVAwSMmmacKyLB/DMKBpGkRRZBJBEJBKpXyJl/yABLTBtm1Uq1X2JsrlMnRdhyRJTFCpVEAfSafTTUlQoFs1luxBAkoolUqQZbmtJTYTT/AoHInOfpcwtVtkwcSBgrkDGYph+60oisIq4Xm+VfB0+U/P0Lvj3NwPGfHPTcHMvoyFXwpe7UmQtAqTUCU0D1VVbwTPVk5jY19Fe3ZfQny7CE51WJDXqpjeEUHr45ki9rIqa4dmQiJfMLItGEs/FcQ2ucbRmdnSYy5vYWyLx/w3EaMfLmBaDpMQvuDJ65PY8Dpnz3wpYmLtApzcrIAqmfrEgdZH1grY/a36w6Xz0DKD8ES25/niYS6+wWE8mWfByY8cXmYEJFYLkHUHtVqNQcltAvoLD3v7o/FUHsNvzlnwxfsCEukC/ho3yUHaBN5Buo17Ojtyl+DqrnvQgUtfcC0ZcAdkUeA+ye7eMru9AUGIJPe4zh509UP/AAfNypi8oj/mAAAAAElFTkSuQmCC);\r
312
603
  }\r
313
604
  </style>\r
314
605
  </head>\r
315
- <body class="directory">\r
316
- <div class="wrapper">\r
317
- <h1>{{headItem}}</h1>\r
318
- <ul id="files" class="view-tiles">\r
319
- {{listItems}}\r
320
- </ul>\r
321
- </div>\r
606
+ <body>\r
607
+ <div class="breadcrumb">{{breadcrumb}}</div>\r
608
+ <div class="content-area">{{list}}</div>\r
322
609
  </body>\r
323
610
  </html>\r
324
611
  `;
325
612
 
326
- // src/index.ts
613
+ // src/v1_1_0_theme/index.ts
327
614
  function fileServerPlugin(options = {}) {
328
- const { enable = true } = options;
615
+ const { enable = true, root = "", theme = "dark" } = options;
329
616
  return {
330
617
  name: "vite-plugin-files-server",
331
- // 必须唯一
332
- // 核心钩子:配置开发服务器
333
618
  configureServer(server) {
334
619
  if (!enable) return;
620
+ let templateString;
621
+ try {
622
+ if (theme === "light") {
623
+ templateString = tempFolderLight_default;
624
+ } else {
625
+ templateString = tempFolderDark_default;
626
+ }
627
+ } catch (e) {
628
+ console.error("Failed to load template:", e);
629
+ templateString = tempFolderDark_default;
630
+ }
631
+ function buildGalleryTree(dirPath, baseUrl = "", depth = 0) {
632
+ try {
633
+ const files = fs.readdirSync(dirPath);
634
+ let html = "";
635
+ files.sort((a, b) => {
636
+ const aPath = path.join(dirPath, a);
637
+ const bPath = path.join(dirPath, b);
638
+ const aIsDir = fs.statSync(aPath).isDirectory();
639
+ const bIsDir = fs.statSync(bPath).isDirectory();
640
+ if (aIsDir && !bIsDir) return -1;
641
+ if (!aIsDir && bIsDir) return 1;
642
+ return a.localeCompare(b);
643
+ });
644
+ const folderItems = [];
645
+ const htmlFiles = [];
646
+ files.forEach((file) => {
647
+ const filePath = path.join(dirPath, file);
648
+ const relativePath = path.join(baseUrl, file).replace(/\\/g, "/");
649
+ try {
650
+ const stats = fs.statSync(filePath);
651
+ if (stats.isDirectory()) {
652
+ folderItems.push({ file, filePath, relativePath });
653
+ } else if (path.extname(file).toLowerCase() === ".html" || path.extname(file).toLowerCase() === ".htm") {
654
+ htmlFiles.push({ file, relativePath });
655
+ }
656
+ } catch (e) {
657
+ console.error(`Error reading ${filePath}:`, e);
658
+ }
659
+ });
660
+ folderItems.forEach(({ file, filePath, relativePath }) => {
661
+ let level = relativePath.split("/");
662
+ if (level.length == 4) {
663
+ html += `<div class="folder-item">
664
+ <a class="folder-name">${file}</a>
665
+ </div>`;
666
+ } else if (level.length == 5) {
667
+ html += `<div class="folder-item">
668
+ <a class="folder-name level-sub">${file}</a>
669
+ </div>`;
670
+ }
671
+ const subTree = buildGalleryTree(filePath, relativePath, depth + 1);
672
+ if (subTree) {
673
+ html += subTree;
674
+ }
675
+ });
676
+ if (htmlFiles.length > 0) {
677
+ html += `<div class="file-grid">`;
678
+ for (let i = 0; i < htmlFiles.length; i += 3) {
679
+ const rowFiles = htmlFiles.slice(i, i + 3);
680
+ html += `<div class="file-row">`;
681
+ rowFiles.forEach(({ file, relativePath }) => {
682
+ html += `<div class="file-column">
683
+ <a href="${relativePath}" class="html-file-link">${file}</a>
684
+ </div>`;
685
+ });
686
+ for (let j = rowFiles.length; j < 3; j++) {
687
+ html += `<div class="file-column empty-column"></div>`;
688
+ }
689
+ html += `</div>`;
690
+ }
691
+ html += `</div>`;
692
+ }
693
+ return html;
694
+ } catch (e) {
695
+ console.error(`Error reading directory ${dirPath}:`, e);
696
+ return "";
697
+ }
698
+ }
699
+ function generateFileList(fullPath, url) {
700
+ try {
701
+ const files = fs.readdirSync(fullPath);
702
+ let listItems = "";
703
+ const sortedFiles = files.sort((a, b) => {
704
+ const aPath = path.join(fullPath, a);
705
+ const bPath = path.join(fullPath, b);
706
+ const aIsDir = fs.statSync(aPath).isDirectory();
707
+ const bIsDir = fs.statSync(bPath).isDirectory();
708
+ if (aIsDir && !bIsDir) return -1;
709
+ if (!aIsDir && bIsDir) return 1;
710
+ return a.localeCompare(b);
711
+ });
712
+ if (url !== "/") {
713
+ const backUrl = url.split("/").slice(0, -1).join("/") || "/";
714
+ listItems += `<li><a href="${backUrl}" class="folder-link back-link">..</a></li>
715
+ `;
716
+ }
717
+ sortedFiles.forEach((file) => {
718
+ const filePath = path.join(fullPath, file);
719
+ const stats = fs.statSync(filePath);
720
+ const isDir = stats.isDirectory();
721
+ const href = path.join(url, file).replace(/\\/g, "/");
722
+ if (isDir) {
723
+ listItems += `<li><a href="${href}" class="folder-link">${file}</a></li>
724
+ `;
725
+ } else {
726
+ listItems += `<li><a href="${href}" class="file-link">${file}</a></li>
727
+ `;
728
+ }
729
+ });
730
+ return listItems;
731
+ } catch (e) {
732
+ console.error(`Error generating file list:`, e);
733
+ return "";
734
+ }
735
+ }
736
+ function generateHtmlPage(url, content, isGalleryTree = false) {
737
+ let urlSplitArray = url.split("/").filter(Boolean);
738
+ let breadcrumb = "";
739
+ if (url === "/") {
740
+ breadcrumb = '<a href="/" class="breadcrumb-link">/</a>';
741
+ } else {
742
+ breadcrumb = '<a href="/" class="breadcrumb-link">Home</a> ';
743
+ urlSplitArray.forEach((p, index) => {
744
+ const href = "/" + urlSplitArray.slice(0, index + 1).join("/");
745
+ breadcrumb += `<a href="${href}" class="breadcrumb-link"> / ${p}</a>`;
746
+ if (index < urlSplitArray.length - 1) {
747
+ breadcrumb += " ";
748
+ }
749
+ });
750
+ }
751
+ const pageTitle = url === "/" ? "/" : url;
752
+ const list = isGalleryTree ? `<div class="gallery-tree">${content || '<div class="empty-message">No HTML files found</div>'}</div>` : `
753
+ <ul class="file-list">
754
+ ${content || '<li class="empty-message">No files found</li>'}
755
+ </ul>
756
+ `;
757
+ const html = templateString.replace(/{{pageTitle}}/g, pageTitle).replace(/{{breadcrumb}}/g, breadcrumb).replace(/{{list}}/g, list);
758
+ return html;
759
+ }
335
760
  server.middlewares.use((req, res, next) => {
336
761
  const url = req.url ? decodeURIComponent(req.url.split("?")[0]) : "/";
337
762
  if (url.startsWith("/@") || url.includes("vite")) {
@@ -344,51 +769,79 @@ function fileServerPlugin(options = {}) {
344
769
  if (fs.existsSync(path.join(fullPath, "index.html"))) {
345
770
  return next();
346
771
  }
347
- let urlSplitArray = url.split("/");
348
- if (urlSplitArray[urlSplitArray.length - 1] == "") urlSplitArray = urlSplitArray.slice(0, -1);
349
- let headItem = '<a href="/">\u{1F3E0}\uFE0E</a> / ';
350
- urlSplitArray.forEach((p) => {
351
- p && (headItem += `<a href="/${p}">${p}</a> / `);
352
- });
353
- const files = fs.readdirSync(fullPath);
354
- const listItems = files.map((file) => {
355
- const filePath = path.join(fullPath, file);
356
- const isDir = fs.statSync(filePath).isDirectory();
357
- const href = path.join(url, file).replace(/\\/g, "/");
358
- const item = `
359
- <li>
360
- <a href="${href}" class="icon ${isDir ? "icon-directory" : "icon-html icon-text-html"}">
361
- <span class="name">${file}</span>
362
- </a>
363
- </li>`;
364
- return item;
365
- }).join("");
366
- urlSplitArray = urlSplitArray.slice(0, -1);
367
- let backUrl = urlSplitArray.join("/");
368
- const backItem = `
369
- <li>
370
- <a href="${backUrl}" class="icon icon-directory"><span class="name">..</span></a>
371
- </li>`;
372
- let fullList = urlSplitArray.length > 1 ? backItem + listItems : listItems;
373
- const html = temp_default.replace(/{{title}}/g, `Index of ${url}`).replace(/{{headItem}}/g, headItem).replace(/{{url}}/g, url).replace(/{{listItems}}/g, fullList);
772
+ let content = "";
773
+ const isGalleryTree = url === "/apps/gallery" || url.startsWith("/gallery/");
774
+ if (isGalleryTree) {
775
+ content = `<p class="back-all-link"><a href="/apps" class="back-link">..</a></p>`;
776
+ content += buildGalleryTree(fullPath, url === "/" ? "" : url);
777
+ } else {
778
+ content = generateFileList(fullPath, url);
779
+ }
780
+ const html = generateHtmlPage(url, content, isGalleryTree);
374
781
  res.setHeader("Content-Type", "text/html");
375
782
  res.end(html);
376
783
  return;
377
784
  } else if (!fs.existsSync(fullPath)) {
378
- res.statusCode = 404;
379
- const html = "404 Not Found";
380
- res.setHeader("Content-Type", "text/html");
381
- res.end(html);
785
+ setStatus404(res, url, theme);
382
786
  return;
383
787
  }
384
788
  } catch (e) {
385
- console.error("File Server Plugin Error:", e);
789
+ setStatus500(res, e, theme);
790
+ return;
386
791
  }
387
792
  next();
388
793
  });
389
794
  }
390
795
  };
391
796
  }
797
+ function setStatus404(res, url, theme) {
798
+ res.statusCode = 404;
799
+ res.setHeader("Content-Type", "text/html");
800
+ if (theme === "light") {
801
+ res.end(`
802
+ <!DOCTYPE html>
803
+ <html>
804
+ <head><title>404 Not Found</title></head>
805
+ <body style="background:#f8f9fa;color:#212529;font-family:Consolas;padding:20px;">
806
+ <h1>404 Not Found</h1>
807
+ <p>The requested URL ${url} was not found on this server.</p>
808
+ <p><a href="/" style="color:#0d6efd;">Return to home</a></p>
809
+ </body>
810
+ </html>
811
+ `);
812
+ } else {
813
+ res.end(`
814
+ <!DOCTYPE html>
815
+ <html>
816
+ <head><title>404 Not Found</title></head>
817
+ <body style="background:#000;color:#fff;font-family:Consolas;padding:20px;">
818
+ <h1>404 Not Found</h1>
819
+ <p>The requested URL ${url} was not found on this server.</p>
820
+ <p><a href="/" style="color:#569cd6;">Return to home</a></p>
821
+ </body>
822
+ </html>
823
+ `);
824
+ }
825
+ }
826
+ function setStatus500(res, error, theme) {
827
+ console.error("File Server Plugin Error:", error);
828
+ res.statusCode = 500;
829
+ if (theme === "light") {
830
+ res.end(`
831
+ <!DOCTYPE html>
832
+ <html>
833
+ <head><title>500 Internal Server Error</title></head>
834
+ <body style="background:#f8f9fa;color:#212529;font-family:Consolas;padding:20px;">
835
+ <h1>500 Internal Server Error</h1>
836
+ <p>An error occurred on the server.</p>
837
+ <p><a href="/" style="color:#0d6efd;">Return to home</a></p>
838
+ </body>
839
+ </html>
840
+ `);
841
+ } else {
842
+ res.end("Internal Server Error");
843
+ }
844
+ }
392
845
  export {
393
846
  fileServerPlugin as default
394
847
  };