oipage 1.4.0-alpha.1 → 1.4.1-alpha.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.
Files changed (71) hide show
  1. package/.github/FUNDING.yml +11 -11
  2. package/AUTHORS.txt +6 -6
  3. package/CHANGELOG +99 -83
  4. package/LICENSE +20 -20
  5. package/README.md +80 -80
  6. package/bin/data/mineTypes.json +104 -104
  7. package/bin/disk.js +31 -31
  8. package/bin/help.js +25 -24
  9. package/bin/intercept.js +15 -15
  10. package/bin/run +98 -96
  11. package/bin/serve.d.ts +55 -50
  12. package/bin/serve.js +150 -131
  13. package/bin/template/404.html +183 -171
  14. package/bin/tools/format.js +75 -75
  15. package/bin/tools/network.js +42 -42
  16. package/bin/tools/resolve404.js +83 -83
  17. package/bin/tools/resolveImport.js +88 -88
  18. package/bin/website-htmls/dialogs/index.js +43 -0
  19. package/bin/website-htmls/index.html +18 -0
  20. package/bin/website-htmls/logo.png +0 -0
  21. package/bin/website-htmls/main.js +10 -0
  22. package/bin/website-htmls/pages/App/index.html +4 -0
  23. package/bin/website-htmls/pages/App/index.js +23 -0
  24. package/bin/website-htmls/pages/App/index.scss +43 -0
  25. package/bin/website-htmls/pages/appStore/index.html +6 -0
  26. package/bin/website-htmls/pages/appStore/index.js +18 -0
  27. package/bin/website-htmls/pages/appStore/index.scss +27 -0
  28. package/bin/website-htmls/router.config.js +11 -0
  29. package/bin/website-htmls/styles/common.css +3 -0
  30. package/bin/website-htmls/styles/normalize.css +95 -0
  31. package/bin/website-plugins/intercept/head.js +9 -0
  32. package/bin/website-plugins/intercept/index.js +5 -0
  33. package/bin/website-plugins/intercept/oipage-zipaper-intercept.js +40 -0
  34. package/bin/website-plugins/loader/index.js +12 -0
  35. package/bin/website-plugins/loader/oipage-html-loader.js +8 -0
  36. package/bin/website-plugins/loader/oipage-scss-loader.js +150 -0
  37. package/nodejs/animation/index.d.ts +19 -19
  38. package/nodejs/animation/index.js +104 -104
  39. package/nodejs/cmdlog/index.d.ts +20 -20
  40. package/nodejs/cmdlog/index.js +75 -75
  41. package/nodejs/disk/index.d.ts +16 -16
  42. package/nodejs/disk/index.js +78 -78
  43. package/nodejs/format/index.d.ts +29 -0
  44. package/nodejs/format/index.js +114 -0
  45. package/nodejs/json/index.d.ts +9 -9
  46. package/nodejs/json/index.js +206 -206
  47. package/nodejs/logform/index.d.ts +18 -18
  48. package/nodejs/logform/index.js +94 -94
  49. package/nodejs/reader/index.d.ts +32 -32
  50. package/nodejs/reader/index.js +20 -20
  51. package/nodejs/throttle/index.d.ts +30 -30
  52. package/nodejs/throttle/index.js +50 -50
  53. package/package.json +42 -40
  54. package/web/XMLHttpRequest/index.d.ts +18 -0
  55. package/web/XMLHttpRequest/index.js +65 -0
  56. package/web/animation/index.d.ts +19 -19
  57. package/web/animation/index.js +104 -104
  58. package/web/format/index.d.ts +29 -0
  59. package/web/format/index.js +112 -0
  60. package/web/json/index.d.ts +9 -9
  61. package/web/json/index.js +206 -206
  62. package/web/onReady/index.d.ts +7 -7
  63. package/web/onReady/index.js +8 -8
  64. package/web/performChunk/index.d.ts +4 -4
  65. package/web/performChunk/index.js +19 -19
  66. package/web/reader/index.d.ts +32 -32
  67. package/web/reader/index.js +20 -20
  68. package/web/style/index.d.ts +21 -21
  69. package/web/style/index.js +19 -19
  70. package/web/throttle/index.d.ts +30 -30
  71. package/web/throttle/index.js +50 -50
