3 const dynamicRequire = require("./dynamicRequire");
4 const getModulePath = require("./utils/getModulePath");
5 const getStdin = require("get-stdin");
6 const meow = require("meow");
7 const needlessDisablesStringFormatter = require("./formatters/needlessDisablesStringFormatter");
8 const path = require("path");
9 const resolveFrom = require("resolve-from");
10 const standalone = require("./standalone");
12 /*:: type meowOptionsType = {
17 "allow-empty-input": {
43 "disable-default-ignores": {
72 "report-needless-disables": {
101 customFormatter: any,
108 reportNeedlessDisables: any,
116 showVersion: Function
119 /*:: type optionBaseType = {
120 allowEmptyInput?: any,
132 ignoreDisables?: any,
134 reportNeedlessDisables?: any,
136 disableDefaultIgnores?: any,
140 const meowOptions /*: meowOptionsType*/ = {
144 Usage: stylelint [input] [options]
146 Input: Files(s), glob(s), or nothing to use stdin.
148 If an input argument is wrapped in quotation marks, it will be passed to
149 node-glob for cross-platform glob support. node_modules and
150 bower_components are always ignored. You can also pass no input and use
157 Path to a specific configuration file (JSON, YAML, or CommonJS), or the
158 name of a module in node_modules that points to one. If no --config
159 argument is provided, stylelint will search for configuration files in
160 the following places, in this order:
161 - a stylelint property in package.json
162 - a .stylelintrc file (with or without filename extension:
163 .json, .yaml, .yml, and .js are available)
164 - a stylelint.config.js file exporting a JS object
165 The search will begin in the working directory and move up the directory
166 tree until a configuration file is found.
170 An absolute path to the directory that relative paths defining "extends"
171 and "plugins" are *relative to*. Only necessary if these values are
176 Path to a file containing patterns that describe files to ignore. The
177 path can be absolute or relative to process.cwd(). By default, stylelint
178 looks for .stylelintignore in process.cwd().
180 --ignore-pattern, -ip
182 Pattern of files to ignore (in addition to those in .stylelintignore)
186 Specify a non-standard syntax. Options: "scss", "less", "sugarss".
187 If you do not specify a syntax, non-standard syntaxes will be
188 automatically inferred by the file extensions .scss, .less, and .sss.
192 Automatically fix violations of certain rules.
196 Module name or path to a JS file exporting a PostCSS-compatible syntax.
200 A filename to assign stdin input.
202 --ignore-disables, --id
204 Ignore styleline-disable comments.
206 --disable-default-ignores, --di
208 Allow linting of node_modules and bower_components.
210 --cache [default: false]
212 Store the info about processed files in order to only operate on the
213 changed ones the next time you run stylelint. By default, the cache
214 is stored in "./.stylelintcache". To adjust this, use --cache-location.
216 --cache-location [default: '.stylelintcache']
218 Path to a file or directory to be used for the cache location.
219 Default is "./.stylelintcache". If a directory is specified, a cache
220 file will be created inside the specified folder, with a name derived
221 from a hash of the current working directory.
223 If the directory for the cache does not exist, make sure you add a trailing "/"
224 on *nix systems or "\\" on Windows. Otherwise the path will be assumed to be a file.
226 --formatter, -f [default: "string"]
228 The output formatter: "json", "string" or "verbose".
232 Path to a JS file exporting a custom formatting function.
236 Only register warnings for rules with an "error"-level severity (ignore
242 Force enabling/disabling of color.
244 --allow-empty-input, --aei
246 If no files match glob pattern, exits without throwing an error.
248 --report-needless-disables, --rd
250 Report stylelint-disable comments that are not blocking a lint warning.
251 If you provide the argument "error", the process will exit with code 2
252 if needless disables are found.
256 Show the currently installed version of stylelint.
259 "allow-empty-input": {
279 "custom-formatter": {
285 "disable-default-ignores": {
314 "report-needless-disables": {
333 pkg: require("../package.json")
336 const cli /*: cliType*/ = meow(meowOptions);
338 let formatter = cli.flags.formatter;
339 if (cli.flags.customFormatter) {
340 const customFormatter = path.isAbsolute(cli.flags.customFormatter)
341 ? cli.flags.customFormatter
342 : path.join(process.cwd(), cli.flags.customFormatter);
343 formatter = dynamicRequire(customFormatter);
346 const optionsBase /*: optionBaseType*/ = {
351 if (cli.flags.quiet) {
352 optionsBase.configOverrides.quiet = cli.flags.quiet;
355 if (cli.flags.syntax) {
356 optionsBase.syntax = cli.flags.syntax;
359 if (cli.flags.customSyntax) {
360 optionsBase.customSyntax = getModulePath(
362 cli.flags.customSyntax
366 if (cli.flags.config) {
367 // Should check these possibilities:
368 // a. name of a node_module
370 // c. relative path relative to `process.cwd()`.
371 // If none of the above work, we'll try a relative path starting
372 // in `process.cwd()`.
373 optionsBase.configFile =
374 resolveFrom.silent(process.cwd(), cli.flags.config) ||
375 path.join(process.cwd(), cli.flags.config);
378 if (cli.flags.configBasedir) {
379 optionsBase.configBasedir = path.isAbsolute(cli.flags.configBasedir)
380 ? cli.flags.configBasedir
381 : path.resolve(process.cwd(), cli.flags.configBasedir);
384 if (cli.flags.stdinFilename) {
385 optionsBase.codeFilename = cli.flags.stdinFilename;
388 if (cli.flags.ignorePath) {
389 optionsBase.ignorePath = cli.flags.ignorePath;
392 if (cli.flags.ignorePattern) {
393 optionsBase.ignorePattern = cli.flags.ignorePattern;
396 if (cli.flags.ignoreDisables) {
397 optionsBase.ignoreDisables = cli.flags.ignoreDisables;
400 if (cli.flags.disableDefaultIgnores) {
401 optionsBase.disableDefaultIgnores = cli.flags.disableDefaultIgnores;
404 if (cli.flags.cache) {
405 optionsBase.cache = true;
408 if (cli.flags.cacheLocation) {
409 optionsBase.cacheLocation = cli.flags.cacheLocation;
413 optionsBase.fix = cli.flags.fix;
416 const reportNeedlessDisables = cli.flags.reportNeedlessDisables;
418 if (reportNeedlessDisables) {
419 optionsBase.reportNeedlessDisables = reportNeedlessDisables;
422 if (cli.flags.help || cli.flags.h) {
426 if (cli.flags.version || cli.flags.v) {
432 // Add input/code into options
433 if (cli.input.length) {
434 return Object.assign({}, optionsBase, {
438 return getStdin().then(stdin =>
439 Object.assign({}, optionsBase, {
445 if (!options.files && !options.code) {
449 return standalone(options);
452 if (reportNeedlessDisables) {
453 const hasReportNeedlessDisable =
454 !!linted.needlessDisables &&
455 linted.needlessDisables.some(sourceReport => {
456 if (!sourceReport.ranges || sourceReport.ranges.length === 0) {
463 if (hasReportNeedlessDisable) {
464 process.stdout.write(
465 needlessDisablesStringFormatter(linted.needlessDisables)
467 process.exitCode = 2;
473 if (!linted.output) {
476 process.stdout.write(linted.output);
477 if (linted.errored) {
478 process.exitCode = 2;
482 .catch((err /*: { stack: any, code: any }*/) => {
483 console.log(err.stack); // eslint-disable-line no-console
484 const exitCode = typeof err.code === "number" ? err.code : 1;
485 process.exit(exitCode); // eslint-disable-line no-process-exit