File: //proc/1526/cwd/zaklada/html/node_modules/postcss-cli/index.js
'use strict'
const fs = require('fs-promise')
const path = require('path')
const ora = require('ora')
const stdin = require('get-stdin')
const read = require('read-cache')
const chalk = require('chalk')
const globber = require('globby')
const chokidar = require('chokidar')
const postcss = require('postcss')
const postcssrc = require('postcss-load-config')
const reporter = require('postcss-reporter/lib/formatter')()
const depGraph = require('./lib/depGraph')
const logo = `
                                      /|\\
                                    //   //
                                  //       //
                                //___*___*___//
                              //--*---------*--//
                            /|| *             * ||/
                          // ||*               *|| //
                        //   || *             * ||   //
                      //_____||___*_________*___||_____//
`
const version = () => {
  const cli = require('./package.json').version
  return chalk.bold.red(`
                                      /|\\
                                    //   //
                                  //       //
                                //___*___*___//
                              //--*---------*--//
                            /|| *             * ||/
                          // ||*    v${cli}     *|| //
                        //   || *             * ||   //
                      //_____||___*_________*___||_____//
  `)
}
const argv = require('yargs')
  .usage(
`${chalk.bold.red(logo)}
Usage:
  $0 [input.css] [OPTIONS] [--output|-o output.css] [--watch]`
)
  .option('o', {
    alias: 'output',
    desc: 'Output file',
    type: 'string'
  })
  .option('d', {
    alias: 'dir',
    desc: 'Output directory',
    type: 'string'
  })
  .option('r', {
    alias: 'replace',
    desc: 'Replace (overwrite) the input file',
    type: 'boolean'
  })
  .option('u', {
    alias: 'use',
    desc: 'List of postcss plugins to use',
    type: 'array'
  })
  .option('p', {
    alias: 'parser',
    desc: 'Custom postcss parser',
    type: 'string'
  })
  .option('t', {
    alias: 'stringifier',
    desc: 'Custom postcss stringifier',
    type: 'string'
  })
  .option('s', {
    alias: 'syntax',
    desc: 'Custom postcss syntax',
    type: 'string'
  })
  .option('w', {
    alias: 'watch',
    desc: 'Watch files for changes and recompile as needed',
    type: 'boolean'
  })
  .option('poll', {
    desc: 'Use polling for file watching',
    type: 'boolean'
  })
  .option('x', {
    alias: 'ext',
    desc: 'Override the output file extension',
    type: 'string',
    coerce (ext) {
      if (ext.indexOf('.') !== 0) return '.' + ext
      return ext
    }
  })
  .option('e', {
    alias: 'env',
    desc: 'A shortcut for setting NODE_ENV',
    type: 'string'
  })
  .option('b', {
    alias: 'base',
    desc: 'Mirror the directory structure relative to this path in the output directory, this only works together with --dir',
    type: 'string'
  })
  .option('c', {
    alias: 'config',
    desc: 'Set a custom path to look for a config file',
    type: 'string'
  })
  .alias('m', 'map')
    .describe('m', 'Create an external sourcemap')
    .describe('no-map', 'Disable the default inline sourcemaps')
  .version(version).alias('v', 'version')
  .help('h').alias('h', 'help')
  .example('$0 input.css -o output.css', 'Basic usage')
  .example('cat input.css | $0 -u autoprefixer > output.css', 'Piping input & output')
  .epilog(
`If no input files are passed, it reads from stdin. If neither -o, --dir, or --replace is passed, it writes to stdout.
If there are multiple input files, the --dir or --replace option must be passed.
For more details, please see https://github.com/postcss/postcss-cli`
  )
  .argv
let dir = argv.dir
let input = argv._
let output = argv.output
if (argv.map) argv.map = { inline: false }
const spinner = ora()
let config = {
  options: {
    map: argv.map !== undefined ? argv.map : { inline: true },
    parser: argv.parser ? require(argv.parser) : undefined,
    syntax: argv.syntax ? require(argv.syntax) : undefined,
    stringifier: argv.stringifier ? require(argv.stringifier) : undefined
  },
  plugins: argv.use
    ? argv.use.map((plugin) => {
      try {
        return require(plugin)()
      } catch (e) {
        error(`Plugin Error: Cannot find module '${plugin}'`)
      }
    })
    : []
}
if (argv.env) process.env.NODE_ENV = argv.env
if (argv.config) argv.config = path.resolve(argv.config)
Promise.resolve()
  .then(() => {
    if (input && input.length) return globber(input)
    if (argv.replace || argv.dir) error('Input Error: Cannot use --dir or --replace when reading from stdin')
    if (argv.watch) {
      error('Input Error: Cannot run in watch mode when reading from stdin')
    }
    return ['stdin']
  })
  .then((i) => {
    if (!i || !i.length) {
      error('Input Error: You must pass a valid list of files to parse')
    }
    if (i.length > 1 && !argv.dir && !argv.replace) {
      error('Input Error: Must use --dir or --replace with multiple input files')
    }
    if (i[0] !== 'stdin') i = i.map(i => path.resolve(i))
    input = i
    return files(input)
  })
  .then((results) => {
    if (argv.watch) {
      const watcher = chokidar.watch(
        input.concat(dependencies(results)),
        { usePolling: argv.poll }
      )
      if (config.file) watcher.add(config.file)
      watcher
        .on('ready', (file) => console.warn(chalk.bold.cyan('Waiting for file changes...')))
        .on('change', (file) => {
          let recompile = []
          if (~input.indexOf(file)) recompile.push(file)
          recompile = recompile.concat(
            depGraph.dependantsOf(file).filter(file => ~input.indexOf(file))
          )
          if (!recompile.length) recompile = input
          return files(recompile)
            .then((results) => watcher.add(dependencies(results)))
            .then(() => console.warn(chalk.bold.cyan('Waiting for file changes...')))
            .catch(error)
        })
    }
  })
  .catch(error)
