Skip to content

Commit 492d330

Browse files
byCedricmarionebl
authored andcommitted
fix(load): add support for factory-callback parser presets (#834)
* refactor(load): remove custom parser preset factory code * test(load): add tests with all types of conventional presets * fix(load): add support for factory-callback parser presets
1 parent db33fe7 commit 492d330

File tree

14 files changed

+119
-75
lines changed

14 files changed

+119
-75
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
parserPreset: 'conventional-changelog-angular'
3+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "parser-preset-angular",
3+
"version": "1.0.0",
4+
"devDependencies": {
5+
"conventional-changelog-angular": "5.0.5"
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
parserPreset: 'conventional-changelog-conventionalcommits'
3+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "parser-preset-conventionalcommits",
3+
"version": "1.0.0",
4+
"devDependencies": {
5+
"conventional-changelog-conventionalcommits": "4.2.1"
6+
}
7+
}

@commitlint/load/fixtures/parser-preset-factory/commitlint.config.js

-5
This file was deleted.

@commitlint/load/fixtures/parser-preset-factory/conventional-changelog-factory.js

-10
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
parserPreset: 'conventional-changelog-atom'
3+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "@second-extend/recursive-parser-preset-conventional-atom",
3+
"version": "1.0.0",
4+
"devDependencies": {
5+
"conventional-changelog-atom": "2.0.3"
6+
}
7+
}

@commitlint/load/fixtures/recursive-parser-preset-factory/first-extended/second-extended/conventional-changelog-factory.js

-10
This file was deleted.

@commitlint/load/fixtures/recursive-parser-preset-factory/first-extended/second-extended/index.js

-3
This file was deleted.

@commitlint/load/src/index.js

+47-22
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import path from 'path';
22
import executeRule from '@commitlint/execute-rule';
33
import resolveExtends from '@commitlint/resolve-extends';
44
import cosmiconfig from 'cosmiconfig';
5-
import {toPairs, merge, mergeWith, pick} from 'lodash';
5+
import {toPairs, merge, mergeWith, pick, startsWith} from 'lodash';
66
import resolveFrom from 'resolve-from';
77
import loadPlugin from './utils/loadPlugin';
88

@@ -30,20 +30,14 @@ export default async (seed = {}, options = {cwd: process.cwd()}) => {
3030
pick(config, 'extends', 'plugins', 'ignores', 'defaultIgnores')
3131
);
3232

33-
// Resolve parserPreset key from flat-non-extended config
33+
// Resolve parserPreset key when overwritten by main config
3434
if (typeof config.parserPreset === 'string') {
3535
const resolvedParserPreset = resolveFrom(base, config.parserPreset);
36-
let resolvedParserConfig = await require(resolvedParserPreset);
37-
38-
// Resolve loaded parser preset factory
39-
if (typeof resolvedParserConfig === 'function') {
40-
resolvedParserConfig = await resolvedParserConfig();
41-
}
4236

4337
config.parserPreset = {
4438
name: config.parserPreset,
4539
path: resolvedParserPreset,
46-
parserOpts: resolvedParserConfig.parserOpts
40+
parserOpts: require(resolvedParserPreset)
4741
};
4842
}
4943

@@ -55,20 +49,13 @@ export default async (seed = {}, options = {cwd: process.cwd()}) => {
5549
});
5650

5751
const preset = valid(mergeWith(extended, config, w));
58-
// Await parser-preset if applicable
59-
if (
60-
typeof preset.parserPreset === 'object' &&
61-
typeof preset.parserPreset.parserOpts === 'object' &&
62-
typeof preset.parserPreset.parserOpts.then === 'function'
63-
) {
64-
let parserPreset = await preset.parserPreset.parserOpts;
6552

66-
// Resolve loaded parser preset factory from extended config
67-
if (typeof parserPreset === 'function') {
68-
parserPreset = await parserPreset();
69-
}
70-
71-
preset.parserPreset.parserOpts = parserPreset.parserOpts;
53+
// Resolve parser-opts from preset
54+
if (typeof preset.parserPreset === 'object') {
55+
preset.parserPreset.parserOpts = await loadParserOpts(
56+
preset.parserPreset.name,
57+
preset.parserPreset
58+
);
7259
}
7360

7461
// Resolve config-relative formatter module
@@ -129,3 +116,41 @@ async function loadConfig(cwd, configPath) {
129116

130117
return {};
131118
}
119+
120+
async function loadParserOpts(parserName, pendingParser) {
121+
// Await for the module, loaded with require
122+
const parser = await pendingParser;
123+
124+
// Await parser opts if applicable
125+
if (
126+
typeof parser === 'object' &&
127+
typeof parser.parserOpts === 'object' &&
128+
typeof parser.parserOpts.then === 'function'
129+
) {
130+
return (await parser.parserOpts).parserOpts;
131+
}
132+
133+
// Create parser opts from factory
134+
if (
135+
typeof parser === 'object' &&
136+
typeof parser.parserOpts === 'function' &&
137+
startsWith(parserName, 'conventional-changelog-')
138+
) {
139+
return await new Promise(resolve => {
140+
parser.parserOpts((_, opts) => {
141+
resolve(opts.parserOpts);
142+
});
143+
});
144+
}
145+
146+
// Pull nested paserOpts, might happen if overwritten with a module in main config
147+
if (
148+
typeof parser === 'object' &&
149+
typeof parser.parserOpts === 'object' &&
150+
typeof parser.parserOpts.parserOpts === 'object'
151+
) {
152+
return parser.parserOpts.parserOpts;
153+
}
154+
155+
return parser.parserOpts;
156+
}

@commitlint/load/src/index.test.js

+42-25
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import path from 'path';
2-
import {fix, git} from '@commitlint/test';
2+
import {fix, git, npm} from '@commitlint/test';
33
import test from 'ava';
4+
import execa from 'execa';
45
import resolveFrom from 'resolve-from';
56

67
import load from '.';
@@ -84,20 +85,6 @@ test('uses seed with parserPreset', async t => {
8485
});
8586
});
8687

