From 2fe2c96e3dee74a7d08d8e509300abaef651fb99 Mon Sep 17 00:00:00 2001 From: teckliew Date: Fri, 17 Jul 2020 18:04:06 -0700 Subject: [PATCH 1/6] add check command --- bin/enact.js | 1 + commands/check.js | 141 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100755 commands/check.js diff --git a/bin/enact.js b/bin/enact.js index 1a5969ca..131290ba 100755 --- a/bin/enact.js +++ b/bin/enact.js @@ -65,6 +65,7 @@ if (process.argv.indexOf('-v') >= 0 || process.argv.indexOf('--version') >= 0) { case 'eject': case 'template': case 'lint': + case 'check': case 'license': { const task = require('../commands/' + command).cli; task(process.argv.slice(3)); diff --git a/commands/check.js b/commands/check.js new file mode 100755 index 00000000..041b48ed --- /dev/null +++ b/commands/check.js @@ -0,0 +1,141 @@ +/* eslint-env node, es6 */ +const fs = require('fs'); +const {promisify} = require('util'); +const path = require('path'); +const glob = require('glob'); + +const globOpts = { + ignore: [ + '**/node_modules/**', + 'build/**', + '**/dist/**', + 'coverage/**', + 'tests/**', + '**/*-specs.js', + '**/index.js', + 'samples/**', + '**/util.js', + '**/utils.js', + '**/validators.js' + ], + nodir: true +}; + +const readFile = promisify(fs.readFile); +const globPromise = promisify(glob); + +function displayHelp() { + let e = 'node ' + path.relative(process.cwd(), __filename); + if (require.main !== module) e = 'enact check'; + + console.log(' Checks for undefined classnames referenced in JSX'); + console.log(); + console.log(' Usage'); + console.log(` ${e} [options]`); + console.log(); + console.log(' Arguments'); + console.log(); + console.log(' Options'); + console.log(' -v, --version Display version information'); + console.log(' -h, --help Display help information'); + console.log(); + process.exit(0); +} + +function logWarnings(missingClassNames) { + if (missingClassNames.length) { + console.log(); + console.warn(' These classname definitions are missing in the following less files:'); + console.log(); + + missingClassNames.forEach(component => { + const componentName = Object.keys(component)[0]; + console.log(` ${componentName}`); + console.log(component[componentName]); + console.log(); + }); + } else { + console.log(' No problems found.'); + } +} + +function getMissingClassNames(lessFile, classNames) { + return new Promise((resolve, reject) => { + const missingClassNames = {[lessFile]: []}; + + if (lessFile) { + readFile(lessFile, 'utf8') + .then(data => { + // const componentName = file.match(/([^\/]+)(?=\.\w+$)/g)[0]; + // const lessFileName = data.match(/\w*\.module\.less/g); + classNames.forEach(name => { + if (!data.includes(name)) { + missingClassNames[lessFile].push(name); + } + }); + + resolve(missingClassNames[lessFile].length === 0 ? null : missingClassNames); + }) + .catch(err => reject(err)); + } + }); +} + +function getClassNamesUsed(files) { + return new Promise((resolve, reject) => { + const promisesToResolve = []; + + files.forEach((file, index) => { + readFile(file, 'utf8') + .then(data => { + const lessFileName = data.match(/\w*\.module\.less/g); + const dataWithComments = data.replace(/(\/\*([\s\S]*?)\*\/)|(\/\/(.*)$)/gm, ''); + const classNamesUsed = dataWithComments.match(/css\.\w*/g); + + if (lessFileName && classNamesUsed) { + const componentDirectory = file.match(/^(.+)\//g)[0]; + const classNames = classNamesUsed.map(name => name.split('.')[1]); + + promisesToResolve.push( + getMissingClassNames(`${componentDirectory}${lessFileName[0]}`, classNames) + ); + } + + if (index === files.length - 1) { + return promisesToResolve; + } + }) + .then(promises => (promises ? resolve(promises) : null)) + .catch(err => reject(err)); + }); + }); +} + +function getJSfiles() { + return new Promise((resolve, reject) => { + globPromise('**/*.js', globOpts) + .then(files => { + resolve(files); + }) + .catch(err => reject(err)); + }); +} + +function api() { + return Promise.resolve().then(() => + getJSfiles() + .then(files => getClassNamesUsed(files)) + .then(promises => Promise.all(promises)) + .then(results => logWarnings(results.filter(result => result))) + .catch(err => console.err(err)) + ); +} + +function cli(args) { + api(args).catch(() => { + process.exit(1); + }); +} + +module.exports = {api, cli}; +if (require.main === module) cli(process.argv.slice(2)); From f79cda16ced7597c0996e25cf7c2f9176fc98040 Mon Sep 17 00:00:00 2001 From: teckliew Date: Fri, 17 Jul 2020 18:16:21 -0700 Subject: [PATCH 2/6] add displayHelp --- commands/check.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/commands/check.js b/commands/check.js index 041b48ed..1da100fc 100755 --- a/commands/check.js +++ b/commands/check.js @@ -3,6 +3,7 @@ const fs = require('fs'); const {promisify} = require('util'); const path = require('path'); const glob = require('glob'); +const minimist = require('minimist'); const globOpts = { ignore: [ @@ -132,6 +133,12 @@ function api() { } function cli(args) { + const opts = minimist(args, { + boolean: ['help'], + alias: {h: 'help'} + }); + if (opts.help) displayHelp(); + api(args).catch(() => { process.exit(1); }); From bcadbcf6652acddcdf4b52311250f9cb134fe775 Mon Sep 17 00:00:00 2001 From: teckliew Date: Fri, 17 Jul 2020 18:29:46 -0700 Subject: [PATCH 3/6] todo: add default classes --- commands/check.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/commands/check.js b/commands/check.js index 1da100fc..83ea3a1b 100755 --- a/commands/check.js +++ b/commands/check.js @@ -82,6 +82,12 @@ function getMissingClassNames(lessFile, classNames) { }); } +function getDefaultClasses(classNameArray, component) => { + const newArray = [...getDefaultClasses]; + //TODO + return newArray; +} + function getClassNamesUsed(files) { return new Promise((resolve, reject) => { const promisesToResolve = []; @@ -90,8 +96,9 @@ function getClassNamesUsed(files) { readFile(file, 'utf8') .then(data => { const lessFileName = data.match(/\w*\.module\.less/g); - const dataWithComments = data.replace(/(\/\*([\s\S]*?)\*\/)|(\/\/(.*)$)/gm, ''); - const classNamesUsed = dataWithComments.match(/css\.\w*/g); + const dataWithoutComments = data.replace(/(\/\*([\s\S]*?)\*\/)|(\/\/(.*)$)/gm, ''); + let classNamesUsed = dataWithoutComments.match(/css\.\w*/g); + classNamesUsed = getDefaultClasses(classNamesUsed, dataWithoutComments); if (lessFileName && classNamesUsed) { const componentDirectory = file.match(/^(.+)\//g)[0]; From fe06d25369472743cf0c434255943f4007399955 Mon Sep 17 00:00:00 2001 From: teckliew Date: Fri, 17 Jul 2020 18:41:51 -0700 Subject: [PATCH 4/6] update logs --- commands/check.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/commands/check.js b/commands/check.js index 83ea3a1b..5d02a8d1 100755 --- a/commands/check.js +++ b/commands/check.js @@ -29,7 +29,7 @@ function displayHelp() { let e = 'node ' + path.relative(process.cwd(), __filename); if (require.main !== module) e = 'enact check'; - console.log(' Checks for undefined classnames referenced in JSX'); + console.log(' Checks for potential missing class definitions'); console.log(); console.log(' Usage'); console.log(` ${e} [options]`); @@ -46,7 +46,7 @@ function displayHelp() { function logWarnings(missingClassNames) { if (missingClassNames.length) { console.log(); - console.warn(' These classname definitions are missing in the following less files:'); + console.warn(' There might be missing class definitions in the following less files:'); console.log(); missingClassNames.forEach(component => { From 69ca7e18563b55e8c1b8db06b1ff68dc8c9e8961 Mon Sep 17 00:00:00 2001 From: teckliew Date: Fri, 17 Jul 2020 18:43:24 -0700 Subject: [PATCH 5/6] fix lint --- commands/check.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/check.js b/commands/check.js index 5d02a8d1..d73518b2 100755 --- a/commands/check.js +++ b/commands/check.js @@ -82,7 +82,7 @@ function getMissingClassNames(lessFile, classNames) { }); } -function getDefaultClasses(classNameArray, component) => { +function getDefaultClasses() { const newArray = [...getDefaultClasses]; //TODO return newArray; From bdc239bd65f75837dd9ba79bda5b2a0492e8d0ab Mon Sep 17 00:00:00 2001 From: teckliew Date: Fri, 17 Jul 2020 18:44:06 -0700 Subject: [PATCH 6/6] add todo --- commands/check.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/commands/check.js b/commands/check.js index d73518b2..1ec05449 100755 --- a/commands/check.js +++ b/commands/check.js @@ -82,11 +82,11 @@ function getMissingClassNames(lessFile, classNames) { }); } -function getDefaultClasses() { - const newArray = [...getDefaultClasses]; - //TODO - return newArray; -} +// function getDefaultClasses(classNameArray, component) { +// const newArray = [...getDefaultClasses]; +// //TODO +// return newArray; +// } function getClassNamesUsed(files) { return new Promise((resolve, reject) => { @@ -97,8 +97,8 @@ function getClassNamesUsed(files) { .then(data => { const lessFileName = data.match(/\w*\.module\.less/g); const dataWithoutComments = data.replace(/(\/\*([\s\S]*?)\*\/)|(\/\/(.*)$)/gm, ''); - let classNamesUsed = dataWithoutComments.match(/css\.\w*/g); - classNamesUsed = getDefaultClasses(classNamesUsed, dataWithoutComments); + const classNamesUsed = dataWithoutComments.match(/css\.\w*/g); + // classNamesUsed = getDefaultClasses(classNamesUsed, dataWithoutComments); if (lessFileName && classNamesUsed) { const componentDirectory = file.match(/^(.+)\//g)[0];