styled-string-builder
Version:
String Styler class based on a builder design pattern
129 lines (127 loc) • 15.6 kB
JavaScript
import { AnsiReset, styles } from "./constants";
/**
* @description Applies a basic ANSI color code to text.
* @summary This function takes a string, an ANSI color code number, and an optional background flag.
* It returns the text wrapped in the appropriate ANSI escape codes for either foreground or background coloring.
* This function is used for basic 16-color ANSI formatting.
*
* @param {string} text - The text to be colored.
* @param {number} n - The ANSI color code number.
* @param {boolean} [bg=false] - If true, applies the color to the background instead of the foreground.
* @return {string} The text wrapped in ANSI color codes.
*
* @function colorizeANSI
* @memberOf module:@StyledString
*/
export function colorizeANSI(text, n, bg = false) {
if (isNaN(n)) {
console.warn(`Invalid color number on the ANSI scale: ${n}. ignoring...`);
return text;
}
if (bg && ((n > 30 && n <= 40)
|| (n > 90 && n <= 100))) {
n = n + 10;
}
return `\x1b[${n}m${text}${AnsiReset}`;
}
/**
* @description Applies a 256-color ANSI code to text.
* @summary This function takes a string and a color number (0-255) and returns the text
* wrapped in ANSI escape codes for either foreground or background coloring.
*
* @param {string} text - The text to be colored.
* @param {number} n - The color number (0-255).
* @param {boolean} [bg=false] - If true, applies the color to the background instead of the foreground.
* @return {string} The text wrapped in ANSI color codes.
*
* @function colorize256
* @memberOf module:@StyledString
*/
export function colorize256(text, n, bg = false) {
if (isNaN(n)) {
console.warn(`Invalid color number on the 256 scale: ${n}. ignoring...`);
return text;
}
if (n < 0 || n > 255) {
console.warn(`Invalid color number on the 256 scale: ${n}. ignoring...`);
return text;
}
return `\x1b[${bg ? 48 : 38};5;${n}m${text}${AnsiReset}`;
}
/**
* @description Applies an RGB color ANSI code to text.
* @summary This function takes a string and RGB color values (0-255 for each component)
* and returns the text wrapped in ANSI escape codes for either foreground or background coloring.
*
* @param {string} text - The text to be colored.
* @param {number} r - The red component of the color (0-255).
* @param {number} g - The green component of the color (0-255).
* @param {number} b - The blue component of the color (0-255).
* @param {boolean} [bg=false] - If true, applies the color to the background instead of the foreground.
* @return {string} The text wrapped in ANSI color codes.
*
* @function colorizeRGB
* @memberOf module:StyledString
*/
export function colorizeRGB(text, r, g, b, bg = false) {
if (isNaN(r) || isNaN(g) || isNaN(b)) {
console.warn(`Invalid RGB color values: r=${r}, g=${g}, b=${b}. Ignoring...`);
return text;
}
if ([r, g, b].some(v => v < 0 || v > 255)) {
console.warn(`Invalid RGB color values: r=${r}, g=${g}, b=${b}. Ignoring...`);
return text;
}
return `\x1b[${bg ? 48 : 38};2;${r};${g};${b}m${text}${AnsiReset}`;
}
/**
* @description Applies an ANSI style code to text.
* @summary This function takes a string and a style code (either a number or a key from the styles object)
* and returns the text wrapped in the appropriate ANSI escape codes for that style.
*
* @param {string} text - The text to be styled.
* @param {number | string} n - The style code or style name.
* @return {string} The text wrapped in ANSI style codes.
*
* @function applyStyle
* @memberOf module:StyledString
*/
export function applyStyle(text, n) {
const styleCode = typeof n === "number" ? n : styles[n];
return `\x1b[${styleCode}m${text}${AnsiReset}`;
}
/**
* @description Removes all ANSI formatting codes from text.
* @summary This function takes a string that may contain ANSI escape codes for formatting
* and returns a new string with all such codes removed, leaving only the plain text content.
* It uses a regular expression to match and remove ANSI escape sequences.
*
* @param {string} text - The text potentially containing ANSI formatting codes.
* @return {string} The input text with all ANSI formatting codes removed.
*
* @function clear
* @memberOf module:StyledString
*/
export function clear(text) {
// Regular expression to match ANSI escape codes
// eslint-disable-next-line no-control-regex
const ansiRegex = /\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g;
return text.replace(ansiRegex, '');
}
/**
* @description Applies raw ANSI escape codes to text.
* @summary This function takes a string and a raw ANSI escape code, and returns the text
* wrapped in the provided raw ANSI code and the reset code. This allows for applying custom
* or complex ANSI formatting that may not be covered by other utility functions.
*
* @param {string} text - The text to be formatted.
* @param {string} raw - The raw ANSI escape code to be applied.
* @return {string} The text wrapped in the raw ANSI code and the reset code.
*
* @function raw
* @memberOf module:StyledString
*/
export function raw(text, raw) {
return `${raw}${text}${AnsiReset}`;
}
//# sourceMappingURL=data:application/json;charset=utf8;base64,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QUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4RCxPQUFPLFFBQVEsU0FBUyxJQUFJLElBQUksR0FBRyxTQUFTLEVBQUUsQ0FBQztBQUNqRCxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7O0dBV0c7QUFDSCxNQUFNLFVBQVUsS0FBSyxDQUFDLElBQVk7SUFDaEMsZ0RBQWdEO0lBQ2hELDRDQUE0QztJQUM1QyxNQUFNLFNBQVMsR0FBRyx3Q0FBd0MsQ0FBQztJQUMzRCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBQ3JDLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxNQUFNLFVBQVUsR0FBRyxDQUFDLElBQVksRUFBRSxHQUFXO0lBQzNDLE9BQU8sR0FBRyxHQUFHLEdBQUcsSUFBSSxHQUFHLFNBQVMsRUFBRSxDQUFDO0FBQ3JDLENBQUMiLCJmaWxlIjoiY29sb3JzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQW5zaVJlc2V0LCBzdHlsZXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcblxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBcHBsaWVzIGEgYmFzaWMgQU5TSSBjb2xvciBjb2RlIHRvIHRleHQuXG4gKiBAc3VtbWFyeSBUaGlzIGZ1bmN0aW9uIHRha2VzIGEgc3RyaW5nLCBhbiBBTlNJIGNvbG9yIGNvZGUgbnVtYmVyLCBhbmQgYW4gb3B0aW9uYWwgYmFja2dyb3VuZCBmbGFnLlxuICogSXQgcmV0dXJucyB0aGUgdGV4dCB3cmFwcGVkIGluIHRoZSBhcHByb3ByaWF0ZSBBTlNJIGVzY2FwZSBjb2RlcyBmb3IgZWl0aGVyIGZvcmVncm91bmQgb3IgYmFja2dyb3VuZCBjb2xvcmluZy5cbiAqIFRoaXMgZnVuY3Rpb24gaXMgdXNlZCBmb3IgYmFzaWMgMTYtY29sb3IgQU5TSSBmb3JtYXR0aW5nLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0IC0gVGhlIHRleHQgdG8gYmUgY29sb3JlZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBuIC0gVGhlIEFOU0kgY29sb3IgY29kZSBudW1iZXIuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtiZz1mYWxzZV0gLSBJZiB0cnVlLCBhcHBsaWVzIHRoZSBjb2xvciB0byB0aGUgYmFja2dyb3VuZCBpbnN0ZWFkIG9mIHRoZSBmb3JlZ3JvdW5kLlxuICogQHJldHVybiB7c3RyaW5nfSBUaGUgdGV4dCB3cmFwcGVkIGluIEFOU0kgY29sb3IgY29kZXMuXG4gKlxuICogQGZ1bmN0aW9uIGNvbG9yaXplQU5TSVxuICogQG1lbWJlck9mIG1vZHVsZTpAU3R5bGVkU3RyaW5nXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb2xvcml6ZUFOU0kodGV4dDogc3RyaW5nLCBuOiBudW1iZXIsIGJnID0gZmFsc2UpIHtcblxuICBpZiAoaXNOYU4obikpe1xuICAgIGNvbnNvbGUud2FybihgSW52YWxpZCBjb2xvciBudW1iZXIgb24gdGhlIEFOU0kgc2NhbGU6ICR7bn0uIGlnbm9yaW5nLi4uYCk7XG4gICAgcmV0dXJuIHRleHQ7XG4gIH1cbiAgaWYgKGJnICYmIChcbiAgICAobiA+IDMwICYmIG4gPD0gNDApXG4gICAgfHwgKG4gPiA5MCAmJiBuIDw9IDEwMCkgKSl7XG4gICAgbiA9IG4gKyAxMFxuICB9XG4gIHJldHVybiBgXFx4MWJbJHtufW0ke3RleHR9JHtBbnNpUmVzZXR9YDtcblxufVxuXG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEFwcGxpZXMgYSAyNTYtY29sb3IgQU5TSSBjb2RlIHRvIHRleHQuXG4gKiBAc3VtbWFyeSBUaGlzIGZ1bmN0aW9uIHRha2VzIGEgc3RyaW5nIGFuZCBhIGNvbG9yIG51bWJlciAoMC0yNTUpIGFuZCByZXR1cm5zIHRoZSB0ZXh0XG4gKiB3cmFwcGVkIGluIEFOU0kgZXNjYXBlIGNvZGVzIGZvciBlaXRoZXIgZm9yZWdyb3VuZCBvciBiYWNrZ3JvdW5kIGNvbG9yaW5nLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0IC0gVGhlIHRleHQgdG8gYmUgY29sb3JlZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBuIC0gVGhlIGNvbG9yIG51bWJlciAoMC0yNTUpLlxuICogQHBhcmFtIHtib29sZWFufSBbYmc9ZmFsc2VdIC0gSWYgdHJ1ZSwgYXBwbGllcyB0aGUgY29sb3IgdG8gdGhlIGJhY2tncm91bmQgaW5zdGVhZCBvZiB0aGUgZm9yZWdyb3VuZC5cbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIHRleHQgd3JhcHBlZCBpbiBBTlNJIGNvbG9yIGNvZGVzLlxuICpcbiAqIEBmdW5jdGlvbiBjb2xvcml6ZTI1NlxuICogQG1lbWJlck9mIG1vZHVsZTpAU3R5bGVkU3RyaW5nXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb2xvcml6ZTI1Nih0ZXh0OiBzdHJpbmcsIG46IG51bWJlciwgYmcgPSBmYWxzZSkge1xuXG4gIGlmIChpc05hTihuKSl7XG4gICAgY29uc29sZS53YXJuKGBJbnZhbGlkIGNvbG9yIG51bWJlciBvbiB0aGUgMjU2IHNjYWxlOiAke259LiBpZ25vcmluZy4uLmApO1xuICAgIHJldHVybiB0ZXh0O1xuICB9XG4gIGlmIChuIDwgMCB8fCBuID4gMjU1KSB7XG4gICAgY29uc29sZS53YXJuKGBJbnZhbGlkIGNvbG9yIG51bWJlciBvbiB0aGUgMjU2IHNjYWxlOiAke259LiBpZ25vcmluZy4uLmApO1xuICAgIHJldHVybiB0ZXh0O1xuICB9XG4gIHJldHVybiBgXFx4MWJbJHtiZyA/IDQ4IDogMzh9OzU7JHtufW0ke3RleHR9JHtBbnNpUmVzZXR9YDtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQXBwbGllcyBhbiBSR0IgY29sb3IgQU5TSSBjb2RlIHRvIHRleHQuXG4gKiBAc3VtbWFyeSBUaGlzIGZ1bmN0aW9uIHRha2VzIGEgc3RyaW5nIGFuZCBSR0IgY29sb3IgdmFsdWVzICgwLTI1NSBmb3IgZWFjaCBjb21wb25lbnQpXG4gKiBhbmQgcmV0dXJucyB0aGUgdGV4dCB3cmFwcGVkIGluIEFOU0kgZXNjYXBlIGNvZGVzIGZvciBlaXRoZXIgZm9yZWdyb3VuZCBvciBiYWNrZ3JvdW5kIGNvbG9yaW5nLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0IC0gVGhlIHRleHQgdG8gYmUgY29sb3JlZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSByIC0gVGhlIHJlZCBjb21wb25lbnQgb2YgdGhlIGNvbG9yICgwLTI1NSkuXG4gKiBAcGFyYW0ge251bWJlcn0gZyAtIFRoZSBncmVlbiBjb21wb25lbnQgb2YgdGhlIGNvbG9yICgwLTI1NSkuXG4gKiBAcGFyYW0ge251bWJlcn0gYiAtIFRoZSBibHVlIGNvbXBvbmVudCBvZiB0aGUgY29sb3IgKDAtMjU1KS5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW2JnPWZhbHNlXSAtIElmIHRydWUsIGFwcGxpZXMgdGhlIGNvbG9yIHRvIHRoZSBiYWNrZ3JvdW5kIGluc3RlYWQgb2YgdGhlIGZvcmVncm91bmQuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSB0ZXh0IHdyYXBwZWQgaW4gQU5TSSBjb2xvciBjb2Rlcy5cbiAqXG4gKiBAZnVuY3Rpb24gY29sb3JpemVSR0JcbiAqIEBtZW1iZXJPZiBtb2R1bGU6U3R5bGVkU3RyaW5nXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb2xvcml6ZVJHQih0ZXh0OiBzdHJpbmcsIHI6IG51bWJlciwgZzogbnVtYmVyLCBiOiBudW1iZXIsIGJnID0gZmFsc2UpIHtcbiAgaWYgKGlzTmFOKHIpIHx8IGlzTmFOKGcpIHx8IGlzTmFOKGIpKXtcbiAgICBjb25zb2xlLndhcm4oYEludmFsaWQgUkdCIGNvbG9yIHZhbHVlczogcj0ke3J9LCBnPSR7Z30sIGI9JHtifS4gSWdub3JpbmcuLi5gKTtcbiAgICByZXR1cm4gdGV4dDtcbiAgfVxuICBpZiAoW3IsIGcsIGJdLnNvbWUodiA9PiB2IDwgMCB8fCB2ID4gMjU1KSkge1xuICAgIGNvbnNvbGUud2FybihgSW52YWxpZCBSR0IgY29sb3IgdmFsdWVzOiByPSR7cn0sIGc9JHtnfSwgYj0ke2J9LiBJZ25vcmluZy4uLmApO1xuICAgIHJldHVybiB0ZXh0O1xuICB9XG4gIHJldHVybiBgXFx4MWJbJHtiZyA/IDQ4IDogMzh9OzI7JHtyfTske2d9OyR7Yn1tJHt0ZXh0fSR7QW5zaVJlc2V0fWA7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEFwcGxpZXMgYW4gQU5TSSBzdHlsZSBjb2RlIHRvIHRleHQuXG4gKiBAc3VtbWFyeSBUaGlzIGZ1bmN0aW9uIHRha2VzIGEgc3RyaW5nIGFuZCBhIHN0eWxlIGNvZGUgKGVpdGhlciBhIG51bWJlciBvciBhIGtleSBmcm9tIHRoZSBzdHlsZXMgb2JqZWN0KVxuICogYW5kIHJldHVybnMgdGhlIHRleHQgd3JhcHBlZCBpbiB0aGUgYXBwcm9wcmlhdGUgQU5TSSBlc2NhcGUgY29kZXMgZm9yIHRoYXQgc3R5bGUuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHRleHQgLSBUaGUgdGV4dCB0byBiZSBzdHlsZWQuXG4gKiBAcGFyYW0ge251bWJlciB8IHN0cmluZ30gbiAtIFRoZSBzdHlsZSBjb2RlIG9yIHN0eWxlIG5hbWUuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSB0ZXh0IHdyYXBwZWQgaW4gQU5TSSBzdHlsZSBjb2Rlcy5cbiAqXG4gKiBAZnVuY3Rpb24gYXBwbHlTdHlsZVxuICogQG1lbWJlck9mIG1vZHVsZTpTdHlsZWRTdHJpbmdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5U3R5bGUodGV4dDogc3RyaW5nLCBuOiBudW1iZXIgfCBrZXlvZiB0eXBlb2Ygc3R5bGVzKTogc3RyaW5nIHtcbiAgY29uc3Qgc3R5bGVDb2RlID0gdHlwZW9mIG4gPT09IFwibnVtYmVyXCIgPyBuIDogc3R5bGVzW25dO1xuICByZXR1cm4gYFxceDFiWyR7c3R5bGVDb2RlfW0ke3RleHR9JHtBbnNpUmVzZXR9YDtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmVtb3ZlcyBhbGwgQU5TSSBmb3JtYXR0aW5nIGNvZGVzIGZyb20gdGV4dC5cbiAqIEBzdW1tYXJ5IFRoaXMgZnVuY3Rpb24gdGFrZXMgYSBzdHJpbmcgdGhhdCBtYXkgY29udGFpbiBBTlNJIGVzY2FwZSBjb2RlcyBmb3IgZm9ybWF0dGluZ1xuICogYW5kIHJldHVybnMgYSBuZXcgc3RyaW5nIHdpdGggYWxsIHN1Y2ggY29kZXMgcmVtb3ZlZCwgbGVhdmluZyBvbmx5IHRoZSBwbGFpbiB0ZXh0IGNvbnRlbnQuXG4gKiBJdCB1c2VzIGEgcmVndWxhciBleHByZXNzaW9uIHRvIG1hdGNoIGFuZCByZW1vdmUgQU5TSSBlc2NhcGUgc2VxdWVuY2VzLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0IC0gVGhlIHRleHQgcG90ZW50aWFsbHkgY29udGFpbmluZyBBTlNJIGZvcm1hdHRpbmcgY29kZXMuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBpbnB1dCB0ZXh0IHdpdGggYWxsIEFOU0kgZm9ybWF0dGluZyBjb2RlcyByZW1vdmVkLlxuICpcbiAqIEBmdW5jdGlvbiBjbGVhclxuICogQG1lbWJlck9mIG1vZHVsZTpTdHlsZWRTdHJpbmdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsZWFyKHRleHQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIC8vIFJlZ3VsYXIgZXhwcmVzc2lvbiB0byBtYXRjaCBBTlNJIGVzY2FwZSBjb2Rlc1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29udHJvbC1yZWdleFxuICBjb25zdCBhbnNpUmVnZXggPSAvXFx4MUIoPzpbQC1aXFxcXC1fXXxcXFtbMC0/XSpbIC0vXSpbQC1+XSkvZztcbiAgcmV0dXJuIHRleHQucmVwbGFjZShhbnNpUmVnZXgsICcnKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQXBwbGllcyByYXcgQU5TSSBlc2NhcGUgY29kZXMgdG8gdGV4dC5cbiAqIEBzdW1tYXJ5IFRoaXMgZnVuY3Rpb24gdGFrZXMgYSBzdHJpbmcgYW5kIGEgcmF3IEFOU0kgZXNjYXBlIGNvZGUsIGFuZCByZXR1cm5zIHRoZSB0ZXh0XG4gKiB3cmFwcGVkIGluIHRoZSBwcm92aWRlZCByYXcgQU5TSSBjb2RlIGFuZCB0aGUgcmVzZXQgY29kZS4gVGhpcyBhbGxvd3MgZm9yIGFwcGx5aW5nIGN1c3RvbVxuICogb3IgY29tcGxleCBBTlNJIGZvcm1hdHRpbmcgdGhhdCBtYXkgbm90IGJlIGNvdmVyZWQgYnkgb3RoZXIgdXRpbGl0eSBmdW5jdGlvbnMuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHRleHQgLSBUaGUgdGV4dCB0byBiZSBmb3JtYXR0ZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gcmF3IC0gVGhlIHJhdyBBTlNJIGVzY2FwZSBjb2RlIHRvIGJlIGFwcGxpZWQuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSB0ZXh0IHdyYXBwZWQgaW4gdGhlIHJhdyBBTlNJIGNvZGUgYW5kIHRoZSByZXNldCBjb2RlLlxuICpcbiAqIEBmdW5jdGlvbiByYXdcbiAqIEBtZW1iZXJPZiBtb2R1bGU6U3R5bGVkU3RyaW5nXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByYXcodGV4dDogc3RyaW5nLCByYXc6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgJHtyYXd9JHt0ZXh0fSR7QW5zaVJlc2V0fWA7XG59Il19