styled-string-builder
Version:
String Styler class based on a builder design pattern
441 lines (437 loc) • 27 kB
JavaScript
/**
* @description ANSI escape code for resetting text formatting.
* @summary This constant holds the ANSI escape sequence used to reset all text formatting to default.
* @const AnsiReset
* @memberOf module:StyledString
*/
const AnsiReset = "\x1b[0m";
/**
* @description Standard foreground color codes for ANSI text formatting.
* @summary This object maps color names to their corresponding ANSI color codes for standard foreground colors.
* @const StandardForegroundColors
* @property {number} black - ANSI code for black text (30).
* @property {number} red - ANSI code for red text (31).
* @property {number} green - ANSI code for green text (32).
* @property {number} yellow - ANSI code for yellow text (33).
* @property {number} blue - ANSI code for blue text (34).
* @property {number} magenta - ANSI code for magenta text (35).
* @property {number} cyan - ANSI code for cyan text (36).
* @property {number} white - ANSI code for white text (37).
* @memberOf module:StyledString
*/
const StandardForegroundColors = {
black: 30,
red: 31,
green: 32,
yellow: 33,
blue: 34,
magenta: 35,
cyan: 36,
white: 37,
};
/**
* @description Bright foreground color codes for ANSI text formatting.
* @summary This object maps color names to their corresponding ANSI color codes for bright foreground colors.
* @const BrightForegroundColors
* @property {number} black - ANSI code for bright black text (90).
* @property {number} red - ANSI code for bright red text (91).
* @property {number} green - ANSI code for bright green text (92).
* @property {number} yellow - ANSI code for bright yellow text (93).
* @property {number} blue - ANSI code for bright blue text (94).
* @property {number} magenta - ANSI code for bright magenta text (95).
* @property {number} cyan - ANSI code for bright cyan text (96).
* @property {number} white - ANSI code for bright white text (97).
* @memberOf module:@StyledString
*/
const BrightForegroundColors = {
brightBlack: 90,
brightRed: 91,
brightGreen: 92,
brightYellow: 93,
brightBlue: 94,
brightMagenta: 95,
brightCyan: 96,
brightWhite: 97,
};
/**
* @description Standard background color codes for ANSI text formatting.
* @summary This object maps color names to their corresponding ANSI color codes for standard background colors.
* @const StandardBackgroundColors
* @property {number} bgBlack - ANSI code for black background (40).
* @property {number} bgRed - ANSI code for red background (41).
* @property {number} bgGreen - ANSI code for green background (42).
* @property {number} bgYellow - ANSI code for yellow background (43).
* @property {number} bgBlue - ANSI code for blue background (44).
* @property {number} bgMagenta - ANSI code for magenta background (45).
* @property {number} bgCyan - ANSI code for cyan background (46).
* @property {number} bgWhite - ANSI code for white background (47).
* @memberOf module:@StyledString
*/
const StandardBackgroundColors = {
bgBlack: 40,
bgRed: 41,
bgGreen: 42,
bgYellow: 43,
bgBlue: 44,
bgMagenta: 45,
bgCyan: 46,
bgWhite: 47,
};
/**
* @description Bright background color codes for ANSI text formatting.
* @summary This object maps color names to their corresponding ANSI color codes for bright background colors.
* @const BrightBackgroundColors
* @property {number} bgBrightBlack - ANSI code for bright black background (100).
* @property {number} bgBrightRed - ANSI code for bright red background (101).
* @property {number} bgBrightGreen - ANSI code for bright green background (102).
* @property {number} bgBrightYellow - ANSI code for bright yellow background (103).
* @property {number} bgBrightBlue - ANSI code for bright blue background (104).
* @property {number} bgBrightMagenta - ANSI code for bright magenta background (105).
* @property {number} bgBrightCyan - ANSI code for bright cyan background (106).
* @property {number} bgBrightWhite - ANSI code for bright white background (107).
* @memberOf module:@StyledString
*/
const BrightBackgroundColors = {
bgBrightBlack: 100,
bgBrightRed: 101,
bgBrightGreen: 102,
bgBrightYellow: 103,
bgBrightBlue: 104,
bgBrightMagenta: 105,
bgBrightCyan: 106,
bgBrightWhite: 107,
};
/**
* @description Text style codes for ANSI text formatting.
* @summary This object maps style names to their corresponding ANSI codes for various text styles.
* @const styles
* @property {number} reset - ANSI code to reset all styles (0).
* @property {number} bold - ANSI code for bold text (1).
* @property {number} dim - ANSI code for dim text (2).
* @property {number} italic - ANSI code for italic text (3).
* @property {number} underline - ANSI code for underlined text (4).
* @property {number} blink - ANSI code for blinking text (5).
* @property {number} inverse - ANSI code for inverse colors (7).
* @property {number} hidden - ANSI code for hidden text (8).
* @property {number} strikethrough - ANSI code for strikethrough text (9).
* @property {number} doubleUnderline - ANSI code for double underlined text (21).
* @property {number} normalColor - ANSI code to reset color to normal (22).
* @property {number} noItalicOrFraktur - ANSI code to turn off italic (23).
* @property {number} noUnderline - ANSI code to turn off underline (24).
* @property {number} noBlink - ANSI code to turn off blink (25).
* @property {number} noInverse - ANSI code to turn off inverse (27).
* @property {number} noHidden - ANSI code to turn off hidden (28).
* @property {number} noStrikethrough - ANSI code to turn off strikethrough (29).
* @memberOf module:@StyledString
*/
const styles = {
reset: 0,
bold: 1,
dim: 2,
italic: 3,
underline: 4,
blink: 5,
inverse: 7,
hidden: 8,
strikethrough: 9,
doubleUnderline: 21,
normalColor: 22,
noItalicOrFraktur: 23,
noUnderline: 24,
noBlink: 25,
noInverse: 27,
noHidden: 28,
noStrikethrough: 29,
};
/**
* @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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
function raw(text, raw) {
return `${raw}${text}${AnsiReset}`;
}
/**
* @class StyledString
* @description A class that extends string functionality with ANSI color and style options.
* @summary StyledString provides methods to apply various ANSI color and style options to text strings.
* It implements the ColorizeOptions interface and proxies native string methods to the underlying text.
* This class allows for chaining of styling methods and easy application of colors and styles to text.
*
* @implements {ColorizeOptions}
* @param {string} text - The initial text string to be styled.
*/
class StyledString {
constructor(text) {
this.text = text;
// Basic colors
Object.entries(StandardForegroundColors).forEach(([name, code]) => {
Object.defineProperty(this, name, {
get: () => this.foreground(code),
});
});
Object.entries(BrightForegroundColors).forEach(([name, code]) => {
Object.defineProperty(this, name, {
get: () => this.foreground(code),
});
});
// Background colors
Object.entries(StandardBackgroundColors).forEach(([name, code]) => {
Object.defineProperty(this, name, {
get: () => this.background(code),
});
});
Object.entries(BrightBackgroundColors).forEach(([name, code]) => {
Object.defineProperty(this, name, {
get: () => this.background(code),
});
});
// Styles
Object.entries(styles).forEach(([name, code]) => {
Object.defineProperty(this, name, {
get: () => this.style(code),
});
});
}
/**
* @description Clears all styling from the text.
* @summary Removes all ANSI color and style codes from the text.
* @return {StyledString} The StyledString instance with cleared styling.
*/
clear() {
this.text = clear(this.text);
return this;
}
/**
* @description Applies raw ANSI codes to the text.
* @summary Allows direct application of ANSI escape sequences to the text.
* @param {string} rawAnsi - The raw ANSI escape sequence to apply.
* @return {StyledString} The StyledString instance with the raw ANSI code applied.
*/
raw(rawAnsi) {
this.text = raw(this.text, rawAnsi);
return this;
}
/**
* @description Applies a foreground color to the text.
* @summary Sets the text color using ANSI color codes.
* @param {number} n - The ANSI color code for the foreground color.
* @return {StyledString} The StyledString instance with the foreground color applied.
*/
foreground(n) {
this.text = colorizeANSI(this.text, n);
return this;
}
/**
* @description Applies a background color to the text.
* @summary Sets the background color of the text using ANSI color codes.
* @param {number} n - The ANSI color code for the background color.
* @return {StyledString} The StyledString instance with the background color applied.
*/
background(n) {
this.text = colorizeANSI(this.text, n, true);
return this;
}
/**
* @description Applies a text style to the string.
* @summary Sets text styles such as bold, italic, or underline using ANSI style codes.
* @param {number | string} n - The style code or key from the styles object.
* @return {StyledString} The StyledString instance with the style applied.
*/
style(n) {
if (typeof n === "string" && !(n in styles)) {
console.warn(`Invalid style: ${n}`);
return this;
}
this.text = applyStyle(this.text, n);
return this;
}
/**
* @description Applies a 256-color foreground color to the text.
* @summary Sets the text color using the extended 256-color palette.
* @param {number} n - The color number from the 256-color palette.
* @return {StyledString} The StyledString instance with the 256-color foreground applied.
*/
color256(n) {
this.text = colorize256(this.text, n);
return this;
}
/**
* @description Applies a 256-color background color to the text.
* @summary Sets the background color using the extended 256-color palette.
* @param {number} n - The color number from the 256-color palette.
* @return {StyledString} The StyledString instance with the 256-color background applied.
*/
bgColor256(n) {
this.text = colorize256(this.text, n, true);
return this;
}
/**
* @description Applies an RGB foreground color to the text.
* @summary Sets the text color using RGB values.
* @param {number} r - The red component (0-255).
* @param {number} g - The green component (0-255).
* @param {number} b - The blue component (0-255).
* @return {StyledString} The StyledString instance with the RGB foreground color applied.
*/
rgb(r, g, b) {
this.text = colorizeRGB(this.text, r, g, b);
return this;
}
/**
* @description Applies an RGB background color to the text.
* @summary Sets the background color using RGB values.
* @param {number} r - The red component (0-255).
* @param {number} g - The green component (0-255).
* @param {number} b - The blue component (0-255).
* @return {StyledString} The StyledString instance with the RGB background color applied.
*/
bgRgb(r, g, b) {
this.text = colorizeRGB(this.text, r, g, b, true);
return this;
}
/**
* @description Converts the StyledString to a regular string.
* @summary Returns the underlying text with all applied styling.
* @return {string} The styled text as a regular string.
*/
toString() {
return this.text;
}
}
/**
* @description Applies styling to a given text string.
* @summary This function takes a string and returns a StyledString object, which is an enhanced
* version of the original string with additional methods for applying various ANSI color and style
* options. It sets up a mapper object with methods for different styling operations and then
* defines properties on the text string to make these methods accessible.
*
* @param {string[]} t The input text to be styled.
* @return {StyledString} A StyledString object with additional styling methods.
*
* @function style
*
* @memberOf StyledString
*/
function style(...t) {
return new StyledString(t.join(" "));
}
export { AnsiReset, BrightBackgroundColors, BrightForegroundColors, StandardBackgroundColors, StandardForegroundColors, StyledString, applyStyle, clear, colorize256, colorizeANSI, colorizeRGB, raw, style, styles };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3R5bGVkLXN0cmluZy1idWlsZGVyLmVzbS5janMiLCJzb3VyY2VzIjpbIi4uL3NyYy9jb25zdGFudHMudHMiLCIuLi9zcmMvY29sb3JzLnRzIiwiLi4vc3JjL3N0cmluZ3MudHMiXSwic291cmNlc0NvbnRlbnQiOltudWxsLG51bGwsbnVsbF0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBOzs7OztBQUtHO0FBQ0ksTUFBTSxTQUFTLEdBQUc7QUFFekI7Ozs7Ozs7Ozs7Ozs7QUFhRztBQUNJLE1BQU0sd0JBQXdCLEdBQUc7QUFDdEMsSUFBQSxLQUFLLEVBQUUsRUFBRTtBQUNULElBQUEsR0FBRyxFQUFFLEVBQUU7QUFDUCxJQUFBLEtBQUssRUFBRSxFQUFFO0FBQ1QsSUFBQSxNQUFNLEVBQUUsRUFBRTtBQUNWLElBQUEsSUFBSSxFQUFFLEVBQUU7QUFDUixJQUFBLE9BQU8sRUFBRSxFQUFFO0FBQ1gsSUFBQSxJQUFJLEVBQUUsRUFBRTtBQUNSLElBQUEsS0FBSyxFQUFFLEVBQUU7O0FBR1g7Ozs7Ozs7Ozs7Ozs7QUFhRztBQUNJLE1BQU0sc0JBQXNCLEdBQUc7QUFDcEMsSUFBQSxXQUFXLEVBQUUsRUFBRTtBQUNmLElBQUEsU0FBUyxFQUFFLEVBQUU7QUFDYixJQUFBLFdBQVcsRUFBRSxFQUFFO0FBQ2YsSUFBQSxZQUFZLEVBQUUsRUFBRTtBQUNoQixJQUFBLFVBQVUsRUFBRSxFQUFFO0FBQ2QsSUFBQSxhQUFhLEVBQUUsRUFBRTtBQUNqQixJQUFBLFVBQVUsRUFBRSxFQUFFO0FBQ2QsSUFBQSxXQUFXLEVBQUUsRUFBRTs7QUFHakI7Ozs7Ozs7Ozs7Ozs7QUFhRztBQUNJLE1BQU0sd0JBQXdCLEdBQUc7QUFDdEMsSUFBQSxPQUFPLEVBQUUsRUFBRTtBQUNYLElBQUEsS0FBSyxFQUFFLEVBQUU7QUFDVCxJQUFBLE9BQU8sRUFBRSxFQUFFO0FBQ1gsSUFBQSxRQUFRLEVBQUUsRUFBRTtBQUNaLElBQUEsTUFBTSxFQUFFLEVBQUU7QUFDVixJQUFBLFNBQVMsRUFBRSxFQUFFO0FBQ2IsSUFBQSxNQUFNLEVBQUUsRUFBRTtBQUNWLElBQUEsT0FBTyxFQUFFLEVBQUU7O0FBR2I7Ozs7Ozs7Ozs7Ozs7QUFhRztBQUNJLE1BQU0sc0JBQXNCLEdBQUc7QUFDcEMsSUFBQSxhQUFhLEVBQUUsR0FBRztBQUNsQixJQUFBLFdBQVcsRUFBRSxHQUFHO0FBQ2hCLElBQUEsYUFBYSxFQUFFLEdBQUc7QUFDbEIsSUFBQSxjQUFjLEVBQUUsR0FBRztBQUNuQixJQUFBLFlBQVksRUFBRSxHQUFHO0FBQ2pCLElBQUEsZUFBZSxFQUFFLEdBQUc7QUFDcEIsSUFBQSxZQUFZLEVBQUUsR0FBRztBQUNqQixJQUFBLGFBQWEsRUFBRSxHQUFHOztBQUdwQjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQXNCRztBQUNJLE1BQU0sTUFBTSxHQUFHO0FBQ3BCLElBQUEsS0FBSyxFQUFFLENBQUM7QUFDUixJQUFBLElBQUksRUFBRSxDQUFDO0FBQ1AsSUFBQSxHQUFHLEVBQUUsQ0FBQztBQUNOLElBQUEsTUFBTSxFQUFFLENBQUM7QUFDVCxJQUFBLFNBQVMsRUFBRSxDQUFDO0FBQ1osSUFBQSxLQUFLLEVBQUUsQ0FBQztBQUNSLElBQUEsT0FBTyxFQUFFLENBQUM7QUFDVixJQUFBLE1BQU0sRUFBRSxDQUFDO0FBQ1QsSUFBQSxhQUFhLEVBQUUsQ0FBQztBQUNoQixJQUFBLGVBQWUsRUFBRSxFQUFFO0FBQ25CLElBQUEsV0FBVyxFQUFFLEVBQUU7QUFDZixJQUFBLGlCQUFpQixFQUFFLEVBQUU7QUFDckIsSUFBQSxXQUFXLEVBQUUsRUFBRTtBQUNmLElBQUEsT0FBTyxFQUFFLEVBQUU7QUFDWCxJQUFBLFNBQVMsRUFBRSxFQUFFO0FBQ2IsSUFBQSxRQUFRLEVBQUUsRUFBRTtBQUNaLElBQUEsZUFBZSxFQUFFLEVBQUU7OztBQ2xKckI7Ozs7Ozs7Ozs7Ozs7QUFhRztBQUNHLFNBQVUsWUFBWSxDQUFDLElBQVksRUFBRSxDQUFTLEVBQUUsRUFBRSxHQUFHLEtBQUssRUFBQTtBQUU5RCxJQUFBLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFDO0FBQ1gsUUFBQSxPQUFPLENBQUMsSUFBSSxDQUFDLDJDQUEyQyxDQUFDLENBQUEsYUFBQSxDQUFlLENBQUM7QUFDekUsUUFBQSxPQUFPLElBQUk7SUFDYjtJQUNBLElBQUksRUFBRSxLQUNKLENBQUMsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRTtZQUNkLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFFLEVBQUM7QUFDMUIsUUFBQSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUU7SUFDWjtBQUNBLElBQUEsT0FBTyxRQUFRLENBQUMsQ0FBQSxDQUFBLEVBQUksSUFBSSxDQUFBLEVBQUcsU0FBUyxFQUFFO0FBRXhDO0FBR0E7Ozs7Ozs7Ozs7OztBQVlHO0FBQ0csU0FBVSxXQUFXLENBQUMsSUFBWSxFQUFFLENBQVMsRUFBRSxFQUFFLEdBQUcsS0FBSyxFQUFBO0FBRTdELElBQUEsSUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUM7QUFDWCxRQUFBLE9BQU8sQ0FBQyxJQUFJLENBQUMsMENBQTBDLENBQUMsQ0FBQSxhQUFBLENBQWUsQ0FBQztBQUN4RSxRQUFBLE9BQU8sSUFBSTtJQUNiO0lBQ0EsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxHQUFHLEVBQUU7QUFDcEIsUUFBQSxPQUFPLENBQUMsSUFBSSxDQUFDLDBDQUEwQyxDQUFDLENBQUEsYUFBQSxDQUFlLENBQUM7QUFDeEUsUUFBQSxPQUFPLElBQUk7SUFDYjtBQUNBLElBQUEsT0FBTyxRQUFRLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxNQUFNLENBQUMsQ0FBQSxDQUFBLEVBQUksSUFBSSxDQUFBLEVBQUcsU0FBUyxFQUFFO0FBQzFEO0FBRUE7Ozs7Ozs7Ozs7Ozs7O0FBY0c7QUFDRyxTQUFVLFdBQVcsQ0FBQyxJQUFZLEVBQUUsQ0FBUyxFQUFFLENBQVMsRUFBRSxDQUFTLEVBQUUsRUFBRSxHQUFHLEtBQUssRUFBQTtBQUNuRixJQUFBLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUM7UUFDbkMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFBLDRCQUFBLEVBQStCLENBQUMsQ0FBQSxJQUFBLEVBQU8sQ0FBQyxDQUFBLElBQUEsRUFBTyxDQUFDLENBQUEsYUFBQSxDQUFlLENBQUM7QUFDN0UsUUFBQSxPQUFPLElBQUk7SUFDYjtJQUNBLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsR0FBRyxDQUFDLEVBQUU7UUFDekMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFBLDRCQUFBLEVBQStCLENBQUMsQ0FBQSxJQUFBLEVBQU8sQ0FBQyxDQUFBLElBQUEsRUFBTyxDQUFDLENBQUEsYUFBQSxDQUFlLENBQUM7QUFDN0UsUUFBQSxPQUFPLElBQUk7SUFDYjtJQUNBLE9BQU8sQ0FBQSxLQUFBLEVBQVEsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLE1BQU0sQ0FBQyxDQUFBLENBQUEsRUFBSSxDQUFDLENBQUEsQ0FBQSxFQUFJLENBQUMsSUFBSSxJQUFJLENBQUEsRUFBRyxTQUFTLENBQUEsQ0FBRTtBQUNwRTtBQUVBOzs7Ozs7Ozs7OztBQVdHO0FBQ0csU0FBVSxVQUFVLENBQUMsSUFBWSxFQUFFLENBQStCLEVBQUE7QUFDdEUsSUFBQSxNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsS0FBSyxRQUFRLEdBQUcsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUM7QUFDdkQsSUFBQSxPQUFPLFFBQVEsU0FBUyxDQUFBLENBQUEsRUFBSSxJQUFJLENBQUEsRUFBRyxTQUFTLEVBQUU7QUFDaEQ7QUFFQTs7Ozs7Ozs7Ozs7QUFXRztBQUNHLFNBQVUsS0FBSyxDQUFDLElBQVksRUFBQTs7O0lBR2hDLE1BQU0sU0FBUyxHQUFHLHdDQUF3QztJQUMxRCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQztBQUNwQztBQUVBOzs7Ozs7Ozs7Ozs7QUFZRztBQUNHLFNBQVUsR0FBRyxDQUFDLElBQVksRUFBRSxHQUFXLEVBQUE7QUFDM0MsSUFBQSxPQUFPLEdBQUcsR0FBRyxDQUFBLEVBQUcsSUFBSSxDQUFBLEVBQUcsU0FBUyxFQUFFO0FBQ3BDOztBQzlFQTs7Ozs7Ozs7O0FBU0c7TUFDVSxZQUFZLENBQUE7QUE2U3ZCLElBQUEsV0FBQSxDQUFZLElBQVksRUFBQTtBQUN0QixRQUFBLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSTs7QUFFaEIsUUFBQSxNQUFNLENBQUMsT0FBTyxDQUFDLHdCQUF3QixDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEtBQUk7QUFDaEUsWUFBQSxNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUU7Z0JBQ2hDLEdBQUcsRUFBRSxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDO0FBQ2pDLGFBQUEsQ0FBQztBQUNKLFFBQUEsQ0FBQyxDQUFDO0FBRUYsUUFBQSxNQUFNLENBQUMsT0FBTyxDQUFDLHNCQUFzQixDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEtBQUk7QUFDOUQsWUFBQSxNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUU7Z0JBQ2hDLEdBQUcsRUFBRSxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDO0FBQ2pDLGFBQUEsQ0FBQztBQUNKLFFBQUEsQ0FBQyxDQUFDOztBQUdGLFFBQUEsTUFBTSxDQUFDLE9BQU8sQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxLQUFJO0FBQ2hFLFlBQUEsTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFO2dCQUNoQyxHQUFHLEVBQUUsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQztBQUNqQyxhQUFBLENBQUM7QUFDSixRQUFBLENBQUMsQ0FBQztBQUVGLFFBQUEsTUFBTSxDQUFDLE9BQU8sQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxLQUFJO0FBQzlELFlBQUEsTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFO2dCQUNoQyxHQUFHLEVBQUUsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQztBQUNqQyxhQUFBLENBQUM7QUFDSixRQUFBLENBQUMsQ0FBQzs7QUFHRixRQUFBLE1BQU0sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEtBQUk7QUFDOUMsWUFBQSxNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUU7Z0JBQ2hDLEdBQUcsRUFBRSxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDO0FBQzVCLGFBQUEsQ0FBQztBQUNKLFFBQUEsQ0FBQyxDQUFDO0lBQ0o7QUFFQTs7OztBQUlHO0lBQ0gsS0FBSyxHQUFBO1FBQ0gsSUFBSSxDQUFDLElBQUksR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztBQUM1QixRQUFBLE9BQU8sSUFBSTtJQUNiO0FBRUE7Ozs7O0FBS0c7QUFDSCxJQUFBLEdBQUcsQ0FBQyxPQUFlLEVBQUE7UUFDakIsSUFBSSxDQUFDLElBQUksR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxPQUFPLENBQUM7QUFDbkMsUUFBQSxPQUFPLElBQUk7SUFDYjtBQUVBOzs7OztBQUtHO0FBQ0gsSUFBQSxVQUFVLENBQUMsQ0FBUyxFQUFBO1FBQ2xCLElBQUksQ0FBQyxJQUFJLEdBQUcsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0FBQ3RDLFFBQUEsT0FBTyxJQUFJO0lBQ2I7QUFFQTs7Ozs7QUFLRztBQUNILElBQUEsVUFBVSxDQUFDLENBQVMsRUFBQTtBQUNsQixRQUFBLElBQUksQ0FBQyxJQUFJLEdBQUcsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQztBQUM1QyxRQUFBLE9BQU8sSUFBSTtJQUNiO0FBRUE7Ozs7O0FBS0c7QUFDSCxJQUFBLEtBQUssQ0FBQyxDQUErQixFQUFBO0FBQ25DLFFBQUEsSUFBSSxPQUFPLENBQUMsS0FBSyxRQUFRLElBQUksRUFBRSxDQUFDLElBQUksTUFBTSxDQUFDLEVBQUU7QUFDM0MsWUFBQSxPQUFPLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUEsQ0FBRSxDQUFDO0FBQ25DLFlBQUEsT0FBTyxJQUFJO1FBQ2I7UUFDQSxJQUFJLENBQUMsSUFBSSxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztBQUNwQyxRQUFBLE9BQU8sSUFBSTtJQUNiO0FBRUE7Ozs7O0FBS0c7QUFDSCxJQUFBLFFBQVEsQ0FBQyxDQUFTLEVBQUE7UUFDaEIsSUFBSSxDQUFDLElBQUksR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7QUFDckMsUUFBQSxPQUFPLElBQUk7SUFDYjtBQUVBOzs7OztBQUtHO0FBQ0gsSUFBQSxVQUFVLENBQUMsQ0FBUyxFQUFBO0FBQ2xCLFFBQUEsSUFBSSxDQUFDLElBQUksR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDO0FBQzNDLFFBQUEsT0FBTyxJQUFJO0lBQ2I7QUFFQTs7Ozs7OztBQU9HO0FBQ0gsSUFBQSxHQUFHLENBQUMsQ0FBUyxFQUFFLENBQVMsRUFBRSxDQUFTLEVBQUE7QUFDakMsUUFBQSxJQUFJLENBQUMsSUFBSSxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQzNDLFFBQUEsT0FBTyxJQUFJO0lBQ2I7QUFFQTs7Ozs7OztBQU9HO0FBQ0gsSUFBQSxLQUFLLENBQUMsQ0FBUyxFQUFFLENBQVMsRUFBRSxDQUFTLEVBQUE7QUFDbkMsUUFBQSxJQUFJLENBQUMsSUFBSSxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQztBQUNqRCxRQUFBLE9BQU8sSUFBSTtJQUNiO0FBRUE7Ozs7QUFJRztJQUNILFFBQVEsR0FBQTtRQUNOLE9BQU8sSUFBSSxDQUFDLElBQUk7SUFDbEI7QUFDRDtBQUVEOzs7Ozs7Ozs7Ozs7O0FBYUc7QUFDRyxTQUFVLEtBQUssQ0FBQyxHQUFHLENBQVcsRUFBQTtJQUNsQyxPQUFPLElBQUksWUFBWSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDdEM7Ozs7In0=