xo

by xojs

xojs / xo

❤️ JavaScript linter with great defaults

5.3K Stars 285 Forks Last release: 13 days ago (v0.34.1) MIT License 436 Commits 58 Releases

Available items

No Items, yet!

The developer of this repository has not created any items for sale yet. Need a bug fixed? Help with integration? A different license? Create a request here:


XO


JavaScript/TypeScript linter with great defaults

Build Status Coverage Status XO code style Gitter

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!

Uses ESLint underneath, so issues regarding rules should be opened over there.

JSX is supported by default, but you'll need eslint-config-xo-react for React specific linting.

Vue components are not supported by default. You'll need eslint-config-xo-vue for specific linting in a Vue app.

Highlights

Install

$ npm install --global xo

Usage

$ xo --help

Usage $ xo [ ...]

Options --fix Automagically fix issues --reporter Reporter to use --env Environment preset [Can be set multiple times] --global Global variable [Can be set multiple times] --ignore Additional paths to ignore [Can be set multiple times] --space Use space indent instead of tabs [Default: 2] --no-semicolon Prevent use of semicolons --prettier Conform to Prettier code style --node-version Range of Node.js version to support --plugin Include third-party plugins [Can be set multiple times] --extend Extend defaults with a custom config [Can be set multiple times] --open Open files with issues in your editor --quiet Show only errors and no warnings --extension Additional extension to lint [Can be set multiple times] --no-esnext Don't enforce ES2015+ rules --cwd=

Working directory for files --stdin Validate/fix code from stdin --stdin-filename Specify a filename for the --stdin option

Examples $ xo $ xo index.js $ xo *.js !foo.js $ xo --space $ xo --env=node --env=mocha $ xo --plugin=react $ xo --plugin=html --extension=html $ echo 'const x=true' | xo --stdin --fix

Tips - Add XO to your project with npm init xo. - Put options in package.json instead of using flags so other tools can read it.

Note that the CLI will use your local install of XO when available, even when run globally.

Default code style

Any of these can be overridden if necessary.

  • Tab indentation (or space)
  • Semicolons (or not)
  • Single-quotes
  • No unused variables
  • Space after keyword
    if (condition) {}
  • Always
    ===
    instead of
    ==

Check out an example and the ESLint rules.

Workflow

The recommended workflow is to add XO locally to your project and run it with the tests.

Simply run

$ npm init xo
(with any options) to add XO to your package.json or create one.

Before/after

 {
    "name": "awesome-package",
    "scripts": {
-       "test": "ava",
+       "test": "xo && ava"
    },
    "devDependencies": {
-       "ava": "^2.0.0"
+       "ava": "^2.0.0",
+       "xo": "^0.25.0"
    }
 }

Then just run

$ npm test
and XO will be run before your tests.

Config

You can configure XO options with one of the following files:

  1. As JSON in the
    xo
    property in
    package.json
    :
{
    "name": "awesome-package",
    "xo": {
        "space": true
    }
}
  1. As JSON in
    .xo-config
    or
    .xo-config.json
    :
{
    "space": true
}
  1. As a JavaScript module in
    .xo-config.js
    or
    xo.config.js
    :
module.exports = {
    space: true
};

Globals and rules can be configured inline in files.

envs

Type:

string[]
\ Default:
['es2020', 'node']

Which environments your code is designed to run in. Each environment brings with it a certain set of predefined global variables.

globals

Type:

string[]

Additional global variables your code accesses during execution.

ignores

Type:

string[]

Some paths are ignored by default, including paths in

.gitignore
and .eslintignore. Additional ignores can be added here.

space

Type:

boolean | number
\ Default:
false
(tab indentation)

Set it to

true
to get 2-space indentation or specify the number of spaces.

This option exists for pragmatic reasons, but I would strongly recommend you read "Why tabs are superior".

rules

Type:

object

Override any of the default rules. See the ESLint docs for more info on each rule.

Please take a moment to consider if you really need to use this option.

semicolon

Type:

boolean
\ Default:
true
(Semicolons required)

Set it to

false
to enforce no-semicolon style.

prettier

Type:

boolean
\ Default:
false

Format code with Prettier.

