Skip to content

Commit 702a2f7

Browse files
authored
fix: rebuff rules (#34)
* test: add test cases for footer-empty * fix: finish footer-empty implementation * test: add test cases for footer-max-length * fix: allow empty footer for footer-max-length * test: correct non-criticals in footer-max-length tests * test: add test cases for footer-min-length * fix: allow empty footer for footer-min-length * test: add cases for body-empty * fix: use keywords in body-empty * test: add cases for subject-empty * fix: use keywords in subject-empty * test: add cases for type-empty * test: remove superfluous message prefixes * fix: use keywords in type-empty * style: move tests into colocation * test: add body-case test cases * fix: handle empty body gracefully * fix: rework ensure-case to produce saner output * test: add cases for body-leading-blank * test: add multiline body cases for footer-leading-blank * fix: handle multiline bodies properly * fix: harden body-leading-blank implementation * test: add body-max-length cases * fix: handle empty body gracefully * test: add body-min-length cases * fix: handle empty body gracefully * fix: add test case for footer-tense * feat: introduce object based config for footer-tense * test: add header length tests * test: add case rule tests * fix: handle empty scope * fix: handle empty subject * style: harmonize case rules * fix: handle empty type * test: harmonize length tests * test: add length tests * chore: be specific about ava test files * fix: implement length checks correctly * chore: update dev dependencies * test: add subject-full-stop cases * fix: harden subject-full-stop implementation * test: add case for subject-leading-capital * fix: harden subject-leading-capital * test: add body-tense case * fix: harden body-tense rule * fix: harden subject-tense * test: add export case * test: add case for lang * chore: harden lang implementation * chore: add missing devDependency * chore: add nyc coverage * test: add case for type-enum * fix: harden type-enum * test: add case for ensure-case * chore: bring linting up to speed * style: be consistent with xo * test: add case for ensure-enum * fix: harden ensure-enum * test: add case for ensure-language * test: add case for ensure-max-length * test: add case for ensure-min-length * test: add case for ensure-not-empty * test: add case for ensure-tense * fix: harden ensure tense against type errors * chore: fix babel build on win32 platforms * test: add test cases for execute-rule * fix: handle noop calls gracefully * test: add test cases for get-preset * test: add test cases for format * fix: more solid formatter implementation * test: add shell tests for parse method * fix: solidify and test resolve-extends * test: execute color format test only if supported * fix: harmonize dynamic importers * chore: cleanup * chore: do not babel test files * chore: ignore *.test only for prod builds
1 parent 1e69d54 commit 702a2f7

File tree

92 files changed

+2894
-229
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

92 files changed

+2894
-229
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,5 @@ node_modules
3737

3838
# transpiled artifacts
3939
distribution
40+
41+
.nyc_output

.jsonlintrc

-3
This file was deleted.

package.json

+57-6
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@
1111
},
1212
"scripts": {
1313
"start": "npm run watch",
14-
"build": "babel source --out-dir distribution",
14+
"build": "cross-env BABEL_ENV=production babel source --out-dir distribution",
1515
"watch": "npm run build -- --watch",
1616
"commit": "git-cz",
1717
"commitmsg": "npm run build && node distribution/cli.js --edit",
1818
"changelog": "conventional-changelog --preset angular --infile changelog.md --same-file --output-unreleased",
1919
"push": "git push && git push --tags && hub release create \"v$npm_package_version\" --message=\"v$npm_package_version\n$(conventional-changelog -p angular)\" && npm publish",
2020
"prepretest": "npm run lint",
2121
"pretest": "npm run deps",
22-
"test": "ava",
23-
"lint": "xo *.js",
22+
"test": "nyc ava -c=4",
23+
"lint": "xo",
2424
"deps": "npm run build && dependency-check . --missing && dependency-check . --extra --no-dev -i conventional-changelog-angular -i conventional-changelog-lint-config-angular",
2525
"commitlint": "node distribution/cli.js --from=HEAD~1",
2626
"preversion": "npm run build && npm test",
@@ -30,13 +30,40 @@
3030
"travis:lint:commits": "./scripts/lint:commits.sh"
3131
},
3232
"ava": {
33+
"files": [
34+
"source/**/*.test.js",
35+
"!distribution/**/*"
36+
],
37+
"source": [
38+
"source/**/*.js",
39+
"!distribution/**/*"
40+
],
3341
"babel": "inherit",
3442
"require": [
3543
"babel-register",
3644
"babel-polyfill"
3745
]
3846
},
3947
"babel": {
48+
"env": {
49+
"development": {
50+
"sourceMaps": "inline",
51+
"plugins": [
52+
"add-module-exports",
53+
"istanbul",
54+
[
55+
"transform-runtime",
56+
{
57+
"polyfill": false,
58+
"regenerator": true
59+
}
60+
]
61+
]
62+
},
63+
"production": {
64+
"ignore": ["**/*.test.js"]
65+
}
66+
},
4067
"presets": [
4168
[
4269
"env",
@@ -59,6 +86,22 @@
5986
]
6087
]
6188
},
89+
"nyc": {
90+
"all": true,
91+
"sourceMap": false,
92+
"instrument": false,
93+
"include": [
94+
"source/**/*.js"
95+
]
96+
},
97+
"xo": {
98+
"plugins": [
99+
"flow-check"
100+
],
101+
"rules": {
102+
"flow-check/check": "error"
103+
}
104+
},
62105
"config": {
63106
"commitizen": {
64107
"path": "cz-conventional-changelog-lint"
@@ -89,24 +132,32 @@
89132
},
90133
"license": "MIT",
91134
"devDependencies": {
135+
"ansi-styles": "3.1.0",
92136
"ava": "0.18.2",
93137
"babel-cli": "6.18.0",
94138
"babel-plugin-add-module-exports": "0.2.1",
139+
"babel-plugin-istanbul": "4.1.3",
95140
"babel-plugin-transform-runtime": "6.23.0",
96141
"babel-polyfill": "6.20.0",
97142
"babel-preset-env": "1.2.1",
98143
"babel-preset-stage-0": "6.16.0",
99144
"babel-register": "6.24.1",
100145
"conventional-changelog-cli": "1.2.0",
101146
"conventional-recommended-bump": "0.3.0",
147+
"cross-env": "5.0.1",
102148
"cz-conventional-changelog-lint": "0.1.3",
103149
"denodeify": "1.2.1",
104150
"dependency-check": "2.7.0",
105-
"execa": "0.6.0",
151+
"eslint-plugin-flow-check": "1.1.1",
152+
"execa": "0.6.3",
153+
"globby": "6.1.0",
154+
"has-ansi": "3.0.0",
155+
"import-from": "2.1.0",
156+
"nyc": "10.3.2",
106157
"path-exists": "3.0.0",
158+
"resolve-from": "3.0.0",
107159
"rimraf": "2.6.1",
108-
"unexpected": "10.20.0",
109-
"xo": "0.17.1"
160+
"xo": "0.18.2"
110161
},
111162
"dependencies": {
112163
"babel-polyfill": "6.20.0",

source/cli.js

+3-14
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ import stdin from 'get-stdin';
99

1010
import pkg from '../package.json'; // eslint-disable-line import/extensions
1111
import help from './help';
12-
import lint from './';
13-
import {format, getConfiguration, getPreset, getMessages} from './'; // eslint-disable-line no-duplicate-imports
12+
import lint, {format, getConfiguration, getPreset, getMessages} from './';
1413

1514
/**
1615
* Behavioural rules
@@ -23,12 +22,8 @@ const rules = {
2322
};
2423

2524
const configuration = {
26-
// flags of string type
2725
string: ['from', 'to', 'preset', 'extends'],
28-
// flags of array type
29-
// flags of bool type
3026
boolean: ['edit', 'help', 'version', 'quiet', 'color'],
31-
// flag aliases
3227
alias: {
3328
c: 'color',
3429
e: 'edit',
@@ -41,15 +36,14 @@ const configuration = {
4136
x: 'extends'
4237
},
4338
description: {
44-
color: 'toggle formatted output',
39+
color: 'toggle colored output',
4540
edit: 'read last commit message found in ./git/COMMIT_EDITMSG',
4641
extends: 'array of shareable configurations to extend',
4742
from: 'lower end of the commit range to lint; applies if edit=false',
4843
preset: 'conventional-changelog-preset to use for commit message parsing',
4944
to: 'upper end of the commit range to lint; applies if edit=false',
5045
quiet: 'toggle console output'
5146
},
52-
// flag defaults
5347
default: {
5448
color: true,
5549
edit: false,
@@ -58,7 +52,6 @@ const configuration = {
5852
to: null,
5953
quiet: false
6054
},
61-
// fail on unknown
6255
unknown(arg) {
6356
throw new Error(`unknown flags: ${arg}`);
6457
}
@@ -101,11 +94,7 @@ async function main(options) {
10194
)
10295
});
10396

104-
const formatted = format(report, {
105-
color: flags.color,
106-
signs: [' ', '⚠', '✖'],
107-
colors: ['white', 'yellow', 'red']
108-
});
97+
const formatted = format(report, {color: flags.color});
10998

11099
if (!flags.quiet) {
111100
console.log(`${fmt.grey('⧗')} input: ${fmt.bold(commit.split('\n')[0])}`);

source/index.js

+4-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import {merge} from 'lodash';
2-
31
import ruleFunctions from './rules';
42
import format from './library/format';
53
import getConfiguration from './library/get-configuration';
@@ -11,19 +9,16 @@ export {format, getConfiguration, getMessages, getPreset};
119

1210
export default async (message, options = {}) => {
1311
const {
14-
preset: {
15-
parserOpts: parserOptions
16-
},
1712
configuration: {
1813
rules,
1914
wildcards
2015
}
2116
} = options;
2217

23-
// parse the commit message
18+
// Parse the commit message
2419
const parsed = parse(message);
2520

26-
// wildcard matches skip the linting
21+
// Wildcard matches skip the linting
2722
const bails = Object.entries(wildcards)
2823
.filter(entry => {
2924
const [, pattern] = entry;
@@ -36,7 +31,7 @@ export default async (message, options = {}) => {
3631
})
3732
.map(entry => entry[0]);
3833

39-
// found a wildcard match, skip
34+
// Found a wildcard match, skip
4035
if (bails.length > 0) {
4136
return {
4237
valid: true,
@@ -47,7 +42,7 @@ export default async (message, options = {}) => {
4742
};
4843
}
4944

50-
// validate against all rules
45+
// Validate against all rules
5146
const results = Object.entries(rules)
5247
.filter(entry => {
5348
const [, [level]] = entry;

source/library/ensure-case.js

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
export default (a, stringCase) => {
2-
const method = `to${stringCase[0].toUpperCase()}${stringCase.slice(1)}`;
3-
return typeof a !== 'string' || a[method]() === a;
1+
export default (raw = '', target = 'lowercase') => {
2+
const normalized = String(raw);
3+
4+
switch (target) {
5+
case 'uppercase':
6+
return normalized.toUpperCase() === normalized;
7+
case 'lowercase':
8+
default:
9+
return normalized.toLowerCase() === normalized;
10+
}
411
};

source/library/ensure-case.test.js

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import test from 'ava';
2+
import ensure from './ensure-case';
3+
4+
test('true for no params', t => {
5+
const actual = ensure();
6+
t.is(actual, true);
7+
});
8+
9+
test('true for empty', t => {
10+
const actual = ensure('');
11+
t.is(actual, true);
12+
});
13+
14+
test('true for lowercase', t => {
15+
const actual = ensure('a');
16+
t.is(actual, true);
17+
});
18+
19+
test('false for uppercase', t => {
20+
const actual = ensure('A');
21+
t.is(actual, false);
22+
});
23+
24+
test('true for lowercase on lowercase', t => {
25+
const actual = ensure('a', 'lowercase');
26+
t.is(actual, true);
27+
});
28+
29+
test('false for uppercase on lowercase', t => {
30+
const actual = ensure('A', 'lowercase');
31+
t.is(actual, false);
32+
});
33+
34+
test('true for uppercase on uppercase', t => {
35+
const actual = ensure('A', 'uppercase');
36+
t.is(actual, true);
37+
});
38+
39+
test('false for lowercase on lowercase', t => {
40+
const actual = ensure('a', 'uppercase');
41+
t.is(actual, false);
42+
});

source/library/ensure-enum.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1-
export default (value, enums) => {
1+
export default (value, enums = []) => {
2+
if (value === undefined) {
3+
return false;
4+
}
5+
if (!Array.isArray(enums)) {
6+
return false;
7+
}
28
return enums.indexOf(value) > -1;
39
};

source/library/ensure-enum.test.js

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import test from 'ava';
2+
import ensure from './ensure-enum';
3+
4+
test('false for no params', t => {
5+
const actual = ensure();
6+
t.is(actual, false);
7+
});
8+
9+
test('true for a against a', t => {
10+
const actual = ensure('a', ['a']);
11+
t.is(actual, true);
12+
});
13+
14+
test('false for a against b', t => {
15+
const actual = ensure('a', ['b']);
16+
t.is(actual, false);
17+
});
18+
19+
test('true for a against a, b', t => {
20+
const actual = ensure('a', ['a', 'b']);
21+
t.is(actual, true);
22+
});
23+
24+
test('false for b against a', t => {
25+
const actual = ensure('b', ['a']);
26+
t.is(actual, false);
27+
});
28+
29+
test('true for b against b', t => {
30+
const actual = ensure('b', ['b']);
31+
t.is(actual, true);
32+
});
33+
34+
test('true for b against a, b', t => {
35+
const actual = ensure('b', ['a', 'b']);
36+
t.is(actual, true);
37+
});
38+
39+
test('false for c against a, b', t => {
40+
const actual = ensure('c', ['a', 'b']);
41+
t.is(actual, false);
42+
});

source/library/ensure-language.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import franc from 'franc';
33
export default (input, allowed) => {
44
const detected = franc.all(input)
55
.filter(lang => lang[1] >= 0.45)
6-
.map(lang => lang[0]);
6+
.map(lang => lang[0])
7+
.slice(0, 5);
78

8-
// franc spits out ['und'] when unable to
9+
// Library franc spits out ['und'] when unable to
910
// guess any languages, let it through in this case
1011
const matches = detected[0] === 'und' ||
1112
detected.indexOf(allowed) > -1;

0 commit comments

Comments
 (0)