From 2f34b98dcc69a9caf2961363dbef0ec712c3cb94 Mon Sep 17 00:00:00 2001 From: Tyler Hall <0tillathehun0@gmail.com> Date: Fri, 11 Dec 2020 11:50:02 -0500 Subject: [PATCH 1/3] feat: add option to configure standard via rc config file --- index.js | 11 +++++++---- package.json | 2 +- test/api.js | 19 +++++++++++++++++++ test/lib/.pocketlintrc.js | 3 +++ 4 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 test/lib/.pocketlintrc.js diff --git a/index.js b/index.js index f75b348..07a7da9 100644 --- a/index.js +++ b/index.js @@ -5,8 +5,8 @@ module.exports.linter = Linter const os = require('os') const path = require('path') -const pkgConf = require('pkg-conf') const fs = require('fs') +const { cosmiconfigSync } = require('cosmiconfig') const CACHE_HOME = require('xdg-basedir').cache || os.tmpdir() @@ -151,9 +151,12 @@ Linter.prototype.parseOpts = function (opts) { let packageOpts = {} let rootPath = null + // try default search places up to ~ + const explorerRes = cosmiconfigSync(self.cmd).search(opts.cwd) + if (opts.usePackageJson || opts.useGitIgnore) { - packageOpts = pkgConf.sync(self.cmd, { cwd: opts.cwd }) - const packageJsonPath = pkgConf.filepath(packageOpts) + packageOpts = explorerRes ? explorerRes.config : {} + const packageJsonPath = explorerRes && explorerRes.filepath if (packageJsonPath) rootPath = path.dirname(packageJsonPath) } @@ -202,7 +205,7 @@ Linter.prototype.parseOpts = function (opts) { if (self.customParseOpts) { let rootDir if (opts.usePackageJson) { - const filePath = pkgConf.filepath(packageOpts) + const filePath = explorerRes.filepath rootDir = filePath ? path.dirname(filePath) : opts.cwd } else { rootDir = opts.cwd diff --git a/package.json b/package.json index 454e807..14ab573 100644 --- a/package.json +++ b/package.json @@ -38,9 +38,9 @@ "test": "standard && tape test/clone.js test/api.js" }, "dependencies": { + "cosmiconfig": "^7.0.0", "get-stdin": "^8.0.0", "minimist": "^1.2.5", - "pkg-conf": "^3.1.0", "xdg-basedir": "^4.0.0" }, "devDependencies": { diff --git a/test/api.js b/test/api.js index a09c0c2..c38f82f 100644 --- a/test/api.js +++ b/test/api.js @@ -12,6 +12,17 @@ function getStandard () { }) } +function getStandardRcConfig () { + return new Linter({ + // start in dir containing rc file + cwd: path.resolve(__dirname, 'lib'), + cmd: 'pocketlint', + version: '0.0.0', + eslint: eslint, + eslintConfig: require('../tmp/standard/options').eslintConfig + }) +} + test('api: lintFiles', function (t) { t.plan(3) const standard = getStandard() @@ -55,3 +66,11 @@ test('api: parseOpts -- avoid self.eslintConfig global mutation', function (t) { t.deepEqual(opts.globals, ['what']) t.deepEqual(standard.eslintConfig.globals, []) }) + +test('api: parseOpts -- load config from rc file', function (t) { + t.plan(2) + const standard = getStandardRcConfig() + const opts = standard.parseOpts() + t.deepEqual(opts.globals, undefined) + t.deepEqual(opts.eslintConfig.globals, ['foorc']) +}) diff --git a/test/lib/.pocketlintrc.js b/test/lib/.pocketlintrc.js new file mode 100644 index 0000000..61ed106 --- /dev/null +++ b/test/lib/.pocketlintrc.js @@ -0,0 +1,3 @@ +module.exports = { + globals: ['foorc'] +} \ No newline at end of file From 51469dab0bc2445f451d313d6776be9df783fd0d Mon Sep 17 00:00:00 2001 From: Tyler Hall <0tillathehun0@gmail.com> Date: Fri, 11 Dec 2020 21:11:21 -0500 Subject: [PATCH 2/3] feat: fallback to XDG config directory --- index.js | 26 ++++++++++++++++++++++-- test/api.js | 22 ++++++++++++++++++-- test/lib/.xdgconfig/pocketlint/config.js | 4 ++++ 3 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 test/lib/.xdgconfig/pocketlint/config.js diff --git a/index.js b/index.js index 07a7da9..b5a4877 100644 --- a/index.js +++ b/index.js @@ -6,9 +6,10 @@ module.exports.linter = Linter const os = require('os') const path = require('path') const fs = require('fs') +const xdgBasedir = require('xdg-basedir') const { cosmiconfigSync } = require('cosmiconfig') -const CACHE_HOME = require('xdg-basedir').cache || os.tmpdir() +const CACHE_HOME = xdgBasedir.cache || os.tmpdir() const DEFAULT_EXTENSIONS = [ '.js', @@ -24,6 +25,15 @@ const DEFAULT_IGNORE = [ 'vendor/**' ] +const XDG_CONFIG_SEARCH_PLACES = [ + 'config', + 'config.json', + 'config.yaml', + 'config.yml', + 'config.js', + 'config.cjs' +] + function Linter (opts) { if (!(this instanceof Linter)) return new Linter(opts) if (!opts) opts = {} @@ -152,7 +162,19 @@ Linter.prototype.parseOpts = function (opts) { let rootPath = null // try default search places up to ~ - const explorerRes = cosmiconfigSync(self.cmd).search(opts.cwd) + let explorerRes = cosmiconfigSync(self.cmd).search(opts.cwd) + + // Fallback to XDG config base dir if no config is found + if (!explorerRes && xdgBasedir.config) { + explorerRes = cosmiconfigSync(self.cmd, { + searchPlaces: XDG_CONFIG_SEARCH_PLACES, + // Only search the specific config dir + stopDir: path.join(xdgBasedir.config) + }).search( + // ie. ~/.config/standard/config.js + path.join(xdgBasedir.config, self.cmd) + ) + } if (opts.usePackageJson || opts.useGitIgnore) { packageOpts = explorerRes ? explorerRes.config : {} diff --git a/test/api.js b/test/api.js index c38f82f..7048803 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 eslint = require('eslint') const test = require('tape') +let Linter = require('../').linter + function getStandard () { return new Linter({ cmd: 'pocketlint', @@ -74,3 +75,20 @@ test('api: parseOpts -- load config from rc file', function (t) { t.deepEqual(opts.globals, undefined) t.deepEqual(opts.eslintConfig.globals, ['foorc']) }) + +test('api: parseOpts -- load config from XDG config base dir', function (t) { + process.env.XDG_CONFIG_HOME = path.join(__dirname, 'lib', '.xdgconfig') + + delete require.cache[require.resolve('xdg-basedir')] + delete require.cache[require.resolve('../')] + + // re-require to ensure env variable is used + Linter = require('../').linter + + t.plan(2) + const standard = getStandard() + const opts = standard.parseOpts() + + t.deepEqual(opts.globals, undefined) + t.deepEqual(opts.eslintConfig.globals, ['xdgrc']) +}) diff --git a/test/lib/.xdgconfig/pocketlint/config.js b/test/lib/.xdgconfig/pocketlint/config.js new file mode 100644 index 0000000..851fbf8 --- /dev/null +++ b/test/lib/.xdgconfig/pocketlint/config.js @@ -0,0 +1,4 @@ +// used for testing loading a config from XDG config directory +module.exports = { + globals: ['xdgrc'] +} \ No newline at end of file From 83feba59a1d924374e6f13b3299220c4f8af9b50 Mon Sep 17 00:00:00 2001 From: Tyler Hall <0tillathehun0@gmail.com> Date: Sat, 12 Dec 2020 20:59:34 -0500 Subject: [PATCH 3/3] docs: update README on configuration formats --- README.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/README.md b/README.md index 7bd0b30..a02f41e 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,37 @@ For example, when passing the `src/` directory and the `extensions` option is You can disable these default ignores by setting the `noDefaultExensions` option to `true`. +### Configuration Formats + +This documentation shows examples of adding configuration to `standard-engine` via the `package.json`. Alternatively, a configuration file can be used. The configuration can be provided as follows: + +```js +[ + 'package.json', + `.pocketlintrc`, + `.pocketlintrc.json`, + `.pocketlintrc.yaml`, + `.pocketlintrc.yml`, + `.pocketlintrc.js`, + `.pocketlintrc.cjs`, + `pocketlint.config.js`, + `pocketlint.config.cjs`, +] +``` + +Configuration is searched for in the current directory. If configuration is not found, the parent directory is then searched, and so on until the user's home directory is reached. If configuration is still not found, the `XDG_CONFIG_HOME` is then searched for confguration. The configuration in the XDG config directory can be provided as follows: + +```js +[ + 'pocketlint/config', + 'pocketlint/config.json', + 'pocketlint/config.yaml', + 'pocketlint/config.yml', + 'pocketlint/config.js', + 'pocketlint/config.cjs' +] +``` + ### Ignoring Files The paths `node_modules/**`, `*.min.js`, `coverage/**`, hidden files/folders