Skip to content

Commit

Permalink
Require Node.js 12.20 and enforce ESM
Browse files Browse the repository at this point in the history
  • Loading branch information
sindresorhus committed May 9, 2021
1 parent 0480d80 commit cc06c3c
Show file tree
Hide file tree
Showing 14 changed files with 68 additions and 82 deletions.
6 changes: 3 additions & 3 deletions cli-main.js
Expand Up @@ -5,8 +5,8 @@ const getStdin = require('get-stdin');
const meow = require('meow');
const formatterPretty = require('eslint-formatter-pretty');
const semver = require('semver');
const openReport = require('./lib/open-report');
const xo = require('.');
const openReport = require('./lib/open-report.js');
const xo = require('./index.js');

const cli = meow(`
Usage
Expand Down Expand Up @@ -130,7 +130,7 @@ for (const key in options) {
// Check for string type because `xo --no-space` sets `options.space` to `false`
if (typeof options.space === 'string') {
if (/^\d+$/u.test(options.space)) {
options.space = parseInt(options.space, 10);
options.space = Number.parseInt(options.space, 10);
} else if (options.space === 'true') {
options.space = true;
} else if (options.space === 'false') {
Expand Down
34 changes: 10 additions & 24 deletions config/plugins.js
Expand Up @@ -198,10 +198,7 @@ module.exports = {
}
}
],

// Disabled as it causes problems with TypeScript when you use mixed ESM and CommonJS.
// TODO: Enable again when I target only ESM.
// 'import/first': 'error',
'import/first': 'error',

// Disabled as it doesn't work with TypeScript.
// This issue and some others: https://github.com/benmosher/eslint-plugin-import/issues/1341
Expand All @@ -218,10 +215,12 @@ module.exports = {
'import/no-named-default': 'error',
'import/no-webpack-loader-syntax': 'error',
'import/no-self-import': 'error',

// Enable this sometime in the future when Node.js has ES2015 module support
// 'import/no-cycle': 'error'

'import/no-cycle': [
'error',
{
ignoreExternal: true
}
],
'import/no-useless-path-segments': 'error',

// Disabled as it doesn't work with TypeScript
Expand All @@ -230,10 +229,7 @@ module.exports = {
'import/no-amd': 'error',
'import/no-duplicates': 'error',

// Enable this sometime in the future when Node.js has ES2015 module support
// 'import/unambiguous': 'error',

// Enable this sometime in the future when Node.js has ES2015 module support
// We use `unicorn/prefer-module` instead.
// 'import/no-commonjs': 'error',

// Looks useful, but too unstable at the moment
Expand All @@ -252,9 +248,7 @@ module.exports = {
// }
// ],

// Disabled because of https://github.com/benmosher/eslint-plugin-import/pull/1651 and other issues.
// 'import/order': 'error',

'import/order': 'error',
'import/no-unassigned-import': [
'error',
{
Expand All @@ -277,7 +271,7 @@ module.exports = {
// 'node/no-extraneous-require': 'error',

// Redundant with `import/no-unresolved`.
// 'node/no-missing-import': 'error',
// 'node/no-missing-import': 'error', // This rule is also buggy and doesn't support `node:`.
// 'node/no-missing-require': 'error',

'node/no-unpublished-bin': 'error',
Expand Down Expand Up @@ -329,13 +323,6 @@ module.exports = {
// 'node/shebang': 'error',

'node/no-deprecated-api': 'error',

// Disabled because it causes too much churn and will be moot when we switch to ES2015 modules
// 'node/exports-style': [
// 'error',
// 'module.exports'
// ]

'node/prefer-global/buffer': [
'error',
'always'
Expand All @@ -356,7 +343,6 @@ module.exports = {
'error',
'always'
],

'node/prefer-global/url-search-params': [
'error',
'always'
Expand Down
3 changes: 1 addition & 2 deletions lib/options-manager.js
Expand Up @@ -8,7 +8,6 @@ const mergeWith = require('lodash/mergeWith');
const groupBy = require('lodash/groupBy');
const flow = require('lodash/flow');
const pick = require('lodash/pick');
const fromPairs = require('lodash/fromPairs');
const pathExists = require('path-exists');
const findUp = require('find-up');
const findCacheDir = require('find-cache-dir');
Expand Down Expand Up @@ -300,7 +299,7 @@ const buildConfig = (options, prettierOptions) => {
)(mergeWith(getEmptyConfig(), DEFAULT_CONFIG, mergeFn));
};

const toValueMap = (array, value = true) => fromPairs(array.map(item => [item, value]));
const toValueMap = (array, value = true) => Object.fromEntries(array.map(item => [item, value]));

const buildESLintConfig = options => config => {
if (options.rules) {
Expand Down
12 changes: 6 additions & 6 deletions package.json
Expand Up @@ -12,7 +12,7 @@
},
"bin": "cli.js",
"engines": {
"node": ">=10.18"
"node": ">=12.20"
},
"scripts": {
"test": "eslint --quiet . && nyc ava"
Expand Down Expand Up @@ -61,7 +61,7 @@
"eslint": "^7.24.0",
"eslint-config-prettier": "^8.2.0",
"eslint-config-xo": "^0.36.0",
"eslint-config-xo-typescript": "^0.39.0",
"eslint-config-xo-typescript": "^0.41.0",
"eslint-formatter-pretty": "^4.0.0",
"eslint-import-resolver-webpack": "^0.13.0",
"eslint-plugin-ava": "^12.0.0",
Expand All @@ -71,10 +71,10 @@
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^3.4.0",
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-unicorn": "^30.0.0",
"eslint-plugin-unicorn": "^32.0.0",
"find-cache-dir": "^3.3.1",
"find-up": "^5.0.0",
"fs-extra": "^9.1.0",
"fs-extra": "^10.0.0",
"get-stdin": "^8.0.0",
"globby": "^9.2.0",
"has-flag": "^4.0.0",
Expand Down Expand Up @@ -106,15 +106,15 @@
"esm": "^3.2.25",
"execa": "^5.0.0",
"nyc": "^15.1.0",
"pify": "^5.0.0",
"proxyquire": "^2.1.3",
"temp-write": "^4.0.0",
"webpack": "^5.34.0"
},
"eslintConfig": {
"extends": "eslint-config-xo",
"rules": {
"unicorn/import-index": "off"
"unicorn/prefer-module": "off",
"unicorn/prefer-node-protocol": "off"
}
},
"eslintIgnore": [
Expand Down
33 changes: 13 additions & 20 deletions readme.md
Expand Up @@ -11,13 +11,11 @@
[![Coverage Status](https://codecov.io/gh/xojs/xo/branch/main/graph/badge.svg)](https://codecov.io/gh/xojs/xo/branch/main)
[![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo)

Opinionated but configurable ESLint wrapper with lots of goodies included. Enforces strict and readable code. Never discuss code style on a pull request again! No decision-making. No `.eslintrc` or `.jshintrc` to manage. It just works!
Opinionated but configurable ESLint wrapper with lots of goodies included. Enforces strict and readable code. Never discuss code style on a pull request again! No decision-making. No `.eslintrc` to manage. It just works!

Uses [ESLint](https://eslint.org) underneath, so issues regarding rules should be opened over [there](https://github.com/eslint/eslint/issues).
It uses [ESLint](https://eslint.org) underneath, so issues regarding built-in rules should be opened over [there](https://github.com/eslint/eslint/issues).

*JSX is supported by default, but you'll need [eslint-config-xo-react](https://github.com/xojs/eslint-config-xo-react#use-with-xo) for React specific linting.*

*Vue components are not supported by default. You'll need [eslint-config-xo-vue](https://github.com/ChocPanda/eslint-config-xo-vue#use-with-xo) for specific linting in a Vue app.*
**XO requires your project to be [ESM](https://blog.sindresorhus.com/hello-modules-d1010b4e777b).**

![](https://raw.githubusercontent.com/sindresorhus/eslint-formatter-pretty/main/screenshot.png)

Expand Down Expand Up @@ -45,6 +43,8 @@ Uses [ESLint](https://eslint.org) underneath, so issues regarding rules should b
$ npm install --global xo
```

*JSX is supported by default, but you'll need [eslint-config-xo-react](https://github.com/xojs/eslint-config-xo-react#use-with-xo) for React specific linting. Vue components are not supported by default. You'll need [eslint-config-xo-vue](https://github.com/ChocPanda/eslint-config-xo-vue#use-with-xo) for specific linting in a Vue app.*

## Usage

```
Expand Down Expand Up @@ -165,7 +165,7 @@ module.exports = {
### envs

Type: `string[]`\
Default: `['es2020', 'node']`
Default: `['es2021', 'node']`

Which [environments](https://eslint.org/docs/user-guide/configuring#specifying-environments) your code is designed to run in. Each environment brings with it a certain set of predefined global variables.

Expand Down Expand Up @@ -279,18 +279,12 @@ Set this to a boolean to explicitly enable or disable the resolver.

Setting this to an object enables the resolver and passes the object as configuration. See the [resolver readme](https://github.com/benmosher/eslint-plugin-import/blob/master/resolvers/webpack/README.md) along with the [webpack documentation](https://webpack.js.org/configuration/resolve/) for more information.

## TypeScript and Flow

### TypeScript
## TypeScript

XO will automatically lint TypeScript files (`.ts`, `.d.ts` and `.tsx`) with the rules defined in [eslint-config-xo-typescript#use-with-xo](https://github.com/xojs/eslint-config-xo-typescript#use-with-xo).

XO will handle the [@typescript-eslint/parser `project` option](https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/parser#parseroptionsproject) automatically even if you don't have a `tsconfig.json` in your project.

### Flow

See [eslint-config-xo-flow#use-with-xo](https://github.com/xojs/eslint-config-xo-flow#use-with-xo)

## GitHub Actions

XO uses a different formatter when running in a GitHub Actions workflow to be able to get [inline annotations](https://developer.github.com/changes/2019-09-06-more-check-annotations-shown-in-files-changed-tab/). XO also disables warnings here.
Expand Down Expand Up @@ -363,7 +357,7 @@ For example, if your project targets Node.js 8 but you want to use the latest Ja
```json
{
"engines": {
"node": ">=8"
"node": ">=12"
},
"scripts": {
"build": "babel src --out-dir dist"
Expand All @@ -374,14 +368,14 @@ For example, if your project targets Node.js 8 but you want to use the latest Ja
"overrides": [
{
"files": "{src}/**/*.js",
"nodeVersion": ">=12"
"nodeVersion": ">=16"
}
]
}
}
```

This way your `package.json` will contain the actual minimum Node.js version supported by your published code, but XO will lint your source code as if it targets Node.js 12.
This way your `package.json` will contain the actual minimum Node.js version supported by your published code, but XO will lint your source code as if it targets Node.js 16.

### Including files ignored by default

Expand Down Expand Up @@ -440,7 +434,6 @@ XO is based on ESLint. This project started out as just a shareable ESLint confi
- [stylelint-config-xo-space](https://github.com/xojs/stylelint-config-xo-space) - Stylelint shareable config for XO with 2-space indent
- [tslint-xo](https://github.com/xojs/tslint-xo) - TSLint shareable config for XO
- [eslint-config-xo-typescript](https://github.com/xojs/eslint-config-xo-typescript) - ESLint shareable config for TypeScript
- [eslint-config-xo-flow](https://github.com/xojs/eslint-config-xo-flow) - ESLint shareable config for Flow

## Support

Expand All @@ -463,11 +456,11 @@ You can also find some nice dynamic XO badges on [badgen.net](https://badgen.net

## Team

[![Sindre Sorhus](https://github.com/sindresorhus.png?size=130)](https://sindresorhus.com) | [![Mario Nebl](https://github.com/marionebl.png?size=130)](https://github.com/marionebl) | [![Pierre Vanduynslager](https://github.com/pvdlg.png?size=130)](https://github.com/pvdlg)
---|---|---
[Sindre Sorhus](https://sindresorhus.com) | [Mario Nebl](https://github.com/marionebl) | [Pierre Vanduynslager](https://github.com/pvdlg)
- [Sindre Sorhus](https://github.com/sindresorhus)

###### Former

- [James Talmage](https://github.com/jamestalmage)
- [Michael Mayer](https://github.com/schnittstabil)
- [Mario Nebl](https://github.com/marionebl)
- [Pierre Vanduynslager](https://github.com/pvdlg)
2 changes: 1 addition & 1 deletion test/fixtures/gitignore/test/bar.js
@@ -1,5 +1,5 @@
import test from 'ava'
import fn from '..'
import fn from '../index.js'

test('main', t => {
t.is(fn('foo'), fn('foobar'))
Expand Down
6 changes: 5 additions & 1 deletion test/fixtures/ignores/package.json
Expand Up @@ -4,6 +4,10 @@
"xo": {
"ignore": [
"!dist/**"
]
],
"rules": {
"unicorn/prefer-module": "off",
"unicorn/prefer-node-protocol": "off"
}
}
}
6 changes: 4 additions & 2 deletions test/fixtures/overrides/package.json
Expand Up @@ -13,8 +13,10 @@
}
],
"rules": {
"import/no-extraneous-dependencies": 0,
"ava/no-ignored-test-files": 0
"import/no-extraneous-dependencies": "off",
"ava/no-ignored-test-files": "off",
"unicorn/prefer-module": "off",
"unicorn/prefer-node-protocol": "off"
}
}
}
2 changes: 1 addition & 1 deletion test/fixtures/webpack/no-config/file1.js
@@ -1,2 +1,2 @@
import _ from 'file2alias'; // eslint-disable-line no-unused-vars
import __ from 'inexistent'; // eslint-disable-line no-unused-vars
import _ from 'file2alias'; // eslint-disable-line no-unused-vars
2 changes: 1 addition & 1 deletion test/fixtures/webpack/with-config/file1.js
@@ -1,2 +1,2 @@
import _ from 'file2alias'; // eslint-disable-line no-unused-vars
import __ from 'inexistent'; // eslint-disable-line no-unused-vars
import _ from 'file2alias'; // eslint-disable-line no-unused-vars
6 changes: 3 additions & 3 deletions test/lint-files.js
@@ -1,6 +1,6 @@
import path from 'path';
import test from 'ava';
import xo from '..';
import xo from '../index.js';

process.chdir(__dirname);

Expand Down Expand Up @@ -220,7 +220,7 @@ test('webpack import resolver is used if webpack.config.js is found', async t =>
}
});

t.is(results[0].errorCount, 1);
t.is(results[0].errorCount, 1, JSON.stringify(results[0].messages));

const errorMessage = results[0].messages[0].message;
t.truthy(/Unable to resolve path to module 'inexistent'/.exec(errorMessage));
Expand All @@ -245,7 +245,7 @@ test('webpack import resolver config can be passed through webpack option', asyn
}
});

t.is(results[0].errorCount, 1);
t.is(results[0].errorCount, 1, JSON.stringify(results[0].messages));
});

test('webpack import resolver is used if {webpack: true}', async t => {
Expand Down

0 comments on commit cc06c3c

Please sign in to comment.