Last active
October 15, 2024 20:09
-
-
Save ShayanTheNerd/6c1ba67117b4bd9115fd48036316820b to your computer and use it in GitHub Desktop.
Exhaustive linting and formatting configs for HTML, JS, TS, Astro, Vue, Tailwind, Vitest, Cypress, and Playwright.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import eslintPluginAstro from 'eslint-plugin-astro'; | |
export default { | |
...eslintPluginAstro.configs.recommended.rules, | |
'astro/no-set-html-directive': 'error', | |
'astro/no-set-text-directive': 'error', | |
'astro/no-unused-css-selector': 'error', | |
'astro/prefer-object-class-list': 'error', | |
'astro/no-exports-from-components': 'error', | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const cypressRules = { | |
'cypress/no-pause': 'error', | |
'cypress/no-force': 'error', | |
'cypress/no-async-tests': 'off', | |
'cypress/assertion-before-screenshot': 'error', | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint-disable no-magic-numbers -- Improve SNR */ | |
import process from 'node:process'; | |
import eslintHTMLParser from '@html-eslint/parser'; | |
import eslintConfigAntfu from '@antfu/eslint-config'; | |
import eslintPluginVitest from 'eslint-plugin-vitest'; | |
import eslintConfigNuxt from './.nuxt/eslint.config.mjs'; | |
import eslintTSParser from '@typescript-eslint/parser'; | |
import eslintPLuginHTML from '@html-eslint/eslint-plugin'; | |
import eslintPluginCypress from 'eslint-plugin-cypress/flat'; | |
import eslintPluginPlaywright from 'eslint-plugin-playwright'; | |
function composeESLintConfig(...configs) { | |
return eslintConfigNuxt(eslintConfigAntfu(...configs)); | |
} | |
export default composeESLintConfig( | |
{ | |
ignores: ['**/*.json', '**/env.d.ts'], | |
vue: true, | |
astro: true, | |
typescript: { tsconfigPath: 'tsconfig.json' }, | |
}, | |
{ | |
files: ['**/*.{js,ts}', 'src/**/*.astro', 'src/components/**/*.vue'], | |
rules: { ...stylisticRules, ...jsRules, ...tsRules, ...vueRules }, | |
}, | |
{ | |
files: ['index.html'], | |
plugins: { '@html-eslint': eslintPLuginHTML }, | |
languageOptions: { parser: eslintHTMLParser }, | |
rules: htmlRules, | |
}, | |
{ | |
files: ['src/**/*.astro'], | |
languageOptions: { | |
parser: eslintTSParser, | |
parserOptions: { | |
project: 'tsconfig.json', | |
extraFileExtensions: ['.astro'], | |
}, | |
}, | |
rules: astroRules, | |
}, | |
{ | |
files: ['tests/unit/**/*.test.ts'], | |
plugins: { eslintPluginVitest }, | |
languageOptions: { | |
globals: { | |
...eslintPluginVitest.environments.env.globals, | |
}, | |
}, | |
rules: vitestRules, | |
}, | |
{ | |
files: ['tests/cypress/e2e/**/*.cy.ts'], | |
...eslintPluginCypress.configs.recommended, | |
rules: cypressRules, | |
}, | |
{ | |
files: ['tests/e2e/**/*.test.ts'], | |
...eslintPluginPlaywright.configs['flat/recommended'], | |
rules: playwrightRules | |
}, | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default { | |
/* Best Practices */ | |
'@html-eslint/no-duplicate-id': 'error', | |
'@html-eslint/require-doctype': 'error', | |
'@html-eslint/no-obsolete-tags': 'error', | |
'@html-eslint/no-duplicate-attrs': 'error', | |
'@html-eslint/require-li-container': 'error', | |
'@html-eslint/require-button-type': 'error', | |
'@html-eslint/no-script-style-type': 'error', | |
'@html-eslint/require-meta-charset': 'error', | |
'@html-eslint/require-closing-tags': ['error', { selfClosing: 'always' }], | |
/* SEO */ | |
'@html-eslint/require-lang': 'error', | |
'@html-eslint/require-title': 'error', | |
'@html-eslint/no-multiple-h1': 'error', | |
'@html-eslint/require-meta-description': 'error', | |
'@html-eslint/require-open-graph-protocol': 'error', | |
/* Accessibility */ | |
'@html-eslint/require-img-alt': 'error', | |
'@html-eslint/no-abstract-roles': 'error', | |
'@html-eslint/no-accesskey-attrs': 'error', | |
'@html-eslint/require-frame-title': 'error', | |
'@html-eslint/no-aria-hidden-body': 'error', | |
'@html-eslint/no-positive-tabindex': 'error', | |
'@html-eslint/no-skip-heading-levels': 'error', | |
'@html-eslint/require-meta-viewport': 'error', | |
/* Style */ | |
'@html-eslint/quotes': 'error', | |
'@html-eslint/lowercase': 'error', | |
'@html-eslint/indent': ['error', 'tab'], | |
'@html-eslint/no-trailing-spaces': 'error', | |
'@html-eslint/id-naming-convention': 'error', | |
'@html-eslint/no-multiple-empty-lines': 'error', | |
'@html-eslint/element-newline': ['error', { skip: ['pre', 'code'] }], | |
'@html-eslint/no-extra-spacing-attrs': ['error', { enforceBeforeSelfClose: true }], | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import eslintJS from '@eslint/js'; | |
export default { | |
'unused-imports/no-unused-vars': 'off', | |
...eslintJS.configs.recommended.rules, | |
/* Possible Problems */ | |
'no-await-in-loop': 'error', | |
'no-self-compare': 'error', | |
'no-unreachable-loop': 'error', | |
'no-inner-declarations': 'error', | |
'array-callback-return': 'error', | |
'no-useless-assignment': 'error', | |
'no-constructor-return': 'error', | |
'require-atomic-updates': 'error', | |
'no-async-promise-executor': 'error', | |
'no-template-curly-in-string': 'error', | |
'no-promise-executor-return': 'error', | |
'no-unmodified-loop-condition': 'error', | |
'no-use-before-define': ['error', 'nofunc'], | |
'use-isnan': ['error', { enforceForIndexOf: true }], | |
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }], | |
'no-unsafe-negation': ['error', { enforceForOrderingRelations: true }], | |
'no-unsafe-optional-chaining': ['error', { disallowArithmeticOperators: true }], | |
/* Suggestions */ | |
'yoda': 'error', | |
'strict': 'error', | |
'no-var': 'error', | |
'eqeqeq': 'error', | |
'no-new': 'error', | |
'no-eval': 'error', | |
'no-void': 'error', | |
'new-cap': 'error', | |
'no-proto': 'error', | |
'no-caller': 'error', | |
'no-empty': 'error', | |
'no-eq-null': 'error', | |
'camelcase': 'error', | |
'sort-imports': 'off', | |
'no-redeclare': 'off', | |
'complexity': 'error', | |
'no-iterator': 'error', | |
'no-lonely-if': 'error', | |
'max-params': 'error', | |
'no-shadow': ['error'], | |
'no-label-var': 'error', | |
'no-new-func': 'error', | |
'no-multi-str': 'error', | |
'guard-for-in': 'error', | |
'no-loop-func': 'error', | |
'default-case': 'error', | |
'no-script-url': 'error', | |
'prefer-const': 'error', | |
'no-undefined': 'error', | |
'no-undef-init': 'error', | |
'require-await': 'error', | |
'no-extra-bind': 'error', | |
'prefer-spread': 'error', | |
'dot-notation': ['error'], | |
'no-lone-blocks': 'error', | |
'no-extra-label': 'error', | |
'accessor-pairs': 'error', | |
'no-useless-call': 'error', | |
'max-depth': ['error', 3], | |
'no-implied-eval': 'error', | |
'consistent-this': 'error', | |
'no-octal-escape': 'error', | |
'no-throw-literal': 'error', | |
'prefer-template': 'error', | |
'init-declarations': 'error', | |
'no-new-wrappers': 'error', | |
'block-scoped-var': 'error', | |
'no-extend-native': 'error', | |
'default-case-last': 'error', | |
'object-shorthand': 'error', | |
'no-useless-return': 'error', | |
'consistent-return': 'error', | |
'no-useless-concat': 'error', | |
'no-nested-ternary': 'error', | |
'no-useless-rename': 'error', | |
'no-implicit-globals': 'error', | |
'default-param-last': 'error', | |
'symbol-description': 'error', | |
'curly': ['error', 'multi-line'], | |
'prefer-rest-params': 'error', | |
'no-implicit-coercion': 'error', | |
'radix': ['error', 'as-needed'], | |
'func-name-matching': 'error', | |
'operator-assignment': 'error', | |
'no-unneeded-ternary': 'error', | |
'no-array-constructor': 'error', | |
'prefer-destructuring': 'error', | |
'no-underscore-dangle': 'error', | |
'prefer-object-spread': 'error', | |
'no-object-constructor': 'error', | |
'prefer-object-has-own': 'error', | |
'no-useless-constructor': 'error', | |
'class-methods-use-this': 'error', | |
'prefer-numeric-literals': 'error', | |
'no-useless-computed-key': 'error', | |
'max-nested-callbacks': ['error', 3], | |
'no-return-assign': ['error', 'always'], | |
'prefer-named-capture-group': 'error', | |
'no-bitwise': ['error', { int32Hint: true }], | |
'prefer-exponentiation-operator': 'error', | |
'import/extensions': ['error', 'ignorePackages'], | |
'logical-assignment-operators': ['error', 'always'], | |
'no-sequences': ['error', { allowInParentheses: false }], | |
'no-multi-assign': ['error', { ignoreNonDeclaration: true }], | |
'no-empty-function': ['error', { allow: ['arrowFunctions'] }], | |
'no-plusplus': ['error', { allowForLoopAfterthoughts: true }], | |
'prefer-arrow-callback': ['error', { allowUnboundThis: true }], | |
'func-style': ['error', 'declaration', { allowArrowFunctions: true }], | |
'prefer-promise-reject-errors': ['error', { allowEmptyReject: true }], | |
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', | |
'prefer-regex-literals': ['error', { disallowRedundantWrapping: true }], | |
'no-extra-boolean-cast': ['error', { enforceForInnerExpressions: true }], | |
'no-unused-expressions': ['error', { allowShortCircuit: true, allowTernary: true }], | |
'arrow-body-style': ['error', 'as-needed', { requireReturnForObjectLiteral: true }], | |
'no-restricted-exports': ['error', { | |
restrictDefaultExports: { | |
named: true, | |
namedFrom: true, | |
defaultFrom: true, | |
namespaceFrom: true, | |
}, | |
}], | |
'no-magic-numbers': ['error', { | |
enforceConst: true, | |
ignoreDefaultValues: true, | |
ignoreClassFieldInitialValues: true, | |
ignore: [-100, -1, 0, 1, 2, 100], | |
}], | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { fileURLToPath } from 'node:url'; | |
import { dirname, relative } from 'node:path'; | |
const absoluteFilePath = fileURLToPath(import.meta.url); | |
const cwd = dirname(absoluteFilePath); | |
/** | |
* Converts an array of absolute file paths to a space-separated (`' '`) string of paths relative to the current working directory. | |
* @param {string[]} absolutePaths - An array of absolute file paths. | |
*/ | |
function toRelativePathsString(absolutePaths) { | |
return absolutePaths.map((absolutePath) => relative(cwd, absolutePath)).join(' '); | |
} | |
/** | |
* @typedef {Record<string, (absoluteFilePaths: string[]) => string | string[] | Promise<string | string[]>>} LintStagedConfig | |
* @type {LintStagedConfig} | |
*/ | |
export default { | |
'!*.{js,ts}': (absoluteFilePaths) => `prettier --write ${toRelativePathsString(absoluteFilePaths)} --ignore-unknown --cache`, | |
'*.{js,ts,vue}': (absoluteFilePaths) => `eslint ${toRelativePathsString(absoluteFilePaths)} --fix`, | |
'{app,server}/**/*.{ts,vue}': (absoluteFilePaths) => [ | |
'bun typecheck', | |
`vitest related ${toRelativePathsString(absoluteFilePaths)} --run`, | |
'bun test:e2e', | |
], | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"type": "module", | |
"scripts": { | |
"prepare": "simple-git-hooks", | |
"format": "prettier --write . '!**/*.{js,ts}' --cache", | |
"lint": "eslint --fix --cache --cache-location='/node_modules/.eslintcache/", | |
"test:unit": "vitest", | |
"test:e2e": "playwright test --fail-on-flaky-tests" | |
"test:e2e": "concurrently \"pnpm dev\" \"cypress open\" --kill-others", | |
"test:e2e:ci": "concurrently \"pnpm preview\" \"cypress run\" --kill-others", | |
"all": "pnpm format && pnpm lint && pnpm test:unit --run && pnpm build && pnpm test:e2e:ci" | |
}, | |
"simple-git-hooks": { | |
"pre-commit": "lint-staged" | |
}, | |
"devDependencies": { | |
"@antfu/eslint-config": "^3.7.3", | |
"@eslint/js": "^9.12.0", | |
"@html-eslint/eslint-plugin": "^0.27.0", | |
"@html-eslint/parser": "^0.27.0", | |
"@nuxt/eslint": "^0.6.0", | |
"@stylistic/eslint-plugin": "^2.9.0", | |
"@typescript-eslint/parser": "^8.9.0", | |
"concurrently": "^9.0.1", | |
"cypress": "^13.15.0", | |
"cypress-vite": "^1.5.0", | |
"eslint-plugin-astro": "^1.3.0", | |
"eslint-plugin-cypress": "^4.0.0", | |
"eslint-plugin-vitest": "^0.5.4", | |
"eslint-plugin-vue": "^9.29.0", | |
"lint-staged": "^15.2.10", | |
"prettier": "^3.3.3", | |
"prettier-plugin-tailwindcss": "^0.6.8", | |
"simple-git-hooks": "^2.11.1" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default { | |
'no-magic-numbers': 'off', | |
'playwright/max-expects': 'off', | |
'playwright/prefer-to-be': 'error', | |
'playwright/no-get-by-title': 'error', | |
'playwright/prefer-to-contain': 'error', | |
'playwright/no-wait-for-timeout': 'off', | |
'playwright/no-duplicate-hooks': 'error', | |
'playwright/prefer-strict-equal': 'error', | |
'playwright/prefer-hooks-on-top': 'error', | |
'playwright/prefer-to-have-count': 'error', | |
'playwright/prefer-to-have-length': 'error', | |
'playwright/prefer-hooks-in-order': 'error', | |
'playwright/prefer-equality-matcher': 'error', | |
'playwright/no-commented-out-tests': 'error', | |
'playwright/require-to-throw-message': 'error', | |
'playwright/prefer-comparison-matcher': 'error', | |
'playwright/max-nested-describe': ['error', { max: 1 }], | |
'playwright/prefer-lowercase-title': ['error', { ignoreTopLevelDescribe: true }], | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** @type {import('prettier').Options} */ | |
export default { | |
useTabs: true, | |
printWidth: 150, | |
singleQuote: true, | |
trailingComma: 'all', | |
quoteProps: 'consistent', | |
plugins: ['prettier-plugin-tailwindcss'], | |
tailwindEntryPoint: 'app/assets/styles/app.css', | |
overrides: [ | |
{ | |
files: '*.svg', | |
options: { | |
parser: 'html', | |
}, | |
}, | |
], | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"files.associations": { | |
"*.svg": "html", | |
"*.xml": "html" | |
}, | |
"editor.formatOnSave": true, | |
"[javascript][typescript][vue]": { | |
"editor.formatOnSave": false | |
}, | |
"editor.codeActionsOnSave": { | |
"source.fixAll.eslint": "explicit", | |
"source.organizeImports": "never" | |
}, | |
"editor.defaultFormatter": "esbenp.prettier-vscode", | |
/* Silently auto-fix stylistic rules. */ | |
"eslint.rules.customizations": [ | |
{ "rule": "unocss*", "severity": "off" }, | |
{ "rule": "*sort*", "severity": "off" }, | |
{ "rule": "*style*", "severity": "off" }, | |
{ "rule": "*indent", "severity": "off" }, | |
{ "rule": "*quotes", "severity": "off" }, | |
{ "rule": "import*", "severity": "off" }, | |
{ "rule": "*-spaces", "severity": "off" }, | |
{ "rule": "*-spacing", "severity": "off" }, | |
{ "rule": "*newline*", "severity": "off" }, | |
{ "rule": "attribute*", "severity": "off" }, | |
{ "rule": "format/prettier", "severity": "off" }, | |
{ "rule": "vue/comma-dangle", "severity": "off" }, | |
{ "rule": "vue/space-in-parens", "severity": "off" }, | |
{ "rule": "vue/attributes-order", "severity": "off" }, | |
{ "rule": "vue/define-macros-order", "severity": "off" }, | |
{ "rule": "vue/max-attributes-per-line", "severity": "off" }, | |
{ "rule": "vue/no-static-inline-styles", "severity": "error" }, | |
{ "rule": "vue/first-attribute-linebreak", "severity": "off" }, | |
{ "rule": "vue/enforce-style-attribute", "severity": "error" } | |
], | |
"eslint.validate": [ | |
"javascript", | |
"javascriptreact", | |
"typescript", | |
"typescriptreact", | |
"vue", | |
"html", | |
"markdown", | |
"json", | |
"jsonc", | |
"yaml", | |
"toml", | |
"gql", | |
"graphql" | |
], | |
}, | |
"[git-commit]": { | |
"editor.rulers": [50, 72] | |
}, |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import eslintPluginStylistic from '@stylistic/eslint-plugin'; | |
export default { | |
'antfu/if-newline': 'off', | |
/* Sorting */ | |
'import/order': 'off', | |
'perfectionist/sort-maps': ['error', { type: 'line-length' }], | |
'perfectionist/sort-exports': ['error', { type: 'line-length' }], | |
'perfectionist/sort-union-types': ['error', { type: 'line-length' }], | |
'perfectionist/sort-array-includes': ['error', { type: 'line-length' }], | |
'perfectionist/sort-intersection-types': ['error', { type: 'line-length' }], | |
'perfectionist/sort-named-imports': ['error', { type: 'line-length', groupKind: 'types-first' }], | |
'perfectionist/sort-named-exports': ['error', { type: 'line-length', groupKind: 'types-first' }], | |
'perfectionist/sort-imports': ['error', { | |
'type': 'line-length', | |
'internal-pattern': ['@ts/**', '@styles/**', '@components/**'], | |
'custom-groups': { | |
value: { | |
'astro-components': '@components/**/*.astro', | |
'vue-components': '@components/**/*.vue', | |
} | |
}, | |
'groups': [ | |
['side-effect-style', 'side-effect'], | |
['index-type', 'builtin-type', 'external-type', 'internal-type', 'parent-type', 'sibling-type'], | |
'astro-components', | |
'vue-components', | |
['index', 'builtin', 'external', 'internal', 'parent', 'sibling'], | |
['object', 'unknown'], | |
], | |
}], | |
...eslintPluginStylistic.configs['recommended-flat'].rules, | |
'style/no-tabs': 'off', | |
'style/semi-style': 'error', | |
'style/no-extra-semi': 'error', | |
'style/spaced-comment': 'off', | |
'style/indent': ['error', 'tab'], | |
'style/arrow-parens': ['error', 'always'], | |
'style/indent-binary-ops': ['error', 'tab'], | |
'style/operator-linebreak': ['error', 'none'], | |
'style/implicit-arrow-linebreak': ['error', 'beside'], | |
'style/no-mixed-spaces-and-tabs': ['error', 'smart-tabs'], | |
'style/brace-style': ['error', '1tbs', { allowSingleLine: true }], | |
'style/semi': ['error', 'always', { omitLastInOneLineBlock: true }], | |
'style/lines-around-comment': ['error', { | |
allowTypeStart: true, | |
allowEnumStart: true, | |
allowClassStart: true, | |
allowBlockStart: true, | |
allowArrayStart: true, | |
allowModuleStart: true, | |
allowObjectStart: true, | |
allowInterfaceStart: true, | |
}], | |
'style/member-delimiter-style': ['error', { | |
multilineDetection: 'brackets', | |
multiline: { delimiter: 'semi', requireLast: true }, | |
singleline: { delimiter: 'semi', requireLast: false }, | |
}], | |
'style/padding-line-between-statements': [ | |
'error', | |
{ | |
prev: '*', | |
next: [ | |
'do', | |
'try', | |
'for', | |
'iife', | |
'with', | |
'class', | |
'block', | |
'while', | |
'throw', | |
'return', | |
'switch', | |
'export', | |
'function', | |
'directive', | |
'block-like', | |
'cjs-export', | |
'multiline-block-like', | |
], | |
blankLine: 'always', | |
}, | |
{ | |
prev: 'export', | |
next: 'export', | |
blankLine: 'any', | |
}, | |
{ | |
prev: ['const', 'let', 'var'], | |
next: 'block-like', | |
blankLine: 'any', | |
}, | |
{ | |
prev: 'block-like', | |
next: '*', | |
blankLine: 'always', | |
}, | |
{ | |
prev: 'function-overload', | |
next: 'function', | |
blankLine: 'never', | |
}, | |
], | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default { | |
'ts/no-misused-promises': 'off', | |
'ts/no-unsafe-assignment': 'off', | |
'ts/strict-boolean-expressions': 'off', | |
'ts/consistent-type-definitions': ['error', 'type'], | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import eslintPluginVitest from 'eslint-plugin-vitest'; | |
export default { | |
'no-magic-numbers': 'off', | |
...eslintPluginVitest.configs.recommended.rules, | |
'vitest/prefer-todo': 'error', | |
'vitest/require-hook': 'error', | |
'vitest/prefer-to-be': 'error', | |
'vitest/prefer-spy-on': 'error', | |
'vitest/no-mocks-import': 'error', | |
'vitest/no-test-prefixes': 'error', | |
'vitest/no-alias-methods': 'error', | |
'vitest/no-focused-tests': 'error', | |
'vitest/no-disabled-tests': 'error', | |
'vitest/prefer-to-contain': 'error', | |
'vitest/prefer-called-with': 'error', | |
'vitest/prefer-to-be-falsy': 'error', | |
'vitest/no-duplicate-hooks': 'error', | |
'vitest/prefer-strict-equal': 'error', | |
'vitest/no-conditional-tests': 'error', | |
'vitest/prefer-to-be-truthy': 'error', | |
'vitest/prefer-to-be-object': 'error', | |
'vitest/no-standalone-expect': 'error', | |
'vitest/no-conditional-expect': 'error', | |
'vitest/no-conditional-in-test': 'error', | |
'vitest/prefer-to-have-length': 'error', | |
'vitest/prefer-hooks-in-order': 'error', | |
'vitest/prefer-lowercase-title': 'error', | |
'vitest/prefer-equality-matcher': 'error', | |
'vitest/consistent-test-filename': 'error', | |
'vitest/no-test-return-statement': 'error', | |
'vitest/require-to-throw-message': 'error', | |
'vitest/prefer-comparison-matcher': 'error', | |
'vitest/no-interpolation-in-snapshots': 'error', | |
'vitest/prefer-mock-promise-shorthand': 'error', | |
'vitest/prefer-snapshot-hint': ['error', 'always'], | |
'vitest/max-nested-describe': ['error', { max: 1 }], | |
'vitest/consistent-test-it': ['error', { fn: 'test', withinDescribe: 'test' }], | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { version as vueVersion } from 'vue'; | |
import eslintPluginVue from 'eslint-plugin-vue'; | |
export default { | |
'no-useless-assignment': 'off', | |
'nuxt/prefer-import-meta': 'error', | |
...eslintPluginVue.configs.recommended.rules, | |
/* Base */ | |
'vue/jsx-uses-vars': 'error', | |
'vue/comment-directive': ['error', { reportUnusedDisableDirectives: true }], | |
/* Priority A: Essential (Error Prevention) */ | |
'vue/no-multiple-template-root': 'off', | |
/* Priority B: Strongly Recommended (Improving Readability) */ | |
'vue/html-indent': ['error', 'tab'], | |
'vue/singleline-html-element-content-newline': 'off', | |
'vue/max-attributes-per-line': ['error', { singleline: 3 }], | |
'vue/v-slot-style': ['error', { atComponent: 'shorthand' }], | |
'vue/html-self-closing': ['error', { html: { void: 'always' } }], | |
'vue/first-attribute-linebreak': ['error', { singleline: 'beside' }], | |
'vue/v-on-event-hyphenation': ['error', 'always', { autofix: true }], | |
'vue/v-bind-style': ['error', 'shorthand', { sameNameShorthand: 'always' }], | |
/* Priority C: Recommended (Potentially Dangerous Patterns) */ | |
'vue/attributes-order': ['error', { | |
order: [ | |
'RENDER_MODIFIERS', | |
'DEFINITION', | |
'CONDITIONALS', | |
'LIST_RENDERING', | |
'UNIQUE', | |
'TWO_WAY_BINDING', | |
'OTHER_DIRECTIVES', | |
'OTHER_ATTR', | |
'SLOT', | |
'CONTENT', | |
'GLOBAL', | |
], | |
}], | |
/* Miscellaneous */ | |
'vue/no-root-v-if': ['error'], | |
'vue/require-expose': ['error'], | |
'vue/no-unused-refs': ['error'], | |
'vue/no-useless-v-bind': ['error'], | |
'vue/require-typed-ref': ['error'], | |
'vue/valid-define-options': ['error'], | |
'vue/require-explicit-slots': ['error'], | |
'vue/prefer-define-options': ['error'], | |
'vue/require-emit-validator': ['error'], | |
'vue/require-default-export': ['error'], | |
'vue/no-use-v-else-with-v-for': ['error'], | |
'vue/v-for-delimiter-style': ['error', 'in'], | |
'vue/no-empty-component-block': ['error'], | |
'vue/html-comment-indent': ['error', 'tab'], | |
'vue/no-multiple-objects-in-class': ['error'], | |
'vue/prefer-separate-static-class': ['error'], | |
'vue/no-ref-object-reactivity-loss': ['error'], | |
'vue/no-duplicate-attr-inheritance': ['error'], | |
'vue/no-this-in-before-route-enter': ['error'], | |
'vue/no-setup-props-reactivity-loss': ['error'], | |
'vue/block-lang': ['error', { script: { lang: 'ts' } }], | |
'vue/component-api-style': ['error', ['script-setup']], | |
'vue/padding-line-between-blocks': ['error', 'always'], | |
'vue/define-props-declaration': ['error', 'type-based'], | |
'vue/custom-event-name-casing': ['error', 'camelCase'], | |
'vue/define-emits-declaration': ['error', 'type-literal'], | |
'vue/html-comment-content-spacing': ['error', 'always'], | |
'vue/prefer-true-attribute-shorthand': ['error', 'always'], | |
'vue/no-static-inline-styles': ['error', { allowBinding: true }], | |
'vue/enforce-style-attribute': ['error', { allow: ['scoped'] }], | |
'vue/component-options-name-casing': ['error', 'PascalCase'], | |
'vue/no-required-prop-with-default': ['error', { autofix: true }], | |
'vue/v-on-handler-style': ['error', ['method', 'inline-function']], | |
'vue/no-unsupported-features': ['error', { version: vueVersion }], | |
'vue/no-deprecated-model-definition': ['error', { allowVue3Compat: true }], | |
'vue/html-button-has-type': ['error', { button: true, submit: true, reset: true }], | |
'vue/block-order': ['error', { order: ['script[setup]', 'template', 'style[scoped]'] }], | |
'vue/html-comment-content-newline': ['error', { singleline: 'never', multiline: 'always' }], | |
'vue/match-component-file-name': ['error', { extensions: ['vue'], shouldMatchCase: true }], | |
'vue/block-tag-newline': ['error', { maxEmptyLines: 0, multiline: 'always', singleline: 'consistent' }], | |
'vue/component-name-in-template-casing': ['error', 'PascalCase', { registeredComponentsOnly: false }], | |
'vue/define-macros-order': ['error', { | |
order: [ | |
'defineOptions', | |
'defineProps', | |
], | |
}], | |
'vue/require-macro-variable-name': ['error', { | |
useSlots: 'slots', | |
useAttrs: 'attrs', | |
defineSlots: 'slots', | |
defineProps: 'props', | |
defineEmits: 'emits', | |
}], | |
'vue/no-undef-components': ['error', { | |
/* Ignore built-in Nuxt components. */ | |
ignorePatterns: [ | |
'^Nuxt', | |
'^(Icon|Html|Head|Title|Base|Meta|Link|Style|Body|NoScript)$', | |
], | |
}], | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment