@zhangyu1818/oxlint-config 1.0.0 → 2.1.0
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 +3 -2
- package/dist/index.d.ts +9 -1
- package/dist/index.js +62 -21
- package/dist/react-agent-rules.d.ts +8 -0
- package/dist/react-agent-rules.js +21 -1
- package/package.json +25 -25
package/README.md
CHANGED
|
@@ -65,6 +65,7 @@ react: {
|
|
|
65
65
|
- `react-agent-rules/no-manual-memoization`
|
|
66
66
|
- `react-agent-rules/no-forward-ref`
|
|
67
67
|
- `react-agent-rules/effect-empty-deps-only`
|
|
68
|
+
- `react-agent-rules/no-use-context`
|
|
68
69
|
|
|
69
70
|
```ts
|
|
70
71
|
export default defineConfig({
|
|
@@ -104,8 +105,8 @@ Default formatter options:
|
|
|
104
105
|
```json
|
|
105
106
|
{
|
|
106
107
|
"scripts": {
|
|
107
|
-
"lint": "oxlint",
|
|
108
|
-
"lint:fix": "oxlint --fix",
|
|
108
|
+
"lint": "oxlint -c oxlint.config.ts",
|
|
109
|
+
"lint:fix": "oxlint --fix -c oxlint.config.ts",
|
|
109
110
|
"format": "oxfmt -c oxfmt.config.ts .",
|
|
110
111
|
"format:check": "oxfmt --check -c oxfmt.config.ts ."
|
|
111
112
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ interface JsonObject {
|
|
|
8
8
|
}
|
|
9
9
|
type RuleConfig = Severity | [Severity, ...JsonValue[]];
|
|
10
10
|
type Rules = Record<string, RuleConfig>;
|
|
11
|
+
type OxlintGlobalValue = 'off' | 'readable' | 'readonly' | 'writable' | 'writeable' | boolean;
|
|
12
|
+
type OxlintGlobals = Record<string, OxlintGlobalValue>;
|
|
11
13
|
interface OxlintJsPluginAlias {
|
|
12
14
|
name: string;
|
|
13
15
|
specifier: string;
|
|
@@ -16,7 +18,9 @@ type OxlintJsPlugin = OxlintJsPluginAlias | string;
|
|
|
16
18
|
type OxlintPlugin = 'eslint' | 'import' | 'jest' | 'jsdoc' | 'jsx-a11y' | 'nextjs' | 'node' | 'oxc' | 'promise' | 'react' | 'react-perf' | 'typescript' | 'unicorn' | 'vitest' | 'vue';
|
|
17
19
|
interface OxlintOverride {
|
|
18
20
|
env?: Record<string, boolean>;
|
|
21
|
+
excludeFiles?: string[];
|
|
19
22
|
files: string[];
|
|
23
|
+
globals?: OxlintGlobals;
|
|
20
24
|
jsPlugins?: OxlintJsPlugin[];
|
|
21
25
|
plugins?: OxlintPlugin[];
|
|
22
26
|
rules?: Rules;
|
|
@@ -25,6 +29,8 @@ interface OxlintConfig {
|
|
|
25
29
|
$schema?: string;
|
|
26
30
|
categories?: Record<string, Severity>;
|
|
27
31
|
env?: Record<string, boolean>;
|
|
32
|
+
extends?: string[];
|
|
33
|
+
globals?: OxlintGlobals;
|
|
28
34
|
ignorePatterns?: string[];
|
|
29
35
|
jsPlugins?: OxlintJsPlugin[];
|
|
30
36
|
options?: {
|
|
@@ -71,6 +77,8 @@ interface OxlintPresets {
|
|
|
71
77
|
interface DefineOxlintConfigOptions {
|
|
72
78
|
categories?: Record<string, Severity>;
|
|
73
79
|
env?: Record<string, boolean>;
|
|
80
|
+
extends?: string[];
|
|
81
|
+
globals?: OxlintGlobals;
|
|
74
82
|
ignorePatterns?: string[];
|
|
75
83
|
jsPlugins?: OxlintJsPlugin[];
|
|
76
84
|
overrides?: OxlintOverride[];
|
|
@@ -166,4 +174,4 @@ declare const defaultSortImports: SortImportsOptions;
|
|
|
166
174
|
declare const defaultOxfmtPresets: Required<OxfmtPresets>;
|
|
167
175
|
declare function defineOxfmtConfig(options?: DefineOxfmtConfigOptions): OxfmtConfig;
|
|
168
176
|
|
|
169
|
-
export { type DefineOxfmtConfigOptions, type DefineOxlintConfigOptions, type OxfmtConfig, type OxfmtOverride, type OxfmtPresetConfig, type OxfmtPresets, type OxlintConfig, type OxlintJsPlugin, type OxlintJsPluginAlias, type OxlintOverride, type OxlintPlugin, type OxlintPresetConfig, type OxlintPresets, type ReactOptions, type ReactPresetOptions, type RuleConfig, type Rules, type Severity, type SortImportsOptions, type SortPackageJsonOptions, type TailwindSortOptions, type TypeScriptOptions, defaultIgnorePatterns, defaultOxfmtPresets, defaultOxlintPresets, defaultSortImports, defineConfig, defineOxfmtConfig, defineOxlintConfig };
|
|
177
|
+
export { type DefineOxfmtConfigOptions, type DefineOxlintConfigOptions, type OxfmtConfig, type OxfmtOverride, type OxfmtPresetConfig, type OxfmtPresets, type OxlintConfig, type OxlintGlobalValue, type OxlintGlobals, type OxlintJsPlugin, type OxlintJsPluginAlias, type OxlintOverride, type OxlintPlugin, type OxlintPresetConfig, type OxlintPresets, type ReactOptions, type ReactPresetOptions, type RuleConfig, type Rules, type Severity, type SortImportsOptions, type SortPackageJsonOptions, type TailwindSortOptions, type TypeScriptOptions, defaultIgnorePatterns, defaultOxfmtPresets, defaultOxlintPresets, defaultSortImports, defineConfig, defineOxfmtConfig, defineOxlintConfig };
|
package/dist/index.js
CHANGED
|
@@ -236,6 +236,26 @@ var nodeRules = {
|
|
|
236
236
|
"node/no-path-concat": "error"
|
|
237
237
|
};
|
|
238
238
|
|
|
239
|
+
// src/oxlint/presets/react-agent-rules.ts
|
|
240
|
+
import { existsSync } from "fs";
|
|
241
|
+
import { fileURLToPath } from "url";
|
|
242
|
+
function resolveReactAgentRulesPluginPath() {
|
|
243
|
+
const sourcePluginPath = fileURLToPath(
|
|
244
|
+
new URL("../../react-agent-rules.ts", import.meta.url)
|
|
245
|
+
);
|
|
246
|
+
if (existsSync(sourcePluginPath)) {
|
|
247
|
+
return sourcePluginPath;
|
|
248
|
+
}
|
|
249
|
+
return fileURLToPath(new URL("./react-agent-rules.js", import.meta.url));
|
|
250
|
+
}
|
|
251
|
+
var reactAgentRulesPlugin = resolveReactAgentRulesPluginPath();
|
|
252
|
+
var reactAgentRules = {
|
|
253
|
+
"react-agent-rules/effect-empty-deps-only": "error",
|
|
254
|
+
"react-agent-rules/no-forward-ref": "error",
|
|
255
|
+
"react-agent-rules/no-manual-memoization": "error",
|
|
256
|
+
"react-agent-rules/no-use-context": "error"
|
|
257
|
+
};
|
|
258
|
+
|
|
239
259
|
// src/oxlint/presets/react.ts
|
|
240
260
|
import { isPackageExists } from "local-pkg";
|
|
241
261
|
var jsxA11yRules = {
|
|
@@ -356,25 +376,6 @@ function createReactRules(options, nextEnabled) {
|
|
|
356
376
|
};
|
|
357
377
|
}
|
|
358
378
|
|
|
359
|
-
// src/oxlint/presets/react-agent-rules.ts
|
|
360
|
-
import { existsSync } from "fs";
|
|
361
|
-
import { fileURLToPath } from "url";
|
|
362
|
-
function resolveReactAgentRulesPluginPath() {
|
|
363
|
-
const sourcePluginPath = fileURLToPath(
|
|
364
|
-
new URL("../../react-agent-rules.ts", import.meta.url)
|
|
365
|
-
);
|
|
366
|
-
if (existsSync(sourcePluginPath)) {
|
|
367
|
-
return sourcePluginPath;
|
|
368
|
-
}
|
|
369
|
-
return fileURLToPath(new URL("./react-agent-rules.js", import.meta.url));
|
|
370
|
-
}
|
|
371
|
-
var reactAgentRulesPlugin = resolveReactAgentRulesPluginPath();
|
|
372
|
-
var reactAgentRules = {
|
|
373
|
-
"react-agent-rules/effect-empty-deps-only": "error",
|
|
374
|
-
"react-agent-rules/no-forward-ref": "error",
|
|
375
|
-
"react-agent-rules/no-manual-memoization": "error"
|
|
376
|
-
};
|
|
377
|
-
|
|
378
379
|
// src/oxlint/presets/test.ts
|
|
379
380
|
var vitestRules = {
|
|
380
381
|
"no-unused-expressions": "off",
|
|
@@ -638,6 +639,14 @@ function resolveIgnorePreset(preset, defaultEnabled) {
|
|
|
638
639
|
function mergeRules(...entries) {
|
|
639
640
|
return Object.assign({}, ...entries);
|
|
640
641
|
}
|
|
642
|
+
function pickRules(rules, predicate) {
|
|
643
|
+
if (!rules) {
|
|
644
|
+
return {};
|
|
645
|
+
}
|
|
646
|
+
return Object.fromEntries(
|
|
647
|
+
Object.entries(rules).filter(([rule]) => predicate(rule))
|
|
648
|
+
);
|
|
649
|
+
}
|
|
641
650
|
function appendPlugin(plugins, plugin) {
|
|
642
651
|
if (!plugins.includes(plugin)) {
|
|
643
652
|
plugins.push(plugin);
|
|
@@ -650,6 +659,12 @@ function pruneOverride(override) {
|
|
|
650
659
|
if (override.env && Object.keys(override.env).length !== 0) {
|
|
651
660
|
result.env = override.env;
|
|
652
661
|
}
|
|
662
|
+
if (override.excludeFiles && override.excludeFiles.length !== 0) {
|
|
663
|
+
result.excludeFiles = override.excludeFiles;
|
|
664
|
+
}
|
|
665
|
+
if (override.globals && Object.keys(override.globals).length !== 0) {
|
|
666
|
+
result.globals = override.globals;
|
|
667
|
+
}
|
|
653
668
|
if (override.jsPlugins && override.jsPlugins.length !== 0) {
|
|
654
669
|
result.jsPlugins = override.jsPlugins;
|
|
655
670
|
}
|
|
@@ -659,7 +674,7 @@ function pruneOverride(override) {
|
|
|
659
674
|
if (override.rules && Object.keys(override.rules).length !== 0) {
|
|
660
675
|
result.rules = override.rules;
|
|
661
676
|
}
|
|
662
|
-
return result.rules || result.plugins || result.jsPlugins || result.env ? result : null;
|
|
677
|
+
return result.rules || result.plugins || result.jsPlugins || result.env || result.globals ? result : null;
|
|
663
678
|
}
|
|
664
679
|
|
|
665
680
|
// src/oxlint/index.ts
|
|
@@ -689,13 +704,24 @@ function defineOxlintConfig(options = {}) {
|
|
|
689
704
|
presets.react,
|
|
690
705
|
defaultOxlintPresets.react
|
|
691
706
|
);
|
|
692
|
-
const reactAgentRulesPreset = resolveRulePreset(
|
|
707
|
+
const reactAgentRulesPreset = resolveRulePreset(
|
|
708
|
+
presets.reactAgentRules,
|
|
709
|
+
false
|
|
710
|
+
);
|
|
693
711
|
const testPreset = resolveRulePreset(presets.test, defaultOxlintPresets.test);
|
|
694
712
|
const typeScriptPreset = resolveRulePreset(
|
|
695
713
|
presets.typescript,
|
|
696
714
|
defaultOxlintPresets.typescript
|
|
697
715
|
);
|
|
698
716
|
const unicornPreset = resolveRulePreset(presets.unicorn, true);
|
|
717
|
+
const reactAgentRulesForSourceFiles = reactAgentRulesPreset.enabled ? mergeRules(
|
|
718
|
+
reactAgentRules,
|
|
719
|
+
reactAgentRulesPreset.rules,
|
|
720
|
+
pickRules(
|
|
721
|
+
options.rules,
|
|
722
|
+
(rule) => rule.startsWith("react-agent-rules/")
|
|
723
|
+
)
|
|
724
|
+
) : void 0;
|
|
699
725
|
const plugins = [];
|
|
700
726
|
const rules = mergeRules(
|
|
701
727
|
{
|
|
@@ -733,6 +759,13 @@ function defineOxlintConfig(options = {}) {
|
|
|
733
759
|
appendPlugin(plugins, "node");
|
|
734
760
|
}
|
|
735
761
|
const overrides = [];
|
|
762
|
+
if (reactAgentRulesPreset.enabled && reactAgentRulesForSourceFiles) {
|
|
763
|
+
overrides.push({
|
|
764
|
+
files: sourceFiles,
|
|
765
|
+
jsPlugins: [reactAgentRulesPlugin],
|
|
766
|
+
rules: reactAgentRulesForSourceFiles
|
|
767
|
+
});
|
|
768
|
+
}
|
|
736
769
|
if (javascriptPreset.enabled) {
|
|
737
770
|
overrides.push({
|
|
738
771
|
files: scriptFiles,
|
|
@@ -838,6 +871,8 @@ function defineOxlintConfig(options = {}) {
|
|
|
838
871
|
node: true,
|
|
839
872
|
...options.env ?? {}
|
|
840
873
|
},
|
|
874
|
+
extends: options.extends,
|
|
875
|
+
globals: options.globals,
|
|
841
876
|
ignorePatterns: ignorePreset.enabled ? dedupe([
|
|
842
877
|
...defaultIgnorePatterns,
|
|
843
878
|
...ignorePreset.patterns,
|
|
@@ -857,6 +892,12 @@ function defineOxlintConfig(options = {}) {
|
|
|
857
892
|
if (!config.ignorePatterns || config.ignorePatterns.length === 0) {
|
|
858
893
|
delete config.ignorePatterns;
|
|
859
894
|
}
|
|
895
|
+
if (!config.extends || config.extends.length === 0) {
|
|
896
|
+
delete config.extends;
|
|
897
|
+
}
|
|
898
|
+
if (!config.globals || Object.keys(config.globals).length === 0) {
|
|
899
|
+
delete config.globals;
|
|
900
|
+
}
|
|
860
901
|
if (!config.overrides || config.overrides.length === 0) {
|
|
861
902
|
delete config.overrides;
|
|
862
903
|
}
|
|
@@ -38,6 +38,14 @@ declare const plugin: {
|
|
|
38
38
|
CallExpression(node: CallExpressionNode): void;
|
|
39
39
|
};
|
|
40
40
|
};
|
|
41
|
+
'no-use-context': {
|
|
42
|
+
meta: {
|
|
43
|
+
schema: never[];
|
|
44
|
+
};
|
|
45
|
+
create(context: RuleContext): {
|
|
46
|
+
CallExpression(node: CallExpressionNode): void;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
41
49
|
};
|
|
42
50
|
};
|
|
43
51
|
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
// src/react-agent-rules.ts
|
|
2
2
|
var NO_MANUAL_MEMOIZATION_MESSAGE = "React Compiler automatically optimizes components and values, so manual memoization is not needed.";
|
|
3
3
|
var NO_FORWARD_REF_MESSAGE = "Starting in React 19, ref is a prop, so forwardRef is no longer needed.";
|
|
4
|
+
var NO_USE_CONTEXT_MESSAGE = "In React 19, use is preferred over useContext for reading context because it is more flexible.";
|
|
4
5
|
var EFFECT_EMPTY_DEPS_ONLY_MESSAGE = "Effects here must use an empty dependency array. Use them only for mount and unmount logic. For event-driven logic, use useEffectEvent inside the effect. Do not use effects as a watch mechanism.";
|
|
5
6
|
var manualMemoizationNames = /* @__PURE__ */ new Set(["memo", "useMemo", "useCallback"]);
|
|
6
7
|
var effectNames = /* @__PURE__ */ new Set(["useEffect", "useLayoutEffect"]);
|
|
7
8
|
var forwardRefNames = /* @__PURE__ */ new Set(["forwardRef"]);
|
|
9
|
+
var useContextNames = /* @__PURE__ */ new Set(["useContext"]);
|
|
8
10
|
function isRecord(node) {
|
|
9
11
|
return typeof node === "object" && node !== null;
|
|
10
12
|
}
|
|
@@ -57,6 +59,23 @@ var noForwardRefRule = {
|
|
|
57
59
|
};
|
|
58
60
|
}
|
|
59
61
|
};
|
|
62
|
+
var noUseContextRule = {
|
|
63
|
+
meta: {
|
|
64
|
+
schema: []
|
|
65
|
+
},
|
|
66
|
+
create(context) {
|
|
67
|
+
return {
|
|
68
|
+
CallExpression(node) {
|
|
69
|
+
if (isNamedIdentifier(node.callee, useContextNames) || isReactMember(node.callee, useContextNames)) {
|
|
70
|
+
context.report({
|
|
71
|
+
message: NO_USE_CONTEXT_MESSAGE,
|
|
72
|
+
node
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
};
|
|
60
79
|
var effectEmptyDepsOnlyRule = {
|
|
61
80
|
meta: {
|
|
62
81
|
schema: []
|
|
@@ -85,7 +104,8 @@ var plugin = {
|
|
|
85
104
|
rules: {
|
|
86
105
|
"effect-empty-deps-only": effectEmptyDepsOnlyRule,
|
|
87
106
|
"no-forward-ref": noForwardRefRule,
|
|
88
|
-
"no-manual-memoization": noManualMemoizationRule
|
|
107
|
+
"no-manual-memoization": noManualMemoizationRule,
|
|
108
|
+
"no-use-context": noUseContextRule
|
|
89
109
|
}
|
|
90
110
|
};
|
|
91
111
|
var react_agent_rules_default = plugin;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhangyu1818/oxlint-config",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Native Oxlint and Oxfmt config preset package",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"oxc",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"repository": {
|
|
13
13
|
"type": "git",
|
|
14
|
-
"url": "https://github.com/zhangyu1818/oxlint-config.git"
|
|
14
|
+
"url": "git+https://github.com/zhangyu1818/oxlint-config.git"
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
17
|
"dist"
|
|
@@ -25,35 +25,35 @@
|
|
|
25
25
|
"import": "./dist/index.js"
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
|
-
"scripts": {
|
|
29
|
-
"build": "tsup",
|
|
30
|
-
"format": "oxfmt -c oxfmt.config.ts .",
|
|
31
|
-
"format:check": "oxfmt --check -c oxfmt.config.ts .",
|
|
32
|
-
"lint": "oxlint",
|
|
33
|
-
"lint:fix": "oxlint --fix",
|
|
34
|
-
"test": "vitest --run",
|
|
35
|
-
"test:watch": "vitest",
|
|
36
|
-
"tsc:check": "tsc"
|
|
37
|
-
},
|
|
38
28
|
"dependencies": {
|
|
39
|
-
"local-pkg": "^1.1
|
|
29
|
+
"local-pkg": "^1.2.1"
|
|
40
30
|
},
|
|
41
31
|
"devDependencies": {
|
|
42
|
-
"@types/node": "^25.
|
|
43
|
-
"oxfmt": "^0.
|
|
44
|
-
"oxlint": "^1.
|
|
45
|
-
"oxlint-tsgolint": "^0.
|
|
32
|
+
"@types/node": "^25.9.3",
|
|
33
|
+
"oxfmt": "^0.54.0",
|
|
34
|
+
"oxlint": "^1.69.0",
|
|
35
|
+
"oxlint-tsgolint": "^0.23.0",
|
|
46
36
|
"tsup": "^8.5.1",
|
|
47
|
-
"typescript": "^
|
|
48
|
-
"vitest": "^4.1.
|
|
37
|
+
"typescript": "^6.0.3",
|
|
38
|
+
"vitest": "^4.1.8"
|
|
49
39
|
},
|
|
50
40
|
"peerDependencies": {
|
|
51
|
-
"oxfmt": "^0.
|
|
52
|
-
"oxlint": "^1.
|
|
53
|
-
"oxlint-tsgolint": "^0.
|
|
41
|
+
"oxfmt": "^0.54.0",
|
|
42
|
+
"oxlint": "^1.69.0",
|
|
43
|
+
"oxlint-tsgolint": "^0.23.0"
|
|
54
44
|
},
|
|
55
45
|
"engines": {
|
|
56
|
-
"node": "
|
|
46
|
+
"node": ">=24"
|
|
57
47
|
},
|
|
58
|
-
"
|
|
59
|
-
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsup",
|
|
50
|
+
"format": "oxfmt -c oxfmt.config.ts .",
|
|
51
|
+
"format:check": "oxfmt --check -c oxfmt.config.ts .",
|
|
52
|
+
"lint": "oxlint -c oxlint.config.ts",
|
|
53
|
+
"lint:fix": "oxlint --fix -c oxlint.config.ts",
|
|
54
|
+
"test": "vitest --run",
|
|
55
|
+
"test:smoke": "node tests/package-smoke.mjs",
|
|
56
|
+
"test:watch": "vitest",
|
|
57
|
+
"tsc:check": "tsc"
|
|
58
|
+
}
|
|
59
|
+
}
|