Files
react-native-devtools-frontend/node_modules/stylelint/lib/cli.js
T
Tim van der Lippe 16b822804c Reland "Reland "Update stylelint to 14.0.1""
This reverts commit 2b4a9df2d9.

Reason for revert: subsequent presubmit uploads should be fixed now.

Original change's description:
> Revert "Reland "Update stylelint to 14.0.1""
>
> This reverts commit f2ea2c940d.
>
> Reason for revert: https://ci.chromium.org/ui/p/devtools-frontend/builders/try/dtf_presubmit_linux/b8831129368825517985/overview
>
> Original change's description:
> > Reland "Update stylelint to 14.0.1"
> >
> > This reverts commit 6c0f161c95.
> >
> > Reason for revert: the prerequisite CL (https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/3259703) has landed
> >
> > Original change's description:
> > > Revert "Update stylelint to 14.0.1"
> > >
> > > This reverts commit 1e08ee816b.
> > >
> > > Reason for revert: tree is closed due to errors https://ci.chromium.org/ui/p/devtools-frontend/builders/ci/Stand-alone%20Linux/8169/overview
> > >
> > > Original change's description:
> > > > Update stylelint to 14.0.1
> > > >
> > > > This also upgrades PostCSS to 8.3.11.
> > > >
> > > > DISABLE_THIRD_PARTY_CHECK=Updating Stylelint configuration
> > > > R=​szuend@chromium.org
> > > >
> > > > Bug: none
> > > > Change-Id: I606540b03509d7c6e73f3d490327cd4174e03d31
> > > > Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/3259541
> > > > Reviewed-by: Simon Zünd <szuend@chromium.org>
> > > > Commit-Queue: Tim van der Lippe <tvanderlippe@chromium.org>
> > >
> > > Bug: none
> > > Change-Id: Icb1c02b41dbccc3b4fc5760f5dd0b78eca078b61
> > > No-Presubmit: true
> > > No-Tree-Checks: true
> > > No-Try: true
> > > Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/3263399
> > > Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
> > > Owners-Override: Alex Rudenko <alexrudenko@chromium.org>
> > > Commit-Queue: Alex Rudenko <alexrudenko@chromium.org>
> >
> > DISABLE_THIRD_PARTY_CHECK=Updating Stylelint configuration
> >
> > Bug: none
> > Change-Id: If132a67ee4253d27114caedd66c5ee61c774a6c7
> > Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/3264206
> > Commit-Queue: Tim van der Lippe <tvanderlippe@chromium.org>
> > Reviewed-by: Simon Zünd <szuend@chromium.org>
> > Reviewed-by: Alex Rudenko <alexrudenko@chromium.org>
>
> Bug: none
> Change-Id: Idc6c9f5cc1e225c752799461eb0344e94b4ad1e5
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/3264222
> Auto-Submit: Tim van der Lippe <tvanderlippe@chromium.org>
> Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
> Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>

DISABLE_THIRD_PARTY_CHECK=Updating Stylelint configuration

Bug: none
Change-Id: I609941d48b46bfcf454b03dcc75a76d460fbe674
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/3264223
Reviewed-by: Jack Franklin <jacktfranklin@chromium.org>
Commit-Queue: Tim van der Lippe <tvanderlippe@chromium.org>
2021-11-08 14:47:39 +00:00

533 lines
13 KiB
JavaScript

