git-cz
Version:
Semantic emojified git commit, git-cz.
1,960 lines (1,601 loc) โข 1.41 MB
JavaScript
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
const chalk = require('chalk');
const InputPrompt = require('inquirer/lib/prompts/input');
class LimitedInputPrompt extends InputPrompt {
constructor (...args) {
super(...args);
if (!this.opt.maxLength) {
this.throwParamError('maxLength');
}
this.originalMessage = this.opt.message;
this.spacer = new Array(this.opt.maxLength).fill('-').join('');
if (this.opt.leadingLabel) {
if (typeof this.opt.leadingLabel === 'function') {
this.leadingLabel = ' ' + this.opt.leadingLabel(this.answers);
} else {
this.leadingLabel = ' ' + this.opt.leadingLabel;
}
} else {
this.leadingLabel = '';
}
this.leadingLength = this.leadingLabel.length;
}
remainingChar () {
return this.opt.maxLength - this.leadingLength - this.rl.line.length;
}
onKeypress () {
if (this.rl.line.length > this.opt.maxLength - this.leadingLength) {
this.rl.line = this.rl.line.slice(0, this.opt.maxLength - this.leadingLength);
this.rl.cursor--;
}
this.render();
}
getCharsLeftText () {
const chars = this.remainingChar();
if (chars > 15) {
return chalk.green(`${chars} chars left`);
} else if (chars > 5) {
return chalk.yellow(`${chars} chars left`);
} else {
return chalk.red(`${chars} chars left`);
}
}
render (error) {
let bottomContent = '';
let message = this.getQuestion();
let appendContent = '';
const isFinal = this.status === 'answered';
if (isFinal) {
appendContent = this.answer;
} else {
appendContent = this.rl.line;
}
message = `${message}
[${this.spacer}] ${this.getCharsLeftText()}
${this.leadingLabel} ${appendContent}`;
if (error) {
bottomContent = chalk.red('>> ') + error;
}
this.screen.render(message, bottomContent);
}
}
module.exports = LimitedInputPrompt;
},{"chalk":41,"inquirer/lib/prompts/input":116}],2:[function(require,module,exports){
const {spawn, execSync} = require('child_process');
const fs = require('fs');
const {join} = require('path');
const shellescape = require('any-shell-escape');
const signale = require('signale');
const parseArgs = require('./parseArgs');
const createState = require('./createState');
const runInteractiveQuestions = require('./runInteractiveQuestions');
const runNonInteractiveMode = require('./runNonInteractiveMode');
const formatCommitMessage = require('./formatCommitMessage');
const getGitDir = require('./util/getGitDir');
// eslint-disable-next-line no-process-env
const executeCommand = (command, env = process.env) => {
const proc = spawn(command, [], {
env,
shell: true,
stdio: [0, 1, 2]
});
proc.on('close', (code) => {
// eslint-disable-next-line no-process-exit
process.exit(code);
});
};
// eslint-disable-next-line complexity
const main = async () => {
try {
const {cliAnswers, cliOptions, passThroughParams} = parseArgs();
let state = null;
if (cliOptions.disableEmoji) {
state = createState({disableEmoji: cliOptions.disableEmoji});
} else {
state = createState();
}
if (cliOptions.dryRun) {
// eslint-disable-next-line no-console
console.log('Running in dry mode.');
} else if (
!passThroughParams['allow-empty'] &&
!passThroughParams.a &&
!passThroughParams.amend
) {
try {
/**
* @author https://github.com/rodrigograca31
* @see https://github.com/streamich/git-cz/issues/177
*
* Exits with 1 if there are differences and 0 if no differences.
*/
execSync('git diff HEAD --staged --quiet --exit-code');
// Executes the following line only if the one above didn't crash (exit code: 0)
signale.error('No files staged!');
// eslint-disable-next-line no-process-exit
process.exit(0);
} catch (error) {
// eslint-disable no-empty
}
}
if (cliOptions.nonInteractive) {
await runNonInteractiveMode(state, cliAnswers);
} else {
await runInteractiveQuestions(state, cliAnswers);
}
const message = formatCommitMessage(state);
const appendedArgs = [];
// eslint-disable-next-line guard-for-in
for (const key in passThroughParams) {
const value = passThroughParams[key];
if (key.length === 1) {
appendedArgs.push('-' + key);
} else {
appendedArgs.push('--' + key);
}
if (value !== true) {
appendedArgs.push(value);
}
}
const commitMsgFile = join(getGitDir(), 'COMMIT_EDITMSG');
const command = shellescape([
'git',
'commit',
'--file',
commitMsgFile,
...appendedArgs
]);
if (cliOptions.dryRun) {
// eslint-disable-next-line no-console
console.log('Will execute command:');
// The full path is replaced with a relative path to make the test pass on every machine
// eslint-disable-next-line no-console
console.log(command.replace(commitMsgFile, '.git/COMMIT_EDITMSG'));
// eslint-disable-next-line no-console
console.log('Message:');
// eslint-disable-next-line no-console
console.log(message);
} else {
fs.writeFileSync(commitMsgFile, message);
/**
* @author https://github.com/oxyii
* @see https://github.com/streamich/git-cz/issues/79
*/
if (cliOptions.hook) {
// eslint-disable-next-line no-process-exit
process.exit(0);
}
executeCommand(command);
}
} catch (error) {
signale.fatal(error);
}
};
main();
},{"./createState":4,"./formatCommitMessage":6,"./parseArgs":8,"./runInteractiveQuestions":16,"./runNonInteractiveMode":17,"./util/getGitDir":18,"any-shell-escape":23,"child_process":undefined,"fs":undefined,"path":undefined,"signale":564}],3:[function(require,module,exports){
/* eslint-disable import/no-dynamic-require, global-require */
const qBody = require('./questions/body');
const qBreaking = require('./questions/breaking');
const qIssues = require('./questions/issues');
const qLerna = require('./questions/lerna');
const qScope = require('./questions/scope');
const qSubject = require('./questions/subject');
const qType = require('./questions/type');
const creators = {
body: qBody,
breaking: qBreaking,
issues: qIssues,
lerna: qLerna,
scope: qScope,
subject: qSubject,
type: qType
};
const createQuestions = (state, cliAnswers) => {
const questions = state.config.questions
.filter((name) => cliAnswers[name] === undefined)
.map((name) => {
const question = creators[name].createQuestion(state);
if (state.config.messages && state.config.messages[name]) {
question.message = state.config.messages[name];
}
return question;
});
return questions.filter(Boolean);
};
module.exports = createQuestions;
},{"./questions/body":9,"./questions/breaking":10,"./questions/issues":11,"./questions/lerna":12,"./questions/scope":13,"./questions/subject":14,"./questions/type":15}],4:[function(require,module,exports){
const getGitRootDir = require('./util/getGitRootDir');
const getConfig = require('./getConfig');
const createState = (config = {}) => {
let root;
try {
root = getGitRootDir();
} catch (error) {
throw new Error('Could not find Git root folder.');
}
const state = {
answers: {
body: '',
breaking: '',
issues: '',
lerna: '',
scope: '',
subject: '',
type: ''
},
config: {
...getConfig(root),
...config
},
root
};
return state;
};
module.exports = createState;
},{"./getConfig":7,"./util/getGitRootDir":19}],5:[function(require,module,exports){
const format = '{type}{scope}: {emoji}{subject}';
const types = {
chore: {
description: 'Build process or auxiliary tool changes',
emoji: '๐ค',
value: 'chore'
},
ci: {
description: 'CI related changes',
emoji: '๐ก',
value: 'ci'
},
docs: {
description: 'Documentation only changes',
emoji: 'โ๏ธ',
value: 'docs'
},
feat: {
description: 'A new feature',
emoji: '๐ธ',
value: 'feat'
},
fix: {
description: 'A bug fix',
emoji: '๐',
value: 'fix'
},
perf: {
description: 'A code change that improves performance',
emoji: 'โก๏ธ',
value: 'perf'
},
refactor: {
description: 'A code change that neither fixes a bug or adds a feature',
emoji: '๐ก',
value: 'refactor'
},
release: {
description: 'Create a release commit',
emoji: '๐น',
value: 'release'
},
style: {
description: 'Markup, white-space, formatting, missing semi-colons...',
emoji: '๐',
value: 'style'
},
test: {
description: 'Adding missing tests',
emoji: '๐',
value: 'test'
}
};
// https://github.com/angular/angular/blob/master/CONTRIBUTING.md#type
const list = [
'test',
'feat',
'fix',
'chore',
'docs',
'refactor',
'style',
'ci',
'perf'
];
// https://github.com/angular/angular/blob/master/CONTRIBUTING.md#scope
const scopes = [];
const questions = [
'type',
'scope',
'subject',
'body',
'breaking',
'issues',
'lerna'
];
module.exports = {
breakingChangePrefix: '๐งจ ',
closedIssueMessage: 'Closes: ',
closedIssuePrefix: 'โ
',
format,
list,
maxMessageLength: 64,
minMessageLength: 3,
questions,
scopes,
types
};
},{}],6:[function(require,module,exports){
/* eslint-disable complexity */
const wrap = require('word-wrap');
const MAX_LINE_WIDTH = 72;
const makeAffectsLine = function (answers) {
const selectedPackages = answers.packages;
if (selectedPackages && selectedPackages.length) {
return `\naffects: ${selectedPackages.join(', ')}`;
}
return '';
};
const formatCommitMessage = (state) => {
const {config, answers} = state;
const wrapOptions = {
indent: '',
trim: true,
width: MAX_LINE_WIDTH
};
const emoji = config.types[answers.type].emoji;
const scope = answers.scope ? '(' + answers.scope.trim() + ')' : '';
const subject = answers.subject.trim();
const type = answers.type;
const format = config.format || '{type}{scope}: {emoji}{subject}';
const affectsLine = makeAffectsLine(answers);
// Wrap these lines at MAX_LINE_WIDTH character
const body = wrap((answers.body || '') + affectsLine, wrapOptions);
const breaking = wrap(answers.breaking, wrapOptions);
const issues = wrap(answers.issues, wrapOptions);
// @note(emoji) Add space after emoji (breakingChangePrefix/closedIssueEmoji)
const head = format
.replace(/\{emoji\}/g, config.disableEmoji ? '' : emoji + ' ')
.replace(/\{scope\}/g, scope)
.replace(/\{subject\}/g, subject)
.replace(/\{type\}/g, type);
let msg = head;
if (body) {
msg += '\n\n' + body;
}
if (breaking) {
const breakingEmoji = config.disableEmoji ? '' : config.breakingChangePrefix;
msg += '\n\nBREAKING CHANGE: ' + breakingEmoji + breaking;
}
if (issues) {
const closedIssueEmoji = config.disableEmoji ? '' : config.closedIssuePrefix;
msg += '\n\n' + closedIssueEmoji + config.closedIssueMessage + issues;
}
return msg;
};
module.exports = formatCommitMessage;
},{"word-wrap":587}],7:[function(require,module,exports){
/* eslint-disable global-require, import/no-dynamic-require */
const path = require('path');
const fs = require('fs');
const signale = require('signale');
const defaults = require('./defaults');
const configFiles = [
'.git-cz.json',
'changelog.config.js',
'changelog.config.cjs',
'changelog.config.json'
];
const findOverrides = (root) => {
const dir = root || process.cwd();
for (const file of configFiles) {
const filename = path.resolve(dir, file);
if (fs.existsSync(filename) && fs.statSync(filename).isFile()) {
return require(filename);
}
}
const parent = path.resolve(dir, '..');
const pkgFilename = path.join(dir, 'package.json');
if (fs.existsSync(pkgFilename)) {
try {
const changelog = require(pkgFilename).config.commitizen.changelog;
if (changelog) {
return changelog;
}
// eslint-disable-next-line no-empty
} catch (error) {}
}
if (parent !== dir) {
return findOverrides(parent);
}
return {};
};
const getConfig = (root) => {
const overrides = findOverrides(root);
if (typeof overrides !== 'object') {
signale.fatal(new TypeError('Expected changelog config to be an object.'));
// eslint-disable-next-line no-process-exit
process.exit(1);
}
return {
...defaults,
...overrides
};
};
module.exports = getConfig;
},{"./defaults":5,"fs":undefined,"path":undefined,"signale":564}],8:[function(require,module,exports){
/* eslint-disable no-process-exit */
/* eslint-disable no-console */
/* eslint-disable id-length */
const minimist = require('minimist');
const pkg = require('../package.json');
const helpScreen = `
${pkg.description}
Usage: git-cz [options]
options:
-h, --help show usage information
-v, --version print version info and exit
--disable-emoji don't add emoji to commit title
--format custom formatting options for subject
--non-interactive run git-cz in non-interactive mode
non-interactive mode options:
--type type of the commit, defaults to "chore"
--subject message of the commit, defaults to "automated commit"
--scope semantic commit scope
--body extended description of the commit
--breaking description of breaking changes, if any
--issues GitHub issues this commit closed, e.g "#123"
--lerna Lerna mono-repo packages this commit affects
`;
const parseArgs = () => {
const {
// eslint-disable-next-line no-unused-vars
_: inputs,
'dry-run': dryRun,
hook,
'disable-emoji': disableEmoji,
format,
'non-interactive': nonInteractive,
body,
breaking,
issues,
lerna,
scope,
subject,
type,
help,
h,
version,
v,
...passThroughParams
} = minimist(process.argv.slice(2), {
alias: {
h: 'help',
v: 'version'
},
boolean: [
'version',
'help',
'disable-emoji',
'non-interactive',
'hook',
'dry-run'
],
string: [
'format',
'type',
'subject',
'scope',
'body',
'breaking',
'issues',
'learna'
]
});
if (help || h) {
console.log(helpScreen);
process.exit();
}
if (version || v) {
console.log(pkg.version);
process.exit();
}
const cliOptions = {
disableEmoji,
dryRun,
format,
help,
hook,
nonInteractive,
version
};
const cliAnswers = {
body,
breaking,
issues,
lerna,
scope,
subject,
type
};
return {
cliAnswers,
cliOptions,
passThroughParams
};
};
module.exports = parseArgs;
},{"../package.json":589,"minimist":319}],9:[function(require,module,exports){
exports.createQuestion = () => {
const question = {
message: 'Provide a longer description of the change:\n ',
name: 'body',
type: 'input'
};
return question;
};
},{}],10:[function(require,module,exports){
const chalk = require('chalk');
exports.createQuestion = () => {
const question = {
message: `List any breaking changes\n ${chalk.red('BREAKING CHANGE')}:`,
name: 'breaking',
type: 'input'
};
return question;
};
},{"chalk":41}],11:[function(require,module,exports){
exports.createQuestion = () => ({
message: 'Issues this commit closes, e.g #123:',
name: 'issues',
type: 'input'
});
},{}],12:[function(require,module,exports){
const {getAllPackages, getChangedPackages, isLerna} = require('../util/lerna');
exports.createQuestion = (state) => {
if (!isLerna(state)) {
return null;
}
const changedPackages = getChangedPackages(state);
const allPackages = getAllPackages(state);
const question = {
choices: allPackages,
default: changedPackages,
message: `The packages that this commit has affected (${changedPackages.length} detected)\n`,
name: 'packages',
type: 'checkbox'
};
return question;
};
},{"../util/lerna":20}],13:[function(require,module,exports){
const fuzzy = require('fuzzy');
/**
* Searches for the scopes containing the given substring.
*
* @param {string} substring Substring to search with.
* @param {string[]} scopes Scopes list.
*/
const findScope = function (substring, scopes) {
return Promise.resolve(fuzzy.filter(substring || '', scopes).map(({original: scope}) => scope));
};
exports.createQuestion = (state) => {
const {scopes} = state.config;
if (!scopes) {
return null;
}
if (!Array.isArray(scopes)) {
throw new TypeError('scopes must be an array of strings.');
}
if (scopes.length < 1) {
return null;
}
const question = {
message: 'Select the scope this component affects:',
name: 'scope',
source: (_answers, input) => findScope(input, scopes),
type: 'autocomplete'
};
return question;
};
},{"fuzzy":71}],14:[function(require,module,exports){
exports.createQuestion = (state) => {
const {config} = state;
const minTitleLengthErrorMessage = `The subject must have at least ${config.minMessageLength} characters`;
const question = {
filter: (input) => {
let subject;
subject = input.trim();
while (subject.endsWith('.')) {
subject = subject.substr(0, subject.length - 1).trim();
}
return subject;
},
leadingLabel: (answers) => {
let scope = '';
if (answers.scope && answers.scope !== 'none') {
scope = `(${answers.scope})`;
}
return `${state.answers.type || answers.type}${scope}:`;
},
// Minus 3 chars are for emoji + space.
maxLength: config.maxMessageLength - 3,
message: 'Write a short, imperative mood description of the change:',
name: 'subject',
type: 'limitedInput',
validate: (input) => input.length >= config.minMessageLength || minTitleLengthErrorMessage
};
return question;
};
},{}],15:[function(require,module,exports){
const fuzzy = require('fuzzy');
const typeToListItem = ({types, disableEmoji}, type) => {
const {description, emoji, value} = types[type];
const prefix = emoji && !disableEmoji ? emoji + ' ' : '';
return {
name: prefix + (value + ':').padEnd(12, ' ') + description,
value
};
};
/**
* Searches for the type that includes the given substring.
*
* @param {string} substring Substring to search with.
* @param {string[]} config The whole config.
*/
const findType = function (substring, config) {
const types = config.list;
return Promise.resolve(fuzzy.filter(substring || '', types).map(({original: type}) => typeToListItem(config, type)));
};
exports.createQuestion = (state) => {
const {config} = state;
const question = {
message: 'Select the type of change that you\'re committing:',
name: 'type',
source: (_answers, input) => findType(input, config),
type: 'autocomplete'
};
return question;
};
},{"fuzzy":71}],16:[function(require,module,exports){
const inquirer = require('inquirer');
const AutocompletePrompt = require('inquirer-list-search-prompt');
const LimitedInputPrompt = require('./LimitedInputPrompt');
const createQuestions = require('./createQuestions');
inquirer.registerPrompt('limitedInput', LimitedInputPrompt);
inquirer.registerPrompt('autocomplete', AutocompletePrompt);
// if (IS_LERNA_PROJECT) {
// const allPackages = getAllPackages().map((pkg) => pkg.name);
// const changedPackages = getChangedPackages();
//
// promptQuestions = promptQuestions.concat(createPackagesQuestion(allPackages, changedPackages));
// }
const runInteractiveQuestions = async (state, cliAnswers = {}) => {
Object.keys(cliAnswers).forEach((key) => {
state.answers[key] = cliAnswers[key];
});
const questions = createQuestions(state, cliAnswers);
const answers = await inquirer.prompt(questions);
Object.keys(state.answers).forEach((key) => {
if (answers[key]) {
state.answers[key] = answers[key];
}
});
return answers;
};
module.exports = runInteractiveQuestions;
},{"./LimitedInputPrompt":1,"./createQuestions":3,"inquirer":107,"inquirer-list-search-prompt":96}],17:[function(require,module,exports){
const runNonInteractiveMode = (state, {type = 'chore', subject = 'automated commit', ...restAnswers}) => {
const answers = {
subject,
type,
...restAnswers
};
Object.keys(state.answers).forEach((key) => {
if (answers[key]) {
state.answers[key] = answers[key];
delete answers[key];
}
});
};
module.exports = runNonInteractiveMode;
},{}],18:[function(require,module,exports){
const {execSync} = require('child_process');
const getGitDir = () => {
const devNull = process.platform === 'win32' ? ' nul' : '/dev/null';
const dir = execSync('git rev-parse --absolute-git-dir 2>' + devNull)
.toString()
.trim();
return dir;
};
module.exports = getGitDir;
},{"child_process":undefined}],19:[function(require,module,exports){
const {execSync} = require('child_process');
const getGitRootDir = () => {
const devNull = process.platform === 'win32' ? ' nul' : '/dev/null';
const dir = execSync('git rev-parse --show-toplevel 2>' + devNull)
.toString()
.trim();
return dir;
};
module.exports = getGitRootDir;
},{"child_process":undefined}],20:[function(require,module,exports){
const {execSync} = require('child_process');
const path = require('path');
const fs = require('fs');
const isLerna = (state) =>
fs.existsSync(path.join(state.root, 'lerna.json'));
const isDir = (root) => (name) => {
const filepath = path.join(root, name);
try {
const stats = fs.statSync(filepath);
return stats.isDirectory();
} catch (error) {
return false;
}
};
const removeLastDirectoryPartOf = (url) => url.substring(0, url.lastIndexOf('/'));
const getPackageDirectories = (state) => {
const pkgFilename = path.join(state.root, 'package.json');
if (fs.existsSync(pkgFilename)) {
try {
const workspacesConfig = require(String(pkgFilename)).workspaces;
const workspacePackages = Array.isArray(workspacesConfig) ? workspacesConfig : workspacesConfig.packages;
if (workspacePackages && workspacePackages.length) {
return workspacePackages
.filter((workspacePackage) => workspacePackage.endsWith('*'))
.map((workspacePackage) =>
removeLastDirectoryPartOf(String(workspacePackage))
// else {
// TODO: support paths that do not end with '*', in that case the package it self is the directory so we don't need to look at inner directories
// return workspacePackage
// }
);
// Remove the /* on the tail
}
// eslint-disable-next-line no-empty
} catch (error) {
}
}
return 'packages';
};
const getAllPackages = (state) => {
try {
const dirs = getPackageDirectories(state).map((dir) => path.join(state.root, dir));
return dirs.flatMap((dir) => fs.readdirSync(dir).filter(isDir(dir)));
} catch (error) {
return [];
}
};
const getChangedFiles = () => {
const devNull = process.platform === 'win32' ? ' nul' : '/dev/null';
return execSync('git diff --cached --name-only 2>' + devNull)
.toString()
.trim()
.split('\n');
};
const getChangedPackages = (state) => {
const unique = {};
const changedFiles = getChangedFiles();
const regex = new RegExp('^' + getPackageDirectories(state) + '\/([^/]+)\/', 'is');
for (const filename of changedFiles) {
const matches = filename.match(regex);
if (matches) {
unique[matches[1]] = 1;
}
}
return Object.keys(unique);
};
module.exports = {
getAllPackages,
getChangedPackages,
isLerna
};
},{"child_process":undefined,"fs":undefined,"path":undefined}],21:[function(require,module,exports){
'use strict';
const ansiEscapes = module.exports;
// TODO: remove this in the next major version
module.exports.default = ansiEscapes;
const ESC = '\u001B[';
const OSC = '\u001B]';
const BEL = '\u0007';
const SEP = ';';
const isTerminalApp = process.env.TERM_PROGRAM === 'Apple_Terminal';
ansiEscapes.cursorTo = (x, y) => {
if (typeof x !== 'number') {
throw new TypeError('The `x` argument is required');
}
if (typeof y !== 'number') {
return ESC + (x + 1) + 'G';
}
return ESC + (y + 1) + ';' + (x + 1) + 'H';
};
ansiEscapes.cursorMove = (x, y) => {
if (typeof x !== 'number') {
throw new TypeError('The `x` argument is required');
}
let ret = '';
if (x < 0) {
ret += ESC + (-x) + 'D';
} else if (x > 0) {
ret += ESC + x + 'C';
}
if (y < 0) {
ret += ESC + (-y) + 'A';
} else if (y > 0) {
ret += ESC + y + 'B';
}
return ret;
};
ansiEscapes.cursorUp = (count = 1) => ESC + count + 'A';
ansiEscapes.cursorDown = (count = 1) => ESC + count + 'B';
ansiEscapes.cursorForward = (count = 1) => ESC + count + 'C';
ansiEscapes.cursorBackward = (count = 1) => ESC + count + 'D';
ansiEscapes.cursorLeft = ESC + 'G';
ansiEscapes.cursorSavePosition = isTerminalApp ? '\u001B7' : ESC + 's';
ansiEscapes.cursorRestorePosition = isTerminalApp ? '\u001B8' : ESC + 'u';
ansiEscapes.cursorGetPosition = ESC + '6n';
ansiEscapes.cursorNextLine = ESC + 'E';
ansiEscapes.cursorPrevLine = ESC + 'F';
ansiEscapes.cursorHide = ESC + '?25l';
ansiEscapes.cursorShow = ESC + '?25h';
ansiEscapes.eraseLines = count => {
let clear = '';
for (let i = 0; i < count; i++) {
clear += ansiEscapes.eraseLine + (i < count - 1 ? ansiEscapes.cursorUp() : '');
}
if (count) {
clear += ansiEscapes.cursorLeft;
}
return clear;
};
ansiEscapes.eraseEndLine = ESC + 'K';
ansiEscapes.eraseStartLine = ESC + '1K';
ansiEscapes.eraseLine = ESC + '2K';
ansiEscapes.eraseDown = ESC + 'J';
ansiEscapes.eraseUp = ESC + '1J';
ansiEscapes.eraseScreen = ESC + '2J';
ansiEscapes.scrollUp = ESC + 'S';
ansiEscapes.scrollDown = ESC + 'T';
ansiEscapes.clearScreen = '\u001Bc';
ansiEscapes.clearTerminal = process.platform === 'win32' ?
`${ansiEscapes.eraseScreen}${ESC}0f` :
// 1. Erases the screen (Only done in case `2` is not supported)
// 2. Erases the whole screen including scrollback buffer
// 3. Moves cursor to the top-left position
// More info: https://www.real-world-systems.com/docs/ANSIcode.html
`${ansiEscapes.eraseScreen}${ESC}3J${ESC}H`;
ansiEscapes.beep = BEL;
ansiEscapes.link = (text, url) => {
return [
OSC,
'8',
SEP,
SEP,
url,
BEL,
text,
OSC,
'8',
SEP,
SEP,
BEL
].join('');
};
ansiEscapes.image = (buffer, options = {}) => {
let ret = `${OSC}1337;File=inline=1`;
if (options.width) {
ret += `;width=${options.width}`;
}
if (options.height) {
ret += `;height=${options.height}`;
}
if (options.preserveAspectRatio === false) {
ret += ';preserveAspectRatio=0';
}
return ret + ':' + buffer.toString('base64') + BEL;
};
ansiEscapes.iTerm = {
setCwd: (cwd = process.cwd()) => `${OSC}50;CurrentDir=${cwd}${BEL}`,
annotation: (message, options = {}) => {
let ret = `${OSC}1337;`;
const hasX = typeof options.x !== 'undefined';
const hasY = typeof options.y !== 'undefined';
if ((hasX || hasY) && !(hasX && hasY && typeof options.length !== 'undefined')) {
throw new Error('`x`, `y` and `length` must be defined when `x` or `y` is defined');
}
message = message.replace(/\|/g, '');
ret += options.isHidden ? 'AddHiddenAnnotation=' : 'AddAnnotation=';
if (options.length > 0) {
ret +=
(hasX ?
[message, options.length, options.x, options.y] :
[options.length, message]).join('|');
} else {
ret += message;
}
return ret + BEL;
}
};
},{}],22:[function(require,module,exports){
'use strict';
const wrapAnsi16 = (fn, offset) => (...args) => {
const code = fn(...args);
return `\u001B[${code + offset}m`;
};
const wrapAnsi256 = (fn, offset) => (...args) => {
const code = fn(...args);
return `\u001B[${38 + offset};5;${code}m`;
};
const wrapAnsi16m = (fn, offset) => (...args) => {
const rgb = fn(...args);
return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`;
};
const ansi2ansi = n => n;
const rgb2rgb = (r, g, b) => [r, g, b];
const setLazyProperty = (object, property, get) => {
Object.defineProperty(object, property, {
get: () => {
const value = get();
Object.defineProperty(object, property, {
value,
enumerable: true,
configurable: true
});
return value;
},
enumerable: true,
configurable: true
});
};
/** @type {typeof import('color-convert')} */
let colorConvert;
const makeDynamicStyles = (wrap, targetSpace, identity, isBackground) => {
if (colorConvert === undefined) {
colorConvert = require('color-convert');
}
const offset = isBackground ? 10 : 0;
const styles = {};
for (const [sourceSpace, suite] of Object.entries(colorConvert)) {
const name = sourceSpace === 'ansi16' ? 'ansi' : sourceSpace;
if (sourceSpace === targetSpace) {
styles[name] = wrap(identity, offset);
} else if (typeof suite === 'object') {
styles[name] = wrap(suite[targetSpace], offset);
}
}
return styles;
};
function assembleStyles() {
const codes = new Map();
const styles = {
modifier: {
reset: [0, 0],
// 21 isn't widely supported and 22 does the same thing
bold: [1, 22],
dim: [2, 22],
italic: [3, 23],
underline: [4, 24],
inverse: [7, 27],
hidden: [8, 28],
strikethrough: [9, 29]
},
color: {
black: [30, 39],
red: [31, 39],
green: [32, 39],
yellow: [33, 39],
blue: [34, 39],
magenta: [35, 39],
cyan: [36, 39],
white: [37, 39],
// Bright color
blackBright: [90, 39],
redBright: [91, 39],
greenBright: [92, 39],
yellowBright: [93, 39],
blueBright: [94, 39],
magentaBright: [95, 39],
cyanBright: [96, 39],
whiteBright: [97, 39]
},
bgColor: {
bgBlack: [40, 49],
bgRed: [41, 49],
bgGreen: [42, 49],
bgYellow: [43, 49],
bgBlue: [44, 49],
bgMagenta: [45, 49],
bgCyan: [46, 49],
bgWhite: [47, 49],
// Bright color
bgBlackBright: [100, 49],
bgRedBright: [101, 49],
bgGreenBright: [102, 49],
bgYellowBright: [103, 49],
bgBlueBright: [104, 49],
bgMagentaBright: [105, 49],
bgCyanBright: [106, 49],
bgWhiteBright: [107, 49]
}
};
// Alias bright black as gray (and grey)
styles.color.gray = styles.color.blackBright;
styles.bgColor.bgGray = styles.bgColor.bgBlackBright;
styles.color.grey = styles.color.blackBright;
styles.bgColor.bgGrey = styles.bgColor.bgBlackBright;
for (const [groupName, group] of Object.entries(styles)) {
for (const [styleName, style] of Object.entries(group)) {
styles[styleName] = {
open: `\u001B[${style[0]}m`,
close: `\u001B[${style[1]}m`
};
group[styleName] = styles[styleName];
codes.set(style[0], style[1]);
}
Object.defineProperty(styles, groupName, {
value: group,
enumerable: false
});
}
Object.defineProperty(styles, 'codes', {
value: codes,
enumerable: false
});
styles.color.close = '\u001B[39m';
styles.bgColor.close = '\u001B[49m';
setLazyProperty(styles.color, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, false));
setLazyProperty(styles.color, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, false));
setLazyProperty(styles.color, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, false));
setLazyProperty(styles.bgColor, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, true));
setLazyProperty(styles.bgColor, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, true));
setLazyProperty(styles.bgColor, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, true));
return styles;
}
// Make the export immutable
Object.defineProperty(module, 'exports', {
enumerable: true,
get: assembleStyles
});
},{"color-convert":57}],23:[function(require,module,exports){
var util = require('util'),
winCmd = /^win/.test(process.platform),
escapePath;
function escapePathSh(path) {
if (!/^[A-Za-z0-9_\/-]+$/.test(path))
return ("'" + path.replace(/'/g, "'\"'\"'") + "'").replace(/''/g, '');
else
return path;
}
function escapePathWin(path) {
if (!/^[A-Za-z0-9_\/-]+$/.test(path))
return '"' + path.replace(/"/g, '""') + '"';
else
return path;
}
if (winCmd) {
escapePath = escapePathWin;
} else {
escapePath = escapePathSh;
}
module.exports = function(stringOrArray) {
var ret = [];
if (typeof(stringOrArray) == 'string') {
return escapePath(stringOrArray);
} else {
stringOrArray.forEach(function(member) {
ret.push(escapePath(member));
});
return ret.join(' ');
}
};
if (winCmd) {
// Cannot escape messages on windows
module.exports.msg = function(x) {
if (typeof(x) == 'string') {
return x;
} else {
return x.join(' ');
}
};
} else {
module.exports.msg = module.exports;
}
},{"util":undefined}],24:[function(require,module,exports){
'use strict'
const { Buffer } = require('buffer')
const symbol = Symbol.for('BufferList')
function BufferList (buf) {
if (!(this instanceof BufferList)) {
return new BufferList(buf)
}
BufferList._init.call(this, buf)
}
BufferList._init = function _init (buf) {
Object.defineProperty(this, symbol, { value: true })
this._bufs = []
this.length = 0
if (buf) {
this.append(buf)
}
}
BufferList.prototype._new = function _new (buf) {
return new BufferList(buf)
}
BufferList.prototype._offset = function _offset (offset) {
if (offset === 0) {
return [0, 0]
}
let tot = 0
for (let i = 0; i < this._bufs.length; i++) {
const _t = tot + this._bufs[i].length
if (offset < _t || i === this._bufs.length - 1) {
return [i, offset - tot]
}
tot = _t
}
}
BufferList.prototype._reverseOffset = function (blOffset) {
const bufferId = blOffset[0]
let offset = blOffset[1]
for (let i = 0; i < bufferId; i++) {
offset += this._bufs[i].length
}
return offset
}
BufferList.prototype.get = function get (index) {
if (index > this.length || index < 0) {
return undefined
}
const offset = this._offset(index)
return this._bufs[offset[0]][offset[1]]
}
BufferList.prototype.slice = function slice (start, end) {
if (typeof start === 'number' && start < 0) {
start += this.length
}
if (typeof end === 'number' && end < 0) {
end += this.length
}
return this.copy(null, 0, start, end)
}
BufferList.prototype.copy = function copy (dst, dstStart, srcStart, srcEnd) {
if (typeof srcStart !== 'number' || srcStart < 0) {
srcStart = 0
}
if (typeof srcEnd !== 'number' || srcEnd > this.length) {
srcEnd = this.length
}
if (srcStart >= this.length) {
return dst || Buffer.alloc(0)
}
if (srcEnd <= 0) {
return dst || Buffer.alloc(0)
}
const copy = !!dst
const off = this._offset(srcStart)
const len = srcEnd - srcStart
let bytes = len
let bufoff = (copy && dstStart) || 0
let start = off[1]
// copy/slice everything
if (srcStart === 0 && srcEnd === this.length) {
if (!copy) {
// slice, but full concat if multiple buffers
return this._bufs.length === 1
? this._bufs[0]
: Buffer.concat(this._bufs, this.length)
}
// copy, need to copy individual buffers
for (let i = 0; i < this._bufs.length; i++) {
this._bufs[i].copy(dst, bufoff)
bufoff += this._bufs[i].length
}
return dst
}
// easy, cheap case where it's a subset of one of the buffers
if (bytes <= this._bufs[off[0]].length - start) {
return copy
? this._bufs[off[0]].copy(dst, dstStart, start, start + bytes)
: this._bufs[off[0]].slice(start, start + bytes)
}
if (!copy) {
// a slice, we need something to copy in to
dst = Buffer.allocUnsafe(len)
}
for (let i = off[0]; i < this._bufs.length; i++) {
const l = this._bufs[i].length - start
if (bytes > l) {
this._bufs[i].copy(dst, bufoff, start)
bufoff += l
} else {
this._bufs[i].copy(dst, bufoff, start, start + bytes)
bufoff += l
break
}
bytes -= l
if (start) {
start = 0
}
}
// safeguard so that we don't return uninitialized memory
if (dst.length > bufoff) return dst.slice(0, bufoff)
return dst
}
BufferList.prototype.shallowSlice = function shallowSlice (start, end) {
start = start || 0
end = typeof end !== 'number' ? this.length : end
if (start < 0) {
start += this.length
}
if (end < 0) {
end += this.length
}
if (start === end) {
return this._new()
}
const startOffset = this._offset(start)
const endOffset = this._offset(end)
const buffers = this._bufs.slice(startOffset[0], endOffset[0] + 1)
if (endOffset[1] === 0) {
buffers.pop()
} else {
buffers[buffers.length - 1] = buffers[buffers.length - 1].slice(0, endOffset[1])
}
if (startOffset[1] !== 0) {
buffers[0] = buffers[0].slice(startOffset[1])
}
return this._new(buffers)
}
BufferList.prototype.toString = function toString (encoding, start, end) {
return this.slice(start, end).toString(encoding)
}
BufferList.prototype.consume = function consume (bytes) {
// first, normalize the argument, in accordance with how Buffer does it
bytes = Math.trunc(bytes)
// do nothing if not a positive number
if (Number.isNaN(bytes) || bytes <= 0) return this
while (this._bufs.length) {
if (bytes >= this._bufs[0].length) {
bytes -= this._bufs[0].length
this.length -= this._bufs[0].length
this._bufs.shift()
} else {
this._bufs[0] = this._bufs[0].slice(bytes)
this.length -= bytes
break
}
}
return this
}
BufferList.prototype.duplicate = function duplicate () {
const copy = this._new()
for (let i = 0; i < this._bufs.length; i++) {
copy.append(this._bufs[i])
}
return copy
}
BufferList.prototype.append = function append (buf) {
if (buf == null) {
return this
}
if (buf.buffer) {
// append a view of the underlying ArrayBuffer
this._appendBuffer(Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength))
} else if (Array.isArray(buf)) {
for (let i = 0; i < buf.length; i++) {
this.append(buf[i])
}
} else if (this._isBufferList(buf)) {
// unwrap argument into individual BufferLists
for (let i = 0; i < buf._bufs.length; i++) {
this.append(buf._bufs[i])
}
} else {
// coerce number arguments to strings, since Buffer(number) does
// uninitialized memory allocation
if (typeof buf === 'number') {
buf = buf.toString()
}
this._appendBuffer(Buffer.from(buf))
}
return this
}
BufferList.prototype._appendBuffer = function appendBuffer (buf) {
this._bufs.push(buf)
this.length += buf.length
}
BufferList.prototype.indexOf = function (search, offset, encoding) {
if (encoding === undefined && typeof offset === 'string') {
encoding = offset
offset = undefined
}
if (typeof search === 'function' || Array.isArray(search)) {
throw new TypeError('The "value" argument must be one of type string, Buffer, BufferList, or Uint8Array.')
} else if (typeof search === 'number') {
search = Buffer.from([search])
} else if (typeof search === 'string') {
search = Buffer.from(search, encoding)
} else if (this._isBufferList(search)) {
search = search.slice()
} else if (Array.isArray(search.buffer)) {
search = Buffer.from(search.buffer, search.byteOffset, search.byteLength)
} else if (!Buffer.isBuffer(search)) {
search = Buffer.from(search)
}
offset = Number(offset || 0)
if (isNaN(offset)) {
offset = 0
}
if (offset < 0) {
offset = this.length + offset
}
if (offset < 0) {
offset = 0
}
if (search.length === 0) {
return offset > this.length ? this.length : offset
}
const blOffset = this._offset(offset)
let blIndex = blOffset[0] // index of which internal buffer we're working on
let buffOffset = blOffset[1] // offset of the internal buffer we're working on
// scan over each buffer
for (; blIndex < this._bufs.length; blIndex++) {
const buff = this._bufs[blIndex]
while (buffOffset < buff.length) {
const availableWindow = buff.length - buffOffset
if (availableWindow >= search.length) {
const nativeSearchResult = buff.indexOf(search, buffOffset)
if (nativeSearchResult !== -1) {
return this._reverseOffset([blIndex, nativeSearchResult])
}
buffOffset = buff.length - search.length + 1 // end of native search window
} else {
const revOffset = this._reverseOffset([blIndex, buffOffset])
if (this._match(revOffset, search)) {
return revOffset
}
buffOffset++
}
}
buffOffset = 0
}
return -1
}
BufferList.prototype._match = function (offset, search) {
if (this.length - offset < search.length) {
return false
}
for (let searchOffset = 0; searchOffset < search.length; searchOffset++) {
if (this.get(offset + searchOffset) !== search[searchOffset]) {
return false
}
}
return true
}
;(function () {
const methods = {
readDoubleBE: 8,
readDoubleLE: 8,
readFloatBE: 4,
readFloatLE: 4,
readInt32BE: 4,
readInt32LE: 4,
readUInt32BE: 4,
readUInt32LE: 4,
readInt16BE: 2,
readInt16LE: 2,
readUInt16BE: 2,
readUInt16LE: 2,
readInt8: 1,
readUInt8: 1,
readIntBE: null,
readIntLE: null,
readUIntBE: null,
readUIntLE: null
}
for (const m in methods) {
(function (m) {
if (methods[m] === null) {
BufferList.prototype[m] = function (offset, byteLength) {
return this.slice(offset, offset + byteLength)[m](0, byteLength)
}
} else {
BufferList.prototype[m] = function (offset = 0) {
return this.slice(offset, offset + methods[m])[m](0)
}
}
}(m))
}
}())
// Used internally by the class and also as an indicator of this object being
// a `BufferList`. It's not possible to use `instanceof BufferList` in a browser
// environment because there could be multiple different copies of the
// BufferList class and some `BufferList`s might be `BufferList`s.
BufferList.prototype._isBufferList = function _isBufferList (b) {
return b instanceof BufferList || BufferList.isBufferList(b)
}
BufferList.isBufferList = function isBufferList (b) {
return b != null && b[symbol]
}
module.exports = BufferList
},{"buffer":undefined}],25:[function(require,module,exports){
'use strict'
const DuplexStream = require('readable-stream').Duplex
const inherits = require('inherits')
const BufferList = require('./BufferList')
function BufferListStream (callback) {
if (!(this instanceof BufferListStream)) {
return new BufferListStream(callback)
}
if (typeof callback === 'function') {
this._callback = callback
const piper = function piper (err) {
if (this._callback) {
this._callback(err)
this._callback = null
}
}.bind(this)
this.on('pipe', function onPipe (src) {
src.on('error', piper)
})
this.on('unpipe', function onUnpipe (src) {
src.removeListener('error', piper)
})
callback = null
}
BufferList._init.call(this, callback)
DuplexStream.call(this)
}
inherits(BufferListStream, DuplexStream)
Object.assign(BufferListStream.prototype, BufferList.prototype)
BufferListStream.prototype._new = function _new (callback) {
return new BufferListStream(callback)
}
BufferListStream.prototype._write = function _write (buf, encoding, callback) {
this._appendBuffer(buf)
if (typeof callback === 'function') {
callback()
}
}
BufferListStream.prototype._read = function _read (size) {
if (!this.length) {
return this.push(null)
}
size = Math.min(size, this.length)
this.push(this.slice(0, size))
this.consume(size)
}
BufferListStream.prototype.end = function end (chunk) {
DuplexStream.prototype.end.call(this, chunk)
if (this._callback) {
this._callback(null, this.slice())
this._callback = null
}
}
BufferListStream.prototype._destroy = function _destroy (err, cb) {
this._bufs.length = 0
this.length = 0
cb(err)
}
BufferListStream.prototype._isBufferList = function _isBufferList (b) {
return b instanceof BufferListStream || b instanceof BufferList || BufferListStream.isBufferList(b)
}
BufferListStream.isBufferList = BufferList.isBufferList
module.exports = BufferListStream
module.exports.BufferListStream = BufferListStream
module.exports.BufferList = BufferList
},{"./BufferList":24,"inherits":94,"readable-stream":40}],26:[function(require,module,exports){
'use strict';
const codes = {};
function createErrorType(code, message, Base) {
if (!Base) {
Base = Error
}
function getMessage (arg1, arg2, arg3) {
if (typeof message === 'string') {
return message
} else {
return message(arg1, arg2, arg3)
}
}
class NodeError extends Base {
constructor (arg1, arg2, arg3) {
super(getMessage(arg1, arg2, arg3));
}
}
NodeError.prototype.name = Base.name;
NodeError.prototype.code = code;
codes[code] = NodeError;
}
// https://github.com/nodejs/node/blob/v10.8.0/lib/internal/errors.js
function oneOf(expected, thing) {
if (Array.isArray(expected)) {
const len = expected.length;
expected = expected.map((i) => String(i));
if (len > 2) {
return `one of ${thing} ${expected.slice(0, len - 1).join(', ')}, or ` +
expected[len - 1];
} else if (len === 2) {
return `one of ${thing} ${expected[0]} or ${expected[1]}`;
} else {
return `of ${thing} ${expected[0]}`;
}
} else {
return `of ${thing} ${String(expected)}`;
}
}
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
function startsWith(str, search, pos) {
return str.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search;
}
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
function endsWith(str, search, this_len) {
if (this_len === undefined || this_len > str.length) {
this_len = str.length;
}
return str.substring(this_len - search.length, this_len) === search;
}
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes
function includes(str, search, start) {
if (typeof start !== 'number') {
start = 0;
}
if (start + search.length > str.length) {
return false;
} else {
return str.indexOf(search, start) !== -1;
}
}
createErrorType('ERR_INVALID_OPT_VALUE', function (name, value) {
return 'The value "' + value + '" is invalid for option "' + name + '"'
}, TypeError);
createErrorType('ERR_INVALID_ARG_TYPE', function (name, expected, actual) {
// determiner: 'must be' or 'must not be'
let determiner;
if (typeof expected === 'string' && startsWith(expected, 'not ')) {
determiner = 'must not be';
expected = expected.replace(/^not /, '');
} else {
determiner = 'must be';
}
let msg;
if (endsWith(name, ' argument')) {
// For cases like 'first argument'
msg = `The ${name} ${determiner} ${oneOf(expected, 'type')}`;
} else {
const type = includes(name, '.') ? 'property' : 'argument';
msg = `The "${name}" ${type} ${determiner} ${oneOf(expected, 'type')}`;
}
msg += `. Received type ${typeof actual}`;
return msg;
}, TypeError);
createErrorType('ERR_STREAM_PUSH_AFTER_EOF', 'stream.push() after EOF');
createErrorType('ERR_METHOD_NOT_IMPLEMENTED', function (name) {
return 'The ' + name + ' method is not implemented'
});
createErrorType('ERR_STREAM_PREMATURE_CLOSE', 'Premature close');
createErrorType('ERR_STREAM_DESTROYED', function (name) {
return 'Cannot call ' + name + ' after a stream was destroyed';
});
createErrorType('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times');
createErrorType('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable');
createErrorType('ERR_STREAM_WRITE_AFTER_END', 'write after end');
createErrorType('ERR_STREAM_NULL_VALUES', 'May not write null values to stream', TypeError);
createErrorType('ERR_UNKNOWN_ENCODING', function (arg) {
return 'Unknown encoding: ' + arg
}, TypeError);
createErrorType('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', 'stream.unshift() after end event');
module.exports.codes = codes;
},{}],27:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// 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 PARTICUL