| 'use strict'; |
| const escapeStringRegexp = require('escape-string-regexp'); |
| const ansiStyles = require('ansi-styles'); |
| const stdoutColor = require('supports-color').stdout; |
| |
| const template = require('./templates.js'); |
| |
| const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); |
| |
| // `supportsColor.level` → `ansiStyles.color[name]` mapping |
| const levelMapping = ['ansi', 'ansi', 'ansi256', 'ansi16m']; |
| |
| // `color-convert` models to exclude from the Chalk API due to conflicts and such |
| const skipModels = new Set(['gray']); |
| |
| const styles = Object.create(null); |
| |
| function applyOptions(obj, options) { |
| options = options || {}; |
| |
| // Detect level if not set manually |
| const scLevel = stdoutColor ? stdoutColor.level : 0; |
| obj.level = options.level === undefined ? scLevel : options.level; |
| obj.enabled = 'enabled' in options ? options.enabled : obj.level > 0; |
| } |
| |
| function Chalk(options) { |
| // We check for this.template here since calling `chalk.constructor()` |
| // by itself will have a `this` of a previously constructed chalk object |
| if (!this || !(this instanceof Chalk) || this.template) { |
| const chalk = {}; |
| applyOptions(chalk, options); |
| |
| chalk.template = function () { |
| const args = [].slice.call(arguments); |
| return chalkTag.apply(null, [chalk.template].concat(args)); |
| }; |
| |
| Object.setPrototypeOf(chalk, Chalk.prototype); |
| Object.setPrototypeOf(chalk.template, chalk); |
| |
| chalk.template.constructor = Chalk; |
| |
| return chalk.template; |
| } |
| |
| applyOptions(this, options); |
| } |
| |
| // Use bright blue on Windows as the normal blue color is illegible |
| if (isSimpleWindowsTerm) { |
| ansiStyles.blue.open = '\u001B[94m'; |
| } |
| |
| for (const key of Object.keys(ansiStyles)) { |
| ansiStyles[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g'); |
| |
| styles[key] = { |
| get() { |
| const codes = ansiStyles[key]; |
| return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, key); |
| } |
| }; |
| } |
| |
| styles.visible = { |
| get() { |
| return build.call(this, this._styles || [], true, 'visible'); |
| } |
| }; |
| |
| ansiStyles.color.closeRe = new RegExp(escapeStringRegexp(ansiStyles.color.close), 'g'); |
| for (const model of Object.keys(ansiStyles.color.ansi)) { |
| if (skipModels.has(model)) { |
| continue; |
| } |
| |
| styles[model] = { |
| get() { |
| const level = this.level; |
| return function () { |
| const open = ansiStyles.color[levelMapping[level]][model].apply(null, arguments); |
| const codes = { |
| open, |
| close: ansiStyles.color.close, |
| closeRe: ansiStyles.color.closeRe |
| }; |
| return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model); |
| }; |
| } |
| }; |
| } |
| |
| ansiStyles.bgColor.closeRe = new RegExp(escapeStringRegexp(ansiStyles.bgColor.close), 'g'); |
| for (const model of Object.keys(ansiStyles.bgColor.ansi)) { |
| if (skipModels.has(model)) { |
| continue; |
| } |
| |
| const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1); |
| styles[bgModel] = { |
| get() { |
| const level = this.level; |
| return function () { |
| const open = ansiStyles.bgColor[levelMapping[level]][model].apply(null, arguments); |
| const codes = { |
| open, |
| close: ansiStyles.bgColor.close, |
| closeRe: ansiStyles.bgColor.closeRe |
| }; |
| return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model); |
| }; |
| } |
| }; |
| } |
| |
| const proto = Object.defineProperties(() => {}, styles); |
| |
| function build(_styles, _empty, key) { |
| const builder = function () { |
| return applyStyle.apply(builder, arguments); |
| }; |
| |
| builder._styles = _styles; |
| builder._empty = _empty; |
| |
| const self = this; |
| |
| Object.defineProperty(builder, 'level', { |
| enumerable: true, |
| get() { |
| return self.level; |
| }, |
| set(level) { |
| self.level = level; |
| } |
| }); |
| |
| Object.defineProperty(builder, 'enabled', { |
| enumerable: true, |
| get() { |
| return self.enabled; |
| }, |
| set(enabled) { |
| self.enabled = enabled; |
| } |
| }); |
| |
| // See below for fix regarding invisible grey/dim combination on Windows |
| builder.hasGrey = this.hasGrey || key === 'gray' || key === 'grey'; |
| |
| // `__proto__` is used because we must return a function, but there is |
| // no way to create a function with a different prototype |
| builder.__proto__ = proto; // eslint-disable-line no-proto |
| |
| return builder; |
| } |
| |
| function applyStyle() { |
| // Support varags, but simply cast to string in case there's only one arg |
| const args = arguments; |
| const argsLen = args.length; |
| let str = String(arguments[0]); |
| |
| if (argsLen === 0) { |
| return ''; |
| } |
| |
| if (argsLen > 1) { |
| // Don't slice `arguments`, it prevents V8 optimizations |
| for (let a = 1; a < argsLen; a++) { |
| str += ' ' + args[a]; |
| } |
| } |
| |
| if (!this.enabled || this.level <= 0 || !str) { |
| return this._empty ? '' : str; |
| } |
| |
| // Turns out that on Windows dimmed gray text becomes invisible in cmd.exe, |
| // see https://github.com/chalk/chalk/issues/58 |
| // If we're on Windows and we're dealing with a gray color, temporarily make 'dim' a noop. |
| const originalDim = ansiStyles.dim.open; |
| if (isSimpleWindowsTerm && this.hasGrey) { |
| ansiStyles.dim.open = ''; |
| } |
| |
| for (const code of this._styles.slice().reverse()) { |
| // 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'. |
| str = code.open + str.replace(code.closeRe, code.open) + code.close; |
| |
| // 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 |
| str = str.replace(/\r?\n/g, `${code.close}$&${code.open}`); |
| } |
| |
| // Reset the original `dim` if we changed it to work around the Windows dimmed gray issue |
| ansiStyles.dim.open = originalDim; |
| |
| return str; |
| } |
| |
| function chalkTag(chalk, strings) { |
| if (!Array.isArray(strings)) { |
| // If chalk() was called by itself or with a string, |
| // return the string itself as a string. |
| return [].slice.call(arguments, 1).join(' '); |
| } |
| |
| const args = [].slice.call(arguments, 2); |
| const parts = [strings.raw[0]]; |
| |
| for (let i = 1; i < strings.length; i++) { |
| parts.push(String(args[i - 1]).replace(/[{}\\]/g, '\\$&')); |
| parts.push(String(strings.raw[i])); |
| } |
| |
| return template(chalk, parts.join('')); |
| } |
| |
| Object.defineProperties(Chalk.prototype, styles); |
| |
| module.exports = Chalk(); // eslint-disable-line new-cap |
| module.exports.supportsColor = stdoutColor; |
| module.exports.default = module.exports; // For TypeScript |