package/bin/serve.js CHANGED
@@ -1,132 +1,151 @@
1
- const { join } = require("path");
2
- const { existsSync, lstatSync, statSync, createReadStream } = require("fs");
3
- const { createServer } = require('http');
4
- const packageValue = require("../package.json");
5
- const network = require("./tools/network.js");
6
- const mineTypes = require("./data/mineTypes.json");
7
- const resolve404 = require("./tools/resolve404.js");
8
- const resolveImportFactory = require("./tools/resolveImport.js");
9
- const { doIntercept } = require("./intercept.js");
10
-
11
- // 开发服务器
12
- module.exports = function (config) {
13
- let startTime = new Date().valueOf();
14
-
15
- const port = config.devServer.port; // 端口号
16
- const basePath = (/^\./.test(config.devServer.baseUrl)) ? join(process.cwd(), config.devServer.baseUrl) : config.devServer.baseUrl; // 服务器根路径
17
-
18
- const name = (config.name || "OIPage") + "-http-server";
19
- const version = config.version || packageValue.version;
20
-
21
- let Server = createServer(function (request, response) {
22
- let headers = request.headers;
23
- let url = decodeURIComponent(request.url);
24
-
25
- let urlArray = url.split("?");
26
- url = urlArray[0];
27
-
28
- // 请求的文件路径
29
- let filePath = join(basePath, url == "/" ? "index.html" : url.replace(/^\//, ""));
30
-
31
- // 请求拦截
32
- if (doIntercept(url.replace(/^\/@modules\//, ""), config.devServer.intercept, request, response)) {
33
- console.log("<i> \x1b[1m\x1b[32m[" + name + "] intercept: " + url + '\x1b[0m ' + new Date().toLocaleString());
34
- }
35
-
36
- // 如果存在且是文件
37
- else if (existsSync(filePath) && !lstatSync(filePath).isDirectory()) {
38
-
39
- let dotName = /\./.test(filePath) ? filePath.match(/\.([^.]+)$/)[1] : "";
40
- let fileType = mineTypes[dotName]; // 文件类型
41
- let fileInfo = statSync(filePath);
42
-
43
- let fileModifiedTime = new Date(fileInfo.mtime).toGMTString();
44
-
45
- let responseHeader = {
46
- 'Content-type': (fileType || "text/plain") + ";charset=utf-8",
47
- 'Access-Control-Allow-Origin': '*',
48
- 'Server': 'Powered by ' + name + '@' + version,
49
- 'Cache-Control': 'no-cache',
50
- 'Last-Modified': fileModifiedTime
51
- };
52
-
53
- if (headers["if-modified-since"]) {
54
- let ifModifiedSince = new Date(headers["if-modified-since"]).valueOf()
55
- let lastModified = new Date(fileModifiedTime).valueOf()
56
- if (lastModified <= ifModifiedSince) {
57
- response.writeHead('304', responseHeader);
58
- response.end();
59
- console.log("<i> \x1b[1m\x1b[32m[" + name + "] Cache File: " + url + "\x1b[0m " + new Date().toLocaleString() + "\x1b[33m\x1b[1m 304\x1b[0m");
60
- return;
61
- }
62
- }
63
-
64
- let sendType = "";
65
- let entry = headers.accept !== "*/*";
66
-
67
- // 如果文件小于10M,认为不大,直接读取
68
- if (fileInfo.size < 10 * 1024 * 1024) {
69
- let { source, resolveImport } = resolveImportFactory(basePath, filePath, entry, config.devServer.intercept, urlArray[1] === "download")
70
-
71
- // 只处理非下载文件
72
- // 过大的也不进行处理
73
- if (urlArray[1] !== "download") {
74
- for (let i = 0; i < config.module.rules.length; i++) {
75
- if (config.module.rules[i].test.test(filePath)) {
76
- source = config.module.rules[i].use.call({
77
- root: basePath, // 服务器根路径
78
- path: filePath.replace(basePath, ""), // 文件相对路径
79
- entry, // 是否是浏览器地址栏直接访问
80
- setFileType(_fileType) { // 设置文件类型
81
- fileType = _fileType;
82
- responseHeader['Content-type'] = _fileType + ";charset=utf-8";
83
- }
84
- }, source);
85
- break;
86
- }
87
- }
88
- }
89
-
90
- sendType = "Read";
91
- response.writeHead('200', responseHeader);
92
- response.write(resolveImport(source, fileType !== "application/javascript"));
93
- response.end();
94
- }
95
-
96
- // 对于大文件,使用流读取
97
- else {
98
- sendType = "Stream";
99
- responseHeader["Content-Length"] = fileInfo.size;
100
- response.writeHead('200', responseHeader);
101
- createReadStream(filePath).pipe(response);
102
- }
103
-
104
- console.log("<i> \x1b[1m\x1b[32m[" + name + "] " + sendType + " File: " + url + '\x1b[0m ' + new Date().toLocaleString());
105
- }
106
-
107
- // 否则就是404
108
- else {
109
- response.writeHead(404, {
110
- 'Content-type': "text/html;charset=utf-8",
111
- 'Access-Control-Allow-Origin': '*',
112
- 'Server': 'Powered by ' + name + '@' + version
113
- });
114
- response.write(resolve404(filePath, url));
115
- response.end();
116
- }
117
-
118
- });
119
-
120
- Server.listen(port);
121
-
122
- // 获取网络信息
123
- let networkValue = network();
124
-
125
- // 打印成功提示
126
- console.log('<i> \x1b[1m\x1b[32m[' + name + '] Project is running at:\x1b[0m');
127
- console.log('<i> \x1b[1m\x1b[32m[' + name + '] Loopback: \x1b[36mhttp://localhost:' + port + '/\x1b[0m');
128
- for (let ipv4Item of networkValue.IPv4) console.log('<i> \x1b[1m\x1b[32m[' + name + '] On Your Network (IPv4):\x1b[36m http://' + ipv4Item.address + ':' + port + '/\x1b[0m');
129
- for (let ipv6Item of networkValue.IPv6) console.log('<i> \x1b[1m\x1b[32m[' + name + '] On Your Network (IPv6): \x1b[36mhttp://[' + ipv6Item.address + ']:' + port + '/\x1b[0m');
130
- console.log('<i> \x1b[1m\x1b[32m[' + name + '] Content not from ' + (config.name || "OIPage") + ' is served from \x1b[36m"' + basePath + '" \x1b[0mdirectory');
131
- console.log('\n' + (config.name || "OIPage") + ' ' + version + ' compiled \x1b[1m\x1b[32msuccessfully\x1b[0m in ' + (new Date().valueOf() - startTime) + ' ms\n')
1
+ const { join } = require("path");
2
+ const { existsSync, lstatSync, statSync, createReadStream } = require("fs");
3
+ const { createServer } = require('http');
4
+ const packageValue = require("../package.json");
5
+ const network = require("./tools/network.js");
6
+ const mineTypes = require("./data/mineTypes.json");
7
+ const resolve404 = require("./tools/resolve404.js");
8
+ const resolveImportFactory = require("./tools/resolveImport.js");
9
+ const { doIntercept } = require("./intercept.js");
10
+
11
+ const webisteIntercept = require("./website-plugins/intercept/index.js");
12
+ const webisteLoader = require("./website-plugins/loader/index.js");
13
+
14
+ // 开发服务器
15
+ module.exports = function (config) {
16
+ let startTime = new Date().valueOf();
17
+
18
+ const cache = "cache" in config.devServer ? config.devServer.cache : true;
19
+ const port = config.devServer.port; // 端口号
20
+ const basePath = (/^\./.test(config.devServer.baseUrl)) ? join(process.cwd(), config.devServer.baseUrl) : config.devServer.baseUrl; // 服务器根路径
21
+
22
+ const name = (config.name || "OIPage") + "-http-server";
23
+ const version = config.version || packageValue.version;
24
+
25
+ let Server = createServer(function (request, response) {
26
+ let headers = request.headers;
27
+ let url = decodeURIComponent(request.url);
28
+
29
+ let urlArray = url.split("?");
30
+ url = urlArray[0];
31
+
32
+ // 请求的文件路径
33
+ let filePath;
34
+
35
+ let isWebsite = /^\/_oipage_website_\//.test(url);
36
+ if (isWebsite) {
37
+ filePath = join(__dirname, "./website-htmls/", url.replace(/^\/_oipage_website_\//, ""));
38
+ } else {
39
+ filePath = join(basePath, url == "/" ? "index.html" : url.replace(/^\//, ""));
40
+ }
41
+
42
+ // 请求拦截
43
+ if (doIntercept(url.replace(/^\/_oipage_website_/, "").replace(/^\/@modules\//, ""), isWebsite ? webisteIntercept : config.devServer.intercept, request, response)) {
44
+ console.log("<i> \x1b[1m\x1b[32m[" + name + "] intercept: " + url + '\x1b[0m ' + new Date().toLocaleString());
45
+ }
46
+
47
+ // 如果存在且是文件
48
+ else if (existsSync(filePath) && !lstatSync(filePath).isDirectory()) {
49
+
50
+ let dotName = /\./.test(filePath) ? filePath.match(/\.([^.]+)$/)[1] : "";
51
+ let fileType = mineTypes[dotName]; // 文件类型
52
+ let fileInfo = statSync(filePath);
53
+
54
+ let fileModifiedTime = new Date(fileInfo.mtime).toGMTString();
55
+
56
+ let responseHeader = {
57
+ 'Content-type': (fileType || "text/plain") + ";charset=utf-8",
58
+ 'Access-Control-Allow-Origin': '*',
59
+ 'Server': 'Powered by ' + name + '@' + version,
60
+ 'Cache-Control': 'no-cache',
61
+ // 'Content-Length': fileInfo.size, // 会导致拦截修改的文本内容不对
62
+ 'Last-Modified': fileModifiedTime
63
+ };
64
+
65
+ if (cache && headers["if-modified-since"]) {
66
+ let ifModifiedSince = new Date(headers["if-modified-since"]).valueOf()
67
+ let lastModified = new Date(fileModifiedTime).valueOf()
68
+ if (lastModified <= ifModifiedSince) {
69
+ response.writeHead('304', responseHeader);
70
+ response.end();
71
+ console.log("<i> \x1b[1m\x1b[32m[" + name + "] Cache File: " + url + "\x1b[0m " + new Date().toLocaleString() + "\x1b[33m\x1b[1m 304\x1b[0m");
72
+ return;
73
+ }
74
+ }
75
+
76
+ let sendType = "";
77
+ let entry = headers.accept !== "*/*";
78
+
79
+ // 如果文件小于10M,认为不大,直接读取
80
+ if (fileInfo.size < 10 * 1024 * 1024) {
81
+ let { source, resolveImport } = resolveImportFactory(basePath, filePath, entry, isWebsite ? webisteIntercept : config.devServer.intercept, urlArray[1] === "download", isWebsite)
82
+
83
+ // 只处理非下载文件
84
+ // 过大的也不进行处理
85
+ // (对webiste无效)
86
+ if (urlArray[1] !== "download") {
87
+ let loaders = isWebsite ? webisteLoader : config.module;
88
+
89
+ for (let i = 0; i < loaders.rules.length; i++) {
90
+ if (loaders.rules[i].test.test(filePath)) {
91
+ source = loaders.rules[i].use.call({
92
+ root: basePath, // 服务器根路径
93
+ path: filePath.replace(basePath, ""), // 文件相对路径
94
+ entry, // 是否是浏览器地址栏直接访问
95
+ setFileType(_fileType) { // 设置文件类型
96
+ fileType = _fileType;
97
+ responseHeader['Content-type'] = _fileType + ";charset=utf-8";
98
+ }
99
+ }, source);
100
+ break;
101
+ }
102
+ }
103
+
104
+ }
105
+
106
+ sendType = "Read";
107
+ response.writeHead('200', responseHeader);
108
+ response.write(resolveImport(source, fileType !== "application/javascript"));
109
+ response.end();
110
+ }
111
+
112
+ // 对于大文件,使用流读取
113
+ else {
114
+ sendType = "Stream";
115
+
116
+ responseHeader['Content-Length'] = fileInfo.size
117
+
118
+ response.writeHead('200', responseHeader);
119
+ createReadStream(filePath).pipe(response);
120
+ }
121
+
122
+ console.log("<i> \x1b[1m\x1b[32m[" + name + "] " + sendType + " File: " + url + '\x1b[0m ' + new Date().toLocaleString());
123
+ }
124
+
125
+ // 否则就是404
126
+ else {
127
+ response.writeHead(404, {
128
+ 'Content-type': "text/html;charset=utf-8",
129
+ 'Access-Control-Allow-Origin': '*',
130
+ 'Server': 'Powered by ' + name + '@' + version
131
+ });
132
+ response.write(resolve404(filePath, url));
133
+ response.end();
134
+ }
135
+
136
+ });
137
+
138
+ Server.listen(port);
139
+
140
+ // 获取网络信息
141
+ let networkValue = network();
142
+
143
+ // 打印成功提示
144
+ console.log('<i> \x1b[1m\x1b[32m[' + name + '] Project is running at:\x1b[0m');
145
+ console.log('<i> \x1b[1m\x1b[32m[' + name + '] Loopback: \x1b[36mhttp://localhost:' + port + '/\x1b[0m');
146
+ for (let ipv4Item of networkValue.IPv4) console.log('<i> \x1b[1m\x1b[32m[' + name + '] On Your Network (IPv4):\x1b[36m http://' + ipv4Item.address + ':' + port + '/\x1b[0m');
147
+ for (let ipv6Item of networkValue.IPv6) console.log('<i> \x1b[1m\x1b[32m[' + name + '] On Your Network (IPv6): \x1b[36mhttp://[' + ipv6Item.address + ']:' + port + '/\x1b[0m');
148
+ console.log('<i> \x1b[1m\x1b[32m[' + name + '] Content not from ' + (config.name || "OIPage") + ' is served from \x1b[36m"' + basePath + '" \x1b[0mdirectory');
149
+ if (!cache) console.log('<i> \x1b[1m\x1b[32m[' + name + '] Cancel 304 Cache!\x1b[0m');
150
+ console.log('\n' + (config.name || "OIPage") + ' ' + version + ' compiled \x1b[1m\x1b[32msuccessfully\x1b[0m in ' + (new Date().valueOf() - startTime) + ' ms\n')
132
151
  };
@@ -1,172 +1,184 @@
1
- <!DOCTYPE html>
2
- <html lang="zh-cn">
3
-
4
- <head>
5
- <meta charset="UTF-8">
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
8
- <title>404 Not Found</title>
9
- <style>
10
- body {
11
- margin: 0px;
12
- background-color: #ffffff;
13
- display: flex;
14
- flex-wrap: wrap;
15
- padding: 100px;
16
- }
17
-
18
- a {
19
- text-decoration: none;
20
- color: #284259;
21
- }
22
-
23
- a:hover {
24
- text-decoration: underline;
25
- }
26
-
27
- .fork {
28
- width: 160px;
29
- line-height: 30px;
30
- position: fixed;
31
- background-color: #607D8B;
32
- text-align: center;
33
- color: white;
34
- outline: 2px dashed #607D8B;
35
- width: 200px;
36
- transform: rotate(45deg);
37
- right: -45px;
38
- top: 45px;
39
- z-index: 1;
40
- }
41
-
42
- .current {
43
- box-sizing: border-box;
44
- position: fixed;
45
- left: 0;
46
- top: 0;
47
- line-height: 50px;
48
- padding-left: 20px;
49
- font-size: 14px;
50
- color: #000000;
51
- font-style: italic;
52
- }
53
-
54
- .filelist {
55
- box-sizing: border-box;
56
- position: fixed;
57
- left: 20px;
58
- top: 50px;
59
- outline: 1px solid #9E9E9E;
60
- width: calc(100vw - 40px);
61
- height: calc(100vh - 70px);
62
- overflow: auto;
63
- padding: 20px;
64
- border-radius: 5px;
65
- background-color: #fcfcfc;
66
- }
67
-
68
- .filelist>table {
69
- width: 100%;
70
- text-align: left;
71
- }
72
-
73
- .filelist>table tr>th {
74
- white-space: nowrap;
75
- padding: 0 10px;
76
- }
77
-
78
- .filelist>table>thead>tr>th {
79
- color: #284259;
80
- font-size: 13px;
81
- line-height: 40px;
82
- }
83
-
84
- .filelist>table>tbody>tr {
85
- border: 1px solid #cdcdcd00;
86
- }
87
-
88
- .filelist>table>tbody>tr>th {
89
- text-decoration: none;
90
- font-size: 12px;
91
- color: #3c3c3c;
92
- word-break: break-all;
93
- font-weight: 400;
94
- line-height: 30px;
95
- }
96
-
97
- .filelist>table>tbody>tr>th>.btn {
98
- color: white;
99
- background-color: #2196F3;
100
- padding: 2px 5px;
101
- border-radius: 5px;
102
- }
103
-
104
- .filelist>table>tbody>tr>th.name {
105
- background-repeat: no-repeat;
106
- background-position: left center;
107
- background-size: auto 90%;
108
- padding-left: 30px;
109
- color: #000000;
110
- }
111
-
112
- .filelist>table>tbody>tr>th.name>span {
113
- white-space: nowrap;
114
- }
115
-
116
- .filelist>table>tbody>tr.file>th.name {
117
- background-image: url('${img_file}');
118
- }
119
-
120
- .filelist>table>tbody>tr.folder>th.name {
121
- background-image: url('${img_folder}');
122
- }
123
- </style>
124
- </head>
125
-
126
- <body>
127
- <a href="https://github.com/oi-contrib/OIPage" target="_blank" class="fork">
128
- Fork me on Github
129
- </a>
130
- <div class="current">
131
- 当前位置:${current}
132
- </div>
133
- <div class="filelist">
134
- <table>
135
- <thead>
136
- <tr>
137
- <th>
138
- 名称
139
- </th>
140
- <th>
141
- 修改日期
142
- </th>
143
- <th>
144
- 类型
145
- </th>
146
- <th>
147
- 大小
148
- </th>
149
- <th>
150
- 操作
151
- </th>
152
- </tr>
153
- </thead>
154
- <tbody>
155
- <tr class="folder">
156
- <th class="name"><a href='../'>..</a></th>
157
- <th>-</th>
158
- <th>
159
- 文件夹
160
- </th>
161
- <th>-</th>
162
- <th>
163
- <a href='../' class="btn">打开</a>
164
- </th>
165
- </tr>
166
- ${template}
167
- </tbody>
168
- </table>
169
- </div>
170
- </body>
171
-
1
+ <!DOCTYPE html>
2
+ <html lang="zh-cn">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
8
+ <title>404 Not Found</title>
9
+ <link rel="shortcut icon" href="/_oipage_website_/logo.png">
10
+ <style>
11
+ body {
12
+ margin: 0px;
13
+ background-color: #ffffff;
14
+ display: flex;
15
+ flex-wrap: wrap;
16
+ padding: 100px;
17
+ }
18
+
19
+ a {
20
+ text-decoration: none;
21
+ color: #284259;
22
+ }
23
+
24
+ a:hover {
25
+ text-decoration: underline;
26
+ }
27
+
28
+ .fork {
29
+ width: 160px;
30
+ line-height: 30px;
31
+ position: fixed;
32
+ background-color: #607D8B;
33
+ text-align: center;
34
+ color: white;
35
+ outline: 2px dashed #607D8B;
36
+ width: 200px;
37
+ transform: rotate(45deg);
38
+ right: -45px;
39
+ top: 45px;
40
+ z-index: 1;
41
+ }
42
+
43
+ .current {
44
+ box-sizing: border-box;
45
+ position: fixed;
46
+ left: 0;
47
+ top: 0;
48
+ line-height: 50px;
49
+ padding-left: 20px;
50
+ font-size: 14px;
51
+ color: #000000;
52
+ font-style: italic;
53
+ }
54
+
55
+ .filelist {
56
+ box-sizing: border-box;
57
+ position: fixed;
58
+ left: 20px;
59
+ top: 50px;
60
+ outline: 1px solid #9E9E9E;
61
+ width: calc(100vw - 40px);
62
+ height: calc(100vh - 100px);
63
+ overflow: auto;
64
+ padding: 20px;
65
+ border-radius: 5px;
66
+ background-color: #fcfcfc;
67
+ }
68
+
69
+ .filelist>table {
70
+ width: 100%;
71
+ text-align: left;
72
+ border-collapse: collapse;
73
+ }
74
+
75
+ .filelist>table tr>th {
76
+ white-space: nowrap;
77
+ padding: 0 10px;
78
+ }
79
+
80
+ .filelist>table>thead>tr>th {
81
+ color: #284259;
82
+ font-size: 13px;
83
+ line-height: 40px;
84
+ }
85
+
86
+ .filelist>table>tbody>tr>th {
87
+ text-decoration: none;
88
+ font-size: 12px;
89
+ color: #3c3c3c;
90
+ word-break: break-all;
91
+ font-weight: 400;
92
+ line-height: 30px;
93
+ border-top: 1px solid #e4e4e4;
94
+ }
95
+
96
+ .filelist>table>tbody>tr>th>.btn {
97
+ color: white;
98
+ background-color: #2196F3;
99
+ padding: 2px 5px;
100
+ border-radius: 5px;
101
+ }
102
+
103
+ .filelist>table>tbody>tr>th.name {
104
+ background-repeat: no-repeat;
105
+ background-position: left center;
106
+ background-size: auto 90%;
107
+ padding-left: 30px;
108
+ color: #000000;
109
+ }
110
+
111
+ .filelist>table>tbody>tr>th.name>span {
112
+ white-space: nowrap;
113
+ }
114
+
115
+ .filelist>table>tbody>tr.file>th.name {
116
+ background-image: url('${img_file}');
117
+ }
118
+
119
+ .filelist>table>tbody>tr.folder>th.name {
120
+ background-image: url('${img_folder}');
121
+ }
122
+
123
+ .website-link {
124
+ position: fixed;
125
+ bottom: 10px;
126
+ line-height: 30px;
127
+ left: 16px;
128
+ font-size: 14px;
129
+ text-decoration: underline;
130
+ font-weight: 800;
131
+ }
132
+ </style>
133
+ </head>
134
+
135
+ <body>
136
+ <a href="https://github.com/oi-contrib/OIPage" target="_blank" class="fork">
137
+ Fork me on Github
138
+ </a>
139
+ <div class="current">
140
+ 当前位置:${current}
141
+ </div>
142
+ <div class="filelist">
143
+ <table>
144
+ <thead>
145
+ <tr>
146
+ <th>
147
+ 名称
148
+ </th>
149
+ <th>
150
+ 修改日期
151
+ </th>
152
+ <th>
153
+ 类型
154
+ </th>
155
+ <th>
156
+ 大小
157
+ </th>
158
+ <th>
159
+ 操作
160
+ </th>
161
+ </tr>
162
+ </thead>
163
+ <tbody>
164
+ <tr class="folder">
165
+ <th class="name"><a href='../'>..</a></th>
166
+ <th>-</th>
167
+ <th>
168
+ 文件夹
169
+ </th>
170
+ <th>-</th>
171
+ <th>
172
+ <a href='../' class="btn">打开</a>
173
+ </th>
174
+ </tr>
175
+ ${template}
176
+ </tbody>
177
+ </table>
178
+ </div>
179
+ <a class="website-link" href="/_oipage_website_/index.html">
180
+ 打开应用市场
181
+ </a>
182
+ </body>
183
+
172
184
  </html>