
Product
Introducing Socket Firewall Enterprise: Flexible, Configurable Protection for Modern Package Ecosystems
Socket Firewall Enterprise is now available with flexible deployment, configurable policies, and expanded language support.
@leaflink/eslint-config
Advanced tools
Opinionated linting configuration for LeafLink's front-end repositories.
Configuration for ESLint, Prettier, Stylelint, and Commitlint at LeafLink.
.ts and .tsx files) and TypeScript within .vue sfc files.[!IMPORTANT]
Requirements ESLint v9 and above Node.js v20 and above Stylelint v16 and above (optional)
If you're going to be using both eslint & stylelint in your project, then the fastest way to get started is to run:
npx install-peerdeps --dev @leaflink/eslint-config
If you don't need to leverage stylelint in your project, then just install this package along with eslint v9:
npm install --save-dev eslint@9 @leaflink/eslint-config@latest
If you want to manually install all peer dependencies without using install-peerdeps, you can run:
npm install --save-dev eslint@9 @leaflink/eslint-config@latest stylelint@16 stylelint-config-standard-scss stylelint-config-standard-vue stylelint-order postcss-html
npm uninstall eslint-config-leaflink stylelint stylelint-config-standard-scss stylelint-config-standard-vue.npx install-peerdeps --dev @leaflink/eslint-config.globals if you have custom globals set in your projects eslint file: npm install -D globals..eslintrc.js to eslint.config.mjs..eslintignore and move listed files/directories into an { ignores: [...] } block inside your ESLint
config.@ts-ignore -> @ts-expect-error. Be aware, this may actually cause ts errors in the event that the
@ts-ignore wasn't actually doing anything. This is a good thing, just remove the comment altogether.lint command: eslint --ext .ts,.js,.vue src -> eslint ..stylelint.config.js to stylelint.config.mjs and refactor to esm. If using a json format, it should be
fine to leave it as is.commitlint.config.js to stylelint.config.mjs and refactor to esm. If using a json format, it should be
fine to leave it as is.[!NOTE] You may also find yourself having to address certain eslint errors that didn't appear before. All 3rd party configs and plugins were upgraded as part of this update, hence some rules have been changed.
Docs: https://eslint.org/docs/latest/use/configure/migration-guide
Summary of main changes
overrides up a level - just "flatten" the overrides array and get rid of it.env objects need to get converted to languageOptions: { globals: { ...globals.node, ...globals.jest } } and you
need to load globals from the globals npm package. They aren't baked in anymore.files always needs to be an array: files: '**/*.spec.ts' -> files: ['**/*.spec.ts']files globs need to be a little more specific it seems. files: ['*.spec.ts'] -> files: ['**/*.spec.ts']Example
Old usage (.eslintrc.js):
module.exports = {
extends: 'leaflink',
// your custom overrides
};
New usage (eslint.config.mjs):
import leaflinkConfig from '@leaflink/eslint-config';
export default [
...leaflinkConfig,
// your custom overrides (using new flat config format)
];
Create an eslint.config.mjs file in the root of your project and extend from the shared LeafLink config.
[!IMPORTANT] If you haven't enabled esm in your project by default, you may need to name your config file
eslint.config.mjs. Otherwise, projects that use"type": "module"in theirpackage.jsoncan probably use the.jsextension.
import leaflinkConfig from '@leaflink/eslint-config';
import { defineConfig, globalIgnores } from 'eslint/config';
export default defineConfig([
...leaflinkConfig,
globalIgnores(['my-custom-path', '**/generated/**']),
// Optionally add overrides here
{
// files: ['**/*.ts', '**/*.tsx'], // (optional) only apply to specific files
rules: {
// your rules overrides here
},
},
]);
If your test files rely on a browser environment, you probably need to configure ESLint to be aware of the browser globals since they are not included by default from Vitest or Testing Library.
// eslint.config.js
import { defineConfig } from 'eslint/config';
import globals from 'globals';
export default defineConfig([
...leaflinkConfig,
{
files: ['**/?(*.)+(spec).[jt]s'],
languageOptions: {
globals: {
...globals.browser,
},
},
},
]);
Including the browser globals for test files will prevent linting errors such as 'window' is not defined and
'document' is not defined.
Be sure to install globals with npm i -D globals.
If you have any other scripts outside of a Vue or React context that rely on the browser, you can tell ESLint to provide
certain globals be adding a globals comment to the top of the file.
For example, imagine that the following is for a runtime script called unregisterServiceWorker.ts.
/* global window, navigator */
export default function unregisterServiceWorker() {
if (window && navigator?.serviceWorker) {
navigator.serviceWorker.getRegistrations().then(function (registrations) {
for (const registration of registrations) {
registration.unregister();
}
});
}
}
Prettier is automatically run through eslint with LeafLink's default configuration. You can optionally
add a prettier.config.mjs configuration file in the root of your project and it will take precedence over the
built-in config within @leaflink/eslint-config.
If you'd like to extend our prettier config and only override a couple of properties, you can do the following:
prettier.config.mjs
import leaflinkConfig from '@leaflink/eslint-config/prettier.js';
/**
* @see https://prettier.io/docs/en/configuration.html
* @type {import("prettier").Config}
*/
const config = {
...leaflinkConfig,
// your overrides here
};
export default config;
In your .stylelintrc file, you can extend from the shared LeafLink stylelint config.
{
"extends": ["@leaflink/eslint-config/stylelint"]
}
Or you can do so in your package.json:
{
"stylelint": {
"extends": ["@leaflink/eslint-config/stylelint"]
}
}
Or in stylelint.config.mjs:
export default {
extends: ['@leaflink/eslint-config/stylelint'],
};
Create a commitlint.config.mjs file at the root of your project with the following content:
import leaflinkConfig from '@leaflink/eslint-config/commitlint.js';
export default leaflinkConfig;
If you want to extend the leaflinkConfig with custom overrides, you can do so like this:
import leaflinkConfig from '@leaflink/eslint-config/commitlint.js';
export default Object.assign(leaflinkConfig, {
// your overrides here
rules: {
'scope-case': [1],
},
});
Lastly, in order for husky to lint your commit messages, you need to create a .husky/commit-msg file in your project
with the following content:
#!/usr/bin/env sh
npx --no -- commitlint --edit $1
Husky hooks are enabled by default and will run automatically when users commit or push. However, individual users can opt-out of Husky hooks in several ways:
Temporary opt-out (single command):
HUSKY=0 git commit -m "Your commit message"
Session opt-out:
export HUSKY=0
git commit -m "Your commit message"
git push
unset HUSKY
Global opt-out (per user): Users can create ~/.config/husky/init.sh with:
export HUSKY=0
Note: this is temporarily disabled until the eslint-plugin-tailwindcss package release a stable version that is compatible with tailwind v4.
There's a tailwindcss/no-custom-classname rule that enforces the use of only valid global classes like Tailwind CSS
utilities. You can allowlist custom global classes that you want to allow. Our config has a default allowlist of classes
that are commonly used across our projects. If you need to add more classes to the allowlist, you can do so in your
project's ESLint config file, but just be sure to include the default allowlist as well.
import leaflinkConfig, { TAILWIND_CLASS_ALLOWLIST } from '@leaflink/eslint-config';
export default [
...leaflinkConfig,
{
rules: {
'tailwindcss/no-custom-classname': [
'error',
{
whitelist: [
...TAILWIND_CLASS_ALLOWLIST,
// Add your custom classes here
'info-cell',
'table',
'col-1',
'col-2',
'col-3',
'col-10',
],
},
],
},
},
];
https://github.com/francoismassart/eslint-plugin-tailwindcss/issues/149
When building dynamic classes, the auto sorting of tailwind classes can break things so beware:
To avoid this happening you can re-wrap the dynamic class expression like so:
class="`p-0 ${`tw-border-${accentColor}`}`"
[!Note] It's recommended you attempt to remove as many of your specific overrides as possible and see how much can be autofixed to be inline with this shared configuration. You can extend from
leaflinkand set temporary overrides to turn some rules off in order to make the initial migration easier.
FAQs
Opinionated linting configuration for LeafLink's front-end repositories.
The npm package @leaflink/eslint-config receives a total of 1,214 weekly downloads. As such, @leaflink/eslint-config popularity was classified as popular.
We found that @leaflink/eslint-config demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 4 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Socket Firewall Enterprise is now available with flexible deployment, configurable policies, and expanded language support.

Security News
Open source dashboard CNAPulse tracks CVE Numbering Authorities’ publishing activity, highlighting trends and transparency across the CVE ecosystem.

Product
Detect malware, unsafe data flows, and license issues in GitHub Actions with Socket’s new workflow scanning support.