87-
test('uses seed with parserPreset factory', async t => {
88-
const cwd = await git.bootstrap('fixtures/parser-preset-factory');
89-
const {parserPreset: actual} = await load(
90-
{
91-
parserPreset: './conventional-changelog-factory'
92-
},
93-
{cwd}
94-
);
95-
t.is(actual.name, './conventional-changelog-factory');
96-
t.deepEqual(actual.parserOpts, {
97-
headerPattern: /^(\w*)(?:\((.*)\))?-(.*)$/
98-
});
99-
});
100-
10188
test('invalid extend should throw', async t => {
10289
const cwd = await git.bootstrap('fixtures/extends-invalid');
10390
await t.throws(load({}, {cwd}));
@@ -228,16 +215,6 @@ test('recursive extends with parserPreset', async t => {
228215
);
229216
});
230217

231-
test('recursive extends with parserPreset factory', async t => {
232-
const cwd = await git.bootstrap('fixtures/recursive-parser-preset-factory');
233-
const actual = await load({}, {cwd});
234-
235-
t.is(actual.parserPreset.name, './conventional-changelog-factory');
236-
t.deepEqual(actual.parserPreset.parserOpts, {
237-
headerPattern: /^(\w*)(?:\((.*)\))?-(.*)$/
238-
});
239-
});
240-
241218
test('ignores unknow keys', async t => {
242219
const cwd = await git.bootstrap('fixtures/trash-file');
243220
const actual = await load({}, {cwd});
@@ -351,3 +328,43 @@ test('does not mutate config module reference', async t => {
351328

352329
t.is(before, after);
353330
});
331+
332+
test('resolves parser preset from conventional commits', async t => {
333+
const cwd = await npm.bootstrap('fixtures/parser-preset-conventionalcommits');
334+
const actual = await load({}, {cwd});
335+
336+
t.is(actual.parserPreset.name, 'conventional-changelog-conventionalcommits');
337+
t.is(typeof actual.parserPreset.parserOpts, 'object');
338+
t.deepEqual(
339+
actual.parserPreset.parserOpts.headerPattern,
340+
/^(\w*)(?:\((.*)\))?!?: (.*)$/
341+
);
342+
});
343+
344+
test('resolves parser preset from conventional angular', async t => {
345+
const cwd = await npm.bootstrap('fixtures/parser-preset-angular');
346+
const actual = await load({}, {cwd});
347+
348+
t.is(actual.parserPreset.name, 'conventional-changelog-angular');
349+
t.is(typeof actual.parserPreset.parserOpts, 'object');
350+
t.deepEqual(
351+
actual.parserPreset.parserOpts.headerPattern,
352+
/^(\w*)(?:\((.*)\))?: (.*)$/
353+
);
354+
});
355+
356+
test('recursive resolves parser preset from conventional atom', async t => {
357+
const cwd = await git.bootstrap(
358+
'fixtures/recursive-parser-preset-conventional-atom'
359+
);
360+
// the package file is nested in 2 folders, `npm.bootstrap` cant do that
361+
await execa('npm', ['install'], {
362+
cwd: path.resolve(cwd, 'first-extended', 'second-extended')
363+
});
364+
365+
const actual = await load({}, {cwd});
366+
367+
t.is(actual.parserPreset.name, 'conventional-changelog-atom');
368+
t.is(typeof actual.parserPreset.parserOpts, 'object');
369+
t.deepEqual(actual.parserPreset.parserOpts.headerPattern, /^(:.*?:) (.*)$/);
370+
});

0 commit comments

Comments
 (0)