@plumeria/eslint-plugin 19.10.1 → 19.10.3
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 +14 -2
- package/bin/oxlint.js +62 -33
- package/dist/cli.d.ts +10 -0
- package/dist/cli.js +97 -0
- package/dist/guard.d.ts +14 -3
- package/dist/guard.js +29 -8
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -34,12 +34,14 @@ export default [plumeria.configs.recommended];
|
|
|
34
34
|
|
|
35
35
|
## Configuring the styling prop
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
`custom-props-require-import`, `no-inline-object`, `no-mixed-styling-props`,
|
|
38
|
+
`no-style-prop-relay` and `no-unresolved-composition` need to know which JSX
|
|
38
39
|
prop carries styles. It is `classStyle` unless you changed it, so most projects
|
|
39
40
|
configure nothing.
|
|
40
41
|
|
|
41
42
|
If you did rename it — via `styleProp` on `withPlumeria` or on the unplugin
|
|
42
|
-
options — tell the plugin the same name.
|
|
43
|
+
options — tell the plugin the same name. The lint the bundler plugins run in the
|
|
44
|
+
build is given that name already. ESLint cannot read it from your bundler
|
|
43
45
|
config, so set it once in `settings` and every rule picks it up:
|
|
44
46
|
|
|
45
47
|
```js
|
|
@@ -257,6 +259,16 @@ plumerialint
|
|
|
257
259
|
The process exits with a non-zero status code if any errors or warnings are found,
|
|
258
260
|
making it suitable for use in CI and build pipelines.
|
|
259
261
|
|
|
262
|
+
### Styling prop
|
|
263
|
+
|
|
264
|
+
If the styling prop is renamed, pass the name with `--style-prop`. Without the
|
|
265
|
+
flag, `plumerialint` asks ESLint for `settings.plumeria.styleProp` when ESLint
|
|
266
|
+
and a flat config are installed, and uses `classStyle` otherwise:
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
plumerialint --style-prop sx
|
|
270
|
+
```
|
|
271
|
+
|
|
260
272
|
### Aborting Builds on Lint Errors (Parallel Pipeline)
|
|
261
273
|
|
|
262
274
|
You can run `plumerialint` in parallel with your build command (e.g. `next build` or `vite build`) using the `--` separator:
|
package/bin/oxlint.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const { spawn } = require('child_process');
|
|
4
4
|
const process = require('process');
|
|
5
5
|
const path = require('path');
|
|
6
|
+
const fs = require('fs');
|
|
6
7
|
const oxlintConfig = path.join(__dirname, '..', 'oxlint.json');
|
|
7
8
|
const oxlintBin = path.join(
|
|
8
9
|
path.dirname(require.resolve('oxlint/package.json')),
|
|
@@ -10,49 +11,73 @@ const oxlintBin = path.join(
|
|
|
10
11
|
'oxlint',
|
|
11
12
|
);
|
|
12
13
|
|
|
14
|
+
const { cliOverrides } = require('../dist/cli.js');
|
|
15
|
+
const { lintConfig, lowerPriority } = require('../dist/guard.js');
|
|
16
|
+
|
|
13
17
|
const doubleDashIndex = process.argv.indexOf('--');
|
|
14
|
-
let
|
|
18
|
+
let cliArgs = [];
|
|
15
19
|
let buildCommand = null;
|
|
16
20
|
let buildArgs = [];
|
|
17
21
|
|
|
18
22
|
if (doubleDashIndex !== -1) {
|
|
19
|
-
|
|
23
|
+
cliArgs = process.argv.slice(2, doubleDashIndex);
|
|
20
24
|
if (doubleDashIndex + 1 < process.argv.length) {
|
|
21
25
|
buildCommand = process.argv[doubleDashIndex + 1];
|
|
22
26
|
buildArgs = process.argv.slice(doubleDashIndex + 2);
|
|
23
27
|
}
|
|
24
28
|
} else {
|
|
25
|
-
|
|
29
|
+
cliArgs = process.argv.slice(2);
|
|
26
30
|
}
|
|
27
31
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
async function startOxlint() {
|
|
33
|
+
const { overrides, rest } = await cliOverrides(cliArgs, process.cwd());
|
|
34
|
+
const config = lintConfig(overrides);
|
|
35
|
+
const child = spawn(
|
|
36
|
+
process.execPath,
|
|
37
|
+
[
|
|
38
|
+
oxlintBin,
|
|
39
|
+
'-c',
|
|
40
|
+
config,
|
|
41
|
+
'--deny-warnings',
|
|
42
|
+
'--no-error-on-unmatched-pattern',
|
|
43
|
+
...(rest.some((arg) => arg.startsWith('--threads'))
|
|
44
|
+
? []
|
|
45
|
+
: ['--threads=2']),
|
|
46
|
+
...rest,
|
|
47
|
+
],
|
|
48
|
+
{ stdio: 'inherit' },
|
|
49
|
+
);
|
|
50
|
+
lowerPriority(child.pid);
|
|
51
|
+
if (config !== oxlintConfig) {
|
|
52
|
+
child.on('close', () => fs.rmSync(config, { force: true }));
|
|
53
|
+
}
|
|
54
|
+
return child;
|
|
55
|
+
}
|
|
36
56
|
|
|
37
57
|
function handleOxlintError(err) {
|
|
38
58
|
console.error('Error running oxlint:', err.message);
|
|
39
59
|
process.exit(1);
|
|
40
60
|
}
|
|
41
61
|
|
|
62
|
+
function fail(err) {
|
|
63
|
+
console.error(`✖ [plumerialint] ${err.message}`);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
|
|
42
67
|
if (!buildCommand) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
68
|
+
startOxlint().then((child) => {
|
|
69
|
+
child.on('error', handleOxlintError);
|
|
70
|
+
child.on('close', (code) => {
|
|
71
|
+
process.exit(code || 0);
|
|
72
|
+
});
|
|
73
|
+
}, fail);
|
|
48
74
|
} else {
|
|
49
75
|
let oxlintExited = false;
|
|
50
76
|
let oxlintCode = null;
|
|
51
77
|
let buildExited = false;
|
|
52
78
|
let buildCode = null;
|
|
53
79
|
let aborted = false;
|
|
54
|
-
|
|
55
|
-
const oxlintChild = spawn(process.execPath, oxlintArgs, { stdio: 'inherit' });
|
|
80
|
+
let oxlintChild = null;
|
|
56
81
|
|
|
57
82
|
const fullBuildCommand =
|
|
58
83
|
buildArgs.length > 0
|
|
@@ -78,16 +103,12 @@ if (!buildCommand) {
|
|
|
78
103
|
} else if (failedSource === 'build') {
|
|
79
104
|
console.error(`\n✖ [plumerialint] Build failed. Aborting lint...`);
|
|
80
105
|
try {
|
|
81
|
-
oxlintChild.kill();
|
|
106
|
+
if (oxlintChild) oxlintChild.kill();
|
|
82
107
|
} catch (e) {}
|
|
83
108
|
process.exit(exitCode || 1);
|
|
84
109
|
}
|
|
85
110
|
}
|
|
86
111
|
|
|
87
|
-
oxlintChild.on('error', (err) => {
|
|
88
|
-
handleOxlintError(err);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
112
|
buildChild.on('error', (err) => {
|
|
92
113
|
console.error(
|
|
93
114
|
`Error running build command "${buildCommand}":`,
|
|
@@ -96,16 +117,6 @@ if (!buildCommand) {
|
|
|
96
117
|
abort(1, 'build');
|
|
97
118
|
});
|
|
98
119
|
|
|
99
|
-
oxlintChild.on('close', (code) => {
|
|
100
|
-
oxlintExited = true;
|
|
101
|
-
oxlintCode = code;
|
|
102
|
-
if (code !== 0) {
|
|
103
|
-
abort(code, 'lint');
|
|
104
|
-
} else if (buildExited) {
|
|
105
|
-
process.exit(buildCode || 0);
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
|
|
109
120
|
buildChild.on('close', (code) => {
|
|
110
121
|
buildExited = true;
|
|
111
122
|
buildCode = code;
|
|
@@ -115,4 +126,22 @@ if (!buildCommand) {
|
|
|
115
126
|
process.exit(oxlintCode || 0);
|
|
116
127
|
}
|
|
117
128
|
});
|
|
129
|
+
|
|
130
|
+
startOxlint().then((child) => {
|
|
131
|
+
if (aborted) {
|
|
132
|
+
child.kill();
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
oxlintChild = child;
|
|
136
|
+
child.on('error', handleOxlintError);
|
|
137
|
+
child.on('close', (code) => {
|
|
138
|
+
oxlintExited = true;
|
|
139
|
+
oxlintCode = code;
|
|
140
|
+
if (code !== 0) {
|
|
141
|
+
abort(code, 'lint');
|
|
142
|
+
} else if (buildExited) {
|
|
143
|
+
process.exit(buildCode || 0);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}, fail);
|
|
118
147
|
}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type LintOverrides } from './guard';
|
|
2
|
+
export declare function takeStyleProp(args: string[]): {
|
|
3
|
+
styleProp?: string;
|
|
4
|
+
rest: string[];
|
|
5
|
+
};
|
|
6
|
+
export declare function stylePropFromESLint(cwd: string): Promise<string | undefined>;
|
|
7
|
+
export declare function cliOverrides(args: string[], cwd: string): Promise<{
|
|
8
|
+
overrides: LintOverrides;
|
|
9
|
+
rest: string[];
|
|
10
|
+
}>;
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.takeStyleProp = takeStyleProp;
|
|
37
|
+
exports.stylePropFromESLint = stylePropFromESLint;
|
|
38
|
+
exports.cliOverrides = cliOverrides;
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const guard_1 = require("./guard");
|
|
41
|
+
const STYLE_PROP_FLAG = '--style-prop';
|
|
42
|
+
const PROBED_FILES = ['src/index.tsx', 'app/page.tsx', 'index.tsx', 'index.js'];
|
|
43
|
+
function takeStyleProp(args) {
|
|
44
|
+
const rest = [];
|
|
45
|
+
let styleProp;
|
|
46
|
+
for (let i = 0; i < args.length; i++) {
|
|
47
|
+
const arg = args[i];
|
|
48
|
+
if (arg === STYLE_PROP_FLAG) {
|
|
49
|
+
styleProp = args[++i];
|
|
50
|
+
if (!styleProp)
|
|
51
|
+
throw new Error(`${STYLE_PROP_FLAG} needs a prop name`);
|
|
52
|
+
}
|
|
53
|
+
else if (arg.startsWith(`${STYLE_PROP_FLAG}=`)) {
|
|
54
|
+
styleProp = arg.slice(STYLE_PROP_FLAG.length + 1);
|
|
55
|
+
if (!styleProp)
|
|
56
|
+
throw new Error(`${STYLE_PROP_FLAG} needs a prop name`);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
rest.push(arg);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return { styleProp, rest };
|
|
63
|
+
}
|
|
64
|
+
async function stylePropFromESLint(cwd) {
|
|
65
|
+
let eslint;
|
|
66
|
+
try {
|
|
67
|
+
eslint = require(require.resolve('eslint', { paths: [cwd] }));
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
const ESLint = eslint.loadESLint
|
|
74
|
+
? await eslint.loadESLint({ useFlatConfig: true })
|
|
75
|
+
: eslint.ESLint;
|
|
76
|
+
const instance = new ESLint({ cwd });
|
|
77
|
+
for (const file of PROBED_FILES) {
|
|
78
|
+
const config = (await instance.calculateConfigForFile(path.join(cwd, file)));
|
|
79
|
+
const styleProp = config?.settings?.plumeria?.styleProp;
|
|
80
|
+
if (typeof styleProp === 'string')
|
|
81
|
+
return styleProp;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
async function cliOverrides(args, cwd) {
|
|
90
|
+
const { styleProp, rest } = takeStyleProp(args);
|
|
91
|
+
return {
|
|
92
|
+
overrides: (0, guard_1.lintOverrides)({
|
|
93
|
+
styleProp: styleProp ?? (await stylePropFromESLint(cwd)),
|
|
94
|
+
}),
|
|
95
|
+
rest,
|
|
96
|
+
};
|
|
97
|
+
}
|
package/dist/guard.d.ts
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
type Spelling = boolean | {
|
|
2
2
|
sizes?: boolean;
|
|
3
3
|
} | undefined;
|
|
4
|
-
interface
|
|
4
|
+
interface LintOptions {
|
|
5
5
|
withoutLogicalProperties?: Spelling;
|
|
6
6
|
withoutPhysicalProperties?: Spelling;
|
|
7
|
+
styleProp?: string;
|
|
7
8
|
}
|
|
8
|
-
export
|
|
9
|
-
|
|
9
|
+
export interface LintOverrides {
|
|
10
|
+
rules?: Record<string, unknown>;
|
|
11
|
+
settings?: {
|
|
12
|
+
plumeria: {
|
|
13
|
+
styleProp: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export declare function lintOverrides(options: LintOptions): LintOverrides;
|
|
18
|
+
export declare function lintConfig(overrides: LintOverrides): string;
|
|
19
|
+
export declare function lowerPriority(pid: number | undefined): boolean;
|
|
20
|
+
export declare function startLintGuard(overrides?: LintOverrides): boolean;
|
|
10
21
|
export {};
|
package/dist/guard.js
CHANGED
|
@@ -33,7 +33,9 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.
|
|
36
|
+
exports.lintOverrides = lintOverrides;
|
|
37
|
+
exports.lintConfig = lintConfig;
|
|
38
|
+
exports.lowerPriority = lowerPriority;
|
|
37
39
|
exports.startLintGuard = startLintGuard;
|
|
38
40
|
const child_process_1 = require("child_process");
|
|
39
41
|
const fs = __importStar(require("fs"));
|
|
@@ -48,7 +50,8 @@ function spellingRule(spelling) {
|
|
|
48
50
|
? ['error', { sizes: true }]
|
|
49
51
|
: 'error';
|
|
50
52
|
}
|
|
51
|
-
function
|
|
53
|
+
function lintOverrides(options) {
|
|
54
|
+
const overrides = {};
|
|
52
55
|
const rules = {};
|
|
53
56
|
const logical = spellingRule(options.withoutLogicalProperties);
|
|
54
57
|
const physical = spellingRule(options.withoutPhysicalProperties);
|
|
@@ -56,27 +59,45 @@ function spellingRules(options) {
|
|
|
56
59
|
rules['@plumeria/no-logical-properties'] = logical;
|
|
57
60
|
if (physical)
|
|
58
61
|
rules['@plumeria/no-physical-properties'] = physical;
|
|
59
|
-
|
|
62
|
+
if (logical || physical)
|
|
63
|
+
overrides.rules = rules;
|
|
64
|
+
if (options.styleProp) {
|
|
65
|
+
overrides.settings = { plumeria: { styleProp: options.styleProp } };
|
|
66
|
+
}
|
|
67
|
+
return overrides;
|
|
60
68
|
}
|
|
61
|
-
function lintConfig(
|
|
62
|
-
if (
|
|
69
|
+
function lintConfig(overrides) {
|
|
70
|
+
if (!overrides.rules && !overrides.settings)
|
|
63
71
|
return BASE_CONFIG;
|
|
64
72
|
const file = path.join(os.tmpdir(), `plumeria-oxlint-${process.pid}.json`);
|
|
65
|
-
fs.writeFileSync(file, JSON.stringify({ extends: [BASE_CONFIG],
|
|
73
|
+
fs.writeFileSync(file, JSON.stringify({ extends: [BASE_CONFIG], ...overrides }));
|
|
66
74
|
return file;
|
|
67
75
|
}
|
|
68
|
-
function
|
|
76
|
+
function lowerPriority(pid) {
|
|
77
|
+
if (!pid)
|
|
78
|
+
return false;
|
|
79
|
+
try {
|
|
80
|
+
os.setPriority(pid, os.constants.priority.PRIORITY_LOW);
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function startLintGuard(overrides = {}) {
|
|
69
88
|
if (process.env[GUARD_ENV])
|
|
70
89
|
return false;
|
|
71
90
|
process.env[GUARD_ENV] = '1';
|
|
72
|
-
const config = lintConfig(
|
|
91
|
+
const config = lintConfig(overrides);
|
|
73
92
|
const child = (0, child_process_1.spawn)(process.execPath, [
|
|
74
93
|
path.join(path.dirname(require.resolve('oxlint/package.json')), 'bin', 'oxlint'),
|
|
75
94
|
'-c',
|
|
76
95
|
config,
|
|
77
96
|
'--deny-warnings',
|
|
78
97
|
'--no-error-on-unmatched-pattern',
|
|
98
|
+
'--threads=2',
|
|
79
99
|
], { stdio: 'inherit' });
|
|
100
|
+
lowerPriority(child.pid);
|
|
80
101
|
const exit = process.exit.bind(process);
|
|
81
102
|
let lintCode = null;
|
|
82
103
|
let pendingCode = null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plumeria/eslint-plugin",
|
|
3
|
-
"version": "19.10.
|
|
3
|
+
"version": "19.10.3",
|
|
4
4
|
"description": "Plumeria ESLint plugin",
|
|
5
5
|
"author": "Refirst 11",
|
|
6
6
|
"license": "MIT",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"known-css-properties": "^0.37.0",
|
|
60
60
|
"oxlint": "1.87.0",
|
|
61
61
|
"zss-engine": "2.9.1",
|
|
62
|
-
"@plumeria/compiler": "19.10.
|
|
62
|
+
"@plumeria/compiler": "19.10.3"
|
|
63
63
|
},
|
|
64
64
|
"scripts": {
|
|
65
65
|
"build": "rimraf dist && pnpm cjs",
|