diff --git a/config/lint/eslint.config.mjs b/config/lint/eslint.config.mjs index be09869..43a51e6 100644 --- a/config/lint/eslint.config.mjs +++ b/config/lint/eslint.config.mjs @@ -11,57 +11,159 @@ const style = { '@stylistic/js': stylistic, '@stylistic/ts': stylistic, }, - 'files': [ '**/*.ts', '**/*.js', '**/*.tsx', '**/*.jsx' ], + 'files': [ + '**/*.ts', + '**/*.js', + '**/*.mjs', + '**/*.cjs', + '**/*.tsx', + '**/*.jsx' + ], 'rules': { // Formatting - '@stylistic/array-bracket-newline': ['error', { 'multiline': true, 'minItems': 2 }], - '@stylistic/array-bracket-spacing': ['error', 'always'], - '@stylistic/array-element-newline': ['error', { 'multiline': true, 'minItems': 2 }], - '@stylistic/arrow-parens': ['error', 'as-needed'], - '@stylistic/arrow-spacing': ['error', { 'before': true, 'after': true }], - '@stylistic/block-spacing': ['error', 'always'], - '@stylistic/brace-style': ['error', '1tbs'], - '@stylistic/comma-spacing': ['error', { 'before': false, 'after': true }], - '@stylistic/comma-style': ['error', 'last'], - '@stylistic/dot-location': ['error', 'property'], - '@stylistic/eol-last': ['error', 'always'], - '@stylistic/function-call-spacing': ['error', 'never'], - '@stylistic/implicit-arrow-linebreak': ['error', 'beside'], - '@stylistic/indent': ['error', 4], - '@stylistic/key-spacing': ['error', { 'beforeColon': false, 'afterColon': true }], - '@stylistic/keyword-spacing': ['error', { 'before': true, 'after': true }], - '@stylistic/lines-between-class-members': ['error', 'always'], - '@stylistic/new-parens': ['error', 'always'], - '@stylistic/newline-per-chained-call': ['error', { - 'ignoreChainWithDepth': 2 - }], - '@stylistic/no-extra-parens': ['error', 'all'], + '@stylistic/array-bracket-newline': [ + 'error', + { + 'multiline': true, + 'minItems': 2 + } + ], + '@stylistic/array-bracket-spacing': [ + 'error', + 'always' + ], + '@stylistic/array-element-newline': [ + 'error', + { + 'multiline': true, + 'minItems': 2 + } + ], + '@stylistic/arrow-parens': [ + 'error', + 'as-needed' + ], + '@stylistic/arrow-spacing': [ + 'error', + { + 'before': true, + 'after': true + } + ], + '@stylistic/block-spacing': [ + 'error', + 'always' + ], + '@stylistic/brace-style': [ + 'error', + '1tbs' + ], + '@stylistic/comma-spacing': [ + 'error', + { + 'before': false, + 'after': true + } + ], + '@stylistic/comma-style': [ + 'error', + 'last' + ], + '@stylistic/dot-location': [ + 'error', + 'property' + ], + '@stylistic/eol-last': [ + 'error', + 'always' + ], + '@stylistic/function-call-spacing': [ + 'error', + 'never' + ], + '@stylistic/implicit-arrow-linebreak': [ + 'error', + 'beside' + ], + '@stylistic/indent': [ + 'error', + 4 + ], + '@stylistic/key-spacing': [ + 'error', + { + 'beforeColon': false, + 'afterColon': true + } + ], + '@stylistic/keyword-spacing': [ + 'error', + { + 'before': true, + 'after': true + } + ], + '@stylistic/lines-between-class-members': [ + 'error', + 'always' + ], + '@stylistic/new-parens': [ + 'error', + 'always' + ], + '@stylistic/newline-per-chained-call': [ + 'error', + { 'ignoreChainWithDepth': 2 } + ], + '@stylistic/no-extra-parens': [ + 'error', + 'all' + ], '@stylistic/no-extra-semi': 'error', '@stylistic/no-floating-decimal': 'error', '@stylistic/no-mixed-operators': 'error', '@stylistic/no-mixed-spaces-and-tabs': 'error', '@stylistic/no-multi-spaces': 'error', - '@stylistic/no-multiple-empty-lines': ['error', { - 'max': 3, - 'maxEOF': 1 - }], + '@stylistic/no-multiple-empty-lines': [ + 'error', + { + 'max': 3, + 'maxEOF': 1 + } + ], '@stylistic/no-tabs': 'error', '@stylistic/no-trailing-spaces': 'error', '@stylistic/no-whitespace-before-property': 'error', - '@stylistic/object-curly-newline': ['error', { 'multiline': true, 'minProperties': 2 }], - '@stylistic/object-curly-spacing': ['error', 'always'], + '@stylistic/object-curly-newline': [ + 'error', + { + 'multiline': true, + 'minProperties': 2 + } + ], + '@stylistic/object-curly-spacing': [ + 'error', + 'always' + ], '@stylistic/object-property-newline': 'error', - '@stylistic/operator-linebreak': ['error', 'before'], + '@stylistic/operator-linebreak': [ + 'error', + 'before' + ], '@stylistic/one-var-declaration-per-line': 'error', - '@stylistic/padded-blocks': ['error', { - 'blocks': 'never', - 'classes': 'always', - 'switches': 'never', - }], + '@stylistic/padded-blocks': [ + 'error', + { + 'blocks': 'never', + 'classes': 'always', + 'switches': 'never', + } + ], // Padding lines. The most in-depth part of this config // ['block', 'block-like', 'break', 'cjs-export', 'cjs-import', 'class', 'const', 'continue', 'debugger', 'directive', 'do', 'empty', 'export', 'expression', 'for', 'function', 'if', 'iife', 'import', 'let', 'return', 'switch', 'throw', 'try', 'var', 'while', 'with'] - '@stylistic/padding-line-between-statements': ['error', + '@stylistic/padding-line-between-statements': [ + 'error', // Variables, Constants { 'blankLine': 'never', @@ -81,17 +183,98 @@ const style = { { 'blankLine': 'always', 'prev': 'var', - 'next': ['block', 'block-like', 'break', 'cjs-export', 'cjs-import', 'class', 'const', 'continue', 'debugger', 'directive', 'do', 'empty', 'export', 'expression', 'for', 'function', 'if', 'iife', 'import', 'let', 'return', 'switch', 'throw', 'try', 'var', 'with'] + 'next': [ + 'block', + 'block-like', + 'break', + 'cjs-export', + 'cjs-import', + 'class', + 'const', + 'continue', + 'debugger', + 'directive', + 'do', + 'empty', + 'export', + 'expression', + 'for', + 'function', + 'if', + 'iife', + 'import', + 'let', + 'return', + 'switch', + 'throw', + 'try', + 'var', + 'with' + ] }, { 'blankLine': 'always', 'prev': 'let', - 'next': ['block', 'block-like', 'break', 'cjs-export', 'cjs-import', 'class', 'const', 'continue', 'debugger', 'directive', 'do', 'empty', 'export', 'expression', 'for', 'function', 'if', 'iife', 'import', 'return', 'switch', 'throw', 'try', 'var', 'while', 'with'] + 'next': [ + 'block', + 'block-like', + 'break', + 'cjs-export', + 'cjs-import', + 'class', + 'const', + 'continue', + 'debugger', + 'directive', + 'do', + 'empty', + 'export', + 'expression', + 'for', + 'function', + 'if', + 'iife', + 'import', + 'return', + 'switch', + 'throw', + 'try', + 'var', + 'while', + 'with' + ] }, { 'blankLine': 'always', 'prev': 'const', - 'next': ['block', 'block-like', 'break', 'cjs-export', 'cjs-import', 'class', 'continue', 'debugger', 'directive', 'do', 'empty', 'export', 'expression', 'for', 'function', 'if', 'iife', 'import', 'let', 'return', 'switch', 'throw', 'try', 'var', 'while', 'with'] + 'next': [ + 'block', + 'block-like', + 'break', + 'cjs-export', + 'cjs-import', + 'class', + 'continue', + 'debugger', + 'directive', + 'do', + 'empty', + 'export', + 'expression', + 'for', + 'function', + 'if', + 'iife', + 'import', + 'let', + 'return', + 'switch', + 'throw', + 'try', + 'var', + 'while', + 'with' + ] }, // Import { @@ -106,23 +289,127 @@ const style = { }, { 'blankLine': 'always', - 'prev': ['block', 'block-like', 'break', 'cjs-export', 'class', 'const', 'continue', 'debugger', 'directive', 'do', 'empty', 'export', 'expression', 'for', 'function', 'if', 'iife', 'let', 'return', 'switch', 'throw', 'try', 'var', 'while', 'with'], + 'prev': [ + 'block', + 'block-like', + 'break', + 'cjs-export', + 'class', + 'const', + 'continue', + 'debugger', + 'directive', + 'do', + 'empty', + 'export', + 'expression', + 'for', + 'function', + 'if', + 'iife', + 'let', + 'return', + 'switch', + 'throw', + 'try', + 'var', + 'while', + 'with' + ], 'next': 'cjs-import' }, { 'blankLine': 'always', 'prev': 'cjs-import', - 'next': ['block', 'block-like', 'break', 'cjs-export', 'class', 'const', 'continue', 'debugger', 'directive', 'do', 'empty', 'export', 'expression', 'for', 'function', 'if', 'iife', 'let', 'return', 'switch', 'throw', 'try', 'var', 'while', 'with'] + 'next': [ + 'block', + 'block-like', + 'break', + 'cjs-export', + 'class', + 'const', + 'continue', + 'debugger', + 'directive', + 'do', + 'empty', + 'export', + 'expression', + 'for', + 'function', + 'if', + 'iife', + 'let', + 'return', + 'switch', + 'throw', + 'try', + 'var', + 'while', + 'with' + ] }, { 'blankLine': 'always', - 'prev': ['block', 'block-like', 'break', 'cjs-export', 'class', 'const', 'continue', 'debugger', 'directive', 'do', 'empty', 'export', 'expression', 'for', 'function', 'if', 'iife', 'let', 'return', 'switch', 'throw', 'try', 'var', 'while', 'with'], + 'prev': [ + 'block', + 'block-like', + 'break', + 'cjs-export', + 'class', + 'const', + 'continue', + 'debugger', + 'directive', + 'do', + 'empty', + 'export', + 'expression', + 'for', + 'function', + 'if', + 'iife', + 'let', + 'return', + 'switch', + 'throw', + 'try', + 'var', + 'while', + 'with' + ], 'next': 'import' }, { 'blankLine': 'always', 'prev': 'import', - 'next': ['block', 'block-like', 'break', 'cjs-export', 'class', 'const', 'continue', 'debugger', 'directive', 'do', 'empty', 'export', 'expression', 'for', 'function', 'if', 'iife', 'let', 'return', 'switch', 'throw', 'try', 'var', 'while', 'with'] + 'next': [ + 'block', + 'block-like', + 'break', + 'cjs-export', + 'class', + 'const', + 'continue', + 'debugger', + 'directive', + 'do', + 'empty', + 'export', + 'expression', + 'for', + 'function', + 'if', + 'iife', + 'let', + 'return', + 'switch', + 'throw', + 'try', + 'var', + 'while', + 'with' + ] }, // If { @@ -256,26 +543,67 @@ const style = { 'next': '*' }, ], - '@stylistic/quote-props': ['error', 'always'], - '@stylistic/quotes': ['error', 'single'], - '@stylistic/rest-spread-spacing': ['error', 'never'], - '@stylistic/semi': ['error', 'always'], - '@stylistic/semi-spacing': ['error', { 'before': false, 'after': true }], - '@stylistic/semi-style': ['error', 'last'], - '@stylistic/space-before-blocks': ['error', 'always'], - '@stylistic/space-before-function-paren': ['error', 'always'], - '@stylistic/space-in-parens': ['error', 'always'], - '@stylistic/space-infix-ops': ['error', { 'int32Hint': false }], + '@stylistic/quote-props': [ + 'error', + 'always' + ], + '@stylistic/quotes': [ + 'error', + 'single' + ], + '@stylistic/rest-spread-spacing': [ + 'error', + 'never' + ], + '@stylistic/semi': [ + 'error', + 'always' + ], + '@stylistic/semi-spacing': [ + 'error', + { + 'before': false, + 'after': true + } + ], + '@stylistic/semi-style': [ + 'error', + 'last' + ], + '@stylistic/space-before-blocks': [ + 'error', + 'always' + ], + '@stylistic/space-before-function-paren': [ + 'error', + 'always' + ], + '@stylistic/space-in-parens': [ + 'error', + 'always' + ], + '@stylistic/space-infix-ops': [ + 'error', + { 'int32Hint': false } + ], '@stylistic/space-unary-ops': 'error', - '@stylistic/spaced-comment': ['error', 'always'], - '@stylistic/template-curly-spacing': ['error', 'always'], + '@stylistic/spaced-comment': [ + 'error', + 'always' + ], + '@stylistic/template-curly-spacing': [ + 'error', + 'always' + ], '@stylistic/switch-colon-spacing': 'error', - '@stylistic/template-curly-spacing': ['error', 'always'], - '@stylistic/wrap-iife': ['error', 'inside'], + '@stylistic/wrap-iife': [ + 'error', + 'inside' + ], '@stylistic/wrap-regex': 'error', '@stylistic/ts/type-annotation-spacing': 'error', } -} +}; /** @type {import('eslint').Linter.Config} */ export default tseslint.config( @@ -286,51 +614,65 @@ export default tseslint.config( // Vue support (including TS and JSX inside SFCs) { - files: ['**/*.vue'], - languageOptions: { - sourceType: 'module', - ecmaVersion: 'latest', - globals: globals.browser, - parserOptions: { - parser: tseslint.parser, - }, + 'files': [ '**/*.vue' ], + 'languageOptions': { + 'sourceType': 'module', + 'ecmaVersion': 'latest', + 'globals': globals.browser, + 'parserOptions': { 'parser': tseslint.parser, }, }, - plugins: { + 'plugins': { 'vue': vue, '@stylistic': stylistic, '@stylistic/js': stylistic, '@stylistic/ts': stylistic, '@typescript-eslint': typescript, }, - extends: [ + 'extends': [ eslint.configs.recommended, ...vue.configs['flat/recommended'] ], - rules: { + 'rules': { ...typescript.configs.recommended.rules, ...style.rules, // Vue specific rules '@stylistic/indent': 'off', - 'vue/html-indent': ['error', 4], - 'vue/html-comment-indent': ['error', 4], - 'vue/script-indent': ['error', 4, { - "baseIndent": 1, - "switchCase": 1 - }], - 'vue/html-self-closing': ['error', { - "html": { - "void": "never", - "normal": "never", - "component": "always" - }, - "svg": "always", - "math": "never" - }], - 'vue/max-attributes-per-line': ['error', { - singleline: 3, - multiline: 1, - }], + 'vue/html-indent': [ + 'error', + 4 + ], + 'vue/html-comment-indent': [ + 'error', + 4 + ], + 'vue/script-indent': [ + 'error', + 4, + { + 'baseIndent': 1, + 'switchCase': 1 + } + ], + 'vue/html-self-closing': [ + 'error', + { + 'html': { + 'void': 'never', + 'normal': 'never', + 'component': 'always' + }, + 'svg': 'always', + 'math': 'never' + } + ], + 'vue/max-attributes-per-line': [ + 'error', + { + 'singleline': 3, + 'multiline': 1, + } + ], }, }, ); diff --git a/config/lint/package.json b/config/lint/package.json new file mode 100644 index 0000000..a3ee9d3 --- /dev/null +++ b/config/lint/package.json @@ -0,0 +1,8 @@ +{ + "devDependencies": { + "@eslint/js": "^9.28.0", + "@stylistic/eslint-plugin": "^4.4.1", + "eslint-plugin-vue": "^10.2.0", + "typescript-eslint": "^8.33.1" + } +} diff --git a/scripts/setup-eslint b/scripts/setup-eslint index b88dce4..da82477 100755 --- a/scripts/setup-eslint +++ b/scripts/setup-eslint @@ -4,6 +4,5 @@ SCRIPT_DIR=$(dirname "$0") cp "$SCRIPT_DIR/../config/lint/eslint.config.mjs" . -# TODO: Improve eslint config to include JSX and Vue configs too, read on website npm i --save-dev @eslint/js typescript-eslint @stylistic/eslint-plugin eslint-plugin-vue