Skip to content

Commit a7dda10

Browse files
committed
refactor!: simplify and flatten configurations
BREAKING CHANGE: Configurations are now returned as objects, like most shared ESLint configurations. The `make*Config` functions are no more. Also, everything is now exported through one file.
1 parent 329b4de commit a7dda10

File tree

8 files changed

+294
-378
lines changed

8 files changed

+294
-378
lines changed

README.md

+77-122
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,40 @@ Install the config along with its peer dependencies, `eslint` and `prettier`:
1212
npm install -D eslint-config-scratch eslint@^9 prettier@^3
1313
```
1414

15-
Add `eslint.config.mjs` to your project root (pick the `export` line appropriate for your project):
15+
Add `eslint.config.mjs` to your project root and, optionally, configure parser options for rules that require type
16+
information:
1617

1718
```js
1819
// myProjectRoot/eslint.config.mjs
19-
import { makeEslintConfig } from 'eslint-config-scratch'
20-
21-
// for a TypeScript project:
22-
export default makeEslintConfig({ globals: 'browser', tsconfigRootDir: import.meta.dirname })
20+
import { eslintConfigScratch } from 'eslint-config-scratch'
2321

2422
// for plain JavaScript:
25-
export default makeEslintConfig({ globals: 'browser' })
23+
export default eslintConfigScratch.recommended
24+
25+
// for a TypeScript project:
26+
export default eslintConfigScratch.config(
27+
eslintConfigScratch.recommended,
28+
{
29+
languageOptions: {
30+
parserOptions: {
31+
projectService: true,
32+
tsconfigRootDir: import.meta.dirname,
33+
},
34+
}
35+
},
36+
)
2637
```
2738

39+
The function `eslintConfigScratch.config` is a re-export of the `config` function from `typescript-eslint`, and helps
40+
with merging and extending configurations.
41+
2842
Add `prettier.config.mjs` to your project root as well:
2943

3044
```js
3145
// myProjectRoot/prettier.config.mjs
32-
import { makePrettierConfig } from 'eslint-config-scratch'
46+
import { prettierConfigScratch } from 'eslint-config-scratch'
3347

34-
export default makePrettierConfig()
48+
export default prettierConfigScratch.recommended
3549
```
3650

3751
Finally, add scripts like these to your `package.json`:
@@ -45,147 +59,88 @@ Finally, add scripts like these to your `package.json`:
4559

4660
## Basic Configuration
4761

48-
The `makeEslintConfig` function takes options to adjust the ESLint configuration object for your project. Most
49-
projects should start with something like this:
50-
51-
```mjs
52-
// myProjectRoot/eslint.config.mjs
53-
import { makeEslintConfig } from 'eslint-config-scratch'
54-
55-
export default makeEslintConfig({
56-
// Optional: specify global variables available in your environment
57-
globals: 'browser',
58-
59-
// Optional: enables rules that use type info, some of which work in JS too
60-
tsconfigRootDir: import.meta.dirname,
61-
})
62-
```
63-
64-
If you have no `tsconfig.json` (or `jsconfig.json`) in your project, you can skip the `tsconfigRootDir` option. Rules
65-
that require type information will be disabled or replaced with less strict alternatives that work without type info.
62+
The `eslintConfigScratch.config` is a re-export of the `config` function from `typescript-eslint`. Full documentation
63+
is available here: <https://typescript-eslint.io/packages/typescript-eslint#config>.
6664

67-
### Globals
65+
The `config` function can be used to add or override rules, plugins, and other configuration options. For example:
6866

69-
The `globals` property is optional. If present, it can take several forms:
70-
71-
- a string, interpreted as a key in the `globals` object exported by the `globals` package.
72-
- Examples: `'browser'`, `'node'`, `'es2021'`, `'jest'`, etc.
73-
- an object, set up as described in the "Specifying Globals" section of the [ESLint documentation](https://eslint.org/docs/latest/use/configure/language-options#using-configuration-files)
74-
- Example: `{ myGlobal: 'readonly', anotherGlobal: 'writable' }`
75-
- an array of zero or more of any mixture of the above
76-
77-
```mjs
78-
// myProjectRoot/eslint.config.mjs
79-
import { makeEslintConfig } from 'eslint-config-scratch'
80-
81-
export default makeEslintConfig({
82-
// Optional: enables rules that use type info, some of which work in JS too
83-
tsconfigRootDir: import.meta.dirname,
84-
85-
// Optional: specify global variables available in your environment
86-
// Warning: this is a very silly configuration
87-
globals: [
88-
'shared-node-browser',
89-
{
90-
fun: 'readonly',
91-
thing: false,
92-
},
93-
'es2021',
94-
{
95-
whyNot: 'writable',
96-
},
97-
],
98-
})
99-
```
100-
101-
### Further Customization
102-
103-
The first parameter to `makeEslintConfig` is covered above. Any further parameters passed to `makeEslintConfig` are
104-
appended to the resulting ESLint configuration array. This means you can customize your configuration further like
105-
this:
106-
107-
```mjs
108-
// myProjectRoot/eslint.config.mjs
109-
import { makeEslintConfig } from 'eslint-config-scratch'
110-
111-
export default makeEslintConfig(
112-
{
113-
// Optional: enables rules that use type info, some of which work in JS too
114-
tsconfigRootDir: import.meta.dirname,
115-
116-
// Optional: specify global variables available in your environment
117-
globals: 'browser',
118-
},
119-
// Add custom rules or overrides here
120-
{
121-
files: ['*.test.js'],
122-
rules: {
123-
'no-console': 'off', // Allow console logs in test files
124-
},
125-
},
126-
)
127-
```
128-
129-
You could concatenate more configuration objects onto the array returned by `makeEslintConfig` with equivalent
130-
results, but this approach offers better editor hints for autocomplete and type checking.
131-
132-
All ESLint configuration options are available this way. You can use this to handle globals yourself if the simplified
133-
`globals` configuration from above doesn't meet your needs:
134-
135-
```mjs
67+
```js
13668
// myProjectRoot/eslint.config.mjs
137-
import { makeEslintConfig } from 'eslint-config-scratch'
69+
import { eslintConfigScratch } from 'eslint-config-scratch'
70+
import { globalIgnores } from 'eslint/config'
13871
import globals from 'globals'
13972

140-
export default makeEslintConfig(
141-
{
142-
// Optional: enables rules that use type info, some of which work in JS too
143-
tsconfigRootDir: import.meta.dirname,
144-
},
145-
{
146-
files: ['src/main/**.js'],
147-
languageOptions: {
148-
globals: globals.node,
149-
},
150-
},
73+
export default eslintConfigScratch.config(
74+
eslintConfigScratch.recommended,
15175
{
152-
files: ['src/renderer/**.js'],
15376
languageOptions: {
15477
globals: {
155-
...globals.browser,
78+
...globals.node,
15679
MY_CUSTOM_GLOBAL: 'readonly',
15780
},
81+
parserOptions: {
82+
projectService: true,
83+
tsconfigRootDir: import.meta.dirname,
84+
},
15885
},
15986
},
87+
// Ignore all files in the dist directory
88+
globalIgnores(['dist/**/*']),
16089
)
16190
```
16291

