Skip to content

How to extend eslint-config-vuetify? #31

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
darkbasic opened this issue Apr 17, 2025 · 10 comments
Open

How to extend eslint-config-vuetify? #31

darkbasic opened this issue Apr 17, 2025 · 10 comments

Comments

@darkbasic
Copy link

I want to use an external config like eslint-config-love in addition to vuetifyjs/create's . Previously the following was enough (even though I had some issues):

import eslintConfigLove from 'eslint-config-love'
import eslintPluginVue from 'eslint-plugin-vue'
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
import {
  configureVueProject,
  defineConfigWithVueTs,
  vueTsConfigs
} from '@vue/eslint-config-typescript'

configureVueProject({ scriptLangs: ['ts', 'tsx'] })
const { languageOptions, ...love } = eslintConfigLove

export default defineConfigWithVueTs(
  {
    name: 'app/files-to-lint',
    files: ['src/**/*.{ts,mts,tsx,vue,js,jsx}']
  },

  {
    name: 'app/files-to-ignore',
    ignores: ['**/dist/**', '**/dist-ssr/**', '**/coverage/**']
  },

  ...eslintPluginVue.configs['flat/recommended'],
  eslintPluginPrettierRecommended,
  vueTsConfigs.recommendedTypeChecked,
  love,

  {
    rules: {
      // Custom rules
    }
  }
)

Now with the use of eslint-config-vuetify what's the best way to extend it?

It looks like only the output of defineConfigWithVueTs is being exported and not the single pieces used as its arguments.

@AndreyYolkin
Copy link
Contributor

AndreyYolkin commented Apr 17, 2025

eslint-config-vuetify is a flat config, so I suppose something like

import vuetify from 'eslint-config-vuetify/index.ts.mjs'
import eslintConfigLove from 'eslint-config-love'
import eslintPluginVue from 'eslint-plugin-vue'
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
import {
  configureVueProject,
} from '@vue/eslint-config-typescript'

configureVueProject({ scriptLangs: ['ts', 'tsx'] })
const { languageOptions, ...love } = eslintConfigLove

export default [
  ...vuetify,
  eslintPluginPrettierRecommended,
  vueTsConfigs.recommendedTypeChecked,
  love,
  {
    rules: {
      // Custom rules
    }
  }
]

should work. You can remove eslintPluginVue.configs['flat/recommended'], as it's already included in the vuetify

@darkbasic
Copy link
Author

darkbasic commented Apr 18, 2025

It doesn't work unless I wrap everything into defineConfigWithVueTs() once again.

I have a couple of questions:

  1. What exactly does defineConfigWithVueTs() is being needed for? eslint-config-vuetify already wraps its config with it, is it a problem if re-wrap the final config again? I have to otherwise it doesn't work (TypeError: Unexpected array.).
  2. vueTsConfigs.recommended is already being imported by eslint-config-vuetify: is it I problem if I additionally import vueTsConfigs.recommendedTypeChecked alongside with it?
  3. What's the difference between eslint-config-vuetify/index.ts.mjs and eslint-config-vuetify/index.js.mjs? Which one is being used if I import eslint-config-vuetify?

eslint-config-vuetify/index.ts.mjs:

import config from './index.js.mjs'
import {
  defineConfigWithVueTs,
  vueTsConfigs,
} from '@vue/eslint-config-typescript'

export default defineConfigWithVueTs([
  vueTsConfigs.recommended,
  ...config,
  {
    // False positive for variables in type declarations
    rules: {
      'no-unused-vars': 'off',
    },
  },
])

eslint-config-vuetify/index.js.mjs:

import pluginVue from 'eslint-plugin-vue'
import globals from 'globals'
import eslint from '@eslint/js'
import stylistic from '@stylistic/eslint-plugin'
import { defu } from 'defu'
import { loadAutoImports } from './utils/autoimports.mjs'
import { globalIgnores } from 'eslint/config'

const autoImports = loadAutoImports()

