From e463bae7e9555fc1d4a35c6d7e9d2151a858f330 Mon Sep 17 00:00:00 2001 From: Nikolai Katkov Date: Sat, 18 May 2024 11:23:38 +0200 Subject: [PATCH] add regexp plugin --- .eslintrc.yml | 83 ++++++- README.md | 3 +- package-lock.json | 79 +++++++ package.json | 1 + src/config/rulesets.ts | 2 + src/config/rulesets/ruleset.eslint.ts | 4 +- src/config/rulesets/ruleset.regexp.ts | 304 +++++++++++++++++++++++++ src/config/rulesets/ruleset.unicorn.ts | 10 +- src/lib/context/dependencies.ts | 6 +- src/lib/eslint/getConfig.ts | 13 +- src/lib/ignore/saveIgnore.ts | 2 +- 11 files changed, 494 insertions(+), 13 deletions(-) create mode 100644 src/config/rulesets/ruleset.regexp.ts diff --git a/.eslintrc.yml b/.eslintrc.yml index 6036cb9..d38b3f1 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -16,6 +16,7 @@ plugins: - promise - array-func - import + - regexp parserOptions: sourceType: module ecmaVersion: 2021 @@ -206,6 +207,86 @@ rules: promise/param-names: error promise/valid-params: error radix: error + regexp/confusing-quantifier: error + regexp/control-character-escape: error + regexp/grapheme-string-literal: error + regexp/hexadecimal-escape: error + regexp/letter-case: error + regexp/match-any: error + regexp/negation: error + regexp/no-contradiction-with-assertion: error + regexp/no-control-character: error + regexp/no-dupe-characters-character-class: error + regexp/no-dupe-disjunctions: error + regexp/no-empty-alternative: error + regexp/no-empty-capturing-group: error + regexp/no-empty-character-class: error + regexp/no-empty-group: error + regexp/no-empty-lookarounds-assertion: error + regexp/no-empty-string-literal: error + regexp/no-escape-backspace: error + regexp/no-extra-lookaround-assertions: error + regexp/no-invalid-regexp: error + regexp/no-invisible-character: error + regexp/no-lazy-ends: error + regexp/no-legacy-features: error + regexp/no-misleading-capturing-group: error + regexp/no-misleading-unicode-character: error + regexp/no-missing-g-flag: error + regexp/no-non-standard-flag: error + regexp/no-obscure-range: error + regexp/no-octal: error + regexp/no-optional-assertion: error + regexp/no-potentially-useless-backreference: error + regexp/no-standalone-backslash: error + regexp/no-super-linear-backtracking: error + regexp/no-super-linear-move: error + regexp/no-trivially-nested-assertion: error + regexp/no-trivially-nested-quantifier: error + regexp/no-unused-capturing-group: error + regexp/no-useless-assertions: error + regexp/no-useless-backreference: error + regexp/no-useless-character-class: error + regexp/no-useless-dollar-replacements: error + regexp/no-useless-escape: error + regexp/no-useless-flag: error + regexp/no-useless-lazy: error + regexp/no-useless-non-capturing-group: error + regexp/no-useless-quantifier: error + regexp/no-useless-range: error + regexp/no-useless-set-operand: error + regexp/no-useless-string-literal: error + regexp/no-zero-quantifier: error + regexp/optimal-lookaround-quantifier: error + regexp/optimal-quantifier-concatenation: error + regexp/prefer-character-class: error + regexp/prefer-d: + - error + - insideCharacterClass: range + regexp/prefer-escape-replacement-dollar-char: error + regexp/prefer-lookaround: error + regexp/prefer-named-backreference: error + regexp/prefer-named-replacement: error + regexp/prefer-plus-quantifier: error + regexp/prefer-predefined-assertion: error + regexp/prefer-quantifier: error + regexp/prefer-question-quantifier: error + regexp/prefer-regexp-exec: error + regexp/prefer-regexp-test: error + regexp/prefer-result-array-groups: error + regexp/prefer-set-operation: error + regexp/prefer-star-quantifier: error + regexp/prefer-unicode-codepoint-escapes: error + regexp/prefer-w: error + regexp/require-unicode-regexp: error + regexp/simplify-set-operations: error + regexp/sort-alternatives: error + regexp/sort-character-class-elements: error + regexp/sort-flags: error + regexp/strict: error + regexp/unicode-escape: error + regexp/unicode-property: error + regexp/use-ignore-case: error require-atomic-updates: error require-yield: error simple-import-sort/exports: error @@ -238,7 +319,6 @@ rules: - markers: - / symbol-description: error - unicorn/better-regex: error unicorn/catch-error-name: error unicorn/consistent-destructuring: error unicorn/consistent-function-scoping: error @@ -399,6 +479,7 @@ overrides: - '@typescript-eslint' parserOptions: project: true + EXPERIMENTAL_useProjectService: true rules: '@typescript-eslint/adjacent-overload-signatures': error '@typescript-eslint/array-type': diff --git a/README.md b/README.md index d5008fc..0761fd7 100644 --- a/README.md +++ b/README.md @@ -55,8 +55,6 @@ You can achieve best results running `do-me-lint` once or periodically if you wa It makes sense to keep `.domelintrc.yml` as part of your git repository. -For monorepos you need to run the script from each project's directory. - ## Troubleshooting If there are too many warnings to fix in one go: @@ -117,3 +115,4 @@ relaxedRules: - [array-func](https://github.com/freaktechnik/eslint-plugin-array-func) - [import](https://github.com/import-js/eslint-plugin-import) - [Playwright](https://github.com/playwright-community/eslint-plugin-playwright) +- [eslint-plugin-regexp](https://ota-meshi.github.io/) diff --git a/package-lock.json b/package-lock.json index 5ed8ffd..9f4afa3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,6 +41,7 @@ "eslint-plugin-jest": "^27.6.0", "eslint-plugin-playwright": "^0.9.0", "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-regexp": "^2.5.0", "eslint-plugin-simple-import-sort": "^10.0.0", "eslint-plugin-sonarjs": "^0.23.0", "eslint-plugin-unicorn": "^49.0.0", @@ -2535,6 +2536,15 @@ "node": ">= 0.8" } }, + "node_modules/comment-parser": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", + "dev": true, + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -3244,6 +3254,27 @@ "eslint": "^7.0.0 || ^8.0.0" } }, + "node_modules/eslint-plugin-regexp": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-2.5.0.tgz", + "integrity": "sha512-I7vKcP0o75WS5SHiVNXN+Eshq49sbrweMQIuqSL3AId9AwDe9Dhbfug65vw64LxmOd4v+yf5l5Xt41y9puiq0g==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.9.1", + "comment-parser": "^1.4.0", + "jsdoc-type-pratt-parser": "^4.0.0", + "refa": "^0.12.1", + "regexp-ast-analysis": "^0.7.1", + "scslre": "^0.3.0" + }, + "engines": { + "node": "^18 || >=20" + }, + "peerDependencies": { + "eslint": ">=8.44.0" + } + }, "node_modules/eslint-plugin-simple-import-sort": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-10.0.0.tgz", @@ -5539,6 +5570,15 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsdoc-type-pratt-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", + "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", + "dev": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/jsesc": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", @@ -6447,6 +6487,31 @@ "node": ">= 6" } }, + "node_modules/refa": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/refa/-/refa-0.12.1.tgz", + "integrity": "sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.8.0" + }, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/regexp-ast-analysis": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/regexp-ast-analysis/-/regexp-ast-analysis-0.7.1.tgz", + "integrity": "sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.8.0", + "refa": "^0.12.1" + }, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, "node_modules/regexp-tree": { "version": "0.1.27", "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", @@ -6718,6 +6783,20 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/scslre": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/scslre/-/scslre-0.3.0.tgz", + "integrity": "sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.8.0", + "refa": "^0.12.0", + "regexp-ast-analysis": "^0.7.0" + }, + "engines": { + "node": "^14.0.0 || >=16.0.0" + } + }, "node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", diff --git a/package.json b/package.json index b01067e..873fba6 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "eslint-plugin-jest": "^27.6.0", "eslint-plugin-playwright": "^0.9.0", "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-regexp": "^2.5.0", "eslint-plugin-simple-import-sort": "^10.0.0", "eslint-plugin-sonarjs": "^0.23.0", "eslint-plugin-unicorn": "^49.0.0", diff --git a/src/config/rulesets.ts b/src/config/rulesets.ts index 1541875..7912838 100644 --- a/src/config/rulesets.ts +++ b/src/config/rulesets.ts @@ -8,6 +8,7 @@ import { ruleset as playwright } from './rulesets/ruleset.playwright' import { ruleset as promise } from './rulesets/ruleset.promise' import { ruleset as react } from './rulesets/ruleset.react' import { ruleset as reactHooks } from './rulesets/ruleset.react-hooks' +import { ruleset as regexp } from './rulesets/ruleset.regexp' import { ruleset as simpleSort } from './rulesets/ruleset.simple-import-sort' import { ruleset as sonarjs } from './rulesets/ruleset.sonarjs' import { ruleset as typescript } from './rulesets/ruleset.typescript' @@ -29,4 +30,5 @@ export const ruleset: Record = { ...arrayFunction, ...importPlugin, ...playwright, + ...regexp, } diff --git a/src/config/rulesets/ruleset.eslint.ts b/src/config/rulesets/ruleset.eslint.ts index 78c805c..dc295e4 100644 --- a/src/config/rulesets/ruleset.eslint.ts +++ b/src/config/rulesets/ruleset.eslint.ts @@ -405,7 +405,7 @@ export const ruleset: Record = { enabled: true, }, 'prefer-named-capture-group': { - enabled: false, // in practice most regexps don't need it and migration takes ages + enabled: false, // in practice most regexps don't need it and migration takes ages; also there is better regexp/prefer-named-capture-group }, 'prefer-object-has-own': { enabled: false, // until Object.hasOwn stops being experimental: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn#browser_compatibility @@ -425,7 +425,7 @@ export const ruleset: Record = { scope: 'js', // @typescript-eslint/require-await }, 'require-unicode-regexp': { - enabled: false, // reports even for latin-only regexps, annoying in webpack config + enabled: false, // superceded by regexp/require-unicode-regexp and regexp/require-unicode-sets-regexp }, 'vars-on-top': { enabled: false, // doesn't make sense in ES6 world diff --git a/src/config/rulesets/ruleset.regexp.ts b/src/config/rulesets/ruleset.regexp.ts new file mode 100644 index 0000000..d013f44 --- /dev/null +++ b/src/config/rulesets/ruleset.regexp.ts @@ -0,0 +1,304 @@ +import type { Rule } from '../../lib/eslint/rulesConfig' + +export const ruleset: Record = { + // Possible Errors + 'regexp/no-contradiction-with-assertion': { + enabled: true, + }, + 'regexp/no-control-character': { + enabled: true, + }, + 'regexp/no-dupe-disjunctions': { + enabled: true, + }, + 'regexp/no-empty-alternative': { + enabled: true, + }, + 'regexp/no-empty-capturing-group': { + enabled: true, + }, + 'regexp/no-empty-character-class': { + enabled: true, + }, + 'regexp/no-empty-group': { + enabled: true, + }, + 'regexp/no-empty-lookarounds-assertion': { + enabled: true, + }, + 'regexp/no-escape-backspace': { + enabled: true, + }, + 'regexp/no-invalid-regexp': { + enabled: true, + }, + 'regexp/no-lazy-ends': { + enabled: true, + }, + 'regexp/no-misleading-capturing-group': { + enabled: true, + }, + 'regexp/no-misleading-unicode-character': { + enabled: true, + // fixable: true, https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-misleading-unicode-character.html#options + }, + 'regexp/no-missing-g-flag': { + enabled: true, + fixable: true, + }, + 'regexp/no-optional-assertion': { + enabled: true, + }, + 'regexp/no-potentially-useless-backreference': { + enabled: true, + }, + 'regexp/no-super-linear-backtracking': { + enabled: true, + fixable: true, + }, + 'regexp/no-super-linear-move': { + enabled: true, + }, + 'regexp/no-useless-assertions': { + enabled: true, + }, + 'regexp/no-useless-backreference': { + enabled: true, + }, + 'regexp/no-useless-dollar-replacements': { + enabled: true, + }, + 'regexp/strict': { + enabled: true, + fixable: true, + }, + + // Best Practices + 'regexp/confusing-quantifier': { + enabled: true, + }, + 'regexp/control-character-escape': { + enabled: true, + fixable: true, + }, + 'regexp/negation': { + enabled: true, + fixable: true, + }, + 'regexp/no-dupe-characters-character-class': { + enabled: true, + fixable: true, + }, + 'regexp/no-empty-string-literal': { + enabled: true, // don't quite understand it though, apols + }, + 'regexp/no-extra-lookaround-assertions': { + enabled: true, + fixable: true, + }, + 'regexp/no-invisible-character': { + enabled: true, + fixable: true, + }, + 'regexp/no-legacy-features': { + enabled: true, + }, + 'regexp/no-non-standard-flag': { + enabled: true, + }, + 'regexp/no-obscure-range': { + enabled: true, + }, + 'regexp/no-octal': { + enabled: true, + }, + 'regexp/no-standalone-backslash': { + enabled: true, + }, + 'regexp/no-trivially-nested-assertion': { + enabled: true, + fixable: true, + }, + 'regexp/no-trivially-nested-quantifier': { + enabled: true, + fixable: true, + }, + 'regexp/no-unused-capturing-group': { + enabled: true, + fixable: true, + }, + 'regexp/no-useless-character-class': { + enabled: true, + fixable: true, + }, + 'regexp/no-useless-flag': { + enabled: true, + fixable: true, + }, + 'regexp/no-useless-lazy': { + enabled: true, + fixable: true, + }, + 'regexp/no-useless-quantifier': { + enabled: true, + fixable: true, + }, + 'regexp/no-useless-range': { + enabled: true, + fixable: true, + }, + 'regexp/no-useless-set-operand': { + enabled: true, + fixable: true, + }, + 'regexp/no-useless-string-literal': { + enabled: true, + fixable: true, + }, + 'regexp/no-zero-quantifier': { + enabled: true, + fixable: true, + }, + 'regexp/optimal-lookaround-quantifier': { + enabled: true, + }, + 'regexp/optimal-quantifier-concatenation': { + enabled: true, + fixable: true, + }, + 'regexp/prefer-escape-replacement-dollar-char': { + enabled: true, + }, + 'regexp/prefer-predefined-assertion': { + enabled: true, + fixable: true, + }, + 'regexp/prefer-quantifier': { + enabled: true, // opinionated, but as per today it seems more readable to have numbers, especially with autofixes + fixable: true, + }, + 'regexp/prefer-regexp-exec': { + enabled: true, + }, + 'regexp/prefer-regexp-test': { + enabled: true, + fixable: true, + }, + 'regexp/prefer-set-operation': { + enabled: true, + fixable: true, + }, + 'regexp/require-unicode-regexp': { + enabled: true, // supercedes require-unicode-regexp + fixable: true, + }, + 'regexp/require-unicode-sets-regexp': { + enabled: false, // breaks vitest (https://github.com/vitest-dev/vitest/issues/5220); works as expected only with regexp/require-unicode-regexp turned on (they even have this: https://github.com/ota-meshi/eslint-plugin-regexp/pull/598/files#diff-b4c4c12d6d85db6f07b5b67c694b10fc77c9d6b33b39a5acf1a47a1e39579bcaR79) + fixable: true, + }, + 'regexp/simplify-set-operations': { + enabled: true, + fixable: true, + }, + 'regexp/sort-alternatives': { + enabled: true, + fixable: true, + }, + 'regexp/use-ignore-case': { + enabled: true, + fixable: true, + }, + + // Stylistic issues + 'regexp/grapheme-string-literal': { + enabled: true, + }, + 'regexp/hexadecimal-escape': { + fixable: true, + enabled: true, + }, + 'regexp/letter-case': { + fixable: true, + enabled: true, + }, + 'regexp/match-any': { + enabled: true, + fixable: true, + }, + 'regexp/no-useless-escape': { + enabled: true, + fixable: true, + }, + 'regexp/no-useless-non-capturing-group': { + enabled: true, + fixable: true, + }, + 'regexp/prefer-character-class': { + enabled: true, + fixable: true, + }, + 'regexp/prefer-d': { + enabled: true, + fixable: true, + options: { + insideCharacterClass: 'range', + }, + }, + 'regexp/prefer-lookaround': { + enabled: true, + fixable: true, + }, + 'regexp/prefer-named-backreference': { + // similar to regexp/prefer-named-replacement + enabled: true, + fixable: true, + }, + 'regexp/prefer-named-capture-group': { + enabled: false, // in practice most regexps don't need it and migration takes ages + }, + 'regexp/prefer-named-replacement': { + // similar to regexp/prefer-named-backreference + enabled: true, + fixable: true, + }, + 'regexp/prefer-plus-quantifier': { + enabled: true, + fixable: true, + }, + 'regexp/prefer-question-quantifier': { + enabled: true, + fixable: true, + }, + 'regexp/prefer-result-array-groups': { + enabled: true, + fixable: true, + }, + 'regexp/prefer-star-quantifier': { + enabled: true, + fixable: true, + }, + 'regexp/prefer-unicode-codepoint-escapes': { + enabled: true, + fixable: true, + }, + 'regexp/prefer-w': { + enabled: true, + fixable: true, + }, + 'regexp/sort-character-class-elements': { + enabled: true, + fixable: true, + }, + 'regexp/sort-flags': { + enabled: true, + fixable: true, + }, + 'regexp/unicode-escape': { + enabled: true, + fixable: true, + }, + 'regexp/unicode-property': { + enabled: true, + fixable: true, + }, +} diff --git a/src/config/rulesets/ruleset.unicorn.ts b/src/config/rulesets/ruleset.unicorn.ts index f0a696f..5a11cb6 100644 --- a/src/config/rulesets/ruleset.unicorn.ts +++ b/src/config/rulesets/ruleset.unicorn.ts @@ -1,8 +1,16 @@ import type { Rule } from '../../lib/eslint/rulesConfig' export const ruleset: Record = { + /* the rule is actually great and has autofixing, but I still preferred eslint-plugin-regexp plugin + * with more granular settings and level of nerdiness that is pretty much in + * do-me-lint's spirit, and excellent documentation for each rule (just look at + * https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-super-linear-move.html). + * + * This decision may change in the future, dependent on the developlment of both plugins, + * see https://github.com/ota-meshi/eslint-plugin-regexp/issues/445#issuecomment-1173361584 + */ 'unicorn/better-regex': { - enabled: true, + enabled: false, // overlaps with regexp/*, see above fixable: true, }, 'unicorn/catch-error-name': { diff --git a/src/lib/context/dependencies.ts b/src/lib/context/dependencies.ts index e275982..d64e2e4 100644 --- a/src/lib/context/dependencies.ts +++ b/src/lib/context/dependencies.ts @@ -1,5 +1,3 @@ -/* eslint-disable no-continue */ -import type { LockFileObject } from '@yarnpkg/lockfile' import { parse as parseYarnLock } from '@yarnpkg/lockfile' import fs from 'fs' import yaml from 'js-yaml' @@ -39,7 +37,7 @@ const getNpmPackages = (projectDirectory: string): InstalledPackage[] => { for (const packageNameWithPath in packageLock.packages) { if (Object.prototype.hasOwnProperty.call(packageLock.packages, packageNameWithPath)) { const dependencyInfo = packageLock.packages[packageNameWithPath] - const packageNameMatch = packageNameWithPath.match(/\/(?(?:@.*?\/)?[^/]*?)$/u) + const packageNameMatch = /\/(?(?:@.*?\/)?[^/]*)$/u.exec(packageNameWithPath) if (packageNameMatch?.groups === undefined) { console.error(packageNameWithPath) continue @@ -68,7 +66,7 @@ const getYarnPackages = ( if (!Object.prototype.hasOwnProperty.call(lockFileObject, dependencyWithVersion)) { continue } - const match = dependencyWithVersion.match(/^(?.*?)@(?[^@]+)$/u) + const match = /^(?.*?)@(?[^@]+)$/u.exec(dependencyWithVersion) if (!match?.groups) { continue } diff --git a/src/lib/eslint/getConfig.ts b/src/lib/eslint/getConfig.ts index 84e55b9..1ca9ee6 100644 --- a/src/lib/eslint/getConfig.ts +++ b/src/lib/eslint/getConfig.ts @@ -63,7 +63,15 @@ const maybeObject = (object: T): T | undefined => const getPlugins = (projectDependencies: string[]): ByScope => { const plugins: ByScope = { all: [], js: [], ts: [], testJest: [], yaml: [] } - plugins.all.push('simple-import-sort', 'unicorn', 'sonarjs', 'promise', 'array-func', 'import') + plugins.all.push( + 'simple-import-sort', + 'unicorn', + 'sonarjs', + 'promise', + 'array-func', + 'import', + 'regexp' + ) plugins.yaml.push('yml') if (projectDependencies.includes('react')) { @@ -229,7 +237,8 @@ const getDependencies = (projectDependencies: string[]): ExactDependency[] => { ['eslint-plugin-promise', '6.1.1'], ['eslint-plugin-yml', '1.10.0'], ['eslint-plugin-array-func', '4.0.0'], - ['eslint-plugin-import', '2.29.0'] + ['eslint-plugin-import', '2.29.0'], + ['eslint-plugin-regexp', '2.5.0'] ) if (projectDependencies.includes('babel')) { diff --git a/src/lib/ignore/saveIgnore.ts b/src/lib/ignore/saveIgnore.ts index 31310bf..ed28b19 100644 --- a/src/lib/ignore/saveIgnore.ts +++ b/src/lib/ignore/saveIgnore.ts @@ -26,7 +26,7 @@ export const saveIgnore = ({ ignoreFileName, projectDirectory, gitignore }: Para if (fileExists(filename)) { const oldContent = fs.readFileSync(filename, 'utf8') - const match = oldContent.match(/# >>> domelint-start.*# <<< domelint-end/su) + const match = /# >>> domelint-start.*# <<< domelint-end/su.exec(oldContent) if (match) { const [oldInset] = match newContent = oldContent.replace(oldInset, newInset)