❤️ JavaScript/TypeScript linter (ESLint wrapper) with great defaults

Overview


XO


JavaScript/TypeScript linter (ESLint wrapper) with great defaults

Coverage Status XO code style

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 [<file|glob> ...]

  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]
    --cwd=<dir>       Working directory for files
    --stdin           Validate/fix code from stdin
    --stdin-filename  Specify a filename for the --stdin option
    --print-config    Print the ESLint configuration for the given file

  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
    $ xo --print-config=index.js

  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:

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, .jsx, .mjs, and .cjs. 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-parser if you're using language features that ESLint doesn't yet support.

processor

Type: string

ESLint processor.

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

GitHub Actions

XO uses a different formatter when running in a GitHub Actions workflow to be able to get inline annotations. XO also disables warnings here.

Note: For this to work, the setup-node action must be run before 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",
				"space": 3
			},
			{
				 "files": "test/foo.js",
				 "semicolon": 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. The resulting config is:

{
	"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:
{
	"semicolon": true,
	"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
Comments
  • Slow when linting a single file

    Slow when linting a single file

    xo seems to load really slowly when linting a single file. The main issue from what I can see relies around eslint:glob-util and loading plugin:unicorn/recommended because of these two the lint can take upwards of 2 seconds to lint a 19 line file. This doesn't sound so bad until you take into account it takes the same time when running in atom with the atom-linter-xo package.

    I used this to run xo DEBUG=* xo js/helpers/config.js.

    This is the file I was linting.

    // @TODO: Setup defaults so we can use config before the api resolves the request
    export default {
        baseUrl: $('body').attr('base-url'),
        token: $('body').attr('token'),
        posterSortby: undefined,
        animeSplitHome: undefined,
        rootDirs: undefined,
        selectedRootIndex: undefined,
        layout: {
            show: {
                specials: true,
                allSeasons: true
            },
            home: 'banner',
            history: 'detailed',
            schedule: 'banner'
        }
    };
    
    xo Using local install of XO. +0ms
      eslint:config-file Loading /Users/xo/code/Medusa/node_modules/xo/config/plugins.js +0ms
      eslint:config-file Loading JS config file: /Users/xo/code/Medusa/node_modules/xo/config/plugins.js +3ms
      eslint:config-file Loading plugin:unicorn/recommended +741ms
      eslint:config-file Attempting to resolve eslint-plugin-unicorn +1ms
      eslint:config-file Loading JS config file: /Users/xo/code/Medusa/node_modules/eslint-plugin-unicorn/index.js +1ms
      eslint:config-file Loading plugin:ava/recommended +5ms
      eslint:config-file Attempting to resolve eslint-plugin-ava +1ms
      eslint:config-file Loading JS config file: /Users/xo/code/Medusa/node_modules/eslint-plugin-ava/index.js +0ms
      eslint:config-file Loading /Users/xo/code/Medusa/node_modules/xo/config/overrides.js +8ms
      eslint:config-file Loading JS config file: /Users/xo/code/Medusa/node_modules/xo/config/overrides.js +0ms
      eslint:config-file Loading xo +2ms
      eslint:config-file Attempting to resolve eslint-config-xo +0ms
      eslint:config-file Loading JS config file: /Users/xo/code/Medusa/node_modules/eslint-config-xo/index.js +1ms
      eslint:glob-util Creating list of files to process. +620ms
      eslint:ignored-paths Looking for ignore file in /Users/xo/code/Medusa +7ms
      eslint:ignored-paths Could not find ignore file in cwd +0ms
      eslint:config Constructing config for /Users/xo/code/Medusa/js/helpers/config.js +7ms
      eslint:config Not using .eslintrc or package.json files +0ms
      eslint:config Merging command line environment settings +0ms
      eslint:config Merging command line rules +1ms
      eslint:config Merging command line plugins +0ms
      eslint:config-ops Apply environment settings to config +0ms
      eslint:config-ops Creating config for environment node +1ms
      eslint:config-ops Creating config for environment es6 +0ms
      eslint:config-ops Creating config for environment browser +0ms
      eslint:config-ops Creating config for environment jquery +1ms
      eslint:cli-engine Processing /Users/xo/code/Medusa/js/helpers/config.js +12ms
      eslint:cli-engine Linting /Users/xo/code/Medusa/js/helpers/config.js +1ms
      eslint:config Constructing config for /Users/xo/code/Medusa/js/helpers/config.js +1ms
      eslint:config Using config from cache +0ms
      eslint:code-path onCodePathStart s1 +200ms
      eslint:code-path onCodePathSegmentStart s1_1 +3ms
      eslint:code-path s1_1) Program +2ms
      eslint:code-path s1_1) ExportDefaultDeclaration +46ms
      eslint:code-path s1_1) ObjectExpression +6ms
      eslint:code-path s1_1) Property +10ms
      eslint:code-path s1_1) Identifier +3ms
      eslint:code-path s1_1) Identifier:exit +2ms
      eslint:code-path s1_1) CallExpression +0ms
      eslint:code-path s1_1) MemberExpression +8ms
      eslint:code-path s1_1) CallExpression +3ms
      eslint:code-path s1_1) Identifier +2ms
      eslint:code-path s1_1) Identifier:exit +0ms
      eslint:code-path s1_1) Literal +0ms
      eslint:code-path s1_1) Literal:exit +3ms
      eslint:code-path s1_1) CallExpression:exit +0ms
      eslint:code-path s1_1) Identifier +1ms
      eslint:code-path s1_1) Identifier:exit +0ms
      eslint:code-path s1_1) MemberExpression:exit +0ms
      eslint:code-path s1_1) Literal +0ms
      eslint:code-path s1_1) Literal:exit +1ms
      eslint:code-path s1_1) CallExpression:exit +0ms
      eslint:code-path s1_1) Property:exit +0ms
      eslint:code-path s1_1) Property +0ms
      eslint:code-path s1_1) Identifier +0ms
      eslint:code-path s1_1) Identifier:exit +1ms
      eslint:code-path s1_1) CallExpression +0ms
      eslint:code-path s1_1) MemberExpression +1ms
      eslint:code-path s1_1) CallExpression +0ms
      eslint:code-path s1_1) Identifier +1ms
      eslint:code-path s1_1) Identifier:exit +1ms
      eslint:code-path s1_1) Literal +0ms
      eslint:code-path s1_1) Literal:exit +0ms
      eslint:code-path s1_1) CallExpression:exit +0ms
      eslint:code-path s1_1) Identifier +0ms
      eslint:code-path s1_1) Identifier:exit +1ms
      eslint:code-path s1_1) MemberExpression:exit +0ms
      eslint:code-path s1_1) Literal +0ms
      eslint:code-path s1_1) Literal:exit +0ms
      eslint:code-path s1_1) CallExpression:exit +0ms
      eslint:code-path s1_1) Property:exit +0ms
      eslint:code-path s1_1) Property +0ms
      eslint:code-path s1_1) Identifier +0ms
      eslint:code-path s1_1) Identifier:exit +1ms
      eslint:code-path s1_1) Identifier +0ms
      eslint:code-path s1_1) Identifier:exit +0ms
      eslint:code-path s1_1) Property:exit +0ms
      eslint:code-path s1_1) Property +0ms
      eslint:code-path s1_1) Identifier +1ms
      eslint:code-path s1_1) Identifier:exit +0ms
      eslint:code-path s1_1) Identifier +0ms
      eslint:code-path s1_1) Identifier:exit +0ms
      eslint:code-path s1_1) Property:exit +0ms
      eslint:code-path s1_1) Property +0ms
      eslint:code-path s1_1) Identifier +1ms
      eslint:code-path s1_1) Identifier:exit +0ms
      eslint:code-path s1_1) Identifier +0ms
      eslint:code-path s1_1) Identifier:exit +0ms
      eslint:code-path s1_1) Property:exit +0ms
      eslint:code-path s1_1) Property +0ms
      eslint:code-path s1_1) Identifier +2ms
      eslint:code-path s1_1) Identifier:exit +0ms
      eslint:code-path s1_1) Identifier +0ms
      eslint:code-path s1_1) Identifier:exit +1ms
      eslint:code-path s1_1) Property:exit +0ms
      eslint:code-path s1_1) Property +1ms
      eslint:code-path s1_1) Identifier +0ms
      eslint:code-path s1_1) Identifier:exit +0ms
      eslint:code-path s1_1) ObjectExpression +0ms
      eslint:code-path s1_1) Property +1ms
      eslint:code-path s1_1) Identifier +0ms
      eslint:code-path s1_1) Identifier:exit +1ms
      eslint:code-path s1_1) ObjectExpression +0ms
      eslint:code-path s1_1) Property +0ms
      eslint:code-path s1_1) Identifier +0ms
      eslint:code-path s1_1) Identifier:exit +0ms
      eslint:code-path s1_1) Literal +1ms
      eslint:code-path s1_1) Literal:exit +0ms
      eslint:code-path s1_1) Property:exit +0ms
      eslint:code-path s1_1) Property +0ms
      eslint:code-path s1_1) Identifier +0ms
      eslint:code-path s1_1) Identifier:exit +0ms
      eslint:code-path s1_1) Literal +0ms
      eslint:code-path s1_1) Literal:exit +0ms
      eslint:code-path s1_1) Property:exit +1ms
      eslint:code-path s1_1) ObjectExpression:exit +0ms
      eslint:code-path s1_1) Property:exit +0ms
      eslint:code-path s1_1) Property +0ms
      eslint:code-path s1_1) Identifier +0ms
      eslint:code-path s1_1) Identifier:exit +0ms
      eslint:code-path s1_1) Literal +1ms
      eslint:code-path s1_1) Literal:exit +0ms
      eslint:code-path s1_1) Property:exit +0ms
      eslint:code-path s1_1) Property +0ms
      eslint:code-path s1_1) Identifier +0ms
      eslint:code-path s1_1) Identifier:exit +1ms
      eslint:code-path s1_1) Literal +1ms
      eslint:code-path s1_1) Literal:exit +1ms
      eslint:code-path s1_1) Property:exit +0ms
      eslint:code-path s1_1) Property +0ms
      eslint:code-path s1_1) Identifier +1ms
      eslint:code-path s1_1) Identifier:exit +7ms
      eslint:code-path s1_1) Literal +1ms
      eslint:code-path s1_1) Literal:exit +1ms
      eslint:code-path s1_1) Property:exit +0ms
      eslint:code-path s1_1) ObjectExpression:exit +0ms
      eslint:code-path s1_1) Property:exit +0ms
      eslint:code-path s1_1) ObjectExpression:exit +0ms
      eslint:code-path s1_1) ExportDefaultDeclaration:exit +0ms
      eslint:code-path s1_1) Program:exit +1ms
      eslint-plugin-import:rules:newline-after-import exit processing for /Users/xo/code/Medusa/js/helpers/config.js +17ms
      eslint-plugin-import:rules:newline-after-import got scope: [ Node {
        type: 'ExportDefaultDeclaration',
        start: 83,
        end: 482,
        loc: SourceLocation { start: [Object], end: [Object] },
        range: [ 83, 482 ],
        declaration: 
         Node {
           type: 'ObjectExpression',
           start: 98,
           end: 481,
           loc: [Object],
           range: [Object],
           properties: [Object],
           parent: [Circular] },
        leadingComments: [ [Object] ],
        parent: 
         Node {
           type: 'Program',
           start: 0,
           end: 483,
           loc: [Object],
           range: [Object],
           body: [Circular],
           sourceType: 'module',
           comments: [Object],
           tokens: [Object],
           parent: null } } ] +0ms
      eslint:code-path onCodePathSegmentEnd s1_1 +8ms
      eslint:code-path onCodePathEnd s1 +1ms
      eslint:code-path DOT 
    digraph {
    node[shape=box,style="rounded,filled",fillcolor=white];
    initial[label="",shape=circle,style=filled,fillcolor=black,width=0.25,height=0.25];
    final[label="",shape=doublecircle,style=filled,fillcolor=black,width=0.25,height=0.25];
    s1_1[label="Program\nExportDefaultDeclaration\nObjectExpression\nProperty\nIdentifier (baseUrl)\nCallExpression\nMemberExpression\nCallExpression\nIdentifier ($)\nLiteral (body)\nIdentifier (attr)\nLiteral (base-url)\nProperty\nIdentifier (token)\nCallExpression\nMemberExpression\nCallExpression\nIdentifier ($)\nLiteral (body)\nIdentifier (attr)\nLiteral (token)\nProperty\nIdentifier (posterSortby)\nIdentifier (undefined)\nProperty\nIdentifier (animeSplitHome)\nIdentifier (undefined)\nProperty\nIdentifier (rootDirs)\nIdentifier (undefined)\nProperty\nIdentifier (selectedRootIndex)\nIdentifier (undefined)\nProperty\nIdentifier (layout)\nObjectExpression\nProperty\nIdentifier (show)\nObjectExpression\nProperty\nIdentifier (specials)\nLiteral (true)\nProperty\nIdentifier (allSeasons)\nLiteral (true)\nProperty\nIdentifier (home)\nLiteral (banner)\nProperty\nIdentifier (history)\nLiteral (detailed)\nProperty\nIdentifier (schedule)\nLiteral (banner)\nIdentifier:exit (baseUrl)\nIdentifier:exit ($)\nLiteral:exit (body)\nCallExpression:exit\nIdentifier:exit (attr)\nMemberExpression:exit\nLiteral:exit (base-url)\nCallExpression:exit\nProperty:exit\nIdentifier:exit (token)\nIdentifier:exit ($)\nLiteral:exit (body)\nCallExpression:exit\nIdentifier:exit (attr)\nMemberExpression:exit\nLiteral:exit (token)\nCallExpression:exit\nProperty:exit\nIdentifier:exit (posterSortby)\nIdentifier:exit (undefined)\nProperty:exit\nIdentifier:exit (animeSplitHome)\nIdentifier:exit (undefined)\nProperty:exit\nIdentifier:exit (rootDirs)\nIdentifier:exit (undefined)\nProperty:exit\nIdentifier:exit (selectedRootIndex)\nIdentifier:exit (undefined)\nProperty:exit\nIdentifier:exit (layout)\nIdentifier:exit (show)\nIdentifier:exit (specials)\nLiteral:exit (true)\nProperty:exit\nIdentifier:exit (allSeasons)\nLiteral:exit (true)\nProperty:exit\nObjectExpression:exit\nProperty:exit\nIdentifier:exit (home)\nLiteral:exit (banner)\nProperty:exit\nIdentifier:exit (history)\nLiteral:exit (detailed)\nProperty:exit\nIdentifier:exit (schedule)\nLiteral:exit (banner)\nProperty:exit\nObjectExpression:exit\nProperty:exit\nObjectExpression:exit\nExportDefaultDeclaration:exit\nProgram:exit"];
    initial->s1_1->final;
    } +3ms
      eslint:cli-engine Linting complete in: 389ms +4ms
    
    help wanted 
    opened by OmgImAlexis 43
  • Unable to find no-empty-blocks plugin though npm says is loaded

    Unable to find no-empty-blocks plugin though npm says is loaded

    Since updating my deps and re doing npm install I now get errors

    $ npm list eslint-plugin-no-empty-blocks
    [email protected] C:\projects\brian
    └─┬ [email protected]
      └── [email protected]
    
    > [email protected] lint C:\projects\brian
    > xo ./client/src/js/**/*.js
    
    Error: Failed to load plugin no-empty-blocks: Cannot find module 'eslint-plugin-no-empty-blocks'
    Referenced from:
        at Function.Module._resolveFilename (module.js:325:15)
        at Function.Module._load (module.js:276:25)
        at Module.require (module.js:353:17)
        at require (internal/module.js:12:17)
        at Object.module.exports.load (C:\projects\brian\node_modules\eslint\lib\config\plugins.js:116:26)
        at Array.forEach (native)
        at Object.module.exports.loadAll (C:\projects\brian\node_modules\eslint\lib\config\plugins.js:138:21)
        at load (C:\projects\brian\node_modules\eslint\lib\config\config-file.js:470:21)
        at C:\projects\brian\node_modules\eslint\lib\config\config-file.js:369:36
        at Array.reduceRight (native)
    

    part of package.json:

    "xo": {
        "esnext": true,
        "semicolon": false,
        "space": 2,
        "envs": [
          "browser",
          "node"
        ],
        "plugins": [
          "immutable"
        ],
        "rules": {
          "babel/new-cap": 0,
          "comma-dangle": [
            2,
            "only-multiline"
          ],
          "immutable/no-let": 2,
          "immutable/no-this": 2,
          "immutable/no-mutation": 2,
          "no-var": 2,
          "no-undef": 2,
          "no-param-reassign": 2
        }
      }
    }
    
    bug 
    opened by SteveALee 32
  • Add TypeScript support

    Add TypeScript support

    Fix #373 Fix xojs/eslint-config-xo-typescript#15

    Xo will now automatically lint .ts and .tsx with the config from eslint-config-xo-typescript. No configuration needed!


    IssueHunt Summary

    Referenced issues

    This pull request has been submitted to:


    IssueHunt has been backed by the following sponsors. Become a sponsor

    opened by pvdlg 29
  • Huge memory usage regression: 580 MB in 0.43 → 6300 MB in 0.44

    Huge memory usage regression: 580 MB in 0.43 → 6300 MB in 0.44

    Using Node.js 14.17.5 with NPM 6.14.14 for this reproduction recipe (npx works slightly differently in NPM 7).

    $ git clone -b v5.8.1 https://github.com/zulip/zulip-desktop.git
    $ cd zulip-desktop
    $ npm i
    $ rm -rf node_modules/.cache
    $ npx -p [email protected] time xo
    …
      110 errors
    Command exited with non-zero status 1
    45.72user 0.89system 0:28.89elapsed 161%CPU (0avgtext+0avgdata 581408maxresident)k
    0inputs+0outputs (0major+155120minor)pagefaults 0swaps
    $ rm -rf node_modules/.cache
    $ npx -p [email protected] time xo
    …
    FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
    …
    Command terminated by signal 6
    200.27user 7.35system 1:29.69elapsed 231%CPU (0avgtext+0avgdata 2274772maxresident)k
    0inputs+0outputs (0major+717566minor)pagefaults 0swaps
    $ rm -rf node_modules/.cache
    $ NODE_OPTIONS=--max-old-space-size=8192 npx -p [email protected] time xo
    …
      148 errors
    Command exited with non-zero status 1
    182.59user 5.34system 1:54.32elapsed 164%CPU (0avgtext+0avgdata 6284536maxresident)k
    2808inputs+0outputs (2major+1631648minor)pagefaults 0swaps
    
    

    I bisected this memory usage regression to e2e715dbff660187d432a6bdad6c3da435f80194 “Simplify lintFiles (#583)”. Cc @fisker.

    bug 
    opened by andersk 28
  • Too slow on large projects

    Too slow on large projects

    Description

    I am using XO and Ava in a large project. Both packages are too slow to be used. I never actually tried to let them finish. I usually give up after 10+ minutes. I first thought this might be related to globby: https://github.com/sindresorhus/globby/issues/43

    As mentioned in that issue I created a test source that reproduces this issue. The glob targets a folder that exists only once.

    I opened a separate issue in Ava. https://github.com/avajs/ava/issues/1418

    Test Source

    • https://github.com/pixelass/ava-xo-test
    • https://github.com/pixelass/ava-xo-test/blob/3f9f228f279804d8634a367f5458f69ffbc7d253/one/a/b/c/d/e/f/g/h/i/j/this-is-it

    Error Message & Stack Trace

    nothing happens

    Config

    https://github.com/pixelass/ava-xo-test/blob/3f9f228f279804d8634a367f5458f69ffbc7d253/package.json#L35-L41

    {
      "xo": {
        "ignores": [
          "node_modules/*"
        ],
        "rules": {
          "import/no-unassigned-import": 0
        }
      }
    }
    

    Command-Line Arguments

    https://github.com/pixelass/ava-xo-test/blob/3f9f228f279804d8634a367f5458f69ffbc7d253/package.json#L10

    {
    "scripts": {
        "xo": "xo --quiet './**/*.js'"
      },
    }
    
    xo --quiet './**/*.js
    

    Relevant Links

    Minimal reproduction:
    https://github.com/pixelass/ava-xo-test/

    Environment

    OS X 10.12.5 (16F73)  
    Node 6.11.0  
    

    Requested log:

    Platform: darwin 16.6.0
    xo: 0.18.2
    node: 6.11.0
    npm: 3.10.10
    
    opened by pixelass 28
  • Prefer locally installed version, fall back to global.

    Prefer locally installed version, fall back to global.

    Use whatever version of xo is installed locally in node_modules, before using the globally installed version.

    Fairly naive implementation, but it works and is backward compatible as far back as I checked (0.7.x).

    I disable update-notifier if a local version is found. That could maybe be improved upon by still notifying if local is out of date. update-notifier seems to always recommend installation with the -g flag though.

    opened by jamestalmage 25
  • Add ability to ignore directories

    Add ability to ignore directories

    Issuehunt badges

    https://github.com/joakimbeng/unistyle/commit/4dfa6bc4137c47aaee00662bc079eac79df64422#commitcomment-13087626

    Right now you have to do directory/** to ignore all files in a directory, but would be nice, and probably more natural, if you could ignore a directroy directly by using directroy.


    IssueHunt Summary

    sindresorhus sindresorhus has been rewarded.

    Backers (Total: $60.00)

    Submitted pull Requests


    Tips

    enhancement help wanted :gift: Rewarded on Issuehunt 
    opened by sindresorhus 23
  • Prefer `Reflect.deleteProperty` over the `delete` keyword in ES2015?

    Prefer `Reflect.deleteProperty` over the `delete` keyword in ES2015?

    ESLint 1.2.0 came with a new ES2015 rule called prefer-reflect that suggests Reflect where applicable.

    The only method I'm unsure about is preferring Reflect.deleteProperty over the delete keyword.

    https://github.com/sindresorhus/eslint-config-xo/commit/8b16afce0fc7e1f899c62bf14cf7df0781fd2f94#diff-52091282b1c3f2e056102160d5de3ec2R35

    Thoughts?

    Also, does it make sense to use Reflect over the other methods, like call, apply, etc?

    question 
    opened by sindresorhus 23
  • Add support for TypeScript and document usage with Flow

    Add support for TypeScript and document usage with Flow

    Fixes #315

    Allows TypeScript and Flow files to be parsed by XO by setting "flow": true or "typescript": true in the config.

    I think the error messages can be improved a bit. And I'm not 100% sure if that's where this particular block of code should go, but it works.

    Also there is probably a better way to get the devDependencies list.

    opened by jorgegonzalez 21
  • Add support for Flow

    Add support for Flow

    It seems that XO does not support Flow.

    babel-eslint could be used as the default parser and an optional option flow could be added for configuration.

    eslint-plugin-flowtype could be used

    opened by ghost 21
  • Add optional Prettier support

    Add optional Prettier support

    Add the prettier boolean options. The default value is false.

    If prettier options is set to true:

    • xo --fix will format the code with Prettier
    • xo will report errors for each snippet of code that is not formatted in accordance with Prettier format

    Under the hood it uses:

    The prettier dependency is explicitly set with ~ as some small format change can occur on minor prettier releases. This way no unexpected change will happen for xo users. They will see a potential change in formatting only after the xo team upgrade the prettier dependency version and releases a new xo version. That said, in my ~6 months of using Prettier, it happened only once that a minor version upgrade required me to change my code formatting.

    Fix #176

    opened by pvdlg 17
  • Parent Folder Config File Ignored?

    Parent Folder Config File Ignored?

    Hello, I have been trying to get a parent folder / monorepo structure up and running with all kinds of ways. Tried following the instructions on the readme.md file and all.

    However, I have not been able to do it. Next to that the xo-linter extension for VS Code also seems to not be able to find my config files.

    I tried renaming them, converting them to JSON, etc. I even tried if the package.json structure would work. No luck with any of those options for both (cli and vs code extension).

    Is there a trick that I don't know about?

    Here is my .xo-config.cjs file which I am using and when I run my xo in the folder where the config file actually is, it also works.

    Config File: ```js module.exports = { extensions: ['js', 'vue'], ignores: [ './dist', './ios', ], rules: { semi: ['error', 'never'], indent: ['error', 2, { SwitchCase: 1, }], quotes: ['error', 'single', { allowTemplateLiterals: true, }], curly: ['error', 'multi-line'], 'object-curly-spacing': ['error', 'always'], 'arrow-parens': ['error', 'always'], 'capitalized-comments': 'off', 'import/extensions': [ 'error', 'never', { json: 'always', vue: 'always', css: 'always', scss: 'always', }, ], 'node/file-extension-in-import': [ 'error', 'never', { tryExtensions: ['.js', '.json'], '.json': 'always', '.vue': 'always', '.css': 'always', '.scss': 'always', }, ], 'import/no-unassigned-import': [ 'error', { allow: ['**/*.css', '**/*.scss'], }, ], // 'no-multiple-empty-lines': ['error', { max: 2, maxEOF: 0 }], // 'padding-line-between-statements': ['error', { blankLine: 'any', prev: '*', next: '*' }], // 'no-unused-vars': ['warn', { caughtErrors: 'none', varsIgnorePattern: '^error$', args: 'none' }], // 'require-await': 'error', // 'no-return-await': 'off', 'unicorn/filename-case': [ 'error', { cases: { camelCase: true, pascalCase: true, }, ignore: ['\\d*-[\\w\\d]*.js'], }, ], // 'unicorn/prefer-optional-catch-binding': 'off', // 'unicorn/no-process-exit': 'off', }, }; ```
    opened by chrisspiegl 0
  • Re-enable `eslint-plugin-promise` as it now supports ESLint 8

    Re-enable `eslint-plugin-promise` as it now supports ESLint 8

    opened by qyurila 0
  • Problem with global installing XO via npx command

    Problem with global installing XO via npx command

    Hello. My Specs are:

    • M1 Mac with Monterey 12.5.1
    • Node 16.15.1

    When I first tried to install I got this error: Error: EPERM: operation not permitted, scandir Users/Me/.Trash I got rid of it by getting Full Disk Access to Terminal App in mac system settings. Then I had second problem with no solutions yet:

    ➜  ~ npx xo
    
    <--- Last few GCs --->
    
    [88170:0x130008000]   148976 ms: Mark-sweep 3975.7 (4137.2) -> 3965.6 (4140.4) MB, 1421.5 / 0.0 ms  (average mu = 0.146, current mu = 0.059) task scavenge might not succeed
    [88170:0x130008000]   150392 ms: Mark-sweep 3978.6 (4140.4) -> 3968.7 (4143.9) MB, 1360.5 / 0.0 ms  (average mu = 0.096, current mu = 0.039) task scavenge might not succeed
    
    
    <--- JS stacktrace --->
    
    FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
     1: 0x1026d82dc node::Abort() [/Users/zagoor/.nvm/versions/node/v16.15.1/bin/node]
     2: 0x1026d8464 node::errors::TryCatchScope::~TryCatchScope() [/Users/zagoor/.nvm/versions/node/v16.15.1/bin/node]
     3: 0x102827b90 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/Users/zagoor/.nvm/versions/node/v16.15.1/bin/node]
     4: 0x102827b24 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/Users/zagoor/.nvm/versions/node/v16.15.1/bin/node]
     5: 0x1029ab23c v8::internal::Heap::GarbageCollectionReasonToString(v8::internal::GarbageCollectionReason) [/Users/zagoor/.nvm/versions/node/v16.15.1/bin/node]
     6: 0x1029ae84c v8::internal::Heap::CollectSharedGarbage(v8::internal::GarbageCollectionReason) [/Users/zagoor/.nvm/versions/node/v16.15.1/bin/node]
     7: 0x1029aba04 v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [/Users/zagoor/.nvm/versions/node/v16.15.1/bin/node]
     8: 0x1029a932c v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/Users/zagoor/.nvm/versions/node/v16.15.1/bin/node]
     9: 0x102a23d2c v8::internal::ScavengeJob::Task::RunInternal() [/Users/zagoor/.nvm/versions/node/v16.15.1/bin/node]
    10: 0x102736084 node::PerIsolatePlatformData::RunForegroundTask(std::__1::unique_ptr<v8::Task, std::__1::default_delete<v8::Task> >) [/Users/zagoor/.nvm/versions/node/v16.15.1/bin/node]
    11: 0x102734d1c node::PerIsolatePlatformData::FlushForegroundTasksInternal() [/Users/zagoor/.nvm/versions/node/v16.15.1/bin/node]
    12: 0x102f49f00 uv__async_io [/Users/zagoor/.nvm/versions/node/v16.15.1/bin/node]
    13: 0x102f5bc78 uv__io_poll [/Users/zagoor/.nvm/versions/node/v16.15.1/bin/node]
    14: 0x102f4a390 uv_run [/Users/zagoor/.nvm/versions/node/v16.15.1/bin/node]
    15: 0x102626ccc node::SpinEventLoop(node::Environment*) [/Users/zagoor/.nvm/versions/node/v16.15.1/bin/node]
    16: 0x1027116e0 node::NodeMainInstance::Run(int*, node::Environment*) [/Users/zagoor/.nvm/versions/node/v16.15.1/bin/node]
    17: 0x1027113ac node::NodeMainInstance::Run(node::EnvSerializeInfo const*) [/Users/zagoor/.nvm/versions/node/v16.15.1/bin/node]
    18: 0x1026ab2e0 node::Start(int, char**) [/Users/zagoor/.nvm/versions/node/v16.15.1/bin/node]
    19: 0x10735908c 
    [1]    88169 abort      npx xo
    

    Is anyone faced similar problems and know how to fix it?

    opened by zagoorland 1
  • xo does not appear to use `extends: [

    xo does not appear to use `extends: ["plugin:?"]` when specified in config

    Hi! 👋🏻 thanks for this great tool, seems like it will save me a ton of time setting this all up on every project.

    I noticed that some rules I prefer, like @typescript-eslint/no-non-null-assertion wasn't included, so I attempted to add it by using the extends of xo config in package.json (and .xo-config.json while testing):

      "xo": {
        "extends": [
          "plugin:@typescript-eslint/eslint-recommended",
          "plugin:@typescript-eslint/recommended-requiring-type-checking"
        ]
      }
    

    And expected to see Forbidden non-null assertion. eslint(@typescript-eslint/no-non-null-assertion) on this code:

    document.getElementById("whatever")!
    

    but it did not appear. Running

    npx xo --print-config src/main.ts
    

    does not show the extra rules provided by the extended plugins.

    I've read through the documentation and looked through all of the issues that GitHub's issue search would show and it seems like this should work.

    I created an example repo here: https://github.com/bbugh/xo-not-using-extends - just need to run

    npm install
    npx xo --print-config src/main.ts
    
    opened by bbugh 2
  • Rules @typescript-eslint/indent and react/jsx-indent-props fight for identation

    Rules @typescript-eslint/indent and react/jsx-indent-props fight for identation

    So

                    {imgLink === ''
                        ? <div className={aniClass} id='downloadQr'>
                            <Image
                                text={`${process.env.REACT_APP_API_LINK}` + props.alias}
    ...
                            />
                        </div>
                        : <img
                            className={aniClass} // Expected indentation of 28 space characters but found 24.
                            src={imgLink || defaultProfilePicture} // Expected indentation of 28 space characters but found 24.
                                alt='User pic' // Expected indentation of 24 spaces but found 28.
                        />
                    }
    
    
    opened by godlikeSwan 3
  • Write a JSON Schema for config

    Write a JSON Schema for config

    It would be awesome to have JSON Schema support for the config file (and submit to Schema Store). Existing schema for .eslintrc is a good starting point.

    The work would probably needs to wait after #428 is resolved though.

    opened by kidonng 0
Releases(v0.53.1)
Owner
XO
❤️ JavaScript happiness style linter
XO
🐠 Babel is a compiler for writing next generation JavaScript.

The compiler for writing next generation JavaScript. Supporting Babel Babel (pronounced "babble") is a community-driven project used by many companies

Babel 41.8k Jan 8, 2023
Find and fix problems in your JavaScript code.

ESLint Website | Configuring | Rules | Contributing | Reporting Bugs | Code of Conduct | Twitter | Mailing List | Chat Room ESLint is a tool for ident

ESLint 22k Jan 8, 2023
Pipeable javascript. Quickly filter, map, and reduce from the terminal

Pipeable JavaScript - another utility like sed/awk/wc... but with JS! Quickly filter, map and reduce from the command line. Features a streaming API.

Daniel St. Jules 410 Dec 10, 2022
Pretty diff to html javascript cli (diff2html-cli)

diff2html-cli Diff to Html generates pretty HTML diffs from unified and git diff output in your terminal Table of Contents Features Online Example Dis

Rodrigo Fernandes 404 Dec 19, 2022
Discord bot template written with javascript, include slash.

Getting Started This Discord Template with Slash is an advanced, easy to setup, free, and unbranded Discord bot. Official Discord Server If you need h

null 8 Aug 22, 2021
All-in-one code linter and formatter for TypeScript and JavaScript

Uniform is a CLI tool - code linter and formatter for JavaScript and TypeScript. Works using eslint and prettier under the hood.

Irakli Dautashvili 21 Feb 27, 2022
Smarter defaults for colors on the web.

colors.css 3.0.0 Better default colors for the web. A collection of skin classes for faster prototyping and nicer looking sites. Stats 903 85 85 bytes

murmurs 9.2k Jan 9, 2023
Create your own wrappings with optional key bindings for selected text, a set of useful defaults is also provided.

Create your own wrappings with optional key bindings for selected text, a set of useful defaults is also provided.

Seth Yuan 66 Jan 1, 2023
A Remix starter with intuitive defaults, like support for internationalization and localized URLs

?? Remix Starter A Remix starter with intuitive defaults, like support for internationalization and localized URLs. Coming soon: Authentication and au

Anand Chowdhary 51 Jan 8, 2023
The Basement SDK has sensible defaults and flexibility to allow you to get the data you want efficiently and effortlessly.

Basement SDK The Basement SDK has sensible defaults and flexibility to allow you to get the data you want efficiently and effortlessly. Installation B

Basement for Developers 10 Dec 6, 2022
NodeJS library develop quick start: TypeScript + CI/CD + Release Workflow + Linter + Changelog + ...

node-lib-starter Start NodeJS + TypeScript library developing with ease, have fun! Include Lint Git Hooks Release workflow CI/CD Changelog Configurati

LinbuduLab 22 Oct 28, 2022
🌟 JavaScript Style Guide, with linter & automatic code fixer

JavaScript Standard Style Sponsored by English • Español (Latinoamérica) • Français • Bahasa Indonesia • Italiano (Italian) • 日本語 (Japanese) • 한국어 (Ko

Standard JS 27.8k Dec 31, 2022
🌟 JavaScript Style Guide, with linter & automatic code fixer

JavaScript Standard Style Sponsored by English • Español (Latinoamérica) • Français • Bahasa Indonesia • Italiano (Italian) • 日本語 (Japanese) • 한국어 (Ko

Standard JS 27.8k Dec 31, 2022
The Type Linter for JS

TypL The Type Linter for JS. Overview TypL provides optional type annotations for JS programs, so you can verify that you haven't mixed incompatible v

Kyle Simpson 352 Nov 24, 2022
🤪 A linter, prettier, and test suite that does everything as-simple-as-possible.

Features Fully Featured Code Grading Knowing if you need to work on your code is important- that's why we grade your code automatically. But, unlike o

Fairfield Programming Association 18 Sep 25, 2022
Linter for Nix using tree-sitter 🌳 + ❄️

Linter for Nix using tree-sitter ?? + ❄️ This is a simple linter for Nix that uses tree-sitter. I plan on extending it with more detections in the fut

Ben Siraphob 41 Dec 20, 2022
Yet another linter rule to detect compatibility of CSS features.

stylelint-browser-compat Yet another linter rule to detect compatibility of CSS features. This plugin checks if the CSS you're using is supported by t

Masahiro Miyashiro (3846masa) 16 Dec 15, 2022
Lightweight WebSocketServer wrapper lib using ws-wrapper to wrap connected WebSockets

ws-server-wrapper Lightweight WebSocketServer wrapper lib using ws-wrapper and ws to wrap connected WebSockets. The only dependency is ws-wrapper itse

Blake Miner 17 May 9, 2022
great circle routes in javascript

arc.js Calculate great circles routes as lines in GeoJSON or WKT format. Algorithms from https://edwilliams.org/avform.htm#Intermediate Includes basic

Dane Springmeyer 341 Dec 26, 2022
A concise collection of classes for PHP, Python, JavaScript and Ruby to calculate great circle distance, bearing, and destination from geographic coordinates

GreatCircle A set of three functions, useful in geographical calculations of different sorts. Available for PHP, Python, Javascript and Ruby. Live dem

null 72 Sep 30, 2022