'use strict';
const checkInvalidCLIOptions = require('./utils/checkInvalidCLIOptions');
const EOL = require('os').EOL;
const getFormatterOptionsText = require('./utils/getFormatterOptionsText');
const getModulePath = require('./utils/getModulePath');
const getStdin = require('get-stdin');
const meow = require('meow');
const path = require('path');
const printConfig = require('./printConfig');
const resolveFrom = require('resolve-from');
const standalone = require('./standalone');
const writeOutputFile = require('./writeOutputFile');
const { red, dim } = require('picocolors');
const EXIT_CODE_ERROR = 2;
/**
* @typedef {object} CLIFlags
* @property {boolean} [cache]
* @property {string} [cacheLocation]
* @property {string | false} config
* @property {string} [configBasedir]
* @property {string} [customSyntax]
* @property {string} [printConfig]
* @property {string} [color]
* @property {string} [customFormatter]
* @property {boolean} [disableDefaultIgnores]
* @property {boolean} [fix]
* @property {string} [formatter="string"]
* @property {string} [help]
* @property {boolean} [ignoreDisables]
* @property {string} [ignorePath]
* @property {string[]} [ignorePattern]
* @property {string} [noColor]
* @property {string} [outputFile]
* @property {boolean} [stdin]
* @property {string} [stdinFilename]
* @property {boolean} [reportNeedlessDisables]
* @property {boolean} [reportInvalidScopeDisables]
* @property {boolean} [reportDescriptionlessDisables]
* @property {number} [maxWarnings]
* @property {boolean} quiet
* @property {string} [syntax]
* @property {string} [version]
* @property {boolean} [allowEmptyInput]
*/
/**
* @typedef {object} CLIOptions
* @property {any} input
* @property {any} help
* @property {any} pkg
* @property {Function} showHelp
* @property {Function} showVersion
* @property {CLIFlags} flags
*/
/**
* @typedef {object} OptionBaseType
* @property {any} formatter
* @property {boolean} [cache]
* @property {string} [configFile]
* @property {string} [cacheLocation]
* @property {string} [customSyntax]
* @property {string} [codeFilename]
* @property {string} [configBasedir]
* @property {boolean} [quiet]
* @property {any} [printConfig]
* @property {boolean} [fix]
* @property {boolean} [ignoreDisables]
* @property {any} [ignorePath]
* @property {string} [outputFile]
* @property {boolean} [reportNeedlessDisables]
* @property {boolean} [reportInvalidScopeDisables]
* @property {boolean} [reportDescriptionlessDisables]
* @property {boolean} [disableDefaultIgnores]
* @property {number} [maxWarnings]
* @property {string} [syntax]
* @property {string[]} [ignorePattern]
* @property {boolean} [allowEmptyInput]
* @property {string} [files]
* @property {string} [code]
*/
const meowOptions = {
autoHelp: false,
autoVersion: false,
help: `
Usage: stylelint [input] [options]
Input: Files(s), glob(s), or nothing to use stdin.
If an input argument is wrapped in quotation marks, it will be passed to
globby for cross-platform glob support. node_modules are always ignored.
You can also pass no input and use stdin, instead.
Options:
--config
Path to a specific configuration file (JSON, YAML, or CommonJS), or the
name of a module in node_modules that points to one. If no --config
argument is provided, stylelint will search for configuration files in
the following places, in this order:
- a stylelint property in package.json
- a .stylelintrc file (with or without filename extension:
.json, .yaml, .yml, and .js are available)
- a stylelint.config.js file exporting a JS object
The search will begin in the working directory and move up the directory
tree until a configuration file is found.
--config-basedir
An absolute path to the directory that relative paths defining "extends"
and "plugins" are *relative to*. Only necessary if these values are
relative paths.
--print-config
Print the configuration for the given path.
--ignore-path, -i
Path to a file containing patterns that describe files to ignore. The
path can be absolute or relative to process.cwd(). By default, stylelint
looks for .stylelintignore in process.cwd().
--ignore-pattern, --ip
Pattern of files to ignore (in addition to those in .stylelintignore)
--fix
Automatically fix problems of certain rules.
--custom-syntax
Module name or path to a JS file exporting a PostCSS-compatible syntax.
--stdin
Accept stdin input even if it is empty.
--stdin-filename
A filename to assign stdin input.
--ignore-disables, --id
Ignore stylelint-disable comments.
--disable-default-ignores, --di
Allow linting of node_modules.
--cache [default: false]
Store the info about processed files in order to only operate on the
changed ones the next time you run stylelint. By default, the cache
is stored in "./.stylelintcache". To adjust this, use --cache-location.
--cache-location [default: '.stylelintcache']
Path to a file or directory to be used for the cache location.
Default is "./.stylelintcache". If a directory is specified, a cache
file will be created inside the specified folder, with a name derived
from a hash of the current working directory.
If the directory for the cache does not exist, make sure you add a trailing "/"
on *nix systems or "\\" on Windows. Otherwise the path will be assumed to be a file.
--formatter, -f [default: "string"]
The output formatter: ${getFormatterOptionsText({ useOr: true })}.
--custom-formatter
Path to a JS file exporting a custom formatting function.
--quiet, -q
Only register problems for rules with an "error"-level severity (ignore
"warning"-level).
--color
--no-color
Force enabling/disabling of color.
--report-needless-disables, --rd
Also report errors for stylelint-disable comments that are not blocking a lint warning.
The process will exit with code ${EXIT_CODE_ERROR} if needless disables are found.
--report-invalid-scope-disables, --risd
Report stylelint-disable comments that used for rules that don't exist within the configuration object.
The process will exit with code ${EXIT_CODE_ERROR} if invalid scope disables are found.
--report-descriptionless-disables, --rdd
Report stylelint-disable comments without a description.
The process will exit with code ${EXIT_CODE_ERROR} if descriptionless disables are found.
--max-warnings, --mw
Number of warnings above which the process will exit with code ${EXIT_CODE_ERROR}.
Useful when setting "defaultSeverity" to "warning" and expecting the
process to fail on warnings (e.g. CI build).
--output-file, -o
Path of file to write report.
--version, -v
Show the currently installed version of stylelint.
--allow-empty-input, --aei
When glob pattern matches no files, the process will exit without throwing an error.
`,
flags: {
allowEmptyInput: {
alias: 'aei',
type: 'boolean',
},
cache: {
type: 'boolean',
},
cacheLocation: {
type: 'string',
},
color: {
type: 'boolean',
},
config: {
type: 'string',
},
configBasedir: {
type: 'string',
},
customFormatter: {
type: 'string',
},
customSyntax: {
type: 'string',
},
disableDefaultIgnores: {
alias: 'di',
type: 'boolean',
},
fix: {
type: 'boolean',
},
formatter: {
alias: 'f',
default: 'string',
type: 'string',
},
help: {
alias: 'h',
type: 'boolean',
},
ignoreDisables: {
alias: 'id',
type: 'boolean',
},
ignorePath: {
alias: 'i',
type: 'string',
},
ignorePattern: {
alias: 'ip',
type: 'string',
isMultiple: true,
},
maxWarnings: {
alias: 'mw',
type: 'number',
},
outputFile: {
alias: 'o',
type: 'string',
},
printConfig: {
type: 'boolean',
},
quiet: {
alias: 'q',
type: 'boolean',
},
reportDescriptionlessDisables: {
alias: 'rdd',
type: 'boolean',
},
reportInvalidScopeDisables: {
alias: 'risd',
type: 'boolean',
},
reportNeedlessDisables: {
alias: 'rd',
type: 'boolean',
},
stdin: {
type: 'boolean',
},
stdinFilename: {
type: 'string',
},
syntax: {
alias: 's',
type: 'string',
},
version: {
alias: 'v',
type: 'boolean',
},
},
};
/**
* @param {string[]} argv
* @returns {Promise<any>}
*/
module.exports = async (argv) => {
const cli = buildCLI(argv);
const invalidOptionsMessage = checkInvalidCLIOptions(meowOptions.flags, cli.flags);
if (invalidOptionsMessage) {
process.stderr.write(invalidOptionsMessage);
process.exit(EXIT_CODE_ERROR); // eslint-disable-line no-process-exit
}
let formatter = cli.flags.formatter;
if (cli.flags.customFormatter) {
const customFormatter = path.isAbsolute(cli.flags.customFormatter)
? cli.flags.customFormatter
: path.join(process.cwd(), cli.flags.customFormatter);
formatter = require(customFormatter);
}
/** @type {OptionBaseType} */
const optionsBase = {
formatter,
};
if (cli.flags.quiet) {
optionsBase.quiet = cli.flags.quiet;
}
if (cli.flags.syntax) {
optionsBase.syntax = cli.flags.syntax;
}
if (cli.flags.customSyntax) {
optionsBase.customSyntax = getModulePath(process.cwd(), cli.flags.customSyntax);
}
if (cli.flags.config) {
// Should check these possibilities:
// a. name of a node_module
// b. absolute path
// c. relative path relative to `process.cwd()`.
// If none of the above work, we'll try a relative path starting
// in `process.cwd()`.
optionsBase.configFile =
resolveFrom.silent(process.cwd(), cli.flags.config) ||
path.join(process.cwd(), cli.flags.config);
}
if (cli.flags.configBasedir) {
optionsBase.configBasedir = path.isAbsolute(cli.flags.configBasedir)
? cli.flags.configBasedir
: path.resolve(process.cwd(), cli.flags.configBasedir);
}
if (cli.flags.stdinFilename) {
optionsBase.codeFilename = cli.flags.stdinFilename;
}
if (cli.flags.ignorePath) {
optionsBase.ignorePath = cli.flags.ignorePath;
}
if (cli.flags.ignorePattern) {
optionsBase.ignorePattern = cli.flags.ignorePattern;
}
if (cli.flags.ignoreDisables) {
optionsBase.ignoreDisables = cli.flags.ignoreDisables;
}
if (cli.flags.disableDefaultIgnores) {
optionsBase.disableDefaultIgnores = cli.flags.disableDefaultIgnores;
}
if (cli.flags.cache) {
optionsBase.cache = true;
}
if (cli.flags.cacheLocation) {
optionsBase.cacheLocation = cli.flags.cacheLocation;
}
if (cli.flags.fix) {
optionsBase.fix = cli.flags.fix;
}
if (cli.flags.outputFile) {
optionsBase.outputFile = cli.flags.outputFile;
}
const reportNeedlessDisables = cli.flags.reportNeedlessDisables;
const reportInvalidScopeDisables = cli.flags.reportInvalidScopeDisables;
const reportDescriptionlessDisables = cli.flags.reportDescriptionlessDisables;
if (reportNeedlessDisables) {
optionsBase.reportNeedlessDisables = reportNeedlessDisables;
}
if (reportInvalidScopeDisables) {
optionsBase.reportInvalidScopeDisables = reportInvalidScopeDisables;
}
if (reportDescriptionlessDisables) {
optionsBase.reportDescriptionlessDisables = reportDescriptionlessDisables;
}
const maxWarnings = cli.flags.maxWarnings;
if (maxWarnings !== undefined) {
optionsBase.maxWarnings = maxWarnings;
}
if (cli.flags.help) {
cli.showHelp(0);
return;
}
if (cli.flags.version) {
cli.showVersion();
return;
}
if (cli.flags.allowEmptyInput) {
optionsBase.allowEmptyInput = cli.flags.allowEmptyInput;
}
// Add input/code into options
/** @type {OptionBaseType} */
const options = cli.input.length
? {
...optionsBase,
files: /** @type {string} */ (cli.input),
}
: await getStdin().then((stdin) => {
return {
...optionsBase,
code: stdin,
};
});
if (cli.flags.printConfig) {
return printConfig(options)
.then((config) => {
process.stdout.write(JSON.stringify(config, null, ' '));
})
.catch(handleError);
}
if (!options.files && !options.code && !cli.flags.stdin) {
cli.showHelp();
return;
}
return standalone(options)
.then((linted) => {
if (!linted.output) {
return;
}
process.stdout.write(linted.output);
if (options.outputFile) {
writeOutputFile(linted.output, options.outputFile).catch(handleError);
}
if (linted.errored) {
process.exitCode = EXIT_CODE_ERROR;
} else if (maxWarnings !== undefined && linted.maxWarningsExceeded) {
const foundWarnings = linted.maxWarningsExceeded.foundWarnings;
process.stderr.write(
`${EOL}${red(`Max warnings exceeded: `)}${foundWarnings} found. ${dim(
`${maxWarnings} allowed${EOL}${EOL}`,
)}`,
);
process.exitCode = EXIT_CODE_ERROR;
}
})
.catch(handleError);
};
/**
* @param {{ stack: any, code: any }} err
* @returns {void}
*/
function handleError(err) {
process.stderr.write(err.stack + EOL);
const exitCode = typeof err.code === 'number' ? err.code : 1;
process.exitCode = exitCode;
}
/**
* @param {string[]} argv
* @returns {CLIOptions}
*/
function buildCLI(argv) {
// @ts-expect-error -- TODO TYPES
return meow({ ...meowOptions, argv });
}
module.exports.buildCLI = buildCLI;