auto-cr-cmd 2.0.99 → 2.0.101

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/README.md CHANGED
@@ -52,17 +52,14 @@ Common flags:
52
52
  Sample output:
53
53
 
54
54
  ```text
55
- WARN [12:56:18] ⚠️ [Base Rules]: no-deep-relative-imports
56
-
57
- File: /Volumes/Wei/Codes/github/auto-cr/examples/src/app/features/admin/pages/dashboard.ts:2
58
- Description: Import path "../../../../shared/deep/utils" must not exceed max depth 2
59
- Code: ../../../../shared/deep/utils
60
- Suggestion: Use a path alias (for example: @shared/deep/utils). | Create an index file at a higher level to re-export the module and shorten the import.
61
-
62
- WARN [12:56:18] ⚠️ [untagged]: no-index-import
63
-
64
- File: /Volumes/Wei/Codes/github/auto-cr/examples/src/app/features/admin/pages/dashboard.ts:3
65
- Description: Import ../../consts/index is not allowed. Import the concrete file instead.
55
+ [auto-cr] [warning] /Volumes/Wei/Codes/github/auto-cr/examples/src/app/features/admin/pages/dashboard.ts:2 Import path "../../../../shared/deep/utils" must not exceed max depth 2
56
+ rule: no-deep-relative-imports (Base)
57
+ code: ../../../../shared/deep/utils
58
+ suggestion:
59
+ - Use a path alias (for example: @shared/deep/utils).
60
+ - Create an index file at a higher level to re-export the module and shorten the import.
61
+ [auto-cr] [warning] /Volumes/Wei/Codes/github/auto-cr/examples/src/app/features/admin/pages/dashboard.ts:3 Import ../../consts/index is not allowed. Import the concrete file instead.
62
+ rule: no-index-import (untagged)
66
63
 
67
64
  ✔ Code scan complete, scanned 3 files: 0 with errors, 1 with warnings, 0 with optimizing hints!
68
65
  ```
package/README.zh-CN.md CHANGED
@@ -52,17 +52,14 @@ npx auto-cr-cmd --language zh [需要扫描的代码目录]
52
52
  示例输出:
53
53
 
54
54
  ```text
55
- WARN [12:52:48] ⚠️ [基础规则]:no-deep-relative-imports
56
-
57
- 文件位置: .../dashboard.ts:2
58
- 错误描述: 导入路径 "../../../../shared/deep/utils",不能超过最大层级2
59
- 错误代码: ../../../../shared/deep/utils
60
- 优化建议: 使用别名路径(如 @shared/deep/utils); 或在上层聚合导出,避免过深相对路径。
61
-
62
- WARN [12:52:48] ⚠️ [未定义]:no-index-import
63
-
64
- 文件位置: .../dashboard.ts:3
65
- 错误描述: 禁止直接导入 ../../consts/index,请改用具体文件
55
+ [auto-cr] [warning] .../dashboard.ts:2 导入路径 "../../../../shared/deep/utils",不能超过最大层级2
56
+ rule: no-deep-relative-imports (基础规则)
57
+ code: ../../../../shared/deep/utils
58
+ suggestion:
59
+ - 使用别名路径(如 @shared/deep/utils)。
60
+ - 或在上层聚合导出,避免过深相对路径。
61
+ [auto-cr] [warning] .../dashboard.ts:3 禁止直接导入 ../../consts/index,请改用具体文件
62
+ rule: no-index-import (未定义)
66
63
 
67
64
  ✔ 代码扫描完成,本次共扫描3个文件,其中0个文件存在错误,1个文件存在警告,0个文件存在优化建议!
68
65
  ```
package/dist/index.js CHANGED
@@ -78,10 +78,16 @@ var loader_1 = require("./rules/loader");
78
78
  var autocrrc_1 = require("./config/autocrrc");
79
79
  var ignore_1 = require("./config/ignore");
80
80
  consola_1.consola.options.formatOptions = __assign(__assign({}, consola_1.consola.options.formatOptions), { date: false });
