<commit_before>var restify = require('restify');
var irc = require('irc');
var request = require('request');
var util = require('util');
var config = require('./config.json');

var client = new irc.Client(config.irc.server, config.irc.nick, config.irc);
client.addListener('error', console.error);

var server = restify.createServer();

server.use(restify.queryParser());
server.use(restify.bodyParser());

server.post(config.http.path, (req, res, next) => {
	var channel = '#'+(req.query.channel || config.irc.homeChannel);
	if (req.header('X-GitHub-Event')) {
		var event = req.header('X-GitHub-Event');
		var action = req.body.action;
		var repo = req.body.repository ? req.body.repository.full_name : null;
		var org = req.body.organization ? req.body.organization.login : null;
		var sender = req.body.sender.login;
		if (event === 'issues') {
			var issue = req.body.issue;
			if (action === 'opened') {
				msg(channel, repo, 'Issue #'+issue.number+' §a§lopened§r by '+sender, issue.title, issue.html_url);
			} else if (action === 'closed') {
				msg(channel, repo, 'Issue #'+issue.number+' §c§lclosed§r by '+sender, issue.title, issue.html_url);
			} else if (action === 'reopened') {
				msg(channel, repo, 'Issue #'+issue.number+' §e§lreopened§r by '+sender, issue.title, issue.html_url);
			}
		} else if (event === 'pull_request') {
			var pr = req.body.pull_request;
			if (action === 'opened') {
				msg(channel, repo, 'Pull #'+pr.number+' §a§lopened§r by '+sender, pr.title, pr.html_url);
			} else if (action === 'closed') {
				if (req.body.pull_request.merged) {
					msg(channel, repo, 'Pull #'+pr.number+' §d§lmerged§r by '+sender, pr.title, pr.html_url);
				} else {
					msg(channel, repo, 'Pull #'+pr.number+' §c§lclosed§r by '+sender, pr.title, pr.html_url);
				}
			} else if (action === 'reopened') {
				msg(channel, repo, 'Pull #'+pr.number+' §e§lreopened§r by '+sender, pr.title, pr.html_url);
			}
		} else if (event === 'push') {
			var branch = req.body.ref.slice(11)+'/';
			if (branch === req.body.repository.default_branch) branch = '';
			req.body.commits.forEach((commit) => {
				msg(channel, repo, 'Commit §a§lpushed§r by '+sender, '§l'+branch+commit.id.slice(0, 8)+'§r '+commit.message.split('\n')[0], commit.url);
			});
		} else if (event === 'repository') {
			if (action === 'created') {
				msg(channel, repo, 'Repository §a§lcreated§r by '+sender, req.body.repository.description, req.body.repository.html_url);
			} else if (action === 'deleted') {
				msg(channel, repo, 'Repository §c§ldeleted§r by '+sender, '', null);
			}
		} else if (event === 'organization') {
			if (action === 'member_added') {
				msg(channel, org, req.body.membership.user.login+' §c§ljoined§r', '', null);
			} else if (action === 'member_removed') {
				msg(channel, org, req.body.membership.user.login+' §c§lleft§r', '', null);
			} else if (action === 'member_invited') {
				msg(channel, org, req.body.invitation.login+' §d§linvited§r by '+sender, '', null);
			}
		} else if (event === "ping") {
			msg(channel, req.body.hook.type === "Repository" ? req.body.repository.full_name : req.body.organization.login+'/*', 'Bot connected by '+sender, req.body.zen, null);
			if (channel !== '#'+config.irc.homeChannel) {
				msg('#'+config.irc.homeChannel, req.body.hook.type === "Repository" ? req.body.repository.full_name : req.body.organization.login+'/*', 'Bot connected to '+channel+' by '+sender, req.body.zen, null);
			}
		} else if (event === "gollum") {
			req.body.pages.forEach((page) => {
				if (page.action === "created") {
					msg(channel, repo, 'Wiki page §a§lcreated§r by '+sender, page.title, page.html_url);
				} else if (page.action === "edited") {
					msg(channel, repo, 'Wiki page §e§lmodified§r by '+sender, page.title, page.html_url);
				}
			});
		} else if (event === "release") {
			msg(channel, repo, 'Release §a§lpublished§r by '+sender, req.body.release.name || req.body.release.tag_name, req.body.release.html_url);
		} else if (event === "create") {
			if (req.body.ref_type === "branch") {
				var ref = req.body.ref.replace("refs/heads/", "");
				msg(channel, repo, 'Branch §a§lcreated§r by '+sender, ref, req.body.repository.html_url+"/tree/"+ref);
			}
		} else if (event === "delete") {
			if (req.body.ref_type === "branch") {
				var ref = req.body.ref.replace("refs/heads/", "");
				msg(channel, repo, 'Branch §c§ldeleted§r by '+sender, ref, req.body.repository.html_url+"/tree/"+ref);
			}
		} else if (event === "team") {
			if (action === "created") {
				msg(channel, org, 'Team §a§lcreated§r by '+sender, req.body.team.name, null);
			} else if (action === "deleted") {
				msg(channel, org, 'Team §c§ldeleted§r by '+sender, req.body.team.name, null);
			} else if (action === "edited") {
				msg(channel, org, 'Team §e§ledited§r by '+sender, req.body.team.name, null);
			} else if (action === "added_to_repository") {
				msg(channel, repo, 'Team §a§ladded§r to repository by '+sender, req.body.team.name, null);
			} else if (action === "removed_from_repository") {
				msg(channel, repo, 'Team §c§lremoved§r from repository by '+sender, req.body.team.name, null);
			}
		} else if (event === 'issue_comment') {
			var issue = req.body.issue;
			var comment = req.body.comment;
			if (action === 'created') {
				msg(channel, repo, 'Comment on issue #'+issue.number+' §a§lposted§r by '+sender, issue.title, comment.html_url);
			} else if (action === 'deleted') {
				msg(channel, repo, 'Comment on issue #'+issue.number+' §c§ldeleted§r by '+sender, issue.title, comment.html_url);
			} else if (action === 'edited') {
				msg(channel, repo, 'Comment on issue #'+issue.number+' §e§ledited§r by '+sender, issue.title, comment.html_url);
			}
		} else if (event === 'status') {
			var branch = req.body.branches[0].name+'/';
			if (branch === req.body.repository.default_branch) branch = '';
			var state = req.body.state;
			var commit = req.body.sha.slice(0, 8);
			if (state === 'success') {
				msg(channel, repo, 'Build §a§lsuccessful§r!', '§l'+branch+commit+'§r');
			} else if (state === 'failure') {
				msg(channel, repo, 'Build §c§lfailed§r.', '§l'+branch+commit+'§r');
			} else if (state === 'error') {
				msg(channel, repo, 'Build §7§lerrored§r!', '§l'+branch+commit+'§r');
			}
		}
		res.send(200, 'OK');
	} else if (req.header('X-Gitlab-Event')) {
		var repo = req.body.project ? req.body.project.namespace+"/"+req.body.project.name : null;
		var event = req.header('X-Gitlab-Event');
		if (event === "Push Hook") {
			var senderId = req.body.user_id;
			request.get(config.gitlab.url+'users/'+senderId+'?private_token='+config.gitlab.token, (err, res, body) => {
				if (res && res.statusCode == 200) {
					var sender = JSON.parse(body).username;
					var branch = req.body.ref.slice(11)+'/';
					if (branch === req.body.project.default_branch+'/') branch = '';
					req.body.commits.forEach((commit) => {
						msg(channel, repo, 'Commit §a§lpushed§r by '+sender, '§l'+branch+commit.id.slice(0, 8)+'§r '+commit.message.split('\n')[0], null, true);
					});
				} else {
					console.error("GitLab API returned "+res.statusCode);
				}
			});
		} else if (event === "Note Hook") {
			var sender = req.body.user.username;
			var objectType = req.body.object_attributes.noteable_type;
			if (objectType === "Commit") {
				msg(channel, repo, 'Comment on commit '+req.body.commit.id.slice(0, 8)+' §a§lposted§r by '+sender, req.body.commit.message.split('\n')[0], null, true);
			} else if (objectType === "MergeRequest") {
				msg(channel, repo, 'Comment on merge request #'+req.body.merge_request.id+' §a§lposted§r by '+sender, req.body.merge_request.title, null, true);
			} else if (objectType === "Issue") {
				msg(channel, repo, 'Comment on issue #'+req.body.issue.iid+' §a§lposted§r by '+sender, req.body.issue.title, null, true);
			} else if (objectType === "Snippet") {
				msg(channel, repo, 'Comment on snippet #'+req.body.snippet.iid+' §a§lposted§r by '+sender, req.body.snippet.title, null, true);
			}
		} else if (event === "Merge Request Hook") {
			var sender = req.body.user.username;
			var issue = req.body.object_attributes;
			var action = issue.action;
			if (action === 'open') {
				msg(channel, repo, 'Issue #'+issue.iid+' §a§lopened§r by '+sender, issue.title, false, true);
			} else if (action === 'close') {
				msg(channel, repo, 'Issue #'+issue.iid+' §c§lclosed§r by '+sender, issue.title, false, true);
			} else if (action === 'reopen') {
				msg(channel, repo, 'Issue #'+issue.iid+' §e§lreopened§r by '+sender, issue.title, false, true);
			}
		} else if (event === "Issue Hook") {
			var sender = req.body.user.username;
			var issue = req.body.object_attributes;
			var action = issue.action;
			if (action === 'open') {
				msg(channel, repo, 'Issue #'+issue.iid+' §a§lopened§r by '+sender, issue.title, false, true);
			} else if (action === 'close') {
				msg(channel, repo, 'Issue #'+issue.iid+' §c§lclosed§r by '+sender, issue.title, false, true);
			} else if (action === 'reopen') {
				msg(channel, repo, 'Issue #'+issue.iid+' §e§lreopened§r by '+sender, issue.title, false, true);
			}
		}
		res.send(200, 'OK');
	} else {
		res.send(404);
	}
});

server.listen(config.http.port, config.http.bind);

// I've spent WAY too much time manually writing Minecraft color codes, so this
// is actually /easier/ for me than some utility methods that take names
var mcCodes = {
	"§0": "\x0301", // black
	"§1": "\x0302", // navy
	"§2": "\x0303", // green
	"§3": "\x0310", // teal
	"§4": "\x0305", // maroon
	"§5": "\x0306", // purple
	"§6": "\x0307", // olive
	"§7": "\x0315", // silver
	"§8": "\x0314", // grey
	"§9": "\x0312", // blue
	"§a": "\x0309", // green
	"§b": "\x0311", // cyan
	"§c": "\x0304", // red
	"§d": "\x0313", // pink
	"§e": "\x0308", // yellow
	"§f": "\x0300", // white

	"§l": "\x02", // bold
	"§o": "\x1D", // italic
	"§m": "",     // strike, no IRC equivalent
	"§n": "\x1F", // underline
	"§r": "\x0F", // reset
}

function msg(channel, repo, msg, desc, url, gitlab) {
	console.log('[%s] %s: %s %s', repo, msg, desc, url || "");
	if (url) {
		request.post('https://git.io/create', {
			form:{url:url}
		}, (err, res, body) => {
			client.say(channel, substituteColors(util.format((gitlab ? config.messageFormatGitlab : config.messageFormat), repo, msg, desc, err || (!res || res.statusCode != 200) ? url : 'https://git.io/'+body)));
		});
	} else {
		client.say(channel, substituteColors(util.format((gitlab ? config.messageFormatGitlab : config.messageFormat), repo, msg, desc, '')));
	}
}

function substituteColors(str) {
	Object.keys(mcCodes).forEach((k) => {
		str = str.replace(new RegExp(k, "gi"), mcCodes[k]);
	});
	return str;
}

