You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					143 lines
				
				4.2 KiB
			
		
		
			
		
	
	
					143 lines
				
				4.2 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								const fs = require('fs')
							 | 
						||
| 
								 | 
							
								const globby = require('globby')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const renamedArrayArgs = {
							 | 
						||
| 
								 | 
							
								  ext: 'extensions',
							 | 
						||
| 
								 | 
							
								  env: 'envs',
							 | 
						||
| 
								 | 
							
								  global: 'globals',
							 | 
						||
| 
								 | 
							
								  rulesdir: 'rulePaths',
							 | 
						||
| 
								 | 
							
								  plugin: 'plugins',
							 | 
						||
| 
								 | 
							
								  'ignore-pattern': 'ignorePattern'
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const renamedArgs = {
							 | 
						||
| 
								 | 
							
								  'inline-config': 'allowInlineConfig',
							 | 
						||
| 
								 | 
							
								  rule: 'rules',
							 | 
						||
| 
								 | 
							
								  eslintrc: 'useEslintrc',
							 | 
						||
| 
								 | 
							
								  c: 'configFile',
							 | 
						||
| 
								 | 
							
								  config: 'configFile'
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = function lint (args = {}, api) {
							 | 
						||
| 
								 | 
							
								  const path = require('path')
							 | 
						||
| 
								 | 
							
								  const cwd = api.resolve('.')
							 | 
						||
| 
								 | 
							
								  const { log, done, exit, chalk, loadModule } = require('@vue/cli-shared-utils')
							 | 
						||
| 
								 | 
							
								  const { CLIEngine } = loadModule('eslint', cwd, true) || require('eslint')
							 | 
						||
| 
								 | 
							
								  const extensions = require('./eslintOptions').extensions(api)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const argsConfig = normalizeConfig(args)
							 | 
						||
| 
								 | 
							
								  const config = Object.assign({
							 | 
						||
| 
								 | 
							
								    extensions,
							 | 
						||
| 
								 | 
							
								    fix: true,
							 | 
						||
| 
								 | 
							
								    cwd
							 | 
						||
| 
								 | 
							
								  }, argsConfig)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const noFixWarnings = (argsConfig.fixWarnings === false)
							 | 
						||
| 
								 | 
							
								  const noFixWarningsPredicate = (lintResult) => lintResult.severity === 2
							 | 
						||
| 
								 | 
							
								  config.fix = config.fix && (noFixWarnings ? noFixWarningsPredicate : true)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (!fs.existsSync(api.resolve('.eslintignore')) && !config.ignorePattern) {
							 | 
						||
| 
								 | 
							
								    // .eslintrc.js files (ignored by default)
							 | 
						||
| 
								 | 
							
								    // However, we need to lint & fix them so as to make the default generated project's
							 | 
						||
| 
								 | 
							
								    // code style consistent with user's selected eslint config.
							 | 
						||
| 
								 | 
							
								    // Though, if users provided their own `.eslintignore` file, we don't want to
							 | 
						||
| 
								 | 
							
								    // add our own customized ignore pattern here (in eslint, ignorePattern is
							 | 
						||
| 
								 | 
							
								    // an addition to eslintignore, i.e. it can't be overridden by user),
							 | 
						||
| 
								 | 
							
								    // following the principle of least astonishment.
							 | 
						||
| 
								 | 
							
								    config.ignorePattern = [
							 | 
						||
| 
								 | 
							
								      '!.*.js',
							 | 
						||
| 
								 | 
							
								      '!{src,tests}/**/.*.js'
							 | 
						||
| 
								 | 
							
								    ]
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const engine = new CLIEngine(config)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const defaultFilesToLint = [
							 | 
						||
| 
								 | 
							
								    'src',
							 | 
						||
| 
								 | 
							
								    'tests',
							 | 
						||
| 
								 | 
							
								    // root config files
							 | 
						||
| 
								 | 
							
								    '*.js',
							 | 
						||
| 
								 | 
							
								    '.*.js'
							 | 
						||
| 
								 | 
							
								  ]
							 | 
						||
| 
								 | 
							
								    .filter(pattern =>
							 | 
						||
| 
								 | 
							
								      globby
							 | 
						||
| 
								 | 
							
								        .sync(pattern, { cwd, absolute: true })
							 | 
						||
| 
								 | 
							
								        .some(p => !engine.isPathIgnored(p))
							 | 
						||
| 
								 | 
							
								    )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const files = args._ && args._.length
							 | 
						||
| 
								 | 
							
								    ? args._
							 | 
						||
| 
								 | 
							
								    : defaultFilesToLint
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // mock process.cwd before executing
							 | 
						||
| 
								 | 
							
								  // See:
							 | 
						||
| 
								 | 
							
								  // https://github.com/vuejs/vue-cli/issues/2554
							 | 
						||
| 
								 | 
							
								  // https://github.com/benmosher/eslint-plugin-import/issues/602
							 | 
						||
| 
								 | 
							
								  // https://github.com/eslint/eslint/issues/11218
							 | 
						||
| 
								 | 
							
								  const processCwd = process.cwd
							 | 
						||
| 
								 | 
							
								  if (!api.invoking) {
							 | 
						||
| 
								 | 
							
								    process.cwd = () => cwd
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  const report = engine.executeOnFiles(files)
							 | 
						||
| 
								 | 
							
								  process.cwd = processCwd
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const formatter = engine.getFormatter(args.format || 'codeframe')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (config.fix) {
							 | 
						||
| 
								 | 
							
								    CLIEngine.outputFixes(report)
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const maxErrors = argsConfig.maxErrors || 0
							 | 
						||
| 
								 | 
							
								  const maxWarnings = typeof argsConfig.maxWarnings === 'number' ? argsConfig.maxWarnings : Infinity
							 | 
						||
| 
								 | 
							
								  const isErrorsExceeded = report.errorCount > maxErrors
							 | 
						||
| 
								 | 
							
								  const isWarningsExceeded = report.warningCount > maxWarnings
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (!isErrorsExceeded && !isWarningsExceeded) {
							 | 
						||
| 
								 | 
							
								    if (!args.silent) {
							 | 
						||
| 
								 | 
							
								      const hasFixed = report.results.some(f => f.output)
							 | 
						||
| 
								 | 
							
								      if (hasFixed) {
							 | 
						||
| 
								 | 
							
								        log(`The following files have been auto-fixed:`)
							 | 
						||
| 
								 | 
							
								        log()
							 | 
						||
| 
								 | 
							
								        report.results.forEach(f => {
							 | 
						||
| 
								 | 
							
								          if (f.output) {
							 | 
						||
| 
								 | 
							
								            log(`  ${chalk.blue(path.relative(cwd, f.filePath))}`)
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        })
							 | 
						||
| 
								 | 
							
								        log()
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      if (report.warningCount || report.errorCount) {
							 | 
						||
| 
								 | 
							
								        console.log(formatter(report.results))
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        done(hasFixed ? `All lint errors auto-fixed.` : `No lint errors found!`)
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    console.log(formatter(report.results))
							 | 
						||
| 
								 | 
							
								    if (isErrorsExceeded && typeof argsConfig.maxErrors === 'number') {
							 | 
						||
| 
								 | 
							
								      log(`Eslint found too many errors (maximum: ${argsConfig.maxErrors}).`)
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if (isWarningsExceeded) {
							 | 
						||
| 
								 | 
							
								      log(`Eslint found too many warnings (maximum: ${argsConfig.maxWarnings}).`)
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    exit(1)
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function normalizeConfig (args) {
							 | 
						||
| 
								 | 
							
								  const config = {}
							 | 
						||
| 
								 | 
							
								  for (const key in args) {
							 | 
						||
| 
								 | 
							
								    if (renamedArrayArgs[key]) {
							 | 
						||
| 
								 | 
							
								      config[renamedArrayArgs[key]] = args[key].split(',')
							 | 
						||
| 
								 | 
							
								    } else if (renamedArgs[key]) {
							 | 
						||
| 
								 | 
							
								      config[renamedArgs[key]] = args[key]
							 | 
						||
| 
								 | 
							
								    } else if (key !== '_') {
							 | 
						||
| 
								 | 
							
								      config[camelize(key)] = args[key]
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return config
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function camelize (str) {
							 | 
						||
| 
								 | 
							
								  return str.replace(/-(\w)/g, (_, c) => c ? c.toUpperCase() : '')
							 | 
						||
| 
								 | 
							
								}
							 |