81
+ // 文本输出统一写入 stderr,避免多线程时 stdout/stderr 混排导致顺序错乱。
82
+ var textLogger = consola_1.consola.create({
83
+ stdout: process.stderr,
84
+ stderr: process.stderr,
85
+ });
86
+ textLogger.options.formatOptions = __assign(__assign({}, textLogger.options.formatOptions), { date: false });
81
87
  var consolaLoggers = {
82
- info: consola_1.consola.info.bind(consola_1.consola),
83
- warn: consola_1.consola.warn.bind(consola_1.consola),
84
- error: consola_1.consola.error.bind(consola_1.consola),
88
+ info: textLogger.info.bind(textLogger),
89
+ warn: textLogger.warn.bind(textLogger),
90
+ error: textLogger.error.bind(textLogger),
85
91
  };
86
92
  // 仅扫描 JS/TS 源码扩展名,避免把配置文件/JSON/图片等送进 SWC 解析导致报错。
87
93
  var SCANNABLE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx'];
@@ -642,12 +648,12 @@ catch (error) {
642
648
  process.exit(exitCode);
643
649
  }
644
650
  if (result.scannedFiles > 0) {
645
- consola_1.consola.log(' ');
651
+ textLogger.log(' ');
646
652
  language = (0, i18n_1.getLanguage)();
647
653
  resultMessage = language.startsWith('zh')
648
654
  ? " ".concat(t.scanComplete(), "\uFF0C\u672C\u6B21\u5171\u626B\u63CF").concat(result.scannedFiles, "\u4E2A\u6587\u4EF6\uFF0C\u5176\u4E2D").concat(result.filesWithErrors, "\u4E2A\u6587\u4EF6\u5B58\u5728\u9519\u8BEF\uFF0C").concat(result.filesWithWarnings, "\u4E2A\u6587\u4EF6\u5B58\u5728\u8B66\u544A\uFF0C").concat(result.filesWithOptimizing, "\u4E2A\u6587\u4EF6\u5B58\u5728\u4F18\u5316\u5EFA\u8BAE\uFF01")
649
655
  : " ".concat(t.scanComplete(), ", scanned ").concat(result.scannedFiles, " files: ").concat(result.filesWithErrors, " with errors, ").concat(result.filesWithWarnings, " with warnings, ").concat(result.filesWithOptimizing, " with optimizing hints!");
650
- consola_1.consola.success(resultMessage);
656
+ textLogger.success(resultMessage);
651
657
  exitCode = result.filesWithErrors > 0 ? 1 : 0;
652
658
  process.exit(exitCode);
653
659
  }
@@ -19,24 +19,26 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
19
19
  }
20
20
  return to.concat(ar || Array.prototype.slice.call(from));
21
21
  };
22
- var __importDefault = (this && this.__importDefault) || function (mod) {
23
- return (mod && mod.__esModule) ? mod : { "default": mod };
24
- };
25
- var _a;
22
+ var _a, _b;
26
23
  Object.defineProperty(exports, "__esModule", { value: true });
27
24
  exports.createReporter = createReporter;
28
25
  exports.renderViolations = renderViolations;
29
26
  var auto_cr_rules_1 = require("auto-cr-rules");
30
- var consola_1 = __importDefault(require("consola"));
31
27
  var i18n_1 = require("../i18n");
32
28
  var UNTAGGED_TAG = 'untagged';
33
29
  var DEFAULT_FORMAT = 'text';