<commit_msg>Add pull request review support<commit_after>var restify = require('restify');
var irc = require('irc');
var request = require('request');
var util = require('util');
var config = require('./config.json');

var client = new irc.Client(config.irc.server, config.irc.nick, config.irc);
client.addListener('error', console.error);

var server = restify.createServer();

server.use(restify.queryParser());
server.use(restify.bodyParser());

server.post(config.http.path, (req, res, next) => {
	var channel = '#'+(req.query.channel || config.irc.homeChannel);
	if (req.header('X-GitHub-Event')) {
		var event = req.header('X-GitHub-Event');
		var action = req.body.action;
		var repo = req.body.repository ? req.body.repository.full_name : null;
		var org = req.body.organization ? req.body.organization.login : null;
		var sender = req.body.sender.login;
		if (event === 'issues') {
			var issue = req.body.issue;
			if (action === 'opened') {
				msg(channel, repo, 'Issue #'+issue.number+' §a§lopened§r by '+sender, issue.title, issue.html_url);
			} else if (action === 'closed') {
				msg(channel, repo, 'Issue #'+issue.number+' §c§lclosed§r by '+sender, issue.title, issue.html_url);
			} else if (action === 'reopened') {
				msg(channel, repo, 'Issue #'+issue.number+' §e§lreopened§r by '+sender, issue.title, issue.html_url);
			}
		} else if (event === 'pull_request') {
			var pr = req.body.pull_request;
			if (action === 'opened') {
				msg(channel, repo, 'Pull #'+pr.number+' §a§lopened§r by '+sender, pr.title, pr.html_url);
			} else if (action === 'closed') {
				if (req.body.pull_request.merged) {
					msg(channel, repo, 'Pull #'+pr.number+' §d§lmerged§r by '+sender, pr.title, pr.html_url);
				} else {
					msg(channel, repo, 'Pull #'+pr.number+' §c§lclosed§r by '+sender, pr.title, pr.html_url);
				}
			} else if (action === 'reopened') {
				msg(channel, repo, 'Pull #'+pr.number+' §e§lreopened§r by '+sender, pr.title, pr.html_url);
			} else if (action === "review_requested") {
				msg(channel, repo, 'Review on pull request #'+req.body.pull_request.number+' from '+req.body.requested_reviewer.login+' §lrequested§r by '+sender, req.body.pull_request.title, req.body.pull_request.html_url);
			}
		} else if (event === 'push') {
			var branch = req.body.ref.slice(11)+'/';
			if (branch === req.body.repository.default_branch) branch = '';
			req.body.commits.forEach((commit) => {
				msg(channel, repo, 'Commit §a§lpushed§r by '+sender, '§l'+branch+commit.id.slice(0, 8)+'§r '+commit.message.split('\n')[0], commit.url);
			});
		} else if (event === 'repository') {
			if (action === 'created') {
				msg(channel, repo, 'Repository §a§lcreated§r by '+sender, req.body.repository.description, req.body.repository.html_url);
			} else if (action === 'deleted') {
				msg(channel, repo, 'Repository §c§ldeleted§r by '+sender, '', null);
			}
		} else if (event === 'organization') {
			if (action === 'member_added') {
				msg(channel, org, req.body.membership.user.login+' §a§ljoined§r', '', null);
			} else if (action === 'member_removed') {
				msg(channel, org, req.body.membership.user.login+' §c§lleft§r', '', null);
			} else if (action === 'member_invited') {
				msg(channel, org, req.body.invitation.login+' §d§linvited§r by '+sender, '', null);
			}
		} else if (event === "ping") {
			msg(channel, req.body.hook.type === "Repository" ? req.body.repository.full_name : req.body.organization.login+'/*', 'Bot connected by '+sender, req.body.zen, null);
			if (channel !== '#'+config.irc.homeChannel) {
				msg('#'+config.irc.homeChannel, req.body.hook.type === "Repository" ? req.body.repository.full_name : req.body.organization.login+'/*', 'Bot connected to '+channel+' by '+sender, req.body.zen, null);
			}
		} else if (event === "gollum") {
			req.body.pages.forEach((page) => {
				if (page.action === "created") {
					msg(channel, repo, 'Wiki page §a§lcreated§r by '+sender, page.title, page.html_url);
				} else if (page.action === "edited") {
					msg(channel, repo, 'Wiki page §e§lmodified§r by '+sender, page.title, page.html_url);
				}
			});
		} else if (event === "release") {
			msg(channel, repo, 'Release §a§lpublished§r by '+sender, req.body.release.name || req.body.release.tag_name, req.body.release.html_url);
		} else if (event === "create") {
			if (req.body.ref_type === "branch") {
				var ref = req.body.ref.replace("refs/heads/", "");
				msg(channel, repo, 'Branch §a§lcreated§r by '+sender, ref, req.body.repository.html_url+"/tree/"+ref);
			}
		} else if (event === "delete") {
			if (req.body.ref_type === "branch") {
				var ref = req.body.ref.replace("refs/heads/", "");
				msg(channel, repo, 'Branch §c§ldeleted§r by '+sender, ref, req.body.repository.html_url+"/tree/"+ref);
			}
		} else if (event === "team") {
			if (action === "created") {
				msg(channel, org, 'Team §a§lcreated§r by '+sender, req.body.team.name, null);
			} else if (action === "deleted") {
				msg(channel, org, 'Team §c§ldeleted§r by '+sender, req.body.team.name, null);
			} else if (action === "edited") {
				msg(channel, org, 'Team §e§ledited§r by '+sender, req.body.team.name, null);
			} else if (action === "added_to_repository") {
				msg(channel, repo, 'Team §a§ladded§r to repository by '+sender, req.body.team.name, null);
			} else if (action === "removed_from_repository") {
				msg(channel, repo, 'Team §c§lremoved§r from repository by '+sender, req.body.team.name, null);
			}
		} else if (event === 'issue_comment') {
			var issue = req.body.issue;
			var comment = req.body.comment;
			var type = (req.body.issue.pull_request ? "pull request" : "issue");
			if (action === 'created') {
				msg(channel, repo, 'Comment on '+type+' #'+issue.number+' §a§lposted§r by '+sender, issue.title, comment.html_url);
			} else if (action === 'deleted') {
				msg(channel, repo, 'Comment on '+type+' #'+issue.number+' §c§ldeleted§r by '+sender, issue.title, comment.html_url);
			} else if (action === 'edited') {
				msg(channel, repo, 'Comment on '+type+' #'+issue.number+' §e§ledited§r by '+sender, issue.title, comment.html_url);
			}
		} else if (event === 'status') {
			var branch = req.body.branches[0].name+'/';
			if (branch === req.body.repository.default_branch) branch = '';
			var state = req.body.state;
			var commit = req.body.sha.slice(0, 8);
			if (state === 'success') {
				msg(channel, repo, 'Build §a§lsuccessful§r!', '§l'+branch+commit+'§r');
			} else if (state === 'failure') {
				msg(channel, repo, 'Build §c§lfailed§r.', '§l'+branch+commit+'§r');
			} else if (state === 'error') {
				msg(channel, repo, 'Build §7§lerrored§r!', '§l'+branch+commit+'§r');
			}
		} else if (event === "pull_request_review") {
			var issue = req.body.pull_request;
			var review = req.body.review;
			if (req.body.action === "submitted") {
				if (review.state === "approved") {
					msg(channel, repo, 'Pull request #'+issue.number+' §a§lapproved§r by '+sender, issue.title, review.html_url);
				} else if (review.state === "changes_requested") {
					msg(channel, repo, 'Pull request #'+issue.number+' §c§lrejected§r by '+sender, issue.title, review.html_url);
				}
			} else if (req.body.action === "dismissed") {
				msg(channel, repo, 'Review on pull request #'+issue.number+' §7§ldismissed§r by <unknown>', issue.title, review.html_url);
			}
		}
		res.send(200, 'OK');
	} else if (req.header('X-Gitlab-Event')) {
		var repo = req.body.project ? req.body.project.namespace+"/"+req.body.project.name : null;
		var event = req.header('X-Gitlab-Event');
		if (event === "Push Hook") {
			var senderId = req.body.user_id;
			request.get(config.gitlab.url+'users/'+senderId+'?private_token='+config.gitlab.token, (err, res, body) => {
				if (res && res.statusCode == 200) {
					var sender = JSON.parse(body).username;
					var branch = req.body.ref.slice(11)+'/';
					if (branch === req.body.project.default_branch+'/') branch = '';
					req.body.commits.forEach((commit) => {
						msg(channel, repo, 'Commit §a§lpushed§r by '+sender, '§l'+branch+commit.id.slice(0, 8)+'§r '+commit.message.split('\n')[0], null, true);
					});
				} else {
					console.error("GitLab API returned "+res.statusCode);
				}
			});
		} else if (event === "Note Hook") {
			var sender = req.body.user.username;
			var objectType = req.body.object_attributes.noteable_type;
			if (objectType === "Commit") {
				msg(channel, repo, 'Comment on commit '+req.body.commit.id.slice(0, 8)+' §a§lposted§r by '+sender, req.body.commit.message.split('\n')[0], null, true);
			} else if (objectType === "MergeRequest") {
				msg(channel, repo, 'Comment on merge request !'+req.body.merge_request.iid+' §a§lposted§r by '+sender, req.body.merge_request.title, null, true);
			} else if (objectType === "Issue") {
				msg(channel, repo, 'Comment on issue #'+req.body.issue.iid+' §a§lposted§r by '+sender, req.body.issue.title, null, true);
			} else if (objectType === "Snippet") {
				msg(channel, repo, 'Comment on snippet $'+req.body.snippet.id+' §a§lposted§r by '+sender, req.body.snippet.title, null, true);
			}
		} else if (event === "Merge Request Hook") {
			var sender = req.body.user.username;
			var issue = req.body.object_attributes;
			var action = issue.action;
			if (action === 'open') {
				msg(channel, repo, 'Merge request !'+issue.iid+' §a§lopened§r by '+sender, issue.title, false, true);
			} else if (action === 'close') {
				msg(channel, repo, 'Merge request !'+issue.iid+' §c§lclosed§r by '+sender, issue.title, false, true);
			} else if (action === 'reopen') {
				msg(channel, repo, 'Merge request !'+issue.iid+' §e§lreopened§r by '+sender, issue.title, false, true);
			} else if (action === 'update') {
				msg(channel, repo, 'Merge request !'+issue.iid+' §e§lupdated§r by '+sender, issue.title, false, true);
			} else if (action === 'merge') {
				msg(channel, repo, 'Merge request !'+issue.iid+' §d§lmerged§r by '+sender, issue.title, false, true);
			}
		} else if (event === "Issue Hook") {
			var sender = req.body.user.username;
			var issue = req.body.object_attributes;
			var action = issue.action;
			if (action === 'open') {
				msg(channel, repo, 'Issue #'+issue.iid+' §a§lopened§r by '+sender, issue.title, false, true);
			} else if (action === 'close') {
				msg(channel, repo, 'Issue #'+issue.iid+' §c§lclosed§r by '+sender, issue.title, false, true);
			} else if (action === 'reopen') {
				msg(channel, repo, 'Issue #'+issue.iid+' §e§lreopened§r by '+sender, issue.title, false, true);
			}
		}
		res.send(200, 'OK');
	} else {
		res.send(404);
	}
});

server.listen(config.http.port, config.http.bind);

