rhine-lint 1.4.3 → 1.5.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/README.md +26 -7
- package/dist/cli.js +47 -25
- package/dist/config.d.ts +83 -1
- package/dist/core/config.js +2 -1
- package/dist/core/runner.js +3 -3
- package/dist/utils/logger.js +0 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -111,6 +111,10 @@ export default {
|
|
|
111
111
|
|
|
112
112
|
// ESLint 专项配置
|
|
113
113
|
eslint: {
|
|
114
|
+
// 是否启用 ESLint (默认为 true)
|
|
115
|
+
// 设为 false 可禁用 ESLint 检查
|
|
116
|
+
enable: true,
|
|
117
|
+
|
|
114
118
|
// 启用/禁用特定范围的规则
|
|
115
119
|
scope: {
|
|
116
120
|
frontend: true, // 开启前端规则 (React 等)
|
|
@@ -133,6 +137,10 @@ export default {
|
|
|
133
137
|
|
|
134
138
|
// Prettier 专项配置
|
|
135
139
|
prettier: {
|
|
140
|
+
// 是否启用 Prettier (默认为 true)
|
|
141
|
+
// 设为 false 可禁用 Prettier 格式检查
|
|
142
|
+
enable: true,
|
|
143
|
+
|
|
136
144
|
config: {
|
|
137
145
|
printWidth: 100,
|
|
138
146
|
semi: true,
|
|
@@ -154,6 +162,9 @@ CLI 参数优先级高于配置文件:
|
|
|
154
162
|
- `--ignore-file <path>`: 指定类似 `.gitignore` 的忽略文件 (支持多次使用, e.g. `--ignore-file .gitignore --ignore-file .eslintignore`)。
|
|
155
163
|
- `--ignore <pattern>`: 添加忽略模式 (支持多次使用, e.g. `--ignore dist --ignore coverage`)。
|
|
156
164
|
- `--no-ignore`: 强制禁用所有忽略规则 (包括 ignoreFiles 和 ignores)。
|
|
165
|
+
- `--disable-eslint`: 禁用 ESLint 检查 (覆盖配置文件中的 `eslint.enable`)。
|
|
166
|
+
- `--disable-prettier`: 禁用 Prettier 格式检查 (覆盖配置文件中的 `prettier.enable`)。
|
|
167
|
+
- `--no-time`: 禁用各阶段耗时信息显示(默认启用)。
|
|
157
168
|
- `--debug`: 打印调试信息(包括生成的配置、忽略列表等)。
|
|
158
169
|
- `--cache-dir <dir>`: 指定缓存目录(默认使用 `node_modules/.cache/rhine-lint`)。
|
|
159
170
|
|
|
@@ -337,6 +348,9 @@ cli
|
|
|
337
348
|
.option("--ignore [pattern]", "Add ignore pattern (can be used multiple times)")
|
|
338
349
|
.option("--no-ignore", "Disable all ignore rules")
|
|
339
350
|
.option("--cache-dir <dir>", "Custom cache directory")
|
|
351
|
+
.option("--no-time", "Disable elapsed time display")
|
|
352
|
+
.option("--disable-eslint", "Disable ESLint linting")
|
|
353
|
+
.option("--disable-prettier", "Disable Prettier formatting check")
|
|
340
354
|
.option("--debug", "Enable debug mode")
|
|
341
355
|
```
|
|
342
356
|
|
|
@@ -534,16 +548,21 @@ export type Config = {
|
|
|
534
548
|
type?: 'js' | 'ts' | 'frontend' | 'react' | 'nextjs',
|
|
535
549
|
cacheDir?: string,
|
|
536
550
|
fix?: boolean,
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
551
|
+
time?: boolean, // 显示各阶段耗时 (default: true)
|
|
552
|
+
projectTypeCheck?: boolean, // 启用项目级类型检查 (default: true)
|
|
553
|
+
tsconfig?: string, // tsconfig 文件路径 (default: './tsconfig.json')
|
|
554
|
+
ignoreFiles?: string[], // gitignore 风格的忽略文件列表 (default: ['./.gitignore'])
|
|
555
|
+
ignores?: string[], // 忽略模式列表 (default: ['package-lock.json', ...])
|
|
556
|
+
ignore?: string[], // [deprecated] 使用 ignores 代替
|
|
540
557
|
eslint?: {
|
|
541
|
-
|
|
542
|
-
|
|
558
|
+
enable?: boolean, // 是否启用 ESLint (default: true)
|
|
559
|
+
config?: [...], // ESLint Flat Config 数组
|
|
560
|
+
overlay?: boolean, // 覆盖模式 (true: 完全覆盖内置配置)
|
|
543
561
|
},
|
|
544
562
|
prettier?: {
|
|
545
|
-
|
|
546
|
-
|
|
563
|
+
enable?: boolean, // 是否启用 Prettier (default: true)
|
|
564
|
+
config?: {...}, // Prettier 配置对象
|
|
565
|
+
overlay?: boolean, // 覆盖模式 (true: 完全覆盖内置配置)
|
|
547
566
|
}
|
|
548
567
|
}
|
|
549
568
|
```
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'module';
|
|
3
|
-
// import cac from "cac";
|
|
4
3
|
import path from "node:path";
|
|
5
4
|
import { loadUserConfig, generateTempConfig, cleanup } from "./core/config.js";
|
|
6
5
|
import { runEslint, runPrettier } from "./core/runner.js";
|
|
@@ -21,15 +20,17 @@ cli
|
|
|
21
20
|
.option("--ignore [pattern]", "Add ignore pattern (can be used multiple times)")
|
|
22
21
|
.option("--no-ignore", "Disable all ignore rules (including .gitignore)")
|
|
23
22
|
.option("--cache-dir <dir>", "Custom temporary cache directory")
|
|
24
|
-
.option("--time", "
|
|
23
|
+
.option("--no-time", "Disable elapsed time display for each phase")
|
|
24
|
+
.option("--disable-eslint", "Disable ESLint linting")
|
|
25
|
+
.option("--disable-prettier", "Disable Prettier formatting check")
|
|
25
26
|
.option("--debug", "Enable debug mode")
|
|
26
27
|
.action(async (files, options) => {
|
|
27
28
|
const cwd = process.cwd();
|
|
28
29
|
// If files is empty, default to "."
|
|
29
30
|
const targetFiles = files.length > 0 ? files : ["."];
|
|
30
31
|
let usedCachePath;
|
|
31
|
-
//
|
|
32
|
-
let showTime = options.time
|
|
32
|
+
// 计时功能:默认启用,可通过 --no-time 或配置文件禁用
|
|
33
|
+
let showTime = options.time !== false;
|
|
33
34
|
const startTotal = Date.now();
|
|
34
35
|
let startPhase = startTotal;
|
|
35
36
|
try {
|
|
@@ -75,34 +76,55 @@ cli
|
|
|
75
76
|
startPhase = Date.now();
|
|
76
77
|
}
|
|
77
78
|
console.log();
|
|
79
|
+
// 确定是否启用 ESLint 和 Prettier(CLI 选项优先于配置文件)
|
|
80
|
+
const enableEslint = options.disableEslint ? false : (userConfigResult.config.eslint?.enable ?? true);
|
|
81
|
+
const enablePrettier = options.disablePrettier ? false : (userConfigResult.config.prettier?.enable ?? true);
|
|
82
|
+
let eslintResult = null;
|
|
83
|
+
let prettierResult = null;
|
|
78
84
|
// 3. Run ESLint
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
85
|
+
if (enableEslint) {
|
|
86
|
+
eslintResult = await runEslint(cwd, temps.eslintPath, options.fix ?? false, targetFiles);
|
|
87
|
+
// 计时:第二阶段(ESLint)
|
|
88
|
+
if (showTime) {
|
|
89
|
+
logTime("ESLint", Date.now() - startPhase);
|
|
90
|
+
startPhase = Date.now();
|
|
91
|
+
}
|
|
92
|
+
console.log();
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
logInfo("ESLint: Disabled");
|
|
96
|
+
console.log();
|
|
84
97
|
}
|
|
85
|
-
console.log();
|
|
86
98
|
// 4. Run Prettier
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
99
|
+
if (enablePrettier) {
|
|
100
|
+
prettierResult = await runPrettier(cwd, temps.prettierPath, options.fix ?? false, targetFiles);
|
|
101
|
+
// 计时:第三阶段(Prettier)
|
|
102
|
+
if (showTime) {
|
|
103
|
+
logTime("Prettier", Date.now() - startPhase);
|
|
104
|
+
}
|
|
105
|
+
console.log();
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
logInfo("Prettier: Disabled");
|
|
109
|
+
console.log();
|
|
91
110
|
}
|
|
92
|
-
console.log();
|
|
93
111
|
if (eslintResult || prettierResult) {
|
|
94
112
|
logError("Linting completed with issues:");
|
|
95
|
-
if (
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
logError(`Prettier: ${prettierResult}`);
|
|
113
|
+
if (enableEslint) {
|
|
114
|
+
if (eslintResult) {
|
|
115
|
+
logError(`ESLint: ${eslintResult}`);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
logSuccess(`ESLint: No issues found`);
|
|
119
|
+
}
|
|
103
120
|
}
|
|
104
|
-
|
|
105
|
-
|
|
121
|
+
if (enablePrettier) {
|
|
122
|
+
if (prettierResult) {
|
|
123
|
+
logError(`Prettier: ${prettierResult}`);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
logSuccess(`Prettier: No issues found`);
|
|
127
|
+
}
|
|
106
128
|
}
|
|
107
129
|
process.exit(1);
|
|
108
130
|
}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,11 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rhine Lint configuration options.
|
|
3
|
+
* All options are optional with sensible defaults.
|
|
4
|
+
* Priority: CLI arguments > Config file > Default values
|
|
5
|
+
*/
|
|
1
6
|
export type Config = {
|
|
7
|
+
/**
|
|
8
|
+
* Project type level that determines which linting rules to enable.
|
|
9
|
+
* Each level includes all rules from previous levels:
|
|
10
|
+
* - `'js'`: JavaScript only (no type checking)
|
|
11
|
+
* - `'ts'`: TypeScript with type-aware rules
|
|
12
|
+
* - `'frontend'` / `'react'`: TypeScript + React/JSX/Hooks rules
|
|
13
|
+
* - `'nextjs'`: TypeScript + React + Next.js specific rules
|
|
14
|
+
* @default 'frontend'
|
|
15
|
+
*/
|
|
2
16
|
type?: 'js' | 'ts' | 'frontend' | 'react' | 'nextjs';
|
|
17
|
+
/**
|
|
18
|
+
* Directory for storing generated virtual config files and cache metadata.
|
|
19
|
+
* Can be absolute or relative to the project root.
|
|
20
|
+
* @default 'node_modules/.cache/rhine-lint' (if node_modules exists) or '.cache/rhine-lint'
|
|
21
|
+
*/
|
|
3
22
|
cacheDir?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Automatically fix linting errors and formatting issues.
|
|
25
|
+
* When enabled, ESLint will apply auto-fixes and Prettier will rewrite files.
|
|
26
|
+
* @default false
|
|
27
|
+
*/
|
|
4
28
|
fix?: boolean;
|
|
5
29
|
/**
|
|
6
30
|
* Enable timing output for each phase.
|
|
7
31
|
* Shows elapsed time for: preparation, ESLint, and Prettier phases.
|
|
8
|
-
* @default
|
|
32
|
+
* @default true
|
|
9
33
|
*/
|
|
10
34
|
time?: boolean;
|
|
11
35
|
/**
|
|
@@ -43,13 +67,71 @@ export type Config = {
|
|
|
43
67
|
* @example ['temp', 'generated', '*.test.ts']
|
|
44
68
|
*/
|
|
45
69
|
ignore?: string[];
|
|
70
|
+
/**
|
|
71
|
+
* ESLint configuration options.
|
|
72
|
+
*/
|
|
46
73
|
eslint?: {
|
|
74
|
+
/**
|
|
75
|
+
* Enable ESLint linting.
|
|
76
|
+
* Set to `false` to skip ESLint entirely (only run Prettier).
|
|
77
|
+
* @default true
|
|
78
|
+
*/
|
|
79
|
+
enable?: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* ESLint Flat Config array to extend or override default rules.
|
|
82
|
+
* These configurations are merged with Rhine Lint's built-in rules.
|
|
83
|
+
* @see https://eslint.org/docs/latest/use/configure/configuration-files
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* config: [
|
|
87
|
+
* {
|
|
88
|
+
* rules: {
|
|
89
|
+
* 'no-console': 'warn',
|
|
90
|
+
* '@typescript-eslint/no-unused-vars': 'off'
|
|
91
|
+
* }
|
|
92
|
+
* }
|
|
93
|
+
* ]
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
47
96
|
config?: [
|
|
48
97
|
];
|
|
98
|
+
/**
|
|
99
|
+
* Overlay mode for ESLint configuration.
|
|
100
|
+
* - `true`: User config completely replaces Rhine Lint's default rules
|
|
101
|
+
* - `false`: User config is merged with Rhine Lint's default rules
|
|
102
|
+
* @default false
|
|
103
|
+
*/
|
|
49
104
|
overlay?: boolean;
|
|
50
105
|
};
|
|
106
|
+
/**
|
|
107
|
+
* Prettier configuration options.
|
|
108
|
+
*/
|
|
51
109
|
prettier?: {
|
|
110
|
+
/**
|
|
111
|
+
* Enable Prettier formatting check.
|
|
112
|
+
* Set to `false` to skip Prettier entirely (only run ESLint).
|
|
113
|
+
* @default true
|
|
114
|
+
*/
|
|
115
|
+
enable?: boolean;
|
|
116
|
+
/**
|
|
117
|
+
* Prettier options to extend or override default formatting rules.
|
|
118
|
+
* @see https://prettier.io/docs/en/options.html
|
|
119
|
+
* @example
|
|
120
|
+
* ```ts
|
|
121
|
+
* config: {
|
|
122
|
+
* semi: true,
|
|
123
|
+
* singleQuote: false,
|
|
124
|
+
* printWidth: 80
|
|
125
|
+
* }
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
52
128
|
config?: {};
|
|
129
|
+
/**
|
|
130
|
+
* Overlay mode for Prettier configuration.
|
|
131
|
+
* - `true`: User config completely replaces Rhine Lint's default options
|
|
132
|
+
* - `false`: User config is merged with Rhine Lint's default options
|
|
133
|
+
* @default false
|
|
134
|
+
*/
|
|
53
135
|
overlay?: boolean;
|
|
54
136
|
};
|
|
55
137
|
};
|
package/dist/core/config.js
CHANGED
|
@@ -263,7 +263,8 @@ export async function generateTempConfig(cwd, userConfigResult, cliLevel, cliCac
|
|
|
263
263
|
const defuUrl = pathToFileURL(require.resolve("defu")).href;
|
|
264
264
|
const jitiUrl = pathToFileURL(require.resolve("jiti")).href;
|
|
265
265
|
let finalUserConfigUrl = userConfigUrl;
|
|
266
|
-
|
|
266
|
+
const tsExtensions = ['.ts', '.mts', '.cts'];
|
|
267
|
+
if (userConfigResult.path && tsExtensions.some(ext => userConfigResult.path.endsWith(ext))) {
|
|
267
268
|
try {
|
|
268
269
|
const ts = await import('typescript');
|
|
269
270
|
const fileContent = await fs.readFile(userConfigResult.path, 'utf-8');
|
package/dist/core/runner.js
CHANGED
|
@@ -16,7 +16,7 @@ function resolveBin(pkgName, binPathRelative) {
|
|
|
16
16
|
return require.resolve(`${pkgName}/${binPathRelative}`);
|
|
17
17
|
}
|
|
18
18
|
catch (e) {
|
|
19
|
-
if (e.code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED' && e.code !== 'MODULE_NOT_FOUND') {
|
|
19
|
+
if (e instanceof Error && e.code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED' && e.code !== 'MODULE_NOT_FOUND') {
|
|
20
20
|
logger.debug(`Resolve error for ${pkgName}/${binPathRelative}:`, e);
|
|
21
21
|
}
|
|
22
22
|
}
|
|
@@ -114,7 +114,7 @@ export async function runEslint(cwd, configPath, fix, files = ["."]) {
|
|
|
114
114
|
}
|
|
115
115
|
catch (e) {
|
|
116
116
|
logError("Failed to run ESLint", e);
|
|
117
|
-
return e.message
|
|
117
|
+
return e instanceof Error ? e.message : "Unknown error";
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
export async function runPrettier(cwd, configPath, fix, files = ["."]) {
|
|
@@ -153,6 +153,6 @@ export async function runPrettier(cwd, configPath, fix, files = ["."]) {
|
|
|
153
153
|
}
|
|
154
154
|
catch (e) {
|
|
155
155
|
logError("Failed to run Prettier", e);
|
|
156
|
-
return e.message
|
|
156
|
+
return e instanceof Error ? e.message : "Unknown error";
|
|
157
157
|
}
|
|
158
158
|
}
|
package/dist/utils/logger.js
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { createConsola } from "consola";
|
|
2
2
|
import { colors } from "consola/utils";
|
|
3
3
|
const { cyan, red, green, yellow, gray } = colors;
|
|
4
|
-
// Custom logger to satisfy "RL" prefix requirement
|
|
5
|
-
const rLine = (colorFn, type, msg) => {
|
|
6
|
-
console.log(`${colorFn("RL")} ${msg}`);
|
|
7
|
-
};
|
|
8
4
|
export const logger = createConsola({
|
|
9
5
|
level: 3,
|
|
10
6
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rhine-lint",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.2",
|
|
4
4
|
"module": "./dist/index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"react",
|
|
19
19
|
"opinionated"
|
|
20
20
|
],
|
|
21
|
-
"author": "RhineAI <
|
|
21
|
+
"author": "RhineAI <rhineai@163.com>",
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"repository": {
|
|
24
24
|
"type": "git",
|