Skip to content

Commit 7be9c89

Browse files
committed
feat: allow to override preconfigured options
1 parent 44822e6 commit 7be9c89

File tree

3 files changed

+69
-6
lines changed

3 files changed

+69
-6
lines changed

README.md

+14-3
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ issueParser('Issue description, ref group/user/package#1, !2, implement #3, /dup
5959
### Bitbucket format
6060

6161
```js
62-
const issueParser = require('issue-parser')
62+
const issueParser = require('issue-parser');
6363
const parse = issueParser('bitbucket');
6464

6565
issueParser('Issue description, ref user/package#1, fixing #2. /cc @user');
@@ -76,7 +76,7 @@ issueParser('Issue description, ref user/package#1, fixing #2. /cc @user');
7676
### Custom format
7777

7878
```js
79-
const issueParser = require('issue-parser')
79+
const issueParser = require('issue-parser');
8080
const parse = issueParser({referenceActions: ['complete'], issuePrefixes: ['🐛']});
8181

8282
issueParser('Issue description, related to user/package🐛1, Complete 🐛2');
@@ -266,7 +266,7 @@ Fix #1 Fix #2a Fix a#3
266266

267267
## API
268268

269-
### issueParser([options]) => parse
269+
### issueParser([options], [overrides]) => parse
270270

271271
Create a [parser](#parsetext--result).
272272

@@ -317,6 +317,17 @@ Default: `['issues', 'pull', 'merge_requests']`
317317

318318
List of URL segment used to identify issues and pull requests with [full URL](#parse-references-with-full-issue-url).
319319

320+
#### overrides
321+
322+
Type: `Object`<br>
323+
Option overrides. Useful when using predefined [`options`](#options) (such as `github`, `gitlab` or `bitbucket`). The `overrides` object can define the same properties as [`options`](#options).
324+
325+
For example, the following will use all the `github` predefined options but with a different `hosts` option:
326+
```js
327+
const issueParser = require('issue-parser');
328+
const parse = issueParser('github', {hosts: ['https://custom-url.com']});
329+
```
330+
320331
### parse(text) => Result
321332

322333
Parse an issue description and returns a [Result](#result) object.

index.js

+16-3
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,25 @@ function parse(text, regexp, mentionRegexp, {issuePrefixes, hosts, referenceActi
103103
return results;
104104
}
105105

106-
module.exports = options => {
107-
if (options !== undefined && !isString(options) && !isPlainObject(options)) {
106+
module.exports = (options = 'default', overrides = {}) => {
107+
if (!isString(options) && !isPlainObject(options)) {
108108
throw new TypeError('Options must be a String or an Object');
109109
}
110110

111-
const opts = Object.assign({}, hostConfig.default, isString(options) ? hostConfig[options.toLowerCase()] : options);
111+
if (isString(options) && !includesIgnoreCase(Object.keys(hostConfig), options)) {
112+
throw new TypeError(`The supported configuration are [${Object.keys(hostConfig).join(', ')}], got '${options}'`);
113+
}
114+
115+
if (!isPlainObject(overrides)) {
116+
throw new TypeError('Override must be an Object');
117+
}
118+
119+
const opts = Object.assign(
120+
{},
121+
hostConfig.default,
122+
isString(options) ? hostConfig[options.toLowerCase()] : options,
123+
overrides
124+
);
112125

113126
for (const opt of Object.keys(opts)) {
114127
if (isString(opts[opt])) {

test/index.test.js

+39
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,35 @@ test('Parse with custom options', t => {
135135
);
136136
});
137137

138+
test('Parse with options overrides', t => {
139+
t.deepEqual(
140+
m('default', {
141+
referenceActions: ['fix'],
142+
duplicateActions: [],
143+
mentionsPrefixes: '!',
144+
issuePrefixes: ['#'],
145+
hosts: ['http://host1.com/', 'http://host2.com'],
146+
issueURLSegments: ['bugs'],
147+
})(
148+
'Fix #1 reSOLved gh-2 CLOSES Gh-3 fixed o/r#4 #5 o/r#6 fixing #7 http://host1.com/o/r/bugs/8 http://host2.com/o/r/bugs/9 Duplicate OF #10 !user @other'
149+
),
150+
{
151+
actions: [{raw: 'Fix #1', action: 'Fix', slug: undefined, prefix: '#', issue: '1'}],
152+
refs: [
153+
{raw: 'o/r#4', slug: 'o/r', prefix: '#', issue: '4'},
154+
{raw: '#5', slug: undefined, prefix: '#', issue: '5'},
155+
{raw: 'o/r#6', slug: 'o/r', prefix: '#', issue: '6'},
156+
{raw: '#7', slug: undefined, prefix: '#', issue: '7'},
157+
{raw: 'http://host1.com/o/r/bugs/8', slug: 'o/r', prefix: undefined, issue: '8'},
158+
{raw: 'http://host2.com/o/r/bugs/9', slug: 'o/r', prefix: undefined, issue: '9'},
159+
{raw: '#10', slug: undefined, prefix: '#', issue: '10'},
160+
],
161+
duplicates: [],
162+
mentions: [{raw: '!user', prefix: '!', user: 'user'}],
163+
}
164+
);
165+
});
166+
138167
test('"allRefs" returns "refs", "actions" and "duplicates"', t => {
139168
t.deepEqual(m('github')('Fix #1 #2 Duplicate of #3').allRefs, [
140169
{raw: 'Fix #1', action: 'Fix', slug: undefined, prefix: '#', issue: '1'},
@@ -269,12 +298,22 @@ test('Empty String', t => {
269298
});
270299

271300
test('Throw TypeError for invalid options', t => {
301+
t.throws(() => m('missing-option'), TypeError);
272302
t.throws(() => m([]), TypeError);
273303
t.throws(() => m(1), TypeError);
274304
t.throws(() => m({referenceActions: 1}), TypeError);
275305
t.throws(() => m({referenceActions: [1]}), TypeError);
276306
});
277307

308+
test('Throw TypeError for invalid overrides', t => {
309+
t.throws(() => m({}, []), TypeError);
310+
t.throws(() => m({}, 1), TypeError);
311+
t.throws(() => m({}, {referenceActions: 1}), TypeError);
312+
t.throws(() => m({}, {referenceActions: [1]}), TypeError);
313+
t.throws(() => m({}, ''), TypeError);
314+
t.throws(() => m({}, 'string'), TypeError);
315+
});
316+
278317
test('Throw TypeError for invalid input', t => {
279318
t.throws(() => m()(), TypeError);
280319
t.throws(() => m()(1), TypeError);

0 commit comments

Comments
 (0)