// ESLint flat config codifying the style already in use across src/. // Goal: catch real mistakes and enforce the existing conventions, not impose // an external style guide. Rules were derived by sampling src/scripts/*.js // and src/components/*.vue, not from a template. import js from '@eslint/js'; import vue from 'eslint-plugin-vue'; import globals from 'globals'; export default [ js.configs.recommended, ...vue.configs['flat/essential'], { languageOptions: { ecmaVersion: 'latest', sourceType: 'module', globals: { ...globals.browser } }, rules: { //Indentation: tabs everywhere, one indent per level 'indent': 'off', //too many false positives on Vue template attr wrapping; keep manual 'no-tabs': 'off', //Strings: single quotes (project uses single-quoted strings exclusively) 'quotes': ['warn', 'single', {avoidEscape: true, allowTemplateLiterals: true}], //Semicolons: required almost everywhere. The one consistent //exception is the top-level `export default {...}` in Vue SFCs, //which never gets a trailing semicolon - ESLint's `semi` rule //can't carve that one spot out, so this is 'warn' rather than //'error' to avoid flagging every component's SFC boilerplate //as a hard failure. 'semi': ['warn', 'always'], //Equality: codebase mixes == and === deliberately (e.g. loose checks //against numeric strings from the API) - don't force either 'eqeqeq': 'off', //Function parens: no space before the parameter list - `function(x)`, not `function (x)` 'space-before-function-paren': ['warn', 'never'], //Control structures: no space before the parenthesis - //`if(x)`, `for(...)`, `switch(x)`, not `if (x)` etc. //(100% consistent across src/ - checked via grep before writing this) 'keyword-spacing': ['warn', { after: true, overrides: { if: {after: false}, for: {after: false}, while: {after: false}, switch: {after: false}, catch: {after: false} } }], 'space-before-blocks': ['warn', 'always'], //Object-curly-spacing is deliberately NOT configured: the codebase //consistently uses `{a, b}` (no padding) for object literals and //destructuring, but `import { x } from 'y'` (padded) for imports - //and this rule can't apply different spacing to those two node //kinds, so enforcing either would misfire on the other. 'object-curly-spacing': 'off', 'array-bracket-spacing': ['warn', 'never'], //Prefix convention (Hungarian-ish: sString, iInt, aArray, oObject, bBool) //is a project-wide naming discipline, not something ESLint can check; //left undocumented here on purpose. //Real-bug catchers - keep these strict regardless of style //ignoreRestSiblings covers the `const {prev, ...rest} = obj` idiom //(destructuring a key out just to exclude it from the rest), used //in App.vue - that `prev` binding is intentionally unused. 'no-unused-vars': ['warn', {argsIgnorePattern: '^_', ignoreRestSiblings: true}], 'no-undef': 'error', 'no-var': 'warn', //codebase is ES module/class based; var only appears in one legacy fallback block 'prefer-const': 'off', //not consistently followed, don't force churn //Vue-specific: components are registered and used with camelCase //tags in templates (, ). ESLint's //component-name-in-template-casing rule only supports PascalCase //or kebab-case, neither of which matches, so it's left off here //rather than forced into a casing the codebase doesn't use. 'vue/component-name-in-template-casing': 'off', 'vue/multi-word-component-names': 'off', //AppIcon, Admin, Project etc. mix single/multi-word by design 'vue/attribute-hyphenation': 'off', //existing templates mix camelCase and kebab-case attrs; not consistent enough to enforce yet 'vue/require-default-prop': 'off', 'vue/no-v-html': 'error' //codebase currently has zero v-html usage - keep it that way } }, { ignores: ['public/**', 'vendor/**', 'node_modules/**'] } ];