chore(eslint): update shared presets and config exports
This commit is contained in:
@@ -50,6 +50,7 @@
|
|||||||
"@vitest/eslint-plugin": "^1.6.19",
|
"@vitest/eslint-plugin": "^1.6.19",
|
||||||
"eslint-plugin-import-x": "^4.16.2",
|
"eslint-plugin-import-x": "^4.16.2",
|
||||||
"eslint-plugin-n": "^18.0.1",
|
"eslint-plugin-n": "^18.0.1",
|
||||||
|
"eslint-plugin-regexp": "^3.1.0",
|
||||||
"eslint-plugin-unicorn": "^64.0.0",
|
"eslint-plugin-unicorn": "^64.0.0",
|
||||||
"eslint-plugin-vue": "^10.9.2",
|
"eslint-plugin-vue": "^10.9.2",
|
||||||
"globals": "^17.6.0",
|
"globals": "^17.6.0",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
export { compose } from './compose';
|
export { compose } from './compose';
|
||||||
|
|
||||||
/* Presets */
|
/* Presets */
|
||||||
export { base, ignores, typescript, vue, vitest, imports, node, stylistic } from './presets';
|
export { base, ignores, typescript, vue, vitest, imports, node, stylistic, regexp } from './presets';
|
||||||
|
|
||||||
/* Types */
|
/* Types */
|
||||||
export type {
|
export type {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type { FlatConfigArray } from '../types';
|
|||||||
import js from '@eslint/js';
|
import js from '@eslint/js';
|
||||||
import unicorn from 'eslint-plugin-unicorn';
|
import unicorn from 'eslint-plugin-unicorn';
|
||||||
import globals from 'globals';
|
import globals from 'globals';
|
||||||
|
import { regexp } from './regexp';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Globally ignored paths — build output, coverage, generated artifacts.
|
* Globally ignored paths — build output, coverage, generated artifacts.
|
||||||
@@ -61,41 +62,62 @@ export const base: FlatConfigArray = [
|
|||||||
'no-eval': 'error',
|
'no-eval': 'error',
|
||||||
'no-var': 'error',
|
'no-var': 'error',
|
||||||
'prefer-const': 'error',
|
'prefer-const': 'error',
|
||||||
'prefer-template': 'warn',
|
'prefer-template': 'error',
|
||||||
'no-useless-constructor': 'warn',
|
'no-useless-constructor': 'error',
|
||||||
'no-useless-rename': 'warn',
|
'no-useless-rename': 'error',
|
||||||
'no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
|
'no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
|
||||||
'no-self-compare': 'error',
|
'no-self-compare': 'error',
|
||||||
'no-template-curly-in-string': 'warn',
|
'no-template-curly-in-string': 'error',
|
||||||
'no-throw-literal': 'error',
|
'no-throw-literal': 'error',
|
||||||
'no-return-assign': 'warn',
|
'no-return-assign': 'error',
|
||||||
'no-else-return': 'warn',
|
'no-else-return': 'error',
|
||||||
'no-lonely-if': 'warn',
|
'no-lonely-if': 'error',
|
||||||
'no-unneeded-ternary': 'warn',
|
'no-unneeded-ternary': 'error',
|
||||||
'prefer-object-spread': 'warn',
|
'prefer-object-spread': 'error',
|
||||||
'prefer-exponentiation-operator': 'warn',
|
'prefer-exponentiation-operator': 'error',
|
||||||
'no-useless-computed-key': 'warn',
|
'no-useless-computed-key': 'error',
|
||||||
'no-useless-concat': 'warn',
|
'no-useless-concat': 'error',
|
||||||
|
'no-array-constructor': 'error',
|
||||||
|
'no-new-wrappers': 'error',
|
||||||
|
'no-useless-return': 'error',
|
||||||
|
'object-shorthand': ['error', 'always'],
|
||||||
|
'prefer-spread': 'error',
|
||||||
|
'prefer-rest-params': 'error',
|
||||||
|
'symbol-description': 'error',
|
||||||
curly: 'off',
|
curly: 'off',
|
||||||
|
|
||||||
/* ── unicorn ──────────────────────────────────────────── */
|
/* ── unicorn ──────────────────────────────────────────── */
|
||||||
'unicorn/prefer-node-protocol': 'error',
|
'unicorn/prefer-node-protocol': 'error',
|
||||||
'unicorn/no-instanceof-builtins': 'error',
|
'unicorn/no-instanceof-builtins': 'error',
|
||||||
'unicorn/no-new-array': 'error',
|
'unicorn/no-new-array': 'error',
|
||||||
'unicorn/prefer-array-flat-map': 'warn',
|
'unicorn/prefer-array-flat-map': 'error',
|
||||||
'unicorn/prefer-array-flat': 'warn',
|
'unicorn/prefer-array-flat': 'error',
|
||||||
'unicorn/prefer-includes': 'warn',
|
'unicorn/prefer-includes': 'error',
|
||||||
'unicorn/prefer-string-slice': 'warn',
|
'unicorn/prefer-string-slice': 'error',
|
||||||
'unicorn/prefer-string-starts-ends-with': 'warn',
|
'unicorn/prefer-string-starts-ends-with': 'error',
|
||||||
'unicorn/throw-new-error': 'error',
|
'unicorn/throw-new-error': 'error',
|
||||||
'unicorn/error-message': 'warn',
|
'unicorn/error-message': 'error',
|
||||||
'unicorn/no-useless-spread': 'warn',
|
'unicorn/no-useless-spread': 'error',
|
||||||
'unicorn/no-useless-undefined': 'off',
|
'unicorn/no-useless-undefined': 'off',
|
||||||
'unicorn/prefer-optional-catch-binding': 'warn',
|
'unicorn/prefer-optional-catch-binding': 'error',
|
||||||
'unicorn/prefer-type-error': 'warn',
|
'unicorn/prefer-type-error': 'error',
|
||||||
'unicorn/no-thenable': 'error',
|
'unicorn/no-thenable': 'error',
|
||||||
'unicorn/prefer-number-properties': 'warn',
|
'unicorn/prefer-number-properties': 'error',
|
||||||
'unicorn/prefer-global-this': 'warn',
|
'unicorn/prefer-global-this': 'error',
|
||||||
|
'unicorn/prefer-array-some': 'error',
|
||||||
|
'unicorn/prefer-array-find': 'error',
|
||||||
|
'unicorn/prefer-array-index-of': 'error',
|
||||||
|
'unicorn/prefer-date-now': 'error',
|
||||||
|
'unicorn/prefer-modern-math-apis': 'error',
|
||||||
|
'unicorn/prefer-negative-index': 'error',
|
||||||
|
'unicorn/prefer-set-has': 'error',
|
||||||
|
'unicorn/prefer-string-trim-start-end': 'error',
|
||||||
|
'unicorn/prefer-regexp-test': 'error',
|
||||||
|
'unicorn/prefer-string-replace-all': 'error',
|
||||||
|
'unicorn/no-typeof-undefined': 'error',
|
||||||
|
'unicorn/no-array-push-push': 'error',
|
||||||
|
'unicorn/no-useless-promise-resolve-reject': 'error',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
...regexp,
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -25,17 +25,19 @@ export const imports: FlatConfigArray = [
|
|||||||
rules: {
|
rules: {
|
||||||
'import-x/no-duplicates': 'error',
|
'import-x/no-duplicates': 'error',
|
||||||
'import-x/no-self-import': 'error',
|
'import-x/no-self-import': 'error',
|
||||||
'import-x/no-cycle': 'warn',
|
'import-x/no-cycle': 'error',
|
||||||
'import-x/first': 'warn',
|
'import-x/first': 'error',
|
||||||
'import-x/no-mutable-exports': 'error',
|
'import-x/no-mutable-exports': 'error',
|
||||||
'import-x/no-amd': 'error',
|
'import-x/no-amd': 'error',
|
||||||
'import-x/no-commonjs': 'warn',
|
'import-x/no-commonjs': 'error',
|
||||||
'import-x/no-empty-named-blocks': 'warn',
|
'import-x/no-empty-named-blocks': 'error',
|
||||||
'import-x/consistent-type-specifier-style': ['warn', 'prefer-top-level'],
|
'import-x/no-useless-path-segments': ['error', { noUselessIndex: false }],
|
||||||
|
'import-x/consistent-type-specifier-style': ['error', 'prefer-top-level'],
|
||||||
|
|
||||||
/* Only enforce member order within `{ … }`; declaration order is sorted
|
/* Only enforce member order within `{ … }`; declaration order is sorted
|
||||||
by source path across the codebase, which core `sort-imports` (orders
|
by source path across the codebase, which core `sort-imports` (orders
|
||||||
by first member name) would otherwise fight. */
|
by first member name) would otherwise fight. Kept at `warn` — it is not
|
||||||
|
autofixable and member order is a soft preference. */
|
||||||
'sort-imports': ['warn', { ignoreDeclarationSort: true }],
|
'sort-imports': ['warn', { ignoreDeclarationSort: true }],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,4 +4,5 @@ export { vue } from './vue';
|
|||||||
export { vitest } from './vitest';
|
export { vitest } from './vitest';
|
||||||
export { imports } from './imports';
|
export { imports } from './imports';
|
||||||
export { node } from './node';
|
export { node } from './node';
|
||||||
|
export { regexp } from './regexp';
|
||||||
export { stylistic } from './stylistic';
|
export { stylistic } from './stylistic';
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import type { FlatConfigArray } from '../types';
|
||||||
|
import regexpPlugin from 'eslint-plugin-regexp';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regular-expression correctness & optimization rules via
|
||||||
|
* [`eslint-plugin-regexp`](https://ota-meshi.github.io/eslint-plugin-regexp/).
|
||||||
|
*
|
||||||
|
* Applies the plugin's flat `recommended` ruleset — catches buggy/ambiguous
|
||||||
|
* patterns (control characters, useless quantifiers, ReDoS-prone constructs)
|
||||||
|
* and pushes toward clearer, faster expressions. Included in {@link base} so it
|
||||||
|
* applies to every package.
|
||||||
|
*/
|
||||||
|
export const regexp: FlatConfigArray = [
|
||||||
|
{
|
||||||
|
...regexpPlugin.configs['flat/recommended'],
|
||||||
|
name: 'robonen/regexp',
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -12,7 +12,7 @@ import stylisticPlugin from '@stylistic/eslint-plugin';
|
|||||||
* - commaDangle: always-multiline
|
* - commaDangle: always-multiline
|
||||||
* - arrowParens: as-needed
|
* - arrowParens: as-needed
|
||||||
* - blockSpacing: true
|
* - blockSpacing: true
|
||||||
* - quoteProps: consistent-as-needed
|
* - quoteProps: as-needed
|
||||||
* - jsx: true
|
* - jsx: true
|
||||||
*
|
*
|
||||||
* @see https://eslint.style/guide/config-presets
|
* @see https://eslint.style/guide/config-presets
|
||||||
|
|||||||
@@ -4,15 +4,22 @@ import tseslint from 'typescript-eslint';
|
|||||||
/**
|
/**
|
||||||
* TypeScript-specific configuration.
|
* TypeScript-specific configuration.
|
||||||
*
|
*
|
||||||
* Pulls in `typescript-eslint`'s recommended (non type-checked) setup — which
|
* Adopts `typescript-eslint`'s **strict** (non type-checked) ruleset plus the
|
||||||
* registers the parser/plugin and disables core rules superseded by their
|
* **stylistic** ruleset — registering the parser/plugin, disabling core rules
|
||||||
* TypeScript-aware counterparts — then layers opinionated rules on top.
|
* superseded by TS-aware counterparts, and enforcing the full strict + stylistic
|
||||||
|
* sets at `error`. A small overlay re-tunes a few rules for this monorepo.
|
||||||
|
*
|
||||||
|
* Two deliberate carve-outs: `no-explicit-any` is kept at `warn` (the low-level
|
||||||
|
* stdlib/toolkit does a lot of type-boundary work where `any` is idiomatic), and
|
||||||
|
* `no-non-null-assertion` is `off` (the `!` operator is how the codebase satisfies
|
||||||
|
* `noUncheckedIndexedAccess` on provably-bounded indexed access).
|
||||||
*
|
*
|
||||||
* `.vue` files are included so the rules apply inside `<script lang="ts">`
|
* `.vue` files are included so the rules apply inside `<script lang="ts">`
|
||||||
* blocks; the `vue` preset assigns the matching parser for them.
|
* blocks; the `vue` preset assigns the matching parser for them.
|
||||||
*/
|
*/
|
||||||
export const typescript: FlatConfigArray = [
|
export const typescript: FlatConfigArray = [
|
||||||
...tseslint.configs.recommended,
|
...tseslint.configs.strict,
|
||||||
|
...tseslint.configs.stylistic,
|
||||||
{
|
{
|
||||||
name: 'robonen/typescript',
|
name: 'robonen/typescript',
|
||||||
files: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts', '**/*.vue'],
|
files: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts', '**/*.vue'],
|
||||||
@@ -25,27 +32,33 @@ export const typescript: FlatConfigArray = [
|
|||||||
false positives (e.g. globals, auto-imports, compiler macros). */
|
false positives (e.g. globals, auto-imports, compiler macros). */
|
||||||
'no-undef': 'off',
|
'no-undef': 'off',
|
||||||
|
|
||||||
'@typescript-eslint/consistent-type-imports': 'error',
|
/* Deliberate carve-outs from `strict` (see file header). */
|
||||||
'@typescript-eslint/no-explicit-any': 'off',
|
'@typescript-eslint/no-explicit-any': 'warn',
|
||||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||||
'@typescript-eslint/prefer-as-const': 'error',
|
/* noop/default callbacks (`() => {}`) are an intentional, pervasive pattern. */
|
||||||
'@typescript-eslint/no-empty-object-type': ['warn', { allowInterfaces: 'with-single-extends' }],
|
'@typescript-eslint/no-empty-function': 'off',
|
||||||
'@typescript-eslint/no-wrapper-object-types': 'error',
|
/* The libraries expose deliberate overload signatures (better inference/DX
|
||||||
'@typescript-eslint/no-duplicate-enum-values': 'error',
|
than a single union signature) — don't force-merge them. */
|
||||||
'@typescript-eslint/no-unsafe-declaration-merging': 'error',
|
'@typescript-eslint/unified-signatures': 'off',
|
||||||
|
/* Plain objects are used as keyed dictionaries (e.g. forms errors/touched
|
||||||
|
maps) where dynamic `delete` is legitimate. */
|
||||||
|
'@typescript-eslint/no-dynamic-delete': 'off',
|
||||||
|
/* Index-based `for` loops are sometimes a deliberate perf choice; this rule
|
||||||
|
is not autofixable and converting can subtly change semantics. */
|
||||||
|
'@typescript-eslint/prefer-for-of': 'off',
|
||||||
|
/* Idiomatic callback return unions (`() => void | false`, `() => void |
|
||||||
|
Promise<T>`) are pervasive in composables; the rule is hostile to them. */
|
||||||
|
'@typescript-eslint/no-invalid-void-type': 'off',
|
||||||
|
|
||||||
|
/* Allow our type-helper interfaces that extend a single mapped type. */
|
||||||
|
'@typescript-eslint/no-empty-object-type': ['error', { allowInterfaces: 'with-single-extends' }],
|
||||||
|
|
||||||
|
/* House preferences (override the strict/stylistic defaults' options). */
|
||||||
|
'@typescript-eslint/consistent-type-imports': 'error',
|
||||||
|
'@typescript-eslint/consistent-type-definitions': ['error', 'interface'],
|
||||||
|
'@typescript-eslint/array-type': ['error', { default: 'array-simple' }],
|
||||||
'@typescript-eslint/no-import-type-side-effects': 'error',
|
'@typescript-eslint/no-import-type-side-effects': 'error',
|
||||||
'@typescript-eslint/no-useless-empty-export': 'warn',
|
'@typescript-eslint/no-useless-empty-export': 'error',
|
||||||
'@typescript-eslint/no-inferrable-types': 'warn',
|
|
||||||
'@typescript-eslint/prefer-function-type': 'warn',
|
|
||||||
'@typescript-eslint/ban-tslint-comment': 'error',
|
|
||||||
'@typescript-eslint/consistent-type-definitions': ['warn', 'interface'],
|
|
||||||
'@typescript-eslint/prefer-for-of': 'warn',
|
|
||||||
'@typescript-eslint/no-unnecessary-type-constraint': 'warn',
|
|
||||||
'@typescript-eslint/adjacent-overload-signatures': 'warn',
|
|
||||||
'@typescript-eslint/array-type': ['warn', { default: 'array-simple' }],
|
|
||||||
'@typescript-eslint/no-this-alias': 'error',
|
|
||||||
'@typescript-eslint/triple-slash-reference': 'error',
|
|
||||||
'@typescript-eslint/no-namespace': 'error',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ import vitestPlugin from '@vitest/eslint-plugin';
|
|||||||
/**
|
/**
|
||||||
* Vitest configuration for test files.
|
* Vitest configuration for test files.
|
||||||
*
|
*
|
||||||
* Scoped to common test file patterns; also relaxes a few strict rules that
|
* Scoped to common test file patterns. Adopts the plugin's full `recommended`
|
||||||
* are noisy in tests.
|
* ruleset, layers extra preference rules at `error`, and relaxes a few strict
|
||||||
|
* rules that are noisy in tests.
|
||||||
*/
|
*/
|
||||||
export const vitest: FlatConfigArray = [
|
export const vitest: FlatConfigArray = [
|
||||||
{
|
{
|
||||||
@@ -20,19 +21,29 @@ export const vitest: FlatConfigArray = [
|
|||||||
vitest: vitestPlugin,
|
vitest: vitestPlugin,
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
'vitest/no-conditional-tests': 'warn',
|
...vitestPlugin.configs.recommended.rules,
|
||||||
|
|
||||||
|
/* House convention: `describe(useX, …)` / `it(fn, …)` pass a FUNCTION as the
|
||||||
|
title (nicer reporter output) — valid-title only accepts strings. */
|
||||||
|
'vitest/valid-title': 'off',
|
||||||
|
/* Niche stylistic preference; the explicit two-assertion form is clearer. */
|
||||||
|
'vitest/prefer-called-exactly-once-with': 'off',
|
||||||
|
|
||||||
'vitest/no-import-node-test': 'error',
|
'vitest/no-import-node-test': 'error',
|
||||||
'vitest/prefer-to-be-truthy': 'warn',
|
'vitest/no-conditional-tests': 'error',
|
||||||
'vitest/prefer-to-be-falsy': 'warn',
|
'vitest/prefer-to-be-truthy': 'error',
|
||||||
'vitest/prefer-to-be-object': 'warn',
|
'vitest/prefer-to-be-falsy': 'error',
|
||||||
'vitest/prefer-to-have-length': 'warn',
|
'vitest/prefer-to-be-object': 'error',
|
||||||
'vitest/consistent-test-filename': 'warn',
|
'vitest/prefer-to-have-length': 'error',
|
||||||
'vitest/prefer-describe-function-title': 'warn',
|
'vitest/consistent-test-filename': 'error',
|
||||||
|
'vitest/prefer-describe-function-title': 'error',
|
||||||
|
|
||||||
/* relax strict rules in tests */
|
/* relax strict rules in tests */
|
||||||
'no-unused-vars': 'off',
|
'no-unused-vars': 'off',
|
||||||
'@typescript-eslint/no-unused-vars': 'off',
|
'@typescript-eslint/no-unused-vars': 'off',
|
||||||
'@typescript-eslint/no-explicit-any': 'off',
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
|
/* Empty mock/fixture classes (e.g. stubbing `class DeviceOrientationEvent {}`). */
|
||||||
|
'@typescript-eslint/no-extraneous-class': 'off',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,16 +1,28 @@
|
|||||||
import type { FlatConfigArray } from '../types';
|
import type { FlatConfigArray, Rules } from '../types';
|
||||||
import pluginVue from 'eslint-plugin-vue';
|
import pluginVue from 'eslint-plugin-vue';
|
||||||
import tseslint from 'typescript-eslint';
|
import tseslint from 'typescript-eslint';
|
||||||
import vueParser from 'vue-eslint-parser';
|
import vueParser from 'vue-eslint-parser';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge the rule maps from every config object in an eslint-plugin-vue flat
|
||||||
|
* preset (they ship as arrays) into a single rules record.
|
||||||
|
*/
|
||||||
|
function collectRules(configs: Array<{ rules?: unknown }>): Rules {
|
||||||
|
return configs.reduce<Rules>((rules, config) => ({ ...rules, ...(config.rules as Rules | undefined) }), {});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Priority-A "Essential" (error-prevention) ruleset from eslint-plugin-vue.
|
||||||
|
*/
|
||||||
|
const essentialRules = collectRules(pluginVue.configs['flat/essential'] as Array<{ rules?: unknown }>);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vue.js configuration.
|
* Vue.js configuration.
|
||||||
*
|
*
|
||||||
* Registers `eslint-plugin-vue` with `vue-eslint-parser` (delegating
|
* Registers `eslint-plugin-vue` with `vue-eslint-parser` (delegating
|
||||||
* `<script lang="ts">` to the TypeScript parser) and enables an opinionated
|
* `<script lang="ts">` to the TypeScript parser), adopts the plugin's full
|
||||||
* subset that enforces Composition API with `<script setup>` and type-based
|
* **Essential** (Priority-A) ruleset, and layers opinionated rules that enforce
|
||||||
* declarations. Only the listed rules are turned on — the plugin's large
|
* the Composition API with `<script setup>` and type-based declarations.
|
||||||
* `recommended` set is intentionally not pulled in.
|
|
||||||
*/
|
*/
|
||||||
export const vue: FlatConfigArray = [
|
export const vue: FlatConfigArray = [
|
||||||
{
|
{
|
||||||
@@ -34,19 +46,19 @@ export const vue: FlatConfigArray = [
|
|||||||
name: 'robonen/vue/rules',
|
name: 'robonen/vue/rules',
|
||||||
files: ['**/*.vue'],
|
files: ['**/*.vue'],
|
||||||
rules: {
|
rules: {
|
||||||
'vue/no-arrow-functions-in-watch': 'error',
|
...essentialRules,
|
||||||
'vue/no-deprecated-destroyed-lifecycle': 'error',
|
|
||||||
'vue/no-export-in-script-setup': 'error',
|
/* Component library: single-word component names (Primitive, Slot, …) are intentional. */
|
||||||
'vue/no-lifecycle-after-await': 'error',
|
'vue/multi-word-component-names': 'off',
|
||||||
|
|
||||||
|
/* House additions / stricter opinions on top of Essential. */
|
||||||
'vue/no-multiple-slot-args': 'error',
|
'vue/no-multiple-slot-args': 'error',
|
||||||
'vue/no-import-compiler-macros': 'error',
|
'vue/no-import-compiler-macros': 'error',
|
||||||
'vue/define-emits-declaration': ['error', 'type-based'],
|
'vue/define-emits-declaration': ['error', 'type-based'],
|
||||||
'vue/define-props-declaration': ['error', 'type-based'],
|
'vue/define-props-declaration': ['error', 'type-based'],
|
||||||
'vue/prefer-import-from-vue': 'error',
|
'vue/prefer-import-from-vue': 'error',
|
||||||
'vue/no-required-prop-with-default': 'warn',
|
'vue/no-required-prop-with-default': 'error',
|
||||||
'vue/valid-define-emits': 'error',
|
'vue/require-typed-ref': 'error',
|
||||||
'vue/valid-define-props': 'error',
|
|
||||||
'vue/require-typed-ref': 'warn',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user