From 08ae48b655fa61dc9a92c3bed0a65d16a4c16017 Mon Sep 17 00:00:00 2001 From: Edvard Chen Date: Sat, 7 May 2022 14:52:59 +0800 Subject: [PATCH] feat: support option jsx-attributes --- lib/helper/shouldSkip.js | 17 +++++------ lib/rules/no-literal-string.js | 45 ++++------------------------ tests/lib/rules/no-literal-string.js | 36 ++++++++++++---------- 3 files changed, 33 insertions(+), 65 deletions(-) diff --git a/lib/helper/shouldSkip.js b/lib/helper/shouldSkip.js index bee8ebb..2670322 100644 --- a/lib/helper/shouldSkip.js +++ b/lib/helper/shouldSkip.js @@ -1,16 +1,13 @@ const matchPatterns = require('./matchPatterns'); module.exports = function shouldSkip({ exclude = [], include = [] }, text) { - let skipped = 0; - if (exclude.length) { - if (matchPatterns(exclude, text)) { - skipped++; + if (include.length || exclude.length) { + if ( + (!exclude.length || matchPatterns(exclude, text)) && + !matchPatterns(include, text) + ) { + return true; } } - if (include.length) { - if (matchPatterns(include, text)) { - skipped--; - } - } - return skipped > 0; + return false; }; diff --git a/lib/rules/no-literal-string.js b/lib/rules/no-literal-string.js index 4275216..b1d7cee 100644 --- a/lib/rules/no-literal-string.js +++ b/lib/rules/no-literal-string.js @@ -5,12 +5,7 @@ 'use strict'; const _ = require('lodash'); -const { - isUpperCase, - generateFullMatchRegExp, - isAllowedDOMAttr, - shouldSkip, -} = require('../helper'); +const { isUpperCase, isAllowedDOMAttr, shouldSkip } = require('../helper'); //------------------------------------------------------------------------------ // Rule Definition @@ -29,20 +24,16 @@ module.exports = { create(context) { // variables should be defined here const { parserServices } = context; - const options = _.defaultsDeep( + const options = _.defaults( {}, context.options[0], require('../options/defaults.json') ); const { - onlyAttribute = [], markupOnly: _markupOnly, validateTemplate, ignoreComponent = [], - ignoreAttribute = [], - ignoreProperty = [], - ignoreCallee = [], } = options; const message = 'disallow literal string'; @@ -64,7 +55,6 @@ module.exports = { } function isValidFunctionCall({ callee }) { - let calleeName = callee.name; if (callee.type === 'Import') return true; const sourceText = context.getSourceCode().getText(callee); @@ -72,36 +62,12 @@ module.exports = { return shouldSkip(options.callees, sourceText); } - const ignoredClassProperties = ['displayName']; - - const userJSXAttrs = [ - 'className', - 'styleName', - 'style', - 'type', - 'key', - 'id', - 'width', - 'height', - - ...ignoreAttribute, - ]; - function isValidAttrName(name) { - if (onlyAttribute.length) { - // only validate those attributes in onlyAttribute option - return !onlyAttribute.includes(name); - } - return userJSXAttrs.includes(name); - } - // Ignore the Trans component for react-i18next compatibility const ignoredComponents = ['Trans', ...ignoreComponent]; //---------------------------------------------------------------------- // Public //---------------------------------------------------------------------- - const visited = new WeakSet(); - function getNearestAncestor(node, type) { let temp = node.parent; while (temp) { @@ -164,8 +130,7 @@ module.exports = { context.report({ node, message }); } - // onlyAttribute would turn on markOnly - const markupOnly = _markupOnly || !!onlyAttribute.length; + const markupOnly = _markupOnly; function endIndicator() { indicatorStack.pop(); @@ -224,7 +189,7 @@ module.exports = { const attrName = node.name.name; // allow - if (isValidAttrName(attrName)) { + if (shouldSkip(options['jsx-attributes'], attrName)) { indicatorStack.push(true); return; } @@ -286,7 +251,7 @@ module.exports = { ClassProperty(node) { indicatorStack.push( - !!(node.key && ignoredClassProperties.includes(node.key.name)) + !!(node.key && shouldSkip(options['class-properties'], node.key.name)) ); }, 'ClassProperty:exit': endIndicator, diff --git a/tests/lib/rules/no-literal-string.js b/tests/lib/rules/no-literal-string.js index 629473a..46af9f9 100644 --- a/tests/lib/rules/no-literal-string.js +++ b/tests/lib/rules/no-literal-string.js @@ -57,30 +57,34 @@ ruleTester.run('no-literal-string', rule, { encoding: 'utf8', }), }, - { code: '
', options: [{ ignoreAttribute: ['foo'] }] }, + { + code: '
', + options: [{ 'jsx-attributes': { exclude: ['foo'] } }], + }, { code: 'foo', options: [{ ignoreComponent: ['Icon'] }] }, { code: 'arrow', options: [{ ignoreComponent: ['Icon'] }] }, { code: `a + "b" -const c =
{import("abc")}
-const d =
{[].map(item=>"abc")}
-const e =
{"hello" + "world"}
-const f =
- `, + const c =
{import("abc")}
+ const d =
{[].map(item=>"abc")}
+ const e =
{"hello" + "world"}
+ const f =
+ `, options: [{ markupOnly: true }], }, { - code: '
', - options: [{ markupOnly: true, ignoreAttribute: ['foo'] }], + code: '
', + options: [{ markupOnly: true, 'jsx-attributes': { exclude: ['foo'] } }], + }, + { + code: '
', + options: [{ 'jsx-attributes': { include: ['bar'] } }], }, - // when onlyAttribute was configured, the markOnly would be treated as true - { code: 'const a = "foo";', options: [{ onlyAttribute: ['bar'] }] }, - { code: '
', options: [{ onlyAttribute: ['bar'] }] }, { code: `import(\`hello\`); - var a = \`12345\` - var a = \`\` - `, + var a = \`12345\` + var a = \`\` + `, options: [{ validateTemplate: true }], }, ], @@ -175,7 +179,9 @@ const tsTester = new RuleTester({ tsTester.run('no-literal-string', rule, { valid: [ - { code: `declare module 'country-emoji' {}` }, + { + code: `declare module 'country-emoji' {}`, + }, { code: '
', filename: 'a.tsx' }, { code: "var a: Element['nodeName']" }, { code: "var a: Omit" },