All files / standard-engine/bin cmd.js

50.24% Statements 103/205
31.25% Branches 5/16
50% Functions 1/2
50.24% Lines 103/205

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 2062x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x       1x 1x                                                           1x 1x         1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x               1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                             1x 1x 1x 1x                 1x 1x 1x 1x 1x 1x 1x 1x                                                                           1x 1x 1x 1x 2x 2x  
#!/usr/bin/env node
 
const minimist = require('minimist')
const getStdin = require('get-stdin')
 
/**
 * @typedef StandardCliOptions
 * @property {import('../').StandardEngine} [standardEngine]
 * @property {string} [cmd]
 * @property {string} [tagline]
 * @property {string} [homepage]
 * @property {string} [bugs]
 */
 
/**
 * @param {Omit<import('../').StandardEngineOptions, 'cmd'> & StandardCliOptions} rawOpts
 * @returns {void}
 */
function cli (rawOpts) {
  const opts = {
    cmd: 'standard-engine',
    tagline: 'JavaScript Custom Style',
    version: '0.0.0',
    ...rawOpts
  }
 
  const standard = rawOpts.standardEngine || new (require('../').StandardEngine)(opts)
 
  const argv = minimist(process.argv.slice(2), {
    alias: {
      global: 'globals',
      plugin: 'plugins',
      env: 'envs',
      help: 'h'
    },
    boolean: [
      'fix',
      'help',
      'stdin',
      'version'
    ],
    string: [
      'ext',
      'global',
      'plugin',
      'parser',
      'env'
    ]
  })
 
  // Unix convention: Command line argument `-` is a shorthand for `--stdin`
  if (argv._[0] === '-') {
    argv.stdin = true
    argv._.shift()
  }
 
  if (argv.help) {
    if (opts.tagline) console.log('%s - %s (%s)', opts.cmd, opts.tagline, opts.homepage)
    console.log(`
Usage:
    ${opts.cmd} <flags> [FILES...]

    If FILES is omitted, all JavaScript source files (*.js, *.jsx, *.mjs, *.cjs)
    in the current working directory are checked, recursively.

    Certain paths (node_modules/, coverage/, vendor/, *.min.js, and
    files/folders that begin with '.' like .git/) are automatically ignored.

    Paths in a project's root .gitignore file are also automatically ignored.

Flags:
        --fix       Automatically fix problems
        --version   Show current version
    -h, --help      Show usage information

Flags (advanced):
        --stdin     Read file text from stdin
        --ext       Specify JavaScript file extensions
        --global    Declare global variable
        --plugin    Use custom eslint plugin
        --env       Use custom eslint environment
        --parser    Use custom js parser (e.g. babel-eslint)
    `)
    process.exitCode = 0
    return
  }
 
  if (argv.version) {
    console.log(opts.version)
    process.exitCode = 0
    return
  }
 
  const lintOpts = {
    fix: argv.fix,
    extensions: argv.ext,
    globals: argv.global,
    plugins: argv.plugin,
    envs: argv.env,
    parser: argv.parser
  }
 
  const outputFixed = argv.stdin && argv.fix
 
  /**
   * Print lint errors to stdout -- this is expected output from `standard-engine`.
   * Note: When fixing code from stdin (`standard --stdin --fix`), the transformed
   * code is printed to stdout, so print lint errors to stderr in this case.
   * @type {typeof console.log}
   */
  const log = (...args) => {
    if (outputFixed) {
      args[0] = opts.cmd + ': ' + args[0]
      console.error.apply(console, args)
    } else {
      console.log.apply(console, args)
    }
  }
 
  Promise.resolve(argv.stdin ? getStdin() : '').then(async stdinText => {
    /** @type {import('eslint').ESLint.LintResult[]} */
    let results
 
    try {
      results = argv.stdin
        ? await standard.lintText(stdinText, lintOpts)
        : await standard.lintFiles(argv._, lintOpts)
    } catch (err) {
      console.error(opts.cmd + ': Unexpected linter output:\n')
      if (err instanceof Error) {
        console.error(err.stack || err.message)
      } else {
        console.error(err)
      }
      console.error(
        '\nIf you think this is a bug in `%s`, open an issue: %s',
        opts.cmd,
        opts.bugs
      )
      process.exitCode = 1
      return
    }
 
    if (!results) throw new Error('expected a results')
 
    if (outputFixed) {
      if (results[0] && results[0].output) {
        // Code contained fixable errors, so print the fixed code
        process.stdout.write(results[0].output)
      } else {
        // Code did not contain fixable errors, so print original code
        process.stdout.write(stdinText)
      }
    }
 
    const hasErrors = results.some(item => item.errorCount !== 0)
    const hasWarnings = results.some(item => item.warningCount !== 0)
 
    if (!hasErrors && !hasWarnings) {
      process.exitCode = 0
      return
    }

    console.error('%s: %s (%s)', opts.cmd, opts.tagline, opts.homepage)

    if (hasWarnings) {
      const homepage = opts.homepage != null ? ` (${opts.homepage})` : ''
      console.error(
        '%s: %s',
        opts.cmd,
        `Some warnings are present which will be errors in the next version${homepage}`
      )
    }

    // Are any fixable rules present?
    const hasFixable = results.some(item => item.messages.some(message => !!message.fix))

    if (hasFixable) {
      console.error(
        '%s: %s',
        opts.cmd,
        'Run `' + opts.cmd + ' --fix` to automatically fix some problems.'
      )
    }

    for (const item of results) {
      for (const message of item.messages) {
        log(
          '  %s:%d:%d: %s%s%s',
          item.filePath,
          message.line || 0,
          message.column || 0,
          message.message,
          ' (' + message.ruleId + ')',
          message.severity === 1 ? ' (warning)' : ''
        )
      }
    }

    process.exitCode = hasErrors ? 1 : 0
  })
    .catch(err => process.nextTick(() => { throw err }))
}
 
module.exports = cli