Skip to content

Commit d59514a

Browse files
committed
✨ Feat: add scope and default values (fixes #18)
1 parent d150c5e commit d59514a

File tree

11 files changed

+123
-22
lines changed

11 files changed

+123
-22
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,30 @@ $ sgc
4141
You can even create a global config. Just go to your users home and create a `.sgcrc`. The global config will be triggered if no project configurations are present.
4242

4343
**Options:**
44+
- [questions](#questions)
4445
- [emojies](#emojies)
4546
- [types](#types)
4647
- [rules](#rules)
4748

49+
### questions
50+
51+
**Type:** `object`
52+
53+
**Options:**
54+
- `scope` Asks for the scope in parentheses of the commit. Default: `false`
55+
- `moreInfo` Asks if more info (body) should be added. Default: `true`
56+
57+
An object with predefined settings, what should be asked.
58+
59+
Example:
60+
```js
61+
{
62+
"questions": {
63+
"scope": true
64+
}
65+
}
66+
```
67+
4868
### emojies
4969

5070
**Type:** `boolean`

lib/cli.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import updateNotifier from 'update-notifier';
1010
import pkg from '../package.json';
1111
import getConfig from './getConfig';
1212
import questions from './questions';
13+
import combineTypeScope from './helpers/combineTypeScope';
1314

1415
const config = getConfig();
1516
const questionsList = questions(config);
@@ -31,7 +32,8 @@ if (argv.v) {
3132
console.error(chalk.red('Please', chalk.bold('git add'), 'some files first before you commit.'));
3233
} else {
3334
inquirer.prompt(questionsList).then((answers) => {
34-
const message = answers.moreInfo ? `${answers.editor}` : `${answers.type} ${answers.description}`;
35+
const typeScope = combineTypeScope(answers.type, answers.scope);
36+
const message = answers.moreInfo ? `${answers.editor}` : `${typeScope} ${answers.description}`;
3537

3638
return execa('git', ['commit', '-m', message], { stdio: 'inherit' })
3739
.catch(() => {

lib/getConfig.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os from 'os';
22
import path from 'path';
33
import json from 'json-extra';
4+
import merge from 'lodash.merge';
45

56
const cwd = process.cwd();
67
const homedir = os.homedir();
@@ -18,7 +19,17 @@ const getConfig = (altPath) => {
1819
// - 2. (package.json).sgc
1920
// 2. global config
2021
// 3. default config from ../.sgcrc_default
21-
const config = configObject || packageConfig || globalConfig || sgcrcDefaultConfig;
22+
let config = configObject || packageConfig || globalConfig || sgcrcDefaultConfig;
23+
24+
// set defaults
25+
const configDefaults = {
26+
questions: {
27+
scope: false,
28+
moreInfo: true,
29+
},
30+
};
31+
32+
config = merge({}, configDefaults, config);
2233

2334
return config;
2435
};

lib/helpers/combineTypeScope.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
const combineTypeScope = (type, scope) => {
2+
let thisType = type;
3+
let thisScope = scope;
4+
5+
if (thisScope === undefined) {
6+
thisScope = '';
7+
}
8+
9+
// add scope correctly if ':' is at the end
10+
if (thisScope.length > 0) {
11+
if (thisType.charAt(thisType.length - 1) === ':') {
12+
thisType = thisType.slice(0, thisType.length - 1);
13+
thisType = `${thisType} ${thisScope}:`;
14+
} else {
15+
thisType = `${thisType} ${thisScope}`;
16+
}
17+
}
18+
19+
return thisType;
20+
};
21+
22+
export default combineTypeScope;

lib/questions.js

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import chalk from 'chalk';
22
import ruleWarningMessages from './rules/ruleWarningMessages';
3+
import combineTypeScope from './helpers/combineTypeScope';
34

4-
const choices = (configuration) => {
5+
const choices = (config) => {
56
const choicesList = [];
67

7-
configuration.types.forEach((type) => {
8-
const isEmojies = configuration.emojies === undefined ? true : configuration.emojies;
8+
config.types.forEach((type) => {
9+
const isEmojies = config.emojies === undefined ? true : config.emojies;
910
const emoji = isEmojies && type.emoji ? `${type.emoji} ` : '';
1011
const configType = type.type;
1112
const description = type.description || '';
@@ -28,6 +29,13 @@ const questions = (config) => {
2829
message: 'Select the type of your commit:',
2930
choices: choicesList,
3031
},
32+
{
33+
type: 'input',
34+
name: 'scope',
35+
message: 'Enter your scope (no whitespaces allowed):',
36+
when: () => config.questions.scope,
37+
filter: answers => (answers ? `(${answers})` : answers),
38+
},
3139
{
3240
type: 'input',
3341
name: 'description',
@@ -42,14 +50,19 @@ const questions = (config) => {
4250
type: 'confirm',
4351
name: 'moreInfo',
4452
message: 'Do you want to add more information to your commit?',
53+
when: () => config.questions.moreInfo,
4554
default: false,
4655
},
4756
{
4857
type: 'editor',
4958
name: 'editor',
5059
message: 'This will let you add more information',
5160
when: answers => answers.moreInfo,
52-
default: answers => `${answers.type} ${answers.description}\n\n\n`,
61+
default: (answers) => {
62+
const type = combineTypeScope(answers.type, answers.scope);
63+
64+
return `${type} ${answers.description}\n\n\n`;
65+
},
5366
},
5467
];
5568

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
"is-git-added": "^1.0.1",
6969
"is-git-repository": "^1.0.1",
7070
"json-extra": "^0.5.0",
71+
"lodash.merge": "^4.6.0",
7172
"object.entries": "^1.0.4",
7273
"update-notifier": "^2.1.0",
7374
"yargs": "^7.0.2"

test/fixtures/.sgcrc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
{
2+
"questions": {
3+
"scope": false,
4+
"moreInfo": true
5+
},
26
"types": [
37
{
48
"emoji": ":emo:",

test/getConfig.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ const randomString = Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0
1515

1616
let globalExist = false;
1717

18-
1918
// rename global .sgcrc
2019
test.before(() => {
2120
if (fs.existsSync(path.join(homedir, '.sgcrc'))) {
@@ -24,7 +23,7 @@ test.before(() => {
2423
}
2524
});
2625

27-
test.after(() => {
26+
test.after.always(() => {
2827
if (globalExist) {
2928
fs.renameSync(path.join(homedir, `.sgcrc.${randomString}-${datetime}.back`), path.join(homedir, '.sgcrc'));
3029
}
@@ -35,10 +34,17 @@ test('read config from a specific path', (t) => {
3534
});
3635

3736
test('read config from a .sgcrc_default', (t) => {
38-
t.deepEqual(getConfig(), json.readToObjSync(path.join(cwd, '.sgcrc_default')));
37+
const globalConfig = json.readToObjSync(path.join(cwd, '.sgcrc_default'));
38+
39+
globalConfig.questions = {
40+
scope: false,
41+
moreInfo: true,
42+
};
43+
44+
t.deepEqual(getConfig(), globalConfig);
3945
});
4046

41-
test.serial('read config from package.json', (t) => {
47+
test('read config from package.json', (t) => {
4248
const sgcrc = json.readToObjSync(path.join(fixtures, '.sgcrc'));
4349
const packageJson = json.readToObjSync(path.join(cwd, 'package.json'));
4450

test/helpers/combineTypeScope.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import test from 'ava';
2+
3+
import combineTypeScope from '../../lib/helpers/combineTypeScope';
4+
5+
test('check if the combination is correct', (t) => {
6+
t.is(combineTypeScope('Type:', '(scope)'), 'Type (scope):');
7+
t.is(combineTypeScope('Type', '(scope)'), 'Type (scope)');
8+
});

test/questions.js

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import os from 'os';
22
import test from 'ava';
33
import path from 'path';
44
import fs from 'fs-extra';
5-
import json from 'json-extra';
65

76
import getConfig from '../lib/getConfig';
87
import questions, { choices } from '../lib/questions';
@@ -25,16 +24,12 @@ test.before(() => {
2524
}
2625
});
2726

28-
test.after(() => {
27+
test.after.always(() => {
2928
if (globalExist) {
3029
fs.renameSync(path.join(homedir, `.sgcrc.${randomString}-${datetime}.back`), path.join(homedir, '.sgcrc'));
3130
}
3231
});
3332

34-
test('get configuration file equals .sgcrc_default', (t) => {
35-
t.deepEqual(getConfig(), json.readToObjSync(path.join(cwd, '.sgcrc_default')));
36-
});
37-
3833
test('choices are rendered without emojis', (t) => {
3934
const sgc = getConfig(path.join(fixtures, '.sgcrc'));
4035

@@ -56,22 +51,37 @@ test('check the values of the question object', (t) => {
5651
const config = getConfig();
5752
const questionsList = questions(config);
5853

59-
t.deepEqual(typeof questionsList, 'object');
54+
t.is(typeof questionsList, 'object');
55+
});
56+
57+
test('check if scope is off by default', (t) => {
58+
const config = getConfig();
59+
const questionsList = questions(config);
60+
61+
t.is(questionsList[1].when(), false);
62+
});
63+
64+
test('check if scope validates correctly', (t) => {
65+
const config = getConfig();
66+
const questionsList = questions(config);
67+
68+
t.is(questionsList[1].filter('answer'), '(answer)');
69+
t.is(questionsList[1].filter(''), '');
6070
});
6171

6272
test('validate functions in questions', (t) => {
6373
const config = getConfig();
6474
const questionsList = questions(config);
6575

66-
t.deepEqual(questionsList[1].validate('input text'), true);
67-
t.deepEqual(questionsList[1].validate('This message has over 72 characters. So this test will definitely fail. I can guarantee that I am telling the truth'), 'The commit message is not allowed to be longer as 72. Consider writing a body.\n');
76+
t.is(questionsList[2].validate('input text'), true);
77+
t.is(questionsList[2].validate('This message has over 72 characters. So this test will definitely fail. I can guarantee that I am telling the truth'), 'The commit message is not allowed to be longer as 72. Consider writing a body.\n');
6878
});
6979

7080
test('when and default functions in questions', (t) => {
7181
const config = getConfig();
7282
const questionsList = questions(config);
7383

74-
t.deepEqual(questionsList[3].when({ moreInfo: true }), true);
75-
t.deepEqual(questionsList[3].when({ moreInfo: false }), false);
76-
t.deepEqual(questionsList[3].default({ type: ':wrench: Chore:', description: 'This is a commit message!', moreInfo: true }), ':wrench: Chore: This is a commit message!\n\n\n');
84+
t.is(questionsList[4].when({ moreInfo: true }), true);
85+
t.is(questionsList[4].when({ moreInfo: false }), false);
86+
t.deepEqual(questionsList[4].default({ type: ':wrench: Chore:', description: 'This is a commit message!', moreInfo: true }), ':wrench: Chore: This is a commit message!\n\n\n');
7787
});

0 commit comments

Comments
 (0)