You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					230 lines
				
				5.9 KiB
			
		
		
			
		
	
	
					230 lines
				
				5.9 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								const ansiStyles = require('ansi-styles');
							 | 
						||
| 
								 | 
							
								const {stdout: stdoutColor, stderr: stderrColor} = require('supports-color');
							 | 
						||
| 
								 | 
							
								const {
							 | 
						||
| 
								 | 
							
									stringReplaceAll,
							 | 
						||
| 
								 | 
							
									stringEncaseCRLFWithFirstIndex
							 | 
						||
| 
								 | 
							
								} = require('./util');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const {isArray} = Array;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// `supportsColor.level` → `ansiStyles.color[name]` mapping
							 | 
						||
| 
								 | 
							
								const levelMapping = [
							 | 
						||
| 
								 | 
							
									'ansi',
							 | 
						||
| 
								 | 
							
									'ansi',
							 | 
						||
| 
								 | 
							
									'ansi256',
							 | 
						||
| 
								 | 
							
									'ansi16m'
							 | 
						||
| 
								 | 
							
								];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const styles = Object.create(null);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const applyOptions = (object, options = {}) => {
							 | 
						||
| 
								 | 
							
									if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {
							 | 
						||
| 
								 | 
							
										throw new Error('The `level` option should be an integer from 0 to 3');
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Detect level if not set manually
							 | 
						||
| 
								 | 
							
									const colorLevel = stdoutColor ? stdoutColor.level : 0;
							 | 
						||
| 
								 | 
							
									object.level = options.level === undefined ? colorLevel : options.level;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ChalkClass {
							 | 
						||
| 
								 | 
							
									constructor(options) {
							 | 
						||
| 
								 | 
							
										// eslint-disable-next-line no-constructor-return
							 | 
						||
| 
								 | 
							
										return chalkFactory(options);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const chalkFactory = options => {
							 | 
						||
| 
								 | 
							
									const chalk = {};
							 | 
						||
| 
								 | 
							
									applyOptions(chalk, options);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									chalk.template = (...arguments_) => chalkTag(chalk.template, ...arguments_);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									Object.setPrototypeOf(chalk, Chalk.prototype);
							 | 
						||
| 
								 | 
							
									Object.setPrototypeOf(chalk.template, chalk);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									chalk.template.constructor = () => {
							 | 
						||
| 
								 | 
							
										throw new Error('`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.');
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									chalk.template.Instance = ChalkClass;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return chalk.template;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function Chalk(options) {
							 | 
						||
| 
								 | 
							
									return chalkFactory(options);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								for (const [styleName, style] of Object.entries(ansiStyles)) {
							 | 
						||
| 
								 | 
							
									styles[styleName] = {
							 | 
						||
| 
								 | 
							
										get() {
							 | 
						||
| 
								 | 
							
											const builder = createBuilder(this, createStyler(style.open, style.close, this._styler), this._isEmpty);
							 | 
						||
| 
								 | 
							
											Object.defineProperty(this, styleName, {value: builder});
							 | 
						||
| 
								 | 
							
											return builder;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								styles.visible = {
							 | 
						||
| 
								 | 
							
									get() {
							 | 
						||
| 
								 | 
							
										const builder = createBuilder(this, this._styler, true);
							 | 
						||
| 
								 | 
							
										Object.defineProperty(this, 'visible', {value: builder});
							 | 
						||
| 
								 | 
							
										return builder;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const usedModels = ['rgb', 'hex', 'keyword', 'hsl', 'hsv', 'hwb', 'ansi', 'ansi256'];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								for (const model of usedModels) {
							 | 
						||
| 
								 | 
							
									styles[model] = {
							 | 
						||
| 
								 | 
							
										get() {
							 | 
						||
| 
								 | 
							
											const {level} = this;
							 | 
						||
| 
								 | 
							
											return function (...arguments_) {
							 | 
						||
| 
								 | 
							
												const styler = createStyler(ansiStyles.color[levelMapping[level]][model](...arguments_), ansiStyles.color.close, this._styler);
							 | 
						||
| 
								 | 
							
												return createBuilder(this, styler, this._isEmpty);
							 | 
						||
| 
								 | 
							
											};
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								for (const model of usedModels) {
							 | 
						||
| 
								 | 
							
									const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1);
							 | 
						||
| 
								 | 
							
									styles[bgModel] = {
							 | 
						||
| 
								 | 
							
										get() {
							 | 
						||
| 
								 | 
							
											const {level} = this;
							 | 
						||
| 
								 | 
							
											return function (...arguments_) {
							 | 
						||
| 
								 | 
							
												const styler = createStyler(ansiStyles.bgColor[levelMapping[level]][model](...arguments_), ansiStyles.bgColor.close, this._styler);
							 | 
						||
| 
								 | 
							
												return createBuilder(this, styler, this._isEmpty);
							 | 
						||
| 
								 | 
							
											};
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const proto = Object.defineProperties(() => {}, {
							 | 
						||
| 
								 | 
							
									...styles,
							 | 
						||
| 
								 | 
							
									level: {
							 | 
						||
| 
								 | 
							
										enumerable: true,
							 | 
						||
| 
								 | 
							
										get() {
							 | 
						||
| 
								 | 
							
											return this._generator.level;
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
										set(level) {
							 | 
						||
| 
								 | 
							
											this._generator.level = level;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const createStyler = (open, close, parent) => {
							 | 
						||
| 
								 | 
							
									let openAll;
							 | 
						||
| 
								 | 
							
									let closeAll;
							 | 
						||
| 
								 | 
							
									if (parent === undefined) {
							 | 
						||
| 
								 | 
							
										openAll = open;
							 | 
						||
| 
								 | 
							
										closeAll = close;
							 | 
						||
| 
								 | 
							
									} else {
							 | 
						||
| 
								 | 
							
										openAll = parent.openAll + open;
							 | 
						||
| 
								 | 
							
										closeAll = close + parent.closeAll;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return {
							 | 
						||
| 
								 | 
							
										open,
							 | 
						||
| 
								 | 
							
										close,
							 | 
						||
| 
								 | 
							
										openAll,
							 | 
						||
| 
								 | 
							
										closeAll,
							 | 
						||
| 
								 | 
							
										parent
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const createBuilder = (self, _styler, _isEmpty) => {
							 | 
						||
| 
								 | 
							
									const builder = (...arguments_) => {
							 | 
						||
| 
								 | 
							
										if (isArray(arguments_[0]) && isArray(arguments_[0].raw)) {
							 | 
						||
| 
								 | 
							
											// Called as a template literal, for example: chalk.red`2 + 3 = {bold ${2+3}}`
							 | 
						||
| 
								 | 
							
											return applyStyle(builder, chalkTag(builder, ...arguments_));
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Single argument is hot path, implicit coercion is faster than anything
							 | 
						||
| 
								 | 
							
										// eslint-disable-next-line no-implicit-coercion
							 | 
						||
| 
								 | 
							
										return applyStyle(builder, (arguments_.length === 1) ? ('' + arguments_[0]) : arguments_.join(' '));
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// We alter the prototype because we must return a function, but there is
							 | 
						||
| 
								 | 
							
									// no way to create a function with a different prototype
							 | 
						||
| 
								 | 
							
									Object.setPrototypeOf(builder, proto);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									builder._generator = self;
							 | 
						||
| 
								 | 
							
									builder._styler = _styler;
							 | 
						||
| 
								 | 
							
									builder._isEmpty = _isEmpty;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return builder;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const applyStyle = (self, string) => {
							 | 
						||
| 
								 | 
							
									if (self.level <= 0 || !string) {
							 | 
						||
| 
								 | 
							
										return self._isEmpty ? '' : string;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									let styler = self._styler;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (styler === undefined) {
							 | 
						||
| 
								 | 
							
										return string;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									const {openAll, closeAll} = styler;
							 | 
						||
| 
								 | 
							
									if (string.indexOf('\u001B') !== -1) {
							 | 
						||
| 
								 | 
							
										while (styler !== undefined) {
							 | 
						||
| 
								 | 
							
											// Replace any instances already present with a re-opening code
							 | 
						||
| 
								 | 
							
											// otherwise only the part of the string until said closing code
							 | 
						||
| 
								 | 
							
											// will be colored, and the rest will simply be 'plain'.
							 | 
						||
| 
								 | 
							
											string = stringReplaceAll(string, styler.close, styler.open);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											styler = styler.parent;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// We can move both next actions out of loop, because remaining actions in loop won't have
							 | 
						||
| 
								 | 
							
									// any/visible effect on parts we add here. Close the styling before a linebreak and reopen
							 | 
						||
| 
								 | 
							
									// after next line to fix a bleed issue on macOS: https://github.com/chalk/chalk/pull/92
							 | 
						||
| 
								 | 
							
									const lfIndex = string.indexOf('\n');
							 | 
						||
| 
								 | 
							
									if (lfIndex !== -1) {
							 | 
						||
| 
								 | 
							
										string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return openAll + string + closeAll;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let template;
							 | 
						||
| 
								 | 
							
								const chalkTag = (chalk, ...strings) => {
							 | 
						||
| 
								 | 
							
									const [firstString] = strings;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (!isArray(firstString) || !isArray(firstString.raw)) {
							 | 
						||
| 
								 | 
							
										// If chalk() was called by itself or with a string,
							 | 
						||
| 
								 | 
							
										// return the string itself as a string.
							 | 
						||
| 
								 | 
							
										return strings.join(' ');
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									const arguments_ = strings.slice(1);
							 | 
						||
| 
								 | 
							
									const parts = [firstString.raw[0]];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for (let i = 1; i < firstString.length; i++) {
							 | 
						||
| 
								 | 
							
										parts.push(
							 | 
						||
| 
								 | 
							
											String(arguments_[i - 1]).replace(/[{}\\]/g, '\\$&'),
							 | 
						||
| 
								 | 
							
											String(firstString.raw[i])
							 | 
						||
| 
								 | 
							
										);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (template === undefined) {
							 | 
						||
| 
								 | 
							
										template = require('./templates');
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return template(chalk, parts.join(''));
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Object.defineProperties(Chalk.prototype, styles);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const chalk = Chalk(); // eslint-disable-line new-cap
							 | 
						||
| 
								 | 
							
								chalk.supportsColor = stdoutColor;
							 | 
						||
| 
								 | 
							
								chalk.stderr = Chalk({level: stderrColor ? stderrColor.level : 0}); // eslint-disable-line new-cap
							 | 
						||
| 
								 | 
							
								chalk.stderr.supportsColor = stderrColor;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = chalk;
							 |