| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 | 'use strict';const EOL = require('os').EOL;const levenshtein = require('fastest-levenshtein');const { red, cyan } = require('picocolors');/** * @param {{ [key: string]: { alias?: string } }} allowedOptions * @return {string[]} */const buildAllowedOptions = (allowedOptions) => {	const options = Object.keys(allowedOptions);	for (const { alias } of Object.values(allowedOptions)) {		if (alias) {			options.push(alias);		}	}	options.sort();	return options;};/** * @param {string[]} all * @param {string} invalid * @return {null|string} */const suggest = (all, invalid) => {	const maxThreshold = 10;	for (let threshold = 1; threshold <= maxThreshold; threshold++) {		const suggestion = all.find((option) => levenshtein.distance(option, invalid) <= threshold);		if (suggestion) {			return suggestion;		}	}	return null;};/** * Converts a string to kebab case. * For example, `kebabCase('oneTwoThree') === 'one-two-three'`. * @param {string} opt * @returns {string} */const kebabCase = (opt) => {	const matches = opt.match(/[A-Z]?[a-z]+|[A-Z]|[0-9]+/g);	if (matches) {		return matches.map((s) => s.toLowerCase()).join('-');	}	return '';};/** * @param {string} opt * @return {string} */const cliOption = (opt) => {	if (opt.length === 1) {		return `"-${opt}"`;	}	return `"--${kebabCase(opt)}"`;};/** * @param {string} invalid * @param {string|null} suggestion * @return {string} */const buildMessageLine = (invalid, suggestion) => {	let line = `Invalid option ${red(cliOption(invalid))}.`;	if (suggestion) {		line += ` Did you mean ${cyan(cliOption(suggestion))}?`;	}	return line + EOL;};/** * @param {{ [key: string]: any }} allowedOptions * @param {{ [key: string]: any }} inputOptions * @return {string} */module.exports = function checkInvalidCLIOptions(allowedOptions, inputOptions) {	const allOptions = buildAllowedOptions(allowedOptions);	return Object.keys(inputOptions)		.filter((opt) => !allOptions.includes(opt))		.map((opt) => kebabCase(opt))		.reduce((msg, invalid) => {			// NOTE: No suggestion for shortcut options because it's too difficult			const suggestion = invalid.length >= 2 ? suggest(allOptions, invalid) : null;			return msg + buildMessageLine(invalid, suggestion);		}, '');};
 |