Comparing version 0.1.8 to 0.2.0
@@ -7,4 +7,9 @@ 'use strict'; | ||
grunt.initConfig({ | ||
nodeunit: { | ||
files: ['test/**/*_test.js'] | ||
mochaTest: { | ||
test: { | ||
options: { | ||
reporter: 'spec' | ||
}, | ||
src: ['test/**/*.js'] | ||
} | ||
}, | ||
@@ -20,5 +25,2 @@ jshint: { | ||
src: ['lib/**/*.js'] | ||
}, | ||
test: { | ||
src: ['test/**/*.js'] | ||
} | ||
@@ -33,7 +35,7 @@ }, | ||
files: '<%= jshint.lib.src %>', | ||
tasks: ['jshint:lib', 'nodeunit'] | ||
tasks: ['jshint:lib', 'mochaTest'] | ||
}, | ||
test: { | ||
files: '<%= jshint.test.src %>', | ||
tasks: ['jshint:test', 'nodeunit'] | ||
tasks: ['jshint:test', 'mochaTest'] | ||
} | ||
@@ -45,3 +47,3 @@ } | ||
grunt.loadTasks('./tasks'); | ||
grunt.loadNpmTasks('grunt-contrib-nodeunit'); | ||
grunt.loadNpmTasks('grunt-mocha-test'); | ||
grunt.loadNpmTasks('grunt-contrib-jshint'); | ||
@@ -51,6 +53,6 @@ grunt.loadNpmTasks('grunt-contrib-watch'); | ||
// Default task. | ||
grunt.registerTask('default', ['jshint', 'nodeunit']); | ||
grunt.registerTask('default', ['jshint', 'mochaTest']); | ||
// Default task. | ||
grunt.registerTask('test', ['jshint', 'nodeunit']); | ||
grunt.registerTask('test', ['jshint', 'mochaTest']); | ||
}; |
166
lib/chg.js
@@ -16,3 +16,2 @@ /* | ||
var moment = require('moment'); | ||
var semver = require('semver'); | ||
@@ -26,3 +25,3 @@ var changeLogFile = 'CHANGELOG.md'; | ||
function defCallback(){} | ||
function noopCallback(){} | ||
@@ -36,8 +35,23 @@ function getChangeLog(){ | ||
/** | ||
* Callbacks are standard "node style" | ||
* @callback chgCallback | ||
* @param {object} Error | ||
* @param {string} responseMessage | ||
*/ | ||
/** | ||
* Creates CHANGELOG.md if it does not exist. | ||
* @param {object} options | ||
* @param {chgCallback} callback - successfull returns the new changelog file. | ||
* @returns {string} changelog filename | ||
*/ | ||
chg.init = function(options, callback){ | ||
options = options || {}; | ||
callback = callback || defCallback; | ||
callback = callback || noopCallback; | ||
if (fs.existsSync(changeLogFile)){ | ||
return callback(changeLogFile + ' already exists'); | ||
var err = new Error(changeLogFile + ' already exists'); | ||
callback(err); | ||
return err; | ||
} | ||
@@ -50,17 +64,38 @@ | ||
callback(null, changeLogFile+' created'); | ||
callback(null, changeLogFile); | ||
return changeLogFile; | ||
}; | ||
/** | ||
* Deletes CHANGELOG.md | ||
* @param {object} options | ||
* @param {chgCallback} callback - success returns the deleted changelog file | ||
* @returns {string} changelog filename | ||
*/ | ||
chg.delete = function(options, callback){ | ||
options = options || {}; | ||
callback = callback || defCallback; | ||
callback = callback || noopCallback; | ||
if (fs.existsSync(changeLogFile)){ | ||
shell.rm(changeLogFile); | ||
callback(null, changeLogFile+' deleted'); | ||
} else { | ||
callback(changeLogFile+' does not exist'); | ||
if (!fs.existsSync(changeLogFile)) { | ||
var err = new Error(changeLogFile+' does not exist'); | ||
callback(err); | ||
return err; | ||
} | ||
shell.rm(changeLogFile); | ||
callback(null, changeLogFile); | ||
return changeLogFile; | ||
}; | ||
/** | ||
* Add a new line to CHANGELOG.md | ||
* @param {string} line - the new line to be added | ||
* @param {object} options | ||
* @param {chgCallback} callback - success returns the newly added line | ||
* @returns {string} the new line added | ||
*/ | ||
chg.add = function(line, options, callback){ | ||
@@ -70,8 +105,10 @@ var contents, sections, top; | ||
options = options || {}; | ||
callback = callback || defCallback; | ||
callback = callback || noopCallback; | ||
// get existing contents | ||
contents = getChangeLog(); | ||
if (!contents) { | ||
return callback(ERR_NO_CHANGELOG); | ||
if (!contents) { | ||
var err = new Error(ERR_NO_CHANGELOG); | ||
callback(err); | ||
return err; | ||
} | ||
@@ -91,9 +128,24 @@ | ||
callback(null, 'Change added'); | ||
callback(null, line); | ||
return line; | ||
}; | ||
/** | ||
* Creates a new release by bumping the version, moving everything in the unreleased head to a new section headed by the new version (and creating a new, empty head) | ||
* @param {string} version - the new release (this will be the title for the changelog) | ||
* @param {object} options | ||
* @param {string} options.date - date of the new release (defaults to the current date) | ||
* @param {string} options.version - release type to create (if version param is null) | ||
* @param {chgCallback} callback - success returns an object containing the new changes | ||
* @returns {object} changeData | ||
* @returns {object} changeData.title - new title to be created | ||
* @returns {object} changeData.changes - list of changes added under the new title | ||
* @returns {object} changeData.changelog - entire changelog contents | ||
*/ | ||
chg.release = function(version, options, callback){ | ||
var date, contents, changes, title, pkgVersion; | ||
var date, contents, changes, title, err; | ||
callback = callback || defCallback; | ||
callback = callback || noopCallback; | ||
options = options || {}; | ||
@@ -103,20 +155,14 @@ date = options.date || moment().format('YYYY-MM-DD'); | ||
if (!version) { | ||
return callback('Version required'); | ||
if (!version) { | ||
err = new Error('Version required'); | ||
callback(err); | ||
return err; | ||
} | ||
// allow incrementing version for a release type | ||
if (['major','minor','patch'].indexOf(version) !== -1) { | ||
if (fs.existsSync('./package.json')) { | ||
pkgVersion = require(process.cwd()+'/package.json').version; | ||
version = semver.inc(pkgVersion, version); | ||
} else { | ||
callback('No package.json was found'); | ||
} | ||
} | ||
// get existing contents | ||
contents = getChangeLog(); | ||
if (!contents) { | ||
return callback(ERR_NO_CHANGELOG); | ||
if (!contents) { | ||
err = new Error(ERR_NO_CHANGELOG); | ||
callback(err); | ||
return err; | ||
} | ||
@@ -138,3 +184,57 @@ | ||
callback(null, 'Changelog updated with new release'); | ||
}; | ||
var changeData = { title: title, changes: changes, changelog: contents }; | ||
callback(null, changeData); | ||
return changeData; | ||
}; | ||
/** | ||
* Finds a section by title in the changelog, and if it exists, returns the information. If no title is found, an empty object is returned. | ||
* @param {string} title - the title of the desired section | ||
* @param {object} options | ||
* @param {chgCallback} callback - success returns an object containing the requested section | ||
* @returns {object} section | ||
* @returns {string} section.title - title of the section found | ||
* @returns {array} section.changes - changes in the section | ||
* @returns {string} section.changesRaw - raw text of the changes in the section | ||
*/ | ||
chg.find = function(title, options, callback) { | ||
options = options || {}; | ||
callback = callback || noopCallback; | ||
var err; | ||
if (!title) { | ||
err = new Error('Title required'); | ||
callback(err); | ||
return err; | ||
} | ||
var contents = getChangeLog(); | ||
if (!contents) { | ||
err = new Error(ERR_NO_CHANGELOG); | ||
callback(err); | ||
return err; | ||
} | ||
// Get everything from the title to the first empty line | ||
var regex = new RegExp('(## '+ title +'.*)\n((.+\n)+)'); | ||
var result = regex.exec(contents); | ||
if (!result) { | ||
callback(null, {}); | ||
return {}; | ||
} | ||
// Turn the changes into an array before handing them back to the callback | ||
var changeArray = result[2].split('\n'); | ||
var resObj = { | ||
title: result[1], | ||
changesRaw: result[2], | ||
changes: changeArray | ||
}; | ||
callback(null, resObj); | ||
return resObj; | ||
}; |
@@ -49,2 +49,16 @@ /* | ||
commands.find = function(version, options, callback){ | ||
options = options || {}; | ||
if (version) { | ||
return chg.find(version, options, callback); | ||
} | ||
textPrompt('What release version number are you looking for?', options, function(err, text){ | ||
if (err) { return callback(err); } | ||
chg.find(text, options, callback); | ||
}); | ||
}; | ||
commands.delete = function(options, callback){ | ||
@@ -76,7 +90,7 @@ prompt.start(); | ||
prompt.get(options, function (err, result) { | ||
if (err) { | ||
return callback(err); | ||
if (err) { | ||
return callback(err); | ||
} | ||
callback(null, result.text); | ||
}); | ||
} | ||
} |
{ | ||
"name": "chg", | ||
"version": "0.1.8", | ||
"main": "lib/changelog.js", | ||
"version": "0.2.0", | ||
"main": "lib/chg.js", | ||
"description": "simple changelog/release history manager", | ||
@@ -34,7 +34,10 @@ "homepage": "https://github.com/heff/chg", | ||
"devDependencies": { | ||
"chai": "^1.10.0", | ||
"grunt": "~0.4.0", | ||
"grunt-cli": "~0.1.0", | ||
"grunt": "~0.4.0", | ||
"grunt-contrib-jshint": "~0.6.0", | ||
"grunt-contrib-nodeunit": "~0.2.0", | ||
"grunt-contrib-watch": "~0.5.0" | ||
"grunt-contrib-watch": "~0.5.0", | ||
"grunt-mocha-test": "^0.12.7", | ||
"mocha": "^2.1.0" | ||
}, | ||
@@ -41,0 +44,0 @@ "dependencies": { |
@@ -90,2 +90,9 @@ # chg [![Build Status](https://secure.travis-ci.org/heff/chg.png?branch=master)](http://travis-ci.org/heff/chg) | ||
chg.release('0.0.1', {}, callback); | ||
// each command can take a callback, but each also returns synchronously | ||
var changeData = chg.release('3.0.0', {}); | ||
// changeData = { title: '0.0.1', changes: '* Removed crusty semantic html, javascript app ftw', changeLog: '/* entire changelog */' } | ||
chg.find('1.1.1'); | ||
// => { title: '## 1.1.1 (2002-08-16)', changes: ['* Added a dot.gif to 3,000 table cells to fix layout issues'], changesRaw: '* Added a dot.gif to 3,000 table cells to fix layout issues' } | ||
``` | ||
@@ -174,6 +181,12 @@ | ||
### find(version:String) | ||
Finds a release given a version. | ||
### delete() | ||
Delete the current changelog | ||
## Release History | ||
See [CHANGELOG.md](CHANGELOG.md) :scream-cat: | ||
See [CHANGELOG.md](CHANGELOG.md) :scream_cat: | ||
## License | ||
Copyright (c) 2014 heff. Licensed under the Apache license. |
@@ -20,7 +20,7 @@ /* | ||
if (err) { | ||
return grunt.log.error(err); | ||
} else if (success) { | ||
grunt.log.writeln(success); | ||
done(); | ||
grunt.log.error(err.message); | ||
return done(false); | ||
} | ||
grunt.log.writeln(success); | ||
done(true); | ||
} | ||
@@ -41,9 +41,27 @@ } | ||
var done = this.async(); | ||
commands.release(version, {}, getCallback(done)); | ||
commands.release(version, {}, function(err, release) { | ||
if (err) { | ||
grunt.log.error(err.message); | ||
done(false); | ||
} | ||
grunt.config.set('chg.release.title', release.title); | ||
grunt.config.set('chg.release.changes', release.changes); | ||
}); | ||
}); | ||
grunt.registerTask('chg-find', 'Find a release in the changelog', function(version) { | ||
var release = commands.find(version); | ||
if (Object.keys(release).length === 0) { | ||
return grunt.log.write('Release not found in the changelog'); | ||
} | ||
return release; | ||
}); | ||
grunt.registerTask('chg-delete', 'Delete the changelog', function() { | ||
var done = this.async(); | ||
commands.release({}, getCallback(done)); | ||
commands.delete({}, getCallback(done)); | ||
}); | ||
}; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
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
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
24545
18
477
191
8
1