newneostandard
v0.14.3
Published
A modern successor to standard
Readme
A spiritual successor to the standard
javascript style guide.
Fork
This is a fork of neostandard, updated to work with eslint version 10.
[!IMPORTANT] ESLint 10 + JSX: This release supports ESLint 10 (while keeping ESLint 9 support). JSX/TSX files are still parsed and the JSX style rules still apply, but the React-specific logic rules (from
eslint-plugin-react) are temporarily removed becauseeslint-plugin-reactis not yet compatible with ESLint 10 (jsx-eslint/eslint-plugin-react#3977). They return once a v10-compatible React plugin is adopted. Tracking: #350.
[!NOTE] ESM, Node.js and TypeScript versions: newneostandard is now an ESM package requiring Node.js
^22.13.0 || >=24. CommonJS configs keep working unchanged —require('newneostandard')returns thenewneostandardfunction withpluginsandresolveIgnoresFromGitignoreattached, same as before (they are also proper ESM named exports, the preferred form). For thetsoption, the supported TypeScript range for the installedtypescriptpackage tops out at 6.0 (typescript-eslint's peer is<6.1.0, and TypeScript 7 ships no compiler API for tooling until 7.1) — TypeScript 7 users should installtypescript@npm:@typescript/typescript6for linting and alias TS7 separately fortsc, per Microsoft's side-by-side guidance.
Table of Contents
- Quick Start
- Configuration options
- Extending
- Additional exports
- Missing for 1.0.0 release
- Differences to standard / eslint-config-standard 17.x
- Config helper
- Readme badges
- Mission statement
- Governance
- Used by
Quick Start
Migrate from standard
npm install -D newneostandard eslint- (Validate that it runs cleanly by running
npx newneostandard --help, see #267) npx newneostandard --migrate > eslint.config.js(uses our config helper)- Replace
standardwitheslintin all places where you runstandard, eg."scripts"and.github/workflows/(newneostandardCLI tracked in #2) - (Add ESLint editor integration, eg. VS Code ESLint extension)
- Cleanup:
npm uninstall standard- Remove unused
"standard"top level key from yourpackage.json - Deactivate
standardspecific integrations if you no longer use them (eg. vscode-standard))
Add to new project
npm install -D newneostandard eslintAdd an
eslint.config.js:Using config helper:
npx newneostandard --esm > eslint.config.jsOr to get CommonJS:
npx newneostandard > eslint.config.jsOr manually create the file as ESM:
import { newneostandard } from 'newneostandard' export default newneostandard({ // options })Or as CommonJS:
module.exports = require('newneostandard')({ // options })Run
newneostandardby running ESLint, eg. usingnpx eslint,npx eslint --fixor similar
Configuration options
All examples below use ESM (ECMAScript Modules) syntax. If you're using CommonJS (CJS), replace the import/export statements with the following:
// Replace
import { newneostandard } from 'newneostandard'
export default newneostandard({ /* options */ })
// With
const newneostandard = require('newneostandard')
module.exports = newneostandard({ /* options */ })Here's a basic example of how to configure newneostandard:
import { newneostandard } from 'newneostandard'
export default newneostandard({
ts: true, // an option
// Add other options here
})The options below allow you to customize newneostandard for your project. Use them to add global variables, ignore files, enable TypeScript support, and more.
env-string[]- adds additional globals by importing them from the globals npm moduleimport { newneostandard } from 'newneostandard' export default newneostandard({ env: ['browser', 'mocha'], // Add browser and mocha global variables })files-string[]- additional file patterns to match. Uses the same shape as ESLintfilesimport { newneostandard } from 'newneostandard' export default newneostandard({ files: ['src/**/*.js', 'tests/**/*.js'], // Also lint these patterns (newneostandard's built-in JS/TS patterns still apply) })filesTs-string[]- additional file patterns for the TypeScript configs to match. Uses the same shape as ESLintfilesimport { newneostandard } from 'newneostandard' export default newneostandard({ ts: true, // Enable TypeScript support filesTs: ['src/**/*.ts', 'tests/**/*.ts'], // Also lint these as TypeScript (newneostandard's built-in TS patterns still apply) })globals-string[] | object- an array of names of globals or an object of the same shape as ESLintlanguageOptions.globalsUsing an array:
import { newneostandard } from 'newneostandard' export default newneostandard({ globals: ['$', 'jQuery'], // Treat $ and jQuery as global variables })Using an object:
import { newneostandard } from 'newneostandard' export default newneostandard({ globals: { $: 'readonly', // $ is a read-only global jQuery: 'writable', // jQuery can be modified localStorage: 'off', // Disable the localStorage global }, })ignores-string[]- an array of glob patterns for files that the config should not apply to, see ESLint documentation for detailsimport { newneostandard } from 'newneostandard' export default newneostandard({ ignores: ['dist/**/*', 'tests/**'], // Ignore files in dist/ and tests/ directories })noJsx-boolean- if set, skips JSX parsing and the JSX style rules. (Note: the React-specific logic rules are currently not included regardless — pending ESLint 10 support; see the note at the top and #350)noStyle-boolean- if set, no style rules will be added. Especially useful when combined with Prettier, dprint or similarimport { newneostandard } from 'newneostandard' export default newneostandard({ noStyle: true, // Disable style-related rules (useful with Prettier or dprint) })semi-boolean- if set, enforce rather than forbid semicolons (same assemistandarddid)import { newneostandard } from 'newneostandard' export default newneostandard({ semi: true, // Enforce semicolons (like semistandard) })ts-boolean- if set, TypeScript syntax will be supported and*.ts(including*.d.ts) will be checked. To add additional file patterns to the TypeScript checks, usefilesTsimport { newneostandard } from 'newneostandard' export default newneostandard({ ts: true, // Enable TypeScript support and lint .ts files })
Extending
The newneostandard() function returns an ESLint config array which is intended to be exported directly or, if you want to modify or extend the config, can be combined with other configs using ESLint's defineConfig helper (from eslint/config):
import { defineConfig } from 'eslint/config'
import { newneostandard } from 'newneostandard'
import jsdoc from 'eslint-plugin-jsdoc'
export default defineConfig([
...newneostandard(),
jsdoc.configs['flat/recommended-typescript-flavor'],
])Do note that newneostandard() is intended to be a complete linting config in itself, only extend it if you have needs that goes beyond what newneostandard provides, and open an issue if you believe newneostandard itself should be extended or changed in that direction.
It's recommended to stay compatible with the plain config when extending and only make your config stricter, not relax any of the rules, as your project would then still pass when using just the plain newneostandard-config, which helps people know what baseline to expect from your project.
[!WARNING] Scope your rule-tweak layers. newneostandard defines its plugins only for the JS/TS files it owns, so a config object that adjusts eg.
@stylistic/*rules without afilesscope applies to every lintable file — and as soon as any other language is linted (package.jsonviaeslint-plugin-package-json,@eslint/json,@eslint/markdown, …) that file sees a rule for a plugin that isn't defined there, which is a fatalcould not find pluginconfig error. Scope such layers with the exportedglobs:import { defineConfig } from 'eslint/config' import { globs, newneostandard } from 'newneostandard' export default defineConfig([ ...newneostandard(), { files: [...globs.all], // the same files newneostandard itself touches rules: { '@stylistic/comma-dangle': ['warn', { arrays: 'always-multiline' }], }, }, ])
Linting other languages (Markdown, JSON, …)
newneostandard scopes all of its rules to the JavaScript and TypeScript files it owns (.js, .cjs, .mjs, .jsx, .ts, .tsx, plus whatever you add through the files / filesTs options). It will not apply its rules to other languages, so it composes directly with the official ESLint language plugins:
import { defineConfig } from 'eslint/config'
import { newneostandard } from 'newneostandard'
import markdown from '@eslint/markdown'
import json from '@eslint/json'
export default defineConfig([
...newneostandard(),
...markdown.configs.recommended,
{ ...json.configs.recommended, files: ['**/*.json'], language: 'json/json' },
])Fenced code blocks inside Markdown (the virtual *.md/*.js files produced by @eslint/markdown's processor) are intentionally not linted by newneostandard for now — see #296. To lint them yourself, add your own config block scoped to **/*.md/**.
If you need to apply newneostandard to a non-default set of files (or scope it to a subdirectory), wrap it with ESLint's defineConfig and its extends — the parent files/ignores propagate into every layer:
import { defineConfig } from 'eslint/config'
import { newneostandard } from 'newneostandard'
export default defineConfig([
{ files: ['packages/app/**/*.js'], extends: [newneostandard()] },
])Adding back import checking
As of newneostandard v0.13.0, eslint-plugin-import-x has been removed to reduce dependency weight and installation complexity. For most projects, TypeScript's compiler (tsc) provides superior import/export checking with full project context.
If you still need ESLint-based import checking, you can add it back manually:
import { defineConfig } from 'eslint/config'
import { newneostandard } from 'newneostandard'
import importX from 'eslint-plugin-import-x'
export default defineConfig([
...newneostandard(),
{
plugins: {
'import-x': importX
},
rules: {
'import-x/export': 'error',
'import-x/first': 'error',
'import-x/no-absolute-path': ['error', { esmodule: true, commonjs: true, amd: false }],
'import-x/no-duplicates': 'error',
'import-x/no-named-default': 'error',
'import-x/no-webpack-loader-syntax': 'error',
}
}
])For TypeScript projects, you may also want to add the TypeScript resolver:
import { defineConfig } from 'eslint/config'
import { newneostandard } from 'newneostandard'
import importX from 'eslint-plugin-import-x'
import { createTypeScriptImportResolver } from 'eslint-import-resolver-typescript'
export default defineConfig([
...newneostandard(),
{
plugins: {
'import-x': importX
},
settings: {
'import-x/resolver-next': [
createTypeScriptImportResolver({
project: './tsconfig.json'
})
]
},
rules: {
'import-x/export': 'error',
'import-x/first': 'error',
'import-x/no-absolute-path': ['error', { esmodule: true, commonjs: true, amd: false }],
'import-x/no-duplicates': 'error',
'import-x/no-named-default': 'error',
'import-x/no-webpack-loader-syntax': 'error',
}
}
])Recommended alternative: Use TypeScript's compiler for import checking instead:
tsc --noEmitThis provides more comprehensive checking including type imports, module resolution, and cross-file validation.
Additional exports
resolveIgnoresFromGitignore()
Finds a .gitignore file that resides in the same directory as the ESLint config file and returns an array of ESLint ignores that matches the same files.
ESM:
import { newneostandard, resolveIgnoresFromGitignore } from 'newneostandard'
export default newneostandard({
ignores: resolveIgnoresFromGitignore(),
})CommonJS:
module.exports = require('newneostandard')({
ignores: require('newneostandard').resolveIgnoresFromGitignore(),
})Exported plugins
newneostandard exports all the ESLint plugins that it uses. This to ensure that users who need to reference the plugin themselves will use the exact same instance of the plugin, which is a necessity when a plugin prefix is defined in multiple places.
List of exported plugins
@stylistic- export of@stylistic/eslint-pluginn- export ofeslint-plugin-npromise- export ofeslint-plugin-promisetypescript-eslint- export oftypescript-eslint
(The react plugin export is temporarily removed along with the React logic rules — see the note at the top.)
Usage of exported plugin
If one eg. wants to add the eslint-plugin-n recommended config, then one can do:
import { defineConfig } from 'eslint/config'
import { newneostandard, plugins } from 'newneostandard'
export default defineConfig([
...newneostandard(),
plugins.n.configs['flat/recommended'],
])Missing for 1.0.0 release
Full list in 1.0.0 milestone
Differences to standard / eslint-config-standard 17.x
- Open governance, resolving governance issue
- Built for ESLint 9 and ESLint 10
- Relies on ESLint flat config to bundle plugins rather than custom
standard-engine - Replaces deprecated ESLint style rules with
eslint-stylisticrules - Defaults to the
standardbehaviour of bundling JSX-support (ported fromeslint-config-standard-jsx) with anoJsxoption that deactivates it; the React-specific logic rules are temporarily removed pending ESLint 10 compatibility of the React plugin (see #350) - Built in options replaces need for separate modules
tsoption makes*.tsfiles be checked as well (used to be handled byts-standard)semioption enforces rather than ban semicolons (used to be handled bysemistandard)noStyleoption deactivates style rules (used to require something likeeslint-config-prettier)
Relaxed rules
@stylistic/comma-dangle– changed – set to ignore dangling commas in arrays, objects, imports, exports and is it set towarnrather thanerror@stylistic/no-multi-spaces– changed – setsignoreEOLCommentstotrue, useful for aligning comments across multiple linedot-notation– deactivated – clashes with thenoPropertyAccessFromIndexSignaturecheck in TypeScriptn/no-deprecated-api– changed – changed towarninstead oferroras they are not urgent to fix
Config helper
You can use the provided CLI tool to generate a config for you:
newneostandard --semi --ts > eslint.config.jsTo see all available flags, run:
newneostandard --helpConfig migration
The CLI tool can also migrate an existing "standard" configuration from package.json:
newneostandard --migrate > eslint.config.jsMigrations can also be extended, so to eg. migrate a semistandard setup, do:
newneostandard --semi --migrate > eslint.config.jsReadme badges
Yes! If you use newneostandard in your project, you can include one of these badges in
your readme to let people know that your code is using the newneostandard style.
[](https://github.com/neostandard/neostandard)[](https://github.com/neostandard/neostandard)[](https://github.com/neostandard/neostandard)Mission statement
Prior to the 1.0.0 release we are still rapidly evolving with fixes and improvements to reach rule parity with standard, hence more breaking changes will be experienced until then, as well as evolution of this statement
newneostandard intends to set an expectable baseline for project linting that's descriptive of best practices rather than prescriptive of any opinionated approach.
Rule guidelines
newneostandardrules describes current best practices in the community and help align developers, contributors and maintainers along thosenewneostandardrules are not a tool to promote changed practices within the community by prescribing new such practicesnewneostandardrule changes and additions should be aligned with projects prior to being released, by eg. sending PR:s to them to align them ahead of time. When new best practices are incompatible with current best practices, rules should first be relaxed to allow for both approaches, then be made stricter when the community has moved to the new approachnewneostandardrule changes and additions should improve the description of project best practices, not prescribe new practicesnewneostandardshould, when faced with no clear best practice, avoid adding such a rule as it risks becoming prescriptive rather than descriptive. If leaving out such a rule would makenewneostandardan incomplete baseline config, and the community is split between a few clear alternatives (such assemi), then making it configurable can enable it to still be added, but that should only be done in exceptional cases
Governance
newneostandard is a community project with open governance.
See GOVERNANCE.md for specifics.
Used by
A subset of some of the projects that rely on newneostandard:
bcomnes/npm-run-all2(https://github.com/bcomnes/npm-run-all2/pull/142)fastify/fastify(https://github.com/fastify/fastify/pull/5509)nodejs/undici(https://github.com/nodejs/undici/pull/3485)poolifier/poolifieruuidjs/uuid(https://github.com/uuidjs/uuid/pull/752)
