Skip to content

Commit

Permalink
feat(preset): add jshint
Browse files Browse the repository at this point in the history
  • Loading branch information
stevemao committed Jun 30, 2015
1 parent 34b0f46 commit 384e6ce
Show file tree
Hide file tree
Showing 10 changed files with 232 additions and 6 deletions.
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -23,7 +23,7 @@ Adapted from code originally written by @vojtajina and @btford in [grunt-convent

*Note:* As 0.1.x this module is rewritten and so the API is not backward compatible. If you are still using 0.0.x please checkout the README in your downloaded package or dig through the old tags.

*Note:*: As the next release is still under development and we would like you to help test pre-release features, you can install by typing
*Note:* As the next release is still under development and we would like you to help test pre-release features, you can install by typing

```sh
$ npm install conventional-changelog@next
Expand Down Expand Up @@ -59,7 +59,7 @@ Returns a readable stream.

##### preset

Type: `string` Possible values: `'angular'`, `'jquery'`
Type: `string` Possible values: `'angular'`, `'jquery'`, `'jshint'`

A set of options of a popular project.

Expand Down
76 changes: 76 additions & 0 deletions conventions/jshint.md
@@ -0,0 +1,76 @@
Commit Message Guidelines
-------------------------

### Overview

Commit messages are written in a simple format which clearly describes the purpose of a change.

The format in general should look like this:

```
[[TYPE]] <Short description>
<Blank line>
<Body / Detailed description>
<Footer>
```

Line lengths in commit messages are not strict, but good commit messages should have headers of no
more than 60 characters, and bodies/footers wrapped at 100 columns. This renders nicely on Github's
UI.

### Header

The first line is the commit message header, which will indicate the type of change, and a general
description of the change. This should fit within 60 characters, ideally. For instance:

```
[[FIX]] Ignore "nocomma" when parsing object literals
```

The title `[[FIX]]` indicates that the change is a bugfix, while the remainder clarifies what the
change actually contains.

Several commit types are used by jshint:

1. `[[FIX]]` --- Commit fixes a bug or regression
2. `[[FEAT]]` --- Commit introduces new functionality
3. `[[DOCS]]` --- Commit modifies documentation. Docs commits should only touch comments in source code, or scripts and assets which are used to generate the documentation.
4. `[[TEST]]` --- Commit modifies tests or test infrastructure only
5. `[[CHORE]]` --- Commit affects dev-ops, CI, or package dependencies

### Body

`<Body>` is a detailed commit message explaining exactly what has changed, and a summary of the
reason why. Lines in the body should be wrapped to 100 characters for best rendering.

For a historical example, see this [example](https://github.com/jshint/jshint/commit/5751c5ed249b7a035758a3ae876cfa1a360fd144)

### Footer

`<Footer>` contains a description of any breaking changes, no matter how subtle, as well as a list
of issues affected or fixed by this commit. Lines in the footer should be wrapped to 100 characters
for best rendering.

For instance:

```
[[FEAT]] Enable `norecurs` option by default
Commit 124124a7f introduced an option which forbids recursion. We liked it so much, we've enabled
it by default.
BREAKING CHANGE:
This change will break the CI builds of many applications and frameworks.
In order to work around this issue, you will need to re-engineer your applications and frameworks
to avoid making recursive calls. Use Arrays as stacks rather than relying on the VM call stack.
Fixes #1000009
Closes #888888
Closes #77777
```

Based on https://github.com/jshint/jshint/blob/master/CONTRIBUTING.md#commit-message-guidelines
2 changes: 0 additions & 2 deletions presets/angular.js
Expand Up @@ -50,8 +50,6 @@ function presetOpts(cb) {
return;
}

regex.lastIndex = 0;

if (typeof commit.hash === 'string') {
commit.hash = commit.hash.substring(0, 7);
}
Expand Down
2 changes: 0 additions & 2 deletions presets/jquery.js
Expand Up @@ -43,8 +43,6 @@ function presetOpts(cb) {
commit.component = commit.component.substring(0, 72);
componentLength = commit.component.length;

regex.lastIndex = 0;

if (typeof commit.hash === 'string') {
commit.hash = commit.hash.substring(0, 7);
}
Expand Down
81 changes: 81 additions & 0 deletions presets/jshint.js
@@ -0,0 +1,81 @@
'use strict';
var dateFormat = require('dateformat');
var Q = require('q');
var readFile = Q.denodeify(require('fs').readFile);
var resolve = require('path').resolve;
var semver = require('semver');
var through = require('through2');

var regex = /tag:\s*[v=]?(.+?)[,\)]/gi;

function presetOpts(cb) {
var parserOpts = {
headerPattern: /^\[\[(.*)]] (.*)$/,
headerCorrespondence: [
'type',
'shortDesc'
]
};

var transform = through.obj(function(chunk, enc, cb) {
if (typeof chunk.gitTags === 'string') {
var match = regex.exec(chunk.gitTags);
if (match) {
chunk.version = match[1];
}
}

if (chunk.committerDate) {
chunk.committerDate = dateFormat(chunk.committerDate, 'yyyy-mm-dd', true);
}

cb(null, chunk);
});

var writerOpts = {
transform: function(commit) {
if (commit.type === 'FEAT') {
commit.type = 'Features';
} else if (commit.type === 'FIX') {
commit.type = 'Bug Fixes';
} else {
return;
}

if (!commit.type || typeof commit.type !== 'string') {
return;
}

if (typeof commit.hash === 'string') {
commit.hash = commit.hash.substring(0, 7);
}

return commit;
},
groupBy: 'type',
commitGroupsSort: 'title',
commitsSort: ['type', 'shortDesc'],
generateOn: function(commit) {
return semver.valid(commit.version);
}
};

Q.all([
readFile(resolve(__dirname, '../templates/jshint/template.hbs'), 'utf-8'),
readFile(resolve(__dirname, '../templates/jshint/header.hbs'), 'utf-8'),
readFile(resolve(__dirname, '../templates/jshint/commit.hbs'), 'utf-8')
])
.spread(function(template, header, commit) {
writerOpts.mainTemplate = template;
writerOpts.headerPartial = header;
writerOpts.commitPartial = commit;

cb(null, {
parserOpts: parserOpts,
transform: transform,
writerOpts: writerOpts
});
});
}

module.exports = presetOpts;
5 changes: 5 additions & 0 deletions templates/jshint/commit.hbs
@@ -0,0 +1,5 @@
* {{#if shortDesc}}{{shortDesc}}{{else}}{{header}}{{/if}}

{{~!-- commit hash --}} {{#if @root.linkReferences}}([{{hash}}]({{@root.host}}/{{@root.repository}}/{{@root.commit}}/{{hash}})){{else}}{{hash~}}{{/if}}

{{~!-- commit references --}}{{#if references}}, closes{{~#each references}} {{#if @root.linkReferences}}[{{this.repository}}#{{this.issue}}]({{@root.host}}/{{#if this.repository}}{{this.repository}}{{else}}{{@root.repository}}{{/if}}/{{@root.issue}}/{{this.issue}}){{else}}{{this.repository}}#{{this.issue}}{{/if}}{{/each}}{{/if}}
2 changes: 2 additions & 0 deletions templates/jshint/header.hbs
@@ -0,0 +1,2 @@
<a name="{{version}}"></a>
{{#if isPatch}}##{{else}}#{{/if}} {{version}}{{#if title}} "{{title}}"{{/if}}{{#if date}} ({{date}}){{/if}}
15 changes: 15 additions & 0 deletions templates/jshint/template.hbs
@@ -0,0 +1,15 @@
{{> header}}

{{#each commitGroups}}

{{#if title}}
### {{title}}

{{/if}}
{{#each commits}}
{{> commit root=@root}}
{{/each}}
{{/each}}



50 changes: 50 additions & 0 deletions test/jshint.js
@@ -0,0 +1,50 @@
'use strict';
var conventionalChangelog = require('../');
var expect = require('chai').expect;
var shell = require('shelljs');
var through = require('through2');
var writeFileSync = require('fs').writeFileSync;

describe('presets', function() {
describe('jshint', function() {
before(function() {
shell.cd('jshint');
shell.exec('git init');
writeFileSync('test1', '');
shell.exec('git add --all && git commit -m"[[Chore]] Move scope-manager to external file"');
writeFileSync('test2', '');
shell.exec('git add --all && git commit -m"[[Test]] Add test for gh-985. Fixes #985"');
writeFileSync('test3', '');
shell.exec('git add --all && git commit -m"[[FIX]] catch params are scoped to the catch only"');
writeFileSync('test4', '');
shell.exec('git add --all && git commit -m"[[FEAT]] Option to assume strict mode"');
writeFileSync('test5', '');
shell.exec('git add --all && git commit -m"Bad commit"');
});

after(function() {
shell.cd('../');
});

it('should work if there is no semver tag', function(done) {
conventionalChangelog({
preset: 'jshint'
})
.pipe(through(function(chunk) {
chunk = chunk.toString();

expect(chunk).to.include('catch params are scoped to the catch only');
expect(chunk).to.include('### Bug Fixes');
expect(chunk).to.include('Option to assume strict mode');
expect(chunk).to.include('### Features');

expect(chunk).to.not.include('Chore');
expect(chunk).to.not.include('Move scope-manager to external file');
expect(chunk).to.not.include('Add test for gh-985.');
expect(chunk).to.not.include('Bad');

done();
}));
});
});
});
1 change: 1 addition & 0 deletions test/prepare.js
Expand Up @@ -8,4 +8,5 @@ shell.cd('tmp');
shell.mkdir('test');
shell.mkdir('angular');
shell.mkdir('jquery');
shell.mkdir('jshint');
shell.mkdir('cli');

0 comments on commit 384e6ce

Please sign in to comment.