163-
Of course, another option would be to place a different `eslint.config.mjs` file in each subdirectory. If you have
164-
multiple `tsconfig.json` or `jsconfig.json` files in your project, it likely makes sense to have an
165-
`eslint.config.mjs` file beside each one.
92+
## Granular Configuration
93+
94+
The `eslintConfigScratch` object contains granular configurations as well:
95+
96+
- `recommendedTypeFree`: A configuration suitable for contexts without type information, such as a JavaScript project.
97+
- `recommendedTypeChecked`: A configuration suitable for contexts with type information, such as a TypeScript project.
98+
You must provide extra configuration to `parserOptions` to enable type checking. See here:
99+
<https://typescript-eslint.io/getting-started/typed-linting/>
100+
101+
The `recommended` configuration is a combination of the two, and should be suitable for most projects. Features
102+
requiring type information are enabled for TypeScript files, and features that don't require type information are
103+
enabled for all files.
166104

167105
## Legacy Styles
168106

169107
Scratch used very different styling rules in `eslint-config-scratch@^9` and below. If you need to use those rules, you
170-
can use the rule sets under `legacy/`:
108+
can use these legacy configurations:
171109

172-
- `eslint-config-scratch/legacy`: Legacy base configuration, not configured for any particular environment
173-
- `eslint-config-scratch/legacy/es6`: Legacy rules for targeting Scratch's supported web browsers
174-
- `eslint-config-scratch/legacy/node`: Legacy rules for targeting Node.js
175-
- `eslint-config-scratch/legacy/react`: Legacy rules for targeting Scratch's supported web browsers with React
110+
- `eslintConfigScratch.legacy.base`: Legacy base configuration, not configured for any particular environment
111+
- `eslintConfigScratch.legacy.es6`: Legacy rules for targeting Scratch's supported web browsers
112+
- `eslintConfigScratch.legacy.node`: Legacy rules for targeting Node.js
113+
- `eslintConfigScratch.legacy.react`: Legacy rules for targeting Scratch's supported web browsers with React
176114

177115
New projects should not use these rule sets. They may disappear in the future. Scratch did not use Prettier at this
178116
time, so there is no legacy Prettier configuration.
179117

180-
Use these rule sets by importing them directly:
118+
Legacy Scratch projects usually `extend` more than one of these at a time, and potentially a different set per
119+
subdirectory. To do that in this new flat configuration format:
181120

182-
```mjs
183-
// myProjectRoot/eslint.config.mjs
184-
import webConfig from 'eslint-config-scratch/legacy/es6'
121+
```js
122+
// scratch-gui/eslint.config.mjs
123+
import { eslintConfigScratch } from 'eslint-config-scratch'
185124
import { globalIgnores } from 'eslint/config'
125+
import globals from 'globals'
186126

187-
/** @returns {import('eslint').Linter.Config[]} */
188-
export default [...webConfig, globalIgnores(['dist/**/*'])]
127+
export default eslintConfigScratch.config(
128+
eslintConfigScratch.legacy.base,
129+
eslintConfigScratch.legacy.es6,
130+
{
131+
files: ['src/**/*.js', 'src/**/*.jsx'],
132+
extends: [eslintConfigScratch.legacy.react],
133+
languageOptions: {
134+
globals: globals.browser,
135+
},
136+
rules: {
137+
// ...customized rules for `src/`...
138+
},
139+
// ...other settings for `src/`...
140+
},
141+
// ...settings for `test/`, etc...
142+
globalIgnores(['dist/**/*']),
143+
)
189144
```
190145

191146
## Committing

eslint.config.mjs

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import { makeEslintConfig } from './lib/index.mjs'
1+
import globals from 'globals'
2+
import { eslintConfigScratch } from './lib/index.mjs'
23

3-
/** @type {import('typescript-eslint').ConfigArray} */
4-
export default makeEslintConfig({ globals: 'node' })
4+
export default eslintConfigScratch.config(eslintConfigScratch.recommended, {
5+
languageOptions: {
6+
globals: globals.node,
7+
},
8+
})

0 commit comments

Comments
 (0)