vite-plugin-files-server 1.0.3 → 1.1.1

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