diff --git a/@commitlint/load/fixtures/parser-preset-angular/commitlint.config.js b/@commitlint/load/fixtures/parser-preset-angular/commitlint.config.js new file mode 100644 index 0000000000..87e6b2c00f --- /dev/null +++ b/@commitlint/load/fixtures/parser-preset-angular/commitlint.config.js @@ -0,0 +1,3 @@ +module.exports = { + parserPreset: 'conventional-changelog-angular' +}; diff --git a/@commitlint/load/fixtures/parser-preset-angular/package.json b/@commitlint/load/fixtures/parser-preset-angular/package.json new file mode 100644 index 0000000000..200d4ce9af --- /dev/null +++ b/@commitlint/load/fixtures/parser-preset-angular/package.json @@ -0,0 +1,7 @@ +{ + "name": "parser-preset-angular", + "version": "1.0.0", + "devDependencies": { + "conventional-changelog-angular": "5.0.5" + } +} diff --git a/@commitlint/load/fixtures/parser-preset-conventionalcommits/commitlint.config.js b/@commitlint/load/fixtures/parser-preset-conventionalcommits/commitlint.config.js new file mode 100644 index 0000000000..46aa41e38f --- /dev/null +++ b/@commitlint/load/fixtures/parser-preset-conventionalcommits/commitlint.config.js @@ -0,0 +1,3 @@ +module.exports = { + parserPreset: 'conventional-changelog-conventionalcommits' +}; diff --git a/@commitlint/load/fixtures/parser-preset-conventionalcommits/package.json b/@commitlint/load/fixtures/parser-preset-conventionalcommits/package.json new file mode 100644 index 0000000000..bc3ef683be --- /dev/null +++ b/@commitlint/load/fixtures/parser-preset-conventionalcommits/package.json @@ -0,0 +1,7 @@ +{ + "name": "parser-preset-conventionalcommits", + "version": "1.0.0", + "devDependencies": { + "conventional-changelog-conventionalcommits": "4.2.1" + } +} diff --git a/@commitlint/load/fixtures/parser-preset-factory/commitlint.config.js b/@commitlint/load/fixtures/parser-preset-factory/commitlint.config.js deleted file mode 100644 index f3dd71ee2a..0000000000 --- a/@commitlint/load/fixtures/parser-preset-factory/commitlint.config.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - parserOpts: { - parserPreset: './conventional-changelog-factory' - } -}; diff --git a/@commitlint/load/fixtures/parser-preset-factory/conventional-changelog-factory.js b/@commitlint/load/fixtures/parser-preset-factory/conventional-changelog-factory.js deleted file mode 100644 index 7ac0b81719..0000000000 --- a/@commitlint/load/fixtures/parser-preset-factory/conventional-changelog-factory.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = Promise.resolve().then( - () => - function factory() { - return { - parserOpts: { - headerPattern: /^(\w*)(?:\((.*)\))?-(.*)$/ - } - }; - } -); diff --git a/@commitlint/load/fixtures/recursive-parser-preset-factory/commitlint.config.js b/@commitlint/load/fixtures/recursive-parser-preset-conventional-atom/commitlint.config.js similarity index 100% rename from @commitlint/load/fixtures/recursive-parser-preset-factory/commitlint.config.js rename to @commitlint/load/fixtures/recursive-parser-preset-conventional-atom/commitlint.config.js diff --git a/@commitlint/load/fixtures/recursive-parser-preset-factory/first-extended/index.js b/@commitlint/load/fixtures/recursive-parser-preset-conventional-atom/first-extended/index.js similarity index 100% rename from @commitlint/load/fixtures/recursive-parser-preset-factory/first-extended/index.js rename to @commitlint/load/fixtures/recursive-parser-preset-conventional-atom/first-extended/index.js diff --git a/@commitlint/load/fixtures/recursive-parser-preset-conventional-atom/first-extended/second-extended/index.js b/@commitlint/load/fixtures/recursive-parser-preset-conventional-atom/first-extended/second-extended/index.js new file mode 100644 index 0000000000..e858146679 --- /dev/null +++ b/@commitlint/load/fixtures/recursive-parser-preset-conventional-atom/first-extended/second-extended/index.js @@ -0,0 +1,3 @@ +module.exports = { + parserPreset: 'conventional-changelog-atom' +}; diff --git a/@commitlint/load/fixtures/recursive-parser-preset-conventional-atom/first-extended/second-extended/package.json b/@commitlint/load/fixtures/recursive-parser-preset-conventional-atom/first-extended/second-extended/package.json new file mode 100644 index 0000000000..ae831e512d --- /dev/null +++ b/@commitlint/load/fixtures/recursive-parser-preset-conventional-atom/first-extended/second-extended/package.json @@ -0,0 +1,7 @@ +{ + "name": "@second-extend/recursive-parser-preset-conventional-atom", + "version": "1.0.0", + "devDependencies": { + "conventional-changelog-atom": "2.0.3" + } +} diff --git a/@commitlint/load/fixtures/recursive-parser-preset-factory/first-extended/second-extended/conventional-changelog-factory.js b/@commitlint/load/fixtures/recursive-parser-preset-factory/first-extended/second-extended/conventional-changelog-factory.js deleted file mode 100644 index 7ac0b81719..0000000000 --- a/@commitlint/load/fixtures/recursive-parser-preset-factory/first-extended/second-extended/conventional-changelog-factory.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = Promise.resolve().then( - () => - function factory() { - return { - parserOpts: { - headerPattern: /^(\w*)(?:\((.*)\))?-(.*)$/ - } - }; - } -); diff --git a/@commitlint/load/fixtures/recursive-parser-preset-factory/first-extended/second-extended/index.js b/@commitlint/load/fixtures/recursive-parser-preset-factory/first-extended/second-extended/index.js deleted file mode 100644 index bb423b3f4e..0000000000 --- a/@commitlint/load/fixtures/recursive-parser-preset-factory/first-extended/second-extended/index.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - parserPreset: './conventional-changelog-factory' -}; diff --git a/@commitlint/load/src/index.js b/@commitlint/load/src/index.js index 0167c53ded..23030ce3d9 100644 --- a/@commitlint/load/src/index.js +++ b/@commitlint/load/src/index.js @@ -2,7 +2,7 @@ import path from 'path'; import executeRule from '@commitlint/execute-rule'; import resolveExtends from '@commitlint/resolve-extends'; import cosmiconfig from 'cosmiconfig'; -import {toPairs, merge, mergeWith, pick} from 'lodash'; +import {toPairs, merge, mergeWith, pick, startsWith} from 'lodash'; import resolveFrom from 'resolve-from'; import loadPlugin from './utils/loadPlugin'; @@ -30,20 +30,14 @@ export default async (seed = {}, options = {cwd: process.cwd()}) => { pick(config, 'extends', 'plugins', 'ignores', 'defaultIgnores') ); - // Resolve parserPreset key from flat-non-extended config + // Resolve parserPreset key when overwritten by main config if (typeof config.parserPreset === 'string') { const resolvedParserPreset = resolveFrom(base, config.parserPreset); - let resolvedParserConfig = await require(resolvedParserPreset); - - // Resolve loaded parser preset factory - if (typeof resolvedParserConfig === 'function') { - resolvedParserConfig = await resolvedParserConfig(); - } config.parserPreset = { name: config.parserPreset, path: resolvedParserPreset, - parserOpts: resolvedParserConfig.parserOpts + parserOpts: require(resolvedParserPreset) }; } @@ -55,20 +49,13 @@ export default async (seed = {}, options = {cwd: process.cwd()}) => { }); const preset = valid(mergeWith(extended, config, w)); - // Await parser-preset if applicable - if ( - typeof preset.parserPreset === 'object' && - typeof preset.parserPreset.parserOpts === 'object' && - typeof preset.parserPreset.parserOpts.then === 'function' - ) { - let parserPreset = await preset.parserPreset.parserOpts; - // Resolve loaded parser preset factory from extended config - if (typeof parserPreset === 'function') { - parserPreset = await parserPreset(); - } - - preset.parserPreset.parserOpts = parserPreset.parserOpts; + // Resolve parser-opts from preset + if (typeof preset.parserPreset === 'object') { + preset.parserPreset.parserOpts = await loadParserOpts( + preset.parserPreset.name, + preset.parserPreset + ); } // Resolve config-relative formatter module @@ -129,3 +116,41 @@ async function loadConfig(cwd, configPath) { return {}; } + +async function loadParserOpts(parserName, pendingParser) { + // Await for the module, loaded with require + const parser = await pendingParser; + + // Await parser opts if applicable + if ( + typeof parser === 'object' && + typeof parser.parserOpts === 'object' && + typeof parser.parserOpts.then === 'function' + ) { + return (await parser.parserOpts).parserOpts; + } + + // Create parser opts from factory + if ( + typeof parser === 'object' && + typeof parser.parserOpts === 'function' && + startsWith(parserName, 'conventional-changelog-') + ) { + return await new Promise(resolve => { + parser.parserOpts((_, opts) => { + resolve(opts.parserOpts); + }); + }); + } + + // Pull nested paserOpts, might happen if overwritten with a module in main config + if ( + typeof parser === 'object' && + typeof parser.parserOpts === 'object' && + typeof parser.parserOpts.parserOpts === 'object' + ) { + return parser.parserOpts.parserOpts; + } + + return parser.parserOpts; +} diff --git a/@commitlint/load/src/index.test.js b/@commitlint/load/src/index.test.js index 14c6398436..67eb5bd2c3 100644 --- a/@commitlint/load/src/index.test.js +++ b/@commitlint/load/src/index.test.js @@ -1,6 +1,7 @@ import path from 'path'; -import {fix, git} from '@commitlint/test'; +import {fix, git, npm} from '@commitlint/test'; import test from 'ava'; +import execa from 'execa'; import resolveFrom from 'resolve-from'; import load from '.'; @@ -84,20 +85,6 @@ test('uses seed with parserPreset', async t => { }); }); -test('uses seed with parserPreset factory', async t => { - const cwd = await git.bootstrap('fixtures/parser-preset-factory'); - const {parserPreset: actual} = await load( - { - parserPreset: './conventional-changelog-factory' - }, - {cwd} - ); - t.is(actual.name, './conventional-changelog-factory'); - t.deepEqual(actual.parserOpts, { - headerPattern: /^(\w*)(?:\((.*)\))?-(.*)$/ - }); -}); - test('invalid extend should throw', async t => { const cwd = await git.bootstrap('fixtures/extends-invalid'); await t.throws(load({}, {cwd})); @@ -228,16 +215,6 @@ test('recursive extends with parserPreset', async t => { ); }); -test('recursive extends with parserPreset factory', async t => { - const cwd = await git.bootstrap('fixtures/recursive-parser-preset-factory'); - const actual = await load({}, {cwd}); - - t.is(actual.parserPreset.name, './conventional-changelog-factory'); - t.deepEqual(actual.parserPreset.parserOpts, { - headerPattern: /^(\w*)(?:\((.*)\))?-(.*)$/ - }); -}); - test('ignores unknow keys', async t => { const cwd = await git.bootstrap('fixtures/trash-file'); const actual = await load({}, {cwd}); @@ -351,3 +328,43 @@ test('does not mutate config module reference', async t => { t.is(before, after); }); + +test('resolves parser preset from conventional commits', async t => { + const cwd = await npm.bootstrap('fixtures/parser-preset-conventionalcommits'); + const actual = await load({}, {cwd}); + + t.is(actual.parserPreset.name, 'conventional-changelog-conventionalcommits'); + t.is(typeof actual.parserPreset.parserOpts, 'object'); + t.deepEqual( + actual.parserPreset.parserOpts.headerPattern, + /^(\w*)(?:\((.*)\))?!?: (.*)$/ + ); +}); + +test('resolves parser preset from conventional angular', async t => { + const cwd = await npm.bootstrap('fixtures/parser-preset-angular'); + const actual = await load({}, {cwd}); + + t.is(actual.parserPreset.name, 'conventional-changelog-angular'); + t.is(typeof actual.parserPreset.parserOpts, 'object'); + t.deepEqual( + actual.parserPreset.parserOpts.headerPattern, + /^(\w*)(?:\((.*)\))?: (.*)$/ + ); +}); + +test('recursive resolves parser preset from conventional atom', async t => { + const cwd = await git.bootstrap( + 'fixtures/recursive-parser-preset-conventional-atom' + ); + // the package file is nested in 2 folders, `npm.bootstrap` cant do that + await execa('npm', ['install'], { + cwd: path.resolve(cwd, 'first-extended', 'second-extended') + }); + + const actual = await load({}, {cwd}); + + t.is(actual.parserPreset.name, 'conventional-changelog-atom'); + t.is(typeof actual.parserPreset.parserOpts, 'object'); + t.deepEqual(actual.parserPreset.parserOpts.headerPattern, /^(:.*?:) (.*)$/); +});