Skip to content

Commit 756a333

Browse files
authored
refactor: port parse to typescript (#764)
* refactor: port parse to typescript * refactor: add commit interface to parse return type * refactor: remove replaced dependencies from parse * refactor(parse): add strict options interface * refactor(parse): add strict parser type * test(parse): add empty and no commit message tests
1 parent 5176bc7 commit 756a333

File tree

8 files changed

+165
-113
lines changed

8 files changed

+165
-113
lines changed

Diff for: @commitlint/parse/package.json

+5-31
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,13 @@
33
"version": "8.1.0",
44
"description": "Lint your commit messages",
55
"main": "lib/index.js",
6+
"types": "lib/index.d.ts",
67
"files": [
78
"lib/"
89
],
910
"scripts": {
10-
"build": "cross-env NODE_ENV=production babel src --out-dir lib --source-maps",
1111
"deps": "dep-check",
12-
"pkg": "pkg-check",
13-
"start": "concurrently \"ava -c 4 --verbose --watch\" \"yarn run watch\"",
14-
"test": "ava -c 4 --verbose",
15-
"watch": "babel src --out-dir lib --watch --source-maps"
16-
},
17-
"ava": {
18-
"files": [
19-
"src/**/*.test.js",
20-
"!lib/**/*"
21-
],
22-
"source": [
23-
"src/**/*.js",
24-
"!lib/**/*"
25-
],
26-
"babel": "inherit",
27-
"require": [
28-
"babel-register"
29-
]
30-
},
31-
"babel": {
32-
"presets": [
33-
"babel-preset-commitlint"
34-
]
12+
"pkg": "pkg-check"
3513
},
3614
"engines": {
3715
"node": ">=4"
@@ -58,13 +36,9 @@
5836
"devDependencies": {
5937
"@commitlint/test": "8.0.0",
6038
"@commitlint/utils": "^8.1.0",
61-
"ava": "0.22.0",
62-
"babel-cli": "6.26.0",
63-
"babel-preset-commitlint": "^8.0.0",
64-
"babel-register": "6.26.0",
65-
"concurrently": "3.6.1",
66-
"cross-env": "5.1.1",
67-
"import-from": "3.0.0"
39+
"@types/lodash": "^4.14.136",
40+
"import-from": "3.0.0",
41+
"typescript": "^3.5.3"
6842
},
6943
"dependencies": {
7044
"conventional-changelog-angular": "^1.3.3",

Diff for: @commitlint/parse/src/index.js

-17
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,43 @@
11
import importFrom from 'import-from';
2-
import test from 'ava';
32
import parse from '.';
43

5-
test('throws when called without params', async t => {
6-
const error = await t.throws(parse());
7-
t.is(error.message, 'Expected a raw commit');
4+
test('throws when called without params', () => {
5+
expect((parse as any)()).rejects.toThrowError('Expected a raw commit');
86
});
97

10-
test('throws when called with empty message', async t => {
11-
const error = await t.throws(parse());
12-
t.is(error.message, 'Expected a raw commit');
8+
test('throws when called with empty message', () => {
9+
expect(parse('')).rejects.toThrowError('Expected a raw commit');
1310
});
1411

15-
test('returns object with raw message', async t => {
12+
test('returns object with raw message', async () => {
1613
const message = 'type(scope): subject';
1714
const actual = await parse(message);
18-
t.is(actual.raw, message);
15+
16+
expect(actual).toHaveProperty('raw', message);
1917
});
2018

21-
test('calls parser with message and passed options', async t => {
19+
test('calls parser with message and passed options', async () => {
2220
const message = 'message';
2321

24-
await parse(message, m => {
25-
t.is(message, m);
26-
return {};
27-
});
22+
expect.assertions(1);
23+
await parse(
24+
message,
25+
(m: string): any => {
26+
expect(m).toBe(message);
27+
return {};
28+
}
29+
);
2830
});
2931

30-
test('passes object up from parser function', async t => {
32+
test('passes object up from parser function', async () => {
3133
const message = 'message';
32-
const result = {};
34+
const result: any = {};
3335
const actual = await parse(message, () => result);
34-
t.is(actual, result);
36+
37+
expect(actual).toBe(result);
3538
});
3639

37-
test('returns object with expected keys', async t => {
40+
test('returns object with expected keys', async () => {
3841
const message = 'message';
3942
const actual = await parse(message);
4043
const expected = {
@@ -51,10 +54,11 @@ test('returns object with expected keys', async t => {
5154
subject: null,
5255
type: null
5356
};
54-
t.deepEqual(actual, expected);
57+
58+
expect(actual).toMatchObject(expected);
5559
});
5660

57-
test('uses angular grammar', async t => {
61+
test('uses angular grammar', async () => {
5862
const message = 'type(scope): subject';
5963
const actual = await parse(message);
6064
const expected = {
@@ -71,14 +75,15 @@ test('uses angular grammar', async t => {
7175
subject: 'subject',
7276
type: 'type'
7377
};
74-
t.deepEqual(actual, expected);
78+
79+
expect(actual).toMatchObject(expected);
7580
});
7681

77-
test('uses custom opts parser', async t => {
82+
test('uses custom opts parser', async () => {
7883
const message = 'type(scope)-subject';
79-
const changelogOpts = await importFrom(
80-
process.cwd(),
81-
'./fixtures/parser-preset/conventional-changelog-custom'
84+
const changelogOpts: any = await importFrom(
85+
__dirname,
86+
'../fixtures/parser-preset/conventional-changelog-custom.js'
8287
);
8388
const actual = await parse(message, undefined, changelogOpts.parserOpts);
8489
const expected = {
@@ -95,10 +100,11 @@ test('uses custom opts parser', async t => {
95100
subject: 'subject',
96101
type: 'type'
97102
};
98-
t.deepEqual(actual, expected);
103+
104+
expect(actual).toMatchObject(expected);
99105
});
100106

101-
test('does not merge array properties with custom opts', async t => {
107+
test('does not merge array properties with custom opts', async () => {
102108
const message = 'type: subject';
103109
const actual = await parse(message, undefined, {
104110
headerPattern: /^(.*):\s(.*)$/,
@@ -117,73 +123,79 @@ test('does not merge array properties with custom opts', async t => {
117123
subject: 'subject',
118124
type: 'type'
119125
};
120-
t.deepEqual(actual, expected);
126+
127+
expect(actual).toMatchObject(expected);
121128
});
122129

123-
test('supports scopes with /', async t => {
130+
test('supports scopes with /', async () => {
124131
const message = 'type(some/scope): subject';
125132
const actual = await parse(message);
126-
t.is(actual.scope, 'some/scope');
127-
t.is(actual.subject, 'subject');
133+
134+
expect(actual.scope).toBe('some/scope');
135+
expect(actual.subject).toBe('subject');
128136
});
129137

130-
test('supports scopes with / and empty parserOpts', async t => {
138+
test('supports scopes with / and empty parserOpts', async () => {
131139
const message = 'type(some/scope): subject';
132140
const actual = await parse(message, undefined, {});
133-
t.is(actual.scope, 'some/scope');
134-
t.is(actual.subject, 'subject');
141+
142+
expect(actual.scope).toBe('some/scope');
143+
expect(actual.subject).toBe('subject');
135144
});
136145

137-
test('ignores comments', async t => {
146+
test('ignores comments', async () => {
138147
const message = 'type(some/scope): subject\n# some comment';
139-
const changelogOpts = await importFrom(
148+
const changelogOpts: any = await importFrom(
140149
process.cwd(),
141150
'conventional-changelog-angular'
142151
);
143152
const opts = Object.assign({}, changelogOpts.parserOpts, {
144153
commentChar: '#'
145154
});
146155
const actual = await parse(message, undefined, opts);
147-
t.is(actual.body, null);
148-
t.is(actual.footer, null);
149-
t.is(actual.subject, 'subject');
156+
157+
expect(actual.body).toBe(null);
158+
expect(actual.footer).toBe(null);
159+
expect(actual.subject).toBe('subject');
150160
});
151161

152-
test('registers inline #', async t => {
162+
test('registers inline #', async () => {
153163
const message =
154164
'type(some/scope): subject #reference\n# some comment\nthings #reference';
155-
const changelogOpts = await importFrom(
165+
const changelogOpts: any = await importFrom(
156166
process.cwd(),
157167
'conventional-changelog-angular'
158168
);
159169
const opts = Object.assign({}, changelogOpts.parserOpts, {
160170
commentChar: '#'
161171
});
162172
const actual = await parse(message, undefined, opts);
163-
t.is(actual.subject, 'subject #reference');
164-
t.is(actual.body, 'things #reference');
173+
174+
expect(actual.subject).toBe('subject #reference');
175+
expect(actual.body).toBe('things #reference');
165176
});
166177

167-
test('parses references leading subject', async t => {
178+
test('parses references leading subject', async () => {
168179
const message = '#1 some subject';
169180
const opts = await importFrom(
170181
process.cwd(),
171182
'conventional-changelog-angular'
172183
);
173184
const {
174185
references: [actual]
175-
} = await parse(message, undefined, opts);
176-
t.is(actual.issue, '1');
186+
} = await parse(message, undefined, opts as any);
187+
188+
expect(actual.issue).toBe('1');
177189
});
178190

179-
test('parses custom references', async t => {
191+
test('parses custom references', async () => {
180192
const message = '#1 some subject PREFIX-2';
181193
const {references} = await parse(message, undefined, {
182194
issuePrefixes: ['PREFIX-']
183195
});
184196

185-
t.falsy(references.find(ref => ref.issue === '1'));
186-
t.deepEqual(references.find(ref => ref.issue === '2'), {
197+
expect(references.find(ref => ref.issue === '1')).toBeFalsy();
198+
expect(references.find(ref => ref.issue === '2')).toMatchObject({
187199
action: null,
188200
issue: '2',
189201
owner: null,
@@ -193,44 +205,44 @@ test('parses custom references', async t => {
193205
});
194206
});
195207

196-
test('uses permissive default regex without parser opts', async t => {
208+
test('uses permissive default regex without parser opts', async () => {
197209
const message = 'chore(component,demo): bump';
198210
const actual = await parse(message);
199211

200-
t.is(actual.scope, 'component,demo');
212+
expect(actual.scope).toBe('component,demo');
201213
});
202214

203-
test('uses permissive default regex with other parser opts', async t => {
215+
test('uses permissive default regex with other parser opts', async () => {
204216
const message = 'chore(component,demo): bump';
205217
const actual = await parse(message, undefined, {commentChar: '#'});
206218

207-
t.is(actual.scope, 'component,demo');
219+
expect(actual.scope).toBe('component,demo');
208220
});
209221

210-
test('uses restrictive default regex in passed parser opts', async t => {
222+
test('uses restrictive default regex in passed parser opts', async () => {
211223
const message = 'chore(component,demo): bump';
212224
const actual = await parse(message, undefined, {
213225
headerPattern: /^(\w*)(?:\(([a-z]*)\))?: (.*)$/
214226
});
215227

216-
t.is(actual.subject, null);
217-
t.is(actual.scope, null);
228+
expect(actual.subject).toBe(null);
229+
expect(actual.scope).toBe(null);
218230
});
219231

220-
test('works with chinese scope by default', async t => {
232+
test('works with chinese scope by default', async () => {
221233
const message = 'fix(面试评价): 测试';
222234
const actual = await parse(message, undefined, {commentChar: '#'});
223235

224-
t.not(actual.subject, null);
225-
t.not(actual.scope, null);
236+
expect(actual.subject).not.toBe(null);
237+
expect(actual.scope).not.toBe(null);
226238
});
227239

228-
test('does not work with chinese scopes with incompatible pattern', async t => {
240+
test('does not work with chinese scopes with incompatible pattern', async () => {
229241
const message = 'fix(面试评价): 测试';
230242
const actual = await parse(message, undefined, {
231243
headerPattern: /^(\w*)(?:\(([a-z]*)\))?: (.*)$/
232244
});
233245

234-
t.is(actual.subject, null);
235-
t.is(actual.scope, null);
246+
expect(actual.subject).toBe(null);
247+
expect(actual.scope).toBe(null);
236248
});

Diff for: @commitlint/parse/src/index.ts

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import {isArray, mergeWith} from 'lodash';
2+
import {Commit, Parser, ParserOptions} from './types';
3+
4+
const {sync} = require('conventional-commits-parser');
5+
const defaultChangelogOpts = require('conventional-changelog-angular');
6+
7+
export default parse;
8+
export * from './types';
9+
10+
async function parse(
11+
message: string,
12+
parser: Parser = sync,
13+
parserOpts?: ParserOptions
14+
): Promise<Commit> {
15+
const defaultOpts = (await defaultChangelogOpts).parserOpts;
16+
const opts = mergeWith({}, defaultOpts, parserOpts, (objValue, srcValue) => {
17+
if (isArray(objValue)) return srcValue;
18+
});
19+
const parsed = parser(message, opts) as Commit;
20+
parsed.raw = message;
21+
return parsed;
22+
}

0 commit comments

Comments
 (0)