From b92f2da1eea9ce7d2df039d0c305a69bc4c2b892 Mon Sep 17 00:00:00 2001 From: Divlo Date: Tue, 14 Sep 2021 20:26:05 +0200 Subject: [PATCH] feat: usage of ES6 class syntax (#253) --- README.md | 25 +++-- bin/cmd.js | 11 +- index.js | 235 ++++++++++++++++++++------------------- test/api.js | 7 +- test/lib/standard-cmd.js | 1 + 5 files changed, 141 insertions(+), 138 deletions(-) diff --git a/README.md b/README.md index ab0d5fe..698be99 100644 --- a/README.md +++ b/README.md @@ -42,8 +42,8 @@ Create the files below and fill in your own values for `options.js`. ```js // programmatic usage -var Linter = require('standard-engine').linter -var opts = require('./options.js') +const { Linter } = require('standard-engine') +const opts = require('./options.js') module.exports = new Linter(opts) ``` @@ -52,16 +52,17 @@ module.exports = new Linter(opts) ```js #!/usr/bin/env node -var opts = require('../options.js') +const opts = require('../options.js') + require('standard-engine').cli(opts) ``` ### `options.js` ```js -var eslint = require('eslint') -var path = require('path') -var pkg = require('./package.json') +const eslint = require('eslint') +const path = require('path') +const pkg = require('./package.json') module.exports = { // homepage, version and bugs pulled from package.json @@ -78,7 +79,7 @@ module.exports = { } ``` -Additionally an optional `parseOpts()` function can be provided. See below for details. +Additionally an optional `resolveEslintConfig()` function can be provided. See below for details. ### `eslintrc.json` @@ -164,7 +165,7 @@ a `ignore` property to `package.json`: Some files are ignored by default: ```js -var DEFAULT_IGNORE = [ +const DEFAULT_IGNORE = [ '*.min.js', 'coverage/', 'node_modules/', @@ -270,9 +271,9 @@ install `babel-eslint` globally with `npm install babel-eslint -g`. You can provide a `resolveEslintConfig()` function in the `options.js` exports: ```js -var eslint = require('eslint') -var path = require('path') -var pkg = require('./package.json') +const eslint = require('eslint') +const path = require('path') +const pkg = require('./package.json') module.exports = { // homepage, version and bugs pulled from package.json @@ -330,7 +331,7 @@ The `callback` will be called with an `Error` and `results` object. The `results` object will contain the following properties: ```js -var results = { +const results = { results: [ { filePath: '', diff --git a/bin/cmd.js b/bin/cmd.js index 3ee6f85..5f0d4c6 100755 --- a/bin/cmd.js +++ b/bin/cmd.js @@ -1,13 +1,11 @@ #!/usr/bin/env node -module.exports = Cli - const minimist = require('minimist') const getStdin = require('get-stdin') /** * @typedef StandardCliOptions - * @property {import('../').linter} [linter] + * @property {import('../').Linter} [linter] * @property {string} [cmd] * @property {string} [tagline] * @property {string} [homepage] @@ -17,7 +15,7 @@ const getStdin = require('get-stdin') /** * @param {Omit & StandardCliOptions} rawOpts */ -function Cli (rawOpts) { +function cli (rawOpts) { const opts = { cmd: 'standard-engine', tagline: 'JavaScript Custom Style', @@ -25,8 +23,7 @@ function Cli (rawOpts) { ...rawOpts } - const Linter = require('../').linter - const standard = rawOpts.linter || new Linter(opts) + const standard = rawOpts.linter || new (require('../').Linter)(opts) const argv = minimist(process.argv.slice(2), { alias: { @@ -214,3 +211,5 @@ Flags (advanced): } } } + +module.exports = cli diff --git a/index.js b/index.js index d0bdf6a..14ee6c3 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,4 @@ /*! standard-engine. MIT License. Feross Aboukhadijeh */ -module.exports.cli = require('./bin/cmd') - -module.exports.linter = Linter const os = require('os') const path = require('path') @@ -24,128 +21,132 @@ const { resolveEslintConfig } = require('./lib/resolve-eslint-config') * @property {string} [version] */ -/** - * @param {LinterOptions} opts - */ -function Linter (opts) { - if (!(this instanceof Linter)) return new Linter(opts) - - if (!opts || !opts.cmd) throw new Error('opts.cmd option is required') - if (!opts.eslint) throw new Error('opts.eslint option is required') - - /** @type {string} */ - this.cmd = opts.cmd - /** @type {import('eslint')} */ - this.eslint = opts.eslint - /** @type {string} */ - this.cwd = opts.cwd || process.cwd() - this.customEslintConfigResolver = opts.resolveEslintConfig - - const m = opts.version && opts.version.match(/^(\d+)\./) - const majorVersion = (m && m[1]) || '0' - - // Example cache location: ~/.cache/standard/v12/ - const cacheLocation = path.join(CACHE_HOME, this.cmd, `v${majorVersion}/`) - - /** @type {CLIEngineOptions} */ - this.eslintConfig = { - cache: true, - cacheLocation, - envs: [], - fix: false, - globals: [], - plugins: [], - ignorePattern: [], - extensions: [], - useEslintrc: false, - ...(opts.eslintConfig || {}) +class Linter { + /** + * @param {LinterOptions} opts + */ + constructor (opts) { + if (!opts || !opts.cmd) throw new Error('opts.cmd option is required') + if (!opts.eslint) throw new Error('opts.eslint option is required') + + /** @type {string} */ + this.cmd = opts.cmd + /** @type {import('eslint')} */ + this.eslint = opts.eslint + /** @type {string} */ + this.cwd = opts.cwd || process.cwd() + this.customEslintConfigResolver = opts.resolveEslintConfig + + const m = opts.version && opts.version.match(/^(\d+)\./) + const majorVersion = (m && m[1]) || '0' + + // Example cache location: ~/.cache/standard/v12/ + const cacheLocation = path.join(CACHE_HOME, this.cmd, `v${majorVersion}/`) + + /** @type {CLIEngineOptions} */ + this.eslintConfig = { + cache: true, + cacheLocation, + envs: [], + fix: false, + globals: [], + plugins: [], + ignorePattern: [], + extensions: [], + useEslintrc: false, + ...(opts.eslintConfig || {}) + } + + if (this.eslintConfig.configFile != null) { + this.eslintConfig.resolvePluginsRelativeTo = path.dirname( + this.eslintConfig.configFile + ) + } } - if (this.eslintConfig.configFile != null) { - this.eslintConfig.resolvePluginsRelativeTo = - path.dirname(this.eslintConfig.configFile) + /** + * Lint text to enforce JavaScript Style. + * + * @param {string} text file text to lint + * @param {Omit & { filename?: string }} [opts] base options + path of file containing the text being linted + * @returns {import('eslint').CLIEngine.LintReport} + */ + lintTextSync (text, opts) { + const eslintConfig = this.resolveEslintConfig(opts) + const engine = new this.eslint.CLIEngine(eslintConfig) + return engine.executeOnText(text, (opts || {}).filename) } -} -/** - * Lint text to enforce JavaScript Style. - * - * @param {string} text file text to lint - * @param {Omit & { filename?: string }} [opts] base options + path of file containing the text being linted - * @returns {import('eslint').CLIEngine.LintReport} - */ -Linter.prototype.lintTextSync = function (text, opts) { - const eslintConfig = this.resolveEslintConfig(opts) - const engine = new this.eslint.CLIEngine(eslintConfig) - return engine.executeOnText(text, (opts || {}).filename) -} - -/** - * Lint text to enforce JavaScript Style. - * - * @param {string} text file text to lint - * @param {Omit & { filename?: string }} [opts] base options + path of file containing the text being linted - * @param {LinterCallback} [cb] - * @returns {void} - */ -Linter.prototype.lintText = function (text, opts, cb) { - if (typeof opts === 'function') return this.lintText(text, undefined, opts) - if (!cb) throw new Error('callback is required') - - let result - try { - result = this.lintTextSync(text, opts) - } catch (err) { - return process.nextTick(cb, err) + /** + * Lint text to enforce JavaScript Style. + * + * @param {string} text file text to lint + * @param {Omit & { filename?: string }} [opts] base options + path of file containing the text being linted + * @param {LinterCallback} [cb] + * @returns {void} + */ + lintText (text, opts, cb) { + if (typeof opts === 'function') return this.lintText(text, undefined, opts) + if (!cb) throw new Error('callback is required') + + let result + try { + result = this.lintTextSync(text, opts) + } catch (err) { + return process.nextTick(cb, err) + } + process.nextTick(cb, null, result) } - process.nextTick(cb, null, result) -} - -/** - * Lint files to enforce JavaScript Style. - * - * @param {Array.} files file globs to lint - * @param {BaseLintOptions & { cwd?: string }} [opts] base options + file globs to ignore (has sane defaults) + current working directory (default: process.cwd()) - * @param {LinterCallback} [cb] - * @returns {void} - */ -Linter.prototype.lintFiles = function (files, opts, cb) { - if (typeof opts === 'function') return this.lintFiles(files, undefined, opts) - if (!cb) throw new Error('callback is required') - - const eslintConfig = this.resolveEslintConfig(opts) - - if (typeof files === 'string') files = [files] - if (files.length === 0) files = ['.'] - let result - try { - result = new this.eslint.CLIEngine(eslintConfig).executeOnFiles(files) - } catch (err) { - return cb(err) + /** + * Lint files to enforce JavaScript Style. + * + * @param {Array.} files file globs to lint + * @param {BaseLintOptions & { cwd?: string }} [opts] base options + file globs to ignore (has sane defaults) + current working directory (default: process.cwd()) + * @param {LinterCallback} [cb] + * @returns {void} + */ + lintFiles (files, opts, cb) { + if (typeof opts === 'function') { return this.lintFiles(files, undefined, opts) } + if (!cb) throw new Error('callback is required') + + const eslintConfig = this.resolveEslintConfig(opts) + + if (typeof files === 'string') files = [files] + if (files.length === 0) files = ['.'] + + let result + try { + result = new this.eslint.CLIEngine(eslintConfig).executeOnFiles(files) + } catch (err) { + return cb(err) + } + + if (eslintConfig.fix) { + this.eslint.CLIEngine.outputFixes(result) + } + + return cb(null, result) } - if (eslintConfig.fix) { - this.eslint.CLIEngine.outputFixes(result) + /** + * @param {BaseLintOptions & { cwd?: string }} [opts] + * @returns {CLIEngineOptions} + */ + resolveEslintConfig (opts) { + const eslintConfig = resolveEslintConfig( + { + cwd: this.cwd, + ...opts, + cmd: this.cmd + }, + this.eslintConfig, + this.customEslintConfigResolver + ) + + return eslintConfig } - - return cb(null, result) } -/** - * @param {BaseLintOptions & { cwd?: string }} [opts] - * @returns {CLIEngineOptions} - */ -Linter.prototype.resolveEslintConfig = function (opts) { - const eslintConfig = resolveEslintConfig( - { - cwd: this.cwd, - ...opts, - cmd: this.cmd - }, - this.eslintConfig, - this.customEslintConfigResolver - ) - - return eslintConfig -} +module.exports.cli = require('./bin/cmd') +module.exports.Linter = Linter diff --git a/test/api.js b/test/api.js index cf0b40c..dd51d2b 100644 --- a/test/api.js +++ b/test/api.js @@ -1,8 +1,9 @@ const eslint = require('eslint') -const Linter = require('../').linter const path = require('path') const test = require('tape') +const { Linter } = require('../') + function getStandard () { return new Linter({ cmd: 'pocketlint', @@ -40,7 +41,7 @@ test('api: lintTextSync', function (t) { t.equal(result.errorCount, 1, 'should have used single quotes') }) -test('api: parseOpts -- avoid self.eslintConfig parser mutation', function (t) { +test('api: resolveEslintConfig -- avoid this.eslintConfig parser mutation', function (t) { t.plan(2) const standard = getStandard() const opts = standard.resolveEslintConfig({ parser: 'blah' }) @@ -48,7 +49,7 @@ test('api: parseOpts -- avoid self.eslintConfig parser mutation', function (t) { t.equal(standard.eslintConfig.parser, undefined) }) -test('api: parseOpts -- avoid self.eslintConfig global mutation', function (t) { +test('api: resolveEslintConfig -- avoid this.eslintConfig global mutation', function (t) { t.plan(2) const standard = getStandard() const opts = standard.resolveEslintConfig({ globals: ['what'] }) diff --git a/test/lib/standard-cmd.js b/test/lib/standard-cmd.js index 3eff814..2f898f9 100755 --- a/test/lib/standard-cmd.js +++ b/test/lib/standard-cmd.js @@ -1,6 +1,7 @@ #!/usr/bin/env node const path = require('path') const eslint = require('eslint') + const opts = { cmd: 'pocketlint', version: '0.0.0',