123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- import skipFormatting from '@vue/eslint-config-prettier/skip-formatting';
- import vueTsEslintConfig from '@vue/eslint-config-typescript';
- import unocss from '@unocss/eslint-config/flat';
- import eslint from '@eslint/js';
- import pluginVitest from '@vitest/eslint-plugin';
- import pluginCypress from 'eslint-plugin-cypress/flat';
- import pluginImport from 'eslint-plugin-import';
- import pluginJsonc from 'eslint-plugin-jsonc';
- import pluginSimpleImportSort from 'eslint-plugin-simple-import-sort';
- import pluginVue from 'eslint-plugin-vue';
- import globals from 'globals';
- import jsoncParser from 'jsonc-eslint-parser';
- import tseslint from 'typescript-eslint';
- export default tseslint.config(
- {
- name: 'app/files-to-lint',
- files: ['**/*.{ts,mts,tsx,vue}'],
- },
- {
- name: 'app/files-to-ignore',
- ignores: ['**/dist/**', '**/dist-ssr/**', '**/coverage/**', '**/*.json', '!src/i18n/locales/*.json'],
- },
- {
- languageOptions: {
- globals: {
- ...globals.browser,
- ...globals.commonjs,
- ...globals.node,
- },
- },
- },
- eslint.configs.recommended,
- ...pluginJsonc.configs['flat/recommended-with-json'],
- ...pluginJsonc.configs['flat/prettier'],
- ...pluginVue.configs['flat/essential'],
- ...vueTsEslintConfig(),
- skipFormatting,
- unocss,
- {
- ...pluginVitest.configs.recommended,
- files: ['src/**/__tests__/*'],
- },
- {
- ...pluginCypress.configs.recommended,
- files: ['cypress/e2e/**/*.{cy,spec}.{js,ts,jsx,tsx}', 'cypress/support/**/*.{js,ts,jsx,tsx}'],
- },
- // import rules
- {
- files: ['**/*.{js,mjs,cjs,jsx,ts,tsx,vue}'],
- extends: [pluginImport.flatConfigs.recommended, pluginImport.flatConfigs.typescript],
- languageOptions: {
- ecmaVersion: 'latest',
- sourceType: 'module',
- },
- rules: {
- 'import/no-deprecated': 'error',
- 'import/no-empty-named-blocks': 'error',
- 'import/no-mutable-exports': 'error',
- 'import/no-named-as-default': 'error',
- 'import/no-named-as-default-member': 'error',
- 'import/no-absolute-path': 'error',
- 'import/no-dynamic-require': 'error',
- 'import/no-self-import': 'error',
- 'import/no-unresolved': 'off',
- 'import/no-useless-path-segments': [
- 'error',
- {
- noUselessIndex: true,
- },
- ],
- 'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
- 'import/exports-last': 'error',
- 'import/first': 'error',
- 'import/newline-after-import': [
- 'error',
- {
- count: 1,
- considerComments: true,
- },
- ],
- 'import/no-anonymous-default-export': 'error',
- 'import/no-duplicates': 'error',
- 'import/no-named-default': 'error',
- 'import/no-unassigned-import': [
- 'error',
- {
- allow: ['**/*.{css,scss}', '**/styles', 'dayjs/locale/*'],
- },
- ],
- },
- },
- // sort rules
- {
- plugins: {
- 'simple-import-sort': pluginSimpleImportSort,
- },
- rules: {
- 'simple-import-sort/imports': [
- 'error',
- {
- groups: [
- // Packages. `vue` related packages come first.
- ['^vue', '^@vue', 'pinia', '^vite$', '^@vitejs', '^vite-plugin', '^unocss$', '^@unocss', '^@?\\w'],
- // Node.js builtins.
- ['^node:'],
- // Internal packages.
- [
- '^@/layout(/.*|$)',
- '^@/views(/.*|$)',
- '^@/components(/.*|$)',
- '^@/transitions(/.*|$)',
- '^@/hooks(/.*|$)',
- '^@/directives(/.*|$)',
- '^@/stores(/.*|$)',
- '^@/router(/.*|$)',
- '^@/i18n(/.*|$)',
- '^@/api(/.*|$)',
- '^@/utils(/.*|$)',
- '^@/constants(/.*|$)',
- '^@/styles(/.*|$)',
- ],
- // Assets
- ['^@/assets(/.*|$)'],
- // Parent imports. Put `..` last.
- ['^\\.\\.(?!/?$)', '^\\.\\./?$'],
- // Other relative imports. Put same-folder imports and `.` last.
- ['^\\./(?=.*/)(?!/?$)', '^\\.(?!/?$)', '^\\./?$'],
- // Type imports
- [
- '^vue.*\\u0000$',
- '^@vue.*\\u0000$',
- '^pinia.*\\u0000$',
- '^vite\\u0000$',
- '^@vitejs.*\\u0000$',
- '^vite-plugin.*\\u0000$',
- '^unocss\\u0000$',
- '^@unocss.*\\u0000$',
- '^@?\\w.*\\u0000$',
- '^node:.*\\u0000$',
- '^@/constants.*\\u0000$',
- '^@/types.*\\u0000$',
- '^.*\\u0000$',
- ],
- // Style imports.
- ['^.+\\.s?css$'],
- // Side effect imports.
- ['^\\u0000'],
- ],
- },
- ],
- 'simple-import-sort/exports': 'error',
- },
- },
- // json rules
- {
- files: ['**/*.json'],
- languageOptions: {
- parser: jsoncParser,
- },
- rules: {
- 'jsonc/key-name-casing': [
- 'error',
- {
- camelCase: true,
- },
- ],
- 'jsonc/sort-keys': [
- 'error',
- {
- pathPattern: '.*',
- order: { type: 'asc' },
- },
- ],
- },
- },
- // js rules
- {
- files: ['**/*.{js,mjs,cjs,jsx,vue}'],
- rules: {
- 'object-shorthand': ['error', 'always'],
- 'no-unused-vars': 'off',
- 'no-var': 'error',
- },
- },
- // ts rules
- {
- files: ['**/*.{ts,mts,tsx,vue}'],
- rules: {
- 'object-shorthand': ['error', 'always'],
- '@typescript-eslint/no-unused-vars': 'error',
- '@typescript-eslint/no-explicit-any': 'error',
- '@typescript-eslint/no-inferrable-types': 'off',
- '@typescript-eslint/prefer-optional-chain': 'off',
- },
- },
- // vue rules
- {
- files: ['**/*.vue'],
- rules: {
- 'vue/component-tags-order': [
- 'error',
- {
- order: ['script:not([setup])', 'script[setup]', 'template', 'style:not([scoped])', 'style[scoped]'],
- },
- ],
- 'vue/component-name-in-template-casing': [
- 'error',
- 'PascalCase',
- {
- registeredComponentsOnly: false,
- ignores: ['/^un-/'],
- },
- ],
- 'vue/multi-word-component-names': [
- 'error',
- {
- ignores: ['Login'],
- },
- ],
- 'vue/html-self-closing': [
- 'error',
- {
- html: {
- void: 'always',
- normal: 'never',
- component: 'always',
- },
- svg: 'always',
- math: 'always',
- },
- ],
- 'vue/prop-name-casing': ['error', 'camelCase'],
- 'vue/attribute-hyphenation': [
- 'error',
- 'always',
- {
- ignore: [],
- },
- ],
- 'vue/padding-line-between-blocks': ['error', 'always'],
- 'vue/block-lang': [
- 'error',
- {
- script: {
- lang: 'ts',
- },
- template: {},
- style: {
- lang: 'scss',
- },
- },
- ],
- 'vue/no-mutating-props': [
- 'error',
- {
- shallowOnly: true,
- },
- ],
- },
- },
- );
|