Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
6 changes: 0 additions & 6 deletions .eslintrc.ts-next.json

This file was deleted.

6 changes: 0 additions & 6 deletions .eslintrc.ts-react.json

This file was deleted.

6 changes: 0 additions & 6 deletions .eslintrc.ts.json

This file was deleted.

6 changes: 6 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash

set -e
set -o pipefail

npm run lint
26 changes: 26 additions & 0 deletions configs/formatjs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { defineConfig } from 'eslint/config'
import formatjsPlugin from 'eslint-plugin-formatjs'
import jsonc from 'eslint-plugin-jsonc'

export default defineConfig([
{
files: ['**/*.{js,cjs,mjs,jsx,ts,tsx}'],
plugins: {
formatjs: formatjsPlugin,
},
rules: {
'formatjs/enforce-default-message': ['error', 'literal'],
'formatjs/enforce-placeholders': 'error',
'formatjs/no-multiple-whitespaces': 'error',
'formatjs/enforce-id': 'error',
},
},
{
files: ['**/translations/*.json'],
language: 'json/json',
plugins: { jsonc },
rules: {
'jsonc/sort-keys': 'error',
},
},
])
9 changes: 9 additions & 0 deletions configs/jest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { defineConfig } from 'eslint/config'
import jestPlugin from 'eslint-plugin-jest'

export default defineConfig([
{
files: ['**/*.{js,cjs,mjs,jsx,ts,tsx}'],
...jestPlugin.configs['flat/recommended'],
},
])
39 changes: 39 additions & 0 deletions configs/next.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { dirname } from 'path'
import { fileURLToPath } from 'url'
import { FlatCompat } from '@eslint/eslintrc'
import { defineConfig } from 'eslint/config'

const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)

const compat = new FlatCompat({
baseDirectory: __dirname,
})

export default defineConfig([
// coreWebVitals includes Next recommended rules
...compat.extends('plugin:@next/next/core-web-vitals'),
{
files: ['**/*.{js,cjs,mjs,jsx,ts,tsx}'],
rules: {
'@next/next/no-img-element': 'off',
},
},
])

// Alternative/modern approach:
// Working, but has some issues with the Next lint command (running with `next build`).
// This approach can probably be used with Next 16, as they removed Next lint completely.
//
// import next from '@next/eslint-plugin-next'
// import { defineConfig } from 'eslint/config'
// export default defineConfig([
// {
// files: ['**/*.{js,cjs,mjs,jsx,ts,tsx}'],
// // coreWebVitals includes Next recommended rules
// ...next.flatConfig.coreWebVitals,
// rules: {
// '@next/next/no-img-element': 'off',
// },
// },
// ])
44 changes: 44 additions & 0 deletions configs/react.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { defineConfig } from 'eslint/config'
import jsxA11y from 'eslint-plugin-jsx-a11y'
import reactPlugin from 'eslint-plugin-react'
import reactHooks from 'eslint-plugin-react-hooks'

