UNPKG

stylelint

Version:

A mighty, modern CSS linter.

71 lines (52 loc) 1.79 kB
/* @flow */ 'use strict'; const _ = require('lodash'); const chalk = require('chalk'); const EOL = require('os').EOL; const leven = require('leven'); /*:: type allowedOptionsType = { [key: string]: { alias?: string } }*/ const buildAllowedOptions = (allowedOptions /*: allowedOptionsType */) => { let options = Object.keys(allowedOptions); options = options.reduce((opts, opt) => { const alias = allowedOptions[opt].alias; if (alias) { opts.push(alias); } return opts; }, options); options.sort(); return options; }; const suggest = (all /*: string[]*/, invalid /*: string*/) => { const maxThreshold = 10; for (let threshold = 1; threshold <= maxThreshold; threshold++) { const suggestion = all.find((option) => leven(option, invalid) <= threshold); if (suggestion) { return suggestion; } } return null; }; const cliOption = (opt /*: string*/) => opt.length === 1 ? `"-${opt}"` : `"--${_.kebabCase(opt)}"`; const buildMessageLine = (invalid /*: string*/, suggestion /*: ?string*/) => { let line = `Invalid option ${chalk.red(cliOption(invalid))}.`; if (suggestion) { line += ` Did you mean ${chalk.cyan(cliOption(suggestion))}?`; } return line + EOL; }; module.exports = function checkInvalidCLIOptions( allowedOptions /*: { [key: string]: any }*/, inputOptions /*: { [key: string]: any }*/, ) /*: string*/ { const allOptions = buildAllowedOptions(allowedOptions); return Object.keys(inputOptions) .map((opt) => _.kebabCase(opt)) .filter((opt) => !allOptions.includes(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); }, ''); };