oli-colors
Version:
lets you use terminal colors esser
156 lines (147 loc) • 3.2 kB
JavaScript
/**
* @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;