// I've spent WAY too much time manually writing Minecraft color codes, so this
// is actually /easier/ for me than some utility methods that take names
var mcCodes = {
	"§0": "\x0301", // black
	"§1": "\x0302", // navy
	"§2": "\x0303", // green
	"§3": "\x0310", // teal
	"§4": "\x0305", // maroon
	"§5": "\x0306", // purple
	"§6": "\x0307", // olive
	"§7": "\x0315", // silver
	"§8": "\x0314", // grey
	"§9": "\x0312", // blue
	"§a": "\x0309", // green
	"§b": "\x0311", // cyan
	"§c": "\x0304", // red
	"§d": "\x0313", // pink
	"§e": "\x0308", // yellow
	"§f": "\x0300", // white

	"§l": "\x02", // bold
	"§o": "\x1D", // italic
	"§m": "",     // strike, no IRC equivalent
	"§n": "\x1F", // underline
	"§r": "\x0F", // reset
}

function msg(channel, repo, msg, desc, url, gitlab) {
	console.log('[%s] %s: %s %s', repo, msg, desc, url || "");
	if (url) {
		request.post('https://git.io/create', {
			form:{url:url}
		}, (err, res, body) => {
			client.say(channel, substituteColors(util.format((gitlab ? config.messageFormatGitlab : config.messageFormat), repo, msg, desc, err || (!res || res.statusCode != 200) ? url : 'https://git.io/'+body)));
		});
	} else {
		client.say(channel, substituteColors(util.format((gitlab ? config.messageFormatGitlab : config.messageFormat), repo, msg, desc, '')));
	}
}

function substituteColors(str) {
	Object.keys(mcCodes).forEach((k) => {
		str = str.replace(new RegExp(k, "gi"), mcCodes[k]);
	});
	return str;
}

<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict';
const meow = require('meow');
const readPkgUp = require('read-pkg-up');
const opn = require('opn');
const packageJson = require('package-json');
const githubUrlFromGit = require('github-url-from-git');
const isUrl = require('is-url-superb');

const cli = meow(`
	Usage
	  $ npm-home [name]
	  $ nh [name]

	Options
	  --github -g  Open the GitHub repo of the package
	  --yarn -y    Open the Yarn homepage of the package

	Examples
	  $ npm-home
	  $ npm-home chalk -g
`, {
	flags: {
		github: {
			type: 'boolean',
			alias: 'g'
		},
		yarn: {
			type: 'boolean',
			alias: 'y'
		}
	}
});

function openNpm(name) {
	return opn(`https://www.npmjs.com/package/${name}`, {wait: false});
}

function openYarn(name) {
	return opn(`https://yarn.pm/${name}`, {wait: false});
}

function open(name) {
	if (cli.flags.github) {
		return packageJson(name, {fullMetadata: true}).then(pkg => {
			if (pkg.repository) {
				let url = githubUrlFromGit(pkg.repository.url);

				if (!url) {
					url = pkg.repository.url;

					if (isUrl(url) && /^https?:\/\//.test(url)) {
						console.error(`The \`repository\` field in package.json should point to a Git repo and not a website. Please open an issue or pull request on \`${name}\`.`);
					} else {
						console.error(`The \`repository\` field in package.json is invalid. Please open an issue or pull request on \`${name}\`. Using the \`homepage\` field instead.`);

						url = pkg.homepage;
					}
				}

				return opn(url, {wait: false});
			}

			return openNpm(name);
		});
	}

	if (cli.flags.yarn) {
		return openYarn(name);
	}

	return openNpm(name);
}