The Prettier options will be read from the Prettier config and if not set will be determined as follow: - semi: based on semicolon option - useTabs: based on space option - tabWidth: based on space option - trailingComma:

none
- singleQuote:
true
- bracketSpacing:
false
- jsxBracketSameLine:
false

If contradicting options are set for both Prettier and XO an error will be thrown.

nodeVersion

Type:

string | boolean
\ Default: Value of the
engines.node
key in the project
package.json

Enable rules specific to the Node.js versions within the configured range.

If set to

false
, no rules specific to a Node.js version will be enabled.

plugins

Type:

string[]

Include third-party plugins.

extends

Type:

string | string[]

Use one or more shareable configs or plugin configs to override any of the default rules (like

rules
above).

extensions

Type:

string[]

Allow more extensions to be linted besides

.js
and
.jsx
. Make sure they're supported by ESLint or an ESLint plugin.

settings

Type:

object

Shared ESLint settings exposed to rules.

parser

Type:

string

ESLint parser. For example,

babel-eslint
if you're using language features that ESLint doesn't yet support.

esnext

Type:

boolean
\ Default:
true

Enforce ES2015+ rules. Disabling this will make it not enforce ES2015+ syntax and conventions.

*ES2015+ is parsed even without this option. You can already use ES2017 features like

async
/
await
.

webpack

Type:

boolean | object
Default:
false

Use eslint-import-resolver-webpack to resolve import search paths. This is enabled automatically if a

webpack.config.js
file is found.

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 along with the webpack documentation for more information.

TypeScript and Flow

TypeScript

XO will automatically lint TypeScript files (

.ts
,
.d.ts
and
.tsx
) with the rules defined in eslint-config-xo-typescript#use-with-xo.

XO will handle the @typescript-eslint/parser

project
option automatically even if you don't have a

tsconfig.json
in your project.

Flow

See eslint-config-xo-flow#use-with-xo

Config Overrides

XO 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:
{
    "xo": {
        "semicolon": false,
        "space": 2,
        "overrides": [
            {
                "files": "test/*.js",
                "esnext": false,
                "space": 3
            },
            {
                 "files": "test/foo.js",
                 "esnext": true
            }
        ]
    }
}
  • The base configuration is simply

    space: 2
    ,
    semicolon: false
    . These settings are used for every file unless otherwise noted below.
  • 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:
{
    "esnext": false,
    "semicolon": false,
    "space": 3
}
  • 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:
{
    "esnext": true,
    "semicolon": false,
    "space": 3
}

Tips

Using a parent's config

If 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
.

Monorepo

Put a

package.json
with your config at the root and omit the
xo
property in the
package.json
of your bundled packages.

Transpilation

If some files in your project are transpiled in order to support an older Node.js version, you can use the config overrides option to set a specific

nodeVersion
to target your sources files.

For example, if your project targets Node.js 8 but you want to use the latest JavaScript syntax as supported in Node.js 12: 1. Set the

engines.node
property of your
package.json
to
>=8
2. Configure Babel to transpile your source files (in
src
directory in this example) 3. Make sure to include the transpiled files in your published package with the
files
and
main
properties of your
package.json
4. Configure the XO
overrides
option to set
nodeVersion
to
>=12
for your source files directory
{
    "engines": {
        "node": ">=8"
    },
    "scripts": {
        "build": "babel src --out-dir dist"
    },
    "main": "dist/index.js",
    "files": ["dist/**/*.js"],
    "xo": {
        "overrides": [
            {
                "files": "{src}/**/*.js",
                "nodeVersion": ">=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 12.

Including files ignored by default

To include files that XO ignores by default, add them as negative globs in the

ignores
option:
{
    "xo": {
        "ignores": [
            "!vendor/**"
        ]
    }
}

FAQ

What does XO mean?

It means hugs and kisses.

Why not Standard?

The Standard style 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.

Why not ESLint?

XO 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.

Editor plugins

Build-system plugins

Configs

Support

Related

Badge

Show the world you're using XO → XO code style

[![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo)

You can also find some nice dynamic XO badges on badgen.net.

Team

Sindre Sorhus

Mario Nebl Pierre Vanduynslager
Sindre Sorhus Mario Nebl Pierre Vanduynslager

Former

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.