crabatool 1.0.62 → 1.0.65
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/lib/config.js +3 -0
- package/package.json +3 -2
- package/tool/checkgspx.js +96 -0
- package/tool/checkjs.js +71 -16
- package/tool/start.js +2 -1
package/lib/config.js
CHANGED
|
@@ -6,6 +6,9 @@ class Config {
|
|
|
6
6
|
constructor() {
|
|
7
7
|
this.reportHost = "http://crabadoc.ca.com"; // 用于接收检测报告的服务器,可配置的。由于产品没有提供服务,目前统一放到平台的文档服务器
|
|
8
8
|
this.webhooks = "https://oapi.dingtalk.com/robot/send?access_token=ce27b1b1540881540d44c0bd05ba738d865363758892ede137dc1020bd36bd5a";
|
|
9
|
+
this.crabaHooks = "https://oapi.dingtalk.com/robot/send?access_token=ce27b1b1540881540d44c0bd05ba738d865363758892ede137dc1020bd36bd5a";
|
|
10
|
+
//this.webhooks = "https://oapi.dingtalk.com/robot/send?access_token=37279df60e03ebf25e8eb71230ddb93fe74de99951a8d635d0458e60bfcd44d8";
|
|
11
|
+
this.checkgspx = true; // 检查gspx
|
|
9
12
|
|
|
10
13
|
this.Version = pg.version;
|
|
11
14
|
this.Debug = false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "crabatool",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.65",
|
|
4
4
|
"description": "crabatool",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -26,7 +26,8 @@
|
|
|
26
26
|
"axios": "^0.27.2",
|
|
27
27
|
"iconv-jschardet": "^2.0.26",
|
|
28
28
|
"compressing": "^1.6.0",
|
|
29
|
-
"@jslint-org/jslint": "^2022.5.20"
|
|
29
|
+
"@jslint-org/jslint": "^2022.5.20",
|
|
30
|
+
"htmlparser2": "^8.0.1"
|
|
30
31
|
},
|
|
31
32
|
"repository": {
|
|
32
33
|
"type": "git",
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
var utils = require('../lib/utils.js');
|
|
2
|
+
var config = require('../lib/config.js');
|
|
3
|
+
var fs = require('fs');
|
|
4
|
+
var path = require('path');
|
|
5
|
+
var htmlparser2 = require('htmlparser2');
|
|
6
|
+
var warnTags = ['VPanel', 'HPanel', 'HiddenColumn', 'Hblock', 'Vblock']; // 'div', 'table', 'tr', 'td', 'br','HiddenField', 'CloseButton', 'CancelButton'];
|
|
7
|
+
|
|
8
|
+
module.exports.getResults = function() {
|
|
9
|
+
var data = {
|
|
10
|
+
count: 0,
|
|
11
|
+
tags: {},
|
|
12
|
+
tagList: [],
|
|
13
|
+
warnList: {},
|
|
14
|
+
errorList: []
|
|
15
|
+
};
|
|
16
|
+
if (!config.checkgspx) return data;
|
|
17
|
+
|
|
18
|
+
var gspxFiles = utils.getFiles({ source: config.webPath, exts: '.gspx' });
|
|
19
|
+
data.count = gspxFiles.length;
|
|
20
|
+
|
|
21
|
+
gspxFiles.forEach(function(filePath) {
|
|
22
|
+
readGspxToJSON(filePath, data);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
Object.keys(data.tags).forEach((tag, index) => {
|
|
26
|
+
data.tagList.push({ name: tag, count: data.tags[tag] });
|
|
27
|
+
});
|
|
28
|
+
data.tagList.sort(function(item0, item1) {
|
|
29
|
+
return item0.count > item1.count ? -1 : 1;
|
|
30
|
+
});
|
|
31
|
+
return data;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function readGspxToJSON(fileName, data) {
|
|
35
|
+
var rootNode;
|
|
36
|
+
var stack = [];
|
|
37
|
+
var node;
|
|
38
|
+
var byte = fs.readFileSync(fileName);
|
|
39
|
+
var gspxXML = utils.toUtf8(byte);
|
|
40
|
+
|
|
41
|
+
fileName = fileName.replace(config.webPath, ''); // 简化文件路径
|
|
42
|
+
function HtmlParser2ToXml(xml) {
|
|
43
|
+
var parser = new htmlparser2.Parser({
|
|
44
|
+
onopentag: function(name, attrs) {
|
|
45
|
+
node = {};
|
|
46
|
+
node.Name = name;
|
|
47
|
+
node.Attributes = attrs;
|
|
48
|
+
stack.push(node);
|
|
49
|
+
|
|
50
|
+
// 标签使用统计
|
|
51
|
+
if (data.tags[name] === undefined) {
|
|
52
|
+
data.tags[name] = 1;
|
|
53
|
+
} else {
|
|
54
|
+
data.tags[name]++;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// 建议优化页面汇总
|
|
58
|
+
if (warnTags.includes(name)) {
|
|
59
|
+
if (!data.warnList[fileName]) data.warnList[fileName] = [];
|
|
60
|
+
data.warnList[fileName].push(name);
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
ontext: function(text) {
|
|
64
|
+
if (text != null && text.trim() != '') {
|
|
65
|
+
node.Value = text;
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
onclosetag: function(tagname) {
|
|
69
|
+
var pNode = stack.pop();
|
|
70
|
+
if (stack.length == 0) {
|
|
71
|
+
rootNode = pNode;
|
|
72
|
+
} else {
|
|
73
|
+
var parentNode = stack[stack.length - 1];
|
|
74
|
+
if (!parentNode.Childs) parentNode.Childs = [];
|
|
75
|
+
parentNode.Childs.push(pNode);
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
onerror: function(error) {
|
|
79
|
+
console.log("read " + fileName + " " + error);
|
|
80
|
+
|
|
81
|
+
// 异常文件统计
|
|
82
|
+
data.errorList.push({ fileName: fileName, tag: node.Name, error: error });
|
|
83
|
+
}
|
|
84
|
+
}, {
|
|
85
|
+
lowerCaseTags: false,
|
|
86
|
+
lowerCaseAttributeNames: false,
|
|
87
|
+
xmlMode: true
|
|
88
|
+
});
|
|
89
|
+
parser.write(gspxXML);
|
|
90
|
+
parser.end();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
HtmlParser2ToXml(gspxXML);
|
|
94
|
+
|
|
95
|
+
return rootNode;
|
|
96
|
+
}
|
package/tool/checkjs.js
CHANGED
|
@@ -5,23 +5,25 @@ var ProgressBar = require('./progressbar.js');
|
|
|
5
5
|
var jschardet = require('iconv-jschardet');
|
|
6
6
|
var path = require('path');
|
|
7
7
|
var axios = require('axios');
|
|
8
|
+
var gspx = require('./checkgspx.js');
|
|
9
|
+
|
|
10
|
+
// js超过多少kb给与提示
|
|
11
|
+
var fileSize = 300;
|
|
12
|
+
// 默认忽略大小的文件
|
|
13
|
+
var sizeBlackList = ['craba.min.js', 'crabaEx.min.js', 'crabaNgp.js', 'echarts-all.js', 'echarts.min.js', 'math.min.js'];
|
|
14
|
+
// 语法规则,不能包含这些关键词
|
|
15
|
+
var dangerousJs = ['\\slet\\s', '\\sconst\\s', '\=\>\\s?\\(?\\{', '\\sasync\\s', '\\sawait\\s', '\\.then\\(', '\\sdebugger\\s'];
|
|
16
|
+
|
|
8
17
|
|
|
9
18
|
module.exports.start = function() {
|
|
10
19
|
var jsFiles = utils.getFiles({ source: config.webPath, exts: '.js', ignores: config.ignoreCheck });
|
|
11
20
|
|
|
12
|
-
var fileSize = 300;
|
|
13
21
|
var errList = [];
|
|
14
22
|
var errRegList = [];
|
|
15
23
|
var bigList = [];
|
|
16
24
|
var notUtf8List = [];
|
|
17
25
|
var utf8List = [];
|
|
18
26
|
|
|
19
|
-
// 默认忽略大小的文件
|
|
20
|
-
var sizeBlackList = ['craba.min.js', 'crabaEx.min.js', 'crabaNgp.js', 'echarts-all.js', 'echarts.min.js', 'math.min.js'];
|
|
21
|
-
|
|
22
|
-
// 语法规则,不能包含这些关键词
|
|
23
|
-
var dangerousJs = ['\\slet\\s', '\\sconst\\s', '\=\>\\s?\\(?\\{', '\\sasync\\s', '\\sawait\\s', '\\.then\\(', '\\sdebugger\\s'];
|
|
24
|
-
|
|
25
27
|
// 开始检测
|
|
26
28
|
var pb = new ProgressBar('检查进度', jsFiles.length);
|
|
27
29
|
jsFiles.forEach(function(filePath) {
|
|
@@ -73,12 +75,17 @@ module.exports.start = function() {
|
|
|
73
75
|
});
|
|
74
76
|
pb.clear('检验完成');
|
|
75
77
|
|
|
78
|
+
// 检查gspx
|
|
79
|
+
var gspxData = gspx.getResults();
|
|
80
|
+
|
|
76
81
|
// 生成检测报告 markdown语法
|
|
77
|
-
var
|
|
78
|
-
|
|
82
|
+
var warnPages = Object.keys(gspxData.warnList).length;
|
|
83
|
+
var status = '无异常';
|
|
84
|
+
if (errList.length > 0 || notUtf8List.length > 0 || warnPages > 0 || gspxData.errorList.length > 0) {
|
|
79
85
|
status = '有异常';
|
|
80
86
|
}
|
|
81
87
|
|
|
88
|
+
|
|
82
89
|
var modName = getModName();
|
|
83
90
|
var webhookList = [];
|
|
84
91
|
var info = [];
|
|
@@ -91,10 +98,11 @@ module.exports.start = function() {
|
|
|
91
98
|
info.push(`| 生成报告时间 | ${new Date().toString()} |`);
|
|
92
99
|
info.push(`| 网站路径 | ${config.webPath} |`);
|
|
93
100
|
info.push(`| 共检查 | ${jsFiles.length}个js文件 |`);
|
|
101
|
+
info.push(`| 共检查 | ${gspxData.count}个gspx文件 |`);
|
|
94
102
|
info.push(`| 忽略目录和文件 | ${config.ignoreCheck ? config.ignoreCheck.join('、') : '无' + ' |'}`);
|
|
95
103
|
|
|
96
|
-
info.push("#
|
|
97
|
-
info.push("|
|
|
104
|
+
info.push("# 检测报表");
|
|
105
|
+
info.push("| 类型 | 数量 |");
|
|
98
106
|
info.push("| ------ | ------ |");
|
|
99
107
|
info.push(`| 语法异常文件数 | ${errList.length}个 |`);
|
|
100
108
|
//webhookList.push(`## 自定义规则`);
|
|
@@ -109,7 +117,11 @@ module.exports.start = function() {
|
|
|
109
117
|
webhookList.push(`1. 超过${fileSize}kb的文件数:${bigList.length}个`);
|
|
110
118
|
}
|
|
111
119
|
|
|
112
|
-
|
|
120
|
+
info.push(`| gspx建议优化数 | ${warnPages}个 |`);
|
|
121
|
+
info.push(`| gspx错误数 | ${gspxData.errorList.length}个 |`);
|
|
122
|
+
|
|
123
|
+
webhookList.push(`1. gspx建议优化数:${warnPages}个`);
|
|
124
|
+
webhookList.push(`1. gspx出错数:${gspxData.errorList.length}个`);
|
|
113
125
|
|
|
114
126
|
|
|
115
127
|
// 代码质量管理需要格式
|
|
@@ -120,7 +132,7 @@ module.exports.start = function() {
|
|
|
120
132
|
var detail = [];
|
|
121
133
|
if (errList.length > 0) {
|
|
122
134
|
detail.push("");
|
|
123
|
-
detail.push('# 语法异常文件清单如下');
|
|
135
|
+
detail.push('# js语法异常文件清单如下');
|
|
124
136
|
errList.forEach((s, index) => {
|
|
125
137
|
|
|
126
138
|
detail.push(`## ${index + 1}. ${s}`);
|
|
@@ -155,6 +167,33 @@ module.exports.start = function() {
|
|
|
155
167
|
});
|
|
156
168
|
}
|
|
157
169
|
|
|
170
|
+
if (gspxData.errorList.length > 0) {
|
|
171
|
+
detail.push(`# 出错误页面清单如下`);
|
|
172
|
+
gspxData.errorList.forEach((info, index) => {
|
|
173
|
+
detail.push(`## ${index + 1}. ${info.name}`);
|
|
174
|
+
detail.push(`> 错误标签: ${info.tag}`);
|
|
175
|
+
detail.push(`> 错误描述:${info.error}`);
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (warnPages > 0) {
|
|
180
|
+
detail.push(`# 建议优化gspx页面清单如下`);
|
|
181
|
+
Object.keys(gspxData.warnList).forEach((key, index) => {
|
|
182
|
+
var tags = gspxData.warnList[key];
|
|
183
|
+
|
|
184
|
+
detail.push(`## ${index + 1}. ${key}`); 4
|
|
185
|
+
detail.push(`> 此页面建议优化标签明细: ${tags.join('、')}`);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
detail.push('# 本项目标签使用情况汇总');
|
|
190
|
+
detail.push("| 标签名称 | 使用次数 |");
|
|
191
|
+
detail.push("| ----- | ------ |");
|
|
192
|
+
gspxData.tagList.forEach((item, index) => {
|
|
193
|
+
detail.push(`| ${item.name} | ${item.count} |`);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
|
|
158
197
|
// 推送报告到钉钉和文档服务器端
|
|
159
198
|
var id = modName + '_' + new Date().getTime();
|
|
160
199
|
var reportUrl = getReportUrl(id);
|
|
@@ -162,9 +201,9 @@ module.exports.start = function() {
|
|
|
162
201
|
postReport(id, reportUrl, content, sonar);
|
|
163
202
|
|
|
164
203
|
// 推送到钉钉
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
204
|
+
if (status != '无异常') { // 检查结果检查就不发到钉钉了; ps:健康也发到钉钉,鼓励开发继续保持;
|
|
205
|
+
postWebhooks(id, reportUrl, webhookList);
|
|
206
|
+
}
|
|
168
207
|
}
|
|
169
208
|
|
|
170
209
|
function getMathReuslts(content, nreg, filterFun) {
|
|
@@ -274,4 +313,20 @@ function postWebhooks(id, reportUrl, webhookList) {
|
|
|
274
313
|
console.log("推送代码检测失败");
|
|
275
314
|
console.log(error);
|
|
276
315
|
});
|
|
316
|
+
|
|
317
|
+
// 如果业务配置的推送地址不是平台群,需要统一推送到平台,汇总一下问题,方便后期统筹
|
|
318
|
+
if (config.webhooks != config.crabaHooks) {
|
|
319
|
+
axios({
|
|
320
|
+
method: 'post',
|
|
321
|
+
url: config.crabaHooks,
|
|
322
|
+
data: data,
|
|
323
|
+
headers: { 'Content-Type': 'application/json' }
|
|
324
|
+
}).then(function(response) {
|
|
325
|
+
console.log("推送代码检测状态");
|
|
326
|
+
console.log(response.data);
|
|
327
|
+
}).catch(function(error) {
|
|
328
|
+
console.log("推送代码检测失败");
|
|
329
|
+
console.log(error);
|
|
330
|
+
});
|
|
331
|
+
}
|
|
277
332
|
}
|
package/tool/start.js
CHANGED
|
@@ -24,7 +24,7 @@ class Start {
|
|
|
24
24
|
"1. 启动服务。\t\t\t\t主要包含:自动合并打包init.js和biz.js,查看本地平台的版本",
|
|
25
25
|
"2. 更新当前项目的平台,然后启动服务。\t主要包含:从<内网>拉取环境相关资源,再拷贝到webPath路径下覆盖老文件,替代手工操作,同时解决npm不稳定问题",
|
|
26
26
|
"3. 查询最新平台版本和日期。\t\t主要包含:从<内网>拉取最新平台版本,开发好及时更新补丁",
|
|
27
|
-
"4.
|
|
27
|
+
"4. 校验当前项目前端js语法和兼容性,以及gspx检查。\t主要包含:对本地js语法做一次初步预检避免上线后才发现问题;比如:编码、let、const、=>、async、await、then、缺function",
|
|
28
28
|
"5. 打包当前项目前端所有js。\t\t主要包含:前端es6语法的打包和js的统一压缩处理",
|
|
29
29
|
"6. 安装或更新IDEA环境。\t\t\t主要包含:从<内网>拉取环境相关资源,包括智能语法、新增页面模板、更多新功能",
|
|
30
30
|
"7. 安装或更新vscode环境。\t\t主要包含:从<内网>拉取环境相关资源,包括智能语法、新增页面模板、ctrl+alt+n、alt+j快捷键",
|
|
@@ -83,6 +83,7 @@ class Start {
|
|
|
83
83
|
bindConfigByArgv('-childModList', 'array');
|
|
84
84
|
bindConfigByArgv('-ignoreCompress', 'boolean');
|
|
85
85
|
bindConfigByArgv('-Debug', 'boolean');
|
|
86
|
+
bindConfigByArgv('-checkgspx', 'boolean');
|
|
86
87
|
|
|
87
88
|
if (!config.webPath) {
|
|
88
89
|
throw new Error('请检查craba.js,必须告诉工具当前项目的前端路径地址,填绝对路径哦');
|