export default defineConfig([
{
languageOptions: {
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
files: ['**/*.{js,cjs,mjs,jsx,ts,tsx}'],
extends: [
reactPlugin.configs.flat.recommended,
reactPlugin.configs.flat['jsx-runtime'],
reactHooks.configs['recommended-latest'],
jsxA11y.flatConfigs.strict,
],
settings: {
react: {
version: 'detect',
},
},
rules: {
'react/jsx-curly-brace-presence': [
'error',
{ props: 'never', children: 'never', propElementValues: 'always' },
],
'react/self-closing-comp': [
'error',
{
component: true,
html: true,
},
],
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'error',
'jsx-a11y/no-autofocus': 'off',
},
},
])
27 changes: 27 additions & 0 deletions configs/storybook.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { defineConfig } from 'eslint/config'
import * as mdx from 'eslint-plugin-mdx'
import { configs as storybookConfigs } from 'eslint-plugin-storybook'
import { configs as tseslintConfigs } from 'typescript-eslint'

export default defineConfig([
{
files: ['**/*.{js,cjs,mjs,jsx,ts,tsx}'],
extends: [storybookConfigs['flat/recommended']],
},
{
ignores: ['!.storybook'],
},
{
...mdx.flat,
processor: mdx.createRemarkProcessor({
lintCodeBlocks: false, // Disable linting of code blocks as it shows irrelevant errors.
}),
},
{
...mdx.flatCodeBlocks,
extends: [tseslintConfigs.disableTypeChecked],
rules: {
'import/no-unresolved': 'off',
},
},
])
55 changes: 55 additions & 0 deletions configs/tailwind.js
Comment thread
lukasvice marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { defineConfig } from 'eslint/config'
import eslintPluginBetterTailwindcss from 'eslint-plugin-better-tailwindcss'
import { getDefaultSelectors } from 'eslint-plugin-better-tailwindcss/api/defaults'
import { SelectorKind } from 'eslint-plugin-better-tailwindcss/types'

export default defineConfig([
{
files: ['**/*.{js,cjs,mjs,jsx,ts,tsx}'],
extends: [eslintPluginBetterTailwindcss.configs['recommended-error']],
rules: {
// Configure rules
'better-tailwindcss/enforce-consistent-line-wrapping': ['off'], // This rule is not compatible with prettier

// Additional rules
'better-tailwindcss/enforce-consistent-variable-syntax': ['error'],
'better-tailwindcss/enforce-consistent-important-position': ['error'],
'better-tailwindcss/enforce-shorthand-classes': ['error'],
},
settings: {
'better-tailwindcss': {
selectors: [
...getDefaultSelectors(),
{
kind: SelectorKind.Callee,
match: [
{ type: 'strings' },
{ type: 'objectValues', pathPattern: '.*' },
{ type: 'objectKeys', pathPattern: '.*' },
],
name: '^classNames$',
},
{
kind: SelectorKind.Variable,
match: [
{ type: 'strings' },
{ type: 'objectValues', pathPattern: '.*' },
{ type: 'objectKeys', pathPattern: '.*' },
],
name: '.*[cC]lassNames?$',
},
],
},
},
/*
settings: {
'better-tailwindcss': {
// Entrypoint for Tailwind CSS 4
entryPoint: 'styles/index.css',
// Entrypoint for Tailwind CSS 3
tailwindConfig: 'tailwind.config.js',
},
},
*/
},
])
117 changes: 117 additions & 0 deletions configs/ts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import eslint from '@eslint/js'
import json from '@eslint/json'
import { defineConfig } from 'eslint/config'
import importPlugin from 'eslint-plugin-import'
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
import unusedImports from 'eslint-plugin-unused-imports'
import globals from 'globals'
import { configs as tseslintConfigs } from 'typescript-eslint'

export default defineConfig([
{
files: ['**/*.{js,mjs,cjs,ts,jsx,tsx}'],
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
globals: {
...globals.browser,
...globals.node,
},
},
extends: [
eslint.configs.recommended,
tseslintConfigs.strictTypeChecked,
tseslintConfigs.stylisticTypeChecked,
importPlugin.flatConfigs.recommended,
importPlugin.flatConfigs.typescript,
eslintPluginPrettierRecommended,
],
plugins: {
'unused-imports': unusedImports,
},
settings: {
'import/resolver': {
typescript: true,
node: true,
},
},
rules: {
'@typescript-eslint/consistent-type-definitions': ['error', 'type'],
'@typescript-eslint/switch-exhaustiveness-check': 'error',
'@typescript-eslint/restrict-template-expressions': [
'error',
{
allowNumber: true,
allowAny: false,
allowNullish: false,
allowBoolean: false,
allowRegExp: false,
allowNever: false,
},
],
'@typescript-eslint/member-delimiter-style': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-deprecated': 'warn',
'import/order': [
'error',
{
groups: [
'builtin',
'external',
'internal',
'unknown',
'parent',
'sibling',
'index',
'object',
'type',
],
alphabetize: {
order: 'asc',
orderImportKind: 'asc',
caseInsensitive: false,
},
'newlines-between': 'never',
warnOnUnassignedImports: true,
named: true,
},
],
'no-console': [
'error',
{
allow: ['warn', 'error', 'assert'],
},
],
'no-implicit-coercion': 'error',
curly: ['error', 'all'],
'object-shorthand': ['error'],
eqeqeq: 'error',

// Rules for eslint-plugin-unused-imports
'@typescript-eslint/no-unused-vars': 'off',
'unused-imports/no-unused-imports': 'error',
'unused-imports/no-unused-vars': [
'error',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
destructuredArrayIgnorePattern: '^_',
},
],
},
},
{
files: ['**/*.{js,mjs,cjs,jsx}'],
extends: [tseslintConfigs.disableTypeChecked],
},
{
files: ['**/*.json'],
ignores: ['package-lock.json'],
plugins: { json },
language: 'json/json',
extends: [eslintPluginPrettierRecommended, json.configs.recommended],
},
])
9 changes: 9 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { defineConfig } from 'eslint/config'
import ts from './configs/ts.js'

export default defineConfig([
ts,
{
ignores: ['node_modules'],
},
])
9 changes: 0 additions & 9 deletions formatjs.js

This file was deleted.

Loading