Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to flat config #86

Merged
merged 5 commits into from
Aug 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .eslintrc.cjs

This file was deleted.

6 changes: 3 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ jobs:
fail-fast: false
matrix:
node-version:
- 16
- 14
- 12
- 22
- 20
- 18
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
Expand Down
38 changes: 23 additions & 15 deletions browser.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
'use strict';
const path = require('path');
const confusingBrowserGlobals = require('confusing-browser-globals');
import globals from 'globals';
import confusingBrowserGlobals from 'confusing-browser-globals';
import eslintConfigXo from './index.js';

module.exports = {
extends: path.join(__dirname, 'index.js'),
env: {
node: false,
browser: true,
},
rules: {
'no-restricted-globals': [
'error',
...confusingBrowserGlobals,
],
const [config] = eslintConfigXo;

export default [
{
...config,
languageOptions: {
...config.languageOptions,
globals: {
...globals.es2021,
...globals.browser,
},
},
rules: {
...config.rules,
'no-restricted-globals': [
'error',
...confusingBrowserGlobals,
],
},
},
};
];
1 change: 1 addition & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {default} from './index.js';
25 changes: 15 additions & 10 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
'use strict';
import globals from 'globals';

module.exports = {
parserOptions: {
ecmaVersion: 'latest',
const config = {
languageOptions: {
sourceType: 'module',
ecmaFeatures: {
jsx: true,
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
globals: {
...globals.es2021,
...globals.node,
},
},
env: {
es2021: true,
node: true,
linterOptions: {
reportUnusedDisableDirectives: 'error',
},
reportUnusedDisableDirectives: true,
rules: {
'comma-dangle': [
'error',
Expand Down Expand Up @@ -204,7 +207,7 @@
radix: 'error',

// Disabled for now as it causes too much churn
// TODO: Enable it in the future when I have time to deal with

Check warning on line 210 in index.js

View workflow job for this annotation

GitHub Actions / Node.js 22

Unexpected 'todo' comment: 'TODO: Enable it in the future when I...'

Check warning on line 210 in index.js

View workflow job for this annotation

GitHub Actions / Node.js 20

Unexpected 'todo' comment: 'TODO: Enable it in the future when I...'

Check warning on line 210 in index.js

View workflow job for this annotation

GitHub Actions / Node.js 18

Unexpected 'todo' comment: 'TODO: Enable it in the future when I...'
// the churn and the rule is stable and has an autofixer.
// Still doesn't have a fixer as of ESLint 7.24.0.
// 'require-unicode-regexp': 'error',
Expand All @@ -222,7 +225,7 @@
'no-restricted-globals': [
'error',
'event',
// TODO: Enable this in 2025.

Check warning on line 228 in index.js

View workflow job for this annotation

GitHub Actions / Node.js 22

Unexpected 'todo' comment: 'TODO: Enable this in 2025.'

Check warning on line 228 in index.js

View workflow job for this annotation

GitHub Actions / Node.js 20

Unexpected 'todo' comment: 'TODO: Enable this in 2025.'

Check warning on line 228 in index.js

View workflow job for this annotation

GitHub Actions / Node.js 18

Unexpected 'todo' comment: 'TODO: Enable this in 2025.'
// {
// name: 'Buffer',
// message: 'Use Uint8Array instead. See: https://sindresorhus.com/blog/goodbye-nodejs-buffer',
Expand Down Expand Up @@ -266,7 +269,7 @@
'sys',
'querystring',
'colors',
// TODO: Enable this in 2025.

Check warning on line 272 in index.js

View workflow job for this annotation

GitHub Actions / Node.js 22

Unexpected 'todo' comment: 'TODO: Enable this in 2025.'

Check warning on line 272 in index.js

View workflow job for this annotation

GitHub Actions / Node.js 20

Unexpected 'todo' comment: 'TODO: Enable this in 2025.'

Check warning on line 272 in index.js

View workflow job for this annotation

GitHub Actions / Node.js 18

Unexpected 'todo' comment: 'TODO: Enable this in 2025.'
// {
// name: 'buffer',
// message: 'Use Uint8Array instead. See: https://sindresorhus.com/blog/goodbye-nodejs-buffer',
Expand Down Expand Up @@ -637,7 +640,7 @@
{
// `array` is disabled because it forces destructuring on
// stupid stuff like `foo.bar = process.argv[2];`
// TODO: Open ESLint issue about this

Check warning on line 643 in index.js

View workflow job for this annotation

GitHub Actions / Node.js 22

Unexpected 'todo' comment: 'TODO: Open ESLint issue about this'

Check warning on line 643 in index.js

View workflow job for this annotation

GitHub Actions / Node.js 20

Unexpected 'todo' comment: 'TODO: Open ESLint issue about this'

Check warning on line 643 in index.js

View workflow job for this annotation

GitHub Actions / Node.js 18

Unexpected 'todo' comment: 'TODO: Open ESLint issue about this'
VariableDeclarator: {
array: false,
object: true,
Expand Down Expand Up @@ -671,3 +674,5 @@
],
},
};

export default [config];
19 changes: 14 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
"version": "0.45.0",
"description": "ESLint shareable config for XO",
"license": "MIT",
"type": "module",
"exports": {
".": "./index.js",
"./browser": "./browser.js",
"./space": "./space.js",
"./space/browser": "./space-browser.js"
},
"repository": "xojs/eslint-config-xo",
"funding": "https://github.com/sponsors/sindresorhus",
"author": {
Expand All @@ -19,7 +26,9 @@
},
"files": [
"index.js",
"browser.js"
"browser.js",
"space.js",
"space-browser.js"
],
"keywords": [
"eslintconfig",
Expand Down Expand Up @@ -50,12 +59,12 @@
"simple"
],
"dependencies": {
"confusing-browser-globals": "1.0.11"
"confusing-browser-globals": "1.0.11",
"globals": "^15.3.0"
},
"devDependencies": {
"ava": "^2.4.0",
"eslint": "^8.56.0",
"is-plain-obj": "^3.0.0"
"ava": "^6.1.3",
"eslint": "^9.4.0"
},
"peerDependencies": {
"eslint": ">=8.56.0"
Expand Down
51 changes: 32 additions & 19 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,44 @@ npm install --save-dev eslint-config-xo

## Usage

Add some ESLint config to your `package.json`:

```json
{
"name": "my-awesome-project",
"eslintConfig": {
"extends": "xo"
}
}
Add some ESLint config to your `eslint.config.js`:

```js
import eslintConfigXo from 'eslint-config-xo';

export default [
...eslintConfigXo,
];
```

This package also exposes [`eslint-config-xo/browser`](browser.js) if you're in the browser:

```js
import eslintConfigXoBrowser from 'eslint-config-xo/browser';

export default [
...eslintConfigXoBrowser,
];
Comment on lines +19 to +36
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opted for a neostandard({ semi: true }) style to construct the config in neostandard. Have you considered doing that instead of /browser? Having something like export default xo({ browser: true })?

That way you can have space, browser etc exposed without having to have files for the combinations as well, like space/browser

```

Or to `.eslintrc`:
This package also exposes [`eslint-config-xo/space`](space.js) if you're in favor of 2-space indent:

```json
{
"extends": "xo"
}
```js
import eslintConfigXoSpace from 'eslint-config-xo/space';

export default [
...eslintConfigXoSpace,
];
```

This package also exposes [`xo/browser`](browser.js) if you're in the browser:
This package also exposes [`eslint-config-xo/space/browser`](space-browser.js) if you're in favor of 2-space indent and in browser:

```js
import eslintConfigXoSpaceBrowser from 'eslint-config-xo/space/browser';

```json
{
"extends": "xo/browser"
}
export default [
...eslintConfigXoSpaceBrowser,
];
```

## Use the XO CLI instead
Expand Down
19 changes: 19 additions & 0 deletions space-browser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import eslintConfigXoBrowser from './browser.js';

const [config] = eslintConfigXoBrowser;

export default [
{
...config,
rules: {
...config.rules,
indent: [
Comment on lines +5 to +10
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the benefit of this over having the space config be its own config? The latter is what I opted for in neostandard

Suggested change
export default [
{
...config,
rules: {
...config.rules,
indent: [
export default [
config,
{
rules: {
indent: [

I would do something like:

import base from './configs/base.js';
import browser from './configs/browser.js';
import space from './configs/space.js';

export default [
  base,
  browser,
  space,
];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A benefit of having them as separate (+ including names for each one of them) is that its very clear which config that leads to which config. See example here from the config inspector generated for neostandard: https://neostandard.github.io/neostandard/configs

'error',
2,
{
SwitchCase: 1,
},
],
},
},
];
19 changes: 19 additions & 0 deletions space.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import eslintConfigXo from './index.js';

const [config] = eslintConfigXo;

export default [
{
...config,
rules: {
...config.rules,
indent: [
'error',
2,
{
SwitchCase: 1,
},
],
},
},
];
64 changes: 51 additions & 13 deletions test/test.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import test from 'ava';
import isPlainObj from 'is-plain-obj';
import {ESLint} from 'eslint';
import eslintConfigXoNode from '../index.js';
import eslintConfigXoBrowser from '../browser.js';
import eslintConfigXoSpaceNode from '../space.js';
import eslintConfigXoSpaceBrowser from '../space-browser.js';

const hasRule = (errors, ruleId) => errors.some(error => error.ruleId === ruleId);

async function runEslint(string, config) {
const eslint = new ESLint({
useEslintrc: false,
overrideConfigFile: true,
overrideConfig: config,
});

Expand All @@ -15,21 +18,56 @@ async function runEslint(string, config) {
return firstResult.messages;
}

test('main', async t => {
const config = require('../index.js');
test('node', async t => {
for (const config of [eslintConfigXoNode, eslintConfigXoSpaceNode]) {
t.true(Array.isArray(config));

t.true(isPlainObj(config));
t.true(isPlainObj(config.rules));

const errors = await runEslint('\'use strict\';\nconsole.log("unicorn")\n', config);
t.true(hasRule(errors, 'quotes'), JSON.stringify(errors));
// eslint-disable-next-line no-await-in-loop
const errors = await runEslint('\'use strict\';\nconsole.log("unicorn")\n', config);
t.true(hasRule(errors, 'quotes'), JSON.stringify(errors));
}
});

test('browser', async t => {
const config = require('../browser.js');
for (const config of [eslintConfigXoBrowser, eslintConfigXoSpaceBrowser]) {
t.true(Array.isArray(config));

// eslint-disable-next-line no-await-in-loop
const errors = await runEslint('\'use strict\';\nprocess.exit();\n', config);
t.true(hasRule(errors, 'no-undef'), JSON.stringify(errors));
}
});

t.true(isPlainObj(config));
test('space', async t => {
const fixture = `
export function foo() {
\treturn true;
}
`.trim();

const errors = await runEslint('\'use strict\';\nprocess.exit();\n', config);
t.true(hasRule(errors, 'no-undef'), JSON.stringify(errors));
for (const {
expected,
config,
} of [
{
config: eslintConfigXoSpaceNode,
expected: true,
},
{
config: eslintConfigXoSpaceBrowser,
expected: true,
},
{
config: eslintConfigXoNode,
expected: false,
},
{
config: eslintConfigXoBrowser,
expected: false,
},
]) {
// eslint-disable-next-line no-await-in-loop
const errors = await runEslint(fixture, config);
t.is(hasRule(errors, 'indent'), expected, JSON.stringify(errors));
}
});