diff --git a/.changeset/healthy-needles-boil.md b/.changeset/healthy-needles-boil.md new file mode 100644 index 00000000..de3a1476 --- /dev/null +++ b/.changeset/healthy-needles-boil.md @@ -0,0 +1,6 @@ +--- +"@git-validator/eslint-config": patch +"@git-validator/eslint-plugin": patch +--- + +feat: add rule `@git-validator/no-unnecessary-template-string` diff --git a/packages/eslint-config/src/javascript-config.ts b/packages/eslint-config/src/javascript-config.ts index d334a35f..ab823a41 100644 --- a/packages/eslint-config/src/javascript-config.ts +++ b/packages/eslint-config/src/javascript-config.ts @@ -317,7 +317,7 @@ export default { { patterns: [ { - group: [`*.d.js`, `*.d.cjs`, `*.d.mjs`, `*.d.jsx`], + group: ["*.d.js", "*.d.cjs", "*.d.mjs", "*.d.jsx"], message: "Do not import from a declaration style file", }, { @@ -411,6 +411,7 @@ export default { "@git-validator/no-instanceof-builtin": "error", "@git-validator/no-legacy-getter-setter": "error", "@git-validator/no-relative-parent-imports": "error", + "@git-validator/no-unnecessary-template-string": "error", "@git-validator/prefer-global-this": "error", "@git-validator/prefer-shortest-relative-path": "error", "@git-validator/require-reduce-initial-value": "error", diff --git a/packages/eslint-plugin/src/index.ts b/packages/eslint-plugin/src/index.ts index 0974a11e..58fdf90c 100644 --- a/packages/eslint-plugin/src/index.ts +++ b/packages/eslint-plugin/src/index.ts @@ -11,6 +11,7 @@ import noInstanceofBuiltin from "./rules/no-instanceof-builtin.js"; import noLegacyGetterSetter from "./rules/no-legacy-getter-setter.js"; import noPropertyDecorator from "./rules/no-property-decorator.js"; import noRelativeParentImports from "./rules/no-relative-parent-imports.js"; +import noUnnecessaryTemplateString from "./rules/no-unnecessary-template-string.js"; import noUntypedEmptyArray from "./rules/no-untyped-empty-array.js"; import preferGlobalThis from "./rules/prefer-global-this.js"; import preferShortestRelativePath from "./rules/prefer-shortest-relative-path.js"; @@ -31,6 +32,7 @@ export default { [noLegacyGetterSetter.name]: noLegacyGetterSetter.rule, [noPropertyDecorator.name]: noPropertyDecorator.rule, [noRelativeParentImports.name]: noRelativeParentImports.rule, + [noUnnecessaryTemplateString.name]: noUnnecessaryTemplateString.rule, [noUntypedEmptyArray.name]: noUntypedEmptyArray.rule, [preferGlobalThis.name]: preferGlobalThis.rule, [preferShortestRelativePath.name]: preferShortestRelativePath.rule, diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-template-string.spec.ts b/packages/eslint-plugin/src/rules/no-unnecessary-template-string.spec.ts new file mode 100644 index 00000000..186857f0 --- /dev/null +++ b/packages/eslint-plugin/src/rules/no-unnecessary-template-string.spec.ts @@ -0,0 +1,16 @@ +import rule from "./no-unnecessary-template-string.js"; +import { test } from "./utils.spec.js"; + +const valid = [ + "'abc'", + '"def"', + "`ab${cd}ef`", // eslint-disable-line no-template-curly-in-string + "`\n`", + "`abc\n`", + "`\nabc`", + "`a\nbc`", +]; + +const invalid = ["``", "`abc`", "`abc\\n`", "`\\nabc`", "`a\\nbc`"]; + +test({ valid, invalid, ...rule }); diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-template-string.ts b/packages/eslint-plugin/src/rules/no-unnecessary-template-string.ts new file mode 100644 index 00000000..cd35fb67 --- /dev/null +++ b/packages/eslint-plugin/src/rules/no-unnecessary-template-string.ts @@ -0,0 +1,18 @@ +import { createSimpleRule, getRuleName } from "../utils.js"; + +export default createSimpleRule({ + name: getRuleName(import.meta.url), + message: + "Disallow using template string when it's unnecessary. Use normal literal string expression instead.", + create: (context) => ({ + TemplateLiteral: (node) => { + if ( + node.quasis.length === 1 && + node.expressions.length === 0 && + node.loc.start.line === node.loc.end.line + ) { + context.reportNode(node); + } + }, + }), +});