oipage 1.3.0-alpha.1 → 1.3.0-alpha.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/CHANGELOG +64 -64
- package/bin/intercept.js +15 -7
- package/bin/run +96 -96
- package/bin/serve.js +114 -114
- package/bin/tools/resolveImport.js +88 -81
- package/nodejs/animation/index.js +1 -1
- package/nodejs/cmdlog/index.js +1 -1
- package/nodejs/disk/index.js +1 -1
- package/nodejs/logform/index.js +1 -1
- package/nodejs/reader/index.js +1 -1
- package/nodejs/throttle/index.js +1 -1
- package/package.json +1 -1
- package/web/animation/index.js +1 -1
- package/web/onReady/index.js +1 -1
- package/web/reader/index.js +1 -1
- package/web/style/index.js +1 -1
- package/web/throttle/index.js +1 -1
package/CHANGELOG
CHANGED
|
@@ -1,64 +1,64 @@
|
|
|
1
|
-
v1.0.0:
|
|
2
|
-
date:2025-02-13
|
|
3
|
-
changes:
|
|
4
|
-
- 原v0.x的功能将独立一个分支继续维护:https://github.com/oi-contrib/OIPage/blob/v0.x/CHANGELOG
|
|
5
|
-
(v0.x保持对零碎方法这种形式的支持和维护,此版本开始将作为一个框架或一个系统的工具箱以提供更高效的使用方式,这是一次彻底的非兼容改造)
|
|
6
|
-
- 初始化版本(v1.x)
|
|
7
|
-
1、API功能(浏览器)
|
|
8
|
-
* animation 动画
|
|
9
|
-
* getStyle 获取节点样式
|
|
10
|
-
* setStyle 设置节点样式
|
|
11
|
-
* onReady 加载完毕执行
|
|
12
|
-
* throttle 节流函数
|
|
13
|
-
2、API功能(Node.js)
|
|
14
|
-
* animation 动画
|
|
15
|
-
* deeplog 进度打印
|
|
16
|
-
* linglog 单行打印
|
|
17
|
-
* throttle 节流函数
|
|
18
|
-
3、命令(oipage-cli)
|
|
19
|
-
* serve 开发服务器
|
|
20
|
-
v1.1.0:
|
|
21
|
-
date:2025-02-18
|
|
22
|
-
changes:
|
|
23
|
-
- 修复bug
|
|
24
|
-
1、通过路径类型判断以修复开发服务器无法设置绝对路径问题
|
|
25
|
-
- 优化改造
|
|
26
|
-
1、使用流读取以使开发服务器支持大文件下载
|
|
27
|
-
(同时添加下载进度可查)
|
|
28
|
-
- 新增功能
|
|
29
|
-
1、API功能(Node.js)
|
|
30
|
-
* disk 磁盘相关操作
|
|
31
|
-
(包括:deleteDisk、copyDisk)
|
|
32
|
-
* logform 表单输入
|
|
33
|
-
2、命令(oipage-cli)
|
|
34
|
-
* dist 磁盘操作
|
|
35
|
-
* run 运行多命令
|
|
36
|
-
v1.2.0:
|
|
37
|
-
date:2025-02-25
|
|
38
|
-
changes:
|
|
39
|
-
- 优化改造
|
|
40
|
-
1、优化npm包目录结构等
|
|
41
|
-
- 新增功能
|
|
42
|
-
1、开发服务器
|
|
43
|
-
* 添加配置文件
|
|
44
|
-
(oipage-cli serve --config ./oipage.config.js)
|
|
45
|
-
* 新增对node_modules包引入支持
|
|
46
|
-
v1.2.1:
|
|
47
|
-
date:2025-03-06
|
|
48
|
-
changes:
|
|
49
|
-
- 修复bug
|
|
50
|
-
1、开发服务器
|
|
51
|
-
* 修复路径不存在时未正确同步修改浏览器地址问题
|
|
52
|
-
v1.3.0:
|
|
53
|
-
date:
|
|
54
|
-
changes:
|
|
55
|
-
- 修复bug
|
|
56
|
-
1、开发服务器
|
|
57
|
-
* 修复服务器根路径判断错误导致node_modules包查找错误问题
|
|
58
|
-
- 新增功能
|
|
59
|
-
1、API功能(浏览器)
|
|
60
|
-
* reader 文本分析读取器
|
|
61
|
-
2、API功能(Node.js)
|
|
62
|
-
* reader 文本分析读取器
|
|
63
|
-
3、开发服务器
|
|
64
|
-
* 新增 devServer.intercept 请求拦截
|
|
1
|
+
v1.0.0:
|
|
2
|
+
date:2025-02-13
|
|
3
|
+
changes:
|
|
4
|
+
- 原v0.x的功能将独立一个分支继续维护:https://github.com/oi-contrib/OIPage/blob/v0.x/CHANGELOG
|
|
5
|
+
(v0.x保持对零碎方法这种形式的支持和维护,此版本开始将作为一个框架或一个系统的工具箱以提供更高效的使用方式,这是一次彻底的非兼容改造)
|
|
6
|
+
- 初始化版本(v1.x)
|
|
7
|
+
1、API功能(浏览器)
|
|
8
|
+
* animation 动画
|
|
9
|
+
* getStyle 获取节点样式
|
|
10
|
+
* setStyle 设置节点样式
|
|
11
|
+
* onReady 加载完毕执行
|
|
12
|
+
* throttle 节流函数
|
|
13
|
+
2、API功能(Node.js)
|
|
14
|
+
* animation 动画
|
|
15
|
+
* deeplog 进度打印
|
|
16
|
+
* linglog 单行打印
|
|
17
|
+
* throttle 节流函数
|
|
18
|
+
3、命令(oipage-cli)
|
|
19
|
+
* serve 开发服务器
|
|
20
|
+
v1.1.0:
|
|
21
|
+
date:2025-02-18
|
|
22
|
+
changes:
|
|
23
|
+
- 修复bug
|
|
24
|
+
1、通过路径类型判断以修复开发服务器无法设置绝对路径问题
|
|
25
|
+
- 优化改造
|
|
26
|
+
1、使用流读取以使开发服务器支持大文件下载
|
|
27
|
+
(同时添加下载进度可查)
|
|
28
|
+
- 新增功能
|
|
29
|
+
1、API功能(Node.js)
|
|
30
|
+
* disk 磁盘相关操作
|
|
31
|
+
(包括:deleteDisk、copyDisk)
|
|
32
|
+
* logform 表单输入
|
|
33
|
+
2、命令(oipage-cli)
|
|
34
|
+
* dist 磁盘操作
|
|
35
|
+
* run 运行多命令
|
|
36
|
+
v1.2.0:
|
|
37
|
+
date:2025-02-25
|
|
38
|
+
changes:
|
|
39
|
+
- 优化改造
|
|
40
|
+
1、优化npm包目录结构等
|
|
41
|
+
- 新增功能
|
|
42
|
+
1、开发服务器
|
|
43
|
+
* 添加配置文件
|
|
44
|
+
(oipage-cli serve --config ./oipage.config.js)
|
|
45
|
+
* 新增对node_modules包引入支持
|
|
46
|
+
v1.2.1:
|
|
47
|
+
date:2025-03-06
|
|
48
|
+
changes:
|
|
49
|
+
- 修复bug
|
|
50
|
+
1、开发服务器
|
|
51
|
+
* 修复路径不存在时未正确同步修改浏览器地址问题
|
|
52
|
+
v1.3.0:
|
|
53
|
+
date:
|
|
54
|
+
changes:
|
|
55
|
+
- 修复bug
|
|
56
|
+
1、开发服务器
|
|
57
|
+
* 修复服务器根路径判断错误导致node_modules包查找错误问题
|
|
58
|
+
- 新增功能
|
|
59
|
+
1、API功能(浏览器)
|
|
60
|
+
* reader 文本分析读取器
|
|
61
|
+
2、API功能(Node.js)
|
|
62
|
+
* reader 文本分析读取器
|
|
63
|
+
3、开发服务器
|
|
64
|
+
* 新增 devServer.intercept 请求拦截
|
package/bin/intercept.js
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
for (let item of intercept) {
|
|
3
|
-
if (item.test.test(url)) {
|
|
4
|
-
item.handler(request, response);
|
|
5
|
-
return true;
|
|
6
|
-
}
|
|
7
|
-
}
|
|
1
|
+
exports.doIntercept = function (url, intercept, request, response) {
|
|
2
|
+
for (let item of intercept) {
|
|
3
|
+
if (item.test.test(url)) {
|
|
4
|
+
item.handler(request, response);
|
|
5
|
+
return true;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
exports.testIntercept = function (url, intercept) {
|
|
11
|
+
for (let item of intercept) {
|
|
12
|
+
if (item.test.test(url)) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
8
16
|
}
|
package/bin/run
CHANGED
|
@@ -1,97 +1,97 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
'use strict';
|
|
4
|
-
|
|
5
|
-
process.title = 'OIPage';
|
|
6
|
-
|
|
7
|
-
const { exec } = require('child_process');
|
|
8
|
-
const { join } = require("path");
|
|
9
|
-
const { existsSync, lstatSync } = require("fs");
|
|
10
|
-
const { mergeOption } = require("vislite");
|
|
11
|
-
const { formatArgv } = require("./tools/format.js");
|
|
12
|
-
|
|
13
|
-
// 开发服务器
|
|
14
|
-
if (process.argv[2] === "serve") {
|
|
15
|
-
|
|
16
|
-
let argvObj = formatArgv(process.argv, {
|
|
17
|
-
"-p": "--port",
|
|
18
|
-
"-c": "--config"
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
let config = {
|
|
22
|
-
devServer: {
|
|
23
|
-
port: 8080,
|
|
24
|
-
baseUrl: "./",
|
|
25
|
-
intercept: []
|
|
26
|
-
},
|
|
27
|
-
module: {
|
|
28
|
-
rules: []
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
// 如果设置了配置文件
|
|
33
|
-
if (argvObj["--config"]) {
|
|
34
|
-
let configPath = join(process.cwd(), argvObj["--config"][0] || "./oipage.config.js");
|
|
35
|
-
if (existsSync(configPath) && !lstatSync(configPath).isDirectory()) {
|
|
36
|
-
let configValue = require(configPath);
|
|
37
|
-
mergeOption(config, configValue);
|
|
38
|
-
} else {
|
|
39
|
-
console.log("\x1b[0m\x1b[31m" + configPath + "\x1b[0m");
|
|
40
|
-
throw new Error("OIPage: The configuration file does not exist or is not a file.");
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if ((argvObj["--port"] || [])[0]) config.devServer.port = (argvObj["--port"] || [])[0];
|
|
45
|
-
if ((argvObj["--baseUrl"] || [])[0]) config.devServer.baseUrl = (argvObj["--baseUrl"] || [])[0];
|
|
46
|
-
|
|
47
|
-
require("./serve.js")(config);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// 磁盘操作
|
|
51
|
-
else if (process.argv[2] === "disk") {
|
|
52
|
-
|
|
53
|
-
let argvObj = formatArgv(process.argv, {
|
|
54
|
-
"-f": "--force",
|
|
55
|
-
"-d": "--delete",
|
|
56
|
-
"-m": "--move",
|
|
57
|
-
"-c": "--copy"
|
|
58
|
-
}, true);
|
|
59
|
-
|
|
60
|
-
require("./disk.js")(argvObj);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// 运行多命令
|
|
64
|
-
else if (process.argv[2] === "run") {
|
|
65
|
-
|
|
66
|
-
let argvObj = formatArgv(process.argv, {});
|
|
67
|
-
|
|
68
|
-
for (let index = 0; index < argvObj.args.length; index++) {
|
|
69
|
-
const child = exec(argvObj.args[index]);
|
|
70
|
-
|
|
71
|
-
// 监听子线程的stdout
|
|
72
|
-
child.stdout.on('data', (data) => {
|
|
73
|
-
console.log(`[${index + 1}] log:${data}`);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
// 监听子线程的stderr
|
|
77
|
-
child.stderr.on('data', (data) => {
|
|
78
|
-
console.error(`[${index + 1}] error:${data}`);
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
// 子线程结束处理
|
|
82
|
-
child.on('close', (code) => {
|
|
83
|
-
console.log(`[${index + 1}] 子线程结束,退出码 ${code}`);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
// 子线程出错处理
|
|
87
|
-
child.on('error', (error) => {
|
|
88
|
-
console.error(`[${index + 1}] 子线程错误: ${error.message}`);
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// 默认,帮助
|
|
95
|
-
else {
|
|
96
|
-
require("./help.js")();
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
process.title = 'OIPage';
|
|
6
|
+
|
|
7
|
+
const { exec } = require('child_process');
|
|
8
|
+
const { join } = require("path");
|
|
9
|
+
const { existsSync, lstatSync } = require("fs");
|
|
10
|
+
const { mergeOption } = require("vislite");
|
|
11
|
+
const { formatArgv } = require("./tools/format.js");
|
|
12
|
+
|
|
13
|
+
// 开发服务器
|
|
14
|
+
if (process.argv[2] === "serve") {
|
|
15
|
+
|
|
16
|
+
let argvObj = formatArgv(process.argv, {
|
|
17
|
+
"-p": "--port",
|
|
18
|
+
"-c": "--config"
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
let config = {
|
|
22
|
+
devServer: {
|
|
23
|
+
port: 8080,
|
|
24
|
+
baseUrl: "./",
|
|
25
|
+
intercept: []
|
|
26
|
+
},
|
|
27
|
+
module: {
|
|
28
|
+
rules: []
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// 如果设置了配置文件
|
|
33
|
+
if (argvObj["--config"]) {
|
|
34
|
+
let configPath = join(process.cwd(), argvObj["--config"][0] || "./oipage.config.js");
|
|
35
|
+
if (existsSync(configPath) && !lstatSync(configPath).isDirectory()) {
|
|
36
|
+
let configValue = require(configPath);
|
|
37
|
+
mergeOption(config, configValue);
|
|
38
|
+
} else {
|
|
39
|
+
console.log("\x1b[0m\x1b[31m" + configPath + "\x1b[0m");
|
|
40
|
+
throw new Error("OIPage: The configuration file does not exist or is not a file.");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if ((argvObj["--port"] || [])[0]) config.devServer.port = (argvObj["--port"] || [])[0];
|
|
45
|
+
if ((argvObj["--baseUrl"] || [])[0]) config.devServer.baseUrl = (argvObj["--baseUrl"] || [])[0];
|
|
46
|
+
|
|
47
|
+
require("./serve.js")(config);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// 磁盘操作
|
|
51
|
+
else if (process.argv[2] === "disk") {
|
|
52
|
+
|
|
53
|
+
let argvObj = formatArgv(process.argv, {
|
|
54
|
+
"-f": "--force",
|
|
55
|
+
"-d": "--delete",
|
|
56
|
+
"-m": "--move",
|
|
57
|
+
"-c": "--copy"
|
|
58
|
+
}, true);
|
|
59
|
+
|
|
60
|
+
require("./disk.js")(argvObj);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 运行多命令
|
|
64
|
+
else if (process.argv[2] === "run") {
|
|
65
|
+
|
|
66
|
+
let argvObj = formatArgv(process.argv, {});
|
|
67
|
+
|
|
68
|
+
for (let index = 0; index < argvObj.args.length; index++) {
|
|
69
|
+
const child = exec(argvObj.args[index]);
|
|
70
|
+
|
|
71
|
+
// 监听子线程的stdout
|
|
72
|
+
child.stdout.on('data', (data) => {
|
|
73
|
+
console.log(`[${index + 1}] log:${data}`);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// 监听子线程的stderr
|
|
77
|
+
child.stderr.on('data', (data) => {
|
|
78
|
+
console.error(`[${index + 1}] error:${data}`);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// 子线程结束处理
|
|
82
|
+
child.on('close', (code) => {
|
|
83
|
+
console.log(`[${index + 1}] 子线程结束,退出码 ${code}`);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// 子线程出错处理
|
|
87
|
+
child.on('error', (error) => {
|
|
88
|
+
console.error(`[${index + 1}] 子线程错误: ${error.message}`);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// 默认,帮助
|
|
95
|
+
else {
|
|
96
|
+
require("./help.js")();
|
|
97
97
|
}
|
package/bin/serve.js
CHANGED
|
@@ -1,115 +1,115 @@
|
|
|
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 { formatRawHeaders } = require("./tools/format.js");
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
// 开发服务器
|
|
13
|
-
module.exports = function (config) {
|
|
14
|
-
let startTime = new Date().valueOf();
|
|
15
|
-
|
|
16
|
-
const port = config.devServer.port; // 端口号
|
|
17
|
-
const basePath = (/^\./.test(config.devServer.baseUrl)) ? join(process.cwd(), config.devServer.baseUrl) : config.devServer.baseUrl; // 服务器根路径
|
|
18
|
-
|
|
19
|
-
let Server = createServer(function (request, response) {
|
|
20
|
-
let headers = formatRawHeaders(request.rawHeaders);
|
|
21
|
-
let url = decodeURIComponent(request.url);
|
|
22
|
-
|
|
23
|
-
let urlArray = url.split("?");
|
|
24
|
-
url = urlArray[0];
|
|
25
|
-
|
|
26
|
-
// 请求的文件路径
|
|
27
|
-
let filePath = join(basePath, url == "/" ? "index.html" : url.replace(/^\//, ""));
|
|
28
|
-
|
|
29
|
-
// 请求拦截
|
|
30
|
-
if (
|
|
31
|
-
console.log("<i> \x1b[1m\x1b[32m[OIPage-dev-server] intercept: " + url + '\x1b[0m ' + new Date().toLocaleString());
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// 如果存在且是文件
|
|
35
|
-
else if (existsSync(filePath) && !lstatSync(filePath).isDirectory()) {
|
|
36
|
-
|
|
37
|
-
let dotName = /\./.test(filePath) ? filePath.match(/\.([^.]+)$/)[1] : "";
|
|
38
|
-
let fileType = mineTypes[dotName]; // 文件类型
|
|
39
|
-
let fileInfo = statSync(filePath);
|
|
40
|
-
|
|
41
|
-
let responseHeader = {
|
|
42
|
-
'Content-type': (fileType || "text/plain") + ";charset=utf-8",
|
|
43
|
-
'Access-Control-Allow-Origin': '*',
|
|
44
|
-
'Server': 'Powered by OIPage-dev-server@' + packageValue.version
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
let sendType = "";
|
|
48
|
-
let entry = headers.Accept !== "*/*";
|
|
49
|
-
|
|
50
|
-
// 如果文件小于10M,认为不大,直接读取
|
|
51
|
-
if (fileInfo.size < 10 * 1024 * 1024) {
|
|
52
|
-
let { source, resolveImport } = resolveImportFactory(basePath, filePath, entry, urlArray[1] === "download")
|
|
53
|
-
|
|
54
|
-
// 只处理非下载文件
|
|
55
|
-
// 过大的也不进行处理
|
|
56
|
-
if (urlArray[1] !== "download") {
|
|
57
|
-
for (let i = 0; i < config.module.rules.length; i++) {
|
|
58
|
-
if (config.module.rules[i].test.test(filePath)) {
|
|
59
|
-
source = config.module.rules[i].use.call({
|
|
60
|
-
root: basePath, // 服务器根路径
|
|
61
|
-
path: filePath.replace(basePath, ""), // 文件相对路径
|
|
62
|
-
entry, // 是否是浏览器地址栏直接访问
|
|
63
|
-
setFileType(_fileType) { // 设置文件类型
|
|
64
|
-
fileType = _fileType;
|
|
65
|
-
responseHeader['Content-type'] = _fileType + ";charset=utf-8";
|
|
66
|
-
}
|
|
67
|
-
}, source);
|
|
68
|
-
break;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
sendType = "Read";
|
|
74
|
-
response.writeHead('200', responseHeader);
|
|
75
|
-
response.write(resolveImport(source, fileType !== "application/javascript"));
|
|
76
|
-
response.end();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// 对于大文件,使用流读取
|
|
80
|
-
else {
|
|
81
|
-
sendType = "Stream";
|
|
82
|
-
responseHeader["Content-Length"] = fileInfo.size;
|
|
83
|
-
response.writeHead('200', responseHeader);
|
|
84
|
-
createReadStream(filePath).pipe(response);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
console.log("<i> \x1b[1m\x1b[32m[OIPage-dev-server] " + sendType + " File: " + url + '\x1b[0m ' + new Date().toLocaleString());
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// 否则就是404
|
|
91
|
-
else {
|
|
92
|
-
response.writeHead(404, {
|
|
93
|
-
'Content-type': "text/html;charset=utf-8",
|
|
94
|
-
'Access-Control-Allow-Origin': '*',
|
|
95
|
-
'Server': 'Powered by OIPage-dev-server@' + packageValue.version
|
|
96
|
-
});
|
|
97
|
-
response.write(resolve404(filePath, url));
|
|
98
|
-
response.end();
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
Server.listen(port);
|
|
104
|
-
|
|
105
|
-
// 获取网络信息
|
|
106
|
-
let networkValue = network();
|
|
107
|
-
|
|
108
|
-
// 打印成功提示
|
|
109
|
-
console.log('<i> \x1b[1m\x1b[32m[OIPage-dev-server] Project is running at:\x1b[0m');
|
|
110
|
-
console.log('<i> \x1b[1m\x1b[32m[OIPage-dev-server] Loopback: \x1b[36mhttp://localhost:' + port + '/\x1b[0m');
|
|
111
|
-
for (let ipv4Item of networkValue.IPv4) console.log('<i> \x1b[1m\x1b[32m[OIPage-dev-server] On Your Network (IPv4):\x1b[36m http://' + ipv4Item.address + ':' + port + '/\x1b[0m');
|
|
112
|
-
for (let ipv6Item of networkValue.IPv6) console.log('<i> \x1b[1m\x1b[32m[OIPage-dev-server] On Your Network (IPv6): \x1b[36mhttp://[' + ipv6Item.address + ']:' + port + '/\x1b[0m');
|
|
113
|
-
console.log('<i> \x1b[1m\x1b[32m[OIPage-dev-server] Content not from OIPage is served from \x1b[36m"' + basePath + '" \x1b[0mdirectory');
|
|
114
|
-
console.log('\nOIPage ' + packageValue.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 { formatRawHeaders } = require("./tools/format.js");
|
|
10
|
+
const { doIntercept } = require("./intercept.js");
|
|
11
|
+
|
|
12
|
+
// 开发服务器
|
|
13
|
+
module.exports = function (config) {
|
|
14
|
+
let startTime = new Date().valueOf();
|
|
15
|
+
|
|
16
|
+
const port = config.devServer.port; // 端口号
|
|
17
|
+
const basePath = (/^\./.test(config.devServer.baseUrl)) ? join(process.cwd(), config.devServer.baseUrl) : config.devServer.baseUrl; // 服务器根路径
|
|
18
|
+
|
|
19
|
+
let Server = createServer(function (request, response) {
|
|
20
|
+
let headers = formatRawHeaders(request.rawHeaders);
|
|
21
|
+
let url = decodeURIComponent(request.url);
|
|
22
|
+
|
|
23
|
+
let urlArray = url.split("?");
|
|
24
|
+
url = urlArray[0];
|
|
25
|
+
|
|
26
|
+
// 请求的文件路径
|
|
27
|
+
let filePath = join(basePath, url == "/" ? "index.html" : url.replace(/^\//, ""));
|
|
28
|
+
|
|
29
|
+
// 请求拦截
|
|
30
|
+
if (doIntercept(url.replace(/^\/@modules\//, ""), config.devServer.intercept, request, response)) {
|
|
31
|
+
console.log("<i> \x1b[1m\x1b[32m[OIPage-dev-server] intercept: " + url + '\x1b[0m ' + new Date().toLocaleString());
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// 如果存在且是文件
|
|
35
|
+
else if (existsSync(filePath) && !lstatSync(filePath).isDirectory()) {
|
|
36
|
+
|
|
37
|
+
let dotName = /\./.test(filePath) ? filePath.match(/\.([^.]+)$/)[1] : "";
|
|
38
|
+
let fileType = mineTypes[dotName]; // 文件类型
|
|
39
|
+
let fileInfo = statSync(filePath);
|
|
40
|
+
|
|
41
|
+
let responseHeader = {
|
|
42
|
+
'Content-type': (fileType || "text/plain") + ";charset=utf-8",
|
|
43
|
+
'Access-Control-Allow-Origin': '*',
|
|
44
|
+
'Server': 'Powered by OIPage-dev-server@' + packageValue.version
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
let sendType = "";
|
|
48
|
+
let entry = headers.Accept !== "*/*";
|
|
49
|
+
|
|
50
|
+
// 如果文件小于10M,认为不大,直接读取
|
|
51
|
+
if (fileInfo.size < 10 * 1024 * 1024) {
|
|
52
|
+
let { source, resolveImport } = resolveImportFactory(basePath, filePath, entry, config.devServer.intercept, urlArray[1] === "download")
|
|
53
|
+
|
|
54
|
+
// 只处理非下载文件
|
|
55
|
+
// 过大的也不进行处理
|
|
56
|
+
if (urlArray[1] !== "download") {
|
|
57
|
+
for (let i = 0; i < config.module.rules.length; i++) {
|
|
58
|
+
if (config.module.rules[i].test.test(filePath)) {
|
|
59
|
+
source = config.module.rules[i].use.call({
|
|
60
|
+
root: basePath, // 服务器根路径
|
|
61
|
+
path: filePath.replace(basePath, ""), // 文件相对路径
|
|
62
|
+
entry, // 是否是浏览器地址栏直接访问
|
|
63
|
+
setFileType(_fileType) { // 设置文件类型
|
|
64
|
+
fileType = _fileType;
|
|
65
|
+
responseHeader['Content-type'] = _fileType + ";charset=utf-8";
|
|
66
|
+
}
|
|
67
|
+
}, source);
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
sendType = "Read";
|
|
74
|
+
response.writeHead('200', responseHeader);
|
|
75
|
+
response.write(resolveImport(source, fileType !== "application/javascript"));
|
|
76
|
+
response.end();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// 对于大文件,使用流读取
|
|
80
|
+
else {
|
|
81
|
+
sendType = "Stream";
|
|
82
|
+
responseHeader["Content-Length"] = fileInfo.size;
|
|
83
|
+
response.writeHead('200', responseHeader);
|
|
84
|
+
createReadStream(filePath).pipe(response);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.log("<i> \x1b[1m\x1b[32m[OIPage-dev-server] " + sendType + " File: " + url + '\x1b[0m ' + new Date().toLocaleString());
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// 否则就是404
|
|
91
|
+
else {
|
|
92
|
+
response.writeHead(404, {
|
|
93
|
+
'Content-type': "text/html;charset=utf-8",
|
|
94
|
+
'Access-Control-Allow-Origin': '*',
|
|
95
|
+
'Server': 'Powered by OIPage-dev-server@' + packageValue.version
|
|
96
|
+
});
|
|
97
|
+
response.write(resolve404(filePath, url));
|
|
98
|
+
response.end();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
Server.listen(port);
|
|
104
|
+
|
|
105
|
+
// 获取网络信息
|
|
106
|
+
let networkValue = network();
|
|
107
|
+
|
|
108
|
+
// 打印成功提示
|
|
109
|
+
console.log('<i> \x1b[1m\x1b[32m[OIPage-dev-server] Project is running at:\x1b[0m');
|
|
110
|
+
console.log('<i> \x1b[1m\x1b[32m[OIPage-dev-server] Loopback: \x1b[36mhttp://localhost:' + port + '/\x1b[0m');
|
|
111
|
+
for (let ipv4Item of networkValue.IPv4) console.log('<i> \x1b[1m\x1b[32m[OIPage-dev-server] On Your Network (IPv4):\x1b[36m http://' + ipv4Item.address + ':' + port + '/\x1b[0m');
|
|
112
|
+
for (let ipv6Item of networkValue.IPv6) console.log('<i> \x1b[1m\x1b[32m[OIPage-dev-server] On Your Network (IPv6): \x1b[36mhttp://[' + ipv6Item.address + ']:' + port + '/\x1b[0m');
|
|
113
|
+
console.log('<i> \x1b[1m\x1b[32m[OIPage-dev-server] Content not from OIPage is served from \x1b[36m"' + basePath + '" \x1b[0mdirectory');
|
|
114
|
+
console.log('\nOIPage ' + packageValue.version + ' compiled \x1b[1m\x1b[32msuccessfully\x1b[0m in ' + (new Date().valueOf() - startTime) + ' ms\n')
|
|
115
115
|
};
|
|
@@ -1,82 +1,89 @@
|
|
|
1
|
-
const { readFileSync, existsSync, lstatSync } = require("fs");
|
|
2
|
-
const { join } = require("path");
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
let
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
//
|
|
28
|
-
if (
|
|
29
|
-
let
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
1
|
+
const { readFileSync, existsSync, lstatSync } = require("fs");
|
|
2
|
+
const { join } = require("path");
|
|
3
|
+
const { testIntercept } = require("../intercept.js");
|
|
4
|
+
|
|
5
|
+
module.exports = function (basePath, filePath, entry, intercept, isDownload) {
|
|
6
|
+
basePath = join(basePath, "./");
|
|
7
|
+
|
|
8
|
+
let source = readFileSync(filePath);
|
|
9
|
+
let resolveImport = content => content;
|
|
10
|
+
|
|
11
|
+
let __resolveImport = function (content) {
|
|
12
|
+
return content.replace(/import [^'"]* from (['"])([^'"]*)['"]/sg, function (_importCode, _, _importUrl) {
|
|
13
|
+
if (/^[./]/.test(_importUrl)) {
|
|
14
|
+
return _importCode;
|
|
15
|
+
} else {
|
|
16
|
+
return _importCode.replace(_importUrl, _importUrl.replace(/([^/])+/s, function (npmName) {
|
|
17
|
+
|
|
18
|
+
if (testIntercept(npmName, intercept)) {
|
|
19
|
+
return "/@modules/" + npmName;
|
|
20
|
+
} else {
|
|
21
|
+
|
|
22
|
+
let node_modulesRootPath = join(filePath, "../");
|
|
23
|
+
let prePath = "";
|
|
24
|
+
while (true) {
|
|
25
|
+
let npmBundlePath = join(node_modulesRootPath, "./node_modules/", npmName);
|
|
26
|
+
|
|
27
|
+
// 如果存在
|
|
28
|
+
if (existsSync(npmBundlePath) && lstatSync(npmBundlePath).isDirectory()) {
|
|
29
|
+
let npmNameValue = npmName;
|
|
30
|
+
|
|
31
|
+
// 对于类似 import VISLite from "vislite"
|
|
32
|
+
// 需要把包名解析成具体的文件
|
|
33
|
+
if (!/\//.test(_importUrl)) {
|
|
34
|
+
let bundlePackage = require(join(npmBundlePath, "./package.json"));
|
|
35
|
+
npmNameValue = npmName + "/" + bundlePackage.main;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return (prePath ? prePath : "./") + "node_modules/" + npmNameValue;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (node_modulesRootPath === basePath) {
|
|
42
|
+
|
|
43
|
+
// 如果命令行根目录是一个项目
|
|
44
|
+
let packagePath = join(basePath, "./package.json");
|
|
45
|
+
if (existsSync(packagePath) && !lstatSync(packagePath).isDirectory()) {
|
|
46
|
+
let bundlePackage = require(packagePath);
|
|
47
|
+
if (!/\//.test(_importUrl)) {
|
|
48
|
+
return "/" + bundlePackage.main;
|
|
49
|
+
} else {
|
|
50
|
+
return "/"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return npmName;
|
|
55
|
+
} else {
|
|
56
|
+
node_modulesRootPath = join(node_modulesRootPath, "../");
|
|
57
|
+
prePath = "../" + prePath;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
}
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// 如果是下载
|
|
68
|
+
if (isDownload) {
|
|
69
|
+
// todo
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// 如果不是直接访问的
|
|
73
|
+
else if (!entry) {
|
|
74
|
+
source += "";
|
|
75
|
+
resolveImport = (content, notResolve) => notResolve ? content : __resolveImport(content);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// 如果是.html或.htm结尾
|
|
79
|
+
else if (/\.html{0,1}$/.test(filePath)) {
|
|
80
|
+
source = (source + "").replace(/<script type="module">(.*)<\/script>/sg, function (_, _matchCode) {
|
|
81
|
+
return `<script type="module">${__resolveImport(_matchCode)}</script>`;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
source,
|
|
87
|
+
resolveImport
|
|
88
|
+
};
|
|
82
89
|
};
|
package/nodejs/cmdlog/index.js
CHANGED
package/nodejs/disk/index.js
CHANGED
package/nodejs/logform/index.js
CHANGED
package/nodejs/reader/index.js
CHANGED
package/nodejs/throttle/index.js
CHANGED
package/package.json
CHANGED
package/web/animation/index.js
CHANGED
package/web/onReady/index.js
CHANGED
package/web/reader/index.js
CHANGED
package/web/style/index.js
CHANGED
package/web/throttle/index.js
CHANGED