From f8f135515517f5e68276e7a59a4c4449f9c934ac Mon Sep 17 00:00:00 2001 From: Bruno Ribeito Date: Mon, 19 Feb 2018 22:54:09 +0000 Subject: [PATCH] Validate colors --- src/renderer/ColorManager.ts | 72 +++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 21 deletions(-) diff --git a/src/renderer/ColorManager.ts b/src/renderer/ColorManager.ts index 90ef0431..43a41f56 100644 --- a/src/renderer/ColorManager.ts +++ b/src/renderer/ColorManager.ts @@ -66,6 +66,8 @@ function toPaddedHex(c: number): string { * Manages the source of truth for a terminal's colors. */ export class ColorManager implements IColorManager { + private VALID_NON_NAMED_COLORS = new RegExp('^(#[0-9a-f]{3}|#(?:[0-9a-f]{2}){2,4}|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d\.]+%?\))$', 'g'); + public colors: IColorSet; constructor() { @@ -85,26 +87,54 @@ export class ColorManager implements IColorManager { * colors will be used where colors are not defined. */ public setTheme(theme: ITheme): void { - this.colors.foreground = theme.foreground || DEFAULT_FOREGROUND; - this.colors.background = theme.background || DEFAULT_BACKGROUND; - this.colors.cursor = theme.cursor || DEFAULT_CURSOR; - this.colors.cursorAccent = theme.cursorAccent || DEFAULT_CURSOR_ACCENT; - this.colors.selection = theme.selection || DEFAULT_SELECTION; - this.colors.ansi[0] = theme.black || DEFAULT_ANSI_COLORS[0]; - this.colors.ansi[1] = theme.red || DEFAULT_ANSI_COLORS[1]; - this.colors.ansi[2] = theme.green || DEFAULT_ANSI_COLORS[2]; - this.colors.ansi[3] = theme.yellow || DEFAULT_ANSI_COLORS[3]; - this.colors.ansi[4] = theme.blue || DEFAULT_ANSI_COLORS[4]; - this.colors.ansi[5] = theme.magenta || DEFAULT_ANSI_COLORS[5]; - this.colors.ansi[6] = theme.cyan || DEFAULT_ANSI_COLORS[6]; - this.colors.ansi[7] = theme.white || DEFAULT_ANSI_COLORS[7]; - this.colors.ansi[8] = theme.brightBlack || DEFAULT_ANSI_COLORS[8]; - this.colors.ansi[9] = theme.brightRed || DEFAULT_ANSI_COLORS[9]; - this.colors.ansi[10] = theme.brightGreen || DEFAULT_ANSI_COLORS[10]; - this.colors.ansi[11] = theme.brightYellow || DEFAULT_ANSI_COLORS[11]; - this.colors.ansi[12] = theme.brightBlue || DEFAULT_ANSI_COLORS[12]; - this.colors.ansi[13] = theme.brightMagenta || DEFAULT_ANSI_COLORS[13]; - this.colors.ansi[14] = theme.brightCyan || DEFAULT_ANSI_COLORS[14]; - this.colors.ansi[15] = theme.brightWhite || DEFAULT_ANSI_COLORS[15]; + this.colors.foreground = this._validateColor(theme.foreground, DEFAULT_FOREGROUND); + this.colors.background = this._validateColor(theme.background, DEFAULT_BACKGROUND); + this.colors.cursor = this._validateColor(theme.cursor, DEFAULT_CURSOR); + this.colors.cursorAccent = this._validateColor(theme.cursorAccent, DEFAULT_CURSOR_ACCENT); + this.colors.selection = this._validateColor(theme.selection, DEFAULT_SELECTION); + this.colors.ansi[0] = this._validateColor(theme.black, DEFAULT_ANSI_COLORS[0]); + this.colors.ansi[1] = this._validateColor(theme.red, DEFAULT_ANSI_COLORS[1]); + this.colors.ansi[2] = this._validateColor(theme.green, DEFAULT_ANSI_COLORS[2]); + this.colors.ansi[3] = this._validateColor(theme.yellow, DEFAULT_ANSI_COLORS[3]); + this.colors.ansi[4] = this._validateColor(theme.blue, DEFAULT_ANSI_COLORS[4]); + this.colors.ansi[5] = this._validateColor(theme.magenta, DEFAULT_ANSI_COLORS[5]); + this.colors.ansi[6] = this._validateColor(theme.cyan, DEFAULT_ANSI_COLORS[6]); + this.colors.ansi[7] = this._validateColor(theme.white, DEFAULT_ANSI_COLORS[7]); + this.colors.ansi[8] = this._validateColor(theme.brightBlack, DEFAULT_ANSI_COLORS[8]); + this.colors.ansi[9] = this._validateColor(theme.brightRed, DEFAULT_ANSI_COLORS[9]); + this.colors.ansi[10] = this._validateColor(theme.brightGreen, DEFAULT_ANSI_COLORS[10]); + this.colors.ansi[11] = this._validateColor(theme.brightYellow, DEFAULT_ANSI_COLORS[11]); + this.colors.ansi[12] = this._validateColor(theme.brightBlue, DEFAULT_ANSI_COLORS[12]); + this.colors.ansi[13] = this._validateColor(theme.brightMagenta, DEFAULT_ANSI_COLORS[13]); + this.colors.ansi[14] = this._validateColor(theme.brightCyan, DEFAULT_ANSI_COLORS[14]); + this.colors.ansi[15] = this._validateColor(theme.brightWhite, DEFAULT_ANSI_COLORS[15]); + } + + private _validateColor(color: string, fallback: string): string { + if (!color) { + return fallback; + } + + const isColorValid = this.VALID_NON_NAMED_COLORS.exec(color) || this._validateNamedColor(color); + + if (!isColorValid) { + console.warn(`Color: ${color} is invalid using fallback ${fallback}`); + } + + return isColorValid ? color : fallback; + } + + private _validateNamedColor(color: string): boolean { + const litmus = 'red'; + const d = document.createElement('div'); + d.style.color = litmus; + d.style.color = color; + + // Element's style.color will be reverted to litmus or set to '' if an invalid color is given + if (color !== litmus && (d.style.color === litmus || d.style.color === '')) { + return false; + } + + return true; } }