From c8e752c457560b8aabd78c62ef2e2a33167f3ee0 Mon Sep 17 00:00:00 2001 From: BRIAN MUENZENMEYER Date: Sat, 26 Nov 2016 05:53:10 -0600 Subject: [PATCH 1/3] start #566 by copying @raphaelokon's great work over at https://github.com/pattern-lab/patternlab-node-cli/blob/master/bin/utils.js --- core/lib/pattern_assembler.js | 16 +-- core/lib/patternlab.js | 28 ++-- core/lib/plugin_manager.js | 6 +- core/lib/starterkit_manager.js | 8 +- core/lib/ui_builder.js | 6 +- core/lib/utilities.js | 236 ++++++++++++++++++--------------- core/scripts/postinstall.js | 6 +- 7 files changed, 165 insertions(+), 141 deletions(-) diff --git a/core/lib/pattern_assembler.js b/core/lib/pattern_assembler.js index 05df15e82..e3ef03be3 100644 --- a/core/lib/pattern_assembler.js +++ b/core/lib/pattern_assembler.js @@ -45,7 +45,7 @@ var pattern_assembler = function () { return patternlab.patterns[i]; } } - plutils.logOrange('Could not find pattern referenced with partial syntax ' + partialName + '. This can occur when a pattern was renamed, moved, or no longer exists but it still called within a different template somewhere.'); + plutils.warning('Could not find pattern referenced with partial syntax ' + partialName + '. This can occur when a pattern was renamed, moved, or no longer exists but it still called within a different template somewhere.'); return undefined; } @@ -81,7 +81,7 @@ var pattern_assembler = function () { if (patternlab.config.patternStates && patternlab.config.patternStates[pattern.patternPartial]) { if (displayDeprecatedWarning) { - plutils.logRed("Deprecation Warning: Using patternlab-config.json patternStates object will be deprecated in favor of the state frontmatter key associated with individual pattern markdown files."); + plutils.error("Deprecation Warning: Using patternlab-config.json patternStates object will be deprecated in favor of the state frontmatter key associated with individual pattern markdown files."); console.log("This feature will still work in it's current form this release (but still be overridden by the new parsing method), and will be removed in the future."); } @@ -245,13 +245,13 @@ var pattern_assembler = function () { var relativeDepth = (relPath.match(/\w(?=\\)|\w(?=\/)/g) || []).length; if (relativeDepth > 2) { console.log(''); - plutils.logOrange('Warning:'); - plutils.logOrange('A pattern file: ' + relPath + ' was found greater than 2 levels deep from ' + patternlab.config.paths.source.patterns + '.'); - plutils.logOrange('It\'s strongly suggested to not deviate from the following structure under _patterns/'); - plutils.logOrange('[patternType]/[patternSubtype]/[patternName].[patternExtension]'); + plutils.warning('Warning:'); + plutils.warning('A pattern file: ' + relPath + ' was found greater than 2 levels deep from ' + patternlab.config.paths.source.patterns + '.'); + plutils.warning('It\'s strongly suggested to not deviate from the following structure under _patterns/'); + plutils.warning('[patternType]/[patternSubtype]/[patternName].[patternExtension]'); console.log(''); - plutils.logOrange('While Pattern Lab may still function, assets may 404 and frontend links may break. Consider yourself warned. '); - plutils.logOrange('Read More: http://patternlab.io/docs/pattern-organization.html'); + plutils.warning('While Pattern Lab may still function, assets may 404 and frontend links may break. Consider yourself warned. '); + plutils.warning('Read More: http://patternlab.io/docs/pattern-organization.html'); console.log(''); } diff --git a/core/lib/patternlab.js b/core/lib/patternlab.js index 2efde4e49..232103327 100644 --- a/core/lib/patternlab.js +++ b/core/lib/patternlab.js @@ -80,9 +80,9 @@ function checkConfiguration(patternlab) { }; if (!patternlab.config.outputFileSuffixes) { - plutils.logOrange('Configuration Object "outputFileSuffixes" not found, and defaulted to the following:'); + plutils.warning('Configuration Object "outputFileSuffixes" not found, and defaulted to the following:'); console.log(outputFileSuffixes); - plutils.logOrange('Since Pattern Lab Core 2.3.0 this configuration option is required. Suggest you add it to your patternlab-config.json file.'); + plutils.warning('Since Pattern Lab Core 2.3.0 this configuration option is required. Suggest you add it to your patternlab-config.json file.'); console.log(); } patternlab.config.outputFileSuffixes = _.extend(outputFileSuffixes, patternlab.config.outputFileSuffixes); @@ -171,34 +171,34 @@ var patternlab_engine = function (config) { console.log(''); console.log('|=======================================|'); - plutils.logGreen(' Pattern Lab Node Help v' + patternlab.package.version); + plutils.debug(' Pattern Lab Node Help v' + patternlab.package.version); console.log('|=======================================|'); console.log(''); console.log('Command Line Interface - usually consumed by an edition'); console.log(''); - plutils.logGreen(' patternlab:build'); + plutils.debug(' patternlab:build'); console.log(' > Compiles the patterns and frontend, outputting to config.paths.public'); console.log(''); - plutils.logGreen(' patternlab:patternsonly'); + plutils.debug(' patternlab:patternsonly'); console.log(' > Compiles the patterns only, outputting to config.paths.public'); console.log(''); - plutils.logGreen(' patternlab:version'); + plutils.debug(' patternlab:version'); console.log(' > Return the version of patternlab-node you have installed'); console.log(''); - plutils.logGreen(' patternlab:help'); + plutils.debug(' patternlab:help'); console.log(' > Get more information about patternlab-node, pattern lab in general, and where to report issues.'); console.log(''); - plutils.logGreen(' patternlab:liststarterkits'); + plutils.debug(' patternlab:liststarterkits'); console.log(' > Returns a url with the list of available starterkits hosted on the Pattern Lab organization Github account'); console.log(''); - plutils.logGreen(' patternlab:loadstarterkit'); + plutils.debug(' patternlab:loadstarterkit'); console.log(' > Load a starterkit into config.paths.source/*'); console.log(' > NOTE: Overwrites existing content, and only cleans out existing directory if --clean=true argument is passed.'); console.log(' > NOTE: In most cases, `npm install starterkit-name` will precede this call.'); @@ -274,7 +274,7 @@ var patternlab_engine = function (config) { patternlab.userHead = headPattern.extendedTemplate; } catch (ex) { - plutils.logRed('\nWARNING: Could not find the user-editable header template, currently configured to be at ' + path.join(config.paths.source.meta, '_00-head.mustache') + '. Your configured path may be incorrect (check paths.source.meta in your config file), the file may have been deleted, or it may have been left in the wrong place during a migration or update.\n'); + plutils.error('\nWARNING: Could not find the user-editable header template, currently configured to be at ' + path.join(config.paths.source.meta, '_00-head.mustache') + '. Your configured path may be incorrect (check paths.source.meta in your config file), the file may have been deleted, or it may have been left in the wrong place during a migration or update.\n'); if (patternlab.config.debug) { console.log(ex); } process.exit(1); } @@ -294,7 +294,7 @@ var patternlab_engine = function (config) { patternlab.userFoot = footPattern.extendedTemplate; } catch (ex) { - plutils.logRed('\nWARNING: Could not find the user-editable footer template, currently configured to be at ' + path.join(config.paths.source.meta, '_01-foot.mustache') + '. Your configured path may be incorrect (check paths.source.meta in your config file), the file may have been deleted, or it may have been left in the wrong place during a migration or update.\n'); + plutils.error('\nWARNING: Could not find the user-editable footer template, currently configured to be at ' + path.join(config.paths.source.meta, '_01-foot.mustache') + '. Your configured path may be incorrect (check paths.source.meta in your config file), the file may have been deleted, or it may have been left in the wrong place during a migration or update.\n'); if (patternlab.config.debug) { console.log(ex); } process.exit(1); } @@ -338,13 +338,13 @@ var patternlab_engine = function (config) { try { patternlab.data = buildPatternData(paths.source.data, fs); } catch (ex) { - plutils.logRed('missing or malformed' + paths.source.data + 'data.json Pattern Lab may not work without this file.'); + plutils.error('missing or malformed' + paths.source.data + 'data.json Pattern Lab may not work without this file.'); patternlab.data = {}; } try { patternlab.listitems = fs.readJSONSync(path.resolve(paths.source.data, 'listitems.json')); } catch (ex) { - plutils.logOrange('WARNING: missing or malformed ' + paths.source.data + 'listitems.json file. Pattern Lab may not work without this file.'); + plutils.warning('WARNING: missing or malformed ' + paths.source.data + 'listitems.json file. Pattern Lab may not work without this file.'); patternlab.listitems = {}; } try { @@ -355,7 +355,7 @@ var patternlab_engine = function (config) { patternlab.viewAll = fs.readFileSync(path.resolve(paths.source.patternlabFiles, 'viewall.mustache'), 'utf8'); } catch (ex) { console.log(ex); - plutils.logRed('\nERROR: missing an essential file from ' + paths.source.patternlabFiles + '. Pattern Lab won\'t work without this file.\n'); + plutils.error('\nERROR: missing an essential file from ' + paths.source.patternlabFiles + '. Pattern Lab won\'t work without this file.\n'); process.exit(1); } patternlab.patterns = []; diff --git a/core/lib/plugin_manager.js b/core/lib/plugin_manager.js index 2a0869036..136cc7324 100644 --- a/core/lib/plugin_manager.js +++ b/core/lib/plugin_manager.js @@ -29,8 +29,8 @@ var plugin_manager = function (config, configPath) { try { var pluginDirStats = fs.statSync(pluginPath); } catch (ex) { - util.logRed(pluginName + ' not found, please use npm to install it first.'); - util.logRed(pluginName + ' not loaded.'); + util.error(pluginName + ' not found, please use npm to install it first.'); + util.error(pluginName + ' not loaded.'); return; } var pluginPathDirExists = pluginDirStats.isDirectory(); @@ -50,7 +50,7 @@ var plugin_manager = function (config, configPath) { //write config entry back fs.outputFileSync(path.resolve(configPath), JSON.stringify(diskConfig, null, 2)); - util.logGreen('Plugin ' + pluginName + ' installed.'); + util.debug('Plugin ' + pluginName + ' installed.'); //todo, tell them how to uninstall or disable diff --git a/core/lib/starterkit_manager.js b/core/lib/starterkit_manager.js index 3dec08115..db4153486 100644 --- a/core/lib/starterkit_manager.js +++ b/core/lib/starterkit_manager.js @@ -8,7 +8,7 @@ var starterkit_manager = function (config) { paths = config.paths; /** - * Loads npm module identified by the starterkitName parameter. + * Loads npm module identified by the starterkitName parameter. * * @param starterkitName {string} Kit name * @param clean {boolean} Indicates if the directory should be cleaned before loading @@ -22,8 +22,8 @@ var starterkit_manager = function (config) { try { var kitDirStats = fs.statSync(kitPath); } catch (ex) { - util.logRed(starterkitName + ' not found, please use npm to install it first.'); - util.logRed(starterkitName + ' not loaded.'); + util.error(starterkitName + ' not found, please use npm to install it first.'); + util.error(starterkitName + ' not loaded.'); return; } var kitPathDirExists = kitDirStats.isDirectory(); @@ -40,7 +40,7 @@ var starterkit_manager = function (config) { if (ex) { console.error(ex); } - util.logGreen('starterkit ' + starterkitName + ' loaded successfully.'); + util.debug('starterkit ' + starterkitName + ' loaded successfully.'); }); } } catch (ex) { diff --git a/core/lib/ui_builder.js b/core/lib/ui_builder.js index 9f97d80ab..e112dd8b3 100644 --- a/core/lib/ui_builder.js +++ b/core/lib/ui_builder.js @@ -167,7 +167,7 @@ var ui_builder = function () { var patternType = _.find(patternlab.patternTypes, ['patternType', pattern.patternType]); if (!patternType) { - plutils.logRed('Could not find patternType' + pattern.patternType + '. This is a critical error.'); + plutils.error('Could not find patternType' + pattern.patternType + '. This is a critical error.'); console.trace(); process.exit(1); } @@ -186,7 +186,7 @@ var ui_builder = function () { var patternSubType = _.find(patternType.patternTypeItems, ['patternSubtype', pattern.patternSubType]); if (!patternSubType) { - plutils.logRed('Could not find patternType ' + pattern.patternType + '-' + pattern.patternType + '. This is a critical error.'); + plutils.error('Could not find patternType ' + pattern.patternType + '-' + pattern.patternType + '. This is a critical error.'); console.trace(); process.exit(1); } @@ -274,7 +274,7 @@ var ui_builder = function () { function addPatternItem(patternlab, pattern, isViewAllVariant) { var patternType = getPatternType(patternlab, pattern); if (!patternType) { - plutils.logRed('Could not find patternType' + pattern.patternType + '. This is a critical error.'); + plutils.error('Could not find patternType' + pattern.patternType + '. This is a critical error.'); console.trace(); process.exit(1); } diff --git a/core/lib/utilities.js b/core/lib/utilities.js index 8e1488814..fd4f59376 100644 --- a/core/lib/utilities.js +++ b/core/lib/utilities.js @@ -1,129 +1,153 @@ "use strict"; -var fs = require('fs-extra'), - path = require('path'); +const fs = require('fs-extra'); +const path = require('path'); +const chalk = require('chalk'); +const EventEmitter = require('events').EventEmitter; -var util = { - /** - * Shuffles an array in place. - * http://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array-in-javascript - * - * @param {Array} o - * @returns {Array} o - */ - shuffle: function (o) { - /*eslint-disable curly*/ - for (var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x); - return o; +/** + * @name log + * @desc tiny event-based logger + * @type {*} + */ +const log = Object.assign({ + debug(msg) { + this.emit('debug', chalk.green(msg)); }, - - /** - * Logs a message to the console with green text. - * - * @param {string} message - * @returns {string} message - */ - logGreen: function (message) { - console.log('\x1b[32m', message, '\x1b[0m'); + info(msg) { + this.emit('info', msg); }, - - /** - * Logs a message to the console with orange text. - * - * @param {string} message - * @returns {string} message - */ - logOrange: function (message) { - console.log('\x1b[33m', message, '\x1b[0m'); + warning(msg) { + this.emit('warning', chalk.orange(msg)); }, + error(msg) { + this.emit('error', chalk.red(msg)); + } +}, EventEmitter.prototype); - /** - * Logs a message to the console with red text. - * - * @param {string} message - * @returns {string} message - */ - logRed: function (message) { - console.log('\x1b[41m', message, '\x1b[0m'); - }, +/** + * @func debug + * @desc Coloured debug log + * @param {*} msg - The variadic messages to log out. + * @return {void} + */ +const debug = log.debug.bind(log); + +/** + * @func warning + * @desc Coloured error log + * @param {*} e - The variadic messages to log out. + * @return {void} + */ +const warning = log.warning.bind(log); + +/** + * @func error + * @desc Coloured error log + * @param {*} e - The variadic messages to log out. + * @return {void} + */ +const error = log.error.bind(log); /** - * Recursively merge properties of two objects. + * Shuffles an array in place. + * http://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array-in-javascript * - * @param {Object} obj1 If obj1 has properties obj2 doesn't, add to obj2. - * @param {Object} obj2 This object's properties have priority over obj1. - * @returns {Object} obj2 + * @param {Array} o + * @returns {Array} o */ - mergeData: function (obj1, obj2) { - /*eslint-disable no-param-reassign, guard-for-in*/ - if (typeof obj2 === 'undefined') { - obj2 = {}; - } - for (var p in obj1) { - try { - // Only recurse if obj1[p] is an object. - if (obj1[p].constructor === Object) { - // Requires 2 objects as params; create obj2[p] if undefined. - if (typeof obj2[p] === 'undefined') { - obj2[p] = {}; - } - obj2[p] = util.mergeData(obj1[p], obj2[p]); +const shuffle = function (o) { + /*eslint-disable curly*/ + for (var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x); + return o; +}; - // Pop when recursion meets a non-object. If obj1[p] is a non-object, - // only copy to undefined obj2[p]. This way, obj2 maintains priority. - } else if (typeof obj2[p] === 'undefined') { - obj2[p] = obj1[p]; - } - } catch (e) { - // Property in destination object not set; create it and set its value. +/** + * Recursively merge properties of two objects. + * + * @param {Object} obj1 If obj1 has properties obj2 doesn't, add to obj2. + * @param {Object} obj2 This object's properties have priority over obj1. + * @returns {Object} obj2 + */ +const mergeData = function (obj1, obj2) { + /*eslint-disable no-param-reassign, guard-for-in*/ + if (typeof obj2 === 'undefined') { + obj2 = {}; + } + for (var p in obj1) { + try { + // Only recurse if obj1[p] is an object. + if (obj1[p].constructor === Object) { + // Requires 2 objects as params; create obj2[p] if undefined. if (typeof obj2[p] === 'undefined') { - obj2[p] = obj1[p]; + obj2[p] = {}; } + obj2[p] = mergeData(obj1[p], obj2[p]); + + // Pop when recursion meets a non-object. If obj1[p] is a non-object, + // only copy to undefined obj2[p]. This way, obj2 maintains priority. + } else if (typeof obj2[p] === 'undefined') { + obj2[p] = obj1[p]; + } + } catch (e) { + // Property in destination object not set; create it and set its value. + if (typeof obj2[p] === 'undefined') { + obj2[p] = obj1[p]; } } - return obj2; - }, + } + return obj2; +}; - /** - * Determines whether or not an object is empty. - * - * @param {Object} obj - * @returns {Boolean} - */ - isObjectEmpty: function (obj) { - for (var prop in obj) { - if (obj.hasOwnProperty(prop)) { return false; } - } - return true; - }, +/** + * Determines whether or not an object is empty. + * + * @param {Object} obj + * @returns {Boolean} + */ +const isObjectEmpty = function (obj) { + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { return false; } + } + return true; +}; - /** - * Recursively delete the contents of directory. - * Adapted from https://gist.github.com/tkihira/2367067 - * - * @param {string} dir - directory to empty - * @param {string} cleanDir - already empty directory - * @returns {undefined} - */ - emptyDirectory: function (dir, cleanDir) { - var list = fs.readdirSync(dir); - for (var i = 0; i < list.length; i++) { - var filename = path.join(dir, list[i]); - var stat = fs.statSync(filename); +/** + * Recursively delete the contents of directory. + * Adapted from https://gist.github.com/tkihira/2367067 + * + * @param {string} dir - directory to empty + * @param {string} cleanDir - already empty directory + * @returns {undefined} + */ +const emptyDirectory = function (dir, cleanDir) { + var list = fs.readdirSync(dir); + for (var i = 0; i < list.length; i++) { + var filename = path.join(dir, list[i]); + var stat = fs.statSync(filename); - if (filename === "." || filename === "..") { - // pass these files - } else if (stat.isDirectory()) { - this.emptyDirectory(filename); - } else { - // rm fiilename - fs.unlinkSync(filename); - } - } - if (cleanDir) { - fs.rmdirSync(dir); + if (filename === "." || filename === "..") { + // pass these files + } else if (stat.isDirectory()) { + this.emptyDirectory(filename); + } else { + // rm fiilename + fs.unlinkSync(filename); } } + if (cleanDir) { + fs.rmdirSync(dir); + } +}; + +module.exports = { + debug, + warning, + error, + log, + shuffle, + mergeData, + isObjectEmpty, + emptyDirectory }; -module.exports = util; diff --git a/core/scripts/postinstall.js b/core/scripts/postinstall.js index 53636e1d0..019697667 100644 --- a/core/scripts/postinstall.js +++ b/core/scripts/postinstall.js @@ -38,10 +38,10 @@ try { } } - u.logGreen('Pattern Lab postinstall complete.'); + u.debug('Pattern Lab postinstall complete.'); } catch (ex) { console.log(ex); - u.logOrange('An error occurred during Pattern Lab Node postinstall.'); - u.logOrange('Pattern Lab postinstall completed with errors.'); + u.warning('An error occurred during Pattern Lab Node postinstall.'); + u.warning('Pattern Lab postinstall completed with errors.'); } From f3abd131f559812a6a74f26fe0176dca1630d172 Mon Sep 17 00:00:00 2001 From: BRIAN MUENZENMEYER Date: Sat, 26 Nov 2016 06:13:22 -0600 Subject: [PATCH 2/3] orange is not a valid chalk color --- core/lib/utilities.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/lib/utilities.js b/core/lib/utilities.js index fd4f59376..28166a830 100644 --- a/core/lib/utilities.js +++ b/core/lib/utilities.js @@ -18,7 +18,7 @@ const log = Object.assign({ this.emit('info', msg); }, warning(msg) { - this.emit('warning', chalk.orange(msg)); + this.emit('warning', chalk.yellow(msg)); }, error(msg) { this.emit('error', chalk.red(msg)); From 1e54af003a69492d98dc22df0757630a299033ec Mon Sep 17 00:00:00 2001 From: BRIAN MUENZENMEYER Date: Sat, 26 Nov 2016 06:13:37 -0600 Subject: [PATCH 3/3] register our events --- core/lib/patternlab.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/lib/patternlab.js b/core/lib/patternlab.js index 232103327..8bf83016d 100644 --- a/core/lib/patternlab.js +++ b/core/lib/patternlab.js @@ -22,6 +22,12 @@ var diveSync = require('diveSync'), packageInfo = require('../../package.json'), plutils = require('./utilities'); +//register our log events +plutils.log.on('error', msg => console.log(msg)); +plutils.log.on('debug', msg => console.log(msg)); +plutils.log.on('warning', msg => console.log(msg)); +plutils.log.on('info', msg => console.log(msg)); + console.log( chalk.bold('\n====[ Pattern Lab / Node'), `- v${packageInfo.version}`,