diff --git a/src/rules/jsxUseTranslationFunctionRule.ts b/src/rules/jsxUseTranslationFunctionRule.ts index dfaea4a..c7fd608 100644 --- a/src/rules/jsxUseTranslationFunctionRule.ts +++ b/src/rules/jsxUseTranslationFunctionRule.ts @@ -24,6 +24,8 @@ interface IOptions { allowHtmlEntities: boolean; } +const htmlEntityRegex = /(&(?:#[0-9]+|[a-zA-Z]+);)/; + export class Rule extends Lint.Rules.AbstractRule { /* tslint:disable:object-literal-sort-keys */ public static metadata: Lint.IRuleMetadata = { @@ -99,17 +101,23 @@ function isInvalidText(text: string, options: Readonly) { return false; } - let invalid = true; - - if (options.allowPunctuation) { - invalid = /\w/.test(t); + if (options.allowPunctuation && t.indexOf("&") === -1) { + // fast path: any punctuation that is not potentially an HTML entity + return /\w/.test(t); } - if (options.allowHtmlEntities && t.indexOf("&") !== -1) { - invalid = t.split("&") - .filter((entity) => entity !== "") - .some((entity) => /^&(?:#[0-9]+|[a-zA-Z]+);$/.test(`&${entity}`) !== true); - } + // split the text into HTML entities and everything else so we can test each part of the string individually + const parts = t.split(htmlEntityRegex).filter((entity) => entity !== ""); + + return parts.some((entity) => { + if (options.allowHtmlEntities && htmlEntityRegex.test(entity)) { + return false; + } + + if (options.allowPunctuation) { + return /\w/.test(entity); + } - return invalid; + return true; + }); } diff --git a/test/rules/jsx-use-translation-function/allow-both/test.tsx.lint b/test/rules/jsx-use-translation-function/allow-both/test.tsx.lint new file mode 100644 index 0000000..d7cc396 --- /dev/null +++ b/test/rules/jsx-use-translation-function/allow-both/test.tsx.lint @@ -0,0 +1,66 @@ +
Hello world!
+ ~~~~~~~~~~~~ [0] + +
{'Hello world!'}
+ ~~~~~~~~~~~~~~~~ [0] + +
{translate('hello-world')}
+ + + + ~~~~~~ [1] + + + + ~~~~~~~~ [1] + +
+
{translate('hi')}
+
+ +
+ {translate('this')}is bad + ~~~~~~ [0] +
+ +
{`foo`}
+ ~~~~~~~ [0] + +
{`foo ${1}`}
+ + + +
-
+ +
&
+ +
+ +
+ ~~~~~~ [0] + +
{' - '}
+ + + +
 
+ +
{' '}
+ + + +
hello - world
+ ~~~~~~~~~~~~~ [0] + +
hello world
+ ~~~~~~~~~~~~~~~~ [0] + +[0]: String literals are disallowed as JSX. Use a translation function +[1]: String literal is not allowed for value of placeholder. Use a translation function diff --git a/test/rules/jsx-use-translation-function/allow-both/tslint.json b/test/rules/jsx-use-translation-function/allow-both/tslint.json new file mode 100644 index 0000000..b9b56e2 --- /dev/null +++ b/test/rules/jsx-use-translation-function/allow-both/tslint.json @@ -0,0 +1,7 @@ +{ + "rules": { + "jsx-use-translation-function": { + "options": ["allow-punctuation", "allow-htmlentities"] + } + } +} diff --git a/test/rules/jsx-use-translation-function/allow-htmlentities/test.tsx.lint b/test/rules/jsx-use-translation-function/allow-htmlentities/test.tsx.lint index 827d78a..a4c63d0 100644 --- a/test/rules/jsx-use-translation-function/allow-htmlentities/test.tsx.lint +++ b/test/rules/jsx-use-translation-function/allow-htmlentities/test.tsx.lint @@ -48,9 +48,17 @@
 
+
  
+
{' '}
+
hello - world
+ ~~~~~~~~~~~~~ [0] + +
hello world
+ ~~~~~~~~~~~~~~~~ [0] + [0]: String literals are disallowed as JSX. Use a translation function [1]: String literal is not allowed for value of placeholder. Use a translation function diff --git a/test/rules/jsx-use-translation-function/allow-punctuation/test.tsx.lint b/test/rules/jsx-use-translation-function/allow-punctuation/test.tsx.lint index d8f8e12..69009e2 100644 --- a/test/rules/jsx-use-translation-function/allow-punctuation/test.tsx.lint +++ b/test/rules/jsx-use-translation-function/allow-punctuation/test.tsx.lint @@ -39,6 +39,11 @@
-
+
&
+ +
+ ~~~~~~~ [0] +
{' - '}
@@ -52,5 +57,11 @@ ~~~~~~~~ [1] +
hello - world
+ ~~~~~~~~~~~~~ [0] + +
hello world
+ ~~~~~~~~~~~~~~~~ [0] + [0]: String literals are disallowed as JSX. Use a translation function [1]: String literal is not allowed for value of placeholder. Use a translation function