diff --git a/.eslintrc.yml b/.eslintrc.yml index 6683556..ae08042 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -2,3 +2,18 @@ root: true extends: - plugin:@mysticatea/es2015 - plugin:@mysticatea/+eslint-plugin + +overrides: + - files: ["lib/utils.js", "scripts/*.js"] + rules: + "@mysticatea/node/no-sync": off + + - files: + [ + "lib/configs.js", + "lib/foreign-rules/ts.js", + "lib/processors.js", + "lib/rules.js", + ] + rules: + "@mysticatea/node/global-require": off diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 1d61214..317dd08 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -10,17 +10,34 @@ on: jobs: test: name: Test - runs-on: ubuntu-latest strategy: matrix: - node: [12.x, 10.x, 8.x] + os: [ubuntu-latest] + eslint: [7] + node: [16] + include: + # On other platforms + - node: 16 + os: windows-latest + - node: 16 + os: macos-latest + # On old Node.js versions + - node: 14 + os: ubuntu-latest + - node: 12 + os: ubuntu-latest + - node: 10 + os: ubuntu-latest + # On the minimum supported ESLint/Node.js version + - node: 10.12.0 + os: ubuntu-latest + + runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v1 - with: - fetch-depth: 1 + uses: actions/checkout@v2 - name: Install Node.js ${{ matrix.node }} - uses: actions/setup-node@v1 + uses: actions/setup-node@v2 with: node-version: ${{ matrix.node }} - name: Install Packages diff --git a/README.md b/README.md index 2d9263c..0f80663 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,8 @@ npm install --save-dev eslint @mysticatea/eslint-plugin ### Requirements -- Node.js `^8.10.0` or newer versions. -- ESLint `^6.3.0` or newer versions. +- Node.js `^10.12.0 || >=12.0.0` or newer versions. +- ESLint `^7.0.0` or newer versions. ## 📖 Usage diff --git a/lib/configs/+eslint-plugin.js b/lib/configs/+eslint-plugin.js index 1241df1..d39bef6 100644 --- a/lib/configs/+eslint-plugin.js +++ b/lib/configs/+eslint-plugin.js @@ -34,6 +34,7 @@ module.exports = { "@mysticatea/eslint-plugin/no-missing-placeholders": "error", "@mysticatea/eslint-plugin/no-unused-placeholders": "error", "@mysticatea/eslint-plugin/no-useless-token-range": "error", + "@mysticatea/eslint-plugin/prefer-object-rule": "error", "@mysticatea/eslint-plugin/prefer-output-null": "error", "@mysticatea/eslint-plugin/prefer-placeholders": "error", "@mysticatea/eslint-plugin/prefer-replace-text": "error", @@ -41,11 +42,14 @@ module.exports = { "error", "[^a-z'\"{].*\\.$", ], + "@mysticatea/eslint-plugin/require-meta-docs-description": + "error", "@mysticatea/eslint-plugin/require-meta-docs-url": [ "error", { pattern: rulesDocumentUrl }, ], "@mysticatea/eslint-plugin/require-meta-fixable": "error", + "@mysticatea/eslint-plugin/require-meta-schema": "error", "@mysticatea/eslint-plugin/require-meta-type": "error", "@mysticatea/eslint-plugin/test-case-property-ordering": [ "error", diff --git a/lib/configs/+node.js b/lib/configs/+node.js index b151b63..19e59d2 100644 --- a/lib/configs/+node.js +++ b/lib/configs/+node.js @@ -46,12 +46,15 @@ module.exports = { require: "readonly", }, rules: { + "@mysticatea/node/callback-return": "error", "@mysticatea/node/exports-style": ["error", "module.exports"], "@mysticatea/node/file-extension-in-import": [ "error", "always", { ".js": "never", ".ts": "never", ".tsx": "never" }, ], + "@mysticatea/node/global-require": "error", + "@mysticatea/node/handle-callback-err": "error", "@mysticatea/node/no-callback-literal": "off", "@mysticatea/node/no-deprecated-api": "error", "@mysticatea/node/no-exports-assign": "error", @@ -59,6 +62,14 @@ module.exports = { "@mysticatea/node/no-extraneous-require": "error", "@mysticatea/node/no-missing-import": "error", "@mysticatea/node/no-missing-require": "error", + "@mysticatea/node/no-mixed-requires": "error", + "@mysticatea/node/no-new-require": "error", + "@mysticatea/node/no-path-concat": "error", + "@mysticatea/node/no-process-env": "error", + "@mysticatea/node/no-process-exit": "error", + "@mysticatea/node/no-restricted-import": "error", + "@mysticatea/node/no-restricted-require": "error", + "@mysticatea/node/no-sync": "error", "@mysticatea/node/no-unpublished-bin": "error", "@mysticatea/node/no-unpublished-import": "error", "@mysticatea/node/no-unpublished-require": "error", diff --git a/lib/configs/_base.js b/lib/configs/_base.js index 4a21337..d6c36db 100644 --- a/lib/configs/_base.js +++ b/lib/configs/_base.js @@ -27,12 +27,14 @@ module.exports = { "consistent-return": "error", curly: "error", "default-case": "error", + "default-case-last": "error", "default-param-last": "error", "dot-notation": "error", eqeqeq: ["error", "always", { null: "ignore" }], "for-direction": "error", "func-style": ["error", "declaration"], "getter-return": "error", + "grouped-accessor-pairs": "error", "init-declarations": "error", "linebreak-style": ["error", "unix"], "lines-between-class-members": "error", @@ -47,11 +49,13 @@ module.exports = { "no-compare-neg-zero": "error", "no-cond-assign": "error", "no-constant-condition": "error", + "no-constructor-return": "error", "no-control-regex": "error", "no-debugger": "error", "no-delete-var": "error", "no-div-regex": "error", "no-dupe-args": "error", + "no-dupe-else-if": "error", "no-dupe-keys": "error", "no-duplicate-case": "error", "no-else-return": "error", @@ -89,6 +93,7 @@ module.exports = { "no-lone-blocks": "error", "no-lonely-if": "error", "no-loop-func": "error", + "no-loss-of-precision": "error", "no-misleading-character-class": "error", "no-mixed-operators": [ "error", @@ -103,10 +108,12 @@ module.exports = { "no-new-object": "error", "no-new-require": "error", "no-new-wrappers": "error", + "no-nonoctal-decimal-escape": "error", "no-obj-calls": "error", "no-octal": "error", "no-octal-escape": "error", "no-param-reassign": ["error", { props: false }], + "no-promise-executor-return": "error", "no-process-env": "error", "no-process-exit": "error", "no-prototype-builtins": "error", @@ -128,6 +135,7 @@ module.exports = { "no-self-assign": ["error", { props: true }], "no-self-compare": "error", "no-sequences": "error", + "no-setter-return": "error", "no-shadow": ["error", { builtinGlobals: true }], "no-shadow-restricted-names": "error", "no-sparse-arrays": "error", @@ -138,8 +146,10 @@ module.exports = { "no-unmodified-loop-condition": "error", "no-unneeded-ternary": "error", "no-unreachable": "error", + "no-unreachable-loop": "error", "no-unsafe-finally": "error", "no-unsafe-negation": ["error", { enforceForOrderingRelations: true }], + "no-unsafe-optional-chaining": "error", "no-unused-expressions": "error", "no-unused-labels": "error", "no-unused-vars": [ @@ -153,6 +163,7 @@ module.exports = { }, ], "no-use-before-define": ["error", "nofunc"], + "no-useless-backreference": "error", "no-useless-call": "error", "no-useless-catch": "error", "no-useless-concat": "error", @@ -173,6 +184,7 @@ module.exports = { { blankLine: "always", next: "function", prev: "*" }, { blankLine: "always", next: "*", prev: "function" }, ], + "prefer-exponentiation-operator": "error", "prefer-promise-reject-errors": "error", "prefer-regex-literals": "error", quotes: ["error", "double", { avoidEscape: true }], @@ -294,6 +306,7 @@ module.exports = { "guard-for-in": "off", "handle-callback-err": "off", "id-blacklist": "off", + "id-denylist": "off", "id-length": "off", "id-match": "off", "line-comment-position": "off", @@ -327,6 +340,7 @@ module.exports = { "no-path-concat": "off", "no-plusplus": "off", "no-proto": "off", + "no-restricted-exports": "off", "no-restricted-globals": "off", "no-restricted-imports": "off", "no-restricted-modules": "off", @@ -387,6 +401,7 @@ module.exports = { ], }, ], + "@mysticatea/eslint-comments/require-description": "error", // prettier "@mysticatea/prettier": [ diff --git a/lib/configs/_browser-globals.js b/lib/configs/_browser-globals.js index e4cba16..44a269e 100644 --- a/lib/configs/_browser-globals.js +++ b/lib/configs/_browser-globals.js @@ -1,4 +1,6 @@ +// // DON'T EDIT THIS FILE WHICH WAS GENERATED BY './scripts/generate-browser-globals.js'. +// "use strict" module.exports = { diff --git a/lib/configs/_override-special.js b/lib/configs/_override-special.js index 17916c0..e24a2fa 100644 --- a/lib/configs/_override-special.js +++ b/lib/configs/_override-special.js @@ -18,7 +18,6 @@ module.exports = { extends: [require.resolve("./+node.js")], rules: { "no-console": "off", - "no-process-env": "off", }, }, { @@ -33,7 +32,6 @@ module.exports = { ], rules: { "no-console": "off", - "no-process-env": "off", }, }, ], diff --git a/lib/configs/_override-ts.js b/lib/configs/_override-ts.js index 3b94d9a..e730239 100644 --- a/lib/configs/_override-ts.js +++ b/lib/configs/_override-ts.js @@ -19,40 +19,79 @@ module.exports = { "@mysticatea/ts/adjacent-overload-signatures": "error", "@mysticatea/ts/array-type": "error", "@mysticatea/ts/await-thenable": "error", - "@mysticatea/ts/ban-ts-ignore": "error", - "@mysticatea/ts/class-name-casing": "error", + "@mysticatea/ts/ban-ts-comment": "error", + "@mysticatea/ts/ban-tslint-comment": "error", + "@mysticatea/ts/class-literal-property-style": "error", + "@mysticatea/ts/comma-spacing": "error", + "@mysticatea/ts/no-confusing-non-null-assertion": "error", "@mysticatea/ts/consistent-type-assertions": "error", + "@mysticatea/ts/default-param-last": "error", + "@mysticatea/ts/dot-notation": "error", "@mysticatea/ts/explicit-member-accessibility": "error", - "@mysticatea/ts/interface-name-prefix": "error", - "@mysticatea/ts/member-naming": "error", + "@mysticatea/ts/explicit-module-boundary-types": "error", + "@mysticatea/ts/init-declarations": "error", + "@mysticatea/ts/keyword-spacing": "error", + "@mysticatea/ts/method-signature-style": "error", + "@mysticatea/ts/naming-convention": "error", "@mysticatea/ts/no-array-constructor": "error", + "@mysticatea/ts/no-base-to-string": "error", + "@mysticatea/ts/no-dupe-class-members": "error", + "@mysticatea/ts/no-dynamic-delete": "error", "@mysticatea/ts/no-empty-interface": "error", + "@mysticatea/ts/no-implicit-any-catch": "error", + "@mysticatea/ts/no-extra-non-null-assertion": "error", + "@mysticatea/ts/no-extra-semi": "error", "@mysticatea/ts/no-extraneous-class": "error", "@mysticatea/ts/no-floating-promises": "error", "@mysticatea/ts/no-for-in-array": "error", + "@mysticatea/ts/no-implied-eval": "error", "@mysticatea/ts/no-inferrable-types": "error", + "@mysticatea/ts/no-invalid-this": "error", + "@mysticatea/ts/no-invalid-void-type": "error", "@mysticatea/ts/no-misused-new": "error", "@mysticatea/ts/no-misused-promises": "error", + "@mysticatea/ts/no-non-null-asserted-optional-chain": "error", "@mysticatea/ts/no-parameter-properties": "error", "@mysticatea/ts/no-require-imports": "error", "@mysticatea/ts/no-this-alias": [ "error", { allowDestructuring: true }, ], + "@mysticatea/ts/no-throw-literal": "error", + "@mysticatea/ts/no-unnecessary-boolean-literal-compare": + "error", "@mysticatea/ts/no-unnecessary-qualifier": "error", "@mysticatea/ts/no-unnecessary-type-arguments": "error", "@mysticatea/ts/no-unnecessary-type-assertion": "error", + "@mysticatea/ts/no-unsafe-assignment": "error", + "@mysticatea/ts/no-unsafe-call": "error", + "@mysticatea/ts/no-unsafe-member-access": "error", + "@mysticatea/ts/no-unsafe-return": "error", + "@mysticatea/ts/no-unused-expressions": "error", + "@mysticatea/ts/no-unused-vars-experimental": "error", "@mysticatea/ts/no-var-requires": "error", + "@mysticatea/ts/prefer-as-const": "error", + "@mysticatea/ts/prefer-enum-initializers": "error", // https://github.com/typescript-eslint/typescript-eslint/issues/454 "@mysticatea/ts/prefer-function-type": "off", "@mysticatea/ts/prefer-includes": "error", + "@mysticatea/ts/prefer-literal-enum-member": "error", "@mysticatea/ts/prefer-namespace-keyword": "error", + "@mysticatea/ts/prefer-nullish-coalescing": "error", + "@mysticatea/ts/prefer-optional-chain": "error", + "@mysticatea/ts/prefer-readonly-parameter-types": "error", // https://github.com/typescript-eslint/typescript-eslint/issues/946 "@mysticatea/ts/prefer-readonly": "off", + "@mysticatea/ts/prefer-reduce-type-parameter": "off", "@mysticatea/ts/prefer-regexp-exec": "error", "@mysticatea/ts/prefer-string-starts-ends-with": "error", + "@mysticatea/ts/prefer-ts-expect-error": "off", + "@mysticatea/ts/require-array-sort-compare": "off", "@mysticatea/ts/restrict-plus-operands": "error", - "@mysticatea/ts/require-array-sort-compare": "error", + "@mysticatea/ts/restrict-template-expressions": "error", + "@mysticatea/ts/return-await": "error", + "@mysticatea/ts/space-before-function-paren": "error", + "@mysticatea/ts/switch-exhaustiveness-check": "error", "@mysticatea/ts/triple-slash-reference": "error", // ăȘんかèȘ€æ€œçŸ„ăŒć€šă„... "@mysticatea/ts/unbound-method": [ @@ -61,6 +100,8 @@ module.exports = { ], // https://github.com/typescript-eslint/typescript-eslint/issues/452 "@mysticatea/ts/unified-signatures": "off", + "@mysticatea/ts/lines-between-class-members": "error", + "@mysticatea/ts/no-loss-of-precision": "error", "@mysticatea/prettier": [ "error", { @@ -75,8 +116,6 @@ module.exports = { ], // Replacements - camelcase: "off", - "@mysticatea/ts/camelcase": "error", "no-empty-function": "off", "@mysticatea/ts/no-empty-function": "error", "no-useless-constructor": "off", @@ -101,7 +140,6 @@ module.exports = { "@mysticatea/ts/consistent-type-definitions": "off", "@mysticatea/ts/explicit-function-return-type": "off", // I want but this is not so... "@mysticatea/ts/func-call-spacing": "off", // favor of Prettier. - "@mysticatea/ts/generic-type-naming": "off", "@mysticatea/ts/indent": "off", // favor of Prettier. "@mysticatea/ts/member-delimiter-style": "off", // favor of Prettier. "@mysticatea/ts/member-ordering": "off", diff --git a/lib/configs/_override-vue.js b/lib/configs/_override-vue.js index 9d38f11..1b4ec25 100644 --- a/lib/configs/_override-vue.js +++ b/lib/configs/_override-vue.js @@ -15,9 +15,14 @@ module.exports = { parser: require.resolve("vue-eslint-parser"), rules: { // Enabled rules + "@mysticatea/vue/array-bracket-newline": "error", "@mysticatea/vue/array-bracket-spacing": ["error", "never"], "@mysticatea/vue/arrow-spacing": "error", + "@mysticatea/vue/attribute-hyphenation": "error", + "@mysticatea/vue/attributes-order": "error", + "@mysticatea/vue/block-lang": "error", "@mysticatea/vue/block-spacing": "error", + "@mysticatea/vue/block-tag-newline": "error", "@mysticatea/vue/brace-style": "error", "@mysticatea/vue/camelcase": "error", "@mysticatea/vue/comma-dangle": [ @@ -30,13 +35,40 @@ module.exports = { functions: "always", }, ], + "@mysticatea/vue/comma-spacing": "error", + "@mysticatea/vue/comma-style": "error", "@mysticatea/vue/comment-directive": "error", + "@mysticatea/vue/component-definition-name-casing": "error", + "@mysticatea/vue/component-name-in-template-casing": [ + "error", + "kebab-case", + ], + "@mysticatea/vue/component-tags-order": "error", + "@mysticatea/vue/custom-event-name-casing": "error", "@mysticatea/vue/dot-location": "error", + "@mysticatea/vue/dot-notation": "error", "@mysticatea/vue/eqeqeq": [ "error", "always", { null: "ignore" }, ], + "@mysticatea/vue/func-call-spacing": "error", + "@mysticatea/vue/html-button-has-type": "error", + "@mysticatea/vue/html-closing-bracket-newline": [ + "error", + { + singleline: "never", + multiline: "always", + }, + ], + "@mysticatea/vue/html-closing-bracket-spacing": "error", + "@mysticatea/vue/html-comment-content-newline": "error", + "@mysticatea/vue/html-comment-content-spacing": "error", + "@mysticatea/vue/html-comment-indent": "error", + "@mysticatea/vue/html-end-tags": "error", + "@mysticatea/vue/html-indent": ["error", 4], + "@mysticatea/vue/html-quotes": "error", + "@mysticatea/vue/html-self-closing": "error", "@mysticatea/vue/jsx-uses-vars": "error", "@mysticatea/vue/key-spacing": "error", "@mysticatea/vue/keyword-spacing": "error", @@ -51,32 +83,142 @@ module.exports = { }, }, ], + "@mysticatea/vue/max-len": ["error", { tabWidth: 4 }], + "@mysticatea/vue/multiline-html-element-content-newline": + "error", + "@mysticatea/vue/mustache-interpolation-spacing": "error", + "@mysticatea/vue/new-line-between-multi-line-property": "error", + "@mysticatea/vue/next-tick-style": "error", + "@mysticatea/vue/no-arrow-functions-in-watch": "error", "@mysticatea/vue/no-async-in-computed-properties": "error", + "@mysticatea/vue/no-bare-strings-in-template": "error", "@mysticatea/vue/no-boolean-default": "error", + "@mysticatea/vue/no-constant-condition": "error", + "@mysticatea/vue/no-custom-modifiers-on-v-model": "error", + "@mysticatea/vue/no-deprecated-data-object-declaration": + "error", + "@mysticatea/vue/no-deprecated-destroyed-lifecycle": "error", + "@mysticatea/vue/no-deprecated-dollar-listeners-api": "error", + "@mysticatea/vue/no-deprecated-dollar-scopedslots-api": "error", + "@mysticatea/vue/no-deprecated-events-api": "error", + "@mysticatea/vue/no-deprecated-filter": "error", + "@mysticatea/vue/no-deprecated-functional-template": "error", + "@mysticatea/vue/no-deprecated-html-element-is": "error", + "@mysticatea/vue/no-deprecated-inline-template": "error", + "@mysticatea/vue/no-deprecated-props-default-this": "error", "@mysticatea/vue/no-deprecated-scope-attribute": "error", + "@mysticatea/vue/no-deprecated-slot-attribute": "error", + "@mysticatea/vue/no-deprecated-slot-scope-attribute": "error", + "@mysticatea/vue/no-deprecated-v-bind-sync": "error", + "@mysticatea/vue/no-deprecated-v-is": "error", + "@mysticatea/vue/no-deprecated-v-on-native-modifier": "error", + "@mysticatea/vue/no-deprecated-v-on-number-modifiers": "error", + "@mysticatea/vue/no-deprecated-vue-config-keycodes": "error", "@mysticatea/vue/no-dupe-keys": "error", + "@mysticatea/vue/no-dupe-v-else-if": "error", + "@mysticatea/vue/no-duplicate-attr-inheritance": "error", "@mysticatea/vue/no-duplicate-attributes": "error", + "@mysticatea/vue/no-empty-component-block": "error", "@mysticatea/vue/no-empty-pattern": "error", + "@mysticatea/vue/no-export-in-script-setup": "error", + "@mysticatea/vue/no-extra-parens": "error", + "@mysticatea/vue/no-invalid-model-keys": "error", + "@mysticatea/vue/no-irregular-whitespace": "error", + "@mysticatea/vue/no-lifecycle-after-await": "error", + "@mysticatea/vue/no-lone-template": "error", + "@mysticatea/vue/no-multi-spaces": "error", + "@mysticatea/vue/no-multiple-objects-in-class": "error", + "@mysticatea/vue/no-multiple-slot-args": "error", + "@mysticatea/vue/no-multiple-template-root": "error", + "@mysticatea/vue/no-mutating-props": "error", "@mysticatea/vue/no-parsing-error": "error", + "@mysticatea/vue/no-potential-component-option-typo": "error", + "@mysticatea/vue/no-ref-as-operand": "error", + "@mysticatea/vue/no-reserved-component-names": "error", "@mysticatea/vue/no-reserved-keys": "error", + "@mysticatea/vue/no-restricted-block": "error", + "@mysticatea/vue/no-restricted-call-after-await": "error", + "@mysticatea/vue/no-restricted-component-options": "error", + "@mysticatea/vue/no-restricted-custom-event": "error", + "@mysticatea/vue/no-restricted-props": "error", + "@mysticatea/vue/no-restricted-static-attribute": "error", + "@mysticatea/vue/no-restricted-v-bind": "error", + "@mysticatea/vue/no-setup-props-destructure": "error", "@mysticatea/vue/no-shared-component-data": "error", "@mysticatea/vue/no-side-effects-in-computed-properties": "error", + "@mysticatea/vue/no-spaces-around-equal-signs-in-attribute": + "error", + "@mysticatea/vue/no-sparse-arrays": "error", + "@mysticatea/vue/no-static-inline-styles": "error", "@mysticatea/vue/no-template-key": "error", + "@mysticatea/vue/no-template-shadow": "error", + "@mysticatea/vue/no-template-target-blank": "error", "@mysticatea/vue/no-textarea-mustache": "error", + "@mysticatea/vue/no-this-in-before-route-enter": "error", + "@mysticatea/vue/no-unregistered-components": "error", + "@mysticatea/vue/no-unsupported-features": "error", + "@mysticatea/vue/no-unused-components": "error", + "@mysticatea/vue/no-unused-properties": "error", + "@mysticatea/vue/no-unused-refs": "error", "@mysticatea/vue/no-unused-vars": "error", + "@mysticatea/vue/no-use-computed-property-like-method": "error", + "@mysticatea/vue/no-use-v-if-with-v-for": "error", + "@mysticatea/vue/no-useless-concat": "error", + "@mysticatea/vue/no-useless-mustaches": "error", + "@mysticatea/vue/no-useless-v-bind": "error", + "@mysticatea/vue/no-v-for-template-key-on-child": "error", + "@mysticatea/vue/no-v-for-template-key": "error", + "@mysticatea/vue/no-v-html": "error", + "@mysticatea/vue/no-v-model-argument": "error", + "@mysticatea/vue/no-watch-after-await": "error", + "@mysticatea/vue/object-curly-newline": "error", "@mysticatea/vue/object-curly-spacing": ["error", "always"], + "@mysticatea/vue/object-property-newline": "error", + "@mysticatea/vue/one-component-per-file": "error", + "@mysticatea/vue/operator-linebreak": "error", + "@mysticatea/vue/order-in-components": "error", + "@mysticatea/vue/padding-line-between-blocks": "error", + "@mysticatea/vue/prefer-template": "error", + "@mysticatea/vue/prop-name-casing": "error", "@mysticatea/vue/require-component-is": "error", + "@mysticatea/vue/require-default-prop": "error", "@mysticatea/vue/require-direct-export": "error", + "@mysticatea/vue/require-emit-validator": "error", + "@mysticatea/vue/require-explicit-emits": "error", + "@mysticatea/vue/require-expose": "error", + "@mysticatea/vue/require-name-property": "error", + "@mysticatea/vue/require-prop-type-constructor": "error", + "@mysticatea/vue/require-prop-types": "error", "@mysticatea/vue/require-render-return": "error", + "@mysticatea/vue/require-slots-as-functions": "error", + "@mysticatea/vue/require-toggle-inside-transition": "error", "@mysticatea/vue/require-v-for-key": "error", "@mysticatea/vue/require-valid-default-prop": "error", "@mysticatea/vue/return-in-computed-property": "error", + "@mysticatea/vue/return-in-emits-validator": "error", + "@mysticatea/vue/script-setup-uses-vars": "error", + "@mysticatea/vue/singleline-html-element-content-newline": + "error", + "@mysticatea/vue/sort-keys": "error", + "@mysticatea/vue/space-in-parens": "error", "@mysticatea/vue/space-infix-ops": "error", "@mysticatea/vue/space-unary-ops": "error", + "@mysticatea/vue/static-class-names-order": "error", + "@mysticatea/vue/template-curly-spacing": "error", + "@mysticatea/vue/this-in-template": "error", + "@mysticatea/vue/use-v-on-exact": "error", + "@mysticatea/vue/v-bind-style": "error", + "@mysticatea/vue/v-for-delimiter-style": "error", + "@mysticatea/vue/v-on-event-hyphenation": "error", "@mysticatea/vue/v-on-function-call": "error", + "@mysticatea/vue/v-on-style": "error", "@mysticatea/vue/v-slot-style": "error", + "@mysticatea/vue/valid-define-emits": "error", + "@mysticatea/vue/valid-define-props": "error", + "@mysticatea/vue/valid-next-tick": "error", "@mysticatea/vue/valid-template-root": "error", + "@mysticatea/vue/valid-v-bind-sync": "error", "@mysticatea/vue/valid-v-bind": "error", "@mysticatea/vue/valid-v-cloak": "error", "@mysticatea/vue/valid-v-else-if": "error", @@ -84,6 +226,8 @@ module.exports = { "@mysticatea/vue/valid-v-for": "error", "@mysticatea/vue/valid-v-html": "error", "@mysticatea/vue/valid-v-if": "error", + "@mysticatea/vue/valid-v-is": "error", + "@mysticatea/vue/valid-v-memo": "error", "@mysticatea/vue/valid-v-model": "error", "@mysticatea/vue/valid-v-on": "error", "@mysticatea/vue/valid-v-once": "error", @@ -91,46 +235,6 @@ module.exports = { "@mysticatea/vue/valid-v-show": "error", "@mysticatea/vue/valid-v-slot": "error", "@mysticatea/vue/valid-v-text": "error", - "@mysticatea/vue/attribute-hyphenation": "error", - "@mysticatea/vue/html-end-tags": "error", - "@mysticatea/vue/html-indent": ["error", 4], - "@mysticatea/vue/html-self-closing": "error", - "@mysticatea/vue/mustache-interpolation-spacing": "error", - "@mysticatea/vue/name-property-casing": "error", - "@mysticatea/vue/no-multi-spaces": "error", - "@mysticatea/vue/require-default-prop": "error", - "@mysticatea/vue/require-prop-types": "error", - "@mysticatea/vue/v-bind-style": "error", - "@mysticatea/vue/v-on-style": "error", - "@mysticatea/vue/attributes-order": "error", - "@mysticatea/vue/html-quotes": "error", - "@mysticatea/vue/order-in-components": "error", - "@mysticatea/vue/this-in-template": "error", - "@mysticatea/vue/html-closing-bracket-newline": [ - "error", - { - singleline: "never", - multiline: "always", - }, - ], - "@mysticatea/vue/html-closing-bracket-spacing": "error", - "@mysticatea/vue/prop-name-casing": "error", - "@mysticatea/vue/component-name-in-template-casing": [ - "error", - "kebab-case", - ], - "@mysticatea/vue/multiline-html-element-content-newline": - "error", - "@mysticatea/vue/singleline-html-element-content-newline": - "error", - "@mysticatea/vue/no-spaces-around-equal-signs-in-attribute": - "error", - "@mysticatea/vue/no-template-shadow": "error", - "@mysticatea/vue/no-unused-components": "error", - "@mysticatea/vue/no-use-v-if-with-v-for": "error", - "@mysticatea/vue/no-v-html": "error", - "@mysticatea/vue/require-prop-type-constructor": "error", - "@mysticatea/vue/use-v-on-exact": "error", // Disabled rules (prefer prettier) "@mysticatea/vue/no-restricted-syntax": "off", diff --git a/lib/rules/no-literal-call.js b/lib/rules/no-literal-call.js index 22e6856..a6973dd 100644 --- a/lib/rules/no-literal-call.js +++ b/lib/rules/no-literal-call.js @@ -18,7 +18,7 @@ const LITERAL_AND_CLASS_TYPE = /^(?:(?:Array|Class|Object)Expression|(?:Template module.exports = { meta: { docs: { - description: "Disallow a call of a literal.", + description: "disallow a call of a literal.", category: "Possible Errors", recommended: false, url: diff --git a/lib/rules/no-this-in-static.js b/lib/rules/no-this-in-static.js index a6a342f..0f6f5cf 100644 --- a/lib/rules/no-this-in-static.js +++ b/lib/rules/no-this-in-static.js @@ -12,7 +12,7 @@ module.exports = { meta: { docs: { - description: "Disallow `this`/`super` in static methods", + description: "disallow `this`/`super` in static methods", category: "Best Practices", url: "https://github.com/mysticatea/eslint-plugin/blob/v13.0.0/docs/rules/no-this-in-static.md", diff --git a/lib/rules/no-use-ignored-vars.js b/lib/rules/no-use-ignored-vars.js index 5a4855b..e69e24b 100644 --- a/lib/rules/no-use-ignored-vars.js +++ b/lib/rules/no-use-ignored-vars.js @@ -17,7 +17,7 @@ const DEFAULT_IGNORE_PATTERN = /^_[a-zA-Z]+$/u module.exports = { meta: { docs: { - description: "Disallow a use of ignored variables.", + description: "disallow a use of ignored variables.", category: "Stylistic Issues", recommended: false, url: diff --git a/lib/rules/no-useless-rest-spread.js b/lib/rules/no-useless-rest-spread.js index ccca71b..64b907d 100644 --- a/lib/rules/no-useless-rest-spread.js +++ b/lib/rules/no-useless-rest-spread.js @@ -94,7 +94,7 @@ function defineFixer(sourceCode, node) { module.exports = { meta: { docs: { - description: "Disallow unnecessary spread operators.", + description: "disallow unnecessary spread operators.", category: "Best Practices", recommended: false, url: @@ -131,11 +131,11 @@ module.exports = { nodeType === "RestElement" && argumentType !== parentType const type1 = nodeType === "RestElement" ? "rest" : "spread" const type2 = - /*eslint-disable @mysticatea/prettier */ + /* eslint-disable @mysticatea/prettier -- start */ isRestParameter ? "parameter" : isArray ? "element" : /* otherwise */ "property" - /*eslint-enable @mysticatea/prettier */ + /* eslint-enable @mysticatea/prettier -- end */ context.report({ node, diff --git a/lib/rules/prefer-for-of.js b/lib/rules/prefer-for-of.js index 37ea4e6..504badc 100644 --- a/lib/rules/prefer-for-of.js +++ b/lib/rules/prefer-for-of.js @@ -107,7 +107,7 @@ function isCalledRecursively(context, node) { * @param {ASTNode} node - The `for` loop node to check. * @returns {boolean} `true` if the node is a simple array traversing. */ -//eslint-disable-next-line complexity +// eslint-disable-next-line complexity -- We know it's too complex for ESLint function isTraversingArray(node) { const init = node.init const test = node.test @@ -115,7 +115,7 @@ function isTraversingArray(node) { let indexDecl = null let lengthDecl = null - /*eslint-disable @mysticatea/prettier */ + /* eslint-disable @mysticatea/prettier -- start */ return ( init != null && init.type === "VariableDeclaration" && @@ -186,7 +186,7 @@ function isTraversingArray(node) { ) ) ) - /*eslint-enable @mysticatea/prettier */ + /* eslint-enable @mysticatea/prettier -- end */ } /** diff --git a/package.json b/package.json index 65aad32..7575aac 100644 --- a/package.json +++ b/package.json @@ -3,30 +3,31 @@ "version": "13.0.0", "description": "Additional ESLint rules.", "engines": { - "node": ">=8.10.0" + "node": "^10.12.0 || >=12.0.0" }, "main": "index.js", "files": [ "lib" ], "peerDependencies": { - "eslint": ">=6.6.0" + "eslint": "^7.0.0" }, "dependencies": { - "@typescript-eslint/eslint-plugin": "~2.6.1", - "@typescript-eslint/parser": "~2.6.1", - "eslint-plugin-eslint-comments": "~3.1.2", - "eslint-plugin-eslint-plugin": "~2.1.0", - "eslint-plugin-node": "~10.0.0", - "eslint-plugin-prettier": "~3.1.1", - "eslint-plugin-vue": "~6.0.0", - "prettier": "~1.19.1", - "vue-eslint-parser": "^7.0.0" + "@eslint/eslintrc": "^0.4.3", + "@typescript-eslint/eslint-plugin": "^4.29.2", + "@typescript-eslint/parser": "^4.29.2", + "eslint-plugin-eslint-comments": "^3.2.0", + "eslint-plugin-eslint-plugin": "^3.5.3", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^3.4.1", + "eslint-plugin-vue": "^7.16.0", + "prettier": "^1.19.1", + "vue-eslint-parser": "^7.10.0" }, "devDependencies": { "@mysticatea/eslint-plugin": "file:.", "codecov": "^3.6.1", - "eslint": "~6.6.0", + "eslint": "^7.32.0", "fs-extra": "^8.1.0", "globals": "^12.1.1", "mocha": "^6.2.2", @@ -34,7 +35,7 @@ "nyc": "^14.1.1", "opener": "^1.5.1", "rimraf": "^3.0.0", - "typescript": "~3.7.2" + "typescript": "^4.3.5" }, "scripts": { "clean": "rimraf .nyc_output coverage", diff --git a/tests/lib/configs/_rules.js b/tests/lib/configs/_rules.js index 170f2cb..bcfad29 100644 --- a/tests/lib/configs/_rules.js +++ b/tests/lib/configs/_rules.js @@ -7,9 +7,10 @@ const { Linter } = require("eslint") const { ConfigArrayFactory, -} = require("eslint/lib/cli-engine/config-array-factory") +} = require("@eslint/eslintrc/lib/config-array-factory") const Validator = require("eslint/lib/shared/config-validator") const { rules: PluginRulesIndex } = require("@mysticatea/eslint-plugin") +const { rules } = require("eslint/conf/replacements.json") const coreRules = new Linter().getRules() const pluginRules = new Map( @@ -25,9 +26,7 @@ const deprecatedRuleNames = new Set( .filter(([, rule]) => rule && rule.meta && rule.meta.deprecated) .map(([ruleId]) => ruleId) ) -const removedRuleNames = new Set( - Object.keys(require("eslint/conf/replacements.json").rules) -) +const removedRuleNames = new Set(Object.keys(rules)) const configFactory = new ConfigArrayFactory() @@ -110,10 +109,12 @@ module.exports = { }, getRulesOfConfig(config, name) { - const rules = {} - for (const [key, value] of this.iterateRulesOfConfig(config, name)) { - rules[key] = value - } - return rules + return this.iterateRulesOfConfig(config, name).reduce( + (configRules, [key, value]) => ({ + ...configRules, + [key]: value, + }), + {} + ) }, } diff --git a/tests/lib/configs/browser.js b/tests/lib/configs/browser.js index d37e11b..8920e03 100644 --- a/tests/lib/configs/browser.js +++ b/tests/lib/configs/browser.js @@ -5,11 +5,10 @@ */ "use strict" +const config = require("../../../lib/configs/+browser") const Rules = require("./_rules") describe("'+browser.js'", () => { - const config = require("../../../lib/configs/+browser") - it("should be a valid config.", () => { Rules.validateConfig(config, "+browser.js") }) diff --git a/tests/lib/configs/es2015.js b/tests/lib/configs/es2015.js index fe430b2..2564d5c 100644 --- a/tests/lib/configs/es2015.js +++ b/tests/lib/configs/es2015.js @@ -6,6 +6,7 @@ "use strict" const assert = require("assert") +const config = require("../../../lib/configs/es2015") const Rules = require("./_rules") /** @@ -22,7 +23,6 @@ function isES6Rule(ruleId) { } describe("'es2015.js'", () => { - const config = require("../../../lib/configs/es2015") const configuredRules = Rules.getRulesOfConfig(config, "es2015") const existingRules = Rules.getCoreRuleNames() diff --git a/tests/lib/configs/es2016.js b/tests/lib/configs/es2016.js index 77dc687..a0db951 100644 --- a/tests/lib/configs/es2016.js +++ b/tests/lib/configs/es2016.js @@ -5,11 +5,10 @@ */ "use strict" +const config = require("../../../lib/configs/es2016") const Rules = require("./_rules") describe("'es2016.js'", () => { - const config = require("../../../lib/configs/es2016") - it("should be a valid config.", () => { Rules.validateConfig(config, "es2016.js") }) diff --git a/tests/lib/configs/es2017.js b/tests/lib/configs/es2017.js index 5101b53..746a45a 100644 --- a/tests/lib/configs/es2017.js +++ b/tests/lib/configs/es2017.js @@ -5,11 +5,10 @@ */ "use strict" +const config = require("../../../lib/configs/es2017") const Rules = require("./_rules") describe("'es2017.js'", () => { - const config = require("../../../lib/configs/es2017") - it("should be a valid config.", () => { Rules.validateConfig(config, "es2017.js") }) diff --git a/tests/lib/configs/es2018.js b/tests/lib/configs/es2018.js index deccfd0..d7b1fca 100644 --- a/tests/lib/configs/es2018.js +++ b/tests/lib/configs/es2018.js @@ -5,11 +5,10 @@ */ "use strict" +const config = require("../../../lib/configs/es2018") const Rules = require("./_rules") describe("'es2018.js'", () => { - const config = require("../../../lib/configs/es2018") - it("should be a valid config.", () => { Rules.validateConfig(config, "es2018.js") }) diff --git a/tests/lib/configs/es2019.js b/tests/lib/configs/es2019.js index 31e1420..ff75bb6 100644 --- a/tests/lib/configs/es2019.js +++ b/tests/lib/configs/es2019.js @@ -4,11 +4,10 @@ */ "use strict" +const config = require("../../../lib/configs/es2019") const Rules = require("./_rules") describe("'es2019.js'", () => { - const config = require("../../../lib/configs/es2019") - it("should be a valid config.", () => { Rules.validateConfig(config, "es2019.js") }) diff --git a/tests/lib/configs/es2020.js b/tests/lib/configs/es2020.js index cb1611a..03ba982 100644 --- a/tests/lib/configs/es2020.js +++ b/tests/lib/configs/es2020.js @@ -4,11 +4,10 @@ */ "use strict" +const config = require("../../../lib/configs/es2020") const Rules = require("./_rules") describe("'es2020.js'", () => { - const config = require("../../../lib/configs/es2020") - it("should be a valid config.", () => { Rules.validateConfig(config, "es2020.js") }) diff --git a/tests/lib/configs/es5.js b/tests/lib/configs/es5.js index 63caafd..d3fd708 100644 --- a/tests/lib/configs/es5.js +++ b/tests/lib/configs/es5.js @@ -6,6 +6,7 @@ "use strict" const assert = require("assert") +const config = require("../../../lib/configs/es5") const Rules = require("./_rules") /** @@ -22,7 +23,6 @@ function isES6Rule(ruleId) { } describe("'es5.js'", () => { - const config = require("../../../lib/configs/es5") const configuredRules = Rules.getRulesOfConfig(config, "es5") const existingRules = [].concat( Rules.getCoreRuleNames(), diff --git a/tests/lib/configs/eslint-plugin.js b/tests/lib/configs/eslint-plugin.js index 7576c68..f285a90 100644 --- a/tests/lib/configs/eslint-plugin.js +++ b/tests/lib/configs/eslint-plugin.js @@ -6,10 +6,10 @@ "use strict" const assert = require("assert") +const config = require("../../../lib/configs/+eslint-plugin") const Rules = require("./_rules") describe("'+eslint-plugin.js'", () => { - const config = require("../../../lib/configs/+eslint-plugin") const configuredRules = Rules.getRulesOfConfig(config, "+eslint-plugin") const existingRules = Rules.getPluginRuleNames("eslint-plugin") diff --git a/tests/lib/configs/mocha.js b/tests/lib/configs/mocha.js index 8b12408..c994ac7 100644 --- a/tests/lib/configs/mocha.js +++ b/tests/lib/configs/mocha.js @@ -5,11 +5,10 @@ */ "use strict" +const config = require("../../../lib/configs/_override-mocha") const Rules = require("./_rules") describe("'mocha.js'", () => { - const config = require("../../../lib/configs/_override-mocha") - it("should be a valid config.", () => { Rules.validateConfig(config, "mocha.js") }) diff --git a/tests/lib/configs/modules.js b/tests/lib/configs/modules.js index 343f9fc..10c7d97 100644 --- a/tests/lib/configs/modules.js +++ b/tests/lib/configs/modules.js @@ -5,11 +5,10 @@ */ "use strict" +const config = require("../../../lib/configs/+modules") const Rules = require("./_rules") describe("'+modules.js'", () => { - const config = require("../../../lib/configs/+modules") - it("should be a valid config.", () => { Rules.validateConfig(config, "+modules.js") }) diff --git a/tests/lib/configs/node.js b/tests/lib/configs/node.js index 7077389..450154b 100644 --- a/tests/lib/configs/node.js +++ b/tests/lib/configs/node.js @@ -6,10 +6,10 @@ "use strict" const assert = require("assert") +const config = require("../../../lib/configs/+node") const Rules = require("./_rules") describe("'+node.js'", () => { - const config = require("../../../lib/configs/+node") const configuredRules = Rules.getRulesOfConfig(config, "+node") const existingRules = Rules.getPluginRuleNames("node") diff --git a/tests/lib/configs/special.js b/tests/lib/configs/special.js index c0de8de..2ff2f8c 100644 --- a/tests/lib/configs/special.js +++ b/tests/lib/configs/special.js @@ -5,11 +5,10 @@ */ "use strict" +const config = require("../../../lib/configs/_override-special") const Rules = require("./_rules") describe("'special.js'", () => { - const config = require("../../../lib/configs/_override-special") - it("should be a valid config.", () => { Rules.validateConfig(config, "special.js") }) diff --git a/tests/lib/configs/ts.js b/tests/lib/configs/ts.js index e671575..70a325d 100644 --- a/tests/lib/configs/ts.js +++ b/tests/lib/configs/ts.js @@ -6,10 +6,10 @@ "use strict" const assert = require("assert") +const config = require("../../../lib/configs/_override-ts") const Rules = require("./_rules") describe("'ts.js'", () => { - const config = require("../../../lib/configs/_override-ts") const configuredRules = Rules.getRulesOfConfig(config, "_override-ts") const existingRules = Rules.getPluginRuleNames("ts") diff --git a/tests/lib/configs/vue.js b/tests/lib/configs/vue.js index 83541fd..6c8f514 100644 --- a/tests/lib/configs/vue.js +++ b/tests/lib/configs/vue.js @@ -6,10 +6,10 @@ "use strict" const assert = require("assert") +const config = require("../../../lib/configs/_override-vue") const Rules = require("./_rules") describe("'vue.js'", () => { - const config = require("../../../lib/configs/_override-vue") const configuredRules = Rules.getRulesOfConfig(config, "_override-ts") const existingRules = Rules.getPluginRuleNames("vue")