blah
Version:
A command line tool to optimize the repetitive actions.
446 lines (389 loc) • 14.8 kB
JavaScript
;
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var writeFile = require("write-file-trim"),
path = require("path"),
markdox = require("markdox"),
isThere = require("is-there"),
rJson = require("r-json"),
wJson = require("w-json"),
parentSearch = require("parent-search"),
findFileInDirs = require("find-file-in-dirs"),
ul = require("ul"),
sameTime = require("same-time"),
oneByOne = require("one-by-one"),
deffy = require("deffy"),
ejs = require("ejs"),
ncp = require("ncp"),
semver = require("semver"),
abs = require("abs"),
yearRange = require("year-range"),
initialCommitDate = require("initial-commit-date"),
currentYear = require("current-year");
// Constants
var BLAH_DIR = ".blah",
BLAH_TEMPLATES = ".blah-templates",
TEMPLATES = "templates",
PACKAGE_JSON = "package.json",
DOCUMENTATION_NAME = "DOCUMENTATION.md",
DOCUMENTATION_TMPL = "docs.ejs",
CONTRIBUTING_TMPL = "CONTRIBUTING.ejs",
CONTRIBUTING_NAME = "CONTRIBUTING.md",
README_TMPL = "README.ejs",
README_NAME = "README.md",
LICENSE_NAME = "LICENSE",
GITIGNORE_TMPL = "gitignore",
GITIGNORE = ".gitignore",
DATA_JS = "data.js";
var Blah = function () {
/**
* Blah
* Creates a new `Blah` instance.
*
* @name Blah
* @function
* @param {String} cwd The Blah working directory (default: `process.cwd()`).
*/
function Blah(cwd) {
_classCallCheck(this, Blah);
// Blah working directory
this.path = deffy(cwd, process.cwd());
// .blah/
this.blah_dir = path.join(this.path, BLAH_DIR);
// ~/.blah-templates
this.usr_templates = abs("~/" + BLAH_TEMPLATES);
// templates/
this.lib_templates = path.join(__dirname, TEMPLATES);
this.templates = {};
this.pack = {};
this.paths = {};
}
/**
* search
* Searches a file in the blah directories.
*
* @name search
* @function
* @param {String} file The relative path to a file to search in the templates
* directories (in the following order: local `.blah` directory,
* `~/.blah-templates`, library templates).
* @param {Function} callback The callback function.
*/
_createClass(Blah, [{
key: "search",
value: function search(file, callback) {
findFileInDirs([
// Local .blah/file
this.blah_dir
// Templates: ~/.blah-templates/file
, this.usr_templates
// Library templates: templates/file
, this.lib_templates], file, function (err, file) {
if (err) {
return callback(err);
}
console.log("Using " + file + " as source.");
callback(null, file);
});
}
/**
* prepare
* Prepares the Blah data.
*
* @name prepare
* @function
* @param {Function} callback The callback function.
*/
}, {
key: "prepare",
value: function prepare(callback) {
var _this = this;
if (this.initialized) {
return callback();
}
oneByOne([function (next) {
return sameTime([function (cb) {
return _this.search(DOCUMENTATION_TMPL, cb);
}, function (cb) {
return _this.search(README_TMPL, cb);
}, function (cb) {
return _this.search(GITIGNORE_TMPL, cb);
}, function (cb) {
return _this.search(CONTRIBUTING_TMPL, cb);
}, function (cb) {
parentSearch(_this.path, PACKAGE_JSON, cb);
}], next);
}, function (next, data) {
_this.paths.markdox = data[0];
_this.paths.readme = data[1];
_this.paths.gitignore = data[2];
_this.paths.contributing = data[3];
_this.paths.pack = data[4];
next();
}, function (next) {
if (!_this.paths.pack) {
return next(null, {});
}
rJson(_this.paths.pack, function (err, pack) {
pack = deffy(pack, {});
next(null, pack);
});
}, function (next, pack) {
_this.pack = pack;
_this.pack.blah = deffy(_this.pack.blah, {});
_this.copyright = {
fullname: _this.pack.author,
year: new Date().getFullYear(),
project: _this.pack.name,
description: _this.pack.description
};
next();
}, function (next) {
initialCommitDate(function (err, d) {
_this.current_year = currentYear();
_this.first_commit_year = err ? _this.current_year : d.getFullYear();
_this.license_year = yearRange(_this.first_commit_year, _this.current_year);
next();
});
}], function (err, data) {
_this.initialized = true;
callback(err, data);
});
}
/**
* init
* Inits the `.blah` directory in the current project.
*
* @name init
* @function
* @param {Function} callback The callback function.
*/
}, {
key: "init",
value: function init(callback) {
var _this2 = this;
oneByOne([function (next) {
return _this2.prepare(next);
}, function (next) {
return _this2.search(next);
}, function (next, path_templates) {
if (path_templates === _this2.blah_dir) {
return next(new Error("Refusing to override existing templates."));
}
ncp(path_templates, _this2.blah_dir, next);
}], callback);
}
/**
* docs
* Generates the DOCUMENTATION.md file, parsing the input files.
*
* @name docs
* @function
* @param {String} input Input file name (default: main file from package.json)
* @param {String} output Output file name (default: `DOCUMENTATION.md`)
* @param {Boolean} writeToFile If `false`, the docs will be returned via the
* callback function, without writing the output file.
* @param {Function} callback The callback function.
*/
}, {
key: "docs",
value: function docs(input, output, writeToFile, callback) {
var _this3 = this;
input = deffy(input, "");
if (typeof writeToFile === "function") {
callback = writeToFile;
writeToFile = true;
}
if (typeof output === "function") {
callback = output;
output = path.join(this.path, DOCUMENTATION_NAME);
} else if (typeof output === "boolean") {
writeToFile = output;
output = null;
}
writeToFile = deffy(writeToFile, true);
oneByOne([function (next) {
return _this3.prepare(next);
}, function (next) {
isThere(input, next.bind(_this3, null));
}, function (next, exists) {
if (!exists) {
if (writeToFile) {
return next(new Error("The input file does not exist."));
}
return next(null, "");
}
markdox.process(input, {
template: _this3.paths.markdox
}, next);
}, function (next, content) {
content = content.split("\n").map(function (c) {
return c.trimRight();
}).join("\n");
if (writeToFile) {
writeFile(output, content, next);
} else {
next(null, content);
}
}], function (err, result) {
if (err) {
return callback(err);
}
callback(null, result.slice(-1)[0]);
});
}
/**
* readme
* Creates the `README.md` file.
*
* @name readme
* @function
* @param {Function} callback The callback function
*/
}, {
key: "readme",
value: function readme(callback) {
var _this4 = this;
oneByOne([function (next) {
return _this4.prepare(next);
}, function (next) {
_this4.docs(_this4.pack.blah.main || _this4.pack.main, false, next);
}, function (next, docs) {
_this4.render(_this4.paths.readme, {
docs: docs
}, next);
}, function (err, content) {
writeFile(path.join(_this4.path, README_NAME), content, callback);
}], callback);
}
/**
* gitignore
* Creates the `.gitignore` file.
*
* @name gitignore
* @function
* @param {Function} callback The callback function.
*/
}, {
key: "gitignore",
value: function gitignore(callback) {
var _this5 = this;
oneByOne([function (next) {
return _this5.prepare(next);
}, function (next) {
ncp(_this5.paths.gitignore, path.join(_this5.path, GITIGNORE), next);
}], callback);
}
/**
* license
* Creates the `LICENSE` file.
*
* @name license
* @function
* @param {String} license The license name.
* @param {Function} callback The callback function.
*/
}, {
key: "license",
value: function license(_license, callback) {
var _this6 = this;
_license = _license.toLowerCase();
oneByOne([function (next) {
return _this6.prepare(next);
}, function (next) {
_this6.search("licenses/" + _license + ".ejs", next);
}, function (next, licensepath) {
if (!_this6.copyright.fullname) {
return next(new Error("Cannot find the author name. Is the package.json file missing?"));
}
_this6.render(licensepath, next);
}, function (next, content) {
writeFile(path.join(_this6.path, LICENSE_NAME), content, next);
}], callback);
}
/**
* render
* Renders a template from file.
*
* @name render
* @function
* @param {String} path The template path.
* @param {Object} data Additional data to merge into the template data.
* @param {Function} callback The callback function.
*/
}, {
key: "render",
value: function render(path, data, callback) {
var _this7 = this;
if (typeof data === "function") {
callback = data;
data = {};
}
this.search(DATA_JS, async function (err, dataJsPath) {
var collectTemplateDataFn = async function collectTemplateDataFn() {};
if (dataJsPath) {
collectTemplateDataFn = require(dataJsPath);
}
var templateData = await collectTemplateDataFn(path, data, _this7);
var renderData = ul.merge({
_: _this7,
require: require
}, ul.merge(templateData, data));
ejs.renderFile(path, renderData, callback);
});
}
/**
* contributing
* Generates the `CONTRIBUTING.md` file.
*
* @name contributing
* @function
* @param {Function} callback The callback function.
*/
}, {
key: "contributing",
value: function contributing(callback) {
var _this8 = this;
oneByOne([function (next) {
return _this8.prepare(next);
}, function (next) {
_this8.render(_this8.paths.contributing, next);
}, function (next, content) {
writeFile(path.join(_this8.path, CONTRIBUTING_NAME), content, next);
}], callback);
}
/**
* version
* Bumps the provided version.
*
* @name version
* @function
* @param {String} what The version which should be bumped. It takes one of the following values: `"major"`, `"minor"`, `"patch"`. The default is `"patch"`.
* @param {Function} callback The callback function.
*/
}, {
key: "version",
value: function version(what, callback) {
var _this9 = this;
if (typeof what === "function") {
callback = what;
what = "patch";
}
oneByOne([function (next) {
return _this9.prepare(next);
}, function (next) {
var version = _this9.pack.version;
if (!version) {
return callback(new Error("Cannot find the version in the package.json file."));
}
_this9.pack.version = semver.inc(version, what);
if (!_this9.pack.version) {
return next(new Error("Invalid version."));
}
wJson(_this9.paths.pack, _this9.pack, next);
}], callback);
}
}]);
return Blah;
}();
module.exports = Blah;