function rc (ctx, path) {
  if (argv.use) return Promise.resolve()
  return postcssrc(ctx, path)
    .then((rc) => {
      if (rc.options.from || rc.options.to) {
        error('Config Error: Can not set from or to options in config file, use CLI arguments instead')
      }
      config = rc
    })
    .catch((err) => {
      if (err.message.indexOf('No PostCSS Config found') === -1) throw err
    })
}
function files (files) {
  if (typeof files === 'string') files = [ files ]
  return Promise.all(files.map((file) => {
    if (file === 'stdin') {
      return stdin()
        .then((content) => {
          if (!content) return error('Input Error: Did not receive any STDIN')
          return css(content, 'stdin')
        })
    }
    return read(file)
      .then((content) => css(content, file))
  }))
}
function css (css, file) {
  const ctx = { options: config.options }
  if (file !== 'stdin') {
    ctx.file = {
      dirname: path.dirname(file),
      basename: path.basename(file),
      extname: path.extname(file)
    }
    if (!argv.config) argv.config = path.dirname(file)
  }
  const relativePath = file !== 'stdin' ? path.relative(path.resolve(), file) : file
  if (!argv.config) argv.config = process.cwd()
  const time = process.hrtime()
  spinner.text = `Processing ${relativePath}`
  spinner.start()
  return rc(ctx, argv.config)
    .then(() => {
      let options = config.options
      if (file === 'stdin' && output) file = output
      // TODO: Unit test this
      options.from = file === 'stdin' ? path.join(process.cwd(), 'stdin') : file
      if (output || dir || argv.replace) {
        options.to = output || (argv.replace ? file : path.join(dir, argv.base ? file.replace(path.resolve(argv.base), '') : path.basename(file)))
        if (argv.ext) {
          options.to = options.to
            .replace(path.extname(options.to), argv.ext)
        }
        options.to = path.resolve(options.to)
      }
      if (!options.to && config.options.map && !config.options.map.inline) {
        spinner.fail()
        error('Output Error: Cannot output external sourcemaps when writing to STDOUT')
      }
      return postcss(config.plugins)
        .process(css, options)
        .then((result) => {
          const tasks = []
          if (options.to) {
            tasks.push(fs.outputFile(options.to, result.css))
            if (result.map) {
              tasks.push(
                fs.outputFile(
                  options.to
                    .replace(
                      path.extname(options.to),
                      path.extname(options.to) + '.map'
                    ),
                    result.map
                )
              )
            }
          } else {
            spinner.text = chalk.bold.green(
              `Finished ${relativePath} (${Math.round(process.hrtime(time)[1] / 1e6)}ms)`
            )
            spinner.succeed()
            return process.stdout.write(result.css, 'utf8')
          }
          return Promise.all(tasks)
            .then(() => {
              spinner.text = chalk.bold.green(
                `Finished ${relativePath} (${Math.round(process.hrtime(time)[1] / 1e6)}ms)`
              )
              if (result.warnings().length) {
                spinner.fail()
                console.warn(reporter(result))
              } else spinner.succeed()
              return result
            })
        })
    }).catch((err) => {
      spinner.fail()
      throw err
    })
}
function dependencies (results) {
  if (!Array.isArray(results)) results = [ results ]
  const messages = []
  results.forEach((result) => {
    if (result.messages <= 0) return
    result.messages
      .filter((msg) => msg.type === 'dependency' ? msg : '')
      .map(depGraph.add)
      .forEach((dependency) => messages.push(dependency.file))
  })
  return messages
}
function error (err) {
  if (typeof err === 'string') {
    spinner.fail(chalk.bold.red(err))
  } else if (err.name === 'CssSyntaxError') {
    console.error('\n')
    spinner.text = spinner.text.replace('Processing ', '')
    spinner.fail(chalk.bold.red(`Syntax Error: ${spinner.text}`))
    if (err.file) {
      err.message = err.message.substr(err.file.length + 1)
    } else {
      err.message = err.message.replace('<css input>:', '')
    }
    err.message = err.message.replace(/:\s/, '] ')
    console.error('\n', chalk.bold.red(`[${err.message}`))
    console.error('\n', err.showSourceCode(), '\n\n')
    if (argv.watch) return
  } else {
    console.error(err)
  }
  process.exit(1)
}