UNPKG

@visulima/colorize

Version:

Terminal and Console string styling done right.

204 lines (197 loc) 8.33 kB
import { isStdoutColorSupported } from '@visulima/is-ansi-color-supported'; import { convertHexToRgb } from './convertHexToRgb-DOIRmKxM.mjs'; import { rgbToAnsi16, rgbToAnsi256, ansi256To16 } from './rgbToAnsi256-DcQVMIqi.mjs'; var __defProp$4 = Object.defineProperty; var __name$4 = (target, value) => __defProp$4(target, "name", { value, configurable: true }); function ansiRegex({ onlyFirst = false } = {}) { const ST = "(?:\\u0007|\\u001B\\u005C|\\u009C)"; const pattern = [ `[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?${ST})`, "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))" ].join("|"); return new RegExp(pattern, onlyFirst ? void 0 : "g"); } __name$4(ansiRegex, "ansiRegex"); var __defProp$3 = Object.defineProperty; var __name$3 = (target, value) => __defProp$3(target, "name", { value, configurable: true }); const clamp = /* @__PURE__ */ __name$3((number_, min, max) => min > number_ ? min : number_ > max ? max : number_, "clamp"); var __defProp$2 = Object.defineProperty; var __name$2 = (target, value) => __defProp$2(target, "name", { value, configurable: true }); const closeCode = 39; const bgCloseCode = 49; const bgOffset = 10; const supportedColor = isStdoutColorSupported(); const mono = { close: "", open: "" }; const esc = supportedColor > 0 ? (open, close) => { return { close: "\x1B[" + close + "m", open: "\x1B[" + open + "m" }; } : () => mono; const createRgbFunction = /* @__PURE__ */ __name$2((function_) => (r, g, b) => function_(rgbToAnsi256(Number(r), Number(g), Number(b))), "createRgbFunction"); const createHexFunction = /* @__PURE__ */ __name$2((function_) => (hex) => { const [r, g, b] = convertHexToRgb(hex); return function_(r, g, b); }, "createHexFunction"); let createAnsi256 = /* @__PURE__ */ __name$2((code) => esc("38;5;" + code, closeCode), "createAnsi256"); let createBgAnsi256 = /* @__PURE__ */ __name$2((code) => esc("48;5;" + code, bgCloseCode), "createBgAnsi256"); let createRgb = /* @__PURE__ */ __name$2((r, g, b) => esc("38;2;" + r + ";" + g + ";" + b, closeCode), "createRgb"); let createBgRgb = /* @__PURE__ */ __name$2((r, g, b) => esc("48;2;" + r + ";" + g + ";" + b, bgCloseCode), "createBgRgb"); if (supportedColor === 1) { createAnsi256 = /* @__PURE__ */ __name$2((code) => esc(ansi256To16(Number(code)), closeCode), "createAnsi256"); createBgAnsi256 = /* @__PURE__ */ __name$2((code) => esc(ansi256To16(Number(code)) + bgOffset, bgCloseCode), "createBgAnsi256"); createRgb = /* @__PURE__ */ __name$2((r, g, b) => esc(rgbToAnsi16(Number(r), Number(g), Number(b)), closeCode), "createRgb"); createBgRgb = /* @__PURE__ */ __name$2((r, g, b) => esc(rgbToAnsi16(Number(r), Number(g), Number(b)) + bgOffset, bgCloseCode), "createBgRgb"); } else if (supportedColor === 2) { createRgb = createRgbFunction(createAnsi256); createBgRgb = createRgbFunction(createBgAnsi256); } const baseStyles = { // 21 isn't widely supported and 22 does the same thing bold: esc(1, 22), dim: esc(2, 22), hidden: esc(8, 28), inverse: esc(7, 27), italic: esc(3, 23), overline: esc(53, 55), reset: esc(0, 0), strike: esc(9, 29), // alias for strikethrough strikethrough: esc(9, 29), underline: esc(4, 24), visible: mono }; const baseColors = { bgBlack: esc(40, bgCloseCode), bgBlackBright: esc(100, bgCloseCode), bgBlue: esc(44, bgCloseCode), bgBlueBright: esc(104, bgCloseCode), bgCyan: esc(46, bgCloseCode), bgCyanBright: esc(106, bgCloseCode), bgGray: esc(100, bgCloseCode), // US spelling alias for bgBlackBright bgGreen: esc(42, bgCloseCode), bgGreenBright: esc(102, bgCloseCode), bgGrey: esc(100, bgCloseCode), // UK spelling alias for bgBlackBright bgMagenta: esc(45, bgCloseCode), bgMagentaBright: esc(105, bgCloseCode), bgRed: esc(41, bgCloseCode), bgRedBright: esc(101, bgCloseCode), bgWhite: esc(47, bgCloseCode), bgWhiteBright: esc(107, bgCloseCode), bgYellow: esc(43, bgCloseCode), bgYellowBright: esc(103, bgCloseCode), black: esc(30, closeCode), blackBright: esc(90, closeCode), blue: esc(34, closeCode), blueBright: esc(94, closeCode), cyan: esc(36, closeCode), cyanBright: esc(96, closeCode), gray: esc(90, closeCode), // US spelling alias for blackBright green: esc(32, closeCode), greenBright: esc(92, closeCode), grey: esc(90, closeCode), // UK spelling alias for blackBright magenta: esc(35, closeCode), magentaBright: esc(95, closeCode), red: esc(31, closeCode), redBright: esc(91, closeCode), white: esc(37, closeCode), whiteBright: esc(97, closeCode), yellow: esc(33, closeCode), yellowBright: esc(93, closeCode) }; const styleMethods = { bg: /* @__PURE__ */ __name$2((code) => createBgAnsi256(clamp(code, 0, 255)), "bg"), bgHex: createHexFunction(createBgRgb), bgRgb: /* @__PURE__ */ __name$2((r, g, b) => createBgRgb(clamp(r, 0, 255), clamp(g, 0, 255), clamp(b, 0, 255)), "bgRgb"), fg: /* @__PURE__ */ __name$2((code) => createAnsi256(clamp(code, 0, 255)), "fg"), hex: createHexFunction(createRgb), rgb: /* @__PURE__ */ __name$2((r, g, b) => createRgb(clamp(r, 0, 255), clamp(g, 0, 255), clamp(b, 0, 255)), "rgb") }; var __defProp$1 = Object.defineProperty; var __name$1 = (target, value) => __defProp$1(target, "name", { value, configurable: true }); const stringReplaceAll = /* @__PURE__ */ __name$1((string_, searchValue, replaceValue) => { if (searchValue === "") { return string_; } let pos = string_.indexOf(searchValue); if (pos < 0) { return string_; } const substringLength = searchValue.length; let lastPos = 0; let result = ""; while (~pos) { result += string_.slice(lastPos, pos) + replaceValue; lastPos = pos + substringLength; pos = string_.indexOf(searchValue, lastPos); } return result + string_.slice(lastPos); }, "stringReplaceAll"); var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); const styles = {}; let stylePrototype = null; const wrapText = /* @__PURE__ */ __name((strings, values, properties) => { if (!strings) { return ""; } let string = strings.raw == null ? strings + "" : String.raw(strings, ...values); if (string.includes("\x1B")) { for (let currentProperties = properties; currentProperties; currentProperties = currentProperties.props) { string = stringReplaceAll(string, currentProperties.close, currentProperties.open); } } if (string.includes("\n")) { string = string.replace(/(\r*\n)/g, properties.closeStack + "$1" + properties.openStack); } return properties.openStack + string + properties.closeStack; }, "wrapText"); const createStyle = /* @__PURE__ */ __name(({ props }, { close, open }) => { const openStack = (props?.openStack ?? "") + open; const closeStack = close + (props?.closeStack ?? ""); const style = /* @__PURE__ */ __name((strings, ...values) => wrapText(strings, values, style.props), "style"); Object.setPrototypeOf(style, stylePrototype); style.props = { close, closeStack, open, openStack, props }; style.open = openStack; style.close = closeStack; return style; }, "createStyle"); const Colorize = /* @__PURE__ */ __name(function() { const self = /* @__PURE__ */ __name((string_) => string_ + "", "self"); self.strip = (value) => value.replaceAll(ansiRegex(), ""); for (const name in baseColors) { styles[name] = { get() { const style = createStyle(this, baseColors[name]); Object.defineProperty(this, name, { value: style }); return style; } }; } for (const name in baseStyles) { styles[name] = { get() { const style = createStyle(this, baseStyles[name]); Object.defineProperty(this, name, { value: style }); return style; } }; } stylePrototype = Object.defineProperties({}, styles); Object.setPrototypeOf(self, stylePrototype); return self; }, "Colorize"); for (const name in styleMethods) { styles[name] = { get() { return (...arguments_) => ( // @ts-expect-error: TODO: fix typing of `arguments_` createStyle(this, styleMethods[name](...arguments_)) ); } }; } styles.ansi256 = styles.fg; styles.bgAnsi256 = styles.bg; export { Colorize as C };