From 1ce57744a02a84328348836b7eef7f994249b3ff Mon Sep 17 00:00:00 2001 From: Yosuke Ota Date: Fri, 19 Apr 2024 18:25:00 +0900 Subject: [PATCH] chore: Use eslint v9 and flat config (#738) This PR changes to use ESLint v9. --- .eslintignore | 39 ---- .eslintrc.js | 192 ----------------- .github/workflows/NodeCI.yml | 26 ++- README.md | 2 +- docs-svelte-kit/.eslintrc.cjs | 15 -- docs-svelte-kit/build-system/build.mts | 13 +- docs-svelte-kit/build-system/src/eslint.mjs | 6 - docs-svelte-kit/shim/fs.mjs | 1 - docs-svelte-kit/shim/globby.mjs | 2 - docs-svelte-kit/shim/module.mjs | 1 - docs-svelte-kit/shim/os.mjs | 1 - docs-svelte-kit/shim/path.mjs | 63 ------ docs-svelte-kit/shim/postcss-load-config.mjs | 1 - docs-svelte-kit/shim/url.mjs | 1 - docs-svelte-kit/src/.eslintrc.js | 10 - .../src/lib/components/ESLintCodeBlock.svelte | 46 +++-- .../lib/components/ESLintPlayground.svelte | 49 +++-- .../src/lib/eslint/ESLintEditor.svelte | 9 +- .../src/lib/eslint/MonacoEditor.svelte | 3 +- .../src/lib/eslint/scripts/linter.js | 39 ++-- docs/.eslintrc.js | 10 - docs/rules/no-useless-mustaches.md | 2 + docs/user-guide.md | 2 +- eslint.config.mjs | 195 ++++++++++++++++++ package.json | 41 ++-- src/rule-types.ts | 4 +- src/rules/comment-directive.ts | 38 ++-- src/rules/first-attribute-linebreak.ts | 6 +- src/rules/indent-helpers/svelte.ts | 1 - src/rules/indent-helpers/ts.ts | 1 - src/rules/mustache-spacing.ts | 40 ++-- src/rules/prefer-class-directive.ts | 10 +- src/shared/comment-directives.ts | 3 +- src/utils/ast-utils.ts | 6 +- svelte-kit-import-hook.mjs | 11 +- svelte-kit-import.mjs | 1 + tests/fixtures/rules/.eslintrc.js | 55 ----- .../rules/indent/invalid/.eslintrc.js | 9 - .../invalid/.eslintrc.json | 5 - .../valid/test01-input.svelte | 4 - .../multiline-class-names01-input.svelte | 19 +- .../valid/.eslintrc.js | 10 - .../rules/sort-attributes/.eslintrc.js | 5 - .../valid/+test003-input.svelte | 2 +- .../valid/+test004-input.svelte | 2 +- tests/utils/utils.ts | 2 +- tools/update-docs.ts | 16 +- tools/update-readme.ts | 6 +- vite.config.mts | 16 +- 49 files changed, 407 insertions(+), 634 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .eslintrc.js delete mode 100644 docs-svelte-kit/.eslintrc.cjs delete mode 100644 docs-svelte-kit/build-system/src/eslint.mjs delete mode 100644 docs-svelte-kit/shim/path.mjs delete mode 100644 docs-svelte-kit/src/.eslintrc.js delete mode 100644 docs/.eslintrc.js create mode 100644 eslint.config.mjs delete mode 100644 tests/fixtures/rules/.eslintrc.js delete mode 100644 tests/fixtures/rules/indent/invalid/.eslintrc.js delete mode 100644 tests/fixtures/rules/no-inner-declarations/invalid/.eslintrc.json delete mode 100644 tests/fixtures/rules/no-unused-svelte-ignore/valid/.eslintrc.js delete mode 100644 tests/fixtures/rules/sort-attributes/.eslintrc.js diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 522400a38..000000000 --- a/.eslintignore +++ /dev/null @@ -1,39 +0,0 @@ -/.nyc_output -/coverage -/lib -/node_modules -!/.vscode -!/.github -!/.devcontainer -/prettier-playground -/tests/fixtures/rules/indent/invalid/ts -/tests/fixtures/rules/indent/invalid/ts-v5 -/tests/fixtures/rules/indent/invalid/snippets01-input.svelte -/tests/fixtures/rules/indent/valid/ -/tests/fixtures/rules/no-unused-class-name/valid/invalid-style01-input.svelte -/tests/fixtures/rules/no-unused-class-name/valid/unknown-lang01-input.svelte -/tests/fixtures/rules/valid-compile/invalid/ts -/tests/fixtures/rules/valid-compile/valid/babel -/tests/fixtures/rules/valid-compile/valid/ts -/tests/fixtures/rules/prefer-style-directive -/tests/fixtures/rules/@typescript-eslint -/tests/fixtures/rules/valid-compile/valid/svelte3-options-custom-element-input.svelte -/tests/fixtures/rules/mustache-spacing/valid/always/snippet-render01-input.svelte -/tests/fixtures/rules/mustache-spacing/invalid/snippet-render01-input.svelte -/.svelte-kit -/svelte.config-dist.js -/build -/docs-svelte-kit/shim/eslint.mjs -/docs-svelte-kit/shim/assert.mjs -!/.*.js -/docs-svelte-kit/src/routes/*.md -/docs-svelte-kit/src/routes/**/*.md -/docs-svelte-kit/src/app.html -/src/rule-types.ts - -# JSONSchema bug? -/.devcontainer/devcontainer.json - -# Parser bug? -/tests/fixtures/rules/indent/invalid/const-tag01-input.svelte -/tests/fixtures/rules/indent/invalid/const-tag01-output.svelte diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 3beeee000..000000000 --- a/.eslintrc.js +++ /dev/null @@ -1,192 +0,0 @@ -'use strict'; - -// const version = require("./package.json").version - -module.exports = { - parserOptions: { - sourceType: 'script', - ecmaVersion: 'latest', - project: require.resolve('./tsconfig.json') - }, - extends: [ - 'plugin:@ota-meshi/recommended', - 'plugin:@ota-meshi/+node', - 'plugin:@ota-meshi/+typescript', - 'plugin:@ota-meshi/+eslint-plugin', - 'plugin:@ota-meshi/+package-json', - 'plugin:@ota-meshi/+json', - 'plugin:@ota-meshi/+yaml', - 'plugin:@ota-meshi/+md', - 'plugin:@ota-meshi/+prettier' - ], - rules: { - 'require-jsdoc': 'off', - 'no-warning-comments': 'warn', - 'no-lonely-if': 'off', - 'new-cap': 'off', - 'no-shadow': 'off', - 'no-void': ['error', { allowAsStatement: true }], - 'prettier/prettier': [ - 'error', - {}, - { - usePrettierrc: true - } - ], - 'n/file-extension-in-import': 'off', // It's a plugin bug(?). - // Repo rule - 'no-restricted-imports': [ - 'error', - { - patterns: [ - { - group: ['/regexpp', '/regexpp/*'], - message: 'Please use `@eslint-community/regexpp` instead.' - }, - { - group: ['/eslint-utils', '/eslint-utils/*'], - message: 'Please use `@eslint-community/eslint-utils` instead.' - } - ] - } - ] - }, - overrides: [ - { - files: ['*.md'], - extends: 'plugin:mdx/recommended', - settings: { - 'mdx/code-blocks': true - } - }, - { - files: ['*.md/**', '**/*.md/**'], - rules: { - 'n/no-missing-import': 'off' - } - }, - { - files: ['*.mjs'], - parserOptions: { - sourceType: 'module' - } - }, - { - files: ['*.svelte'], - extends: ['plugin:svelte/base'], - parser: 'svelte-eslint-parser', - parserOptions: { - parser: { - ts: '@typescript-eslint/parser', - js: 'espree' - } - } - }, - { - files: ['*.ts', '*.mts'], - parser: '@typescript-eslint/parser', - parserOptions: { - sourceType: 'module', - project: require.resolve('./tsconfig.json') - }, - rules: { - '@typescript-eslint/naming-convention': [ - 'error', - { - selector: 'default', - format: ['camelCase'], - leadingUnderscore: 'allow', - trailingUnderscore: 'allow' - }, - { - selector: 'variable', - format: ['camelCase', 'UPPER_CASE', 'PascalCase'], - leadingUnderscore: 'allow', - trailingUnderscore: 'allow' - }, - { - selector: 'typeLike', - format: ['PascalCase'] - }, - { - selector: 'property', - format: null - }, - { - selector: 'method', - format: null - }, - { - selector: 'import', - format: null - } - ], - '@typescript-eslint/no-non-null-assertion': 'off' - } - }, - { - files: ['src/**'], - rules: { - '@typescript-eslint/no-restricted-imports': [ - 'error', - { - patterns: [ - { - group: ['@typescript-eslint/*'], - message: - '@typescript-eslint is not included in dependencies. Only type-import is allowed.', - allowTypeImports: true - } - ] - } - ], - 'no-restricted-properties': [ - 'error', - { object: 'context', property: 'getSourceCode', message: 'Use src/utils/compat.ts' }, - { object: 'context', property: 'getFilename', message: 'Use src/utils/compat.ts' }, - { - object: 'context', - property: 'getPhysicalFilename', - message: 'Use src/utils/compat.ts' - }, - { object: 'context', property: 'getCwd', message: 'Use src/utils/compat.ts' }, - { object: 'context', property: 'getScope', message: 'Use src/utils/compat.ts' }, - { object: 'context', property: 'parserServices', message: 'Use src/utils/compat.ts' } - ] - } - }, - { - files: ['src/rules/**'], - rules: {} - }, - { - files: ['src/rules/indent-helpers/**'], - rules: { - 'eslint-plugin/require-meta-docs-description': 'off', - 'eslint-plugin/require-meta-docs-url': 'off', - 'eslint-plugin/require-meta-type': 'off', - 'eslint-plugin/prefer-message-ids': 'off', - 'eslint-plugin/prefer-object-rule': 'off', - 'eslint-plugin/require-meta-schema': 'off' - } - }, - { - files: ['tests/**'], - rules: { - '@typescript-eslint/no-misused-promises': 'off', - '@typescript-eslint/no-require-imports': 'off' - } - }, - { - files: ['scripts/**/*.ts', 'tests/**/*.ts'], - parser: '@typescript-eslint/parser', - parserOptions: { - sourceType: 'module', - project: require.resolve('./tsconfig.json') - }, - rules: { - 'no-console': 'off' - } - } - ] -}; diff --git a/.github/workflows/NodeCI.yml b/.github/workflows/NodeCI.yml index 30033a9a5..206d2d01b 100644 --- a/.github/workflows/NodeCI.yml +++ b/.github/workflows/NodeCI.yml @@ -39,13 +39,8 @@ jobs: strategy: matrix: os: [ubuntu-latest] - eslint: [7, 8] + eslint: [7, 8, 9] node: [20] - include: - # On next ESLint version - - eslint: ^9.0.0-0 - node: 20 - os: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 @@ -58,7 +53,7 @@ jobs: run: |+ pnpm install -D eslint@${{ matrix.eslint }} rm -rf node_modules - if: matrix.eslint != 8 + if: matrix.eslint != 9 - name: Install Packages run: pnpm install - name: Test @@ -69,7 +64,16 @@ jobs: strategy: matrix: os: [ubuntu-latest] - node: [16, 17, 18, 20] + eslint: [9] + node: [18, 20] + include: + # On old Node.js version + - eslint: 8 + node: 16 + os: ubuntu-latest + - eslint: 8 + node: 17 + os: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 @@ -82,6 +86,10 @@ jobs: run: |+ pnpm install -D svelte@4 rm -rf node_modules + - name: Install ESLint ${{ matrix.eslint }} + run: |+ + pnpm install -D eslint@${{ matrix.eslint }} + rm -rf node_modules - name: Install Packages run: pnpm install - name: Test @@ -107,7 +115,7 @@ jobs: rm -rf node_modules - name: Install svelte@3 run: |+ - pnpm install -D svelte@3 @typescript-eslint/parser@5 @typescript-eslint/eslint-plugin@5 + pnpm install -D svelte@3 @typescript-eslint/parser@5 @typescript-eslint/eslint-plugin@5 eslint@8 rm -rf node_modules - name: Install Packages run: pnpm install diff --git a/README.md b/README.md index 0699e7c81..435777a47 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ Use `eslint.config.js` file to configure rules. See also: null; } diff --git a/docs-svelte-kit/shim/os.mjs b/docs-svelte-kit/shim/os.mjs index 95f24ca2b..535c3e75f 100644 --- a/docs-svelte-kit/shim/os.mjs +++ b/docs-svelte-kit/shim/os.mjs @@ -1,4 +1,3 @@ -/* eslint require-jsdoc:0 -- shim */ function platform() { return ''; } diff --git a/docs-svelte-kit/shim/path.mjs b/docs-svelte-kit/shim/path.mjs deleted file mode 100644 index 63e3abc27..000000000 --- a/docs-svelte-kit/shim/path.mjs +++ /dev/null @@ -1,63 +0,0 @@ -/* eslint require-jsdoc:0 -- shim */ - -function dirname(p) { - return p.split('/').slice(0, -1).join('/') || p; -} - -function extname(p) { - return /\.[\w$-]+$/iu.exec(p)[0]; -} - -function basename(p, ext) { - const nm = p.split('/').slice(-1)[0]; - if (!ext) { - return nm; - } - return nm.endsWith(ext) ? nm.slice(0, -ext.length) : nm; -} - -function relative(s) { - return s; -} - -function resolve(s) { - return s; -} - -function isAbsolute() { - return false; -} - -function join(...args) { - return args.length ? normalize(args.join('/')) : '.'; -} - -function normalize(path) { - let result = []; - for (const part of path.replace(/\/+/gu, '/').split('/')) { - if (part === '..') { - if (result[0] && result[0] !== '..' && result[0] !== '.') result.shift(); - } else if (part === '.' && result.length) { - // noop - } else { - result.unshift(part); - } - } - return result.reverse().join('/'); -} - -const sep = '/'; -const posix = { - dirname, - extname, - resolve, - relative, - sep, - isAbsolute, - join, - normalize, - basename -}; -posix.posix = posix; -export { dirname, extname, posix, resolve, relative, sep, isAbsolute, join, normalize, basename }; -export default posix; diff --git a/docs-svelte-kit/shim/postcss-load-config.mjs b/docs-svelte-kit/shim/postcss-load-config.mjs index bd4450887..a03070451 100644 --- a/docs-svelte-kit/shim/postcss-load-config.mjs +++ b/docs-svelte-kit/shim/postcss-load-config.mjs @@ -1,4 +1,3 @@ -/* eslint require-jsdoc:0 -- shim */ import nested from 'postcss-nested'; function loadConfig() { diff --git a/docs-svelte-kit/shim/url.mjs b/docs-svelte-kit/shim/url.mjs index 00921bad0..ba848d8bd 100644 --- a/docs-svelte-kit/shim/url.mjs +++ b/docs-svelte-kit/shim/url.mjs @@ -1,4 +1,3 @@ -/* eslint require-jsdoc:0 -- shim */ function fileURLToPath(p) { return p; } diff --git a/docs-svelte-kit/src/.eslintrc.js b/docs-svelte-kit/src/.eslintrc.js deleted file mode 100644 index af7e60f6a..000000000 --- a/docs-svelte-kit/src/.eslintrc.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = { - parserOptions: { - sourceType: 'module' - }, - rules: { - 'n/no-unsupported-features/es-syntax': 'off', - 'require-jsdoc': 'off', - 'n/no-missing-import': 'off' - } -}; diff --git a/docs-svelte-kit/src/lib/components/ESLintCodeBlock.svelte b/docs-svelte-kit/src/lib/components/ESLintCodeBlock.svelte index 919c3ea17..393070fc5 100644 --- a/docs-svelte-kit/src/lib/components/ESLintCodeBlock.svelte +++ b/docs-svelte-kit/src/lib/components/ESLintCodeBlock.svelte @@ -1,12 +1,13 @@ {data}, {errors} diff --git a/tests/fixtures/rules/valid-prop-names-in-kit-pages/valid/+test004-input.svelte b/tests/fixtures/rules/valid-prop-names-in-kit-pages/valid/+test004-input.svelte index 6fca7bb73..8b58dace8 100644 --- a/tests/fixtures/rules/valid-prop-names-in-kit-pages/valid/+test004-input.svelte +++ b/tests/fixtures/rules/valid-prop-names-in-kit-pages/valid/+test004-input.svelte @@ -1,5 +1,5 @@ {data}, {errors} diff --git a/tests/utils/utils.ts b/tests/utils/utils.ts index 7429973aa..202a97896 100644 --- a/tests/utils/utils.ts +++ b/tests/utils/utils.ts @@ -2,7 +2,7 @@ import fs from 'fs'; import path from 'path'; import type { RuleTester } from 'eslint'; import type { Linter as LinterType } from 'eslint'; -import plugin = require('../../src/index'); +import plugin from '../../src/index'; import { applyFixes } from './source-code-fixer'; import { parse as parseYaml, stringify as stringifyYaml } from 'yaml'; import semver from 'semver'; diff --git a/tools/update-docs.ts b/tools/update-docs.ts index 9d2bf0b42..4e94068da 100644 --- a/tools/update-docs.ts +++ b/tools/update-docs.ts @@ -89,15 +89,13 @@ class DocFile { } else { notes.push('- :warning: This rule was **deprecated**.'); } - } else { - if (recommended) { - if (recommended === 'base') { - notes.push( - '- :gear: This rule is included in `"plugin:svelte/base"` and `"plugin:svelte/recommended"`.' - ); - } else { - notes.push('- :gear: This rule is included in `"plugin:svelte/recommended"`.'); - } + } else if (recommended) { + if (recommended === 'base') { + notes.push( + '- :gear: This rule is included in `"plugin:svelte/base"` and `"plugin:svelte/recommended"`.' + ); + } else { + notes.push('- :gear: This rule is included in `"plugin:svelte/recommended"`.'); } } if (fixable) { diff --git a/tools/update-readme.ts b/tools/update-readme.ts index 29378b4a9..04fd7e2e5 100644 --- a/tools/update-readme.ts +++ b/tools/update-readme.ts @@ -37,9 +37,9 @@ ${newReadme .replace(/[\s\S]*?/gu, '') .replace( /\(https:\/\/sveltejs.github.io\/eslint-plugin-svelte(.*?)\)/gu, - (_ptn, path: string) => { - const [hash] = /(?:#.*)?$/u.exec(path)!; - const pathWithoutHash = hash ? path.slice(0, -hash.length) : path; + (_ptn, filepath: string) => { + const [hash] = /(?:#.*)?$/u.exec(filepath)!; + const pathWithoutHash = hash ? filepath.slice(0, -hash.length) : filepath; const normalizePathWithoutHash = pathWithoutHash.replace(/\/$/u, ''); const [file] = /[^/]+$/u.exec(normalizePathWithoutHash)!; const pathWithoutFile = file diff --git a/vite.config.mts b/vite.config.mts index ee5c6e607..75a4da399 100644 --- a/vite.config.mts +++ b/vite.config.mts @@ -1,7 +1,8 @@ -// @ts-expect-error -- Missing type information import { sveltekit } from '@sveltejs/kit/vite'; import path from 'path'; +// @ts-expect-error -- Missing types import svelteMd from 'vite-plugin-svelte-md'; +import eslint4b, { requireESLintUseAtYourOwnRisk4b } from 'vite-plugin-eslint4b'; import svelteMdOption from './docs-svelte-kit/tools/vite-plugin-svelte-md-option.mjs'; import './docs-svelte-kit/build-system/build.mts'; @@ -11,12 +12,7 @@ import { fileURLToPath } from 'url'; generateRoutes(); -const dirname = path.dirname( - fileURLToPath( - // @ts-expect-error -- Cannot change `module` option - import.meta.url - ) -); +const dirname = path.dirname(fileURLToPath(import.meta.url)); /** @type {import('vite').UserConfig} */ const config: UserConfig = { @@ -27,19 +23,19 @@ const config: UserConfig = { root: path.join(dirname, './docs') }) ), - sveltekit() + sveltekit(), + eslint4b(), + requireESLintUseAtYourOwnRisk4b() ], server: { fs: { strict: false } }, resolve: { alias: { - eslint: path.join(dirname, './docs-svelte-kit/shim/eslint.mjs'), assert: path.join(dirname, './docs-svelte-kit/shim/assert.mjs'), 'postcss-load-config': path.join(dirname, './docs-svelte-kit/shim/postcss-load-config.mjs'), 'source-map-js': path.join(dirname, './docs-svelte-kit/shim/source-map-js.mjs'), module: path.join(dirname, './docs-svelte-kit/shim/module.mjs'), - path: path.join(dirname, './docs-svelte-kit/shim/path.mjs'), url: path.join(dirname, './docs-svelte-kit/shim/url.mjs'), os: path.join(dirname, './docs-svelte-kit/shim/os.mjs'), fs: path.join(dirname, './docs-svelte-kit/shim/fs.mjs'),