export default [
  globalIgnores(['dist/**'], 'ignore dist folder'),
  eslint.configs.recommended,
  ...pluginVue.configs['flat/recommended'],
  {
    name: 'app/files-to-lint',
    files: ['**/*.{js,mjs,jsx,ts,mts,tsx,vue}'],
    plugins: {
      '@stylistic': stylistic,
    },
    languageOptions: defu(autoImports, {
      globals: {
        ...globals.node,
        ...globals.browser,
      },
    }),
    rules: {[...]},
  },

  {
    name: 'app/overrides',
    files: ['**/*.vue'],
    rules: {[...]},
  },
]
  • index.ts.mjs is wrapped by defineConfigWithVueTs() while eslint-config-vuetify/index.js.mjs isn't.
  • index.ts.mjs imports vueTsConfigs.recommended while eslint-config-vuetify/index.js.mjs doesn't.
  • index.ts.mjs disables 'no-unused-vars' while eslint-config-vuetify/index.js.mjs doesn't.

Ideally I would love to be able to import eslint-config-vuetify/index.js.mjs and use the .find() method on its array to pick name: 'app/files-to-lint' and name: 'app/overrides' (and maybe whatever globalIgnores() produces). The rest I could easily re-add it myself. Unfortunately I have no idea which file eslint-config-vuetify imports (index.ts.mjs or index.js.mjs) and I'm not even sure if I can import these files separately via import vuetify from 'eslint-config-vuetify/index.ts.mjs' or import vuetify from 'eslint-config-vuetify/index.js.mjs' (it doesn't seem to make a different whichever of the two I pick).

@darkbasic
Copy link
Author

darkbasic commented Apr 18, 2025

I ended up doing something like this:

import eslintConfigLove from 'eslint-config-love'
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
import {
  configureVueProject,
  defineConfigWithVueTs,
  vueTsConfigs
} from '@vue/eslint-config-typescript'
import eslint from '@eslint/js'
import pluginVue from 'eslint-plugin-vue'
import vuetify from 'eslint-config-vuetify/index.js.mjs'

const vuetifyFilesToLint = vuetify.find((el) => el.name === 'app/files-to-lint')
if (vuetifyFilesToLint == null) throw new Error('Cannot find app/files-to-lint')

const vuetifyOverrides = vuetify.find((el) => el.name === 'app/overrides')
if (vuetifyFilesToLint == null) throw new Error('Cannot find app/overrides')

configureVueProject({ scriptLangs: ['ts', 'tsx'] })
const { languageOptions, ...love } = eslintConfigLove

export default defineConfigWithVueTs(
  {
    name: 'app/files-to-ignore',
    ignores: [
      '**/dist/**',
      '**/dist-ssr/**',
      '**/coverage/**',
      'src/openapi',
      'src/auto-imports.d.ts',
      'src/components.d.ts',
      'src/typed-router.d.ts',
      'src/vite-env.d.ts'
    ]
  },

  // vuetify
  eslint.configs.recommended,
  // Even if in eslint-config-vuetify is beind added first it should go after eslint.configs.recommended or you get all kind of weird errors
  vueTsConfigs.recommendedTypeChecked,
  ...pluginVue.configs['flat/recommended'],
  vuetifyFilesToLint,
  vuetifyOverrides,

  eslintPluginPrettierRecommended,
  love,

  {
    rules: {[...]}
  }
)

My other questions remain valid though.

@AndreyYolkin
Copy link
Contributor

  1. This is special wrap provided by vue in order to change something for their usage, since you are importing vueTsConfigs.recommendedTypeChecked, you prob need to make it wrapper again,
  2. Yes, vueTsConfigs.recommendedTypeChecked has additional rules, but good catch overall, the next version of config will provide an option to select needed config

@AndreyYolkin
Copy link
Contributor

AndreyYolkin commented Apr 25, 2025

As eslint-config-vuetify 4 is now in RC, this code should work (still need to configure ):

import vuetify from 'eslint-config-vuetify';
import love from 'eslint-config-love'
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'

export default vuetify({
  imports: false, // disable imports plugin as `love` comes with different plugin
  ts: {
    preset: 'recommendedTypeChecked'
  }
},
love,
eslintPluginPrettierRecommended,
)

@AndreyYolkin AndreyYolkin transferred this issue from vuetifyjs/create May 6, 2025
@darkbasic
Copy link
Author

@AndreyYolkin thanks! Unfortunately I'm getting the following error while importing the config now:

Image

Any idea why?

@AndreyYolkin
Copy link
Contributor

Currently no, I didn't face it before. Could you extract a minimal repro?

@GitHubMyHub
Copy link

GitHubMyHub commented May 13, 2025

