diff --git a/configs/@typescript-eslint.jsonc b/configs/@typescript-eslint.jsonc index 265a836..451ed56 100644 --- a/configs/@typescript-eslint.jsonc +++ b/configs/@typescript-eslint.jsonc @@ -211,7 +211,7 @@ "prefer-readonly": "off", "prefer-readonly-parameter-types": "off", "prefer-reduce-type-parameter": "error", - "prefer-regexp-exec": "error", + "prefer-regexp-exec": "off", // Handled by `regexp/prefer-regexp-test` "prefer-return-this-type": "error", "prefer-string-starts-ends-with": "error", "promise-function-async": [ diff --git a/configs/eslint.jsonc b/configs/eslint.jsonc index 42a323f..cd82b30 100644 --- a/configs/eslint.jsonc +++ b/configs/eslint.jsonc @@ -17,15 +17,15 @@ "no-constant-binary-expression": "error", "no-constant-condition": "error", "no-constructor-return": "warn", - "no-control-regex": "error", + "no-control-regex": "off", // Handled by `regexp/no-control-character` "no-debugger": "error", "no-dupe-args": "error", - "no-dupe-class-members": "off", // Handeled by `@typescript-eslint/no-dupe-class-members` + "no-dupe-class-members": "off", // Handled by `@typescript-eslint/no-dupe-class-members` "no-dupe-else-if": "off", // Handled by `sonarjs/no-identical-conditions` "no-dupe-keys": "error", "no-duplicate-case": "off", // Handled by `sonarjs/no-identical-conditions` "no-duplicate-imports": "error", - "no-empty-character-class": "error", + "no-empty-character-class": "off", // Handled by `regexp/no-empty-character-class` "no-empty-pattern": "error", "no-ex-assign": "error", "no-fallthrough": "warn", @@ -35,18 +35,19 @@ "error", "both" ], - "no-invalid-regexp": "error", + "no-invalid-regexp": "off", // Handled by `regexp/no-invalid-regexp`, `regexp/no-non-standard-flag` "no-irregular-whitespace": [ "error", { // It should be escaped unicode sequences and not the literal character - "skipStrings": false + "skipStrings": false, + "skipRegExps": true // Handled by `regexp/no-invisible-character` } ], "no-loss-of-precision": "error", - "no-misleading-character-class": "error", + "no-misleading-character-class": "off", // Handled by `regexp/no-misleading-unicode-character` "no-new-native-nonconstructor": "error", - "no-new-symbol": "off", // handled by `no-new-native-nonconstructor` + "no-new-symbol": "off", // Handled by `no-new-native-nonconstructor` "no-obj-calls": "error", "no-promise-executor-return": "off", // because this also affects `new Promise(res => x.on('y', z => res(z)));` "no-prototype-builtins": "error", @@ -73,7 +74,7 @@ "no-unused-vars": "off", // Handled by `@typescript-eslint/no-unused-vars` "no-use-before-define": "off", // Handled by `@typescript-eslint/no-use-before-define` "no-useless-assignment": "error", - "no-useless-backreference": "error", + "no-useless-backreference": "off", // Handled by `regexp/no-useless-backreference` "require-atomic-updates": "warn", "use-isnan": "error", "valid-typeof": "error", @@ -234,7 +235,7 @@ "no-useless-computed-key": "error", "no-useless-concat": "error", "no-useless-constructor": "off", // Handled by `@typescript-eslint/no-useless-constructor` - "no-useless-escape": "error", + "no-useless-escape": "off", // Handled by `regexp/no-useless-escape` "no-useless-rename": "error", "no-useless-return": "off", // Handled by `sonarjs/no-redundant-jump` "no-var": "error", diff --git a/configs/html.jsonc b/configs/html.jsonc new file mode 100644 index 0000000..5321b58 --- /dev/null +++ b/configs/html.jsonc @@ -0,0 +1,4 @@ +{ + "indent": "+2", + "report-bad-indent": "warn" +} \ No newline at end of file diff --git a/configs/jsdoc.jsonc b/configs/jsdoc.jsonc index 7a994ab..760b86a 100644 --- a/configs/jsdoc.jsonc +++ b/configs/jsdoc.jsonc @@ -12,10 +12,10 @@ "check-template-names": "error", "check-types": "error", "check-values": "error", - "convert-to-jsdoc-comments":"off", + "convert-to-jsdoc-comments": "off", "empty-tags": "error", "implements-on-classes": "error", - "imports-as-dependencies": "error", + "imports-as-dependencies": "off", // "error" // See https://github.com/gajus/eslint-plugin-jsdoc/issues/1114 "informative-docs": "error", "lines-before-block": "off", // Handled by `@stylistic/lines-around-comment` "match-description": "off", diff --git a/configs/regexp.jsonc b/configs/regexp.jsonc new file mode 100644 index 0000000..cf2967d --- /dev/null +++ b/configs/regexp.jsonc @@ -0,0 +1,137 @@ +{ + // [REGEXP] https://github.com/ota-meshi/eslint-plugin-regexp#white_check_mark-rules | Using "warn" wherever applicable + // [POSSIBLE ERRORS] + "no-contradiction-with-assertion": "error", + "no-control-character": "warn", // Overlaps partially with `regexp/control-character-escape` + "no-dupe-disjunctions": [ + "warn", + { + "report": "trivial", + "reportExponentialBacktracking": "potential", + "reportUnreachable": "certain" + } + ], + "no-empty-alternative": "error", + "no-empty-capturing-group": "warn", + "no-empty-character-class": "error", + "no-empty-group": "warn", + "no-empty-lookarounds-assertion": "error", + "no-escape-backspace": "warn", // Incompatible with `regexp/no-control-character`, a eslint-disable comment is required. + "no-invalid-regexp": "error", + "no-lazy-ends": [ + "warn", + { + "ignorePartial": true + } + ], + "no-misleading-capturing-group": "error", + "no-misleading-unicode-character": [ + "error", + { + "fixable": true + } + ], + "no-missing-g-flag": "error", + "no-optional-assertion": "warn", + "no-potentially-useless-backreference": "warn", + "no-super-linear-backtracking": [ + "warn", + { + "report": "certain" + } + ], + "no-super-linear-move": [ + "warn", + { + "report": "certain", + "ignoreSticky": true, + "ignorePartial": true + } + ], + "no-useless-assertions": "warn", + "no-useless-backreference": "error", + "no-useless-dollar-replacements": "warn", + "strict": "error", + // [BEST PRACTICES] + "confusing-quantifier": "warn", + "control-character-escape": "warn", // Overlaps partially with `regexp/no-control-character` + "negation": "warn", + "no-dupe-characters-character-class": "warn", + "no-empty-string-literal": "error", + "no-extra-lookaround-assertions": "warn", + "no-invisible-character": "error", + "no-legacy-features": "off", // Handled by `@typescript-eslint/no-deprecated` + "no-non-standard-flag": "error", + "no-obscure-range": "warn", + "no-octal": "warn", + "no-standalone-backslash": "warn", + "no-trivially-nested-assertion": "warn", + "no-trivially-nested-quantifier": "warn", + "no-unused-capturing-group": "warn", + "no-useless-character-class": "warn", + "no-useless-flag": "warn", + "no-useless-lazy": "warn", + "no-useless-quantifier": "warn", + "no-useless-range": "warn", + "no-useless-set-operand": "warn", + "no-useless-string-literal": "warn", + "no-useless-two-nums-quantifier": "warn", + "no-zero-quantifier": "error", + "optimal-lookaround-quantifier": "warn", + "optimal-quantifier-concatenation": "warn", + "prefer-escape-replacement-dollar-char": "warn", + "prefer-predefined-assertion": "warn", + "prefer-quantifier": "warn", + "prefer-range": [ + "warn", + { + "target": "alphanumeric" + } + ], + "prefer-regexp-exec": "off", // Handled by `regexp/prefer-regexp-test` + "prefer-regexp-test": "warn", + "prefer-set-operation": "off", // I have no idea how they work, and regex101 doesn't support them. + "require-unicode-regexp": "off", // No real need to + "require-unicode-sets-regexp": "off", // No real need to + "simplify-set-operations": "warn", + "sort-alternatives": "warn", + "use-ignore-case": "warn", + // [STYLISTIC] + "grapheme-string-literal": "warn", + "hexadecimal-escape": [ + "error", + "never" + ], + "letter-case": "", // TODO + "match-any": [ + "error", + { + "allows": [ + "dotAll" + ] + } + ], + "no-useless-escape": "off", // Handled by `regexp/strict` + "no-useless-non-capturing-group": "warn", + "prefer-character-class": "warn", + "prefer-d": [ + "warn", + { + "insideCharacterClass": "d" + } + ], + "prefer-lookaround": "warn", + "prefer-named-backreference": "error", + "prefer-named-capture-group": "error", + "prefer-named-replacement": "error", + "prefer-plus-quantifier": "warn", + "prefer-question-quantifier": "warn", + "prefer-result-array-groups": "error", + "prefer-star-quantifier": "warn", + "prefer-unicode-codepoint-escapes": "warn", + "prefer-w": "warn", + "sort-character-class-elements": "warn", + "sort-flags": "warn", + "unicode-escape": "off", + "unicode-property": "warn" +} \ No newline at end of file diff --git a/configs/unicorn.jsonc b/configs/unicorn.jsonc index d548c8b..111fd82 100644 --- a/configs/unicorn.jsonc +++ b/configs/unicorn.jsonc @@ -1,6 +1,6 @@ { // [UNICORN] https://github.com/sindresorhus/eslint-plugin-unicorn?/tree/main/.README#rules - "better-regex": "off", // See https://github.com/sindresorhus/eslint-plugin-unicorn/issues/2409 + "better-regex": "off", // See https://github.com/sindresorhus/eslint-plugin-unicorn/issues/2409 "catch-error-name": "off", "consistent-destructuring": "error", "consistent-empty-array-spread": "error", @@ -35,7 +35,7 @@ "no-document-cookie": "error", "no-empty-file": "error", "no-for-loop": "error", - "no-hex-escape": "error", + "no-hex-escape": "off", // Handled by `regexp/hexadecimal-escape` "no-instanceof-array": "error", "no-invalid-fetch-options": "error", "no-invalid-remove-event-listener": "error", @@ -99,7 +99,7 @@ "prefer-json-parse-buffer": "off", "prefer-keyboard-event-key": "error", "prefer-logical-operator-over-ternary": "error", - "prefer-math-min-max":"error", + "prefer-math-min-max": "error", "prefer-math-trunc": "error", "prefer-modern-dom-apis": "error", "prefer-modern-math-apis": "error", @@ -113,7 +113,7 @@ "prefer-prototype-methods": "error", "prefer-query-selector": "error", "prefer-reflect-apply": "error", - "prefer-regexp-test": "error", + "prefer-regexp-test": "off", // Handled by `regexp/prefer-regexp-test` "prefer-set-has": "error", "prefer-set-size": "error", "prefer-spread": "error", diff --git a/eslint.config.js b/eslint.config.js index e1056ee..711d9c1 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -8,6 +8,8 @@ import stylisticPlugin from '@stylistic/eslint-plugin'; import jsdocPlugin from 'eslint-plugin-jsdoc'; import sonarjsPlugin from 'eslint-plugin-sonarjs'; import unicornPlugin from 'eslint-plugin-unicorn'; +import regExPlugin from 'eslint-plugin-regexp'; +import htmlPlugin from 'eslint-plugin-html'; export { plugins }; @@ -28,7 +30,9 @@ const '@stylistic': stylisticPlugin, jsdoc: jsdocPlugin, sonarjs: sonarjsPlugin, - unicorn: unicornPlugin + unicorn: unicornPlugin, + regexp: regExPlugin, + html: htmlPlugin }, rules = { ...importJsonC('configs/eslint.jsonc'), @@ -36,7 +40,8 @@ const ...importJsonC('configs/@stylistic.jsonc'), ...importJsonC('configs/jsdoc.jsonc'), ...importJsonC('configs/sonarjs.jsonc'), - ...importJsonC('configs/unicorn.jsonc') + ...importJsonC('configs/unicorn.jsonc'), + ...importJsonC('configs/regexp.jsonc') }; @@ -50,10 +55,9 @@ export default [ languageOptions: { parser, parserOptions: { - projectService: { - allowDefaultProject: ['*.js', '*.html'] - }, + project: true, tsconfigRootDir: '.', + extraFileExtensions: ['html'], warnOnUnsupportedTypeScriptVersion: true }, ecmaVersion: 'latest', @@ -67,6 +71,9 @@ export default [ linterOptions: { reportUnusedDisableDirectives: 'warn' }, + settings: { + ...importJsonC('configs/html.jsonc') + }, plugins, rules }, { @@ -77,7 +84,20 @@ export default [ { name: 'eslint-config:html', files: ['**/*.html'], - rules: importJsonC('configs/sonarjs-html.jsonc') + languageOptions: { + globals: globals.browser + }, + rules: { + ...importJsonC('configs/sonarjs-html.jsonc') + '@stylistic/no-multiple-empty-lines': [ + 'error', + { + max: 2, + maxBOF: 1 // tag should be on the next line + } }, { name: 'eslint-config:d.ts', diff --git a/package.json b/package.json index 932d686..656635a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@mephisto5558/eslint-config", - "version": "2.0.2", + "version": "2.1.0", "type": "module", "scripts": { "test": "echo \"Error: no test specified\"" @@ -26,7 +26,9 @@ "@typescript-eslint/eslint-plugin": ">=8.8.1", "@typescript-eslint/parser": "^8.8.1", "eslint": "^9.12.0", + "eslint-plugin-html": ">=8.1.2", "eslint-plugin-jsdoc": ">=50.3.2", + "eslint-plugin-regexp": ">=2.6.0", "eslint-plugin-sonarjs": ">=2.0.3", "eslint-plugin-unicorn": ">=56.0.0", "globals": "^15.11.0"