Skip to content

Commit d7b8d4b

Browse files
committed
feat(rules): add rules for tense-checking
1 parent 6acb930 commit d7b8d4b

File tree

8 files changed

+170
-10
lines changed

8 files changed

+170
-10
lines changed

documentation/rules.md

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,23 @@ Rule configurations are either of type `array` residing on a key with the rule's
5353
0
5454
```
5555

56+
#### body-tense
57+
* **condition**: `body` is verbalized in tense present in `value`
58+
* **rule**: `always`
59+
* **value**
60+
```js
61+
['present-imperative']
62+
```
63+
* **possible values**
64+
```js
65+
[
66+
'past-tense', // did
67+
'present-imperative', // do
68+
'present-participle', // doing
69+
'present-third-person' // does
70+
]
71+
```
72+
5673
#### footer-leading-blank
5774
* **condition**: `footer` begins with blank line
5875
* **rule**: `always`
@@ -73,6 +90,23 @@ Rule configurations are either of type `array` residing on a key with the rule's
7390
0
7491
```
7592

93+
#### footer-tense
94+
* **condition**: `footer` is verbalized in tense present in `value`
95+
* **rule**: `always`
96+
* **value**
97+
```js
98+
['present-imperative']
99+
```
100+
* **possible values**
101+
```js
102+
[
103+
'past-tense', // did
104+
'present-imperative', // do
105+
'present-participle', // doing
106+
'present-third-person' // does
107+
]
108+
```
109+
76110
#### header-max-length
77111
* **condition**: `header` has `value` or less characters
78112
* **rule**: `always`
@@ -143,6 +177,14 @@ Rule configurations are either of type `array` residing on a key with the rule's
143177
* **condition**: `subject` is empty
144178
* **rule**: `never`
145179

180+
#### subject-full-stop
181+
* **condition**: `subject` ends with `value`
182+
* **rule**: `never`
183+
* **value**
184+
```js
185+
'.'
186+
```
187+
146188
#### subject-max-length
147189
* **condition**: `subject` has `value` or less characters
148190
* **rule**: `always`
@@ -159,12 +201,21 @@ Rule configurations are either of type `array` residing on a key with the rule's
159201
0
160202
```
161203

162-
#### subject-full-stop
163-
* **condition**: `subject` ends with `value`
164-
* **rule**: `never`
204+
#### subject-tense
205+
* **condition**: `subject` is verbalized in tense present in `value`
206+
* **rule**: `always`
165207
* **value**
166208
```js
167-
'.'
209+
['present-imperative']
210+
```
211+
* **possible values**
212+
```js
213+
[
214+
'past-tense', // did
215+
'present-imperative', // do
216+
'present-participle', // doing
217+
'present-third-person' // does
218+
]
168219
```
169220

170221
#### type-enum

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,10 @@
7070
"franc": "1.1.2",
7171
"get-stdin": "5.0.1",
7272
"git-raw-commits": "1.0.0",
73-
"lodash.merge": "4.1.0",
74-
"lodash.pick": "4.0.1",
75-
"meow": "3.7.0"
73+
"lodash": "4.5.1",
74+
"meow": "3.7.0",
75+
"pos": "0.3.0",
76+
"rc": "1.1.6"
7677
},
7778
"config": {
7879
"commitizen": {

source/cli.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import 'babel-polyfill';
55
// npm modules
66
import chalk from 'chalk';
77
import meow from 'meow';
8-
import pick from 'lodash.pick';
8+
import {pick} from 'lodash';
99
import stdin from 'get-stdin';
1010

1111
// local modules

source/library/ensure-tense.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import {Lexer, Tagger} from 'pos';
2+
3+
const lexer = new Lexer();
4+
const tagger = new Tagger();
5+
6+
const tenses = {
7+
'past-tense': ['VB', 'VBD'],
8+
'present-imperative': ['VB', 'VBN', 'VBP'],
9+
'present-participle': ['VB', 'VBG'],
10+
'present-third-person': ['VB', 'VBZ']
11+
};
12+
13+
export default (input, allowed) => {
14+
const lemmata = lexer.lex(input);
15+
const tagged = tagger.tag(lemmata);
16+
const verbs = tagged.filter(tag => tag[1][0] === 'V');
17+
const tags = allowed.reduce((registry, name) => {
18+
return [
19+
...registry,
20+
...(tenses[name] || [])
21+
];
22+
}, []);
23+
24+
const offending = verbs
25+
.filter(verb => {
26+
const [, tag] = verb;
27+
return tags.length > 0 && tags.indexOf(tag) === -1;
28+
})
29+
.filter(Boolean)
30+
.map(verb => {
31+
const [lemma, tag] = verb;
32+
const tense = Object.entries(tenses)
33+
.filter(item => {
34+
const [, tags] = item;
35+
return tags.indexOf(tag) > -1;
36+
})
37+
.map(item => item[0])[0];
38+
39+
return {
40+
lemma,
41+
tense
42+
};
43+
});
44+
45+
return {
46+
matches: offending.length === 0,
47+
offending
48+
};
49+
};

source/library/get-configuration.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import merge from 'lodash.merge';
2-
import pick from 'lodash.pick';
1+
import {merge, pick} from 'lodash';
32
import rc from 'rc';
43

54
const defaults = {

source/rules/body-tense.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import ensureTense from '../library/ensure-tense';
2+
3+
export default (parsed, when, value) => {
4+
const negated = when === 'never';
5+
const {matches, offending} = ensureTense(parsed.body, value);
6+
const offenders = offending
7+
.map(item => [item.lemma, item.tense].join(' - '))
8+
.join(',');
9+
10+
return [
11+
negated ? !matches : matches,
12+
[
13+
`tense of body must`,
14+
negated ? `not` : null,
15+
`be ${value}. Verbs in other tenses: ${offenders}`
16+
]
17+
.filter(Boolean)
18+
.join(' ')
19+
];
20+
};

source/rules/footer-tense.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import ensureTense from '../library/ensure-tense';
2+
3+
export default (parsed, when, value) => {
4+
const negated = when === 'never';
5+
const {matches, offending} = ensureTense(parsed.footer, value);
6+
const offenders = offending
7+
.map(item => [item.lemma, item.tense].join(' - '))
8+
.join(',');
9+
10+
return [
11+
negated ? !matches : matches,
12+
[
13+
`tense of footer must`,
14+
negated ? `not` : null,
15+
`be ${value}. Verbs in other tenses: ${offenders}`
16+
]
17+
.filter(Boolean)
18+
.join(' ')
19+
];
20+
};

source/rules/subject-tense.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import ensureTense from '../library/ensure-tense';
2+
3+
export default (parsed, when, value) => {
4+
const negated = when === 'never';
5+
const {matches, offending} = ensureTense(parsed.subject, value);
6+
const offenders = offending
7+
.map(item => [item.lemma, item.tense].join(' - '))
8+
.join(',');
9+
10+
return [
11+
negated ? !matches : matches,
12+
[
13+
`tense of message must`,
14+
negated ? `not` : null,
15+
`be ${value}. Verbs in other tenses: ${offenders}`
16+
]
17+
.filter(Boolean)
18+
.join(' ')
19+
];
20+
};

0 commit comments

Comments
 (0)