From 29b6825a3aa89b1561291265690407a877e02f2f Mon Sep 17 00:00:00 2001 From: Cliff Su Date: Wed, 9 Nov 2022 22:16:47 +0800 Subject: [PATCH 1/2] feat: implement spell check in separated by underscore words --- README.md | 3 +++ rules/spell-checker.js | 58 +++++++++++++++++++++++++++--------------- test/spell-checker.js | 22 ++++++++++++++-- 3 files changed, 60 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index e4bd8f3..7f7f726 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,9 @@ Check Spelling inside identifiers "ignoreRequire": <>, default: false Exclude `require()` imports from spell-checking. Useful for excluding NPM package name false-positives. +"ignoreUpperCaseUnderscore": <>, default: false +Exclude checking uppercase words separated by an underscore. e.g., `SEARCH_CONDITIONS_LIMIT` + "templates": <>, default: true Check Spelling inside ES6 templates you should enable parser options for ES6 features for this to work Refer to: [specifying-parser-options](http://eslint.org/docs/user-guide/configuring#specifying-parser-options) diff --git a/rules/spell-checker.js b/rules/spell-checker.js index 159cdc0..c2f44c3 100644 --- a/rules/spell-checker.js +++ b/rules/spell-checker.js @@ -73,6 +73,10 @@ module.exports = { type: 'boolean', default: false }, + ignoreUpperCaseUnderscore: { + type: 'boolean', + default: false + }, templates: { type: 'boolean', default: true @@ -111,7 +115,6 @@ module.exports = { additionalProperties: false } ] - }, // create (function) returns an object with methods that ESLint calls to “visit” nodes while traversing the abstract syntax tree (AST as defined by ESTree) of JavaScript code: @@ -164,31 +167,31 @@ module.exports = { } function checkSpelling(aNode, value, spellingType) { - if(!hasToSkip(value)) { + if (!hasToSkip(value)) { // Regular expression matches regexp metacharacters, and any special char var regexp = /(\\[sSwdDB0nfrtv])|\\[0-7][0-7][0-7]|\\x[0-9A-F][0-9A-F]|\\u[0-9A-F][0-9A-F][0-9A-F][0-9A-F]|[^0-9a-zA-Z '’]/g, nodeWords = value.replace(regexp, ' ') - .replace(/([A-Z])/g, ' $1').split(' '), + .replace(/([A-Z])/g, ' $1').split(' '), errors; errors = nodeWords .filter(hasToSkipWord) .filter(isSpellingError) - .filter(function(aWord) { - // Split words by numbers for special cases such as test12anything78variable and to include 2nd and 3rd ordinals - // also for Proper names we convert to lower case in second pass. + .filter(function (aWord) { + // Split words by numbers for special cases such as test12anything78variable and to include 2nd and 3rd ordinals + // also for Proper names we convert to lower case in second pass. var splitByNumberWords = aWord.replace(/[0-9']/g, ' ').replace(/([A-Z])/g, ' $1').toLowerCase().split(' '); return splitByNumberWords.some(isSpellingError); }) - .forEach(function(aWord) { + .forEach(function (aWord) { context.report( aNode, 'You have a misspelled word: {{word}} on {{spellingType}}', { - word: aWord, - spellingType: spellingType - }); + word: aWord, + spellingType: spellingType + }); }); - } } + } function isInImportDeclaration(aNode) { // @see https://buildmedia.readthedocs.org/media/pdf/esprima/latest/esprima.pdf @@ -198,26 +201,39 @@ module.exports = { ); } + function underscoreParser(aNode, value, spellingType) { + if (options.ignoreUpperCaseUnderscore) { + checkSpelling(aNode, value, spellingType); + } else { + const hasUnderscore = value.split('_').length > 1; + const splitValues = value.split('_'); + splitValues.forEach((word) => { + checkSpelling(aNode, hasUnderscore ? word.toLowerCase() : word, spellingType); + }) + } + } + function checkComment(aNode) { - if(options.comments) { - checkSpelling(aNode, aNode.value, 'Comment'); + if (options.comments) { + underscoreParser(aNode, aNode.value, 'Comment'); } } - function checkLiteral(aNode){ - if(options.strings && typeof aNode.value === 'string' && !isInImportDeclaration(aNode)) { - checkSpelling(aNode, aNode.value, 'String'); + function checkLiteral(aNode) { + if (options.strings && typeof aNode.value === 'string' && !isInImportDeclaration(aNode)) { + underscoreParser(aNode, aNode.value, 'String'); } } - function checkTemplateElement(aNode){ - if(options.templates && typeof aNode.value.raw === 'string' && !isInImportDeclaration(aNode)) { - checkSpelling(aNode, aNode.value.raw, 'Template'); + + function checkTemplateElement(aNode) { + if (options.templates && typeof aNode.value.raw === 'string' && !isInImportDeclaration(aNode)) { + underscoreParser(aNode, aNode.value.raw, 'Template'); } } function checkIdentifier(aNode) { - if(options.identifiers) { - checkSpelling(aNode, aNode.name, 'Identifier'); + if (options.identifiers) { + underscoreParser(aNode, aNode.name, 'Identifier'); } } /* Returns true if the string in value has to be skipped for spell checking */ diff --git a/test/spell-checker.js b/test/spell-checker.js index 70a1190..c539f7b 100644 --- a/test/spell-checker.js +++ b/test/spell-checker.js @@ -44,6 +44,16 @@ ruleTester.run('spellcheck/spell-checker', rule, { 'var url = "http://examplus.com"', 'var a = Math.trunc(-0.1)', 'var a = "test", test = `${a}`;', + 'var a = "ADD_SUM";', + 'const SEARCH_CONDITIONS_LIMIT = 9;', + { + code: 'var a = "ADD_SMU"', + options:[{ ignoreUpperCaseUnderscore: true }] + }, + { + code: 'const SEACH_CONDITIONS_LIMIT = 9;', + options:[{ ignoreUpperCaseUnderscore: true }] + }, { code: 'var a = 1 // This is a comment', options: [{lang: 'sym', langDir: __dirname}] @@ -183,7 +193,15 @@ ruleTester.run('spellcheck/spell-checker', rule, { errors: [ { message: 'You have a misspelled word: noooot on Template'}] }, - - + { + code: 'var a = "ADD_SMU"', + errors: [ + { message: 'You have a misspelled word: smu on String'}] + }, + { + code: 'const SEACH_CONDITIONS_LIMIT = 9;', + errors: [ + { message: 'You have a misspelled word: seach on Identifier'}] + }, ] }); From 3ee411e403d2c105ee994d5de8dd4dcd5f58796b Mon Sep 17 00:00:00 2001 From: Cliff Su Date: Fri, 18 Nov 2022 23:47:32 +0800 Subject: [PATCH 2/2] refactor: rename ignoreUpperCaseUnderscore to enableUpperCaseUnderscoreCheck --- README.md | 2 +- rules/spell-checker.js | 7 +++---- test/spell-checker.js | 34 +++++++++++++++++++++++----------- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 7f7f726..4904119 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ Check Spelling inside identifiers "ignoreRequire": <>, default: false Exclude `require()` imports from spell-checking. Useful for excluding NPM package name false-positives. -"ignoreUpperCaseUnderscore": <>, default: false +"enableUpperCaseUnderscoreCheck": <>, default: false Exclude checking uppercase words separated by an underscore. e.g., `SEARCH_CONDITIONS_LIMIT` "templates": <>, default: true diff --git a/rules/spell-checker.js b/rules/spell-checker.js index c2f44c3..8b16e5f 100644 --- a/rules/spell-checker.js +++ b/rules/spell-checker.js @@ -73,7 +73,7 @@ module.exports = { type: 'boolean', default: false }, - ignoreUpperCaseUnderscore: { + enableUpperCaseUnderscoreCheck: { type: 'boolean', default: false }, @@ -202,13 +202,12 @@ module.exports = { } function underscoreParser(aNode, value, spellingType) { - if (options.ignoreUpperCaseUnderscore) { + if (!options.enableUpperCaseUnderscoreCheck) { checkSpelling(aNode, value, spellingType); } else { - const hasUnderscore = value.split('_').length > 1; const splitValues = value.split('_'); splitValues.forEach((word) => { - checkSpelling(aNode, hasUnderscore ? word.toLowerCase() : word, spellingType); + checkSpelling(aNode, word.toLowerCase(), spellingType); }) } } diff --git a/test/spell-checker.js b/test/spell-checker.js index c539f7b..7b9f58d 100644 --- a/test/spell-checker.js +++ b/test/spell-checker.js @@ -15,10 +15,10 @@ var ruleTester = new RuleTester({ }, parserOptions: { - "ecmaVersion": 2018, - "sourceType": "module", + 'ecmaVersion': 2018, + 'sourceType': 'module', ecmaFeatures: { - "modules": true + 'modules': true } } }); @@ -45,15 +45,13 @@ ruleTester.run('spellcheck/spell-checker', rule, { 'var a = Math.trunc(-0.1)', 'var a = "test", test = `${a}`;', 'var a = "ADD_SUM";', + 'var a = "ADD_SMU";', 'const SEARCH_CONDITIONS_LIMIT = 9;', - { - code: 'var a = "ADD_SMU"', - options:[{ ignoreUpperCaseUnderscore: true }] - }, - { - code: 'const SEACH_CONDITIONS_LIMIT = 9;', - options:[{ ignoreUpperCaseUnderscore: true }] - }, + 'const SEACH_CONDITIONS_LIMIT = 9;', + 'const KEY = "HELLO_WORLD";', + 'const KEY = "HELLO_WORDL";', + 'const PASSWORD = "123456";', + 'const PASSWROD = "123456";', { code: 'var a = 1 // This is a comment', options: [{lang: 'sym', langDir: __dirname}] @@ -195,13 +193,27 @@ ruleTester.run('spellcheck/spell-checker', rule, { }, { code: 'var a = "ADD_SMU"', + options:[{ enableUpperCaseUnderscoreCheck: true }], errors: [ { message: 'You have a misspelled word: smu on String'}] }, { code: 'const SEACH_CONDITIONS_LIMIT = 9;', + options:[{ enableUpperCaseUnderscoreCheck: true }], errors: [ { message: 'You have a misspelled word: seach on Identifier'}] }, + { + code: 'const KEY = "HELLO_WORDL";', + options:[{ enableUpperCaseUnderscoreCheck: true }], + errors: [ + { message: 'You have a misspelled word: wordl on String'}] + }, + { + code: 'const PASSWROD = "123456";', + options:[{ enableUpperCaseUnderscoreCheck: true }], + errors: [ + { message: 'You have a misspelled word: passwrod on Identifier'}] + }, ] });