diff --git a/README.md b/README.md index 488d60e..ce5681c 100644 --- a/README.md +++ b/README.md @@ -225,7 +225,7 @@ You will enter an interactive shell. To show your parsed output enter "return" t > fix(title): a title is fixed -{"type":"fix","scope":"title","subject":"a title is fixed","header":"fix(title): a title is fixed\n","body":null,"footer":null,"notes":[],"references":[],"revert":null} +{"type":"fix","scope":"title","subject":"a title is fixed","header":"fix(title): a title is fixed","body":null,"footer":null,"notes":[],"references":[],"revert":null} ``` You can also use cli to parse messages from files. @@ -255,7 +255,7 @@ An array of json will be printed to stdout. ```sh [ -{"type":"feat","scope":"ngMessages","subject":"provide support for dynamic message resolution","header":"feat(ngMessages): provide support for dynamic message resolution\n","body":"Prior to this fix it was impossible to apply a binding to a the ngMessage directive to represent the name of the error.\n","footer":"BREAKING CHANGE: The `ngMessagesInclude` attribute is now its own directive and that must be placed as a **child** element within the element with the ngMessages directive.\nCloses #10036\nCloses #9338\n","notes":[{"title":"BREAKING CHANGE","text":"The `ngMessagesInclude` attribute is now its own directive and that must be placed as a **child** element within the element with the ngMessages directive.\n"}],"references":[{"action":"Closes","owner":null,"repository":null,"issue":"10036","raw":"#10036"},{"action":"Closes","owner":null,"repository":null,"issue":"9338","raw":"#9338"}],"revert":null} +{"type":"feat","scope":"ngMessages","subject":"provide support for dynamic message resolution","header":"feat(ngMessages): provide support for dynamic message resolution","body":"Prior to this fix it was impossible to apply a binding to a the ngMessage directive to represent the name of the error.","footer":"BREAKING CHANGE: The `ngMessagesInclude` attribute is now its own directive and that must be placed as a **child** element within the element with the ngMessages directive.\nCloses #10036\nCloses #9338","notes":[{"title":"BREAKING CHANGE","text":"The `ngMessagesInclude` attribute is now its own directive and that must be placed as a **child** element within the element with the ngMessages directive."}],"references":[{"action":"Closes","owner":null,"repository":null,"issue":"10036","raw":"#10036"},{"action":"Closes","owner":null,"repository":null,"issue":"9338","raw":"#9338"}],"revert":null} ] ``` @@ -281,9 +281,9 @@ $ conventional-commits-parser log2.txt '===' ```sh [ -{"type":"docs","scope":"ngMessageExp","subject":"split ngMessage docs up to show its alias more clearly","header":"docs(ngMessageExp): split ngMessage docs up to show its alias more clearly\n","body":null,"footer":null,"notes":[],"references":[],"revert":null} +{"type":"docs","scope":"ngMessageExp","subject":"split ngMessage docs up to show its alias more clearly","header":"docs(ngMessageExp): split ngMessage docs up to show its alias more clearly","body":null,"footer":null,"notes":[],"references":[],"revert":null} , -{"type":"fix","scope":"$animate","subject":"applyStyles from options on leave","header":"fix($animate): applyStyles from options on leave\n","body":null,"footer":"Closes #10068\n","notes":[],"references":[{"action":"Closes","owner":null,"repository":null,"issue":"10068","raw":"#10068"}],"revert":null} +{"type":"fix","scope":"$animate","subject":"applyStyles from options on leave","header":"fix($animate): applyStyles from options on leave","body":null,"footer":"Closes #10068","notes":[],"references":[{"action":"Closes","owner":null,"repository":null,"issue":"10068","raw":"#10068"}],"revert":null} ] ``` diff --git a/lib/parser.js b/lib/parser.js index a53a519..e4842a6 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -1,6 +1,16 @@ 'use strict'; var _ = require('lodash'); +function append(src, line) { + if (src) { + src += '\n' + line; + } else { + src = line; + } + + return src; +} + function parser(raw, options, regex) { if (!raw || !raw.trim()) { throw new TypeError('Expected a raw commit'); @@ -99,11 +109,7 @@ function parser(raw, options, regex) { } if (currentProcessedField) { - if (otherFields[currentProcessedField]) { - otherFields[currentProcessedField] += line + '\n'; - } else { - otherFields[currentProcessedField] = line + '\n'; - } + otherFields[currentProcessedField] = append(otherFields[currentProcessedField], line); return; } @@ -116,15 +122,13 @@ function parser(raw, options, regex) { if (notesMatch) { continueNote = true; isBody = false; - footer += line + '\n'; + footer = append(footer, line); var note = { title: notesMatch[1], text: notesMatch[2] }; - if (note.text.trim()) { - note.text += '\n'; - } + notes.push(note); return; @@ -164,32 +168,30 @@ function parser(raw, options, regex) { } if (referenceMatched) { - footer += line + '\n'; + footer = append(footer, line); return; } // this is the continued important note if (continueNote) { - notes[notes.length - 1].text += line + '\n'; - footer += line + '\n'; + notes[notes.length - 1].text = append(notes[notes.length - 1].text, line); + footer = append(footer, line); return; } // this is the body if (isBody) { - body += line + '\n'; + body = append(body, line); } // this is the continued footer else { - footer += line + '\n'; + footer = append(footer, line); } }); - body = body; - footer = footer; if (!body) { body = null; } @@ -211,7 +213,7 @@ function parser(raw, options, regex) { } var msg = _.merge(headerParts, { - header: header + '\n', + header: header, body: body, footer: footer, notes: notes, diff --git a/test/cli.spec.js b/test/cli.spec.js index 24764f6..b3d0ad8 100644 --- a/test/cli.spec.js +++ b/test/cli.spec.js @@ -81,7 +81,7 @@ describe('cli', function() { .pipe(concat(function(chunk) { expect(chunk.toString()).to.include('"scope":"category","type":"fix:subcategory","subject":"My subject"'); expect(chunk.toString()).to.include('"references":[{"action":"Close","owner":null,"repository":null,"issue":"10036","raw":"#10036"},{"action":"fix","owner":null,"repository":null,"issue":"9338","raw":"#9338"}]'); - expect(chunk.toString()).to.include('"notes":[{"title":"BREAKING NEWS","text":"A lot of changes!\\n"}]'); + expect(chunk.toString()).to.include('"notes":[{"title":"BREAKING NEWS","text":"A lot of changes!"}]'); done(); })); diff --git a/test/index.spec.js b/test/index.spec.js index 6f81575..a94f4ad 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -42,16 +42,16 @@ describe('conventionalCommitsParser', function() { .pipe(conventionalCommitsParser()) .pipe(through.obj(function(chunk, enc, cb) { if (i === 0) { - expect(chunk.header).to.equal('feat(ng-list): Allow custom separator\n'); + expect(chunk.header).to.equal('feat(ng-list): Allow custom separator'); } else if (i === 1) { expect(chunk.notes).to.eql([{ title: 'BREAKING CHANGE', - text: 'some breaking change\n' + text: 'some breaking change' }]); } else if (i === 2) { - expect(chunk.header).to.equal('fix(zzz): Very cool commit\n'); + expect(chunk.header).to.equal('fix(zzz): Very cool commit'); } else if (i === 3) { - expect(chunk.header).to.equal('chore(scope with spaces): some chore\n'); + expect(chunk.header).to.equal('chore(scope with spaces): some chore'); } else if (i === 4) { expect(chunk.revert).to.eql({ header: 'throw an error if a callback is passed to animate methods', @@ -182,7 +182,7 @@ describe('conventionalCommitsParser', function() { expect(chunk.subject).to.equal('Another custom separator'); expect(chunk.notes[0]).to.eql({ title: 'BREAKING CHANGES', - text: 'some breaking changes\n' + text: 'some breaking changes' }); } @@ -240,11 +240,11 @@ describe('conventionalCommitsParser', function() { expect(chunk.subject).to.equal('fix'); expect(chunk.notes[0]).to.eql({ title: 'BREAKING CHANGES', - text: 'some breaking changes\n' + text: 'some breaking changes' }); } else if (i === 2) { - expect(chunk.header).to.equal('blabla\n'); - expect(chunk.hash).to.equal('9b1aff905b638aa274a5fc8f88662df446d374bd\n'); + expect(chunk.header).to.equal('blabla'); + expect(chunk.hash).to.equal('9b1aff905b638aa274a5fc8f88662df446d374bd'); } else if (i === 3) { expect(chunk.revert.header).to.equal('throw an error if a callback is passed to animate methods'); } @@ -265,7 +265,7 @@ describe('sync', function() { 'Closes #123\nCloses #25\nFixes #33\n'; var result = conventionalCommitsParser.sync(commit); - expect(result.header).to.equal('feat(ng-list): Allow custom separator\n'); - expect(result.footer).to.equal('Closes #123\nCloses #25\nFixes #33\n'); + expect(result.header).to.equal('feat(ng-list): Allow custom separator'); + expect(result.footer).to.equal('Closes #123\nCloses #25\nFixes #33'); }); }); diff --git a/test/parser.spec.js b/test/parser.spec.js index 92b31c3..790312a 100644 --- a/test/parser.spec.js +++ b/test/parser.spec.js @@ -115,7 +115,7 @@ describe('parser', function() { }); it('should parse header', function() { - expect(msg.header).to.equal('feat(scope): broadcast $destroy event on scope destruction\n'); + expect(msg.header).to.equal('feat(scope): broadcast $destroy event on scope destruction'); }); it('should understand header parts', function() { @@ -182,7 +182,7 @@ describe('parser', function() { it('should parse body', function() { expect(msg.body).to.equal( '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'); + 'when destroying 10k nested scopes where each scope has a $destroy listener'); }); it('should be null if not found', function() { @@ -201,7 +201,7 @@ describe('parser', function() { 'Kills #1, #123\n' + 'killed #25\n' + 'handle #33, Closes #100, Handled #3 kills repo#77\n' + - 'kills stevemao/conventional-commits-parser#1\n' + 'kills stevemao/conventional-commits-parser#1' ); }); @@ -212,14 +212,14 @@ describe('parser', function() { it('should parse important notes', function() { expect(msg.notes[0]).to.eql({ title: 'BREAKING AMEND', - text: 'some breaking change\n' + text: 'some breaking change' }); }); it('should parse important notes with more than one paragraphs', function() { expect(longNoteMsg.notes[0]).to.eql({ title: 'BREAKING AMEND', - text: 'some breaking change\nsome other breaking change\n' + text: 'some breaking change\nsome other breaking change' }); }); @@ -293,7 +293,7 @@ describe('parser', function() { regex ); - expect(msg.footer).to.equal('Kills #1, #123\nwhat\nkilled #25\nhandle #33, Closes #100, Handled #3\nother\n'); + expect(msg.footer).to.equal('Kills #1, #123\nwhat\nkilled #25\nhandle #33, Closes #100, Handled #3\nother'); }); it('should parse properly if important notes comes after references', function() { @@ -308,7 +308,7 @@ describe('parser', function() { ); expect(msg.notes[0]).to.eql({ title: 'BREAKING AMEND', - text: 'some breaking change\n' + text: 'some breaking change' }); expect(msg.references).to.eql([{ action: 'Kills', @@ -323,7 +323,7 @@ describe('parser', function() { issue: '123', raw: ', #123' }]); - expect(msg.footer).to.equal('Kills #1, #123\nBREAKING AMEND: some breaking change\n'); + 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() { @@ -338,7 +338,7 @@ describe('parser', function() { ); expect(msg.notes[0]).to.eql({ title: 'BREAKING AMEND', - text: 'some breaking change\nsome other breaking change\n' + text: 'some breaking change\nsome other breaking change' }); expect(msg.references).to.eql([{ action: 'Kills', @@ -353,7 +353,7 @@ describe('parser', function() { issue: '123', raw: ', #123' }]); - expect(msg.footer).to.equal('Kills #1, #123\nBREAKING AMEND: some breaking change\nsome other breaking change\n'); + 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() { @@ -369,7 +369,7 @@ describe('parser', function() { ); expect(msg.notes[0]).to.eql({ title: 'BREAKING AMEND', - text: 'some breaking change\n' + text: 'some breaking change' }); expect(msg.references).to.eql([{ action: 'Kills', @@ -384,7 +384,7 @@ describe('parser', function() { issue: '123', raw: ', #123' }]); - expect(msg.footer).to.equal('Kills #1, #123\nother\nBREAKING AMEND: some breaking change\n'); + expect(msg.footer).to.equal('Kills #1, #123\nother\nBREAKING AMEND: some breaking change'); }); }); @@ -410,7 +410,7 @@ describe('parser', function() { regex ); - expect(msg.hash).to.equal('9b1aff905b638aa274a5fc8f88662df446d374bd\n'); + expect(msg.hash).to.equal('9b1aff905b638aa274a5fc8f88662df446d374bd'); }); it('should parse sideNotes', function() { @@ -438,7 +438,7 @@ describe('parser', function() { expect(msg.sideNotes).to.equal('It should warn the correct unfound file names.\n' + 'Also it should continue if one file cannot be found.\n' + - 'Tests are added for these\n'); + 'Tests are added for these'); }); it('should parse committer name and email', function() { @@ -464,8 +464,8 @@ describe('parser', function() { regex ); - expect(msg.committerName).to.equal('Steve Mao\n'); - expect(msg[' committerEmail']).to.equal('test@github.com\n'); + expect(msg.committerName).to.equal('Steve Mao'); + expect(msg[' committerEmail']).to.equal('test@github.com'); }); });