import js from "@eslint/js"; import globals from "globals"; import tseslint from "typescript-eslint"; import vue from "eslint-plugin-vue"; const commonGlobals = { ...globals.browser, ...globals.node, ...globals.es2024, CanvasImageSource: "readonly", EventListener: "readonly", PositionCallback: "readonly", grecaptcha: "readonly", }; const vitestGlobals = { ...globals.vitest, }; const lintTargets = ["**/*.{js,mjs,cjs,ts,tsx,vue}"]; const tsTargets = ["**/*.{ts,tsx,mts,cts}"]; function warningRules(rules = {}) { return Object.fromEntries( Object.entries(rules).map(([name, value]) => { if (value === "off" || value === 0) { return [name, value]; } if (Array.isArray(value)) { return [name, ["warn", ...value.slice(1)]]; } return [name, "warn"]; }), ); } function warningConfig(config, files) { return { ...config, files: config.files ?? files, rules: warningRules(config.rules), }; } const jsRecommended = warningConfig(js.configs.recommended, lintTargets); const tsRecommended = tseslint.configs.recommended.map((config) => warningConfig(config, tsTargets), ); const vueEssential = vue.configs["flat/essential"].map((config) => warningConfig(config, ["**/*.vue"]), ); const ignoredPaths = [ "app/build/**", "coverage/**", "dist/**", "node_modules/**", "node_modules.codex-backup/**", "output/**", "public/build/**", "src/assets/test/**", "test/**", "vendor/**", "*.timestamp-*.mjs", "**/*.timestamp-*.mjs", ]; const commonUnusedOptions = { argsIgnorePattern: "^_", caughtErrorsIgnorePattern: "^_", varsIgnorePattern: "^_", }; export default [ { ignores: ignoredPaths, }, jsRecommended, ...tsRecommended, ...vueEssential, { files: ["**/*.vue"], languageOptions: { parserOptions: { parser: tseslint.parser, extraFileExtensions: [".vue"], ecmaVersion: "latest", sourceType: "module", }, }, }, { files: lintTargets, plugins: { vue, }, languageOptions: { ecmaVersion: "latest", sourceType: "module", globals: commonGlobals, }, rules: { "no-console": "off", "no-debugger": "warn", "no-empty": ["warn", { allowEmptyCatch: true }], "no-undef": "warn", "no-unused-vars": ["warn", commonUnusedOptions], "no-useless-assignment": "warn", "vue/multi-word-component-names": "off", "vue/no-mutating-props": ["warn", { shallowOnly: true }], "vue/no-unused-components": "warn", "vue/no-unused-vars": "warn", "vue/no-v-html": "off", }, }, { files: ["**/*.{ts,tsx}"], plugins: { "@typescript-eslint": tseslint.plugin, }, rules: { "no-unused-vars": "off", "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-unused-vars": ["warn", commonUnusedOptions], }, }, { files: ["tests/**/*.{js,ts}", "playwright*.ts", "scripts/**/*.{js,mjs}"], languageOptions: { globals: { ...commonGlobals, ...globals.node, ...vitestGlobals, }, }, rules: { "no-empty": ["warn", { allowEmptyCatch: true }], }, }, ];