eslint-config-reverentgeek 6.1.1 → 6.3.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/.claude/settings.local.json +11 -0
- package/README.md +31 -65
- package/eslint.config.js +11 -2
- package/package.json +11 -7
- package/src/blog.js +16 -0
- package/{browser.js → src/browser.js} +5 -8
- package/src/common.js +32 -0
- package/src/esm.js +11 -0
- package/{index.js → src/index.js} +1 -1
- package/{node-esm.js → src/node-esm.js} +5 -7
- package/{node.js → src/node.js} +6 -9
- package/src/react.js +13 -0
- package/test/blog.test.js +19 -0
- package/test/browser.test.js +20 -0
- package/test/common.test.js +14 -0
- package/test/esm.test.js +18 -0
- package/test/index.test.js +74 -0
- package/test/merge.test.js +393 -0
- package/test/node-esm.test.js +12 -0
- package/test/node.test.js +16 -0
- package/test/react.test.js +18 -0
- package/test/test-helpers.js +146 -0
- package/blog.js +0 -18
- package/common.js +0 -36
- package/esm.js +0 -9
- package/react.js +0 -12
- /package/{utils.js → src/utils.js} +0 -0
package/README.md
CHANGED
|
@@ -17,68 +17,44 @@ This package is [ReverentGeek's](https://reverentgeek.com/about/) preferred conf
|
|
|
17
17
|
```js
|
|
18
18
|
"use strict";
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
const
|
|
20
|
+
const defineConfig = require( "eslint/config" ).defineConfig; // eslint-disable-line n/no-unpublished-require
|
|
21
|
+
const rg = require( "eslint-config-reverentgeek" ); // eslint-disable-line n/no-extraneous-require
|
|
22
22
|
|
|
23
|
-
module.exports = [
|
|
24
|
-
rgConfig.configs.common,
|
|
23
|
+
module.exports = defineConfig( [
|
|
25
24
|
{
|
|
25
|
+
extends: [ rg.configs.node ],
|
|
26
26
|
rules: {
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
-
];
|
|
29
|
+
] );
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
+
The _node_ config adds specific support for Node.js and CommonJS modules.
|
|
33
|
+
|
|
32
34
|
## Alternative Configs
|
|
33
35
|
|
|
34
36
|
The _node-esm_ config adds specific support for Node.js and ES modules (`import`/`export`).
|
|
35
37
|
|
|
36
38
|
```js
|
|
37
|
-
|
|
38
|
-
import rg from "eslint-config-reverentgeek";
|
|
39
|
+
import { defineConfig } from "eslint/config"; // eslint-disable-line n/no-unpublished-import
|
|
40
|
+
import rg from "eslint-config-reverentgeek"; // eslint-disable-line n/no-extraneous-import
|
|
39
41
|
|
|
40
|
-
export default
|
|
41
|
-
rg.configs["node-esm"],
|
|
42
|
-
{
|
|
43
|
-
rules: {
|
|
44
|
-
}
|
|
42
|
+
export default defineConfig( {
|
|
43
|
+
extends: [ rg.configs["node-esm"] ],
|
|
44
|
+
rules: {
|
|
45
45
|
}
|
|
46
|
-
|
|
46
|
+
} );
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
The _blog_ config changes the code style to two-spaced indentions, which is better for copying code samples to blog posts.
|
|
50
50
|
|
|
51
51
|
```js
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
/* eslint-disable-next-line n/no-unpublished-require */
|
|
55
|
-
const rgConfig = require( "eslint-config-reverentgeek" );
|
|
56
|
-
|
|
57
|
-
module.exports = [
|
|
58
|
-
rgConfig.configs.browser,
|
|
59
|
-
rgConfig.configs.blog,
|
|
60
|
-
{
|
|
61
|
-
rules: {
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
];
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
The _node_ config adds specific support for Node.js and CommonJS modules.
|
|
68
|
-
|
|
69
|
-
```js
|
|
70
|
-
"use strict";
|
|
71
|
-
|
|
72
|
-
/* eslint-disable-next-line n/no-unpublished-require */
|
|
73
|
-
const rgConfig = require( "eslint-config-reverentgeek" );
|
|
52
|
+
import { defineConfig } from "eslint/config";
|
|
53
|
+
import rg from "eslint-config-reverentgeek";
|
|
74
54
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
rules: {
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
];
|
|
55
|
+
export default defineConfig( {
|
|
56
|
+
extends: [ rg.configs.browser, rg.configs.blog ]
|
|
57
|
+
} );
|
|
82
58
|
```
|
|
83
59
|
|
|
84
60
|
The _react_ config adds specific support for React, browser, and ES modules (`import`/`export`).
|
|
@@ -88,39 +64,29 @@ npm install --save-dev eslint-plugin-react
|
|
|
88
64
|
```
|
|
89
65
|
|
|
90
66
|
```js
|
|
91
|
-
|
|
67
|
+
import { defineConfig } from "eslint/config";
|
|
92
68
|
import rg from "eslint-config-reverentgeek";
|
|
93
|
-
/* eslint-disable-next-line n/no-unpublished-import */
|
|
94
69
|
import react from "eslint-plugin-react";
|
|
95
70
|
|
|
96
|
-
export default
|
|
97
|
-
rg.configs.browser,
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
},
|
|
103
|
-
rules: {
|
|
104
|
-
}
|
|
71
|
+
export default defineConfig( {
|
|
72
|
+
extends: [ rg.configs.browser, rg.configs.react ],
|
|
73
|
+
plugins: {
|
|
74
|
+
react
|
|
75
|
+
},
|
|
76
|
+
rules: {
|
|
105
77
|
}
|
|
106
|
-
|
|
78
|
+
} );
|
|
107
79
|
```
|
|
108
80
|
|
|
109
81
|
The _browser_ config sets the `browser` environment and adds ES module support.
|
|
110
82
|
|
|
111
83
|
```js
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
/* eslint-disable-next-line n/no-unpublished-require */
|
|
115
|
-
const rgConfig = require( "eslint-config-reverentgeek" );
|
|
84
|
+
import { defineConfig } from "eslint/config";
|
|
85
|
+
import rg from "eslint-config-reverentgeek";
|
|
116
86
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
rules: {
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
];
|
|
87
|
+
export default defineConfig( {
|
|
88
|
+
extends: [ rg.configs.browser ]
|
|
89
|
+
} );
|
|
124
90
|
```
|
|
125
91
|
|
|
126
92
|
## Legacy .eslintrc.js support (eslint < v9.0)
|
package/eslint.config.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const
|
|
2
|
+
const defineConfig = require( "eslint/config" ).defineConfig; // eslint-disable-line n/no-unpublished-require
|
|
3
|
+
|
|
4
|
+
const node = require( "./src/node" );
|
|
3
5
|
|
|
4
6
|
const config = {
|
|
5
7
|
rules: {
|
|
@@ -12,5 +14,12 @@ const config = {
|
|
|
12
14
|
}
|
|
13
15
|
};
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
const testConfig = {
|
|
18
|
+
files: [ "test/**/*.js" ],
|
|
19
|
+
rules: {
|
|
20
|
+
"n/no-unsupported-features/node-builtins": "off"
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
module.exports = defineConfig( [ node, config, testConfig ] );
|
|
16
25
|
|
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-config-reverentgeek",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.3.0",
|
|
4
4
|
"description": "ESLint rules that ReverentGeek likes :)",
|
|
5
|
-
"main": "index.js",
|
|
5
|
+
"main": "src/index.js",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "git+https://github.com/reverentgeek/eslint-config-reverentgeek.git"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
|
-
"lint": "eslint ./ --fix"
|
|
11
|
+
"lint": "eslint ./ --fix",
|
|
12
|
+
"test": "node --test --experimental-test-coverage test/*.js"
|
|
12
13
|
},
|
|
13
14
|
"keywords": [
|
|
14
15
|
"lint",
|
|
@@ -18,11 +19,14 @@
|
|
|
18
19
|
"author": "David Neal <david@reverentgeek.com> (https://reverentgeek.com)",
|
|
19
20
|
"license": "MIT",
|
|
20
21
|
"dependencies": {
|
|
21
|
-
"@stylistic/eslint-plugin": "^5.
|
|
22
|
-
"eslint-plugin-n": "^17.
|
|
23
|
-
"globals": "^16.
|
|
22
|
+
"@stylistic/eslint-plugin": "^5.4.0",
|
|
23
|
+
"eslint-plugin-n": "^17.23.1",
|
|
24
|
+
"globals": "^16.4.0"
|
|
24
25
|
},
|
|
25
26
|
"devDependencies": {
|
|
26
|
-
"eslint": "^9.
|
|
27
|
+
"eslint": "^9.36.0"
|
|
28
|
+
},
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=18.0.0"
|
|
27
31
|
}
|
|
28
32
|
}
|
package/src/blog.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const defineConfig = require( "eslint/config" ).defineConfig; // eslint-disable-line n/no-unpublished-require
|
|
4
|
+
const styles = require( "@stylistic/eslint-plugin" );
|
|
5
|
+
|
|
6
|
+
module.exports = defineConfig( {
|
|
7
|
+
name: "blog",
|
|
8
|
+
plugins: {
|
|
9
|
+
"@stylistic": styles
|
|
10
|
+
},
|
|
11
|
+
rules: {
|
|
12
|
+
"no-console": [ "off" ],
|
|
13
|
+
"@stylistic/indent": [ "error", 2 ]
|
|
14
|
+
}
|
|
15
|
+
} );
|
|
16
|
+
|
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
const defineConfig = require( "eslint/config" ).defineConfig; // eslint-disable-line n/no-unpublished-require
|
|
2
3
|
const globals = require( "globals" );
|
|
3
4
|
const common = require( "./common" );
|
|
4
|
-
const { merge } = require( "./utils" );
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
module.exports = defineConfig( {
|
|
7
|
+
name: "browser",
|
|
8
|
+
extends: [ common ],
|
|
7
9
|
languageOptions: {
|
|
8
10
|
ecmaVersion: "latest",
|
|
9
11
|
sourceType: "module",
|
|
10
12
|
globals: globals.browser
|
|
11
|
-
},
|
|
12
|
-
rules: {
|
|
13
13
|
}
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
module.exports = merge( common, config );
|
|
17
|
-
|
|
14
|
+
} );
|
package/src/common.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const defineConfig = require( "eslint/config" ).defineConfig; // eslint-disable-line n/no-unpublished-require
|
|
4
|
+
|
|
5
|
+
const eslint = require( "@eslint/js" );
|
|
6
|
+
const styles = require( "@stylistic/eslint-plugin" );
|
|
7
|
+
|
|
8
|
+
module.exports = defineConfig( {
|
|
9
|
+
name: "common",
|
|
10
|
+
extends: [ eslint.configs.recommended, styles.configs.recommended ],
|
|
11
|
+
rules: {
|
|
12
|
+
"no-console": [ "off" ],
|
|
13
|
+
"no-var": [ "error" ],
|
|
14
|
+
"@stylistic/array-bracket-spacing": [ "error", "always", { singleValue: true } ],
|
|
15
|
+
"@stylistic/brace-style": [ "error", "1tbs" ],
|
|
16
|
+
"@stylistic/comma-dangle": [ "error", "never" ],
|
|
17
|
+
"@stylistic/comma-spacing": [ "error", { before: false, after: true } ],
|
|
18
|
+
"@stylistic/eol-last": [ "error", "always" ],
|
|
19
|
+
"@stylistic/indent": [ "error", "tab" ],
|
|
20
|
+
"@stylistic/linebreak-style": [ "error", "unix" ],
|
|
21
|
+
"@stylistic/no-multiple-empty-lines": [ "error", { max: 1 } ],
|
|
22
|
+
"@stylistic/no-tabs": [ "error", { allowIndentationTabs: true } ],
|
|
23
|
+
"@stylistic/no-trailing-spaces": [ "error", { skipBlankLines: false, ignoreComments: false } ],
|
|
24
|
+
"@stylistic/object-curly-spacing": [ "error", "always" ],
|
|
25
|
+
"@stylistic/quote-props": [ "error", "as-needed" ],
|
|
26
|
+
"@stylistic/quotes": [ "error", "double" ],
|
|
27
|
+
"@stylistic/semi": [ "error", "always" ],
|
|
28
|
+
"@stylistic/space-in-parens": [ "error", "always" ],
|
|
29
|
+
"@stylistic/template-curly-spacing": [ "error", "always" ]
|
|
30
|
+
}
|
|
31
|
+
} );
|
|
32
|
+
|
package/src/esm.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const defineConfig = require( "eslint/config" ).defineConfig; // eslint-disable-line n/no-unpublished-require
|
|
3
|
+
|
|
4
|
+
module.exports = defineConfig( {
|
|
5
|
+
name: "esm",
|
|
6
|
+
languageOptions: {
|
|
7
|
+
ecmaVersion: "latest",
|
|
8
|
+
sourceType: "module"
|
|
9
|
+
}
|
|
10
|
+
} );
|
|
11
|
+
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
const defineConfig = require( "eslint/config" ).defineConfig; // eslint-disable-line n/no-unpublished-require
|
|
2
3
|
const common = require( "./common" );
|
|
3
4
|
const nodePlugin = require( "eslint-plugin-n" );
|
|
4
5
|
const nodeRecommended = nodePlugin.configs["flat/recommended-module"];
|
|
5
|
-
const { merge } = require( "./utils" );
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
name: "
|
|
7
|
+
module.exports = defineConfig( {
|
|
8
|
+
name: "node-esm",
|
|
9
|
+
extends: [ common, nodeRecommended ],
|
|
9
10
|
languageOptions: {
|
|
10
11
|
sourceType: "module"
|
|
11
12
|
},
|
|
12
13
|
rules: {
|
|
13
14
|
"n/exports-style": [ "error" ]
|
|
14
15
|
}
|
|
15
|
-
};
|
|
16
|
-
const merged = merge( common, nodeRecommended, config );
|
|
17
|
-
|
|
18
|
-
module.exports = merged;
|
|
16
|
+
} );
|
|
19
17
|
|
package/{node.js → src/node.js}
RENAMED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
|
|
2
2
|
"use strict";
|
|
3
|
+
|
|
4
|
+
const defineConfig = require( "eslint/config" ).defineConfig; // eslint-disable-line n/no-unpublished-require
|
|
3
5
|
const common = require( "./common" );
|
|
4
6
|
const nodePlugin = require( "eslint-plugin-n" );
|
|
5
7
|
const nodeRecommended = nodePlugin.configs["flat/recommended-script"];
|
|
6
|
-
const { merge } = require( "./utils" );
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
name: "
|
|
9
|
+
module.exports = defineConfig( {
|
|
10
|
+
name: "node-commonjs",
|
|
11
|
+
extends: [ common, nodeRecommended ],
|
|
10
12
|
languageOptions: {
|
|
11
13
|
sourceType: "commonjs"
|
|
12
14
|
},
|
|
@@ -14,9 +16,4 @@ const config = {
|
|
|
14
16
|
strict: [ "error", "global" ],
|
|
15
17
|
"n/exports-style": [ "error" ]
|
|
16
18
|
}
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const merged = merge( common, nodeRecommended, config );
|
|
20
|
-
|
|
21
|
-
module.exports = merged;
|
|
22
|
-
|
|
19
|
+
} );
|
package/src/react.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const defineConfig = require( "eslint/config" ).defineConfig; // eslint-disable-line n/no-unpublished-require
|
|
3
|
+
|
|
4
|
+
module.exports = defineConfig( {
|
|
5
|
+
name: "react",
|
|
6
|
+
languageOptions: {
|
|
7
|
+
parserOptions: {
|
|
8
|
+
ecmaFeatures: {
|
|
9
|
+
jsx: true
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
} );
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { test, describe } = require( "node:test" );
|
|
4
|
+
const assert = require( "node:assert" );
|
|
5
|
+
const { testBasicConfigStructure, testHasPlugins, getConfig } = require( "./test-helpers.js" );
|
|
6
|
+
|
|
7
|
+
describe( "blog config", () => {
|
|
8
|
+
const blogConfig = getConfig( "blog" );
|
|
9
|
+
|
|
10
|
+
testBasicConfigStructure( "blog", blogConfig );
|
|
11
|
+
|
|
12
|
+
test( "should use 2-space indentation", () => {
|
|
13
|
+
const indentRule = blogConfig.rules["@stylistic/indent"];
|
|
14
|
+
assert.ok( indentRule, "Should have indent rule" );
|
|
15
|
+
assert.strictEqual( indentRule[1], 2, "Should use 2-space indentation" );
|
|
16
|
+
} );
|
|
17
|
+
|
|
18
|
+
testHasPlugins( blogConfig, [ "@stylistic" ] );
|
|
19
|
+
} );
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { test, describe } = require( "node:test" );
|
|
4
|
+
const assert = require( "node:assert" );
|
|
5
|
+
const { testBasicConfigStructure, testLanguageOptions, getConfig } = require( "./test-helpers.js" );
|
|
6
|
+
|
|
7
|
+
describe( "browser config", () => {
|
|
8
|
+
const browserConfig = getConfig( "browser" );
|
|
9
|
+
|
|
10
|
+
testBasicConfigStructure( "browser", browserConfig );
|
|
11
|
+
|
|
12
|
+
testLanguageOptions( browserConfig, "module", true );
|
|
13
|
+
|
|
14
|
+
test( "should have browser globals", () => {
|
|
15
|
+
assert.ok( browserConfig.languageOptions.globals, "Should have globals" );
|
|
16
|
+
assert.ok( Object.prototype.hasOwnProperty.call( browserConfig.languageOptions.globals, "window" ), "Should have window global" );
|
|
17
|
+
assert.ok( Object.prototype.hasOwnProperty.call( browserConfig.languageOptions.globals, "document" ), "Should have document global" );
|
|
18
|
+
assert.ok( Object.prototype.hasOwnProperty.call( browserConfig.languageOptions.globals, "console" ), "Should have console global" );
|
|
19
|
+
} );
|
|
20
|
+
} );
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { describe } = require( "node:test" );
|
|
4
|
+
const { testBasicConfigStructure, testHasRules, testHasPlugins, getConfig } = require( "./test-helpers.js" );
|
|
5
|
+
|
|
6
|
+
describe( "common config", () => {
|
|
7
|
+
const commonConfig = getConfig( "common" );
|
|
8
|
+
|
|
9
|
+
testBasicConfigStructure( "common", commonConfig );
|
|
10
|
+
|
|
11
|
+
testHasRules( commonConfig, [ "@stylistic/indent", "@stylistic/quotes", "@stylistic/semi", "@stylistic/brace-style" ] );
|
|
12
|
+
|
|
13
|
+
testHasPlugins( commonConfig, [ "@stylistic" ] );
|
|
14
|
+
} );
|
package/test/esm.test.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { test, describe } = require( "node:test" );
|
|
4
|
+
const assert = require( "node:assert" );
|
|
5
|
+
const { testBasicConfigStructure, testLanguageOptions, getConfig } = require( "./test-helpers.js" );
|
|
6
|
+
|
|
7
|
+
describe( "esm config", () => {
|
|
8
|
+
const esmConfig = getConfig( "esm" );
|
|
9
|
+
|
|
10
|
+
testBasicConfigStructure( "esm", esmConfig );
|
|
11
|
+
|
|
12
|
+
testLanguageOptions( esmConfig, "module" );
|
|
13
|
+
|
|
14
|
+
test( "should have latest ecmaVersion", () => {
|
|
15
|
+
assert.ok( esmConfig.languageOptions, "Should have languageOptions" );
|
|
16
|
+
assert.strictEqual( esmConfig.languageOptions.ecmaVersion, "latest", "Should use latest ecmaVersion" );
|
|
17
|
+
} );
|
|
18
|
+
} );
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { test, describe } = require( "node:test" );
|
|
4
|
+
const assert = require( "node:assert" );
|
|
5
|
+
const pkg = require( "../package.json" );
|
|
6
|
+
const configModule = require( "../src/index.js" );
|
|
7
|
+
const { expectedNames, getConfig } = require( "./test-helpers.js" );
|
|
8
|
+
|
|
9
|
+
describe( "eslint-config-reverentgeek", () => {
|
|
10
|
+
test( "should export meta information", () => {
|
|
11
|
+
assert.ok( configModule.meta, "Meta object should exist" );
|
|
12
|
+
assert.strictEqual( configModule.meta.name, pkg.name, "Meta name should match package name" );
|
|
13
|
+
assert.strictEqual( configModule.meta.version, pkg.version, "Meta version should match package version" );
|
|
14
|
+
} );
|
|
15
|
+
|
|
16
|
+
test( "should export configs object", () => {
|
|
17
|
+
assert.ok( configModule.configs, "Configs object should exist" );
|
|
18
|
+
assert.strictEqual( typeof configModule.configs, "object", "Configs should be an object" );
|
|
19
|
+
} );
|
|
20
|
+
|
|
21
|
+
describe( "configs", () => {
|
|
22
|
+
const expectedConfigs = [ "common", "blog", "browser", "node", "node-esm", "esm", "react" ];
|
|
23
|
+
|
|
24
|
+
test( "should have all expected configs", () => {
|
|
25
|
+
expectedConfigs.forEach( ( configName ) => {
|
|
26
|
+
assert.ok( configModule.configs[configName], `Config ${ configName } should exist` );
|
|
27
|
+
} );
|
|
28
|
+
} );
|
|
29
|
+
} );
|
|
30
|
+
|
|
31
|
+
describe( "config structure validation", () => {
|
|
32
|
+
test( "all configs should be valid objects", () => {
|
|
33
|
+
const configNames = Object.keys( configModule.configs );
|
|
34
|
+
|
|
35
|
+
for ( const configName of configNames ) {
|
|
36
|
+
const config = configModule.configs[configName];
|
|
37
|
+
|
|
38
|
+
assert.ok( config, `${ configName } config should exist` );
|
|
39
|
+
assert.strictEqual( typeof config, "object", `${ configName } config should be an object` );
|
|
40
|
+
|
|
41
|
+
if ( config.rules ) {
|
|
42
|
+
assert.strictEqual( typeof config.rules, "object", `${ configName } config rules should be an object` );
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if ( config.plugins ) {
|
|
46
|
+
assert.strictEqual( typeof config.plugins, "object", `${ configName } config plugins should be an object` );
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if ( config.languageOptions ) {
|
|
50
|
+
assert.strictEqual( typeof config.languageOptions, "object", `${ configName } config languageOptions should be an object` );
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
} );
|
|
54
|
+
|
|
55
|
+
test( "all configs should have correct names", () => {
|
|
56
|
+
for ( const [ configName, expectedName ] of Object.entries( expectedNames ) ) {
|
|
57
|
+
const config = getConfig( configName );
|
|
58
|
+
assert.ok( config.name, `${ configName } config should have a name property` );
|
|
59
|
+
assert.strictEqual( typeof config.name, "string", `${ configName } config name should be a string` );
|
|
60
|
+
assert.strictEqual( config.name, expectedName, `${ configName } config should have correct name` );
|
|
61
|
+
}
|
|
62
|
+
} );
|
|
63
|
+
|
|
64
|
+
test( "configs should not be empty objects", () => {
|
|
65
|
+
const configNames = Object.keys( configModule.configs );
|
|
66
|
+
|
|
67
|
+
for ( const configName of configNames ) {
|
|
68
|
+
const config = configModule.configs[configName];
|
|
69
|
+
const keys = Object.keys( config );
|
|
70
|
+
assert.ok( keys.length > 0, `${ configName } config should not be empty` );
|
|
71
|
+
}
|
|
72
|
+
} );
|
|
73
|
+
} );
|
|
74
|
+
} );
|
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { test, describe } = require( "node:test" );
|
|
4
|
+
const assert = require( "node:assert" );
|
|
5
|
+
const { merge } = require( "../src/utils.js" );
|
|
6
|
+
|
|
7
|
+
describe( "merge function", () => {
|
|
8
|
+
describe( "basic functionality", () => {
|
|
9
|
+
test( "should merge two configs", () => {
|
|
10
|
+
const config1 = {
|
|
11
|
+
name: "config1",
|
|
12
|
+
plugins: { plugin1: "plugin1-content" },
|
|
13
|
+
languageOptions: {
|
|
14
|
+
sourceType: "script",
|
|
15
|
+
globals: { global1: true }
|
|
16
|
+
},
|
|
17
|
+
rules: { rule1: "error" }
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const config2 = {
|
|
21
|
+
name: "config2",
|
|
22
|
+
plugins: { plugin2: "plugin2-content" },
|
|
23
|
+
languageOptions: {
|
|
24
|
+
sourceType: "module",
|
|
25
|
+
globals: { global2: false }
|
|
26
|
+
},
|
|
27
|
+
rules: { rule2: "warn" }
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const result = merge( config1, config2 );
|
|
31
|
+
|
|
32
|
+
assert.strictEqual( result.name, "config2", "Should use the last config's name" );
|
|
33
|
+
assert.deepStrictEqual( result.plugins, {
|
|
34
|
+
plugin1: "plugin1-content",
|
|
35
|
+
plugin2: "plugin2-content"
|
|
36
|
+
}, "Should merge plugins from both configs" );
|
|
37
|
+
assert.strictEqual( result.languageOptions.sourceType, "module", "Should use the last config's sourceType" );
|
|
38
|
+
assert.deepStrictEqual( result.languageOptions.globals, {
|
|
39
|
+
global1: true,
|
|
40
|
+
global2: false
|
|
41
|
+
}, "Should merge globals from both configs" );
|
|
42
|
+
assert.deepStrictEqual( result.rules, {
|
|
43
|
+
rule1: "error",
|
|
44
|
+
rule2: "warn"
|
|
45
|
+
}, "Should merge rules from both configs" );
|
|
46
|
+
} );
|
|
47
|
+
|
|
48
|
+
test( "should merge three configs", () => {
|
|
49
|
+
const config1 = {
|
|
50
|
+
name: "config1",
|
|
51
|
+
plugins: { plugin1: "plugin1-content" },
|
|
52
|
+
languageOptions: {
|
|
53
|
+
sourceType: "script",
|
|
54
|
+
globals: { global1: true }
|
|
55
|
+
},
|
|
56
|
+
rules: { rule1: "error" }
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const config2 = {
|
|
60
|
+
name: "config2",
|
|
61
|
+
plugins: { plugin2: "plugin2-content" },
|
|
62
|
+
languageOptions: {
|
|
63
|
+
sourceType: "module",
|
|
64
|
+
globals: { global2: false }
|
|
65
|
+
},
|
|
66
|
+
rules: { rule2: "warn" }
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const config3 = {
|
|
70
|
+
name: "config3",
|
|
71
|
+
plugins: { plugin3: "plugin3-content" },
|
|
72
|
+
languageOptions: {
|
|
73
|
+
sourceType: "commonjs",
|
|
74
|
+
globals: { global3: "readonly" }
|
|
75
|
+
},
|
|
76
|
+
rules: { rule3: "off" }
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const result = merge( config1, config2, config3 );
|
|
80
|
+
|
|
81
|
+
assert.strictEqual( result.name, "config3", "Should use the third config's name" );
|
|
82
|
+
assert.deepStrictEqual( result.plugins, {
|
|
83
|
+
plugin1: "plugin1-content",
|
|
84
|
+
plugin2: "plugin2-content",
|
|
85
|
+
plugin3: "plugin3-content"
|
|
86
|
+
}, "Should merge plugins from all three configs" );
|
|
87
|
+
assert.strictEqual( result.languageOptions.sourceType, "commonjs", "Should use the third config's sourceType" );
|
|
88
|
+
assert.deepStrictEqual( result.languageOptions.globals, {
|
|
89
|
+
global1: true,
|
|
90
|
+
global2: false,
|
|
91
|
+
global3: "readonly"
|
|
92
|
+
}, "Should merge globals from all three configs" );
|
|
93
|
+
assert.deepStrictEqual( result.rules, {
|
|
94
|
+
rule1: "error",
|
|
95
|
+
rule2: "warn",
|
|
96
|
+
rule3: "off"
|
|
97
|
+
}, "Should merge rules from all three configs" );
|
|
98
|
+
} );
|
|
99
|
+
} );
|
|
100
|
+
|
|
101
|
+
describe( "property override behavior", () => {
|
|
102
|
+
test( "should override properties in order - name", () => {
|
|
103
|
+
const config1 = { name: "first-name" };
|
|
104
|
+
const config2 = { name: "second-name" };
|
|
105
|
+
const config3 = { name: "third-name" };
|
|
106
|
+
|
|
107
|
+
const result = merge( config1, config2, config3 );
|
|
108
|
+
assert.strictEqual( result.name, "third-name", "Should use the last config's name" );
|
|
109
|
+
} );
|
|
110
|
+
|
|
111
|
+
test( "should override properties in order - plugins", () => {
|
|
112
|
+
const config1 = { plugins: { shared: "first-value", unique1: "value1" } };
|
|
113
|
+
const config2 = { plugins: { shared: "second-value", unique2: "value2" } };
|
|
114
|
+
const config3 = { plugins: { shared: "third-value", unique3: "value3" } };
|
|
115
|
+
|
|
116
|
+
const result = merge( config1, config2, config3 );
|
|
117
|
+
assert.deepStrictEqual( result.plugins, {
|
|
118
|
+
shared: "third-value",
|
|
119
|
+
unique1: "value1",
|
|
120
|
+
unique2: "value2",
|
|
121
|
+
unique3: "value3"
|
|
122
|
+
}, "Should override shared plugin with last value and include all unique plugins" );
|
|
123
|
+
} );
|
|
124
|
+
|
|
125
|
+
test( "should override properties in order - rules", () => {
|
|
126
|
+
const config1 = { rules: { "shared-rule": "error", rule1: "error" } };
|
|
127
|
+
const config2 = { rules: { "shared-rule": "warn", rule2: "warn" } };
|
|
128
|
+
const config3 = { rules: { "shared-rule": "off", rule3: "off" } };
|
|
129
|
+
|
|
130
|
+
const result = merge( config1, config2, config3 );
|
|
131
|
+
assert.deepStrictEqual( result.rules, {
|
|
132
|
+
"shared-rule": "off",
|
|
133
|
+
rule1: "error",
|
|
134
|
+
rule2: "warn",
|
|
135
|
+
rule3: "off"
|
|
136
|
+
}, "Should override shared rule with last value and include all unique rules" );
|
|
137
|
+
} );
|
|
138
|
+
|
|
139
|
+
test( "should override properties in order - globals", () => {
|
|
140
|
+
const config1 = {
|
|
141
|
+
languageOptions: {
|
|
142
|
+
globals: { shared: true, global1: true }
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
const config2 = {
|
|
146
|
+
languageOptions: {
|
|
147
|
+
globals: { shared: false, global2: false }
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
const config3 = {
|
|
151
|
+
languageOptions: {
|
|
152
|
+
globals: { shared: "readonly", global3: "readonly" }
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const result = merge( config1, config2, config3 );
|
|
157
|
+
assert.deepStrictEqual( result.languageOptions.globals, {
|
|
158
|
+
shared: "readonly",
|
|
159
|
+
global1: true,
|
|
160
|
+
global2: false,
|
|
161
|
+
global3: "readonly"
|
|
162
|
+
}, "Should override shared global with last value and include all unique globals" );
|
|
163
|
+
} );
|
|
164
|
+
|
|
165
|
+
test( "should override sourceType with last non-null value", () => {
|
|
166
|
+
const config1 = { languageOptions: { sourceType: "script" } };
|
|
167
|
+
const config2 = { languageOptions: { sourceType: "module" } };
|
|
168
|
+
const config3 = { languageOptions: { sourceType: "commonjs" } };
|
|
169
|
+
|
|
170
|
+
const result = merge( config1, config2, config3 );
|
|
171
|
+
assert.strictEqual( result.languageOptions.sourceType, "commonjs", "Should use the last sourceType" );
|
|
172
|
+
} );
|
|
173
|
+
} );
|
|
174
|
+
|
|
175
|
+
describe( "edge cases and null handling", () => {
|
|
176
|
+
test( "should handle empty configs", () => {
|
|
177
|
+
const config1 = {};
|
|
178
|
+
const config2 = {};
|
|
179
|
+
|
|
180
|
+
const result = merge( config1, config2 );
|
|
181
|
+
|
|
182
|
+
assert.strictEqual( result.name, undefined, "Should handle missing names" );
|
|
183
|
+
assert.deepStrictEqual( result.plugins, {}, "Should return empty plugins object" );
|
|
184
|
+
assert.strictEqual( result.languageOptions.sourceType, undefined, "Should handle missing sourceType" );
|
|
185
|
+
assert.deepStrictEqual( result.languageOptions.globals, {}, "Should return empty globals object" );
|
|
186
|
+
assert.deepStrictEqual( result.rules, {}, "Should return empty rules object" );
|
|
187
|
+
} );
|
|
188
|
+
|
|
189
|
+
test( "should handle null/undefined configs", () => {
|
|
190
|
+
const config1 = { name: "valid-config", rules: { rule1: "error" } };
|
|
191
|
+
const config2 = null;
|
|
192
|
+
const config3 = undefined;
|
|
193
|
+
const config4 = { name: "another-valid", rules: { rule2: "warn" } };
|
|
194
|
+
|
|
195
|
+
const result = merge( config1, config2, config3, config4 );
|
|
196
|
+
|
|
197
|
+
assert.strictEqual( result.name, "another-valid", "Should skip null/undefined configs for name" );
|
|
198
|
+
assert.deepStrictEqual( result.rules, {
|
|
199
|
+
rule1: "error",
|
|
200
|
+
rule2: "warn"
|
|
201
|
+
}, "Should skip null/undefined configs for rules" );
|
|
202
|
+
} );
|
|
203
|
+
|
|
204
|
+
test( "should handle configs with missing properties", () => {
|
|
205
|
+
const config1 = { name: "config1" }; // No plugins, languageOptions, or rules
|
|
206
|
+
const config2 = { rules: { rule1: "error" } }; // No name, plugins, or languageOptions
|
|
207
|
+
const config3 = { plugins: { plugin1: "content" } }; // No name, languageOptions, or rules
|
|
208
|
+
|
|
209
|
+
const result = merge( config1, config2, config3 );
|
|
210
|
+
|
|
211
|
+
assert.strictEqual( result.name, "config1", "Should use available name" );
|
|
212
|
+
assert.deepStrictEqual( result.plugins, { plugin1: "content" }, "Should use available plugins" );
|
|
213
|
+
assert.deepStrictEqual( result.rules, { rule1: "error" }, "Should use available rules" );
|
|
214
|
+
assert.deepStrictEqual( result.languageOptions.globals, {}, "Should create empty globals" );
|
|
215
|
+
} );
|
|
216
|
+
|
|
217
|
+
test( "should handle configs with null languageOptions properties", () => {
|
|
218
|
+
const config1 = {
|
|
219
|
+
languageOptions: {
|
|
220
|
+
sourceType: null,
|
|
221
|
+
globals: null
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
const config2 = {
|
|
225
|
+
languageOptions: {
|
|
226
|
+
sourceType: "module",
|
|
227
|
+
globals: { window: true }
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
const result = merge( config1, config2 );
|
|
232
|
+
|
|
233
|
+
assert.strictEqual( result.languageOptions.sourceType, "module", "Should skip null sourceType" );
|
|
234
|
+
assert.deepStrictEqual( result.languageOptions.globals, { window: true }, "Should handle null globals" );
|
|
235
|
+
} );
|
|
236
|
+
|
|
237
|
+
test( "should handle single config", () => {
|
|
238
|
+
const config = {
|
|
239
|
+
name: "single-config",
|
|
240
|
+
plugins: { plugin1: "content" },
|
|
241
|
+
languageOptions: {
|
|
242
|
+
sourceType: "module",
|
|
243
|
+
globals: { window: true }
|
|
244
|
+
},
|
|
245
|
+
rules: { rule1: "error" }
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
const result = merge( config );
|
|
249
|
+
|
|
250
|
+
assert.deepStrictEqual( result, {
|
|
251
|
+
name: "single-config",
|
|
252
|
+
plugins: { plugin1: "content" },
|
|
253
|
+
languageOptions: {
|
|
254
|
+
sourceType: "module",
|
|
255
|
+
globals: { window: true }
|
|
256
|
+
},
|
|
257
|
+
rules: { rule1: "error" }
|
|
258
|
+
}, "Should return the single config as-is" );
|
|
259
|
+
} );
|
|
260
|
+
|
|
261
|
+
test( "should handle no configs", () => {
|
|
262
|
+
const result = merge();
|
|
263
|
+
|
|
264
|
+
assert.strictEqual( result.name, undefined, "Should handle no name" );
|
|
265
|
+
assert.deepStrictEqual( result.plugins, {}, "Should return empty plugins" );
|
|
266
|
+
assert.strictEqual( result.languageOptions.sourceType, undefined, "Should handle no sourceType" );
|
|
267
|
+
assert.deepStrictEqual( result.languageOptions.globals, {}, "Should return empty globals" );
|
|
268
|
+
assert.deepStrictEqual( result.rules, {}, "Should return empty rules" );
|
|
269
|
+
} );
|
|
270
|
+
} );
|
|
271
|
+
|
|
272
|
+
describe( "complex merging scenarios", () => {
|
|
273
|
+
test( "should handle nested rule configurations", () => {
|
|
274
|
+
const config1 = {
|
|
275
|
+
rules: {
|
|
276
|
+
indent: [ "error", 2 ],
|
|
277
|
+
quotes: [ "error", "single" ]
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
const config2 = {
|
|
281
|
+
rules: {
|
|
282
|
+
indent: [ "error", 4 ],
|
|
283
|
+
semi: [ "error", "always" ]
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
const result = merge( config1, config2 );
|
|
288
|
+
|
|
289
|
+
assert.deepStrictEqual( result.rules, {
|
|
290
|
+
indent: [ "error", 4 ], // Should override with config2's value
|
|
291
|
+
quotes: [ "error", "single" ],
|
|
292
|
+
semi: [ "error", "always" ]
|
|
293
|
+
}, "Should properly override nested rule arrays" );
|
|
294
|
+
} );
|
|
295
|
+
|
|
296
|
+
test( "should handle complex plugin objects", () => {
|
|
297
|
+
const plugin1 = { rules: { "custom-rule-1": {} }, configs: { recommended: {} } };
|
|
298
|
+
const plugin2 = { rules: { "custom-rule-2": {} }, configs: { strict: {} } };
|
|
299
|
+
|
|
300
|
+
const config1 = { plugins: { "@custom/plugin1": plugin1 } };
|
|
301
|
+
const config2 = { plugins: { "@custom/plugin2": plugin2 } };
|
|
302
|
+
|
|
303
|
+
const result = merge( config1, config2 );
|
|
304
|
+
|
|
305
|
+
assert.deepStrictEqual( result.plugins, {
|
|
306
|
+
"@custom/plugin1": plugin1,
|
|
307
|
+
"@custom/plugin2": plugin2
|
|
308
|
+
}, "Should merge complex plugin objects" );
|
|
309
|
+
} );
|
|
310
|
+
|
|
311
|
+
test( "should handle mixed global types", () => {
|
|
312
|
+
const config1 = {
|
|
313
|
+
languageOptions: {
|
|
314
|
+
globals: {
|
|
315
|
+
window: true,
|
|
316
|
+
document: false,
|
|
317
|
+
console: "readonly"
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
const config2 = {
|
|
322
|
+
languageOptions: {
|
|
323
|
+
globals: {
|
|
324
|
+
document: true, // Override from false to true
|
|
325
|
+
process: "writable",
|
|
326
|
+
Buffer: false
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
const result = merge( config1, config2 );
|
|
332
|
+
|
|
333
|
+
assert.deepStrictEqual( result.languageOptions.globals, {
|
|
334
|
+
window: true,
|
|
335
|
+
document: true, // Should be overridden
|
|
336
|
+
console: "readonly",
|
|
337
|
+
process: "writable",
|
|
338
|
+
Buffer: false
|
|
339
|
+
}, "Should properly merge and override different global types" );
|
|
340
|
+
} );
|
|
341
|
+
} );
|
|
342
|
+
|
|
343
|
+
describe( "order of operations", () => {
|
|
344
|
+
test( "should demonstrate merge order with four configs", () => {
|
|
345
|
+
const base = { name: "base", rules: { "base-rule": "error" } };
|
|
346
|
+
const common = { name: "common", rules: { "common-rule": "warn", "base-rule": "warn" } };
|
|
347
|
+
const specific = { name: "specific", rules: { "specific-rule": "off", "common-rule": "off" } };
|
|
348
|
+
const override = { name: "override", rules: { "override-rule": "error", "base-rule": "off" } };
|
|
349
|
+
|
|
350
|
+
const result = merge( base, common, specific, override );
|
|
351
|
+
|
|
352
|
+
assert.strictEqual( result.name, "override", "Should use the last config's name" );
|
|
353
|
+
assert.deepStrictEqual( result.rules, {
|
|
354
|
+
"base-rule": "off", // Overridden by 'override' config
|
|
355
|
+
"common-rule": "off", // Overridden by 'specific' config
|
|
356
|
+
"specific-rule": "off", // From 'specific' config
|
|
357
|
+
"override-rule": "error" // From 'override' config
|
|
358
|
+
}, "Should apply overrides in the correct order" );
|
|
359
|
+
} );
|
|
360
|
+
|
|
361
|
+
test( "should handle partial overrides correctly", () => {
|
|
362
|
+
const config1 = {
|
|
363
|
+
name: "config1",
|
|
364
|
+
plugins: { plugin1: "v1", shared: "v1" },
|
|
365
|
+
rules: { rule1: "error", shared: "error" }
|
|
366
|
+
};
|
|
367
|
+
const config2 = {
|
|
368
|
+
// No name - should keep config1's name
|
|
369
|
+
plugins: { plugin2: "v2", shared: "v2" }, // Override shared plugin
|
|
370
|
+
rules: { rule2: "warn" } // Don't override shared rule
|
|
371
|
+
};
|
|
372
|
+
const config3 = {
|
|
373
|
+
name: "config3", // Override name
|
|
374
|
+
// No plugins - keep merged plugins from config1 + config2
|
|
375
|
+
rules: { shared: "off" } // Override shared rule
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
const result = merge( config1, config2, config3 );
|
|
379
|
+
|
|
380
|
+
assert.strictEqual( result.name, "config3", "Should use config3's name" );
|
|
381
|
+
assert.deepStrictEqual( result.plugins, {
|
|
382
|
+
plugin1: "v1",
|
|
383
|
+
plugin2: "v2",
|
|
384
|
+
shared: "v2" // From config2
|
|
385
|
+
}, "Should keep merged plugins when config3 has none" );
|
|
386
|
+
assert.deepStrictEqual( result.rules, {
|
|
387
|
+
rule1: "error",
|
|
388
|
+
rule2: "warn",
|
|
389
|
+
shared: "off" // From config3
|
|
390
|
+
}, "Should override shared rule with config3's value" );
|
|
391
|
+
} );
|
|
392
|
+
} );
|
|
393
|
+
} );
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { describe } = require( "node:test" );
|
|
4
|
+
const { testBasicConfigStructure, testLanguageOptions, getConfig } = require( "./test-helpers.js" );
|
|
5
|
+
|
|
6
|
+
describe( "node-esm config", () => {
|
|
7
|
+
const nodeEsmConfig = getConfig( "node-esm" );
|
|
8
|
+
|
|
9
|
+
testBasicConfigStructure( "node-esm", nodeEsmConfig );
|
|
10
|
+
|
|
11
|
+
testLanguageOptions( nodeEsmConfig, "module" );
|
|
12
|
+
} );
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { describe } = require( "node:test" );
|
|
4
|
+
const { testBasicConfigStructure, testHasRules, testHasPlugins, testLanguageOptions, getConfig } = require( "./test-helpers.js" );
|
|
5
|
+
|
|
6
|
+
describe( "node config", () => {
|
|
7
|
+
const nodeConfig = getConfig( "node" );
|
|
8
|
+
|
|
9
|
+
testBasicConfigStructure( "node", nodeConfig );
|
|
10
|
+
|
|
11
|
+
testLanguageOptions( nodeConfig, "commonjs" );
|
|
12
|
+
|
|
13
|
+
testHasRules( nodeConfig, [ "strict", "n/exports-style" ] );
|
|
14
|
+
|
|
15
|
+
testHasPlugins( nodeConfig, [ "n" ] );
|
|
16
|
+
} );
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { test, describe } = require( "node:test" );
|
|
4
|
+
const assert = require( "node:assert" );
|
|
5
|
+
const { testBasicConfigStructure, getConfig } = require( "./test-helpers.js" );
|
|
6
|
+
|
|
7
|
+
describe( "react config", () => {
|
|
8
|
+
const reactConfig = getConfig( "react" );
|
|
9
|
+
|
|
10
|
+
testBasicConfigStructure( "react", reactConfig );
|
|
11
|
+
|
|
12
|
+
test( "should have JSX support", () => {
|
|
13
|
+
assert.ok( reactConfig.languageOptions, "Should have languageOptions" );
|
|
14
|
+
assert.ok( reactConfig.languageOptions.parserOptions, "Should have parserOptions" );
|
|
15
|
+
assert.ok( reactConfig.languageOptions.parserOptions.ecmaFeatures, "Should have ecmaFeatures" );
|
|
16
|
+
assert.ok( reactConfig.languageOptions.parserOptions.ecmaFeatures.jsx, "Should support JSX" );
|
|
17
|
+
} );
|
|
18
|
+
} );
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { test } = require( "node:test" );
|
|
4
|
+
const assert = require( "node:assert" );
|
|
5
|
+
const configModule = require( "../src/index.js" );
|
|
6
|
+
|
|
7
|
+
// Expected names for all configs
|
|
8
|
+
const expectedNames = {
|
|
9
|
+
common: "common",
|
|
10
|
+
blog: "blog",
|
|
11
|
+
browser: "browser",
|
|
12
|
+
node: "node-commonjs",
|
|
13
|
+
"node-esm": "node-esm",
|
|
14
|
+
esm: "esm",
|
|
15
|
+
react: "react"
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Common test helper to validate basic ESLint config structure
|
|
20
|
+
*/
|
|
21
|
+
function testBasicConfigStructure( configName, config ) {
|
|
22
|
+
test( "should be a valid ESLint config object", () => {
|
|
23
|
+
assert.ok( config, `${ configName } config should exist` );
|
|
24
|
+
assert.strictEqual( typeof config, "object", `${ configName } config should be an object` );
|
|
25
|
+
} );
|
|
26
|
+
|
|
27
|
+
test( "should have correct name", () => {
|
|
28
|
+
const expectedName = expectedNames[configName];
|
|
29
|
+
if ( expectedName ) {
|
|
30
|
+
assert.strictEqual( config.name, expectedName, "Should have correct config name" );
|
|
31
|
+
}
|
|
32
|
+
} );
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Test helper for validating rules exist
|
|
37
|
+
*/
|
|
38
|
+
function testHasRules( config, expectedRules = [] ) {
|
|
39
|
+
test( "should have rules", () => {
|
|
40
|
+
assert.ok( config.rules, "Should have rules object" );
|
|
41
|
+
assert.strictEqual( typeof config.rules, "object", "Rules should be an object" );
|
|
42
|
+
} );
|
|
43
|
+
|
|
44
|
+
if ( expectedRules.length > 0 ) {
|
|
45
|
+
test( "should have expected rules", () => {
|
|
46
|
+
const rules = config.rules;
|
|
47
|
+
expectedRules.forEach( ( ruleName ) => {
|
|
48
|
+
assert.ok( rules[ruleName], `Should have ${ ruleName } rule` );
|
|
49
|
+
} );
|
|
50
|
+
} );
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Test helper for validating plugins exist
|
|
56
|
+
*/
|
|
57
|
+
function testHasPlugins( config, expectedPlugins = [] ) {
|
|
58
|
+
test( "should have plugins", () => {
|
|
59
|
+
assert.ok( config.plugins, "Should have plugins object" );
|
|
60
|
+
assert.strictEqual( typeof config.plugins, "object", "Plugins should be an object" );
|
|
61
|
+
} );
|
|
62
|
+
|
|
63
|
+
if ( expectedPlugins.length > 0 ) {
|
|
64
|
+
test( "should have expected plugins", () => {
|
|
65
|
+
const plugins = config.plugins;
|
|
66
|
+
expectedPlugins.forEach( ( pluginName ) => {
|
|
67
|
+
assert.ok( plugins[pluginName], `Should have ${ pluginName } plugin` );
|
|
68
|
+
} );
|
|
69
|
+
} );
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Test helper for validating language options
|
|
75
|
+
*/
|
|
76
|
+
function testLanguageOptions( config, expectedSourceType, hasGlobals = false ) {
|
|
77
|
+
test( "should have correct language options", () => {
|
|
78
|
+
if ( expectedSourceType ) {
|
|
79
|
+
assert.ok( config.languageOptions, "Should have languageOptions" );
|
|
80
|
+
assert.strictEqual( config.languageOptions.sourceType, expectedSourceType, `Should use ${ expectedSourceType } sourceType` );
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if ( hasGlobals ) {
|
|
84
|
+
assert.ok( config.languageOptions.globals, "Should have globals" );
|
|
85
|
+
assert.strictEqual( typeof config.languageOptions.globals, "object", "Globals should be an object" );
|
|
86
|
+
}
|
|
87
|
+
} );
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Get a config from the main module
|
|
92
|
+
* Since configs are now arrays due to defineConfig, we need to handle them properly
|
|
93
|
+
*/
|
|
94
|
+
function getConfig( configName ) {
|
|
95
|
+
const configArray = configModule.configs[configName];
|
|
96
|
+
|
|
97
|
+
// If it's an array (which it should be with defineConfig), we need to get the effective config
|
|
98
|
+
if ( Array.isArray( configArray ) ) {
|
|
99
|
+
// For testing purposes, we'll merge all configs in the array to get the effective configuration
|
|
100
|
+
// This simulates what ESLint would do when processing the config
|
|
101
|
+
const merged = {
|
|
102
|
+
name: null,
|
|
103
|
+
plugins: {},
|
|
104
|
+
rules: {},
|
|
105
|
+
languageOptions: {}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
configArray.forEach( ( config ) => {
|
|
109
|
+
if ( config.name ) {
|
|
110
|
+
merged.name = config.name;
|
|
111
|
+
}
|
|
112
|
+
if ( config.plugins ) {
|
|
113
|
+
Object.assign( merged.plugins, config.plugins );
|
|
114
|
+
}
|
|
115
|
+
if ( config.rules ) {
|
|
116
|
+
Object.assign( merged.rules, config.rules );
|
|
117
|
+
}
|
|
118
|
+
if ( config.languageOptions ) {
|
|
119
|
+
Object.assign( merged.languageOptions, config.languageOptions );
|
|
120
|
+
}
|
|
121
|
+
} );
|
|
122
|
+
|
|
123
|
+
// Clean up empty objects
|
|
124
|
+
if ( Object.keys( merged.plugins ).length === 0 ) {
|
|
125
|
+
delete merged.plugins;
|
|
126
|
+
}
|
|
127
|
+
if ( Object.keys( merged.languageOptions ).length === 0 ) {
|
|
128
|
+
delete merged.languageOptions;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return merged;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Fallback for non-array configs (shouldn't happen with defineConfig)
|
|
135
|
+
return configArray;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
module.exports = {
|
|
139
|
+
configModule,
|
|
140
|
+
expectedNames,
|
|
141
|
+
testBasicConfigStructure,
|
|
142
|
+
testHasRules,
|
|
143
|
+
testHasPlugins,
|
|
144
|
+
testLanguageOptions,
|
|
145
|
+
getConfig
|
|
146
|
+
};
|
package/blog.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
async function createConfig() {
|
|
4
|
-
const styles = await import( "@stylistic/eslint-plugin" );
|
|
5
|
-
|
|
6
|
-
return {
|
|
7
|
-
plugins: {
|
|
8
|
-
"@stylistic": styles.default
|
|
9
|
-
},
|
|
10
|
-
rules: {
|
|
11
|
-
"no-console": [ "off" ],
|
|
12
|
-
"@stylistic/indent": [ "error", 2 ]
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
module.exports = createConfig();
|
|
18
|
-
|
package/common.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const eslint = require( "@eslint/js" );
|
|
4
|
-
const { merge } = require( "./utils" );
|
|
5
|
-
|
|
6
|
-
async function createConfig() {
|
|
7
|
-
const styles = await import( "@stylistic/eslint-plugin" );
|
|
8
|
-
|
|
9
|
-
const config = {
|
|
10
|
-
name: "reverentgeek-common",
|
|
11
|
-
rules: {
|
|
12
|
-
"no-console": [ "off" ],
|
|
13
|
-
"no-var": [ "error" ],
|
|
14
|
-
"@stylistic/array-bracket-spacing": [ "error", "always", { singleValue: true } ],
|
|
15
|
-
"@stylistic/brace-style": [ "error", "1tbs" ],
|
|
16
|
-
"@stylistic/comma-dangle": [ "error", "never" ],
|
|
17
|
-
"@stylistic/comma-spacing": [ "error", { before: false, after: true } ],
|
|
18
|
-
"@stylistic/eol-last": [ "error", "always" ],
|
|
19
|
-
"@stylistic/indent": [ "error", "tab" ],
|
|
20
|
-
"@stylistic/linebreak-style": [ "error", "unix" ],
|
|
21
|
-
"@stylistic/no-multiple-empty-lines": [ "error", { max: 1 } ],
|
|
22
|
-
"@stylistic/no-tabs": [ "error", { allowIndentationTabs: true } ],
|
|
23
|
-
"@stylistic/no-trailing-spaces": [ "error", { skipBlankLines: false, ignoreComments: false } ],
|
|
24
|
-
"@stylistic/object-curly-spacing": [ "error", "always" ],
|
|
25
|
-
"@stylistic/quote-props": [ "error", "as-needed" ],
|
|
26
|
-
"@stylistic/quotes": [ "error", "double" ],
|
|
27
|
-
"@stylistic/semi": [ "error", "always" ],
|
|
28
|
-
"@stylistic/space-in-parens": [ "error", "always" ],
|
|
29
|
-
"@stylistic/template-curly-spacing": [ "error", "always" ]
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
return merge( eslint.configs.recommended, styles.default.configs.recommended, config );
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
module.exports = createConfig();
|
package/esm.js
DELETED
package/react.js
DELETED
|
File without changes
|