diff --git a/install/package.json b/install/package.json index 891d53c4b9..a981965808 100644 --- a/install/package.json +++ b/install/package.json @@ -38,6 +38,7 @@ "body-parser": "1.19.1", "bootbox": "5.5.2", "bootstrap": "3.4.1", + "chalk": "4.1.2", "chart.js": "2.9.4", "cli-graph": "3.2.2", "clipboard": "2.0.9", diff --git a/src/cli/colors.js b/src/cli/colors.js index 4ba0012a40..71723ae42f 100644 --- a/src/cli/colors.js +++ b/src/cli/colors.js @@ -4,7 +4,8 @@ // to include color styling in the output // so the CLI looks nice -const { Command, Help } = require('commander'); +const { Command } = require('commander'); +const chalk = require('chalk'); const colors = [ // depth = 0, top-level command @@ -23,6 +24,11 @@ function humanReadableArgName(arg) { return arg.required ? `<${nameOutput}>` : `[${nameOutput}]`; } +function getControlCharacterSpaces(term) { + const matches = term.match(/.\[\d+m/g); + return matches ? matches.length * 5 : 0; +} + // get depth of command // 0 = top, 1 = subcommand of top, etc Command.prototype.depth = function () { @@ -49,38 +55,50 @@ module.exports = { let parentCmd = cmd.parent; let parentDepth = depth - 1; while (parentCmd) { - parentCmdNames = `${parentCmd.name()[colors[parentDepth].command]} ${parentCmdNames}`; + parentCmdNames = `${chalk[colors[parentDepth].command](parentCmd.name())} ${parentCmdNames}`; parentCmd = parentCmd.parent; parentDepth -= 1; } // from Command.prototype.usage() - const args = cmd._args.map(arg => humanReadableArgName(arg)[colors[depth].arg]); + const args = cmd._args.map(arg => chalk[colors[depth].arg](humanReadableArgName(arg))); const cmdUsage = [].concat( - (cmd.options.length || cmd._hasHelpOption ? '[options]'[colors[depth].option] : []), - (cmd.commands.length ? '[command]'[colors[depth + 1].command] : []), + (cmd.options.length || cmd._hasHelpOption ? chalk[colors[depth].option]('[options]') : []), + (cmd.commands.length ? chalk[colors[depth + 1].command]('[command]') : []), (cmd._args.length ? args : []) ).join(' '); - return `${parentCmdNames}${cmdName[colors[depth].command]} ${cmdUsage}`; + return `${parentCmdNames}${chalk[colors[depth].command](cmdName)} ${cmdUsage}`; }, subcommandTerm(cmd) { const depth = cmd.depth(); // Legacy. Ignores custom usage string, and nested commands. const args = cmd._args.map(arg => humanReadableArgName(arg)).join(' '); - return (cmd._name + ( + return chalk[colors[depth].command](cmd._name + ( cmd._aliases[0] ? `|${cmd._aliases[0]}` : '' - ))[colors[depth].command] + - (cmd.options.length ? ' [options]' : '')[colors[depth].option] + // simplistic check for non-help option - (args ? ` ${args}` : '')[colors[depth].arg]; + )) + + chalk[colors[depth].option](cmd.options.length ? ' [options]' : '') + // simplistic check for non-help option + chalk[colors[depth].arg](args ? ` ${args}` : ''); }, longestOptionTermLength(cmd, helper) { - return Help.prototype.longestOptionTermLength.call(this, cmd, helper) + ''.red.length; + return helper.visibleOptions(cmd).reduce((max, option) => Math.max( + max, + helper.optionTerm(option).length - getControlCharacterSpaces(helper.optionTerm(option)) + ), 0); + }, + longestSubcommandTermLength(cmd, helper) { + return helper.visibleCommands(cmd).reduce((max, command) => Math.max( + max, + helper.subcommandTerm(command).length - getControlCharacterSpaces(helper.subcommandTerm(command)) + ), 0); }, longestArgumentTermLength(cmd, helper) { - return Help.prototype.longestArgumentTermLength.call(this, cmd, helper) + ''.red.length; + return helper.visibleArguments(cmd).reduce((max, argument) => Math.max( + max, + helper.argumentTerm(argument).length - getControlCharacterSpaces(helper.argumentTerm(argument)) + ), 0); }, formatHelp(cmd, helper) { const depth = cmd.depth(); @@ -90,8 +108,9 @@ module.exports = { const itemIndentWidth = 2; const itemSeparatorWidth = 2; // between term and description function formatItem(term, description) { + const padding = ' '.repeat((termWidth + itemSeparatorWidth) - (term.length - getControlCharacterSpaces(term))); if (description) { - const fullText = `${term.padEnd(termWidth + itemSeparatorWidth)}${description}`; + const fullText = `${term}${padding}${description}`; return helper.wrap(fullText, helpWidth - itemIndentWidth, termWidth + itemSeparatorWidth); } return term; @@ -111,7 +130,7 @@ module.exports = { // Arguments const argumentList = helper.visibleArguments(cmd).map(argument => formatItem( - argument.term[colors[depth].arg], + chalk[colors[depth].arg](argument.term), argument.description )); if (argumentList.length > 0) { @@ -120,7 +139,7 @@ module.exports = { // Options const optionList = helper.visibleOptions(cmd).map(option => formatItem( - helper.optionTerm(option)[colors[depth].option], + chalk[colors[depth].option](helper.optionTerm(option)), helper.optionDescription(option) )); if (optionList.length > 0) { diff --git a/src/cli/index.js b/src/cli/index.js index 409b429502..59f1e68aee 100644 --- a/src/cli/index.js +++ b/src/cli/index.js @@ -22,10 +22,10 @@ try { packageInstall.preserveExtraneousPlugins(); try { - fs.accessSync(path.join(paths.nodeModules, 'colors/package.json'), fs.constants.R_OK); + fs.accessSync(path.join(paths.nodeModules, 'chalk/package.json'), fs.constants.R_OK); - require('colors'); - console.log('OK'.green); + const chalk = require('chalk'); + console.log(chalk.green('OK')); } catch (e) { console.log('OK'); } @@ -52,7 +52,7 @@ try { checkVersion('nconf'); checkVersion('async'); checkVersion('commander'); - checkVersion('colors'); + checkVersion('chalk'); } catch (e) { if (['ENOENT', 'DEP_WRONG_VERSION', 'MODULE_NOT_FOUND'].includes(e.code)) { console.warn('Dependencies outdated or not yet installed.'); @@ -61,14 +61,14 @@ try { packageInstall.updatePackageFile(); packageInstall.installAll(); - require('colors'); - console.log('OK'.green + '\n'.reset); + const chalk = require('chalk'); + console.log(`${chalk.green('OK')}\n`); } else { throw e; } } -require('colors'); +const chalk = require('chalk'); const nconf = require('nconf'); const { program } = require('commander'); const yargs = require('yargs'); @@ -173,7 +173,7 @@ program try { initConfig = JSON.parse(initConfig); } catch (e) { - console.warn('Invalid JSON passed as initial config value.'.red); + console.warn(chalk.red('Invalid JSON passed as initial config value.')); console.log('If you meant to pass in an initial config value, please try again.\n'); throw e; @@ -190,7 +190,7 @@ program }); program .command('build [targets...]') - .description(`Compile static assets ${'(JS, CSS, templates, languages)'.red}`) + .description(`Compile static assets ${chalk.red('(JS, CSS, templates, languages)')}`) .option('-s, --series', 'Run builds in series without extra processes') .action((targets, options) => { if (program.opts().dev) { @@ -240,7 +240,7 @@ resetCommand .action((options) => { const valid = ['theme', 'plugin', 'widgets', 'settings', 'all'].some(x => options[x]); if (!valid) { - console.warn('\n No valid options passed in, so nothing was reset.'.red); + console.warn(`\n${chalk.red('No valid options passed in, so nothing was reset.')}`); resetCommand.help(); } @@ -270,8 +270,8 @@ program console.log(`\n${[ 'When running particular upgrade scripts, options are ignored.', 'By default all options are enabled. Passing any options disables that default.', - `Only package and dependency updates: ${'./nodebb upgrade -mi'.yellow}`, - `Only database update: ${'./nodebb upgrade -s'.yellow}`, + `Only package and dependency updates: ${chalk.yellow('./nodebb upgrade -mi')}`, + `Only database update: ${chalk.yellow('./nodebb upgrade -s')}`, ].join('\n')}`); }) .action((scripts, options) => { @@ -289,7 +289,7 @@ program if (err) { throw err; } - console.log('OK'.green); + console.log(chalk.green('OK')); process.exit(); }); }); diff --git a/src/cli/manage.js b/src/cli/manage.js index 326fc22c93..8188b10892 100644 --- a/src/cli/manage.js +++ b/src/cli/manage.js @@ -3,6 +3,7 @@ const winston = require('winston'); const childProcess = require('child_process'); const CliGraph = require('cli-graph'); +const chalk = require('chalk'); const build = require('../meta/build'); const db = require('../database'); @@ -76,9 +77,9 @@ async function listPlugins() { process.stdout.write('Active plugins:\n'); combined.forEach((plugin) => { process.stdout.write(`\t* ${plugin.id}${plugin.version ? `@${plugin.version}` : ''} (`); - process.stdout.write(plugin.installed ? 'installed'.green : 'not installed'.red); + process.stdout.write(plugin.installed ? chalk.green('installed') : chalk.red('not installed')); process.stdout.write(', '); - process.stdout.write(plugin.active ? 'enabled'.green : 'disabled'.yellow); + process.stdout.write(plugin.active ? chalk.green('enabled') : chalk.yellow('disabled')); process.stdout.write(')\n'); }); @@ -88,9 +89,9 @@ async function listPlugins() { async function listEvents(count = 10) { await db.init(); const eventData = await events.getEvents('', 0, count - 1); - console.log((`\nDisplaying last ${count} administrative events...`).bold); + console.log(chalk.bold(`\nDisplaying last ${count} administrative events...`)); eventData.forEach((event) => { - console.log(` * ${String(event.timestampISO).green} ${String(event.type).yellow}${event.text ? ` ${event.text}` : ''}${' (uid: '.reset}${event.uid ? event.uid : 0})`); + console.log(` * ${chalk.green(String(event.timestampISO))} ${chalk.yellow(String(event.type))}${event.text ? ` ${event.text}` : ''} (uid: ${event.uid ? event.uid : 0})`); }); process.exit(); } diff --git a/src/cli/reset.js b/src/cli/reset.js index 75daeeb153..b026a22816 100644 --- a/src/cli/reset.js +++ b/src/cli/reset.js @@ -1,9 +1,9 @@ 'use strict'; -require('colors'); const path = require('path'); const winston = require('winston'); const fs = require('fs'); +const chalk = require('chalk'); const db = require('../database'); const events = require('../events'); @@ -57,8 +57,8 @@ exports.reset = async function (options) { if (!tasks.length) { console.log([ - 'No arguments passed in, so nothing was reset.\n'.yellow, - `Use ./nodebb reset ${'{-t|-p|-w|-s|-a}'.red}`, + chalk.yellow('No arguments passed in, so nothing was reset.\n'), + `Use ./nodebb reset ${chalk.red('{-t|-p|-w|-s|-a}')}`, ' -t\tthemes', ' -p\tplugins', ' -w\twidgets', diff --git a/src/cli/running.js b/src/cli/running.js index d52ab20812..d52e6144e4 100644 --- a/src/cli/running.js +++ b/src/cli/running.js @@ -2,6 +2,7 @@ const fs = require('fs'); const childProcess = require('child_process'); +const chalk = require('chalk'); const fork = require('../meta/debugFork'); const { paths } = require('../constants'); @@ -39,17 +40,17 @@ function start(options) { } if (options.log) { console.log(`\n${[ - 'Starting NodeBB with logging output'.bold, - 'Hit '.red + 'Ctrl-C '.bold + 'to exit'.red, + chalk.bold('Starting NodeBB with logging output'), + chalk.red('Hit ') + chalk.bold('Ctrl-C ') + chalk.red('to exit'), 'The NodeBB process will continue to run in the background', - `Use "${'./nodebb stop'.yellow}" to stop the NodeBB server`, + `Use "${chalk.yellow('./nodebb stop')}" to stop the NodeBB server`, ].join('\n')}`); } else if (!options.silent) { console.log(`\n${[ - 'Starting NodeBB'.bold, - ` "${'./nodebb stop'.yellow}" to stop the NodeBB server`, - ` "${'./nodebb log'.yellow}" to view server output`, - ` "${'./nodebb help'.yellow}${'" for more commands\n'.reset}`, + chalk.bold('Starting NodeBB'), + ` "${chalk.yellow('./nodebb stop')}" to stop the NodeBB server`, + ` "${chalk.yellow('./nodebb log')}" to view server output`, + ` "${chalk.yellow('./nodebb help')}" for more commands\n`, ].join('\n')}`); } @@ -82,7 +83,7 @@ function stop() { function restart(options) { getRunningPid((err, pid) => { if (!err) { - console.log('\nRestarting NodeBB'.bold); + console.log(chalk.bold('\nRestarting NodeBB')); process.kill(pid, 'SIGTERM'); options.silent = true; @@ -97,20 +98,20 @@ function status() { getRunningPid((err, pid) => { if (!err) { console.log(`\n${[ - 'NodeBB Running '.bold + (`(pid ${pid.toString()})`).cyan, - `\t"${'./nodebb stop'.yellow}" to stop the NodeBB server`, - `\t"${'./nodebb log'.yellow}" to view server output`, - `\t"${'./nodebb restart'.yellow}" to restart NodeBB\n`, + chalk.bold('NodeBB Running ') + chalk.cyan(`(pid ${pid.toString()})`), + `\t"${chalk.yellow('./nodebb stop')}" to stop the NodeBB server`, + `\t"${chalk.yellow('./nodebb log')}" to view server output`, + `\t"${chalk.yellow('./nodebb restart')}" to restart NodeBB\n`, ].join('\n')}`); } else { - console.log('\nNodeBB is not running'.bold); - console.log(`\t"${'./nodebb start'.yellow}${'" to launch the NodeBB server\n'.reset}`); + console.log(chalk.bold('\nNodeBB is not running')); + console.log(`\t"${chalk.yellow('./nodebb start')}" to launch the NodeBB server\n`); } }); } function log() { - console.log('\nHit '.red + 'Ctrl-C '.bold + 'to exit\n'.red + '\n'.reset); + console.log(`${chalk.red('\nHit ') + chalk.bold('Ctrl-C ') + chalk.red('to exit\n')}\n`); childProcess.spawn('tail', ['-F', './logs/output.log'], { stdio: 'inherit', cwd, diff --git a/src/cli/upgrade-plugins.js b/src/cli/upgrade-plugins.js index 388e92bd54..863c31dd5d 100644 --- a/src/cli/upgrade-plugins.js +++ b/src/cli/upgrade-plugins.js @@ -7,6 +7,7 @@ const semver = require('semver'); const fs = require('fs'); const path = require('path'); const nconf = require('nconf'); +const chalk = require('chalk'); const { paths, pluginNamePattern } = require('../constants'); @@ -96,11 +97,11 @@ async function checkPlugins() { const toCheck = Object.keys(plugins); if (!toCheck.length) { - process.stdout.write(' OK'.green + ''.reset); + process.stdout.write(chalk.green(' OK')); return []; // no extraneous plugins installed } const suggestedModules = await getSuggestedModules(nbbVersion, toCheck); - process.stdout.write(' OK'.green + ''.reset); + process.stdout.write(chalk.green(' OK')); let current; let suggested; @@ -125,12 +126,12 @@ async function upgradePlugins() { try { const found = await checkPlugins(); if (found && found.length) { - process.stdout.write(`\n\nA total of ${String(found.length).bold} package(s) can be upgraded:\n\n`); + process.stdout.write(`\n\nA total of ${chalk.bold(String(found.length))} package(s) can be upgraded:\n\n`); found.forEach((suggestObj) => { - process.stdout.write(`${' * '.yellow + suggestObj.name.reset} (${suggestObj.current.yellow}${' -> '.reset}${suggestObj.suggested.green}${')\n'.reset}`); + process.stdout.write(`${chalk.yellow(' * ') + suggestObj.name} (${chalk.yellow(suggestObj.current)}' -> '${chalk.green(suggestObj.suggested)}')\n'`); }); } else { - console.log('\nAll packages up-to-date!'.green + ''.reset); + console.log(chalk.green('\nAll packages up-to-date!')); return; } @@ -140,7 +141,7 @@ async function upgradePlugins() { prompt.start(); const result = await prompt.get({ name: 'upgrade', - description: '\nProceed with upgrade (y|n)?'.reset, + description: '\nProceed with upgrade (y|n)?', type: 'string', }); @@ -150,10 +151,10 @@ async function upgradePlugins() { cproc.execFileSync(packageManagerExecutable, args, { stdio: 'ignore' }); } else { - console.log('Package upgrades skipped'.yellow + '. Check for upgrades at any time by running "'.reset + './nodebb upgrade -p'.green + '".'.reset); + console.log(`${chalk.yellow('Package upgrades skipped')}. Check for upgrades at any time by running "${chalk.green('./nodebb upgrade -p')}".`); } } catch (err) { - console.log('Warning'.yellow + ': An unexpected error occured when attempting to verify plugin upgradability'.reset); + console.log(`${chalk.yellow('Warning')}: An unexpected error occured when attempting to verify plugin upgradability`); throw err; } } diff --git a/src/cli/upgrade.js b/src/cli/upgrade.js index 2198203b53..5ad7e772e6 100644 --- a/src/cli/upgrade.js +++ b/src/cli/upgrade.js @@ -1,6 +1,7 @@ 'use strict'; const nconf = require('nconf'); +const chalk = require('chalk'); const packageInstall = require('./package-install'); const { upgradePlugins } = require('./upgrade-plugins'); @@ -11,13 +12,13 @@ const steps = { handler: function () { packageInstall.updatePackageFile(); packageInstall.preserveExtraneousPlugins(); - process.stdout.write(' OK\n'.green); + process.stdout.write(chalk.green(' OK\n')); }, }, install: { message: 'Bringing base dependencies up to date...', handler: function () { - process.stdout.write(' started\n'.green); + process.stdout.write(chalk.green(' started\n')); packageInstall.installAll(); }, }, @@ -49,7 +50,7 @@ async function runSteps(tasks) { for (let i = 0; i < tasks.length; i++) { const step = steps[tasks[i]]; if (step && step.message && step.handler) { - process.stdout.write(`\n${(`${i + 1}. `).bold}${step.message.yellow}`); + process.stdout.write(`\n${chalk.bold(`${i + 1}. `)}${chalk.yellow(step.message)}`); /* eslint-disable-next-line */ await step.handler(); } @@ -60,7 +61,7 @@ async function runSteps(tasks) { const { columns } = process.stdout; const spaces = columns ? new Array(Math.floor(columns / 2) - (message.length / 2) + 1).join(' ') : ' '; - console.log(`\n\n${spaces}${message.green.bold}${'\n'.reset}`); + console.log(`\n\n${spaces}${chalk.green.bold(message)}\n`); process.exit(); } catch (err) { @@ -70,7 +71,7 @@ async function runSteps(tasks) { } async function runUpgrade(upgrades, options) { - console.log('\nUpdating NodeBB...'.cyan); + console.log(chalk.cyan('\nUpdating NodeBB...')); options = options || {}; // disable mongo timeouts during upgrade nconf.set('mongo:options:socketTimeoutMS', 0); diff --git a/src/controllers/helpers.js b/src/controllers/helpers.js index bf0dc70322..a0a5340c7c 100644 --- a/src/controllers/helpers.js +++ b/src/controllers/helpers.js @@ -1,10 +1,10 @@ 'use strict'; -const colors = require('colors/safe'); const nconf = require('nconf'); const validator = require('validator'); const querystring = require('querystring'); const _ = require('lodash'); +const chalk = require('chalk'); const translator = require('../translator'); const user = require('../user'); @@ -451,7 +451,7 @@ helpers.formatApiResponse = async (statusCode, res, payload) => { if (global.env === 'development') { returnPayload.stack = payload.stack; - process.stdout.write(`[${colors.yellow('api')}] Exception caught, error with stack trace follows:\n`); + process.stdout.write(`[${chalk.yellow('api')}] Exception caught, error with stack trace follows:\n`); process.stdout.write(payload.stack); } res.status(statusCode).json(returnPayload); diff --git a/src/meta/aliases.js b/src/meta/aliases.js index ba3a50fcd1..00d7af0a53 100644 --- a/src/meta/aliases.js +++ b/src/meta/aliases.js @@ -1,6 +1,7 @@ 'use strict'; const _ = require('lodash'); +const chalk = require('chalk'); const aliases = { 'plugin static dirs': ['staticdirs'], @@ -30,7 +31,7 @@ function buildTargets() { } return [name, arr.join(', ')]; - }).map(tuple => ` ${_.padEnd(`"${tuple[0]}"`, length + 2).magenta} | ${tuple[1]}`).join('\n'); + }).map(tuple => ` ${chalk.magenta(_.padEnd(`"${tuple[0]}"`, length + 2))} | ${tuple[1]}`).join('\n'); console.log( `\n\n Build targets:\n${ (`\n ${_.padEnd('Target', length + 2)} | Aliases`).green diff --git a/src/meta/build.js b/src/meta/build.js index fec17df85a..207318fe56 100644 --- a/src/meta/build.js +++ b/src/meta/build.js @@ -6,6 +6,7 @@ const nconf = require('nconf'); const _ = require('lodash'); const path = require('path'); const mkdirp = require('mkdirp'); +const chalk = require('chalk'); const cacheBuster = require('./cacheBuster'); const { aliases } = require('./aliases'); @@ -60,8 +61,7 @@ const aliasMap = Object.keys(aliases).reduce((prev, key) => { async function beforeBuild(targets) { const db = require('../database'); - require('colors'); - process.stdout.write(' started'.green + '\n'.reset); + process.stdout.write(`${chalk.green(' started')}\n`); try { await db.init(); meta = require('./index'); diff --git a/src/meta/dependencies.js b/src/meta/dependencies.js index a5dde21fee..5bb2a73c2a 100644 --- a/src/meta/dependencies.js +++ b/src/meta/dependencies.js @@ -5,7 +5,7 @@ const fs = require('fs'); const semver = require('semver'); const winston = require('winston'); -require('colors'); +const chalk = require('chalk'); const pkg = require('../../package.json'); const { paths, pluginNamePattern } = require('../constants'); @@ -49,7 +49,7 @@ Dependencies.parseModuleData = function (moduleName, pkgData) { try { pkgData = JSON.parse(pkgData); } catch (e) { - winston.warn(`[${'missing'.red}] ${moduleName.bold} is a required dependency but could not be found\n`); + winston.warn(`[${chalk.red('missing')}] ${chalk.bold(moduleName)} is a required dependency but could not be found\n`); depsMissing = true; return null; } @@ -64,7 +64,7 @@ Dependencies.doesSatisfy = function (moduleData, packageJSONVersion) { const githubRepo = moduleData._resolved && moduleData._resolved.includes('//github.com'); const satisfies = versionOk || githubRepo; if (!satisfies) { - winston.warn(`[${'outdated'.yellow}] ${moduleData.name.bold} installed v${moduleData.version}, package.json requires ${packageJSONVersion}\n`); + winston.warn(`[${chalk.yellow('outdated')}] ${chalk.bold(moduleData.name)} installed v${moduleData.version}, package.json requires ${packageJSONVersion}\n`); depsOutdated = true; } return satisfies; diff --git a/src/plugins/index.js b/src/plugins/index.js index 04675f1a45..38110c1fe3 100644 --- a/src/plugins/index.js +++ b/src/plugins/index.js @@ -5,6 +5,7 @@ const path = require('path'); const winston = require('winston'); const semver = require('semver'); const nconf = require('nconf'); +const chalk = require('chalk'); const request = require('request-promise-native'); const user = require('../user'); @@ -117,7 +118,7 @@ Plugins.reload = async function () { console.log(''); winston.warn('[plugins/load] The following plugins may not be compatible with your version of NodeBB. This may cause unintended behaviour or crashing. In the event of an unresponsive NodeBB caused by this plugin, run `./nodebb reset -p PLUGINNAME` to disable it.'); for (let x = 0, numPlugins = Plugins.versionWarning.length; x < numPlugins; x += 1) { - console.log(' * '.yellow + Plugins.versionWarning[x]); + console.log(`${chalk.yellow(' * ') + Plugins.versionWarning[x]}`); } console.log(''); } diff --git a/src/prestart.js b/src/prestart.js index 6b1d1dfcc4..55dcb72235 100644 --- a/src/prestart.js +++ b/src/prestart.js @@ -4,6 +4,7 @@ const nconf = require('nconf'); const url = require('url'); const winston = require('winston'); const path = require('path'); +const chalk = require('chalk'); const pkg = require('../package.json'); const { paths } = require('./constants'); @@ -111,7 +112,7 @@ function versionCheck() { if (!compatible) { winston.warn('Your version of Node.js is too outdated for NodeBB. Please update your version of Node.js.'); - winston.warn(`Recommended ${range.green}${', '.reset}${version.yellow}${' provided\n'.reset}`); + winston.warn(`Recommended ${chalk.green(range)}, ${chalk.yellow(version)} provided\n`); } } diff --git a/src/upgrade.js b/src/upgrade.js index 051747b47b..829a338513 100644 --- a/src/upgrade.js +++ b/src/upgrade.js @@ -6,6 +6,7 @@ const util = require('util'); const semver = require('semver'); const readline = require('readline'); const winston = require('winston'); +const chalk = require('chalk'); const db = require('./database'); const file = require('./file'); @@ -118,7 +119,7 @@ Upgrade.runParticular = async function (names) { }; Upgrade.process = async function (files, skipCount) { - console.log('OK'.green + ' | '.reset + String(files.length).cyan + ' script(s) found'.cyan + (skipCount > 0 ? ', '.cyan + String(skipCount).cyan + ' skipped'.cyan : '')); + console.log(`${chalk.green('OK')} | ${chalk.cyan(`${files.length} script(s) found`)}${skipCount > 0 ? chalk.cyan(`, ${skipCount} skipped`) : ''}`); const [schemaDate, schemaLogCount] = await Promise.all([ db.get('schemaDate'), db.sortedSetCard('schemaLog'), @@ -138,11 +139,11 @@ Upgrade.process = async function (files, skipCount) { date: date, }; - process.stdout.write(`${' → '.white + String(`[${[date.getUTCFullYear(), date.getUTCMonth() + 1, date.getUTCDate()].join('/')}] `).gray + String(scriptExport.name).reset}...`); + process.stdout.write(`${chalk.white(' → ') + chalk.gray(`[${[date.getUTCFullYear(), date.getUTCMonth() + 1, date.getUTCDate()].join('/')}] `) + scriptExport.name}...`); // For backwards compatibility, cross-reference with schemaDate (if found). If a script's date is older, skip it if ((!schemaDate && !schemaLogCount) || (scriptExport.timestamp <= schemaDate && semver.lt(version, '1.5.0'))) { - process.stdout.write(' skipped\n'.grey); + process.stdout.write(chalk.grey(' skipped\n')); await db.sortedSetAdd('schemaLog', Date.now(), path.basename(file, '.js')); // eslint-disable-next-line no-continue @@ -165,13 +166,13 @@ Upgrade.process = async function (files, skipCount) { throw err; } const upgradeDuration = ((Date.now() - upgradeStart) / 1000).toFixed(2); - process.stdout.write(` OK (${upgradeDuration} seconds)\n`.green); + process.stdout.write(chalk.green(` OK (${upgradeDuration} seconds)\n`)); // Record success in schemaLog await db.sortedSetAdd('schemaLog', Date.now(), path.basename(file, '.js')); } - console.log('Schema update complete!\n'.green); + console.log(chalk.green('Schema update complete!\n')); }; Upgrade.incrementProgress = function (value) {