1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
| import js from '@eslint/js'; import vue from 'eslint-plugin-vue'; import globals from 'globals'; // 使用 auto-import 時需設定 // import autoImportGlobals from './.eslint-auto-import.js';
export default [ js.configs.recommended, ...vue.configs['flat/recommended'], { languageOptions: { ecmaVersion: 2021, sourceType: 'module', globals: { ...globals.browser, ...globals.es2021, ...globals.node, // 使用 auto-import 時需設定 // ...autoImportGlobals.globals } }, rules: { // ========== 基本規則 ========== // 禁用 var,必須使用 const 或 let 'no-var': 'error', 'prefer-const': 'error', // 分號使用規則 semi: ['error', 'always'], 'semi-spacing': ['error', { before: false, after: true }], // 引號使用規則 - 統一使用單引號 quotes: ['error', 'single', { avoidEscape: true, allowTemplateLiterals: true }], // ========== 格式化 ========== // 縮排規則 - 使用 2 個空格 indent: ['error', 2, { SwitchCase: 1, VariableDeclarator: 1, outerIIFEBody: 1, MemberExpression: 1, FunctionDeclaration: { parameters: 1, body: 1 }, FunctionExpression: { parameters: 1, body: 1 }, CallExpression: { arguments: 1 }, ArrayExpression: 1, ObjectExpression: 1, ImportDeclaration: 1, flatTernaryExpressions: false, ignoreComments: false }], // 換行和空行規則 'max-len': ['warn', { code: 100, ignoreUrls: true, ignoreStrings: true, ignoreTemplateLiterals: true }], 'eol-last': ['error', 'always'], 'no-multiple-empty-lines': ['error', { max: 2, maxEOF: 1 }], // 逗號規則 'comma-dangle': ['error', 'never'], 'comma-spacing': ['error', { before: false, after: true }], 'comma-style': ['error', 'last'], // 括號規則 'brace-style': ['error', '1tbs', { allowSingleLine: true }], curly: ['error', 'all'], // ========== 變數命名規則 ========== // 駝峰命名法 camelcase: ['error', { properties: 'always', ignoreDestructuring: false, ignoreImports: false, ignoreGlobals: false }], // 禁止未使用的變數 'no-unused-vars': ['error', { vars: 'all', args: 'after-used', ignoreRestSiblings: true }], // 變數必須先宣告後使用 'no-undef': 'error', // ========== 函數規則 ========== // 函數名稱規則 'func-names': ['warn', 'as-needed'], 'func-style': ['error', 'declaration', { allowArrowFunctions: true }], // 箭頭函數規則 'arrow-spacing': ['error', { before: true, after: true }], 'arrow-parens': ['error', 'as-needed'], 'prefer-arrow-callback': ['error', { allowNamedFunctions: false }], // ========== 物件和陣列規則 ========== // 物件簡寫語法 'object-shorthand': ['error', 'always'], 'quote-props': ['error', 'as-needed'], // 解構賦值 'prefer-destructuring': ['warn', { array: true, object: true }, { enforceForRenamedProperties: false }], // ========== 比較運算符規則 ========== // 使用嚴格等號 eqeqeq: ['error', 'always', { null: 'ignore' }], 'no-eq-null': 'off', // ========== 錯誤處理規則 ========== // 禁止空的 catch 區塊 'no-empty': ['error', { allowEmptyCatch: false }], // Promise 錯誤處理 'prefer-promise-reject-errors': 'error', // ========== 安全性規則 ========== // 禁止使用 eval 'no-eval': 'error', 'no-implied-eval': 'error', // 禁止使用全域變數 'no-implicit-globals': 'error', // 禁止修改參數 'no-param-reassign': ['error', { props: false }], // ========== 程式碼品質規則 ========== // 禁止 console.log (除了開發環境) 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'warn', 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'warn', // 禁止未使用的表達式 'no-unused-expressions': ['error', { allowShortCircuit: true, allowTernary: true }], // ========== 註解規則 ========== // JSDoc 相關 'spaced-comment': ['error', 'always', { line: { markers: ['/'] }, block: { markers: ['*'], balanced: true } }], // ========== 模組化規則 ========== // ES6 模組 'prefer-template': 'error', 'template-curly-spacing': ['error', 'never'] } }, // Vue { files: ['**/*.vue'], rules: { // Vue 檔案命名 'vue/match-component-file-name': ['error', { extensions: ['vue'], shouldMatchCase: true }], 'vue/multi-word-component-names': 'off', 'vue/component-api-style': ['error', ['script-setup', 'composition']], 'vue/prop-name-casing' : ['off', 'camelCase'], 'vue/attribute-hyphenation': 'off', 'eslintvue/v-on-event-hyphenation':'off', 'vue/component-definition-name-casing': ['off', 'PascalCase'], 'vue/component-name-in-template-casing': ['off', 'kebab-case'] } }, { ignores: ['dist/', 'node_modules/', 'public/', 'vite.config.js'] } ];
|