Skip to content

Commit efce01a

Browse files
committed
feat: support for dynamic and async rules
1 parent 91806a2 commit efce01a

File tree

3 files changed

+54
-16
lines changed

3 files changed

+54
-16
lines changed

documentation/rules.md

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,36 @@
11
# Rules
2+
Rules are made up by a name and a configuration array. The configuration array contains:
3+
* **Level** `[0..2]`: `0` disables the rule. For `1` it will be considered a warning for `2` an error.
4+
* **Applicable** `always|never`: `never` inverts the rule.
5+
* **Value**: value to use for this rule.
6+
7+
Rule configurations are either of type `array` residing on a key with the rule's name as key on the rules `object` or of type function returning type `array` or `Promise<array>`. This means all of the following notations are supported.
8+
9+
**Plain array**
210
```js
311
"rules": {
412
"header-max-length": [0, "always", 72],
5-
// name: [level, applicable, value]
613
}
714
```
8-
Rules are made up by a name and a configuration array. The configuration array contains:
9-
* **Level** `[0..2]`: `0` disables the rule. For `1` it will be considered a warning for `2` an error.
10-
* **Applicable** `always|never`: `never` inverts the rule.
11-
* **Value**: value to use for this rule.
15+
**Function returning array**
16+
```js
17+
"rules": {
18+
"header-max-length": () => [0, "always", 72],
19+
}
20+
```
21+
**Async function returning array**
22+
```js
23+
"rules": {
24+
"header-max-length": async () => [0, "always", 72],
25+
}
26+
```
27+
**Function returning a promise resolving to array**
28+
```js
29+
"rules": {
30+
"header-max-length": () => Promise.resolve([0, "always", 72]),
31+
}
32+
```
33+
1234

1335
### Available rules
1436
#### type-enum

source/cli.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ async function main(options) {
9898
seed.extends = flags.extends.split(',');
9999
}
100100

101-
const report = lint(commit, {
101+
const report = await lint(commit, {
102102
preset: await getPreset(flags.preset),
103103
configuration: await getConfiguration(
104104
'conventional-changelog-lint',
@@ -117,10 +117,7 @@ async function main(options) {
117117

118118
if (!flags.quiet) {
119119
console.log(`${fmt.grey('⧗')} input: ${fmt.bold(commit.split('\n')[0])}`);
120-
console.log(
121-
formatted
122-
.join('\n')
123-
);
120+
console.log(formatted.join('\n'));
124121
}
125122

126123
if (report.errors.length > 0) {

source/index.js

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ export getMessages from './library/get-messages';
66
export getPreset from './library/get-preset';
77
export format from './library/format';
88

9-
export default (message, options = {}) => {
9+
async function executeRule(entry) {
10+
const [name, config] = entry;
11+
return typeof config === 'function' ?
12+
[name, await config()] :
13+
[name, await config];
14+
}
15+
16+
export default async (message, options = {}) => {
1017
const {
1118
preset: {
1219
parserOpts: parserOptions
@@ -22,8 +29,14 @@ export default (message, options = {}) => {
2229
parse(message, parserOptions)
2330
);
2431

32+
// execute wildcard rules
33+
const executedWildcards = await Promise.all(
34+
Object.entries(wildcards || {})
35+
.map(async entry => await executeRule(entry))
36+
);
37+
2538
// wildcard matches skip the linting
26-
const bails = Object.entries(wildcards || {})
39+
const bails = executedWildcards
2740
.filter(entry => {
2841
const [, pattern] = entry;
2942
return Array.isArray(pattern);
@@ -33,7 +46,7 @@ export default (message, options = {}) => {
3346
const expression = new RegExp(...pattern);
3447
return parsed.header.match(expression);
3548
})
36-
.map(entry => entry[0]);
49+
.map(entry => entry[0])
3750

3851
if (bails.length > 0) {
3952
return {
@@ -45,8 +58,14 @@ export default (message, options = {}) => {
4558
};
4659
}
4760

48-
// validate against all rules
49-
const results = Object.entries(rules || {})
61+
// execute linting rules
62+
const executedRules = await Promise.all(
63+
Object.entries(rules || {})
64+
.map(async entry => await executeRule(entry))
65+
);
66+
67+
// validate against all rules
68+
const results = executedRules
5069
.filter(entry => {
5170
const [, [level]] = entry;
5271
return level > 0;
@@ -70,7 +89,7 @@ export default (message, options = {}) => {
7089
message
7190
};
7291
})
73-
.filter(Boolean);
92+
.filter(Boolean)
7493

7594
const errors = results.filter(result =>
7695
result.level > 1 && !result.valid);

0 commit comments

Comments
 (0)