UNPKG

oli-colors

Version:

lets you use terminal colors esser

156 lines (147 loc) 3.2 kB
/** * @typedef {(text: string) => string} ColorFn */ /** * @type {{ * reset: ColorFn, * bold: ColorFn, * dim: ColorFn, * italic: ColorFn, * underline: ColorFn, * blink: ColorFn, * inverse: ColorFn, * hidden: ColorFn, * strikethrough: ColorFn, * black: ColorFn, * red: ColorFn, * green: ColorFn, * yellow: ColorFn, * blue: ColorFn, * magenta: ColorFn, * cyan: ColorFn, * white: ColorFn, * brightBlack: ColorFn, * brightRed: ColorFn, * brightGreen: ColorFn, * brightYellow: ColorFn, * brightBlue: ColorFn, * brightMagenta: ColorFn, * brightCyan: ColorFn, * brightWhite: ColorFn, * bgBlack: ColorFn, * bgRed: ColorFn, * bgGreen: ColorFn, * bgYellow: ColorFn, * bgBlue: ColorFn, * bgMagenta: ColorFn, * bgCyan: ColorFn, * bgWhite: ColorFn, * bgBrightBlack: ColorFn, * bgBrightRed: ColorFn, * bgBrightGreen: ColorFn, * bgBrightYellow: ColorFn, * bgBrightBlue: ColorFn, * bgBrightMagenta: ColorFn, * bgBrightCyan: ColorFn, * bgBrightWhite: ColorFn * }} */ const ESC = '\x1b['; const RESET = `${ESC}0m`; const EFFECT_CODES = { reset: 0, bold: 1, dim: 2, italic: 3, underline: 4, blink: 5, inverse: 7, hidden: 8, strikethrough: 9, }; const FG_CODES = { black: 30, red: 31, green: 32, yellow: 33, blue: 34, magenta: 35, cyan: 36, white: 37, brightBlack: 90, brightRed: 91, brightGreen: 92, brightYellow: 93, brightBlue: 94, brightMagenta: 95, brightCyan: 96, brightWhite: 97, }; const BG_CODES = { black: 40, red: 41, green: 42, yellow: 43, blue: 44, magenta: 45, cyan: 46, white: 47, brightBlack: 100, brightRed: 101, brightGreen: 102, brightYellow: 103, brightBlue: 104, brightMagenta: 105, brightCyan: 106, brightWhite: 107, }; const ALL_CODES = { ...EFFECT_CODES, ...FG_CODES, ...Object.fromEntries( Object.entries(BG_CODES).map(([k, v]) => [ 'bg' + k.charAt(0).toUpperCase() + k.slice(1), v, ]) ), }; /** * Applies ANSI codes to the text * @param {number[]} codes * @param {string} text */ function applyStyles(codes, text) { if (!text) return ''; const prefix = ESC + codes.join(';') + 'm'; return prefix + text + RESET; } /** * Chainable Proxy function to enable .bold.red.bgYellow('text') usage * @param {number[]} styles */ function createChain(styles = []) { const handler = { get(target, prop) { if (prop === 'toString' || prop === 'valueOf' || prop === Symbol.toPrimitive) { return () => styles.join(';'); } if (ALL_CODES[prop] !== undefined) { return createChain([...styles, ALL_CODES[prop]]); } return undefined; }, apply(target, thisArg, args) { return applyStyles(styles, args[0]); }, }; function f(text) { return applyStyles(styles, text); } return new Proxy(f, handler); } /** * @typedef {(text: string) => string & {[key in keyof typeof ALL_CODES]: any}} Chainable * @type {Chainable} */ const e = createChain(); module.exports = e;