const { yellow, bold, underline, options } = require('colorette'); const commandLineUsage = require('command-line-usage'); const { core, commands } = require('../utils/cli-flags'); const { hasUnknownArgs, allNames, commands: commandNames } = require('../utils/unknown-args'); const logger = require('../utils/logger'); // This function prints a warning about invalid flag const printInvalidArgWarning = (args) => { const invalidArgs = hasUnknownArgs(args, allNames); if (invalidArgs.length > 0) { const argType = invalidArgs[0].startsWith('-') ? 'option' : 'command'; logger.warn(`You provided an invalid ${argType} '${invalidArgs[0]}'.`); } }; // This function is responsible for printing command/flag scoped help const printSubHelp = (subject, isCommand) => { const info = isCommand ? commands : core; // Contains object with details about given subject const options = info.find((commandOrFlag) => { if (isCommand) { return commandOrFlag.name == subject || commandOrFlag.alias == subject; } return commandOrFlag.name === subject.slice(2) || commandOrFlag.alias === subject.slice(1); }); const header = (head) => bold(underline(head)); const flagAlias = options.alias ? (isCommand ? ` ${options.alias} |` : ` -${options.alias},`) : ''; const usage = yellow(`webpack${flagAlias} ${options.usage}`); const description = options.description; const link = options.link; logger.raw(`${header('Usage')}: ${usage}`); logger.raw(`${header('Description')}: ${description}`); if (link) { logger.raw(`${header('Documentation')}: ${link}`); } if (options.flags) { const flags = commandLineUsage({ header: 'Options', optionList: options.flags, }); logger.raw(flags); } }; const printHelp = () => { const o = (s) => yellow(s); const options = require('../utils/cli-flags'); const negatedFlags = options.core .filter((flag) => flag.negative) .reduce((allFlags, flag) => { return [...allFlags, { name: `no-${flag.name}`, description: `Negates ${flag.name}`, type: Boolean }]; }, []); const title = bold('⬡ ') + underline('webpack') + bold(' ⬡'); const desc = 'The build tool for modern web applications'; const websitelink = ' ' + underline('https://webpack.js.org'); const usage = bold('Usage') + ': ' + '`' + o('webpack [...options] | ') + '`'; const examples = bold('Example') + ': ' + '`' + o('webpack help --flag | ') + '`'; const hh = ` ${title}\n ${websitelink}\n ${desc}\n ${usage}\n ${examples}\n `; return commandLineUsage([ { content: hh, raw: true, }, { header: 'Available Commands', content: options.commands.map((cmd) => { return { name: `${cmd.name} | ${cmd.alias}`, summary: cmd.description }; }), }, { header: 'Options', optionList: options.core .map((e) => { if (e.type.length > 1) e.type = e.type[0]; // Here we replace special characters with chalk's escape // syntax (`\$&`) to avoid chalk trying to re-process our input. // This is needed because chalk supports a form of `{var}` // interpolation. e.description = e.description.replace(/[{}\\]/g, '\\$&'); return e; }) .concat(negatedFlags), }, ]); }; const outputHelp = (cliArgs) => { options.enabled = !cliArgs.includes('--no-color'); printInvalidArgWarning(cliArgs); const flagOrCommandUsed = allNames.filter((name) => { return cliArgs.includes(name); })[0]; const isCommand = commandNames.includes(flagOrCommandUsed); // Print full help when no flag or command is supplied with help if (flagOrCommandUsed) { printSubHelp(flagOrCommandUsed, isCommand); } else { logger.raw(printHelp()); } logger.raw('\n Made with ♥️ by the webpack team'); }; module.exports = outputHelp;