eslint-config-cepharum
v3.0.0
Published
ESLint configuration to be shared among projects of cepharum GmbH
Readme
eslint-config-cepharum
common ESLint configuration for projects of cepharum GmbH
License
Prerequisites
Starting with v2, the configuration works with versions of ESLint since v9.
Installation
npm i -D eslint-config-cepharumUsage
Create an eslint.config.js file in the root folder of your project. For a project that is plain JavaScript, the default export is all it takes:
import cepharum from "eslint-config-cepharum";
export default [
// put additional configuration objects here ...
...cepharum,
// ... or here
];The default export selects the same files v2.0 did, so updating this package changes
nothing for a project spreading it — including projects that wire eslint-plugin-vue in
themselves, whose components keep being linted. It brings no parser for .vue or .ts
of its own, though, which is why everything beyond plain JavaScript — Vue, TypeScript,
extra ignores, tests in unusual places — goes through configure():
import { configure } from "eslint-config-cepharum";
export default configure( {
ignores: [ "coverage", "server/public" ],
} );Note: In case a warning is displayed regarding a failed attempt to process the configuration as CommonJS, either fix your project's package.json file to include the
"type": "module"declaration or rename the configuration file to eslint.config.mjs.
Coming from v2
Nothing about the API changes — every project already calling configure() keeps working.
What changes is what gets reported:
| Change | Effect on a project |
|---|---|
| A Vue preset comes along by default | New findings in templates; measured across our projects, single digits per repository once no-deprecated-slot-attribute is out of the way. Pass vuePreset: false to keep v2's behaviour. |
| .js read as CommonJS unless the manifest says otherwise | Fewer findings: the strict directive of a CommonJS file is no longer reported, and --fix can no longer delete it. |
| no-await-in-loop, require-await, jsdoc/require-jsdoc are warnings | A pipeline gated on errors stops failing over them. Local blocks switching them off can go. |
| camelcase ignores object keys | The payloads of foreign APIs stop being reported. Inline exceptions for them can go. |
| no-console off for scripts/* and bin/* | Local blocks doing the same can go. |
| **/*.min.js ignored | Fewer findings. |
Options of configure()
| Option | Type | Effect |
|---|---|---|
| vue | module | The project's eslint-plugin-vue, enabling .vue files. |
| vuePreset | string \| false | Which of the plugin's presets to put underneath the house rules. "auto" (the default) picks essential, or vue2-essential when the project has Vue 2. false for none. |
| typescript | module | The project's @typescript-eslint/parser, enabling .ts, .mts, .cts and typed script blocks in .vue files. |
| sourceType | "module" \| "commonjs" | How to read .js files. Taken from the project's package.json when not given. |
| root | string | Folder to read that package.json from; the working directory by default. |
| tests | string[] | Further globs holding test code, beyond the ones recognised by default. |
| ignores | string[] | Further folders or globs to ignore project-wide. A bare folder name is expanded to everything below it. |
Vue and TypeScript are opt-in — and you hand over the package
import { configure } from "eslint-config-cepharum";
import pluginVue from "eslint-plugin-vue";
import tsParser from "@typescript-eslint/parser";
export default configure( {
vue: pluginVue,
typescript: tsParser,
ignores: [ "coverage" ],
} );Both packages are optional peer dependencies, and this configuration never imports
either one itself. That is deliberate: a backend service or a command line tool has no
business installing linter packages for a framework it does not use, and a static import
here would fail loading the configuration outright in exactly those projects. Passing the
module instead of a true flag keeps the configuration synchronous and makes the version
in use the project's own choice.
Files that cannot be parsed without the matching package — .vue without vue, .ts
without typescript — are ignored rather than handed to a JavaScript parser, which
would only report a misleading syntax error on the first line. Pass the option to lint
them.
Handing over the plugin also brings a preset of its own rules: essential, or
vue2-essential in a project that has Vue 2 — read from the project rather than asked of
you. flat/essential is the right level: measured against flat/recommended it drops
about nine tenths of the findings, all of them formatting, and keeps the ones that catch
mistakes. Pick another with vuePreset: "recommended", or none with vuePreset: false.
The preset goes underneath this configuration, which matters for one rule it switches
off: vue/no-deprecated-slot-attribute reads slot="label" as Vue 2 syntax, while on a
web component it is plain HTML and the only way to address a slot. Across our projects that
accounts for 272 of some 300 findings the essential preset reports — and its fixer rewrites
the attribute to v-slot, taking the markup apart. Spreading a preset after configure()
brings the rule, and its fixer, back.
Note on
ecmaVersion: the Vue block pins it to 2025, asvue-eslint-parser(10.4.1, its latest) rejects anything higher while ESLint hands it a higher value from 10.5 on — which would turn every single-file component into a parse error. Override it in a block of your own if you need newer syntax in a script block.
Modules and CommonJS
Flat configuration reads .js as a module, which is wrong in every project without
"type": "module" — and wrong in a way that bites: the strict rule then reports the
"use strict" at the top of a CommonJS file as superfluous, and --fix removes it,
dropping the file out of strict mode with nothing to show for it. So the project's
package.json decides, and .mjs and .cjs are read as what they are regardless. Say
sourceType explicitly where that guess cannot work, e.g. a folder of a monorepo whose
manifest says something else.
Test code
Rules that get in the way of readable tests — jsdoc/require-jsdoc, no-empty-function,
max-len, max-depth, no-console — are switched off for code recognised as a test.
Recognised are both layouts in use across our projects:
- anything below a
test/folder - files named
*.test.*or*.spec.*next to the code they cover
Add more via tests: [ … ].
Ignored by default
**/.vitepress/cache,**/.vitepress/dist**/dist,**/coverage**/playwright-report,**/test-results**/*.d.ts— declaration files hold no runtime code, and every type they export reads as an unused variable to rules written for JavaScript**/*.min.js— the output of something else, and every rule about spacing has an opinion on all of it
Add more via ignores: [ … ]. The older ignoreFolders( … ) helper still works and does
the same as configure( { ignores } ), but is deprecated.
Command line tools
no-console is off for scripts/* and bin/*: printing to a terminal is what a tool
there is for.
Building your own blocks
The rule set and the plugins it needs are exported, so a block of your own does not have to restate them:
import { configure, plugins, rules } from "eslint-config-cepharum";
export default [
...configure(),
{
files: ["scripts/*.js"],
plugins,
rules: { ...rules, "no-console": "off" },
},
];