conventional-changelog 0.0.7 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,17 +5,23 @@ conventional-changelog
5
5
  $ npm install conventional-changelog
6
6
  ```
7
7
 
8
- Generate a changelog from git metadata, using [these commit conventions](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/).
8
+ Generate a changelog from git metadata, using the AngularJS commit conventions.
9
9
 
10
- View [CONVENTIONS.md](https://github.com/ajoslin/conventional-changelog/blob/master/CONVENTIONS.md) for a synposis of the conventions with commit examples.
10
+ - [Synopsis of Conventions in CONVENTIONS.md](https://github.com/ajoslin/conventional-changelog/blob/master/CONVENTIONS.md)
11
+ - [Full Convention Spec on Google Docs](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/)
11
12
 
12
- Adapted from code originally written by @vojtajina, from grunt-conventional-changelog.
13
+ Adapted from code originally written by @vojtajina and @btford in [grunt-conventional-changelog](https://github.com/btford/grunt-conventional-changelog).
13
14
 
14
15
  ## Example output
16
+
15
17
  - https://github.com/ajoslin/conventional-changelog/blob/master/CHANGELOG.md
16
18
  - https://github.com/karma-runner/karma/blob/master/CHANGELOG.md
17
19
 
18
- Recommended usage: use in your workflow with [https://github.com/btford/grunt-conventional-changelog](grunt-conventional-changelog).
20
+ ## Roadmap
21
+
22
+ - Make it return a stream
23
+ - Add a proper command line interface
24
+ - Add configurable subjects & sections
19
25
 
20
26
  ## Documentation
21
27
 
@@ -38,25 +44,34 @@ By default, calls the callback with a string containing a changelog from the pre
38
44
 
39
45
  `options` is the first parameter, an object. The following fields are available:
40
46
 
47
+ ##### The Most Important Options
48
+
41
49
  * `version` `{string}` - The version to be written to the changelog. For example, `{version: require('./package.json').version}`
42
50
 
43
- * `codename` `{string}` - The codename to display after the version in the changelog. For example, it will show '## 1.0.0 "Super Version"' if codename 'Super Version' is given. By default, it's blank.
51
+ * `subtitle` `{string}` - A string to display after the version title in the changelog. For example, it will show '## 1.0.0 "Super Version"' if codename '"Super Version"' is given. By default, it's blank.
44
52
 
45
53
  * `repository` `{string}` - If this is provided, allows issues and commit hashes to be linked to the actual commit. Usually used with github repositories. For example, `{repository: 'http://github.com/joyent/node'}`
46
54
 
47
- * `commitLink` `{function(commitHash)}` - If repository is provided, this function will be used to link to commits. By default, returns a github commit link based on options.repository: `opts.repository + '/commit/' + hash`
48
-
49
- * `issueLink` `{function(issueId)}` - If repository is provided, this function will be used to link to issues. By default, returns a github issue link based on options.repository: `opts.repository + '/issues/' + id`
50
-
51
55
  * `from` `{string}` - Which commit the changelog should start at. By default, uses previous tag, or if no previous tag the first commit.
52
56
 
53
57
  * `to` `{string}` - Which commit the changelog should end at. By default, uses HEAD.
54
58
 
55
- * `file` `{string}` - Which file to read the current changelog from and prepend the new changelog's contents to. By default, uses `'CHANGELOG.md'`.
59
+ * `file` `{string}` - Which file to read the current changelog from and prepend the new changelog's contents to. By default, uses `'CHANGELOG.md'`
60
+
61
+ ##### The "I really want to get crazy" Options
62
+
63
+ * `versionText` `{function(version, subtitle)}` - What to use for the title of a major version in the changelog. Defaults to `'## ' + version + ' ' + subtitle`.
64
+
65
+ * `patchVersionText` `{function(version, subtitle)}` - What to use for the title of a patch version in the changelog. Defaults to `'### ' + version + ' ' + subtitle`.
66
+
67
+ * `commitLink` `{function(commitHash)}` - If repository is provided, this function will be used to link to commits. By default, returns a github commit link based on options.repository: `opts.repository + '/commit/' + hash`
68
+
69
+ * `issueLink` `{function(issueId)}` - If repository is provided, this function will be used to link to issues. By default, returns a github issue link based on options.repository: `opts.repository + '/issues/' + id`
56
70
 
57
71
  * `log` `{function()}` - What logging function to use. For example, `{log: grunt.log.ok}`. By default, uses `console.log`.
58
72
 
59
73
  * `warn` `{function()}` - What warn function to use. For example, `{warn: grunt.log.writeln}`. By default, uses `console.warn`.
60
74
 
61
75
  ## License
76
+
62
77
  BSD
package/index.js CHANGED
@@ -11,7 +11,7 @@ function generate(options, done) {
11
11
  version: null,
12
12
  to: 'HEAD',
13
13
  file: 'CHANGELOG.md',
14
- codename: '',
14
+ subtitle: '',
15
15
  log: console.log.bind(console),
16
16
  }, options || {});
17
17
 
package/lib/git.js CHANGED
@@ -49,7 +49,7 @@ function getCommits(options, done) {
49
49
  cmd,
50
50
  options.grep,
51
51
  options.format,
52
- options.from ? options.from+'..'+options.to : ''
52
+ options.from ? '"' + options.from + '..' + options.to + '"' : ''
53
53
  );
54
54
 
55
55
  return es.child(cp.exec(cmd))
@@ -62,7 +62,7 @@ function getCommits(options, done) {
62
62
  .pipe(es.writeArray(done));
63
63
  }
64
64
 
65
- var COMMIT_PATTERN = /^(\w*)(\(([\w\$\.\-\*]*)\))?\: (.*)$/;
65
+ var COMMIT_PATTERN = /^(\w*)(\(([\w\$\.\-\* ]*)\))?\: (.*)$/;
66
66
  var MAX_SUBJECT_LENGTH = 80;
67
67
  function parseRawCommit(raw, options) {
68
68
  if (!raw) {
@@ -77,24 +77,25 @@ function parseRawCommit(raw, options) {
77
77
  msg.closes = [];
78
78
  msg.breaks = [];
79
79
 
80
- msg.subject = msg.subject.replace(/\s*(?:Closes|Fixes)\s#(\d+)/, function(_, i) {
80
+ msg.subject = msg.subject.replace(/\s*(?:Closes|Fixes|Resolves)\s#(\d+)/ig, function(_, i) {
81
81
  msg.closes.push(parseInt(i, 10));
82
82
  return '';
83
83
  });
84
84
 
85
85
  lines.forEach(function(line) {
86
- match = line.match(/(?:Closes|Fixes)\s((?:#\d+(?:\,\s)?)+)/);
86
+ match = line.match(/(?:Closes|Fixes|Resolves)\s((?:#\d+(?:\,\s)?)+)/ig);
87
87
 
88
- if (match) {
89
- match[1].replace(/[\s#]/g, '').split(',').forEach(function(i) {
90
- msg.closes.push(parseInt(i, 10));
88
+ match && match.forEach(function(m) {
89
+ m && m.split(',').forEach(function(i) {
90
+ var issue = i.match(/\d+/);
91
+ issue && msg.closes.push(parseInt(issue[0], 10));
91
92
  });
92
- }
93
+ });
93
94
  });
94
95
 
95
96
  match = raw.match(/BREAKING CHANGE:\s([\s\S]*)/);
96
97
  if (match) {
97
- msg.breaks.push(match[1]);
98
+ msg.breaks.push(match[1] + '\n');
98
99
  }
99
100
 
100
101
  msg.body = lines.join('\n');
package/lib/writer.js CHANGED
@@ -2,6 +2,8 @@ var es = require('event-stream');
2
2
  var util = require('util');
3
3
  var extend = require('lodash.assign');
4
4
 
5
+ var VERSION = '## %s%s';
6
+ var PATCH_VERSION = '### %s%s';
5
7
  var LINK_ISSUE = '[#%s](%s/issues/%s)';
6
8
  var ISSUE = '(#%s)';
7
9
  var LINK_COMMIT = '[%s](%s/commit/%s)';
@@ -12,6 +14,14 @@ module.exports = {
12
14
  Writer: Writer
13
15
  };
14
16
 
17
+ function getVersion (version, subtitle) {
18
+ subtitle = subtitle ? ' ' + subtitle : '';
19
+ return util.format(VERSION, version, subtitle);
20
+ }
21
+ function getPatchVersion (version, subtitle) {
22
+ subtitle = subtitle ? ' ' + subtitle : '';
23
+ return util.format(PATCH_VERSION, version, subtitle);
24
+ }
15
25
  function getIssueLink(repository, issue) {
16
26
  return repository ?
17
27
  util.format(LINK_ISSUE, issue, repository, issue) :
@@ -25,10 +35,6 @@ function getCommitLink(repository, hash) {
25
35
  }
26
36
 
27
37
  function writeLog(commits, options, done) {
28
- options = extend({
29
- issueLink: getIssueLink.bind(null, options.repository),
30
- commitLink: getCommitLink.bind(null, options.repository)
31
- }, options || {});
32
38
 
33
39
  var log = '';
34
40
  var stream = es.through(function(data) {
@@ -71,15 +77,29 @@ function writeLog(commits, options, done) {
71
77
  writer.end();
72
78
  }
73
79
 
74
- var PATCH_HEADER_TPL = '<a name="%s"></a>\n### %s %s (%s)\n\n';
75
- var MINOR_HEADER_TPL = '<a name="%s"></a>\n## %s %s (%s)\n\n';
80
+ var LINK_HEADER_TPL = '%s (%s)\n\n';
81
+ var PLAIN_HEADER_TPL = '<a name="%s"></a>\n%s (%s)\n\n';
76
82
  var EMPTY_COMPONENT = '$$';
77
- function Writer(stream, options) {
78
83
 
84
+ function Writer(stream, options) {
85
+ options = extend({
86
+ versionText: getVersion,
87
+ patchVersionText: getPatchVersion,
88
+ issueLink: getIssueLink.bind(null, options.repository),
89
+ commitLink: getCommitLink.bind(null, options.repository)
90
+ }, options || {});
91
+
79
92
  this.header = function(version) {
80
- var codename = options.codename ? '"' + options.codename + '"' : '';
81
- var header = version.split('.')[2] === '0' ? MINOR_HEADER_TPL : PATCH_HEADER_TPL;
82
- stream.write(util.format(header, version, version, codename, currentDate()));
93
+ var subtitle = options.subtitle || '';
94
+ var versionText = version.split('.')[2] === '0' ?
95
+ options.versionText(version, subtitle) :
96
+ options.patchVersionText(version, subtitle);
97
+
98
+ if (options.repository) {
99
+ stream.write(util.format(LINK_HEADER_TPL, versionText, currentDate()));
100
+ } else {
101
+ stream.write(util.format(PLAIN_HEADER_TPL, version, versionText, currentDate()));
102
+ }
83
103
  };
84
104
 
85
105
  this.section = function(title, section) {
@@ -122,7 +142,7 @@ function Writer(stream, options) {
122
142
  this.end = function() {
123
143
  stream.end();
124
144
  };
125
- };
145
+ }
126
146
 
127
147
  function currentDate() {
128
148
  var now = new Date();
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "conventional-changelog",
3
- "codename": "delta",
4
- "version": "0.0.7",
3
+ "codename": "reorder",
4
+ "version": "0.0.11",
5
5
  "description": "Generate a markdown changelog from git commit metadata",
6
6
  "main": "index.js",
7
7
  "scripts": {
8
- "test": "mocha test/*.js index.js lib/*.js"
8
+ "test": "mocha test/*.js index.js lib/*.js --no-colors"
9
9
  },
10
10
  "files": [
11
11
  "index.js",
@@ -28,7 +28,7 @@
28
28
  "name": "Vojta Jína"
29
29
  },
30
30
  {
31
- "name": "Andy Joslin"
31
+ "name": "Andrew Joslin"
32
32
  }
33
33
  ],
34
34
  "dependencies": {
package/test/git.spec.js CHANGED
@@ -36,46 +36,72 @@ describe('git', function() {
36
36
  'bla bla bla\n\n' +
37
37
  'BREAKING CHANGE: some breaking change\n'
38
38
  );
39
- expect(msg.breaks).to.deep.equal(['some breaking change\n']);
39
+ expect(msg.breaks).to.deep.equal(['some breaking change\n\n']);
40
40
  });
41
- it('should parse Closes in the subject (and remove it)', function() {
42
- var msg = git.parseRawCommit(
43
- '13f31602f396bc269076ab4d389cfd8ca94b20ba\n' +
44
- 'feat(xxx): Whatever Closes #24\n' +
45
- 'bla bla bla\n\n' +
46
- 'What not ?\n'
47
- );
48
- expect(msg.closes).to.deep.equal([24]);
49
- expect(msg.subject).to.equal('Whatever');
41
+ ['Closes', 'Fixes', 'Resolves'].forEach(function(closeWord) {
42
+ it('should parse ' + closeWord + ' in the subject (and remove it)', function() {
43
+ var msg = git.parseRawCommit(
44
+ '13f31602f396bc269076ab4d389cfd8ca94b20ba\n' +
45
+ 'feat(xxx): Whatever ' + closeWord + ' #24\n' +
46
+ 'bla bla bla\n\n' +
47
+ 'What not ?\n'
48
+ );
49
+ expect(msg.closes).to.deep.equal([24]);
50
+ expect(msg.subject).to.equal('Whatever');
51
+ });
52
+ it('should work with lowercase ' + closeWord + ' in the subject', function() {
53
+ var msg = git.parseRawCommit(
54
+ '13f31602f396bc269076ab4d389cfd8ca94b20ba\n' +
55
+ 'feat(xxx): Whatever ' + closeWord.toLowerCase() + ' #24\n' +
56
+ 'bla bla bla\n\n' +
57
+ 'What not ?\n'
58
+ );
59
+ expect(msg.closes).to.deep.equal([24]);
60
+ expect(msg.subject).to.equal('Whatever');
61
+ });
62
+ it('should parse multiple comma-separated issues closed with ' + closeWord + ' #1, #2', function() {
63
+ var msg = git.parseRawCommit(
64
+ '13f31602f396bc269076ab4d389cfd8ca94b20ba\n' +
65
+ 'fix(yyy): Very cool commit\n' +
66
+ 'bla bla bla\n\n' +
67
+ closeWord + ' #1, #22, #33\n' +
68
+ 'What not ?\n'
69
+ );
70
+ expect(msg.closes).to.deep.equal([1, 22, 33]);
71
+ expect(msg.subject).to.equal('Very cool commit');
72
+ });
50
73
  });
51
- it('should parse Fixes in the subject (and remove it)', function() {
74
+ it('should parse multiple period-separated issues closed with all closed words', function() {
52
75
  var msg = git.parseRawCommit(
53
76
  '13f31602f396bc269076ab4d389cfd8ca94b20ba\n' +
54
- 'feat(xxx): Whatever Fixes #25\n' +
55
- 'bla bla bla\n\n' +
77
+ 'fix(zzz): Very cool commit\n' +
78
+ 'bla bla bla\n\n' +
79
+ 'Closes #2, #3. Resolves #4. Fixes #5. Fixes #6.\n' +
56
80
  'What not ?\n'
57
81
  );
58
- expect(msg.closes).to.deep.equal([25]);
59
- expect(msg.subject).to.equal('Whatever');
82
+ expect(msg.closes).to.deep.equal([2,3,4,5,6]);
83
+ expect(msg.subject).to.equal('Very cool commit');
60
84
  });
61
- it('should parse multiple issues closed with Closes #1, #2', function() {
85
+ it('should parse a msg without scope', function() {
62
86
  var msg = git.parseRawCommit(
63
87
  '13f31602f396bc269076ab4d389cfd8ca94b20ba\n' +
64
- 'feat(xxx): Very cool commit\n' +
88
+ 'chore: some chore\n' +
65
89
  'bla bla bla\n\n' +
66
- 'Closes #1, #22, #33\n' +
67
- 'What not ?\n'
90
+ 'BREAKING CHANGE: some breaking change\n'
68
91
  );
69
- expect(msg.closes).to.deep.equal([1, 22, 33]);
92
+ expect(msg.type).to.equal('chore');
93
+ expect(msg.subject).to.equal('some chore');
70
94
  });
71
- it('should parse a msg without scope', function() {
95
+ it('should parse a scope with spaces', function() {
72
96
  var msg = git.parseRawCommit(
73
97
  '13f31602f396bc269076ab4d389cfd8ca94b20ba\n' +
74
- 'chore: some chore bullshit\n' +
75
- 'bla bla bla\n\n' +
98
+ 'chore(scope with spaces): some chore\n' +
99
+ 'bla bla bla\n\n' +
76
100
  'BREAKING CHANGE: some breaking change\n'
77
101
  );
78
102
  expect(msg.type).to.equal('chore');
103
+ expect(msg.subject).to.equal('some chore');
104
+ expect(msg.component).to.equal('scope with spaces');
79
105
  });
80
106
  });
81
107
  });
@@ -18,6 +18,8 @@ describe("Writer", function() {
18
18
  log = '';
19
19
  var stream = es.through(concat, concat.bind(null,'END'));
20
20
  return new writer.Writer(stream, {
21
+ subtitle: 'subby',
22
+ repository: 'github.com/user/repo',
21
23
  issueLink: function(id) {
22
24
  return id;
23
25
  },
@@ -31,12 +33,12 @@ describe("Writer", function() {
31
33
  it('minor version', function() {
32
34
  var writer = setup();
33
35
  writer.header('0.1.0');
34
- expect(log.indexOf('<a name="0.1.0"></a>\n## 0.1.0')).to.equal(0);
36
+ expect(log).to.contain('## 0.1.0 subby');
35
37
  });
36
38
  it('patch version', function() {
37
39
  var writer = setup();
38
- writer.header('0.0.1');
39
- expect(log.indexOf('<a name="0.0.1"></a>\n### 0.0.1')).to.equal(0);
40
+ writer.header('0.0.3');
41
+ expect(log).to.contain('### 0.0.3 subby');
40
42
  });
41
43
  });
42
44