Skip to content

Commit 54c86c8

Browse files
committed
feat(rule): Create scope-pattern
1 parent 494fc72 commit 54c86c8

File tree

3 files changed

+90
-1
lines changed

3 files changed

+90
-1
lines changed

src/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
import { default as scopePattern } from "./rules/scope-pattern";
2+
13
const plugin = {
2-
rules: {}
4+
rules: {
5+
'scope-pattern': scopePattern
6+
}
37
}
48

59
export default plugin;
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import type { Commit } from 'conventional-commits-parser';
2+
import type { Rule } from '@commitlint/types';
3+
import rule from "."
4+
5+
describe('scope-pattern', () => {
6+
const ruleFn = rule as Rule<[string, string?]>
7+
const createCommit = (scope?: string): Commit => {
8+
return {
9+
type: 'feat',
10+
scope: scope,
11+
header: `feat(${scope}): some message`,
12+
body: null,
13+
footer: null,
14+
merge: null,
15+
revert: null,
16+
mentions: [] as string[],
17+
notes: [] as Commit.Note[],
18+
references: [] as Commit.Reference[]
19+
} as Commit
20+
};
21+
22+
it('passes when scope matches pattern and "always" is used', () => {
23+
const result = ruleFn(createCommit('core'), 'always', ['^core$']);
24+
expect(result).toEqual([true, '']);
25+
});
26+
27+
it('fails when scope does not match pattern and "always" is used', () => {
28+
const result = ruleFn(createCommit('utils'), 'always', ['^core$']);
29+
expect(result).toEqual([false, 'scope must match pattern: ^core$']);
30+
});
31+
32+
it('passes when scope does not match pattern and "never" is used', () => {
33+
const result = ruleFn(createCommit('utils'), 'never', ['^core$']);
34+
expect(result).toEqual([true, '']);
35+
});
36+
37+
it('fails when scope matches pattern and "never" is used', () => {
38+
const result = ruleFn(createCommit('core'), 'never', ['^core$']);
39+
expect(result).toEqual([false, 'scope must not match pattern: ^core$']);
40+
});
41+
42+
it('passes when scope is undefined', () => {
43+
const result = ruleFn(createCommit(undefined), 'always', ['^core$']);
44+
expect(result).toEqual([true, '']);
45+
});
46+
47+
it('uses default "when" and "value" when not provided', () => {
48+
const result = ruleFn(createCommit('anyscope'));
49+
expect(result).toEqual([true, '']);
50+
});
51+
52+
it('uses default "value" when only "when" is provided', () => {
53+
const result = ruleFn(createCommit('anyscope'), 'always');
54+
expect(result).toEqual([true, '']);
55+
});
56+
57+
it('uses custom message when provided and fails', () => {
58+
const result = ruleFn(createCommit('utils'), 'always', ['^core$', 'Custom message']);
59+
expect(result).toEqual([false, 'Custom message']);
60+
});
61+
});

src/rules/scope-pattern/index.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import type { Rule } from '@commitlint/types';
2+
import type { Commit } from 'conventional-commits-parser';
3+
4+
const rule: Rule = (
5+
parsed: Commit,
6+
when: 'always' | 'never' = 'always',
7+
value: [string, string?] = ['']
8+
) => {
9+
const [pattern, message] = value;
10+
11+
if (!parsed.scope) return [true, ''];
12+
13+
const regex = new RegExp(pattern);
14+
const isMatch = regex.test(parsed.scope);
15+
const isNegated = when === 'never';
16+
const pass = isNegated ? !isMatch : isMatch;
17+
18+
return [
19+
pass,
20+
pass ? '' : (message || `scope must ${isNegated ? 'not ' : ''}match pattern: ${pattern}`)
21+
];
22+
};
23+
24+
export default rule

0 commit comments

Comments
 (0)