NodeJS commit message validator
I wrote a commit message validator + CLI in NodeJS.
Notes:
My greatest concern is that the patten I use to represent the results of a validation is inadequate. Options:
- Use adhoc enums
- Create a
ValidationResult
class (?) - Extend
Error
and return an array of those. In this case, how would the--verbose
option, which shows passed rules and informational rules work?
Is the pattern I use in
lib/rules.js
to represent each of the rules adequate?Is there a better (performance and/or readability-wise) way of stripping commit messages than the approach I use in
lib/strip.js
?Other feedback is welcome too, of course.
index.js
:
const strip = require('./lib/strip');
const rules = require('./lib/rules');
function validate(commitMessage) {
const strippedMessage = strip(commitMessage);
const results = ;
for (const rule of rules) {
let outcome;
if (rule.test === undefined) {
outcome = 'info';
results.push({
type: outcome,
message: rule.message
});
continue;
}
if (rule.test(strippedMessage)) {
outcome = 'pass';
} else {
outcome = 'fail';
}
results.push({
type: outcome,
message: rule.message
});
}
return results;
}
module.exports = validate;
cli.js
:
#!/usr/bin/env node
const meow = require('meow');
const fs = require('fs');
const stdin = require('get-stdin');
const validate = require('.');
const log = require('./lib/log');
const cli = meow({
description: 'Validate commit messages against the seven rules of commit messages.',
flags: {
silent: {
type: 'boolean',
alias: 's'
},
verbose: {
type: 'boolean',
alias: 'v'
},
// TODO: Work with --file flag
file: {
type: 'string',
alias: 'f'
}
// TODO: If nothing else, read stdin
}
});
log(); // Leading new line
if (cli.input.length === 0) {
// TODO: Cry
}
const [commitMessage] = cli.input;
const results = validate(commitMessage);
let exitCode = 0;
for (const result of results) {
switch (result.type) {
case 'fail':
if (!cli.flags.silent) {
log.error(result.message);
}
if (exitCode === 0) { exitCode = 1; }
break;
case 'pass':
case 'info':
if (!cli.flags.silent && cli.flags.verbose) {
log[result.type](result.message);
}
break;
default:
throw new Error(`Internal Error: Invalid result type '${result.type}'`);
}
}
process.exit(exitCode);
lib/
lib/rules.js
:
const one = {
message: 'Separate subject from body with a blank line',
test: (commitMessage) => {
const separatedByLf = /^.+(nn(?:.|n)+|n?)$/g;
return separatedByLf.test(commitMessage);
}
};
const two = {
message: 'Limit the subject line to 50 characters',
test: (commitMessage) => {
const subjectLine = getSubjectLine(commitMessage);
const cutOff = 50;
return subjectLine.length < cutOff;
}
};
const three = {
message: 'Capitalize the subject line',
test: (commitMessage) => {
const subjectLine = getSubjectLine(commitMessage);
const firstCharacter = subjectLine[0];
return !isLowerCase(firstCharacter);
}
};
const four = {
message: 'Do not end the subject line with a period',
test: (commitMessage) => {
const subjectLine = getSubjectLine(commitMessage);
const lastCharacter = subjectLine.substr(-1);
return !(lastCharacter === '.');
}
};
const five = {
message: 'Use the imperative mood in the subject line'
// We could, in theory, use NLP to check for this rule,
// ...but it would take effort and would be error prone
};
const six = {
message: 'Wrap the body at 72 characters',
test: (commitMessage) => {
const bodyLines = getBody(commitMessage).split('n');
return bodyLines.every(line => line.length < 72);
}
};
const seven = {
message: 'Use the body to explain _what_ and _why_ vs. _how_'
// This is obviously not detectable programtically
};
const rules = [
one, two, three, four, five, six, seven
];
module.exports = rules;
function getSubjectLine(commitMessage) {
return commitMessage.split('n')[0];
}
function getBody(commitMessage) {
const [, ...body] = commitMessage.split('n');
return body.join('n');
}
function isLowerCase(char) {
return !(char.toUpperCase() === char);
}
lib/log.js
:
const chalk = require('chalk');
const logSymbols = require('log-symbols');
function log(...args) {
args = args.join(' ');
console.log(args);
}
log.error = (...args) => {
console.error(chalk.red(logSymbols.error, args));
};
log.success = (...args) => {
log(chalk.green(logSymbols.success, args));
};
log.warn = (...args) => {
console.warn(chalk.yellow(logSymbols.warn, args));
};
log.info = (...args) => {
console.info(chalk.blue(logSymbols.info, args));
};
module.exports = log;
lib/strip.js
:
// See: https://git-scm.com/docs/git-commit#git-commit-strip
// TODO: Respect git's core.commentchar
function strip(rawCommitMessage) {
const trailingWhitespace = /[ tfv]+$/gm;
const commentary = /^#.*/gm;
const consecutiveEmptyLines = /n{3,}/g;
const leadingTrailingEmptyLines = /^n+|n+$/g;
return rawCommitMessage
.replace(trailingWhitespace, '')
.replace(commentary, '')
.replace(consecutiveEmptyLines, 'nn')
.replace(leadingTrailingEmptyLines, '');
}
module.exports = strip;
javascript node.js console
add a comment |
I wrote a commit message validator + CLI in NodeJS.
Notes:
My greatest concern is that the patten I use to represent the results of a validation is inadequate. Options:
- Use adhoc enums
- Create a
ValidationResult
class (?) - Extend
Error
and return an array of those. In this case, how would the--verbose
option, which shows passed rules and informational rules work?
Is the pattern I use in
lib/rules.js
to represent each of the rules adequate?Is there a better (performance and/or readability-wise) way of stripping commit messages than the approach I use in
lib/strip.js
?Other feedback is welcome too, of course.
index.js
:
const strip = require('./lib/strip');
const rules = require('./lib/rules');
function validate(commitMessage) {
const strippedMessage = strip(commitMessage);
const results = ;
for (const rule of rules) {
let outcome;
if (rule.test === undefined) {
outcome = 'info';
results.push({
type: outcome,
message: rule.message
});
continue;
}
if (rule.test(strippedMessage)) {
outcome = 'pass';
} else {
outcome = 'fail';
}
results.push({
type: outcome,
message: rule.message
});
}
return results;
}
module.exports = validate;
cli.js
:
#!/usr/bin/env node
const meow = require('meow');
const fs = require('fs');
const stdin = require('get-stdin');
const validate = require('.');
const log = require('./lib/log');
const cli = meow({
description: 'Validate commit messages against the seven rules of commit messages.',
flags: {
silent: {
type: 'boolean',
alias: 's'
},
verbose: {
type: 'boolean',
alias: 'v'
},
// TODO: Work with --file flag
file: {
type: 'string',
alias: 'f'
}
// TODO: If nothing else, read stdin
}
});
log(); // Leading new line
if (cli.input.length === 0) {
// TODO: Cry
}
const [commitMessage] = cli.input;
const results = validate(commitMessage);
let exitCode = 0;
for (const result of results) {
switch (result.type) {
case 'fail':
if (!cli.flags.silent) {
log.error(result.message);
}
if (exitCode === 0) { exitCode = 1; }
break;
case 'pass':
case 'info':
if (!cli.flags.silent && cli.flags.verbose) {
log[result.type](result.message);
}
break;
default:
throw new Error(`Internal Error: Invalid result type '${result.type}'`);
}
}
process.exit(exitCode);
lib/
lib/rules.js
:
const one = {
message: 'Separate subject from body with a blank line',
test: (commitMessage) => {
const separatedByLf = /^.+(nn(?:.|n)+|n?)$/g;
return separatedByLf.test(commitMessage);
}
};
const two = {
message: 'Limit the subject line to 50 characters',
test: (commitMessage) => {
const subjectLine = getSubjectLine(commitMessage);
const cutOff = 50;
return subjectLine.length < cutOff;
}
};
const three = {
message: 'Capitalize the subject line',
test: (commitMessage) => {
const subjectLine = getSubjectLine(commitMessage);
const firstCharacter = subjectLine[0];
return !isLowerCase(firstCharacter);
}
};
const four = {
message: 'Do not end the subject line with a period',
test: (commitMessage) => {
const subjectLine = getSubjectLine(commitMessage);
const lastCharacter = subjectLine.substr(-1);
return !(lastCharacter === '.');
}
};
const five = {
message: 'Use the imperative mood in the subject line'
// We could, in theory, use NLP to check for this rule,
// ...but it would take effort and would be error prone
};
const six = {
message: 'Wrap the body at 72 characters',
test: (commitMessage) => {
const bodyLines = getBody(commitMessage).split('n');
return bodyLines.every(line => line.length < 72);
}
};
const seven = {
message: 'Use the body to explain _what_ and _why_ vs. _how_'
// This is obviously not detectable programtically
};
const rules = [
one, two, three, four, five, six, seven
];
module.exports = rules;
function getSubjectLine(commitMessage) {
return commitMessage.split('n')[0];
}
function getBody(commitMessage) {
const [, ...body] = commitMessage.split('n');
return body.join('n');
}
function isLowerCase(char) {
return !(char.toUpperCase() === char);
}
lib/log.js
:
const chalk = require('chalk');
const logSymbols = require('log-symbols');
function log(...args) {
args = args.join(' ');
console.log(args);
}
log.error = (...args) => {
console.error(chalk.red(logSymbols.error, args));
};
log.success = (...args) => {
log(chalk.green(logSymbols.success, args));
};
log.warn = (...args) => {
console.warn(chalk.yellow(logSymbols.warn, args));
};
log.info = (...args) => {
console.info(chalk.blue(logSymbols.info, args));
};
module.exports = log;
lib/strip.js
:
// See: https://git-scm.com/docs/git-commit#git-commit-strip
// TODO: Respect git's core.commentchar
function strip(rawCommitMessage) {
const trailingWhitespace = /[ tfv]+$/gm;
const commentary = /^#.*/gm;
const consecutiveEmptyLines = /n{3,}/g;
const leadingTrailingEmptyLines = /^n+|n+$/g;
return rawCommitMessage
.replace(trailingWhitespace, '')
.replace(commentary, '')
.replace(consecutiveEmptyLines, 'nn')
.replace(leadingTrailingEmptyLines, '');
}
module.exports = strip;
javascript node.js console
add a comment |
I wrote a commit message validator + CLI in NodeJS.
Notes:
My greatest concern is that the patten I use to represent the results of a validation is inadequate. Options:
- Use adhoc enums
- Create a
ValidationResult
class (?) - Extend
Error
and return an array of those. In this case, how would the--verbose
option, which shows passed rules and informational rules work?
Is the pattern I use in
lib/rules.js
to represent each of the rules adequate?Is there a better (performance and/or readability-wise) way of stripping commit messages than the approach I use in
lib/strip.js
?Other feedback is welcome too, of course.
index.js
:
const strip = require('./lib/strip');
const rules = require('./lib/rules');
function validate(commitMessage) {
const strippedMessage = strip(commitMessage);
const results = ;
for (const rule of rules) {
let outcome;
if (rule.test === undefined) {
outcome = 'info';
results.push({
type: outcome,
message: rule.message
});
continue;
}
if (rule.test(strippedMessage)) {
outcome = 'pass';
} else {
outcome = 'fail';
}
results.push({
type: outcome,
message: rule.message
});
}
return results;
}
module.exports = validate;
cli.js
:
#!/usr/bin/env node
const meow = require('meow');
const fs = require('fs');
const stdin = require('get-stdin');
const validate = require('.');
const log = require('./lib/log');
const cli = meow({
description: 'Validate commit messages against the seven rules of commit messages.',
flags: {
silent: {
type: 'boolean',
alias: 's'
},
verbose: {
type: 'boolean',
alias: 'v'
},
// TODO: Work with --file flag
file: {
type: 'string',
alias: 'f'
}
// TODO: If nothing else, read stdin
}
});
log(); // Leading new line
if (cli.input.length === 0) {
// TODO: Cry
}
const [commitMessage] = cli.input;
const results = validate(commitMessage);
let exitCode = 0;
for (const result of results) {
switch (result.type) {
case 'fail':
if (!cli.flags.silent) {
log.error(result.message);
}
if (exitCode === 0) { exitCode = 1; }
break;
case 'pass':
case 'info':
if (!cli.flags.silent && cli.flags.verbose) {
log[result.type](result.message);
}
break;
default:
throw new Error(`Internal Error: Invalid result type '${result.type}'`);
}
}
process.exit(exitCode);
lib/
lib/rules.js
:
const one = {
message: 'Separate subject from body with a blank line',
test: (commitMessage) => {
const separatedByLf = /^.+(nn(?:.|n)+|n?)$/g;
return separatedByLf.test(commitMessage);
}
};
const two = {
message: 'Limit the subject line to 50 characters',
test: (commitMessage) => {
const subjectLine = getSubjectLine(commitMessage);
const cutOff = 50;
return subjectLine.length < cutOff;
}
};
const three = {
message: 'Capitalize the subject line',
test: (commitMessage) => {
const subjectLine = getSubjectLine(commitMessage);
const firstCharacter = subjectLine[0];
return !isLowerCase(firstCharacter);
}
};
const four = {
message: 'Do not end the subject line with a period',
test: (commitMessage) => {
const subjectLine = getSubjectLine(commitMessage);
const lastCharacter = subjectLine.substr(-1);
return !(lastCharacter === '.');
}
};
const five = {
message: 'Use the imperative mood in the subject line'
// We could, in theory, use NLP to check for this rule,
// ...but it would take effort and would be error prone
};
const six = {
message: 'Wrap the body at 72 characters',
test: (commitMessage) => {
const bodyLines = getBody(commitMessage).split('n');
return bodyLines.every(line => line.length < 72);
}
};
const seven = {
message: 'Use the body to explain _what_ and _why_ vs. _how_'
// This is obviously not detectable programtically
};
const rules = [
one, two, three, four, five, six, seven
];
module.exports = rules;
function getSubjectLine(commitMessage) {
return commitMessage.split('n')[0];
}
function getBody(commitMessage) {
const [, ...body] = commitMessage.split('n');
return body.join('n');
}
function isLowerCase(char) {
return !(char.toUpperCase() === char);
}
lib/log.js
:
const chalk = require('chalk');
const logSymbols = require('log-symbols');
function log(...args) {
args = args.join(' ');
console.log(args);
}
log.error = (...args) => {
console.error(chalk.red(logSymbols.error, args));
};
log.success = (...args) => {
log(chalk.green(logSymbols.success, args));
};
log.warn = (...args) => {
console.warn(chalk.yellow(logSymbols.warn, args));
};
log.info = (...args) => {
console.info(chalk.blue(logSymbols.info, args));
};
module.exports = log;
lib/strip.js
:
// See: https://git-scm.com/docs/git-commit#git-commit-strip
// TODO: Respect git's core.commentchar
function strip(rawCommitMessage) {
const trailingWhitespace = /[ tfv]+$/gm;
const commentary = /^#.*/gm;
const consecutiveEmptyLines = /n{3,}/g;
const leadingTrailingEmptyLines = /^n+|n+$/g;
return rawCommitMessage
.replace(trailingWhitespace, '')
.replace(commentary, '')
.replace(consecutiveEmptyLines, 'nn')
.replace(leadingTrailingEmptyLines, '');
}
module.exports = strip;
javascript node.js console
I wrote a commit message validator + CLI in NodeJS.
Notes:
My greatest concern is that the patten I use to represent the results of a validation is inadequate. Options:
- Use adhoc enums
- Create a
ValidationResult
class (?) - Extend
Error
and return an array of those. In this case, how would the--verbose
option, which shows passed rules and informational rules work?
Is the pattern I use in
lib/rules.js
to represent each of the rules adequate?Is there a better (performance and/or readability-wise) way of stripping commit messages than the approach I use in
lib/strip.js
?Other feedback is welcome too, of course.
index.js
:
const strip = require('./lib/strip');
const rules = require('./lib/rules');
function validate(commitMessage) {
const strippedMessage = strip(commitMessage);
const results = ;
for (const rule of rules) {
let outcome;
if (rule.test === undefined) {
outcome = 'info';
results.push({
type: outcome,
message: rule.message
});
continue;
}
if (rule.test(strippedMessage)) {
outcome = 'pass';
} else {
outcome = 'fail';
}
results.push({
type: outcome,
message: rule.message
});
}
return results;
}
module.exports = validate;
cli.js
:
#!/usr/bin/env node
const meow = require('meow');
const fs = require('fs');
const stdin = require('get-stdin');
const validate = require('.');
const log = require('./lib/log');
const cli = meow({
description: 'Validate commit messages against the seven rules of commit messages.',
flags: {
silent: {
type: 'boolean',
alias: 's'
},
verbose: {
type: 'boolean',
alias: 'v'
},
// TODO: Work with --file flag
file: {
type: 'string',
alias: 'f'
}
// TODO: If nothing else, read stdin
}
});
log(); // Leading new line
if (cli.input.length === 0) {
// TODO: Cry
}
const [commitMessage] = cli.input;
const results = validate(commitMessage);
let exitCode = 0;
for (const result of results) {
switch (result.type) {
case 'fail':
if (!cli.flags.silent) {
log.error(result.message);
}
if (exitCode === 0) { exitCode = 1; }
break;
case 'pass':
case 'info':
if (!cli.flags.silent && cli.flags.verbose) {
log[result.type](result.message);
}
break;
default:
throw new Error(`Internal Error: Invalid result type '${result.type}'`);
}
}
process.exit(exitCode);
lib/
lib/rules.js
:
const one = {
message: 'Separate subject from body with a blank line',
test: (commitMessage) => {
const separatedByLf = /^.+(nn(?:.|n)+|n?)$/g;
return separatedByLf.test(commitMessage);
}
};
const two = {
message: 'Limit the subject line to 50 characters',
test: (commitMessage) => {
const subjectLine = getSubjectLine(commitMessage);
const cutOff = 50;
return subjectLine.length < cutOff;
}
};
const three = {
message: 'Capitalize the subject line',
test: (commitMessage) => {
const subjectLine = getSubjectLine(commitMessage);
const firstCharacter = subjectLine[0];
return !isLowerCase(firstCharacter);
}
};
const four = {
message: 'Do not end the subject line with a period',
test: (commitMessage) => {
const subjectLine = getSubjectLine(commitMessage);
const lastCharacter = subjectLine.substr(-1);
return !(lastCharacter === '.');
}
};
const five = {
message: 'Use the imperative mood in the subject line'
// We could, in theory, use NLP to check for this rule,
// ...but it would take effort and would be error prone
};
const six = {
message: 'Wrap the body at 72 characters',
test: (commitMessage) => {
const bodyLines = getBody(commitMessage).split('n');
return bodyLines.every(line => line.length < 72);
}
};
const seven = {
message: 'Use the body to explain _what_ and _why_ vs. _how_'
// This is obviously not detectable programtically
};
const rules = [
one, two, three, four, five, six, seven
];
module.exports = rules;
function getSubjectLine(commitMessage) {
return commitMessage.split('n')[0];
}
function getBody(commitMessage) {
const [, ...body] = commitMessage.split('n');
return body.join('n');
}
function isLowerCase(char) {
return !(char.toUpperCase() === char);
}
lib/log.js
:
const chalk = require('chalk');
const logSymbols = require('log-symbols');
function log(...args) {
args = args.join(' ');
console.log(args);
}
log.error = (...args) => {
console.error(chalk.red(logSymbols.error, args));
};
log.success = (...args) => {
log(chalk.green(logSymbols.success, args));
};
log.warn = (...args) => {
console.warn(chalk.yellow(logSymbols.warn, args));
};
log.info = (...args) => {
console.info(chalk.blue(logSymbols.info, args));
};
module.exports = log;
lib/strip.js
:
// See: https://git-scm.com/docs/git-commit#git-commit-strip
// TODO: Respect git's core.commentchar
function strip(rawCommitMessage) {
const trailingWhitespace = /[ tfv]+$/gm;
const commentary = /^#.*/gm;
const consecutiveEmptyLines = /n{3,}/g;
const leadingTrailingEmptyLines = /^n+|n+$/g;
return rawCommitMessage
.replace(trailingWhitespace, '')
.replace(commentary, '')
.replace(consecutiveEmptyLines, 'nn')
.replace(leadingTrailingEmptyLines, '');
}
module.exports = strip;
javascript node.js console
javascript node.js console
asked yesterday
shreyasminochashreyasminocha
20718
20718
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
Your code looks mostly good, but here are some things:
lib/log.js
: You don't need thelog
function.console.log
does exactly what you do in that function (well not exactly, but it shouldn't make a difference in this context). You can just setlog = (...args) => console.log(...args)
orfunction log(...args) {console.log(...args)}
lib/rules.js
In theisLowerCase
function, you are checking!(char.toUpperCase() === char)
. You should use!==
New contributor
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f211019%2fnodejs-commit-message-validator%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Your code looks mostly good, but here are some things:
lib/log.js
: You don't need thelog
function.console.log
does exactly what you do in that function (well not exactly, but it shouldn't make a difference in this context). You can just setlog = (...args) => console.log(...args)
orfunction log(...args) {console.log(...args)}
lib/rules.js
In theisLowerCase
function, you are checking!(char.toUpperCase() === char)
. You should use!==
New contributor
add a comment |
Your code looks mostly good, but here are some things:
lib/log.js
: You don't need thelog
function.console.log
does exactly what you do in that function (well not exactly, but it shouldn't make a difference in this context). You can just setlog = (...args) => console.log(...args)
orfunction log(...args) {console.log(...args)}
lib/rules.js
In theisLowerCase
function, you are checking!(char.toUpperCase() === char)
. You should use!==
New contributor
add a comment |
Your code looks mostly good, but here are some things:
lib/log.js
: You don't need thelog
function.console.log
does exactly what you do in that function (well not exactly, but it shouldn't make a difference in this context). You can just setlog = (...args) => console.log(...args)
orfunction log(...args) {console.log(...args)}
lib/rules.js
In theisLowerCase
function, you are checking!(char.toUpperCase() === char)
. You should use!==
New contributor
Your code looks mostly good, but here are some things:
lib/log.js
: You don't need thelog
function.console.log
does exactly what you do in that function (well not exactly, but it shouldn't make a difference in this context). You can just setlog = (...args) => console.log(...args)
orfunction log(...args) {console.log(...args)}
lib/rules.js
In theisLowerCase
function, you are checking!(char.toUpperCase() === char)
. You should use!==
New contributor
edited 22 hours ago
New contributor
answered 22 hours ago
FireCubezFireCubez
1011
1011
New contributor
New contributor
add a comment |
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f211019%2fnodejs-commit-message-validator%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown