UNPKG

18.8 kBMarkdownView Raw
1<h1 align="center">
2 <br>
3 <img width="400" src="media/logo.svg" alt="XO">
4 <br>
5 <br>
6 <br>
7</h1>
8
9> JavaScript/TypeScript linter with great defaults
10
11[![Build Status](https://travis-ci.com/xojs/xo.svg?branch=master)](https://travis-ci.com/xojs/xo) [![Coverage Status](https://coveralls.io/repos/github/xojs/xo/badge.svg?branch=master)](https://coveralls.io/github/xojs/xo?branch=master) [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo) [![Gitter](https://badges.gitter.im/join_chat.svg)](https://gitter.im/xojs/Lobby)
12
13Opinionated 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!
14
15Uses [ESLint](https://eslint.org) underneath, so issues regarding rules should be opened over [there](https://github.com/eslint/eslint/issues).
16
17*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.*
18
19*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.*
20
21![](https://raw.githubusercontent.com/sindresorhus/eslint-formatter-pretty/master/screenshot.png)
22
23## Highlights
24
25- Beautiful output.
26- Zero-config, but [configurable when needed](#config).
27- Enforces readable code, because you read more code than you write.
28- No need to specify file paths to lint as it lints all JS/TS files except for [commonly ignored paths](#ignores).
29- [Config overrides per files/globs.](#config-overrides)
30- [TypeScript supported by default](#typescript)
31- Includes many useful ESLint plugins, like [`unicorn`](https://github.com/sindresorhus/eslint-plugin-unicorn), [`import`](https://github.com/benmosher/eslint-plugin-import), [`ava`](https://github.com/avajs/eslint-plugin-ava), [`node`](https://github.com/mysticatea/eslint-plugin-node) and more.
32- Automatically enables rules based on the [`engines`](https://docs.npmjs.com/files/package.json#engines) field in your `package.json`.
33- Caches results between runs for much better performance.
34- Super simple to add XO to a project with [`$ npm init xo`](https://github.com/xojs/create-xo).
35- Fix many issues automagically with `$ xo --fix`.
36- Open all files with errors at the correct line in your editor with `$ xo --open`.
37- Specify [indent](#space) and [semicolon](#semicolon) preferences easily without messing with the rule config.
38- Optionally use the [Prettier](https://github.com/prettier/prettier) code style.
39- Great [editor plugins](#editor-plugins).
40
41## Install
42
43```
44$ npm install --global xo
45```
46
47## Usage
48
49```
50$ xo --help
51
52 Usage
53 $ xo [<file|glob> ...]
54
55 Options
56 --fix Automagically fix issues
57 --reporter Reporter to use
58 --env Environment preset [Can be set multiple times]
59 --global Global variable [Can be set multiple times]
60 --ignore Additional paths to ignore [Can be set multiple times]
61 --space Use space indent instead of tabs [Default: 2]
62 --no-semicolon Prevent use of semicolons
63 --prettier Conform to Prettier code style
64 --node-version Range of Node.js version to support
65 --plugin Include third-party plugins [Can be set multiple times]
66 --extend Extend defaults with a custom config [Can be set multiple times]
67 --open Open files with issues in your editor
68 --quiet Show only errors and no warnings
69 --extension Additional extension to lint [Can be set multiple times]
70 --no-esnext Don't enforce ES2015+ rules
71 --cwd=<dir> Working directory for files
72 --stdin Validate/fix code from stdin
73 --stdin-filename Specify a filename for the --stdin option
74
75 Examples
76 $ xo
77 $ xo index.js
78 $ xo *.js !foo.js
79 $ xo --space
80 $ xo --env=node --env=mocha
81 $ xo --plugin=react
82 $ xo --plugin=html --extension=html
83 $ echo 'const x=true' | xo --stdin --fix
84
85 Tips
86 - Add XO to your project with `npm init xo`.
87 - Put options in package.json instead of using flags so other tools can read it.
88```
89
90*Note that the CLI will use your local install of XO when available, even when run globally.*
91
92## Default code style
93
94*Any of these can be [overridden](#rules) if necessary.*
95
96- Tab indentation *[(or space)](#space)*
97- Semicolons *[(or not)](#semicolon)*
98- Single-quotes
99- No unused variables
100- Space after keyword `if (condition) {}`
101- Always `===` instead of `==`
102
103Check out an [example](index.js) and the [ESLint rules](https://github.com/xojs/eslint-config-xo/blob/master/index.js).
104
105## Workflow
106
107The recommended workflow is to add XO locally to your project and run it with the tests.
108
109Simply run `$ npm init xo` (with any options) to add XO to your package.json or create one.
110
111### Before/after
112
113```diff
114 {
115 "name": "awesome-package",
116 "scripts": {
117- "test": "ava",
118+ "test": "xo && ava"
119 },
120 "devDependencies": {
121- "ava": "^2.0.0"
122+ "ava": "^2.0.0",
123+ "xo": "^0.25.0"
124 }
125 }
126```
127
128Then just run `$ npm test` and XO will be run before your tests.
129
130## Config
131
132You can configure XO options with one of the following files:
133
1341. As JSON in the `xo` property in `package.json`:
135
136```json
137{
138 "name": "awesome-package",
139 "xo": {
140 "space": true
141 }
142}
143```
144
1452. As JSON in `.xo-config` or `.xo-config.json`:
146
147```json
148{
149 "space": true
150}
151```
152
1533. As a JavaScript module in `.xo-config.js` or `xo.config.js`:
154
155```js
156module.exports = {
157 space: true
158};
159```
160
161[Globals](https://eslint.org/docs/user-guide/configuring#specifying-globals) and [rules](https://eslint.org/docs/user-guide/configuring#configuring-rules) can be configured inline in files.
162
163### envs
164
165Type: `string[]`\
166Default: `['es2020', 'node']`
167
168Which [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.
169
170### globals
171
172Type: `string[]`
173
174Additional global variables your code accesses during execution.
175
176### ignores
177
178Type: `string[]`
179
180Some [paths](lib/options-manager.js) are ignored by default, including paths in `.gitignore` and [.eslintignore](https://eslint.org/docs/user-guide/configuring#eslintignore). Additional ignores can be added here.
181
182### space
183
184Type: `boolean | number`\
185Default: `false` *(tab indentation)*
186
187Set it to `true` to get 2-space indentation or specify the number of spaces.
188
189This option exists for pragmatic reasons, but I would strongly recommend you read ["Why tabs are superior"](http://lea.verou.me/2012/01/why-tabs-are-clearly-superior/).
190
191### rules
192
193Type: `object`
194
195Override any of the [default rules](https://github.com/xojs/eslint-config-xo/blob/master/index.js). See the [ESLint docs](https://eslint.org/docs/rules/) for more info on each rule.
196
197Please take a moment to consider if you really need to use this option.
198
199### semicolon
200
201Type: `boolean`\
202Default: `true` *(Semicolons required)*
203
204Set it to `false` to enforce no-semicolon style.
205
206### prettier
207
208Type: `boolean`\
209Default: `false`
210
211Format code with [Prettier](https://github.com/prettier/prettier).
212
213The [Prettier options](https://prettier.io/docs/en/options.html) will be read from the [Prettier config](https://prettier.io/docs/en/configuration.html) and if **not set** will be determined as follow:
214- [semi](https://prettier.io/docs/en/options.html#semicolons): based on [semicolon](#semicolon) option
215- [useTabs](https://prettier.io/docs/en/options.html#tabs): based on [space](#space) option
216- [tabWidth](https://prettier.io/docs/en/options.html#tab-width): based on [space](#space) option
217- [trailingComma](https://prettier.io/docs/en/options.html#trailing-commas): `none`
218- [singleQuote](https://prettier.io/docs/en/options.html#quotes): `true`
219- [bracketSpacing](https://prettier.io/docs/en/options.html#bracket-spacing): `false`
220- [jsxBracketSameLine](https://prettier.io/docs/en/options.html#jsx-brackets): `false`
221
222If contradicting options are set for both Prettier and XO an error will be thrown.
223
224### nodeVersion
225
226Type: `string | boolean`\
227Default: Value of the `engines.node` key in the project `package.json`
228
229Enable rules specific to the Node.js versions within the configured range.
230
231If set to `false`, no rules specific to a Node.js version will be enabled.
232
233### plugins
234
235Type: `string[]`
236
237Include third-party [plugins](https://eslint.org/docs/user-guide/configuring.html#configuring-plugins).
238
239### extends
240
241Type: `string | string[]`
242
243Use one or more [shareable configs](https://eslint.org/docs/developer-guide/shareable-configs.html) or [plugin configs](https://eslint.org/docs/user-guide/configuring#using-the-configuration-from-a-plugin) to override any of the default rules (like `rules` above).
244
245### extensions
246
247Type: `string[]`
248
249Allow more extensions to be linted besides `.js` and `.jsx`. Make sure they're supported by ESLint or an ESLint plugin.
250
251### settings
252
253Type: `object`
254
255[Shared ESLint settings](https://eslint.org/docs/user-guide/configuring#adding-shared-settings) exposed to rules.
256
257### parser
258
259Type: `string`
260
261ESLint parser. For example, [`babel-eslint`](https://github.com/babel/babel-eslint) if you're using language features that ESLint doesn't yet support.
262
263### esnext
264
265Type: `boolean`\
266Default: `true`
267
268Enforce ES2015+ rules. Disabling this will make it not *enforce* ES2015+ syntax and conventions.
269
270*ES2015+ is parsed even without this option. You can already use ES2017 features like [`async`/`await`](https://github.com/lukehoban/ecmascript-asyncawait).
271
272### webpack
273
274Type: `boolean | object`
275Default: `false`
276
277Use [eslint-import-resolver-webpack](https://github.com/benmosher/eslint-plugin-import/tree/master/resolvers/webpack) to resolve import search paths. This is enabled automatically if a `webpack.config.js` file is found.
278
279Set this to a boolean to explicitly enable or disable the resolver.
280
281Setting 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.
282
283## TypeScript and Flow
284
285### TypeScript
286
287XO 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).
288
289XO 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.
290
291### Flow
292
293See [eslint-config-xo-flow#use-with-xo](https://github.com/xojs/eslint-config-xo-flow#use-with-xo)
294
295## Config Overrides
296
297XO makes it easy to override configs for specific files. The `overrides` property must be an array of override objects. Each override object must contain a `files` property which is a glob string, or an array of glob strings, relative to the config file. The remaining properties are identical to those described above, and will override the settings of the base config. If multiple override configs match the same file, each matching override is applied in the order it appears in the array. This means the last override in the array takes precedence over earlier ones. Consider the following example:
298
299```json
300{
301 "xo": {
302 "semicolon": false,
303 "space": 2,
304 "overrides": [
305 {
306 "files": "test/*.js",
307 "esnext": false,
308 "space": 3
309 },
310 {
311 "files": "test/foo.js",
312 "esnext": true
313 }
314 ]
315 }
316}
317```
318
319- The base configuration is simply `space: 2`, `semicolon: false`. These settings are used for every file unless otherwise noted below.
320
321- For every file in `test/*.js`, the base config is used, but `space` is overridden with `3`, and the `esnext` option is set to `false`. The resulting config is:
322
323```json
324{
325 "esnext": false,
326 "semicolon": false,
327 "space": 3
328}
329```
330
331- For `test/foo.js`, the base config is first applied, followed the first overrides config (its glob pattern also matches `test/foo.js`), finally the second override config is applied. The resulting config is:
332
333```json
334{
335 "esnext": true,
336 "semicolon": false,
337 "space": 3
338}
339```
340
341## Tips
342
343### Using a parent's config
344
345If you have a directory structure with nested `package.json` files and you want one of the child manifests to be skipped, you can do so by ommiting the `xo` property in the child's `package.json`. For example, when you have separate app and dev `package.json` files with `electron-builder`.
346
347### Monorepo
348
349Put a `package.json` with your config at the root and omit the `xo` property in the `package.json` of your bundled packages.
350
351### Transpilation
352
353If some files in your project are transpiled in order to support an older Node.js version, you can use the [config overrides](#config-overrides) option to set a specific [`nodeVersion`](#nodeversion) to target your sources files.
354
355For example, if your project targets Node.js 8 but you want to use the latest JavaScript syntax as supported in Node.js 12:
3561. Set the `engines.node` property of your `package.json` to `>=8`
3572. Configure [Babel](https://babeljs.io) to transpile your source files (in `src` directory in this example)
3583. Make sure to include the transpiled files in your published package with the [`files`](https://docs.npmjs.com/files/package.json#files) and [`main`](https://docs.npmjs.com/files/package.json#main) properties of your `package.json`
3594. Configure the XO `overrides` option to set `nodeVersion` to `>=12` for your source files directory
360
361```json
362{
363 "engines": {
364 "node": ">=8"
365 },
366 "scripts": {
367 "build": "babel src --out-dir dist"
368 },
369 "main": "dist/index.js",
370 "files": ["dist/**/*.js"],
371 "xo": {
372 "overrides": [
373 {
374 "files": "{src}/**/*.js",
375 "nodeVersion": ">=12"
376 }
377 ]
378 }
379}
380```
381
382This 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.
383
384### Including files ignored by default
385
386To include files that XO [ignores by default](https://github.com/xojs/xo/blob/master/lib/constants.js#L1), add them as negative globs in the `ignores` option:
387
388```json
389{
390 "xo": {
391 "ignores": [
392 "!vendor/**"
393 ]
394 }
395}
396```
397
398## FAQ
399
400#### What does XO mean?
401
402It means [hugs and kisses](https://en.wiktionary.org/wiki/xoxo).
403
404#### Why not Standard?
405
406The [Standard style](https://standardjs.com) is a really cool idea. I too wish we could have one style to rule them all! But the reality is that the JS community is just too diverse and opinionated to create *one* code style. They also made the mistake of pushing their own style instead of the most popular one. In contrast, XO is more pragmatic and has no aspiration of being *the* style. My goal with XO is to make it simple to enforce consistent code style with close to no config. XO comes with my code style preference by default, as I mainly made it for myself, but everything is configurable.
407
408#### Why not ESLint?
409
410XO is based on ESLint. This project started out as just a shareable ESLint config, but it quickly grew out of that. I wanted something even simpler. Just typing `xo` and be done. No decision-making. No config. I also have some exciting future plans for it. However, you can still get most of the XO benefits while using ESLint directly with the [ESLint shareable config](https://github.com/xojs/eslint-config-xo).
411
412## Editor plugins
413
414- [Sublime Text](https://github.com/xojs/SublimeLinter-contrib-xo)
415- [Atom](https://github.com/xojs/atom-linter-xo)
416- [Vim](https://github.com/xojs/vim-xo)
417- [TextMate 2](https://github.com/claylo/XO.tmbundle)
418- [VSCode](https://github.com/SamVerschueren/vscode-linter-xo)
419- [Emacs](https://github.com/j-em/xo-emacs)
420- [WebStorm](https://github.com/jamestalmage/xo-with-webstorm)
421
422## Build-system plugins
423
424- [Gulp](https://github.com/xojs/gulp-xo)
425- [Grunt](https://github.com/xojs/grunt-xo)
426- [webpack loader](https://github.com/Semigradsky/xo-loader)
427- [webpack plugin](https://github.com/nstanard/xo-webpack-plugin)
428- [Metalsmith](https://github.com/blainsmith/metalsmith-xo)
429- [Fly](https://github.com/lukeed/fly-xo)
430
431## Configs
432
433- [eslint-config-xo](https://github.com/xojs/eslint-config-xo) - ESLint shareable config for XO with tab indent
434- [eslint-config-xo-space](https://github.com/xojs/eslint-config-xo-space) - ESLint shareable config for XO with 2-space indent
435- [eslint-config-xo-react](https://github.com/xojs/eslint-config-xo-react) - ESLint shareable config for React to be used with the above
436- [eslint-config-xo-vue](https://github.com/ChocPanda/eslint-config-xo-vue) - ESLint shareable config for Vue to be used with the above
437- [stylelint-config-xo](https://github.com/xojs/stylelint-config-xo) - Stylelint shareable config for XO with tab indent
438- [stylelint-config-xo-space](https://github.com/xojs/stylelint-config-xo-space) - Stylelint shareable config for XO with 2-space indent
439- [tslint-xo](https://github.com/xojs/tslint-xo) - TSLint shareable config for XO
440- [eslint-config-xo-typescript](https://github.com/xojs/eslint-config-xo-typescript) - ESLint shareable config for TypeScript
441- [eslint-config-xo-flow](https://github.com/xojs/eslint-config-xo-flow) - ESLint shareable config for Flow
442
443## Support
444
445- [Twitter](https://twitter.com/sindresorhus)
446
447## Related
448
449- [eslint-plugin-unicorn](https://github.com/sindresorhus/eslint-plugin-unicorn) - Various awesome ESLint rules *(Bundled in XO)*
450- [xo-summary](https://github.com/LitoMore/xo-summary) - Display output from `xo` as a list of style errors, ordered by count
451
452## Badge
453
454Show the world you're using XO → [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo)
455
456```md
457[![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo)
458```
459
460You can also find some nice dynamic XO badges on [badgen.net](https://badgen.net/#xo).
461
462## Team
463
464[![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)
465---|---|---
466[Sindre Sorhus](https://sindresorhus.com) | [Mario Nebl](https://github.com/marionebl) | [Pierre Vanduynslager](https://github.com/pvdlg)
467
468###### Former
469
470- [James Talmage](https://github.com/jamestalmage)
471- [Michael Mayer](https://github.com/schnittstabil)