diff --git a/docs/rules/no-bare-strings-in-template.md b/docs/rules/no-bare-strings-in-template.md index df1fae123..23a23c116 100644 --- a/docs/rules/no-bare-strings-in-template.md +++ b/docs/rules/no-bare-strings-in-template.md @@ -12,7 +12,7 @@ since: v7.0.0 ## :book: Rule Details -This rule disallows the use of bare strings in `<template>`. +This rule disallows the use of bare strings in `<template>`. In order to be able to internationalize your application, you will need to avoid using plain strings in your templates. Instead, you would need to use a template helper specializing in translation. This rule was inspired by [no-bare-strings rule in ember-template-lint](https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/rule/no-bare-strings.md). @@ -50,7 +50,7 @@ This rule was inspired by [no-bare-strings rule in ember-template-lint](https:// </eslint-code-block> :::tip -This rule does not check for string literals, in bindings and mustaches interpolation. This is because it looks like a conscious decision. +This rule does not check for string literals, in bindings and mustaches interpolation. This is because it looks like a conscious decision. If you want to report these string literals, enable the [vue/no-useless-v-bind] and [vue/no-useless-mustaches] rules and fix the useless string literals. ::: @@ -72,7 +72,7 @@ If you want to report these string literals, enable the [vue/no-useless-v-bind] } ``` -- `allowlist` ... An array of allowed strings. +- `allowlist` ... An array of allowed strings or regular expression patterns (e.g. `/\d+/` to allow numbers). - `attributes` ... An object whose keys are tag name or patterns and value is an array of attributes to check for that tag name. - `directives` ... An array of directive names to check literal value. diff --git a/lib/rules/no-bare-strings-in-template.js b/lib/rules/no-bare-strings-in-template.js index 1c75f5092..8e4acc96d 100644 --- a/lib/rules/no-bare-strings-in-template.js +++ b/lib/rules/no-bare-strings-in-template.js @@ -149,17 +149,33 @@ module.exports = { */ const opts = context.options[0] || {} /** @type {string[]} */ - const allowlist = opts.allowlist || DEFAULT_ALLOWLIST + const rawAllowlist = opts.allowlist || DEFAULT_ALLOWLIST const attributes = parseTargetAttrs(opts.attributes || DEFAULT_ATTRIBUTES) const directives = opts.directives || DEFAULT_DIRECTIVES - const allowlistRe = new RegExp( - allowlist - .map((w) => regexp.escape(w)) - .sort((a, b) => b.length - a.length) - .join('|'), - 'gu' - ) + /** @type {string[]} */ + const stringAllowlist = [] + /** @type {RegExp[]} */ + const regexAllowlist = [] + + for (const item of rawAllowlist) { + if (regexp.isRegExp(item)) { + regexAllowlist.push(regexp.toRegExp(item)) + } else { + stringAllowlist.push(item) + } + } + + const allowlistRe = + stringAllowlist.length > 0 + ? new RegExp( + stringAllowlist + .map((w) => regexp.escape(w)) + .sort((a, b) => b.length - a.length) + .join('|'), + 'gu' + ) + : null /** @type {ElementStack | null} */ let elementStack = null @@ -168,7 +184,21 @@ module.exports = { * @param {string} str */ function getBareString(str) { - return str.trim().replace(allowlistRe, '').trim() + let result = str.trim() + + if (allowlistRe) { + result = result.replace(allowlistRe, '') + } + + for (const regex of regexAllowlist) { + const flags = regex.flags.includes('g') + ? regex.flags + : `${regex.flags}g` + const globalRegex = new RegExp(regex.source, flags) + result = result.replace(globalRegex, '') + } + + return result.trim() } /** diff --git a/tests/lib/rules/no-bare-strings-in-template.js b/tests/lib/rules/no-bare-strings-in-template.js index 4c6c89c7c..6706aaae0 100644 --- a/tests/lib/rules/no-bare-strings-in-template.js +++ b/tests/lib/rules/no-bare-strings-in-template.js @@ -132,6 +132,32 @@ tester.run('no-bare-strings-in-template', rule, { </template> `, options: [{ allowlist: ['@@'] }] + }, + // regex + { + code: ` + <template> + <h1>123 321</h1> + </template> + `, + options: [{ allowlist: [String.raw`/\d+/g`] }] + }, + { + code: ` + <template> + <h1>$foo</h1> + <h1>$bar</h1> + </template> + `, + options: [{ allowlist: [String.raw`/\$\w+/`] }] + }, + { + code: ` + <template> + <h1>foo123foo</h1> + </template> + `, + options: [{ allowlist: [String.raw`/\d+/`, 'foo'] }] } ], invalid: [ @@ -316,6 +342,40 @@ tester.run('no-bare-strings-in-template', rule, { endColumn: 34 } ] + }, + { + code: ` + <template> + <h1>123, foo is invalid, 321</h1> + </template> + `, + options: [{ allowlist: [String.raw`/^\d+$/g`] }], + errors: [ + { + messageId: 'unexpected', + line: 3, + column: 13, + endLine: 3, + endColumn: 37 + } + ] + }, + { + code: ` + <template> + <h1>foo123bar</h1> + </template> + `, + options: [{ allowlist: [String.raw`/\d+/`, 'foo'] }], + errors: [ + { + messageId: 'unexpected', + line: 3, + column: 13, + endLine: 3, + endColumn: 22 + } + ] } ] })