conventional-commits-parser
Advanced tools
Comparing version 0.0.14 to 0.0.15
16
index.js
'use strict'; | ||
var _ = require('lodash'); | ||
var parser = require('./lib/parser'); | ||
var regex = require('./lib/regex'); | ||
var through = require('through2'); | ||
var _ = require('lodash'); | ||
@@ -30,2 +31,3 @@ function conventionalCommitsParser(options) { | ||
headerCorrespondence: ['type', 'scope', 'subject'], | ||
noteKeywords: ['BREAKING CHANGE'], | ||
referenceKeywords: [ | ||
@@ -41,8 +43,12 @@ 'close', | ||
'resolved' | ||
], | ||
noteKeywords: [ | ||
'BREAKING CHANGE' | ||
] | ||
}, options); | ||
var reg = { | ||
hash: regex.reHash, | ||
referenceParts: regex.reReferenceParts, | ||
notes: regex.getNotesRegex(options.noteKeywords), | ||
references: regex.getReferencesRegex(options.referenceKeywords) | ||
}; | ||
return through.obj(function(data, enc, cb) { | ||
@@ -52,3 +58,3 @@ var commit; | ||
try { | ||
commit = parser(data.toString(), options); | ||
commit = parser(data.toString(), options, reg); | ||
cb(null, commit); | ||
@@ -55,0 +61,0 @@ } catch (err) { |
'use strict'; | ||
var regex = require('./regex'); | ||
var _ = require('lodash'); | ||
function parser(raw, options) { | ||
function parser(raw, options, regex) { | ||
if (!raw || !raw.trim()) { | ||
@@ -15,6 +14,10 @@ throw new TypeError('Expected a raw commit'); | ||
var headerMatch; | ||
var referenceSentences; | ||
var referenceMatch; | ||
var lines = _.compact(raw.split('\n')); | ||
var msg = {}; | ||
var continueNote = false; | ||
var isBody = true; | ||
var reNotes = regex.notes; | ||
var reReferenceParts = regex.referenceParts; | ||
var reReferences = regex.references; | ||
@@ -41,15 +44,16 @@ function getHeadCorrespondence(part) { | ||
msg.hash = lines[0]; | ||
msg.header = lines[1]; | ||
msg.type = null; | ||
msg.scope = null; | ||
msg.subject = null; | ||
msg.body = ''; | ||
msg.footer = ''; | ||
msg.notes = []; | ||
msg.references = []; | ||
// msg parts | ||
var hash = lines[0]; | ||
var header = lines[1]; | ||
var type = null; | ||
var scope = null; | ||
var subject = null; | ||
var body = ''; | ||
var footer = ''; | ||
var notes = []; | ||
var references = []; | ||
if (!msg.hash.match(regex.reHash)) { | ||
msg.header = msg.hash; | ||
msg.hash = null; | ||
if (!hash.match(regex.hash)) { | ||
header = hash; | ||
hash = null; | ||
lines.shift(); | ||
@@ -60,28 +64,38 @@ } else { | ||
if (!msg.header) { | ||
if (!header) { | ||
throw new Error('"' + raw + '" does not contain a header'); | ||
} | ||
headerMatch = msg.header.match(options.headerPattern); | ||
headerMatch = header.match(options.headerPattern); | ||
if (headerMatch) { | ||
if (headerMatch[typeIndex]) { | ||
msg.type = headerMatch[typeIndex]; | ||
type = headerMatch[typeIndex]; | ||
} | ||
if (headerMatch[scopeIndex]) { | ||
msg.scope = headerMatch[scopeIndex]; | ||
scope = headerMatch[scopeIndex]; | ||
} | ||
if (headerMatch[subjectIndex]) { | ||
msg.subject = headerMatch[subjectIndex]; | ||
subject = headerMatch[subjectIndex]; | ||
} | ||
} | ||
// incase people reference an issue in the header | ||
while (referenceSentences = reReferences.exec(header)) { | ||
var action = referenceSentences[1]; | ||
var sentence = referenceSentences[2]; | ||
while (referenceMatch = reReferenceParts.exec(sentence)) { | ||
var reference = { | ||
action: action.trim(), | ||
repository: referenceMatch[1] || null, | ||
issue: referenceMatch[2], | ||
raw: referenceMatch[0] | ||
}; | ||
references.push(reference); | ||
} | ||
} | ||
// body or footer | ||
_.forEach(lines, function(line) { | ||
var referenceMatch; | ||
var referenceMatched; | ||
var referenceSentences; | ||
var notes = msg.notes; | ||
var referenceKeywords = options.referenceKeywords; | ||
var reNotes = regex.getNotesRegex(options.noteKeywords); | ||
@@ -93,3 +107,3 @@ // this is a new important note | ||
isBody = false; | ||
msg.footer += line + '\n'; | ||
footer += line + '\n'; | ||
notes.push({ | ||
@@ -104,7 +118,6 @@ title: notesMatch[1], | ||
// this references an issue | ||
var reReferences = regex.getReferencesRegex(referenceKeywords); | ||
while (referenceSentences = reReferences.exec(line)) { | ||
var action = referenceSentences[1]; | ||
var sentence = referenceSentences[2]; | ||
while (referenceMatch = regex.reReferenceParts.exec(sentence)) { | ||
while (referenceMatch = reReferenceParts.exec(sentence)) { | ||
referenceMatched = true; | ||
@@ -119,3 +132,3 @@ continueNote = false; | ||
}; | ||
msg.references.push(reference); | ||
references.push(reference); | ||
} | ||
@@ -125,3 +138,3 @@ } | ||
if (referenceMatched) { | ||
msg.footer += line + '\n'; | ||
footer += line + '\n'; | ||
@@ -135,3 +148,3 @@ return; | ||
notes[notes.length - 1].text = text + (text ? '\n' : '') + line; | ||
msg.footer += line + '\n'; | ||
footer += line + '\n'; | ||
@@ -143,20 +156,30 @@ return; | ||
if (isBody) { | ||
msg.body += line + '\n'; | ||
body += line + '\n'; | ||
} else { | ||
msg.footer += line + '\n'; | ||
footer += line + '\n'; | ||
} | ||
}); | ||
msg.body = msg.body.trim(); | ||
msg.footer = msg.footer.trim(); | ||
if (!msg.body) { | ||
msg.body = null; | ||
body = body.trim(); | ||
footer = footer.trim(); | ||
if (!body) { | ||
body = null; | ||
} | ||
if (!msg.footer) { | ||
msg.footer = null; | ||
if (!footer) { | ||
footer = null; | ||
} | ||
return msg; | ||
return { | ||
hash: hash, | ||
header: header, | ||
type: type, | ||
scope: scope, | ||
subject: subject, | ||
body: body, | ||
footer: footer, | ||
notes: notes, | ||
references: references | ||
}; | ||
} | ||
module.exports = parser; |
{ | ||
"name": "conventional-commits-parser", | ||
"version": "0.0.14", | ||
"version": "0.0.15", | ||
"description": "Parse raw conventional commits", | ||
@@ -17,3 +17,5 @@ "homepage": "https://github.com/stevemao/conventional-commits-parser", | ||
"conventional", | ||
"parser" | ||
"parser", | ||
"parsing", | ||
"logs" | ||
], | ||
@@ -20,0 +22,0 @@ "dependencies": { |
@@ -145,4 +145,4 @@ 'use strict'; | ||
headerPattern: /^(\w*)(?:\(([\w\$\.\-\* ]*)\))?\ (.*)$/, | ||
referenceKeywords: ['fix'], | ||
noteKeywords: ['BREAKING CHANGES'] | ||
noteKeywords: ['BREAKING CHANGES'], | ||
referenceKeywords: ['fix'] | ||
})) | ||
@@ -191,5 +191,5 @@ .pipe(through.obj(function(chunk, enc, cb) { | ||
headerPattern: '^(\\w*)(?:\\(([\\w\\$\\.\\-\\* ]*)\\))?\\ (.*)$', | ||
referenceKeywords: 'fix', | ||
headerCorrespondence: 'subject,type, scope,', | ||
noteKeywords: 'BREAKING CHANGES', | ||
headerCorrespondence: 'subject,type, scope,' | ||
referenceKeywords: 'fix' | ||
})) | ||
@@ -196,0 +196,0 @@ .pipe(through.obj(function(chunk, enc, cb) { |
@@ -7,2 +7,3 @@ 'use strict'; | ||
var options; | ||
var regex; | ||
var msg; | ||
@@ -14,16 +15,12 @@ var simpleMsg; | ||
beforeEach(function() { | ||
regex = { | ||
hash: /\b[0-9a-f]{5,40}\b/, | ||
notes: /(BREAKING AMEND)[:\s]*(.*)/, | ||
referenceParts: /(?:.*?)??\s*(\S*?)??(?:gh-|#)(\d+)/gi, | ||
references: /(kill|kills|killed|handle|handles|handled)(?:\s+(.*?))(?=(?:kill|kills|killed|handle|handles|handled)|$)/gi | ||
}; | ||
options = { | ||
headerPattern: /^(\w*)(?:\(([\w\$\.\-\* ]*)\))?\: (.*)$/, | ||
headerCorrespondence: ['type', 'scope', 'subject'], | ||
referenceKeywords: [ | ||
'kill', | ||
'kills', | ||
'killed', | ||
'handle', | ||
'handles', | ||
'handled' | ||
], | ||
noteKeywords: [ | ||
'BREAKING AMEND' | ||
] | ||
headerCorrespondence: ['type', 'scope', 'subject'] | ||
}; | ||
@@ -40,3 +37,4 @@ | ||
'handle #33, Closes #100, Handled #3 kills repo#77', | ||
options | ||
options, | ||
regex | ||
); | ||
@@ -55,3 +53,4 @@ | ||
'handle #33, Closes #100, Handled #3', | ||
options | ||
options, | ||
regex | ||
); | ||
@@ -61,6 +60,7 @@ | ||
'chore: some chore\n', | ||
options | ||
options, | ||
regex | ||
); | ||
headerOnlyMsg = parser('header', options); | ||
headerOnlyMsg = parser('header', options, regex); | ||
}); | ||
@@ -94,3 +94,4 @@ | ||
'\nhandle #33, Closes #100, Handled #3 kills repo#77\n', | ||
options | ||
options, | ||
regex | ||
)); | ||
@@ -102,3 +103,3 @@ }); | ||
expect(function() { | ||
parser('9b1aff905b638aa274a5fc8f88662df446d374bd', options); | ||
parser('9b1aff905b638aa274a5fc8f88662df446d374bd', options, regex); | ||
}).to.throw('"9b1aff905b638aa274a5fc8f88662df446d374bd" does not contain a header'); | ||
@@ -157,3 +158,3 @@ }); | ||
headerCorrespondence: ['type', 'scope', 'subject'] | ||
}); | ||
}, regex); | ||
expect(msg.scope).to.equal('ng:list'); | ||
@@ -165,10 +166,4 @@ }); | ||
headerPattern: /^(\w*)?(?:\(([\w\$\.\-\* ]*)\))?\: (.*)?$/, | ||
headerCorrespondence: ['type', 'scope', 'subject'], | ||
referenceKeywords: [ | ||
'kill' | ||
], | ||
noteKeywords: [ | ||
'BREAKING AMEND' | ||
] | ||
}); | ||
headerCorrespondence: ['type', 'scope', 'subject'] | ||
}, regex); | ||
@@ -183,10 +178,4 @@ expect(msg.type).to.equal(null); | ||
headerPattern: /^(\w*)(?:\(([\w\$\.\-\* ]*)\))?\: (.*)$/, | ||
headerCorrespondence: ['scope', 'subject', 'type'], | ||
referenceKeywords: [ | ||
'kill' | ||
], | ||
noteKeywords: [ | ||
'BREAKING AMEND' | ||
] | ||
}); | ||
headerCorrespondence: ['scope', 'subject', 'type'] | ||
}, regex); | ||
@@ -202,12 +191,16 @@ expect(msg.type).to.equal('fix this'); | ||
headerPattern: /^(\w*)(?:\(([\w\$\.\-\* ]*)\))?\: (.*)$/, | ||
headerCorrespondence: ['scop', 'subject', 'type'], | ||
referenceKeywords: [ | ||
'kill' | ||
], | ||
noteKeywords: [ | ||
'BREAKING AMEND' | ||
] | ||
}); | ||
headerCorrespondence: ['scop', 'subject', 'type'] | ||
}, regex); | ||
}).to.throw('Expected options.headerCorrespondence to only contain "type" "scope" or "subject"'); | ||
}); | ||
it('should reference an issue', function() { | ||
var msg = parser('handled #1', options, regex); | ||
expect(msg.references).to.eql([{ | ||
action: 'handled', | ||
issue: '1', | ||
raw: '#1', | ||
repository: null | ||
}]); | ||
}); | ||
}); | ||
@@ -302,3 +295,3 @@ | ||
it('should put everything between or after references input footer', function() { | ||
it('should put everything after references in footer', function() { | ||
var msg = parser( | ||
@@ -314,3 +307,4 @@ '9b1aff905b638aa274a5fc8f88662df446d374bd\n' + | ||
'other', | ||
options | ||
options, | ||
regex | ||
); | ||
@@ -320,3 +314,91 @@ | ||
}); | ||
it('shoudl parse properly if important notes comes after references', function() { | ||
var msg = parser( | ||
'9b1aff905b638aa274a5fc8f88662df446d374bd\n' + | ||
'feat(scope): broadcast $destroy event on scope destruction\n' + | ||
'perf testing shows that in chrome this change adds 5-15% overhead\n' + | ||
'when destroying 10k nested scopes where each scope has a $destroy listener\n' + | ||
'Kills #1, #123\n' + | ||
'BREAKING AMEND: some breaking change\n', | ||
options, | ||
regex | ||
); | ||
expect(msg.notes[0]).to.eql({ | ||
title: 'BREAKING AMEND', | ||
text: 'some breaking change' | ||
}); | ||
expect(msg.references).to.eql([{ | ||
action: 'Kills', | ||
issue: '1', | ||
raw: '#1', | ||
repository: null | ||
}, { | ||
action: 'Kills', | ||
issue: '123', | ||
raw: ', #123', | ||
repository: null | ||
}]); | ||
expect(msg.footer).to.equal('Kills #1, #123\nBREAKING AMEND: some breaking change'); | ||
}); | ||
it('shoudl parse properly if important notes comes with more than one paragraphs after references', function() { | ||
var msg = parser( | ||
'9b1aff905b638aa274a5fc8f88662df446d374bd\n' + | ||
'feat(scope): broadcast $destroy event on scope destruction\n' + | ||
'perf testing shows that in chrome this change adds 5-15% overhead\n' + | ||
'when destroying 10k nested scopes where each scope has a $destroy listener\n' + | ||
'Kills #1, #123\n' + | ||
'BREAKING AMEND: some breaking change\nsome other breaking change', | ||
options, | ||
regex | ||
); | ||
expect(msg.notes[0]).to.eql({ | ||
title: 'BREAKING AMEND', | ||
text: 'some breaking change\nsome other breaking change' | ||
}); | ||
expect(msg.references).to.eql([{ | ||
action: 'Kills', | ||
issue: '1', | ||
raw: '#1', | ||
repository: null | ||
}, { | ||
action: 'Kills', | ||
issue: '123', | ||
raw: ', #123', | ||
repository: null | ||
}]); | ||
expect(msg.footer).to.equal('Kills #1, #123\nBREAKING AMEND: some breaking change\nsome other breaking change'); | ||
}); | ||
it('shoudl parse properly if important notes comes after references with something after references', function() { | ||
var msg = parser( | ||
'9b1aff905b638aa274a5fc8f88662df446d374bd\n' + | ||
'feat(scope): broadcast $destroy event on scope destruction\n' + | ||
'perf testing shows that in chrome this change adds 5-15% overhead\n' + | ||
'when destroying 10k nested scopes where each scope has a $destroy listener\n' + | ||
'Kills #1, #123\n' + | ||
'other\n' + | ||
'BREAKING AMEND: some breaking change\n', | ||
options, | ||
regex | ||
); | ||
expect(msg.notes[0]).to.eql({ | ||
title: 'BREAKING AMEND', | ||
text: 'some breaking change' | ||
}); | ||
expect(msg.references).to.eql([{ | ||
action: 'Kills', | ||
issue: '1', | ||
raw: '#1', | ||
repository: null | ||
}, { | ||
action: 'Kills', | ||
issue: '123', | ||
raw: ', #123', | ||
repository: null | ||
}]); | ||
expect(msg.footer).to.equal('Kills #1, #123\nother\nBREAKING AMEND: some breaking change'); | ||
}); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
51536
1118
23