diff --git a/.all-contributorsrc b/.all-contributorsrc
index f22a035..ba2c160 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -247,6 +247,17 @@
"contributions": [
"bug"
]
+ },
+ {
+ "login": "Garbee",
+ "name": "Jonathan Garbee",
+ "avatar_url": "https://avatars.githubusercontent.com/u/868301?v=3",
+ "profile": "http://jonathan.garbee.me",
+ "contributions": [
+ "code",
+ "doc",
+ "test"
+ ]
}
]
}
diff --git a/README.md b/README.md
index fb5a037..5435d2c 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
[![downloads][downloads-badge]][npm-stat]
[![MIT License][license-badge]][LICENSE]
-[![All Contributors](https://img.shields.io/badge/all_contributors-24-orange.svg?style=flat-square)](#contributors)
+[![All Contributors](https://img.shields.io/badge/all_contributors-25-orange.svg?style=flat-square)](#contributors)
[![PRs Welcome][prs-badge]][prs]
[![Donate][donate-badge]][donate]
[![Code of Conduct][coc-badge]][coc]
@@ -34,6 +34,12 @@ You can specify options in `.vcmrc`
```js
{
"types": ["feat", "fix", "docs", "style", "refactor", "perf", "test", "chore", "revert"], // default
+ "scope": {
+ required: false, // default,
+ allowed: ['button', 'card'], // default is '*' for anything,
+ validate: false, // default,
+ multiple: false // default
+ },
"warnOnFail": false, // default
"maxSubjectLength": 100, // default
"subjectPattern": ".+", // default
@@ -50,6 +56,12 @@ or in `package.json`
"config": {
"validate-commit-msg": {
"types": ["feat", "fix", "docs", "style", "refactor", "perf", "test", "chore", "revert"], // default
+ "scope": {
+ required: false, // default,
+ allowed: ['button', 'card'], // default is '*' for anything,
+ validate: false, // default,
+ multiple: false // default
+ },
"warnOnFail": false, // default
"maxSubjectLength": 100, // default
"subjectPattern": ".+", // default
@@ -73,6 +85,28 @@ Or you can specify the name of a module that exports types according to the
[conventional-commit-types](https://github.com/adjohnson916/conventional-commit-types)
spec, e.g. `"types": "conventional-commit-types"`.
+#### scope
+
+This object defines scope requirements for the commit message. Possible properties are:
+
+##### required
+
+A boolean to define whether a scope is required for all commit messages.
+
+##### allowed
+
+An array of scopes that are allowed for your commit message.
+
+You may also define it as `"*"` which is the default to allow any scope names.
+
+##### validate
+
+A boolean to define whether or not to validate the scope(s) provided.
+
+##### multiple
+
+A boolean to define whether or not to allow multiple scopes.
+
#### warnOnFail
If this is set to `true` errors will be logged to the console, however the commit will still pass.
@@ -155,7 +189,7 @@ Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds
| :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| [
Shawn Erquhart](http://www.professant.com)
[π»](https://github.com/kentcdodds/validate-commit-msg/commits?author=erquhart) [π](https://github.com/kentcdodds/validate-commit-msg/commits?author=erquhart) [β οΈ](https://github.com/kentcdodds/validate-commit-msg/commits?author=erquhart) | [
Tushar Mathur](http://tusharm.com)
[π»](https://github.com/kentcdodds/validate-commit-msg/commits?author=tusharmath) [β οΈ](https://github.com/kentcdodds/validate-commit-msg/commits?author=tusharmath) | [
Jason Dreyzehner](https://twitter.com/bitjson)
[π»](https://github.com/kentcdodds/validate-commit-msg/commits?author=bitjson) [π](https://github.com/kentcdodds/validate-commit-msg/commits?author=bitjson) [β οΈ](https://github.com/kentcdodds/validate-commit-msg/commits?author=bitjson) | [
Abimbola Idowu](http://twitter.com/hisabimbola)
[π»](https://github.com/kentcdodds/validate-commit-msg/commits?author=hisabimbola) | [
Gleb Bahmutov](https://glebbahmutov.com/)
[π»](https://github.com/kentcdodds/validate-commit-msg/commits?author=bahmutov) [β οΈ](https://github.com/kentcdodds/validate-commit-msg/commits?author=bahmutov) | [
Dennis](http://dennis.io)
[π»](https://github.com/kentcdodds/validate-commit-msg/commits?author=ds82) | [
Matt Lewis](https://mattlewis.me/)
[π»](https://github.com/kentcdodds/validate-commit-msg/commits?author=mattlewis92) |
| [
Tom Vincent](https://tlvince.com)
[π»](https://github.com/kentcdodds/validate-commit-msg/commits?author=tlvince) | [
Anders D. Johnson](https://andrz.me/)
[π»](https://github.com/kentcdodds/validate-commit-msg/commits?author=adjohnson916) [π](https://github.com/kentcdodds/validate-commit-msg/commits?author=adjohnson916) [β οΈ](https://github.com/kentcdodds/validate-commit-msg/commits?author=adjohnson916) | [
James Zetlen](jameszetlen.com)
[π»](https://github.com/kentcdodds/validate-commit-msg/commits?author=zetlen) [β οΈ](https://github.com/kentcdodds/validate-commit-msg/commits?author=zetlen) | [
Paul Bienkowski](http://opatut.de)
[π»](https://github.com/kentcdodds/validate-commit-msg/commits?author=opatut) [β οΈ](https://github.com/kentcdodds/validate-commit-msg/commits?author=opatut) | [
Barney Scott](https://github.com/bmds)
[π»](https://github.com/kentcdodds/validate-commit-msg/commits?author=bmds) [β οΈ](https://github.com/kentcdodds/validate-commit-msg/commits?author=bmds) | [
Emmanuel Murillo SΓ‘nchez](https://github.com/Emmurillo)
[π»](https://github.com/kentcdodds/validate-commit-msg/commits?author=Emmurillo) [β οΈ](https://github.com/kentcdodds/validate-commit-msg/commits?author=Emmurillo) | [
Hans Kristian Flaatten](https://starefossen.github.io)
[π»](https://github.com/kentcdodds/validate-commit-msg/commits?author=Starefossen) [β οΈ](https://github.com/kentcdodds/validate-commit-msg/commits?author=Starefossen) |
-| [
Bo Lingen](https://github.com/citycide)
[π](https://github.com/kentcdodds/validate-commit-msg/commits?author=citycide) | [
Spyros Ioakeimidis](http://www.spyros.io)
[π»](https://github.com/kentcdodds/validate-commit-msg/commits?author=spirosikmd) [π](https://github.com/kentcdodds/validate-commit-msg/commits?author=spirosikmd) [β οΈ](https://github.com/kentcdodds/validate-commit-msg/commits?author=spirosikmd) | [
Matt Travi](https://matt.travi.org)
[π](https://github.com/kentcdodds/validate-commit-msg/issues?q=author%3Atravi) |
+| [
Bo Lingen](https://github.com/citycide)
[π](https://github.com/kentcdodds/validate-commit-msg/commits?author=citycide) | [
Spyros Ioakeimidis](http://www.spyros.io)
[π»](https://github.com/kentcdodds/validate-commit-msg/commits?author=spirosikmd) [π](https://github.com/kentcdodds/validate-commit-msg/commits?author=spirosikmd) [β οΈ](https://github.com/kentcdodds/validate-commit-msg/commits?author=spirosikmd) | [
Matt Travi](https://matt.travi.org)
[π](https://github.com/kentcdodds/validate-commit-msg/issues?q=author%3Atravi) | [
Jonathan Garbee](http://jonathan.garbee.me)
[π»](https://github.com/kentcdodds/validate-commit-msg/commits?author=Garbee) [π](https://github.com/kentcdodds/validate-commit-msg/commits?author=Garbee) [β οΈ](https://github.com/kentcdodds/validate-commit-msg/commits?author=Garbee) |
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
diff --git a/lib/validateMessage.js b/lib/validateMessage.js
index ae28f5c..4da90d7 100644
--- a/lib/validateMessage.js
+++ b/lib/validateMessage.js
@@ -82,6 +82,8 @@ exports.validateMessage = function validateMessage(raw) {
isValid = false;
}
+ isValid = validateScope(isValid, scope);
+
if (config.autoFix) {
subject = lowercaseFirstLetter(subject);
}
@@ -94,7 +96,6 @@ exports.validateMessage = function validateMessage(raw) {
// Some more ideas, do want anything like this ?
// - Validate the rest of the message (body, footer, BREAKING CHANGE annotations)
- // - allow only specific scopes (eg. fix(docs) should not be allowed ?
// - auto add empty line after subject ?
// - auto remove empty () ?
// - auto correct typos in type ?
@@ -128,3 +129,43 @@ function lowercase(string) {
function lowercaseFirstLetter(string) {
return lowercase(string.charAt(0)) + string.slice(1);
}
+
+function validateScope(isValid, scope) {
+ config.scope = config.scope || {};
+ var validateScopes = config.scope.validate || false;
+ var multipleScopesAllowed = config.scope.multiple || false;
+ var allowedScopes = config.scope.allowed || '*';
+ var scopeRequired = config.scope.required || false;
+ var scopes = scope ? scope.split(',') : [];
+
+ function validateIndividualScope(item) {
+ if (allowedScopes[0].trim() === '*') {
+ return;
+ }
+ if (allowedScopes.indexOf(item) === -1) {
+ error('"%s" is not an allowed scope ! Valid scope are: %s', item, allowedScopes.join(', '));
+ isValid = false;
+ }
+ }
+
+ if (validateScopes) {
+ if (scopeRequired && scopes.length === 0) {
+ error('a scope is required !');
+ isValid = false;
+ }
+ if (isValid && multipleScopesAllowed) {
+ scopes.forEach(validateIndividualScope);
+ }
+ if (isValid && !multipleScopesAllowed) {
+ if (scopes.length > 1) {
+ error('only one scope can be provided !');
+ isValid = false;
+ }
+ if (isValid) {
+ validateIndividualScope(scopes[0]);
+ }
+ }
+ }
+
+ return isValid;
+};
diff --git a/test/validateMessage.test.js b/test/validateMessage.test.js
index a392574..ce4f14a 100644
--- a/test/validateMessage.test.js
+++ b/test/validateMessage.test.js
@@ -157,6 +157,81 @@ describe('validate-commit-msg.js', function() {
expect(logs).to.deep.equal([msg]);
});
+ it('should require a scope', function() {
+ var msg = 'feat: Add new feature';
+
+ m.config.scope = {
+ validate: true,
+ allowed: '*',
+ required: true
+ };
+
+ expect(m.validateMessage(msg)).to.equal(INVALID);
+ expect(errors[0]).to.equal('INVALID COMMIT MSG: a scope is required !');
+ expect(logs).to.deep.equal([msg]);
+
+ m.config.scope = undefined;
+ });
+
+ it('should validate scope', function() {
+ var msg = 'feat(nonexistant): Add new feature';
+
+ m.config.scope = {
+ validate: true,
+ allowed: ['button', 'card']
+ };
+
+ expect(m.validateMessage(msg)).to.equal(INVALID);
+ expect(errors[0]).to.equal('INVALID COMMIT MSG: "nonexistant" is not an allowed scope ! Valid scope are: ' + m.config.scope.allowed.join(', '));
+ expect(logs).to.deep.equal([msg]);
+
+ m.config.scope = undefined;
+ });
+
+ it('should only allow a single scope when multiples is off', function() {
+ var msg = 'feat(button,card): Add new feature';
+
+ m.config.scope = {
+ validate: true,
+ allowed: '*'
+ };
+
+ expect(m.validateMessage(msg)).to.equal(INVALID);
+ expect(errors[0]).to.equal('INVALID COMMIT MSG: only one scope can be provided !');
+ expect(logs).to.deep.equal([msg]);
+
+ m.config.scope = undefined;
+ });
+
+ it('should catch an invalid scope among many', function() {
+ var msg = 'feat(button,card,ripple): Add new feature';
+
+ m.config.scope = {
+ validate: true,
+ allowed: ['button', 'card'],
+ multiple: true
+ };
+
+ expect(m.validateMessage(msg)).to.equal(INVALID);
+ expect(errors[0]).to.equal('INVALID COMMIT MSG: "ripple" is not an allowed scope ! Valid scope are: ' + m.config.scope.allowed.join(', '));
+ expect(logs).to.deep.equal([msg]);
+
+ m.config.scope = undefined;
+ });
+
+ it('should allow any scope if "*" is defined', function() {
+ var msg = 'feat(anything): Fixed';
+
+ m.config.scope = {
+ validate: true
+ };
+
+ expect(m.validateMessage(msg)).to.equal(VALID);
+ expect(logs).to.deep.equal([]);
+
+ m.config.scope = undefined;
+ });
+
it('should allow empty scope', function() {
expect(m.validateMessage('fix: blablabla')).to.equal(VALID);
expect(errors).to.deep.equal([]);