if (cli.input.length > 0) {
	open(cli.input[0]);
} else {
	const pkg = readPkgUp.sync().pkg;

	if (!pkg) {
		console.error('You\'re not in an npm package');
		process.exit(1);
	}

	open(pkg.name);
}
<commit_msg>Verify network connection (#12)<commit_after>#!/usr/bin/env node
'use strict';
const meow = require('meow');
const readPkgUp = require('read-pkg-up');
const opn = require('opn');
const packageJson = require('package-json');
const githubUrlFromGit = require('github-url-from-git');
const isUrl = require('is-url-superb');

const cli = meow(`
	Usage
	  $ npm-home [name]
	  $ nh [name]

	Options
	  --github -g  Open the GitHub repo of the package
	  --yarn -y    Open the Yarn homepage of the package

	Examples
	  $ npm-home
	  $ npm-home chalk -g
`, {
	flags: {
		github: {
			type: 'boolean',
			alias: 'g'
		},
		yarn: {
			type: 'boolean',
			alias: 'y'
		}
	}
});

function openNpm(name) {
	return opn(`https://www.npmjs.com/package/${name}`, {wait: false});
}

function openYarn(name) {
	return opn(`https://yarn.pm/${name}`, {wait: false});
}

function open(name) {
	if (cli.flags.github) {
		return packageJson(name, {fullMetadata: true}).then(pkg => {
			if (pkg.repository) {
				let url = githubUrlFromGit(pkg.repository.url);

				if (!url) {
					url = pkg.repository.url;

					if (isUrl(url) && /^https?:\/\//.test(url)) {
						console.error(`The \`repository\` field in package.json should point to a Git repo and not a website. Please open an issue or pull request on \`${name}\`.`);
					} else {
						console.error(`The \`repository\` field in package.json is invalid. Please open an issue or pull request on \`${name}\`. Using the \`homepage\` field instead.`);

						url = pkg.homepage;
					}
				}

				return opn(url, {wait: false});
			}

			return openNpm(name);
		}).catch(err => {
			if (err.code === 'ENOTFOUND') {
				console.error('No network connection detected!');
				process.exit(1);
			}

			throw err;
		});
	}

	if (cli.flags.yarn) {
		return openYarn(name);
	}

	return openNpm(name);
}

if (cli.input.length > 0) {
	open(cli.input[0]);
} else {
	const pkg = readPkgUp.sync().pkg;

	if (!pkg) {
		console.error('You\'re not in an npm package');
		process.exit(1);
	}

	open(pkg.name);
}
<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict';

const meow = require('meow');
const chalk = require('chalk');
const updateNotifier = require('update-notifier');
const pkg = require('./package.json');
const quote = require('./index.js');

const cli = meow({
	help: [
		'Usage',
		'  $ quote-cli',
		'',
		'Options',
		'	 qotd Display quote of the day',
		'',
		'Examples',
		'  $ quote-cli',
		'  To be or not be, that is the question. - William Shakespeare',
		'  $ quote-cli qotd',
		'  Wars teach us not to love our enemies, but to hate our allies. - W. L. George'
	]
});

updateNotifier({pkg: pkg}).notify();

quote(cli.input[0], function (err, result) {
	if (err) {
		console.log(chalk.bold.red(err));
		process.exit(1);
	}

	console.log(chalk.cyan(chalk.yellow(result.quote.body) + ' - ' + result.quote.author));
	process.exit();
});
<commit_msg>Update help info<commit_after>#!/usr/bin/env node
'use strict';

const meow = require('meow');
const chalk = require('chalk');
const updateNotifier = require('update-notifier');
const pkg = require('./package.json');
const quote = require('./index.js');

const cli = meow({
	help: [
		'Usage',
		'  $ quote [options]',
		'',
		'Options',
		'  qotd Display quote of the day',
		'',
		'Examples',
		'  $ quote',
		'  To be or not be, that is the question. - William Shakespeare',
		'  $ quote qotd',
		'  Wars teach us not to love our enemies, but to hate our allies. - W. L. George'
	]
});

updateNotifier({pkg: pkg}).notify();

quote(cli.input[0], function (err, result) {
	if (err) {
		console.log(chalk.bold.red(err));
		process.exit(1);
	}

	console.log(chalk.cyan(chalk.yellow(result.quote.body) + ' - ' + result.quote.author));
	process.exit();
});
<|endoftext|>


<commit_before>#!/usr/bin/env node

var minimist = require('minimist'),
    each     = require('./util/each'),
    mix      = require('./util/mix'),
    isArray  = require('./util/isArray'),
    readFile = require('./util/readFile'),
    readJSON = require('./util/readJSON'),
    fess     = require('./fess');

var pkg = readJSON(__dirname, 'package.json'),
    argv = minimist(process.argv.slice(2));

if (argv.version) {
  console.log(pkg.version);
  process.exit();
}

if (argv.help) {
  console.log(readFile(__dirname, 'README.md'));
  process.exit();
}

var configFile = argv.config || ('.' + pkg.name + 'rc'),
    config = readJSON(configFile);

if (!config) {
  console.log('no config found, loading defaults');
  config = {};
}

if (!isArray(config)) { config = [ config ] };

var defaults = {
  root: process.cwd(),
  port: 3000,
  name: 'server'
};

each(config, function (server) {
  fess(mix(defaults, server));
});
<commit_msg>added --noconf<commit_after>#!/usr/bin/env node

var minimist = require('minimist'),
    each     = require('./util/each'),
    mix      = require('./util/mix'),
    isArray  = require('./util/isArray'),
    readFile = require('./util/readFile'),
    readJSON = require('./util/readJSON'),
    fess     = require('./fess');

var pkg = readJSON(__dirname, 'package.json'),
    argv = minimist(process.argv.slice(2));

if (argv.version) {
  console.log(pkg.version);
  process.exit();
}

if (argv.help) {
  console.log(readFile(__dirname, 'README.md'));
  process.exit();
}

var configFile = argv.config || ('.' + pkg.name + 'rc'),
    config = argv.noconf ? null : readJSON(configFile);

if (!config) {
  console.log('loading defaults');
  config = argv;
}

if (!isArray(config)) {
  config = [ config ]
};

var defaults = {
  root: process.cwd(),
  port: 3000,
  name: 'server'
};

each(config, function (server) {
  fess(mix(defaults, server));
});
<|endoftext|>


<commit_before>#!/usr/bin/env node

var path = require('path');
var nconf = require('nconf');
var yamlLint = require('./yaml-lint');
var leprechaun = require('leprechaun');
var merge = require('lodash.merge');
var snakeCase = require('lodash.snakecase');
var glob = require('glob');
var Promise = require('bluebird');

var options = {};

nconf.argv().env({
  match: /^yamllint/i
}).file({
  file: path.resolve(process.cwd(), '.yaml-lint.json')
});

[
  'schema'
].forEach(function (key) {
  var env = snakeCase(key);
  options[key] = nconf.get(key) || nconf.get('yamllint_' + env.toLowerCase()) || nconf.get('YAMLLINT' + env.toUpperCase());
});

var config = nconf.get();

var files = [];

(config._ || []).forEach(function (file) {
  files = files.concat(glob.sync(file));
});

Promise.map(files, function (file) {
  return yamlLint.lintFile(file, options);
}).then(function () {
  leprechaun.success('YAML Lint successful.');
}).catch(function (error) {
  leprechaun.error('YAML Lint failed.');
  console.error(error.message);
  process.exit(1);
});
<commit_msg>Implement check for empty file selections while using the CLI<commit_after>#!/usr/bin/env node

var path = require('path');
var nconf = require('nconf');
var yamlLint = require('./yaml-lint');
var leprechaun = require('leprechaun');
var merge = require('lodash.merge');
var snakeCase = require('lodash.snakecase');
var glob = require('glob');
var Promise = require('bluebird');

var options = {};

nconf.argv().env({
  match: /^yamllint/i
}).file({
  file: path.resolve(process.cwd(), '.yaml-lint.json')
});

[
  'schema'
].forEach(function (key) {
  var env = snakeCase(key);
  options[key] = nconf.get(key) || nconf.get('yamllint_' + env.toLowerCase()) || nconf.get('YAMLLINT' + env.toUpperCase());
});

var config = nconf.get();

var files = [];

(config._ || []).forEach(function (file) {
  files = files.concat(glob.sync(file));
});

if (files.length === 0) {

  leprechaun.error('YAML Lint failed.');
  console.error('No YAML files were found matching your selection.');
  process.exit(1);

} else {

  Promise.map(files, function (file) {
    return yamlLint.lintFile(file, options);
  }).then(function () {
    leprechaun.success('YAML Lint successful.');
  }).catch(function (error) {
    leprechaun.error('YAML Lint failed.');
    console.error(error.message);
    process.exit(1);
  });

}
<|endoftext|>


<commit_before>#!/usr/bin/env node

var vzla = require('./index');
var pkg = require('./package.json');
var updateNotifier = require('update-notifier');
var program = require('commander');
var colors = require('colors');
var bandera = '    ' +
    colors.yellow.bold('• ') +
    colors.blue.bold('• ') +
    colors.red.bold('• ');
var respuesta;
var t1;
var t2;
var t3;
var t4;
var t5;

updateNotifier({pkg: pkg}).notify();

program
    .version(pkg.version)
    .usage('<estado|municipio|parroquia> [opciones]')
    .description(colors.yellow('Muestra información sobre el territorio Venezolano.'.bold))
    .option('-a, --ayuda', 'muestra cómo utilizar venezuela-js')
    .option('-c, --capital nombre', 'muestra la capital de la entidad')
    .option('-m, --municipio nombre', 'muestra la información de un municipio')
    .option('-p, --parroquia nombre', 'muestra la información de una parroquia')
    .parse(process.argv);

.on('--help', function () {
  console.log('  Ejemplos:');
  console.log('');
  console.log('    $ venezuela --parroquia "San Juan"');
  console.log('    $ venezuela --capital');
  console.log('    $ venezuela Bolívar');
  console.log('');
});

if ((!program.args.length && program.capital) || program.args[0] === 'caracas') {
    respuesta = JSON.stringify(vzla.capital, null, 4);
} else if (process.argv.length <= 2 || program.ayuda) {
    return program.help();
} else if (program.capital) {
    if (vzla.estado(program.args[0]).capital) {
        respuesta = '    ' + vzla.estado(program.args[0]).capital;
    } else if (vzla.municipio(program.args[0]).capital) {
        respuesta = '    ' + vzla.municipio(program.args[0]).capital;
    } else if (vzla.parroquia(program.args[0]).capital) {
        respuesta = '    ' + vzla.parroquia(program.args[0]).capital;
    } else {
        respuesta = '    ' + program.args[0] + ' es un nombre inválido.';
    }
} else if (program.municipio) {
    respuesta = JSON.stringify(vzla.municipio(program.args[0]), null, 4);
} else if (program.parroquia) {
    respuesta = JSON.stringify(vzla.parroquia(program.args[0]), null, 4);
} else {
    if (!/Tal[ ]vez/.test(vzla.estado(program.args[0]))) {
        respuesta = vzla.estado(program.args[0])
        t1 = colors.white.bold('     ISO 31662    ');
        t2 = colors.white.bold('        ESTADO    ');
        t3 = colors.white.bold('       CAPITAL    ');
        t4 = colors.white.bold('    MUNICIPIOS    ');
        t5 = colors.white.bold('    PARROQUIAS    ');
        console.log('');
        console.log(bandera);
        console.log('');
        console.log(t1 + colors.yellow.bold(respuesta.iso_31662));
        console.log(t2 + colors.yellow.bold(respuesta.estado));
        console.log(t3 + colors.yellow.bold(respuesta.capital));
        console.log(t4 + colors.yellow.bold(respuesta.municipios));
        console.log(t5 + colors.yellow.bold(respuesta.parroquias));
        console.log('');
        return;
    } else if (!/Tal[ ]vez/.test(vzla.municipio(program.args[0]))) {
        respuesta = JSON.stringify(vzla.municipio(program.args[0]), null, 4);
    } else if (!/Tal[ ]vez/.test(vzla.parroquia(program.args[0]))) {
        respuesta = JSON.stringify(vzla.parroquia(program.args[0]), null, 4);
    } else {
        respuesta = '    ' + program.args[0] + ' es un nombre inválido.';
    }
}

console.log('');
console.log(bandera);
console.log('');
console.log(colors.white.bold(respuesta));
console.log('');<commit_msg>Se solucionó un :beetle:<commit_after>#!/usr/bin/env node

var vzla = require('./index');
var pkg = require('./package.json');
var updateNotifier = require('update-notifier');
var program = require('commander');
var colors = require('colors');
var bandera = '    ' +
    colors.yellow.bold('• ') +
    colors.blue.bold('• ') +
    colors.red.bold('• ');
var respuesta;
var t1;
var t2;
var t3;
var t4;
var t5;

updateNotifier({pkg: pkg}).notify();

program
    .version(pkg.version)
    .usage('<estado|municipio|parroquia> [opciones]')
    .description(colors.yellow('Muestra información sobre el territorio Venezolano.'.bold))
    .option('-a, --ayuda', 'muestra cómo utilizar venezuela-js')
    .option('-c, --capital nombre', 'muestra la capital de la entidad')
    .option('-m, --municipio nombre', 'muestra la información de un municipio')
    .option('-p, --parroquia nombre', 'muestra la información de una parroquia')
    .parse(process.argv);

program.on('--help', function (){
  console.log('  Ejemplos:');
  console.log('');
  console.log('    $ venezuela --parroquia "San Juan"');
  console.log('    $ venezuela --capital');
  console.log('    $ venezuela Bolívar');
  console.log('');
});

if ((!program.args.length && program.capital) || program.args[0] === 'caracas') {
    respuesta = JSON.stringify(vzla.capital, null, 4);
} else if (process.argv.length <= 2 || program.ayuda) {
    return program.help();
} else if (program.capital) {
    if (vzla.estado(program.args[0]).capital) {
        respuesta = '    ' + vzla.estado(program.args[0]).capital;
    } else if (vzla.municipio(program.args[0]).capital) {
        respuesta = '    ' + vzla.municipio(program.args[0]).capital;
    } else if (vzla.parroquia(program.args[0]).capital) {
        respuesta = '    ' + vzla.parroquia(program.args[0]).capital;
    } else {
        respuesta = '    ' + program.args[0] + ' es un nombre inválido.';
    }
} else if (program.municipio) {
    respuesta = JSON.stringify(vzla.municipio(program.args[0]), null, 4);
} else if (program.parroquia) {
    respuesta = JSON.stringify(vzla.parroquia(program.args[0]), null, 4);
} else {
    if (!/Tal[ ]vez/.test(vzla.estado(program.args[0]))) {
        respuesta = vzla.estado(program.args[0])
        t1 = colors.white.bold('     ISO 31662    ');
        t2 = colors.white.bold('        ESTADO    ');
        t3 = colors.white.bold('       CAPITAL    ');
        t4 = colors.white.bold('    MUNICIPIOS    ');
        t5 = colors.white.bold('    PARROQUIAS    ');
        console.log('');
        console.log(bandera);
        console.log('');
        console.log(t1 + colors.yellow.bold(respuesta.iso_31662));
        console.log(t2 + colors.yellow.bold(respuesta.estado));
        console.log(t3 + colors.yellow.bold(respuesta.capital));
        console.log(t4 + colors.yellow.bold(respuesta.municipios));
        console.log(t5 + colors.yellow.bold(respuesta.parroquias));
        console.log('');
        return;
    } else if (!/Tal[ ]vez/.test(vzla.municipio(program.args[0]))) {
        respuesta = JSON.stringify(vzla.municipio(program.args[0]), null, 4);
    } else if (!/Tal[ ]vez/.test(vzla.parroquia(program.args[0]))) {
        respuesta = JSON.stringify(vzla.parroquia(program.args[0]), null, 4);
    } else {
        respuesta = '    ' + program.args[0] + ' es un nombre inválido.';
    }
}

console.log('');
console.log(bandera);
console.log('');
console.log(colors.white.bold(respuesta));
console.log('');<|endoftext|>


<commit_before>#!/usr/bin/env node

'use strict';

const fs = require('fs');
const path = require('path');
const assert = require('assert');
const yargs = require('yargs');
const dotenv = require('dotenv');
const log = require('npmlog');

let parsedCmd;

/**
 * Little utility function to setup common yargs stuff.
 *
 * @param {yargs}  yargs The yargs instance
 * @param {string} cmd   The command name
 *
 * @return {yargs} Chaining!
 */
function setupYargs(yargs, cmd) {
    yargs
    .wrap(Math.min(120, yargs.terminalWidth()))
    .help('help').alias('help', 'h');

    if (cmd) {
        parsedCmd = cmd;

        yargs
        .usage(`Usage: ./$0 ${cmd} [options]`)
        .option('log-level', {
            type: 'string',
            default: 'warn',
            alias: 'll',
            describe: 'The log level to use (error, warn, info, verbose, etc.)',
        })
        .option('env-file', {
            type: 'string',
            default: '.env',
            alias: 'e',
            describe: 'The .env file to use',
        });
    } else {
        yargs.usage('Usage: ./$0 <cmd> [options]');
    }

    return yargs;
}

// CLI definition
const argv = setupYargs(yargs)
.demand(1, 1)
.command('observe', 'Starts observing module changes and pushes them into a queue', (yargs) => {
    setupYargs(yargs, 'observe')
    .option('default-seq', {
        type: 'number',
        default: 0,
        alias: 'ds',
        describe: 'The default seq to be used on first run',
    })
    .check((argv) => {
        assert(typeof argv.defaultSeq === 'number', 'Invalid argument: --default-seq must be a number');
        return true;
    });
})
.command('consume', 'Consumes modules from the queue, analyzing them', (yargs) => {
    setupYargs(yargs, 'consume')
    .option('concurrency', {
        type: 'number',
        default: 2,
        alias: 'c',
        describe: 'Number of modules to consume concurrently',
    })
    .check((argv) => {
        assert(typeof argv.concurrency === 'number', 'Invalid argument: --concurrency must be a number');
        return true;
    });
})
.argv;

if (!parsedCmd) {
    yargs.showHelp();
    process.stdout.write('Unknown command\n');
    process.exit(1);
}

// ----------------------------------------------------------------------------

// Configure logger
log.level = argv.loglevel;

// Process .env file
try {
    fs.accessSync(argv.envFile);
} catch (err) {
    if (err.code === 'ENOENT') {
        log.error('', `${path.resolve(argv.envFile)} does not exist`);
        process.exit(1);
    }

    throw err;
}

dotenv.config({ silent: true, path: argv.envFile });

// Run actual command
require(`./cmds/${parsedCmd}`);
<commit_msg>Fix --log-level.<commit_after>#!/usr/bin/env node

'use strict';

const fs = require('fs');
const path = require('path');
const assert = require('assert');
const yargs = require('yargs');
const dotenv = require('dotenv');
const log = require('npmlog');

let parsedCmd;

/**
 * Little utility function to setup common yargs stuff.
 *
 * @param {yargs}  yargs The yargs instance
 * @param {string} cmd   The command name
 *
 * @return {yargs} Chaining!
 */
function setupYargs(yargs, cmd) {
    yargs
    .wrap(Math.min(120, yargs.terminalWidth()))
    .help('help').alias('help', 'h');

    if (cmd) {
        parsedCmd = cmd;

        yargs
        .usage(`Usage: ./$0 ${cmd} [options]`)
        .option('log-level', {
            type: 'string',
            default: 'warn',
            alias: 'll',
            describe: 'The log level to use (error, warn, info, verbose, etc.)',
        })
        .option('env-file', {
            type: 'string',
            default: '.env',
            alias: 'e',
            describe: 'The .env file to use',
        });
    } else {
        yargs.usage('Usage: ./$0 <cmd> [options]');
    }

    return yargs;
}

// CLI definition
const argv = setupYargs(yargs)
.demand(1, 1)
.command('observe', 'Starts observing module changes and pushes them into a queue', (yargs) => {
    setupYargs(yargs, 'observe')
    .option('default-seq', {
        type: 'number',
        default: 0,
        alias: 'ds',
        describe: 'The default seq to be used on first run',
    })
    .check((argv) => {
        assert(typeof argv.defaultSeq === 'number', 'Invalid argument: --default-seq must be a number');
        return true;
    });
})
.command('consume', 'Consumes modules from the queue, analyzing them', (yargs) => {
    setupYargs(yargs, 'consume')
    .option('concurrency', {
        type: 'number',
        default: 2,
        alias: 'c',
        describe: 'Number of modules to consume concurrently',
    })
    .check((argv) => {
        assert(typeof argv.concurrency === 'number', 'Invalid argument: --concurrency must be a number');
        return true;
    });
})
.argv;

if (!parsedCmd) {
    yargs.showHelp();
    process.stdout.write('Unknown command\n');
    process.exit(1);
}

// ----------------------------------------------------------------------------

// Configure logger
log.level = argv.logLevel;

// Process .env file
try {
    fs.accessSync(argv.envFile);
} catch (err) {
    if (err.code === 'ENOENT') {
        log.error('', `${path.resolve(argv.envFile)} does not exist`);
        process.exit(1);
    }

    throw err;
}

dotenv.config({ silent: true, path: argv.envFile });

// Run actual command
require(`./cmds/${parsedCmd}`);
<|endoftext|>


<commit_before>#!/usr/bin/env node
;(function () { // wrapper in case we're in module_context mode
var log = require("./lib/utils/log")
log.waitForConfig()
log.info("ok", "it worked if it ends with")

var fs = require("./lib/utils/graceful-fs")
  , path = require("path")
  , sys = require("./lib/utils/sys")
  , npm = require("./npm")
  , ini = require("./lib/utils/ini")
  , rm = require("./lib/utils/rm-rf")
  , errorHandler = require("./lib/utils/error-handler")

  // supported commands.
  , argv = process.argv.slice(2)
  , arg = ""

  , conf = {}
  , key
  , arglist = []
  , command
  , flagsDone

log.verbose(argv, "cli")

while (arg = argv.shift()) {
  // FIXME: This is a mess right here.
  // FIXME: Add a "config.flags" somewhere for configs that don't take values
  // FIXME: Add config aliases for the shorthands and such.
  if (!key && (arg.match(/^-+[h?]$/i) || arg.match(/^-+help$/i))) {
    arg = "--usage"
  }
  if (!key && arg.match(/^-d+$/i)) {
    // -d --loglevel info
    // -dd --loglevel verbose
    // -ddd --loglevel silly
    key = "loglevel"
    switch (arg.length) {
      case 2: arg = "info"
        break
      case 3: arg = "verbose"
        break
      default: arg = "silly"
    }
  }
  if (!key && (arg.match(/^-+s$/) || arg.match(/^--silent$/))) {
    key = "loglevel"
    arg = "silent"
  } else if (!key && arg.match(/^--verbose$/)) {
    key = "loglevel"
    arg = "verbose"
  }
  if (!command && (npm.commands.hasOwnProperty(arg))) {
    if (key) {
      conf[key] = true
      key = null
    }
    command = arg
  } else if (!flagsDone && arg.substr(0, 2) === "--") {
    if (key) conf[key] = true
    key = arg.substr(2)
    if (key === "usage") conf[key] = true, key = null
    flagsDone = (key === "")
  } else if (key) {
    conf[key] = arg
    key = null
  } else arglist.push(arg)
}
if (key) conf[key] = true
if (conf.noreg) conf.registry = null
npm.argv = arglist

var vindex = arglist.indexOf("-v")
  , printVersion = vindex !== -1 || conf.version
if (printVersion) {
  console.log(npm.version)
  return
} else log("npm@"+npm.version, "using")
log("node@"+process.version, "using")

// make sure that this version of node works with this version of npm.
var semver = require("./lib/utils/semver")
  , nodeVer = process.version
  , reqVer = npm.nodeVersionRequired
if (reqVer && !semver.satisfies(nodeVer, reqVer)) {
  errorHandler(new Error(
    "npm doesn't work with node " + nodeVer + "\nRequired: node@" + reqVer), true)
}

process.on("uncaughtException", errorHandler)

if (!command) conf.usage = true

if (conf.usage && command !== "help") {
  arglist.unshift(command)
  command = "help"
}

// now actually fire up npm and run the command.
// this is how to use npm programmatically:
conf._exit = true
npm.load(conf, function (er) {
  if (er) return errorHandler(er)
  npm.commands[command](arglist, errorHandler)
})
})()
<commit_msg>Factor out the arg parsing<commit_after>#!/usr/bin/env node
;(function () { // wrapper in case we're in module_context mode
var log = require("./lib/utils/log")
log.waitForConfig()
log.info("ok", "it worked if it ends with")

var fs = require("./lib/utils/graceful-fs")
  , path = require("path")
  , sys = require("./lib/utils/sys")
  , npm = require("./npm")
  , ini = require("./lib/utils/ini")
  , rm = require("./lib/utils/rm-rf")
  , errorHandler = require("./lib/utils/error-handler")

  , argv = process.argv.slice(2)
  , parseArgs = require("./lib/utils/parse-args")

log.verbose(argv, "cli")

var conf = parseArgs(argv)
npm.argv = conf.argv.remain
if (-1 !== npm.fullList.indexOf(npm.argv[0])) {
  npm.command = npm.argv.shift()
}

if (conf.version) {
  console.log(npm.version)
  return
} else log("npm@"+npm.version, "using")
log("node@"+process.version, "using")

// make sure that this version of node works with this version of npm.
var semver = require("./lib/utils/semver")
  , nodeVer = process.version
  , reqVer = npm.nodeVersionRequired
if (reqVer && !semver.satisfies(nodeVer, reqVer)) {
  return errorHandler(new Error(
    "npm doesn't work with node " + nodeVer
    + "\nRequired: node@" + reqVer), true)
}

process.on("uncaughtException", errorHandler)

if (conf.usage && npm.command && npm.command !== "help") {
  npm.argv.unshift(npm.command)
  npm.command = "help"
}

// now actually fire up npm and run the command.
// this is how to use npm programmatically:
conf._exit = true
npm.load(conf, function (er) {
  if (er) return errorHandler(er)
  npm.commands[npm.command](npm.argv, errorHandler)
})
})()
<|endoftext|>


<commit_before>#!/usr/bin/env node

var fs = require('fs'),
  colors = require('colors'),
  username = require('username'),
  autostart = require('./lib/index.js'),
  argv = require('yargs')
  .usage('Usage: $0 <command> [options]')
  .command('enable', 'Enable autostart here with a custom key', function(yargs) {
    argv = yargs
      .option('n', {
        demand: true,
        alias: 'name',
        describe: 'Name of the key for identifying startup objecst',
        type: 'string',
        nargs: 1
      })
      .option('c', {
        demand: false,
        alias: 'command',
        describe: 'Command to execute in the path',
        type: 'string',
        default: 'npm start'
      })
      .option('p', {
        demand: false,
        alias: 'path',
        describe: 'Place of execution of command',
        type: 'string',
        default: process.cwd()
      })
      .help('h')
      .alias('h', 'help')
      .showHelpOnFail(false, 'Use --help for further information')
      .argv;

    autostart.enableAutostart(argv.n, argv.c, argv.p, function(err) {
      if (err) {
        console.error('An error occured while trying to enable autostart, here are the details:');
        console.error(err);
        process.exit(1);
      }

      console.log('Done!');
      process.exit(0);
    });
  })
  .command('disable', 'Disable autostart with key', function(yargs) {
    argv = yargs
      .option('n', {
        demand: true,
        alias: 'name',
        describe: 'Name of the key for identifying startup objecst',
        type: 'string',
        nargs: 1
      })
      .help('h')
      .alias('h', 'help')
      .showHelpOnFail(false, 'Use --help for further information')
      .argv;

    autostart.disableAutostart(argv.n, function(err) {
      if (err) {
        console.error('An error occured while trying to disable autostart, here are the details:');
        console.error(err);
        process.exit(1);
      }

      console.log('Done!');
      process.exit(0);
    });
  })
  .command('check', 'Check if autostart is enabled by key', function(yargs) {
    argv = yargs
      .option('n', {
        demand: true,
        alias: 'name',
        describe: 'Name of the key for identifying startup objects',
        type: 'string',
        nargs: 1
      })
      .help('h')
      .alias('h', 'help')
      .showHelpOnFail(false, 'Use --help for further information')
      .argv;

    autostart.isAutostartEnabled(argv.n, function(isEnabled, err) {
      if (err) {
        console.error('An error occured while trying to check if autostart is enabled, here are the details:');
        console.error(err);
        process.exit(1);
      }

      console.log("Done!");
      if (isEnabled) {
        console.log('Autostart is enabled');
        process.exit(0);
      } else if (!isEnabled) {
        console.log('Autostart is not enabled');
        process.exit(0);
      }
    });
  })
  .command('doctor', 'See all enabled autostart services', function(yargs) {
    argv = yargs
      .help('h')
      .alias('h', 'help')
      .showHelpOnFail(false, 'Use --help for further information')
      .argv;

    try {
      fs.statSync((process.env.HOME || process.env.USERPROFILE) + '/.autostart.json');
    } catch (e) {
      console.error('No .autostart file for the user ' + username.sync() + ' found. Aborting.');
      process.exit(1);
    }

    var services = JSON.parse(fs.readFileSync((process.env.HOME || process.env.USERPROFILE) + '/.autostart.json', 'utf-8'));

    console.log('These services are currently active:\n');

    Object.keys(services).forEach(function(key) {
      console.log(('"' + key + '":').inverse + (' ' + services[key]).green);
    });
  })
  .demand(1)
  .help('h')
  .alias('h', 'help')
  .showHelpOnFail(false, 'Use --help for further information')
  .argv;
<commit_msg>Update CLI beahviour<commit_after>#!/usr/bin/env node

var fs = require('fs'),
  colors = require('colors'),
  username = require('username'),
  autostart = require('./lib/index.js'),
  argv = require('yargs')
  .usage('Usage: $0 <command> [options]')
  .command('enable', 'Enable autostart here with a custom key', function(yargs) {
    argv = yargs
      .option('n', {
        demand: true,
        alias: 'name',
        describe: 'Name of the key for identifying startup objecst',
        type: 'string',
        nargs: 1
      })
      .option('c', {
        demand: false,
        alias: 'command',
        describe: 'Command to execute in the path',
        type: 'string',
        default: 'npm start'
      })
      .option('p', {
        demand: false,
        alias: 'path',
        describe: 'Place of execution of command',
        type: 'string',
        default: process.cwd()
      })
      .help('h')
      .alias('h', 'help')
      .showHelpOnFail(false, 'Use --help for further information')
      .argv;

    autostart.enableAutostart(argv.n, argv.c, argv.p, function(err) {
      if (err) {
        console.error('An error occured while trying to enable autostart, here are the details:');
        console.error(err);
        process.exit(1);
      }

      console.log('Done!');
      process.exit(0);
    });
  })
  .command('disable', 'Disable autostart with key', function(yargs) {
    argv = yargs
      .option('n', {
        demand: true,
        alias: 'name',
        describe: 'Name of the key for identifying startup objecst',
        type: 'string',
        nargs: 1
      })
      .help('h')
      .alias('h', 'help')
      .showHelpOnFail(false, 'Use --help for further information')
      .argv;

    autostart.disableAutostart(argv.n, function(err) {
      if (err) {
        console.error('An error occured while trying to disable autostart, here are the details:');
        console.error(err);
        process.exit(1);
      }

      console.log('Done!');
      process.exit(0);
    });
  })
  .command('check', 'Check if autostart is enabled by key', function(yargs) {
    argv = yargs
      .option('n', {
        demand: true,
        alias: 'name',
        describe: 'Name of the key for identifying startup objects',
        type: 'string',
        nargs: 1
      })
      .help('h')
      .alias('h', 'help')
      .showHelpOnFail(false, 'Use --help for further information')
      .argv;

    autostart.isAutostartEnabled(argv.n, function(isEnabled, err) {
      if (err) {
        console.error('An error occured while trying to check if autostart is enabled, here are the details:');
        console.error(err);
        process.exit(1);
      }

      console.log("Done!");
      if (isEnabled) {
        console.log('Autostart is enabled');
        process.exit(0);
      } else if (!isEnabled) {
        console.log('Autostart is not enabled');
        process.exit(0);
      }
    });
  })
  .command('doctor', 'See all enabled autostart services', function(yargs) {
    argv = yargs
      .help('h')
      .alias('h', 'help')
      .showHelpOnFail(false, 'Use --help for further information')
      .argv;

    try {
      fs.statSync((process.env.HOME || process.env.USERPROFILE) + '/.autostart.json');
    } catch (e) {
      console.error('No .autostart file for the user ' + username.sync() + ' found. Aborting.');
      process.exit(1);
    }

    var services = JSON.parse(fs.readFileSync((process.env.HOME || process.env.USERPROFILE) + '/.autostart.json', 'utf-8'));

    if(!Object.keys(services).length) {
      console.log('No services enabled.'.red);
      process.exit(0);
    }

    console.log('These services are currently active:');

    Object.keys(services).forEach(function(key) {
      console.log(('"' + key + '":').inverse + (' ' + services[key]).green);
    });
  })
  .demand(1)
  .help('h')
  .alias('h', 'help')
  .showHelpOnFail(false, 'Use --help for further information')
  .argv;
<|endoftext|>


<commit_before>/*!
 * nodist
 * A Node version manager for the windows folks out there.
 * Copyright 2012 by Marcel Klehr <mklehr@gmx.net>
 *
 * (MIT LICENSE)
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

var version = process.argv[2]
  , nodist   = require('./lib/nodist')
  , path     = require('path')
  , fs       = require('fs')
;

// Exit with a code and (optionally) with a message
var exit = function exit(code, msg) {
  if(msg) console.log(msg);
  process.exit(code);
};

// Abort with an optional message being displayed
var abort = function abort(msg) {
  exit(1, !msg? null : msg.split('. ').join('.\r\n'));
};

// Display the command line help and exit
function help() {
  fs.readFile(__dirname+'\\usage.txt', function(err, usage) {
    if(err) abort('Couldn\'t fetch help info. You\'ll have to look at the README. Sorry.');
    console.log(usage.toString());
    exit();
  });
}

process.title = 'nodist';

// set up the necessary paths
var nodePath = process.env['NODIST_PREFIX'];
var wantX64 = process.env['NODIST_X64'];
var nodistPath = __dirname;
// set up proxy
var proxy = (process.env.HTTP_PROXY || process.env.http_proxy || process.env.HTTPS_PROXY || process.env.https_proxy || "");

// Create a nodist instance
var n = new nodist(
  'http://nodejs.org/dist',
  (nodePath? nodePath : nodistPath)+'\\v',
  proxy.replace("https://", "http://") //replace https for http, nodejs.org/dist doesnt support https
  ,wantX64
);

// Parse args
argv = process.argv.splice(2);
argv.remainder = [];
if(argv.indexOf('--') !== -1) {
  argv.remainder = argv.splice(argv.indexOf('--')).slice(1);
}
args = argv.join(' ');
command = argv[0];

// -V Display nodist version
if (args.match(/-v/i) !== null) {
  console.log(require('./package.json').version);
  exit();
}

// --HELP Display help
if (args.match(/--help/i)) {
  help();
}

// (bare call of 'nodist') -> list
if (!argv[0]) {
  command = 'list';
}

// LIST all installed buids
if (command.match(/^list|ls$/i)) {

  nodist.determineVersion(__dirname+'\\bin\\node.exe', function (err, current) {
    if(err) void(0); //don't bother, if we don't know current version

    n.listInstalled(function(err, ls) {
      if(err) abort(err.message+'. Sorry.');
      if(ls.length == 0) abort('No builds installed, yet.');

      // display all versions
      ls.forEach(function(version) {
        var del = (version == current) ? '> ' : '  ';// highlight current
        console.log(del+version);
      });
      exit();
    });
  });
}else

// DIST list all available buids
if (command.match(/^dist|ds$/i)) {

  n.listAvailable(function(err, ls) {
    if(err) abort(err.message+'. Sorry.');
    if(ls.length == 0) abort('No builds available. Strange...');

    // display all versions
    ls.forEach(function(version) {
      console.log('  '+version);
    });
    exit();
  });

}else

// ADD fetch a specific build
if ((command.match(/^add|\+$/i)) && argv[1]) {
  var version = argv[1];

  if(version.match(/^all$/i)) {
    n.installAll(function(err, real_version) {
      if(err) return console.log(err.message+'.');
      console.log('Installed '+real_version);
    });
  }else
  {
    n.resolveVersion(version, function(er, v) {
      if(er) abort(er.message+'. Sorry.');
      n.install(v, function(err) {
        if(err) abort(err.message+'. Sorry.');
        console.log(v);
        exit();
      });
    })
  }
}else

// REMOVE an installed build
if (command.match(/^remove|rm|-$/i) && argv[1]) {
  var version = argv[1];

  n.resolveVersion(version, function(er, v) {
    if(er) abort(er.message+'. Sorry.');
    n.remove(v, function() {
      exit();
    });
  });
}else

// RUN a specific build
if (command.match(/^run|r$/i) && argv[1]) {
  var version = argv[1];

  n.resolveVersion(version, function(er, v) {
    if(er) abort(er.message+'. Sorry.');
    n.emulate(v, argv.remainder, function(err, code) {
      if(err) abort(err.message+'. Sorry.');
      exit(code);
    });
  });
}else

// BIN get the path to a specific version
if (command.match(/^bin$/i) && argv[1]) {
  var version = argv[1];

  n.resolveVersion(version, function(er, v) {
    if(er) abort(er.message+'. Sorry.');
    n.install(version, function(err) {
      if(err) abort(err.message+'. Sorry.');
      console.log(n.getPathToExe(v));
      exit();
    });
  });
}else

// PATH get the directory of a specific version to be added to the path
if (command.match(/^path$/i) && argv[1]) {
  var version = argv[1];

  n.resolveVersion(version, function(er, v) {
    if(er) abort(er.message+'. Sorry.');
    n.install(version, function(err, v) {
      if(err) abort(err.message+'. Sorry.');
      console.log(path.dirname(n.getPathToExe(v)));
    });
  });
}else

// DEPLOY globally use the specified node version
if (argv[0]) {
  var version = argv[0];

  n.resolveVersion(version, function(er, v) {
    if(er) abort(er.message+'. Sorry.');
    n.deploy(v, function(err) {
      if(err) abort(err.message+'. Sorry.');
      console.log(v);
      exit();
    });
  });
}else

// HELP display help for unknown cli parameters
{
  help();
}<commit_msg>Fix 'path' and 'bin' commands<commit_after>/*!
 * nodist
 * A Node version manager for the windows folks out there.
 * Copyright 2012 by Marcel Klehr <mklehr@gmx.net>
 *
 * (MIT LICENSE)
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

var version = process.argv[2]
  , nodist   = require('./lib/nodist')
  , path     = require('path')
  , fs       = require('fs')
;

// Exit with a code and (optionally) with a message
var exit = function exit(code, msg) {
  if(msg) console.log(msg);
  process.exit(code);
};

// Abort with an optional message being displayed
var abort = function abort(msg) {
  exit(1, !msg? null : msg.split('. ').join('.\r\n'));
};

// Display the command line help and exit
function help() {
  fs.readFile(__dirname+'\\usage.txt', function(err, usage) {
    if(err) abort('Couldn\'t fetch help info. You\'ll have to look at the README. Sorry.');
    console.log(usage.toString());
    exit();
  });
}

process.title = 'nodist';

// set up the necessary paths
var nodePath = process.env['NODIST_PREFIX'];
var wantX64 = process.env['NODIST_X64'];
var nodistPath = __dirname;
// set up proxy
var proxy = (process.env.HTTP_PROXY || process.env.http_proxy || process.env.HTTPS_PROXY || process.env.https_proxy || "");

// Create a nodist instance
var n = new nodist(
  'http://nodejs.org/dist',
  (nodePath? nodePath : nodistPath)+'\\v',
  proxy.replace("https://", "http://") //replace https for http, nodejs.org/dist doesnt support https
  ,wantX64
);

// Parse args
argv = process.argv.splice(2);
argv.remainder = [];
if(argv.indexOf('--') !== -1) {
  argv.remainder = argv.splice(argv.indexOf('--')).slice(1);
}
args = argv.join(' ');
command = argv[0];

// -V Display nodist version
if (args.match(/-v/i) !== null) {
  console.log(require('./package.json').version);
  exit();
}

// --HELP Display help
if (args.match(/--help/i)) {
  help();
}

// (bare call of 'nodist') -> list
if (!argv[0]) {
  command = 'list';
}

// LIST all installed buids
if (command.match(/^list|ls$/i)) {

  nodist.determineVersion(__dirname+'\\bin\\node.exe', function (err, current) {
    if(err) void(0); //don't bother, if we don't know current version

    n.listInstalled(function(err, ls) {
      if(err) abort(err.message+'. Sorry.');
      if(ls.length == 0) abort('No builds installed, yet.');

      // display all versions
      ls.forEach(function(version) {
        var del = (version == current) ? '> ' : '  ';// highlight current
        console.log(del+version);
      });
      exit();
    });
  });
}else

// DIST list all available buids
if (command.match(/^dist|ds$/i)) {

  n.listAvailable(function(err, ls) {
    if(err) abort(err.message+'. Sorry.');
    if(ls.length == 0) abort('No builds available. Strange...');

    // display all versions
    ls.forEach(function(version) {
      console.log('  '+version);
    });
    exit();
  });

}else

// ADD fetch a specific build
if ((command.match(/^add|\+$/i)) && argv[1]) {
  var version = argv[1];

  if(version.match(/^all$/i)) {
    n.installAll(function(err, real_version) {
      if(err) return console.log(err.message+'.');
      console.log('Installed '+real_version);
    });
  }else
  {
    n.resolveVersion(version, function(er, v) {
      if(er) abort(er.message+'. Sorry.');
      n.install(v, function(err) {
        if(err) abort(err.message+'. Sorry.');
        console.log(v);
        exit();
      });
    })
  }
}else

// REMOVE an installed build
if (command.match(/^remove|rm|-$/i) && argv[1]) {
  var version = argv[1];

  n.resolveVersion(version, function(er, v) {
    if(er) abort(er.message+'. Sorry.');
    n.remove(v, function() {
      exit();
    });
  });
}else

// RUN a specific build
if (command.match(/^run|r$/i) && argv[1]) {
  var version = argv[1];

  n.resolveVersion(version, function(er, v) {
    if(er) abort(er.message+'. Sorry.');
    n.emulate(v, argv.remainder, function(err, code) {
      if(err) abort(err.message+'. Sorry.');
      exit(code);
    });
  });
}else

// BIN get the path to a specific version
if (command.match(/^bin$/i) && argv[1]) {
  var version = argv[1];

  n.resolveVersion(version, function(er, v) {
    if(er) abort(er.message+'. Sorry.');
    n.install(v, function(err) {
      if(err) abort(err.message+'. Sorry.');
      console.log(n.getPathToExe(v));
      exit();
    });
  });
}else

// PATH get the directory of a specific version to be added to the path
if (command.match(/^path$/i) && argv[1]) {
  var version = argv[1];

  n.resolveVersion(version, function(er, v) {
    if(er) abort(er.message+'. Sorry.');
    n.install(v, function(err, v) {
      if(err) abort(err.message+'. Sorry.');
      console.log(path.dirname(n.getPathToExe(v)));
    });
  });
}else

// DEPLOY globally use the specified node version
if (argv[0]) {
  var version = argv[0];

  n.resolveVersion(version, function(er, v) {
    if(er) abort(er.message+'. Sorry.');
    n.deploy(v, function(err) {
      if(err) abort(err.message+'. Sorry.');
      console.log(v);
      exit();
    });
  });
}else

// HELP display help for unknown cli parameters
{
  help();
}<|endoftext|>


<commit_before>'use strict';

var async = require('async');
var cleancss = require('clean-css');
var spawn = require('child_process').spawn;
var findit = require('findit');
var fs = require('fs');
var jade = require('jade');
var marked = require('marked');
var mkdirp = require('mkdirp');
var path = require('path');
var uglifyjs = require('uglify-js');
var util = require('util');

var styledocco = require('./styledocco');

var version = require('./package').version;

marked.setOptions({ sanitize: false, gfm: true });

// Helper functions
var mincss = function(css) { return cleancss.process(css); };
var minjs = uglifyjs;
var pluck = function(arr, prop) {
  return arr.map(function(item) { return item[prop]; });
};

var isType = function(o, type) {
    return Object.prototype.toString.call(o) === '[object ' + type + ']';
};

var flatten = function(arr) {
  return arr.reduce(function(tot, cur) {
    return tot.concat(isArray(cur) ? flatten(cur) : cur);
  }, []);
};
var inArray = function(arr, str) { return arr.indexOf(str) !== -1; };
var isArray = function(obj) { return isType(obj, 'Array'); };
var isString = function(obj) { return isType(obj, 'String'); };

var urlsRelative = function(css, path) {
    if (isString(css) && isString(path)) {
        path = path.indexOf('/', path.length -1) > -1? path : path + '/';
        var regex = /(url\(["']?)(?!data:)([^/'"][\w/.]*)/gm;
        return css.replace(regex, "$1" + path + "$2");
    } else {
        throw new Error('1st and 2nd args must be strings.');
    }
};

var dirUp = function(steps) {
    if ( ! steps) return '';
    var str = '';
    for (var i = 0; i < steps; ++i) {
        str += '../';
    }
    return str;
};

// Get a filename without the extension
var baseFilename = function(str) {
  return path.basename(str, path.extname(str)).replace(/^_/, '');
};

var basePathname = function(file, basePath) {
  return path.join(
    path.dirname(path.relative(basePath, file) || path.basename(basePath)),
    baseFilename(file)
  );
};

// Build an HTML file name, named by it's path relative to basePath
var htmlFilename = function(file, basePath) {
  return path.join(
    path.dirname(path.relative(basePath, file) || path.basename(basePath)),
    baseFilename(file) + '.html'
  ).replace(/[\\/]/g, '-');
};

// Find first file matching `re` in `dir`.
var findFile = function(dir, re, cb) {
  fs.stat(dir, function(err, stat) {
    var files = fs.readdir(dir, function(err, files) {
      files = files.sort().filter(function(file) { return file.match(re); });
      if (!files.length) cb(new Error('No file found.'));
      else cb(null, path.join(dir, files[0]));
    });
  });
};

var getFiles = function(inPath, cb) {
  fs.stat(inPath, function(err, stat) {
    if (err != null) return cb(err);
    if (stat.isFile()) {
      cb(null, [ inPath ]);
    } else {
      var finder = findit.find(inPath);
      var files = [];
      finder.on('file', function(file) { files.push(file); });
      finder.on('end', function() { cb(null, files); });
    }
  });
};

// Make `link` objects for the menu.
var menuLinks = function(files, basePath) {
  return files.map(function(file) {
    var parts = path.relative(basePath, file).split('/');
    parts.pop(); // Remove filename
    return {
      name: baseFilename(file),
      href: htmlFilename(file, basePath),
      directory: parts[parts.length-1] || './'
    };
  })
  .reduce(function(links, link) {
    if (links[link.directory] != null) {
      links[link.directory].push(link);
    } else {
      links[link.directory] = [ link ];
    }
    return links;
  }, {});
};

var preprocess = function(file, pp, options, cb) {
  // stdin would have been nice here, but not all preprocessors (less)
  // accepts that, so we need to read the file both here and for the parser.
  // Don't process SASS partials.
  if (file.match(/(^|\/)_.*\.s(c|a)ss$/) != null) {
    process.nextTick(function() { cb(null, ''); });
  } else if (pp != null) {
    pp += ' ';
    pp += file;
    pp = pp.split(' ');
    pp = spawn(pp.shift(), pp);

    pp.stderr.setEncoding('utf8');
    pp.stdout.setEncoding('utf8');

    var stdout = '';

    pp.on('error', function(err) {
      if (err != null && options.verbose) console.error(err.message);
    });

    pp.on('close', function() {
      cb(null, stdout);
    });

    pp.stderr.on('data', function(data) {
      if (data.length && options.verbose) console.error(data);
    });

    pp.stdout.on('data', function(data) {
      stdout += data;
    });
  } else {
    fs.readFile(file, 'utf8', cb);
  }
};

var cli = function(options) {

  var errorMessages = { noFiles: 'No css files found' };
  var resourcesDir = __dirname + '/share/';

  // Filetypes and matching preprocessor binaries.
  var fileTypes = {
    '.css': null,
    '.sass': 'sass',
    '.scss': 'scss',
    '.less': 'lessc',
    '.styl': 'stylus'
  };

  var log = options.verbose ? function(str) { console.log(str); }
                            : function() {};

  // Custom error also outputing StyleDocco and Node versions.
  var SDError = function(msg, err) {
    this.message = msg + '\n' + err.message + '\n' +
      'StyleDocco v' + version +
      ' running on Node ' + process.version + ' ' + process.platform;
    if (options.verbose) {
      this.message += '\nOptions: ' + JSON.stringify(options);
    }
  };
  util.inherits(SDError, Error);

  mkdirp(options.out);

  // Fetch all static resources.
  async.parallel({
    template: function(cb) {
      fs.readFile(resourcesDir + 'docs.jade', 'utf8', function(err, contents) {
        if (err != null) return cb(err);
        cb(null, jade.compile(contents));
      });
    },
    docs: function(cb) {
      async.parallel({
        css: async.apply(fs.readFile, resourcesDir + 'docs.css', 'utf8'),
        js: function(cb) {
          async.parallel([
            async.apply(fs.readFile, resourcesDir + 'docs.ui.js', 'utf8'),
            async.apply(fs.readFile, resourcesDir + 'docs.previews.js', 'utf8')
          ], function(err, res) {
            if (err != null) return cb(err);
            cb(null, res.join(''));
          });
        }
      }, cb);
    },
    // Extra JavaScript and CSS files to include in previews.
    previews: function(cb) {
      fs.readFile(resourcesDir + 'previews.js', 'utf8', function(err, js) {
        if (err != null) return cb(err);
        var code = { js: js, css: '' };
        var files = options.include.filter(function(file) {
          return inArray(['.css', '.js'], path.extname(file));
        });
        async.filter(files, path.exists, function(files) {
          async.reduce(files, code, function(tot, cur, cb) {
            fs.readFile(cur, 'utf8', function(err, contents) {
              if (err != null) return cb(err);
              tot[path.extname(cur).slice(1)] += contents;
              cb(null, tot);
            });
          }, cb);
        });
      });
    },
    // Find input files.
    files: function(cb) {
      async.reduce(options['in'], [], function(all, cur, cb) {
        getFiles(cur, function(err, files) {
          if (err != null) return cb(err);
          cb(null, all.concat(files));
        });
      }, function(err, files) {
        if (err != null) return cb(err);
        files = files.filter(function(file) {
          // No hidden files
          if (file.match(/(\/|^)\.[^\.\/]/)) return false;
          // Only supported file types
          if (!(path.extname(file) in fileTypes)) return false;
          return true;
        }).sort();
        if (!files.length) cb(new Error(errorMessages.noFiles + ' in path "' + options['in'] + '"'));
        cb(null, files);
      });
    },
    // Look for a README file.
    readme: function(cb) {
      findFile(options.basePath, /^readme\.m(ark)?d(own)?/i, function(err, file) {
        if (file != null && err == null) return read(file);
        findFile(process.cwd(), /^readme\.m(ark)?d(own)?/i, function(err, file) {
          if (err != null) file = resourcesDir + 'README.md';
          read(file);
        });
      });
      var read = function(file) {
        fs.readFile(file, 'utf8', function(err, content) {
          if (err != null) cb(err);
          cb(null, content);
        });
      };
    }
  }, function(err, resources) {
    if (err != null) {
      if (err.message.indexOf(errorMessages.noFiles) > -1) {
        console.error(err);
        return;
      } else {
        throw new SDError('Could not process files.', err);
      }
    }
    var menu = menuLinks(resources.files, options.basePath);
    // Run files through preprocessor and StyleDocco parser.
    async.map(resources.files, function(file, cb) {
      async.parallel({
        css: async.apply(preprocess, file,
               options.preprocessor || fileTypes[path.extname(file)], options),
        docs: function(cb) {
          fs.readFile(file, 'utf8', function(err, code) {
            if (err != null) return cb(err);
            cb(null, styledocco(code));
          });
        }
      }, function(err, data) {
        if (err != null) return cb(err);
        data.path = file;
        cb(null, data);
      });
    }, function(err, files) {
      if (err != null) throw err;
      // Get the combined CSS from all files.
      var previewStyles = pluck(files, 'css').join('');
      previewStyles += resources.previews.css;
      // Build a JSON string of all files and their headings, for client side search.
      var searchIndex = flatten(files.map(function(file) {
        var arr = [ { title: baseFilename(file.path),
                      filename: basePathname(file.path, options.basePath),
                      url: htmlFilename(file.path, options.basePath) } ];
        return arr.concat(file.docs.map(function(section) {
          return { title: section.title,
                   filename: basePathname(file.path, options.basePath),
                   url: htmlFilename(file.path, options.basePath) + '#' + section.slug };
        }));
      }));
      searchIndex = 'var searchIndex=' + JSON.stringify(searchIndex) + ';';
      var docsScript = '(function(){' + searchIndex + resources.docs.js + '})();';
      // Render files
      var htmlFiles = files.map(function(file) {
      var relativePath = file.path.split('/');
      relativePath.pop();
      relativePath = dirUp(options.out.split('/').length) + relativePath.join('/');
        return {
          path: file.path,
          html: resources.template({
            title: baseFilename(file.path),
            sections: file.docs,
            project: { name: options.name, menu: menu },
            resources: {
              docs: { js: minjs(docsScript), css: mincss(resources.docs.css) },
              previews: { js: minjs(resources.previews.js), css: mincss(urlsRelative(previewStyles, relativePath)) }
            }
          })
        };
      });
      // Add readme with "fake" index path.
      htmlFiles.push({
        path: path.join(options.basePath, 'index'),
        html: resources.template({
          title: '',
          sections: styledocco.makeSections([{ docs: resources.readme, code: '' }]),
          project: { name: options.name, menu: menu },
          resources: {
            docs: { js: minjs(docsScript), css: mincss(resources.docs.css) }
          }
        })
      });
      // Write files to the output dir.
      htmlFiles.forEach(function(file) {
        var dest = path.join(options.out, htmlFilename(file.path, options.basePath));
        log('styledocco: writing ' + file.path + ' -> ' + dest);
        fs.writeFileSync(dest, file.html);
      });
    });
  });
};

module.exports = cli;
module.exports.htmlFilename = htmlFilename;
module.exports.menuLinks = menuLinks;
module.exports.urlsRelative = urlsRelative;
module.exports.preprocess = preprocess;
<commit_msg>replaced path.exists with fs.exists<commit_after>'use strict';

var async = require('async');
var cleancss = require('clean-css');
var spawn = require('child_process').spawn;
var findit = require('findit');
var fs = require('fs');
var jade = require('jade');
var marked = require('marked');
var mkdirp = require('mkdirp');
var path = require('path');
var uglifyjs = require('uglify-js');
var util = require('util');

var styledocco = require('./styledocco');

var version = require('./package').version;

marked.setOptions({ sanitize: false, gfm: true });

// Helper functions
var mincss = function(css) { return cleancss.process(css); };
var minjs = uglifyjs;
var pluck = function(arr, prop) {
  return arr.map(function(item) { return item[prop]; });
};

var isType = function(o, type) {
    return Object.prototype.toString.call(o) === '[object ' + type + ']';
};

var flatten = function(arr) {
  return arr.reduce(function(tot, cur) {
    return tot.concat(isArray(cur) ? flatten(cur) : cur);
  }, []);
};
var inArray = function(arr, str) { return arr.indexOf(str) !== -1; };
var isArray = function(obj) { return isType(obj, 'Array'); };
var isString = function(obj) { return isType(obj, 'String'); };

var urlsRelative = function(css, path) {
    if (isString(css) && isString(path)) {
        path = path.indexOf('/', path.length -1) > -1? path : path + '/';
        var regex = /(url\(["']?)(?!data:)([^/'"][\w/.]*)/gm;
        return css.replace(regex, "$1" + path + "$2");
    } else {
        throw new Error('1st and 2nd args must be strings.');
    }
};

var dirUp = function(steps) {
    if ( ! steps) return '';
    var str = '';
    for (var i = 0; i < steps; ++i) {
        str += '../';
    }
    return str;
};

// Get a filename without the extension
var baseFilename = function(str) {
  return path.basename(str, path.extname(str)).replace(/^_/, '');
};

var basePathname = function(file, basePath) {
  return path.join(
    path.dirname(path.relative(basePath, file) || path.basename(basePath)),
    baseFilename(file)
  );
};

// Build an HTML file name, named by it's path relative to basePath
var htmlFilename = function(file, basePath) {
  return path.join(
    path.dirname(path.relative(basePath, file) || path.basename(basePath)),
    baseFilename(file) + '.html'
  ).replace(/[\\/]/g, '-');
};

// Find first file matching `re` in `dir`.
var findFile = function(dir, re, cb) {
  fs.stat(dir, function(err, stat) {
    var files = fs.readdir(dir, function(err, files) {
      files = files.sort().filter(function(file) { return file.match(re); });
      if (!files.length) cb(new Error('No file found.'));
      else cb(null, path.join(dir, files[0]));
    });
  });
};

var getFiles = function(inPath, cb) {
  fs.stat(inPath, function(err, stat) {
    if (err != null) return cb(err);
    if (stat.isFile()) {
      cb(null, [ inPath ]);
    } else {
      var finder = findit.find(inPath);
      var files = [];
      finder.on('file', function(file) { files.push(file); });
      finder.on('end', function() { cb(null, files); });
    }
  });
};

// Make `link` objects for the menu.
var menuLinks = function(files, basePath) {
  return files.map(function(file) {
    var parts = path.relative(basePath, file).split('/');
    parts.pop(); // Remove filename
    return {
      name: baseFilename(file),
      href: htmlFilename(file, basePath),
      directory: parts[parts.length-1] || './'
    };
  })
  .reduce(function(links, link) {
    if (links[link.directory] != null) {
      links[link.directory].push(link);
    } else {
      links[link.directory] = [ link ];
    }
    return links;
  }, {});
};

var preprocess = function(file, pp, options, cb) {
  // stdin would have been nice here, but not all preprocessors (less)
  // accepts that, so we need to read the file both here and for the parser.
  // Don't process SASS partials.
  if (file.match(/(^|\/)_.*\.s(c|a)ss$/) != null) {
    process.nextTick(function() { cb(null, ''); });
  } else if (pp != null) {
    pp += ' ';
    pp += file;
    pp = pp.split(' ');
    pp = spawn(pp.shift(), pp);

    pp.stderr.setEncoding('utf8');
    pp.stdout.setEncoding('utf8');

    var stdout = '';

    pp.on('error', function(err) {
      if (err != null && options.verbose) console.error(err.message);
    });

    pp.on('close', function() {
      cb(null, stdout);
    });

    pp.stderr.on('data', function(data) {
      if (data.length && options.verbose) console.error(data);
    });

    pp.stdout.on('data', function(data) {
      stdout += data;
    });
  } else {
    fs.readFile(file, 'utf8', cb);
  }
};

var cli = function(options) {

  var errorMessages = { noFiles: 'No css files found' };
  var resourcesDir = __dirname + '/share/';

  // Filetypes and matching preprocessor binaries.
  var fileTypes = {
    '.css': null,
    '.sass': 'sass',
    '.scss': 'scss',
    '.less': 'lessc',
    '.styl': 'stylus'
  };

  var log = options.verbose ? function(str) { console.log(str); }
                            : function() {};

  // Custom error also outputing StyleDocco and Node versions.
  var SDError = function(msg, err) {
    this.message = msg + '\n' + err.message + '\n' +
      'StyleDocco v' + version +
      ' running on Node ' + process.version + ' ' + process.platform;
    if (options.verbose) {
      this.message += '\nOptions: ' + JSON.stringify(options);
    }
  };
  util.inherits(SDError, Error);

  mkdirp(options.out);

  // Fetch all static resources.
  async.parallel({
    template: function(cb) {
      fs.readFile(resourcesDir + 'docs.jade', 'utf8', function(err, contents) {
        if (err != null) return cb(err);
        cb(null, jade.compile(contents));
      });
    },
    docs: function(cb) {
      async.parallel({
        css: async.apply(fs.readFile, resourcesDir + 'docs.css', 'utf8'),
        js: function(cb) {
          async.parallel([
            async.apply(fs.readFile, resourcesDir + 'docs.ui.js', 'utf8'),
            async.apply(fs.readFile, resourcesDir + 'docs.previews.js', 'utf8')
          ], function(err, res) {
            if (err != null) return cb(err);
            cb(null, res.join(''));
          });
        }
      }, cb);
    },
    // Extra JavaScript and CSS files to include in previews.
    previews: function(cb) {
      fs.readFile(resourcesDir + 'previews.js', 'utf8', function(err, js) {
        if (err != null) return cb(err);
        var code = { js: js, css: '' };
        var files = options.include.filter(function(file) {
          return inArray(['.css', '.js'], path.extname(file));
        });
        async.filter(files, fs.exists, function(files) {
          async.reduce(files, code, function(tot, cur, cb) {
            fs.readFile(cur, 'utf8', function(err, contents) {
              if (err != null) return cb(err);
              tot[path.extname(cur).slice(1)] += contents;
              cb(null, tot);
            });
          }, cb);
        });
      });
    },
    // Find input files.
    files: function(cb) {
      async.reduce(options['in'], [], function(all, cur, cb) {
        getFiles(cur, function(err, files) {
          if (err != null) return cb(err);
          cb(null, all.concat(files));
        });
      }, function(err, files) {
        if (err != null) return cb(err);
        files = files.filter(function(file) {
          // No hidden files
          if (file.match(/(\/|^)\.[^\.\/]/)) return false;
          // Only supported file types
          if (!(path.extname(file) in fileTypes)) return false;
          return true;
        }).sort();
        if (!files.length) cb(new Error(errorMessages.noFiles + ' in path "' + options['in'] + '"'));
        cb(null, files);
      });
    },
    // Look for a README file.
    readme: function(cb) {
      findFile(options.basePath, /^readme\.m(ark)?d(own)?/i, function(err, file) {
        if (file != null && err == null) return read(file);
        findFile(process.cwd(), /^readme\.m(ark)?d(own)?/i, function(err, file) {
          if (err != null) file = resourcesDir + 'README.md';
          read(file);
        });
      });
      var read = function(file) {
        fs.readFile(file, 'utf8', function(err, content) {
          if (err != null) cb(err);
          cb(null, content);
        });
      };
    }
  }, function(err, resources) {
    if (err != null) {
      if (err.message.indexOf(errorMessages.noFiles) > -1) {
        console.error(err);
        return;
      } else {
        throw new SDError('Could not process files.', err);
      }
    }
    var menu = menuLinks(resources.files, options.basePath);
    // Run files through preprocessor and StyleDocco parser.
    async.map(resources.files, function(file, cb) {
      async.parallel({
        css: async.apply(preprocess, file,
               options.preprocessor || fileTypes[path.extname(file)], options),
        docs: function(cb) {
          fs.readFile(file, 'utf8', function(err, code) {
            if (err != null) return cb(err);
            cb(null, styledocco(code));
          });
        }
      }, function(err, data) {
        if (err != null) return cb(err);
        data.path = file;
        cb(null, data);
      });
    }, function(err, files) {
      if (err != null) throw err;
      // Get the combined CSS from all files.
      var previewStyles = pluck(files, 'css').join('');
      previewStyles += resources.previews.css;
      // Build a JSON string of all files and their headings, for client side search.
      var searchIndex = flatten(files.map(function(file) {
        var arr = [ { title: baseFilename(file.path),
                      filename: basePathname(file.path, options.basePath),
                      url: htmlFilename(file.path, options.basePath) } ];
        return arr.concat(file.docs.map(function(section) {
          return { title: section.title,
                   filename: basePathname(file.path, options.basePath),
                   url: htmlFilename(file.path, options.basePath) + '#' + section.slug };
        }));
      }));
      searchIndex = 'var searchIndex=' + JSON.stringify(searchIndex) + ';';
      var docsScript = '(function(){' + searchIndex + resources.docs.js + '})();';
      // Render files
      var htmlFiles = files.map(function(file) {
      var relativePath = file.path.split('/');
      relativePath.pop();
      relativePath = dirUp(options.out.split('/').length) + relativePath.join('/');
        return {
          path: file.path,
          html: resources.template({
            title: baseFilename(file.path),
            sections: file.docs,
            project: { name: options.name, menu: menu },
            resources: {
              docs: { js: minjs(docsScript), css: mincss(resources.docs.css) },
              previews: { js: minjs(resources.previews.js), css: mincss(urlsRelative(previewStyles, relativePath)) }
            }
          })
        };
      });
      // Add readme with "fake" index path.
      htmlFiles.push({
        path: path.join(options.basePath, 'index'),
        html: resources.template({
          title: '',
          sections: styledocco.makeSections([{ docs: resources.readme, code: '' }]),
          project: { name: options.name, menu: menu },
          resources: {
            docs: { js: minjs(docsScript), css: mincss(resources.docs.css) }
          }
        })
      });
      // Write files to the output dir.
      htmlFiles.forEach(function(file) {
        var dest = path.join(options.out, htmlFilename(file.path, options.basePath));
        log('styledocco: writing ' + file.path + ' -> ' + dest);
        fs.writeFileSync(dest, file.html);
      });
    });
  });
};

module.exports = cli;
module.exports.htmlFilename = htmlFilename;
module.exports.menuLinks = menuLinks;
module.exports.urlsRelative = urlsRelative;
module.exports.preprocess = preprocess;
<|endoftext|>