--- /dev/null
+/* @flow */
+"use strict";
+const dynamicRequire = require("./dynamicRequire");
+const getModulePath = require("./utils/getModulePath");
+const getStdin = require("get-stdin");
+const meow = require("meow");
+const needlessDisablesStringFormatter = require("./formatters/needlessDisablesStringFormatter");
+const path = require("path");
+const resolveFrom = require("resolve-from");
+const standalone = require("./standalone");
+
+/*:: type meowOptionsType = {
+ autoHelp: boolean,
+ autoVersion: boolean,
+ help: string,
+ flags: {
+ "allow-empty-input": {
+ alias: string,
+ type: string
+ },
+ cache: {
+ type: string
+ },
+ "cache-location": {
+ type: string
+ },
+ config: {
+ default: boolean,
+ type: string
+ },
+ "config-basedir": {
+ type: string
+ },
+ color: {
+ type: string
+ },
+ "custom-formatter": {
+ type: string
+ },
+ "custom-syntax": {
+ type: string
+ },
+ "disable-default-ignores": {
+ alias: string,
+ type: string
+ },
+ fix: {
+ type: string
+ },
+ formatter: {
+ alias: string,
+ default: "string",
+ type: string
+ },
+ help: {
+ alias: string,
+ type: string
+ },
+ "ignore-disables": {
+ alias: string,
+ type: string
+ },
+ "ignore-path": {
+ alias: string
+ },
+ "ignore-pattern": {
+ alias: string
+ },
+ "no-color": {
+ type: string
+ },
+ "report-needless-disables": {
+ alias: string
+ },
+ "stdin-filename": {
+ type: string
+ },
+ quiet: {
+ alias: string,
+ type: string,
+ default: boolean
+ },
+ syntax: {
+ alias: string
+ },
+ version: {
+ alias: string,
+ type: string
+ }
+ },
+ pkg: string,
+} */
+
+/*:: type cliType = {
+ flags: {
+ allowEmptyInput: any,
+ cache: any,
+ cacheLocation: any,
+ config: any,
+ configBasedir: any,
+ customFormatter: any,
+ customSyntax: any,
+ fix: any,
+ formatter: any,
+ ignoreDisables: any,
+ ignorePath: string,
+ quiet: any,
+ reportNeedlessDisables: any,
+ stdinFilename: any,
+ syntax: any,
+ },
+ input: any,
+ help: any,
+ pkg: any,
+ showHelp: Function,
+ showVersion: Function
+}*/
+
+/*:: type optionBaseType = {
+ allowEmptyInput?: any,
+ formater?: any,
+ cache?: boolean,
+ cacheLocation?: any,
+ codeFilename?: any,
+ configBasedir?: any,
+ configFile?: any,
+ configOverrides: {
+ quiet?: any,
+ },
+ customSyntax?: any,
+ fix?: any,
+ ignoreDisables?: any,
+ ignorePath?: any,
+ reportNeedlessDisables?: any,
+ syntax?: any,
+ disableDefaultIgnores?: any,
+ ignorePattern?: any
+}*/
+
+const meowOptions /*: meowOptionsType*/ = {
+ 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
+ node-glob for cross-platform glob support. node_modules and
+ bower_components 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.
+
+ --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)
+
+ --syntax, -s
+
+ Specify a non-standard syntax. Options: "scss", "less", "sugarss".
+ If you do not specify a syntax, non-standard syntaxes will be
+ automatically inferred by the file extensions .scss, .less, and .sss.
+
+ --fix
+
+ Automatically fix violations of certain rules.
+
+ --custom-syntax
+
+ Module name or path to a JS file exporting a PostCSS-compatible syntax.
+
+ --stdin-filename
+
+ A filename to assign stdin input.
+
+ --ignore-disables, --id
+
+ Ignore styleline-disable comments.
+
+ --disable-default-ignores, --di
+
+ Allow linting of node_modules and bower_components.
+
+ --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: "json", "string" or "verbose".
+
+ --custom-formatter
+
+ Path to a JS file exporting a custom formatting function.
+
+ --quiet, -q
+
+ Only register warnings for rules with an "error"-level severity (ignore
+ "warning"-level).
+
+ --color
+ --no-color
+
+ Force enabling/disabling of color.
+
+ --allow-empty-input, --aei
+
+ If no files match glob pattern, exits without throwing an error.
+
+ --report-needless-disables, --rd
+
+ Report stylelint-disable comments that are not blocking a lint warning.
+ If you provide the argument "error", the process will exit with code 2
+ if needless disables are found.
+
+ --version, -v
+
+ Show the currently installed version of stylelint.
+ `,
+ flags: {
+ "allow-empty-input": {
+ alias: "aei",
+ type: "boolean"
+ },
+ cache: {
+ type: "boolean"
+ },
+ "cache-location": {
+ type: "string"
+ },
+ config: {
+ default: false,
+ type: "string"
+ },
+ "config-basedir": {
+ type: "string"
+ },
+ color: {
+ type: "boolean"
+ },
+ "custom-formatter": {
+ type: "string"
+ },
+ "custom-syntax": {
+ type: "string"
+ },
+ "disable-default-ignores": {
+ alias: "di",
+ type: "boolean"
+ },
+ fix: {
+ type: "boolean"
+ },
+ formatter: {
+ alias: "f",
+ default: "string",
+ type: "string"
+ },
+ help: {
+ alias: "h",
+ type: "boolean"
+ },
+ "ignore-disables": {
+ alias: "id",
+ type: "boolean"
+ },
+ "ignore-path": {
+ alias: "i"
+ },
+ "ignore-pattern": {
+ alias: "ip"
+ },
+ "no-color": {
+ type: "boolean"
+ },
+ "report-needless-disables": {
+ alias: "rd"
+ },
+ "stdin-filename": {
+ type: "string"
+ },
+ quiet: {
+ alias: "q",
+ type: "boolean",
+ default: false
+ },
+ syntax: {
+ alias: "s"
+ },
+ version: {
+ alias: "v",
+ type: "boolean"
+ }
+ },
+ pkg: require("../package.json")
+};
+
+const cli /*: cliType*/ = meow(meowOptions);
+
+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 = dynamicRequire(customFormatter);
+}
+
+const optionsBase /*: optionBaseType*/ = {
+ formatter,
+ configOverrides: {}
+};
+
+if (cli.flags.quiet) {
+ optionsBase.configOverrides.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;
+}
+
+const reportNeedlessDisables = cli.flags.reportNeedlessDisables;
+
+if (reportNeedlessDisables) {
+ optionsBase.reportNeedlessDisables = reportNeedlessDisables;
+}
+
+if (cli.flags.help || cli.flags.h) {
+ cli.showHelp();
+}
+
+if (cli.flags.version || cli.flags.v) {
+ cli.showVersion();
+}
+
+Promise.resolve()
+ .then(() => {
+ // Add input/code into options
+ if (cli.input.length) {
+ return Object.assign({}, optionsBase, {
+ files: cli.input
+ });
+ }
+ return getStdin().then(stdin =>
+ Object.assign({}, optionsBase, {
+ code: stdin
+ })
+ );
+ })
+ .then(options => {
+ if (!options.files && !options.code) {
+ cli.showHelp();
+ }
+
+ return standalone(options);
+ })
+ .then(linted => {
+ if (reportNeedlessDisables) {
+ const hasReportNeedlessDisable =
+ !!linted.needlessDisables &&
+ linted.needlessDisables.some(sourceReport => {
+ if (!sourceReport.ranges || sourceReport.ranges.length === 0) {
+ return false;
+ }
+
+ return true;
+ });
+
+ if (hasReportNeedlessDisable) {
+ process.stdout.write(
+ needlessDisablesStringFormatter(linted.needlessDisables)
+ );
+ process.exitCode = 2;
+ }
+
+ return;
+ }
+
+ if (!linted.output) {
+ return;
+ }
+ process.stdout.write(linted.output);
+ if (linted.errored) {
+ process.exitCode = 2;
+ }
+ return;
+ })
+ .catch((err /*: { stack: any, code: any }*/) => {
+ console.log(err.stack); // eslint-disable-line no-console
+ const exitCode = typeof err.code === "number" ? err.code : 1;
+ process.exit(exitCode); // eslint-disable-line no-process-exit
+ });