34
- // 不同严重级别映射到不同日志级别。
35
- var severityLoggers = (_a = {},
36
- _a[auto_cr_rules_1.RuleSeverity.Error] = consola_1.default.error,
37
- _a[auto_cr_rules_1.RuleSeverity.Warning] = consola_1.default.warn,
38
- _a[auto_cr_rules_1.RuleSeverity.Optimizing] = consola_1.default.info,
30
+ // 文本输出统一写入 stderr,避免 stdout/stderr 混排导致顺序错乱。
31
+ var SEVERITY_LABELS = (_a = {},
32
+ _a[auto_cr_rules_1.RuleSeverity.Error] = 'error',
33
+ _a[auto_cr_rules_1.RuleSeverity.Warning] = 'warning',
34
+ _a[auto_cr_rules_1.RuleSeverity.Optimizing] = 'optimizing',
39
35
  _a);
36
+ var SEVERITY_COLORS = (_b = {},
37
+ _b[auto_cr_rules_1.RuleSeverity.Error] = '\x1b[31m',
38
+ _b[auto_cr_rules_1.RuleSeverity.Warning] = '\x1b[33m',
39
+ _b[auto_cr_rules_1.RuleSeverity.Optimizing] = '\x1b[90m',
40
+ _b);
41
+ var RESET_COLOR = '\x1b[0m';
40
42
  function createReporter(filePath, source, options) {
41
43
  var _a;
42
44
  if (options === void 0) { options = {}; }
@@ -186,52 +188,65 @@ function renderViolations(filePath, violations, options) {
186
188
  if (format !== 'text' || violations.length === 0) {
187
189
  return;
188
190
  }
191
+ (_b = options.onBeforeReport) === null || _b === void 0 ? void 0 : _b.call(options);
192
+ renderCompactViolations(filePath, violations);
193
+ (_c = options.onAfterReport) === null || _c === void 0 ? void 0 : _c.call(options);
194
+ }
195
+ function renderCompactViolations(filePath, violations) {
189
196
  var t = (0, i18n_1.getTranslator)();
190
197
  var language = (0, i18n_1.getLanguage)();
191
- var locale = language === 'zh' ? 'zh-CN' : 'en-US';
192
- var formatter = new Intl.DateTimeFormat(locale, {
193
- hour: '2-digit',
194
- minute: '2-digit',
195
- second: '2-digit',
196
- hour12: false,
197
- });
198
- var indent = ' ';
199
- var colon = language === 'zh' ? ':' : ':';
200
- var headerGap = language === 'zh' ? '' : ' ';
201
- var writeLine = function (stream, line) {
202
- stream.write("".concat(line, "\n"));
203
- };
204
- (_b = options.onBeforeReport) === null || _b === void 0 ? void 0 : _b.call(options);
198
+ var stream = process.stderr;
199
+ var useColor = Boolean(stream.isTTY) && !process.env.NO_COLOR;
200
+ var prefix = '[auto-cr] ';
201
+ var indent = ' ';
202
+ var bulletIndent = ' ';
205
203
  violations.forEach(function (violation) {
206
- var timestamp = formatter.format(new Date());
207
- var tagLabel = t.ruleTagLabel({ tag: violation.tag });
208
- var severityIcon = t.reporterSeverityIcon({ severity: violation.severity });
209
- var logger = getLoggerForSeverity(violation.severity);
210
- var header = "[".concat(timestamp, "] ").concat(severityIcon, " [").concat(tagLabel, "]").concat(colon).concat(headerGap).concat(violation.ruleName);
211
- logger(header);
212
- // header 与详情走同一输出流,避免 stdout/stderr 混排导致顺序错乱。
213
- var detailStream = violation.severity === auto_cr_rules_1.RuleSeverity.Error || violation.severity === auto_cr_rules_1.RuleSeverity.Warning
214
- ? process.stderr
215
- : process.stdout;
216
- var location = typeof violation.line === 'number' ? "".concat(filePath, ":").concat(violation.line) : filePath;
217
- writeLine(detailStream, "".concat(indent).concat(t.reporterFileLabel(), ": ").concat(location));
218
- writeLine(detailStream, "".concat(indent).concat(t.reporterDescriptionLabel(), ": ").concat(violation.message));
219
- if (violation.code) {
220
- writeLine(detailStream, "".concat(indent).concat(t.reporterCodeLabel(), ": ").concat(violation.code));
204
+ var _a, _b;
205
+ var severityLabel = (_a = SEVERITY_LABELS[violation.severity]) !== null && _a !== void 0 ? _a : 'error';
206
+ var color = useColor ? (_b = SEVERITY_COLORS[violation.severity]) !== null && _b !== void 0 ? _b : '' : '';
207
+ var reset = useColor ? RESET_COLOR : '';
208
+ var location = typeof violation.line === 'number' ? "".concat(filePath, ":").concat(violation.line) : "".concat(filePath, ":-");
209
+ var codeText = violation.code ? compactText(violation.code) : undefined;
210
+ var message = stripRedundantCodeSuffix(compactText(violation.message), codeText);
211
+ var header = "".concat(prefix).concat(color, "[").concat(severityLabel, "] ").concat(location, " ").concat(message).concat(reset);
212
+ stream.write("".concat(header, "\n"));
213
+ var tagLabel = formatTagLabel(violation.tag, language, t);
214
+ var tagSuffix = tagLabel ? " (".concat(tagLabel, ")") : '';
215
+ stream.write("".concat(indent, "rule: ").concat(violation.ruleName).concat(tagSuffix, "\n"));
216
+ if (codeText) {
217
+ stream.write("".concat(indent, "code: ").concat(codeText, "\n"));
221
218
  }
222
219
  if (violation.suggestions && violation.suggestions.length > 0) {
223
- var suggestionSeparator = language === 'zh' ? '; ' : ' | ';
224
- var suggestionLine = violation.suggestions
225
- .map(function (suggestion) { return t.reporterFormatSuggestion(suggestion); })
226
- .join(suggestionSeparator);
227
- writeLine(detailStream, "".concat(indent).concat(t.reporterSuggestionLabel(), ": ").concat(suggestionLine));
220
+ stream.write("".concat(indent, "suggestion:\n"));
221
+ violation.suggestions.forEach(function (suggestion) {
222
+ stream.write("".concat(bulletIndent, "- ").concat(compactText(t.reporterFormatSuggestion(suggestion)), "\n"));
223
+ });
228
224
  }
229
225
  });
230
- (_c = options.onAfterReport) === null || _c === void 0 ? void 0 : _c.call(options);
231
226
  }
232
- function getLoggerForSeverity(severity) {
233
- var _a;
234
- return (_a = severityLoggers[severity]) !== null && _a !== void 0 ? _a : consola_1.default.error;
227
+ function formatTagLabel(tag, language, t) {
228
+ var label = t.ruleTagLabel({ tag: tag });
229
+ if (language === 'en' && label.endsWith(' Rules')) {
230
+ return label.slice(0, -' Rules'.length);
231
+ }
232
+ return label;
233
+ }
234
+ function compactText(value) {
235
+ return value.replace(/\s*\n\s*/g, ' ').replace(/\s{2,}/g, ' ').trim();
236
+ }
237
+ function stripRedundantCodeSuffix(message, code) {
238
+ if (!code) {
239
+ return message;
240
+ }
241
+ var trimmed = message.trim();
242
+ var pattern = new RegExp(":\\s*".concat(escapeRegExp(code), "$"));
243
+ if (pattern.test(trimmed)) {
244
+ return trimmed.replace(pattern, '').trim();
245
+ }
246
+ return message;
247
+ }
248
+ function escapeRegExp(value) {
249
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
235
250
  }
236
251
  function resolveLine(record, offsets) {
237
252
  if (typeof record.line === 'number') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auto-cr-cmd",
3
- "version": "2.0.99",
3
+ "version": "2.0.101",
4
4
  "description": "Fast automated code review CLI powered by SWC-based static analysis",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/types/index.d.ts",
@@ -39,7 +39,7 @@
39
39
  "consola": "^3.4.2",
40
40
  "jsonc-parser": "^3.3.1",
41
41
  "picomatch": "^4.0.3",
42
- "auto-cr-rules": "2.0.99"
42
+ "auto-cr-rules": "2.0.101"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@eslint/js": "^9.39.2",