Skip to content

Commit

Permalink
fix: rebuff rules (#34)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
marionebl committed Jul 7, 2017
1 parent 1e69d54 commit 702a2f7
Show file tree
Hide file tree
Showing 92 changed files with 2,894 additions and 229 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,5 @@ node_modules

# transpiled artifacts
distribution

.nyc_output
3 changes: 0 additions & 3 deletions .jsonlintrc

This file was deleted.

63 changes: 57 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@
},
"scripts": {
"start": "npm run watch",
"build": "babel source --out-dir distribution",
"build": "cross-env BABEL_ENV=production babel source --out-dir distribution",
"watch": "npm run build -- --watch",
"commit": "git-cz",
"commitmsg": "npm run build && node distribution/cli.js --edit",
"changelog": "conventional-changelog --preset angular --infile changelog.md --same-file --output-unreleased",
"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",
"prepretest": "npm run lint",
"pretest": "npm run deps",
"test": "ava",
"lint": "xo *.js",
"test": "nyc ava -c=4",
"lint": "xo",
"deps": "npm run build && dependency-check . --missing && dependency-check . --extra --no-dev -i conventional-changelog-angular -i conventional-changelog-lint-config-angular",
"commitlint": "node distribution/cli.js --from=HEAD~1",
"preversion": "npm run build && npm test",
Expand All @@ -30,13 +30,40 @@
"travis:lint:commits": "./scripts/lint:commits.sh"
},
"ava": {
"files": [
"source/**/*.test.js",
"!distribution/**/*"
],
"source": [
"source/**/*.js",
"!distribution/**/*"
],
"babel": "inherit",
"require": [
"babel-register",
"babel-polyfill"
]
},
"babel": {
"env": {
"development": {
"sourceMaps": "inline",
"plugins": [
"add-module-exports",
"istanbul",
[
"transform-runtime",
{
"polyfill": false,
"regenerator": true
}
]
]
},
"production": {
"ignore": ["**/*.test.js"]
}
},
"presets": [
[
"env",
Expand All @@ -59,6 +86,22 @@
]
]
},
"nyc": {
"all": true,
"sourceMap": false,
"instrument": false,
"include": [
"source/**/*.js"
]
},
"xo": {
"plugins": [
"flow-check"
],
"rules": {
"flow-check/check": "error"
}
},
"config": {
"commitizen": {
"path": "cz-conventional-changelog-lint"
Expand Down Expand Up @@ -89,24 +132,32 @@
},
"license": "MIT",
"devDependencies": {
"ansi-styles": "3.1.0",
"ava": "0.18.2",
"babel-cli": "6.18.0",
"babel-plugin-add-module-exports": "0.2.1",
"babel-plugin-istanbul": "4.1.3",
"babel-plugin-transform-runtime": "6.23.0",
"babel-polyfill": "6.20.0",
"babel-preset-env": "1.2.1",
"babel-preset-stage-0": "6.16.0",
"babel-register": "6.24.1",
"conventional-changelog-cli": "1.2.0",
"conventional-recommended-bump": "0.3.0",
"cross-env": "5.0.1",
"cz-conventional-changelog-lint": "0.1.3",
"denodeify": "1.2.1",
"dependency-check": "2.7.0",
"execa": "0.6.0",
"eslint-plugin-flow-check": "1.1.1",
"execa": "0.6.3",
"globby": "6.1.0",
"has-ansi": "3.0.0",
"import-from": "2.1.0",
"nyc": "10.3.2",
"path-exists": "3.0.0",
"resolve-from": "3.0.0",
"rimraf": "2.6.1",
"unexpected": "10.20.0",
"xo": "0.17.1"
"xo": "0.18.2"
},
"dependencies": {
"babel-polyfill": "6.20.0",
Expand Down
17 changes: 3 additions & 14 deletions source/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import stdin from 'get-stdin';

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

/**
* Behavioural rules
Expand All @@ -23,12 +22,8 @@ const rules = {
};

const configuration = {
// flags of string type
string: ['from', 'to', 'preset', 'extends'],
// flags of array type
// flags of bool type
boolean: ['edit', 'help', 'version', 'quiet', 'color'],
// flag aliases
alias: {
c: 'color',
e: 'edit',
Expand All @@ -41,15 +36,14 @@ const configuration = {
x: 'extends'
},
description: {
color: 'toggle formatted output',
color: 'toggle colored output',
edit: 'read last commit message found in ./git/COMMIT_EDITMSG',
extends: 'array of shareable configurations to extend',
from: 'lower end of the commit range to lint; applies if edit=false',
preset: 'conventional-changelog-preset to use for commit message parsing',
to: 'upper end of the commit range to lint; applies if edit=false',
quiet: 'toggle console output'
},
// flag defaults
default: {
color: true,
edit: false,
Expand All @@ -58,7 +52,6 @@ const configuration = {
to: null,
quiet: false
},
// fail on unknown
unknown(arg) {
throw new Error(`unknown flags: ${arg}`);
}
Expand Down Expand Up @@ -101,11 +94,7 @@ async function main(options) {
)
});

const formatted = format(report, {
color: flags.color,
signs: [' ', '⚠', '✖'],
colors: ['white', 'yellow', 'red']
});
const formatted = format(report, {color: flags.color});

if (!flags.quiet) {
console.log(`${fmt.grey('⧗')} input: ${fmt.bold(commit.split('\n')[0])}`);
Expand Down
13 changes: 4 additions & 9 deletions source/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import {merge} from 'lodash';

import ruleFunctions from './rules';
import format from './library/format';
import getConfiguration from './library/get-configuration';
Expand All @@ -11,19 +9,16 @@ export {format, getConfiguration, getMessages, getPreset};

export default async (message, options = {}) => {
const {
preset: {
parserOpts: parserOptions
},
configuration: {
rules,
wildcards
}
} = options;

// parse the commit message
// Parse the commit message
const parsed = parse(message);

// wildcard matches skip the linting
// Wildcard matches skip the linting
const bails = Object.entries(wildcards)
.filter(entry => {
const [, pattern] = entry;
Expand All @@ -36,7 +31,7 @@ export default async (message, options = {}) => {
})
.map(entry => entry[0]);

// found a wildcard match, skip
// Found a wildcard match, skip
if (bails.length > 0) {
return {
valid: true,
Expand All @@ -47,7 +42,7 @@ export default async (message, options = {}) => {
};
}

// validate against all rules
// Validate against all rules
const results = Object.entries(rules)
.filter(entry => {
const [, [level]] = entry;
Expand Down
13 changes: 10 additions & 3 deletions source/library/ensure-case.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
export default (a, stringCase) => {
const method = `to${stringCase[0].toUpperCase()}${stringCase.slice(1)}`;
return typeof a !== 'string' || a[method]() === a;
export default (raw = '', target = 'lowercase') => {
const normalized = String(raw);

switch (target) {
case 'uppercase':
return normalized.toUpperCase() === normalized;
case 'lowercase':
default:
return normalized.toLowerCase() === normalized;
}
};
42 changes: 42 additions & 0 deletions source/library/ensure-case.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import test from 'ava';
import ensure from './ensure-case';

test('true for no params', t => {
const actual = ensure();
t.is(actual, true);
});

test('true for empty', t => {
const actual = ensure('');
t.is(actual, true);
});

test('true for lowercase', t => {
const actual = ensure('a');
t.is(actual, true);
});

test('false for uppercase', t => {
const actual = ensure('A');
t.is(actual, false);
});

test('true for lowercase on lowercase', t => {
const actual = ensure('a', 'lowercase');
t.is(actual, true);
});

test('false for uppercase on lowercase', t => {
const actual = ensure('A', 'lowercase');
t.is(actual, false);
});

test('true for uppercase on uppercase', t => {
const actual = ensure('A', 'uppercase');
t.is(actual, true);
});

test('false for lowercase on lowercase', t => {
const actual = ensure('a', 'uppercase');
t.is(actual, false);
});
8 changes: 7 additions & 1 deletion source/library/ensure-enum.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
export default (value, enums) => {
export default (value, enums = []) => {
if (value === undefined) {
return false;
}
if (!Array.isArray(enums)) {
return false;
}
return enums.indexOf(value) > -1;
};
42 changes: 42 additions & 0 deletions source/library/ensure-enum.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import test from 'ava';
import ensure from './ensure-enum';

test('false for no params', t => {
const actual = ensure();
t.is(actual, false);
});

test('true for a against a', t => {
const actual = ensure('a', ['a']);
t.is(actual, true);
});

test('false for a against b', t => {
const actual = ensure('a', ['b']);
t.is(actual, false);
});

test('true for a against a, b', t => {
const actual = ensure('a', ['a', 'b']);
t.is(actual, true);
});

test('false for b against a', t => {
const actual = ensure('b', ['a']);
t.is(actual, false);
});

test('true for b against b', t => {
const actual = ensure('b', ['b']);
t.is(actual, true);
});

test('true for b against a, b', t => {
const actual = ensure('b', ['a', 'b']);
t.is(actual, true);
});

test('false for c against a, b', t => {
const actual = ensure('c', ['a', 'b']);
t.is(actual, false);
});
5 changes: 3 additions & 2 deletions source/library/ensure-language.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import franc from 'franc';
export default (input, allowed) => {
const detected = franc.all(input)
.filter(lang => lang[1] >= 0.45)
.map(lang => lang[0]);
.map(lang => lang[0])
.slice(0, 5);

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

0 comments on commit 702a2f7

Please sign in to comment.