@AndreyYolkin thanks! Unfortunately I'm getting the following error while importing the config now:

Image

Any idea why?

I could not experience that either.
But how do I apply thoose rules in my eslint.config.ts file? I need specific typescript rules see code below.

import { globalIgnores } from 'eslint/config'
import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript'
import pluginVue from 'eslint-plugin-vue'
import pluginVitest from '@vitest/eslint-plugin'
import pluginPlaywright from 'eslint-plugin-playwright'
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
// import pluginVuetify from 'eslint-plugin-vuetify'
import pluginVuetify from 'eslint-config-vuetify'

export default defineConfigWithVueTs(
  {
    name: 'app/files-to-lint',
    files: ['**/*.{ts,mts,tsx,vue}'],
  },

  globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']),

  pluginVue.configs['flat/recommended'],
  vueTsConfigs.recommendedTypeChecked,
  {
    rules: {
      '@typescript-eslint/array-type': ['error', { default: 'generic' }],
      '@typescript-eslint/consistent-type-imports': 'error',
      '@typescript-eslint/no-empty-function': 'error',
      '@typescript-eslint/no-invalid-this': 'error',
      '@typescript-eslint/no-non-null-assertion': 'error',
      '@typescript-eslint/no-shadow': 'error',
      '@typescript-eslint/no-unused-vars': 'error',
    },
  },

  // pluginVuetify.configs['flat/recommended'],

  // pluginVuetify.configs['flat/base'],
  // {
  //   rules: {
  //     'vue/block-lang': [
  //       'error',
  //       {
  //         script: {
  //           lang: 'ts',
  //         },
  //       },
  //     ],
  //     // 'vue/order-in-components': [
  //     //   'error',
  //     //   {
  //     //     order: [
  //     //       'DEFINITION',
  //     //       'LIST_RENDERING',
  //     //       'CONDITIONALS',
  //     //       'RENDER_MODIFIERS',
  //     //       'GLOBAL',
  //     //       ['UNIQUE', 'SLOT'],
  //     //       'TWO_WAY_BINDING',
  //     //       'OTHER_DIRECTIVES',
  //     //       'ATTR_DYNAMIC',
  //     //       'ATTR_STATIC',
  //     //       'ATTR_SHORTHAND_BOOL',
  //     //       'EVENTS',
  //     //       'CONTENT',
  //     //     ],
  //     //     alphabetical: true,
  //     //   },
  //     // ],
  //   },
  // },

  {
    ...pluginVitest.configs.recommended,
    files: ['src/**/__tests__/*'],
  },

  {
    ...pluginPlaywright.configs['flat/recommended'],
    files: ['e2e/**/*.{test,spec}.{js,ts,jsx,tsx}'],
  },
  eslintPluginPrettierRecommended,
  skipFormatting,
)

There are also few rules missing: 'vue/block-lang' and 'vue/order-in-components' which are present in the 'eslint-plugin-vuetify' plugin.

@AndreyYolkin
Copy link
Contributor

I think it should be like that (vitest, globalIgnores with .gitignore support, vue are already included)

import pluginPlaywright from 'eslint-plugin-playwright'
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
import vuetify from 'eslint-config-vuetify'

export default vuetify({
    ts: { preset: 'recommendedTypeChecked' },
    stylistic: false,
  },
  {
    rules: {
      '@typescript-eslint/array-type': ['error', { default: 'generic' }],
      '@typescript-eslint/consistent-type-imports': 'error',
      '@typescript-eslint/no-empty-function': 'error',
      '@typescript-eslint/no-invalid-this': 'error',
      '@typescript-eslint/no-non-null-assertion': 'error',
      '@typescript-eslint/no-shadow': 'error',
      '@typescript-eslint/no-unused-vars': 'error',
      'vue/order-in-components': [...],
    },
  },

  {
    ...pluginPlaywright.configs['flat/recommended'],
    files: ['e2e/**/*.{test,spec}.{js,ts,jsx,tsx}'],
  },
  eslintPluginPrettierRecommended,
  skipFormatting,
)

@GitHubMyHub
Copy link

I tried that also but the typescript rules dont have any effect.

See empty function or meals (MealValues[] instead of Array.
Image

I got this error in intellij:
Image

Is there a pssability to just use the eslint flat config instead? It would be great instead of using the vuetify wrapper.

Thank you for your help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants