Merge pull request #1346 from bgw/color-parsing
Allow theming with arbitrary CSS color strings
This commit is contained in:
+7
-38
@@ -2235,38 +2235,6 @@ function wasMondifierKeyOnlyEvent(ev: KeyboardEvent): boolean {
|
||||
* ANSI color code.
|
||||
*/
|
||||
|
||||
// Colors 0-15 + 16-255
|
||||
// Much thanks to TooTallNate for writing this.
|
||||
const vcolors: number[][] = (function(): number[][] {
|
||||
const result = DEFAULT_ANSI_COLORS.map(c => {
|
||||
c = c.substring(1);
|
||||
return [
|
||||
parseInt(c.substring(0, 2), 16),
|
||||
parseInt(c.substring(2, 4), 16),
|
||||
parseInt(c.substring(4, 6), 16)
|
||||
];
|
||||
});
|
||||
const r = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff];
|
||||
|
||||
// 16-231
|
||||
for (let i = 0; i < 216; i++) {
|
||||
result.push([
|
||||
r[(i / 36) % 6 | 0],
|
||||
r[(i / 6) % 6 | 0],
|
||||
r[i % 6]
|
||||
]);
|
||||
}
|
||||
|
||||
// 232-255 (grey)
|
||||
let c: number;
|
||||
for (let i = 0; i < 24; i++) {
|
||||
c = 8 + i * 10;
|
||||
result.push([c, c, c]);
|
||||
}
|
||||
|
||||
return result;
|
||||
})();
|
||||
|
||||
const matchColorCache: {[colorRGBHash: number]: number} = {};
|
||||
|
||||
// http://stackoverflow.com/questions/1633828
|
||||
@@ -2287,17 +2255,18 @@ function matchColor_(r1: number, g1: number, b1: number): number {
|
||||
let ldiff = Infinity;
|
||||
let li = -1;
|
||||
let i = 0;
|
||||
let c: number[];
|
||||
let c: number;
|
||||
let r2: number;
|
||||
let g2: number;
|
||||
let b2: number;
|
||||
let diff: number;
|
||||
|
||||
for (; i < vcolors.length; i++) {
|
||||
c = vcolors[i];
|
||||
r2 = c[0];
|
||||
g2 = c[1];
|
||||
b2 = c[2];
|
||||
for (; i < DEFAULT_ANSI_COLORS.length; i++) {
|
||||
c = DEFAULT_ANSI_COLORS[i].rgba;
|
||||
r2 = c >>> 24;
|
||||
g2 = c >>> 16 & 0xFF;
|
||||
b2 = c >>> 8 & 0xFF;
|
||||
// assume that alpha is 0xFF
|
||||
|
||||
diff = matchColorDistance(r1, g1, b1, r2, g2, b2);
|
||||
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ export class Viewport implements IViewport {
|
||||
}
|
||||
|
||||
public onThemeChanged(colors: IColorSet): void {
|
||||
this._viewportElement.style.backgroundColor = colors.background;
|
||||
this._viewportElement.style.backgroundColor = colors.background.css;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -179,7 +179,7 @@ export abstract class BaseRenderLayer implements IRenderLayer {
|
||||
if (this._alpha) {
|
||||
this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);
|
||||
} else {
|
||||
this._ctx.fillStyle = this._colors.background;
|
||||
this._ctx.fillStyle = this._colors.background.css;
|
||||
this._ctx.fillRect(0, 0, this._canvas.width, this._canvas.height);
|
||||
}
|
||||
}
|
||||
@@ -199,7 +199,7 @@ export abstract class BaseRenderLayer implements IRenderLayer {
|
||||
width * this._scaledCellWidth,
|
||||
height * this._scaledCellHeight);
|
||||
} else {
|
||||
this._ctx.fillStyle = this._colors.background;
|
||||
this._ctx.fillStyle = this._colors.background.css;
|
||||
this._ctx.fillRect(
|
||||
x * this._scaledCellWidth,
|
||||
y * this._scaledCellHeight,
|
||||
@@ -311,12 +311,12 @@ export abstract class BaseRenderLayer implements IRenderLayer {
|
||||
this._ctx.textBaseline = 'top';
|
||||
|
||||
if (fg === INVERTED_DEFAULT_COLOR) {
|
||||
this._ctx.fillStyle = this._colors.background;
|
||||
this._ctx.fillStyle = this._colors.background.css;
|
||||
} else if (fg < 256) {
|
||||
// 256 color support
|
||||
this._ctx.fillStyle = this._colors.ansi[fg];
|
||||
this._ctx.fillStyle = this._colors.ansi[fg].css;
|
||||
} else {
|
||||
this._ctx.fillStyle = this._colors.foreground;
|
||||
this._ctx.fillStyle = this._colors.foreground.css;
|
||||
}
|
||||
|
||||
this._clipRow(terminal, y);
|
||||
|
||||
+261
-250
@@ -17,261 +17,272 @@ describe('ColorManager', () => {
|
||||
dom = new jsdom.JSDOM('');
|
||||
window = dom.window;
|
||||
document = window.document;
|
||||
cm = new ColorManager(document);
|
||||
(<any>window).HTMLCanvasElement.prototype.getContext = () => ({
|
||||
createLinearGradient(): any {
|
||||
return null;
|
||||
},
|
||||
|
||||
fillRect(): void { },
|
||||
|
||||
getImageData(): any {
|
||||
return {data: [0, 0, 0, 0xFF]};
|
||||
}
|
||||
});
|
||||
cm = new ColorManager(document, false);
|
||||
});
|
||||
|
||||
describe('constructor', () => {
|
||||
it('should fill all colors with values', () => {
|
||||
for (let key in cm.colors) {
|
||||
if (typeof key === 'string') {
|
||||
for (let key of Object.keys(cm.colors)) {
|
||||
if (key !== 'ansi') {
|
||||
// A #rrggbb or rgba(...)
|
||||
assert.ok(cm.colors[key].length >= 7);
|
||||
assert.ok(cm.colors[key].css.length >= 7);
|
||||
}
|
||||
}
|
||||
assert.equal(cm.colors.ansi.length, 256);
|
||||
});
|
||||
|
||||
it('should fill 240 colors with expected values', () => {
|
||||
assert.equal(cm.colors.ansi[16], '#000000');
|
||||
assert.equal(cm.colors.ansi[17], '#00005f');
|
||||
assert.equal(cm.colors.ansi[18], '#000087');
|
||||
assert.equal(cm.colors.ansi[19], '#0000af');
|
||||
assert.equal(cm.colors.ansi[20], '#0000d7');
|
||||
assert.equal(cm.colors.ansi[21], '#0000ff');
|
||||
assert.equal(cm.colors.ansi[22], '#005f00');
|
||||
assert.equal(cm.colors.ansi[23], '#005f5f');
|
||||
assert.equal(cm.colors.ansi[24], '#005f87');
|
||||
assert.equal(cm.colors.ansi[25], '#005faf');
|
||||
assert.equal(cm.colors.ansi[26], '#005fd7');
|
||||
assert.equal(cm.colors.ansi[27], '#005fff');
|
||||
assert.equal(cm.colors.ansi[28], '#008700');
|
||||
assert.equal(cm.colors.ansi[29], '#00875f');
|
||||
assert.equal(cm.colors.ansi[30], '#008787');
|
||||
assert.equal(cm.colors.ansi[31], '#0087af');
|
||||
assert.equal(cm.colors.ansi[32], '#0087d7');
|
||||
assert.equal(cm.colors.ansi[33], '#0087ff');
|
||||
assert.equal(cm.colors.ansi[34], '#00af00');
|
||||
assert.equal(cm.colors.ansi[35], '#00af5f');
|
||||
assert.equal(cm.colors.ansi[36], '#00af87');
|
||||
assert.equal(cm.colors.ansi[37], '#00afaf');
|
||||
assert.equal(cm.colors.ansi[38], '#00afd7');
|
||||
assert.equal(cm.colors.ansi[39], '#00afff');
|
||||
assert.equal(cm.colors.ansi[40], '#00d700');
|
||||
assert.equal(cm.colors.ansi[41], '#00d75f');
|
||||
assert.equal(cm.colors.ansi[42], '#00d787');
|
||||
assert.equal(cm.colors.ansi[43], '#00d7af');
|
||||
assert.equal(cm.colors.ansi[44], '#00d7d7');
|
||||
assert.equal(cm.colors.ansi[45], '#00d7ff');
|
||||
assert.equal(cm.colors.ansi[46], '#00ff00');
|
||||
assert.equal(cm.colors.ansi[47], '#00ff5f');
|
||||
assert.equal(cm.colors.ansi[48], '#00ff87');
|
||||
assert.equal(cm.colors.ansi[49], '#00ffaf');
|
||||
assert.equal(cm.colors.ansi[50], '#00ffd7');
|
||||
assert.equal(cm.colors.ansi[51], '#00ffff');
|
||||
assert.equal(cm.colors.ansi[52], '#5f0000');
|
||||
assert.equal(cm.colors.ansi[53], '#5f005f');
|
||||
assert.equal(cm.colors.ansi[54], '#5f0087');
|
||||
assert.equal(cm.colors.ansi[55], '#5f00af');
|
||||
assert.equal(cm.colors.ansi[56], '#5f00d7');
|
||||
assert.equal(cm.colors.ansi[57], '#5f00ff');
|
||||
assert.equal(cm.colors.ansi[58], '#5f5f00');
|
||||
assert.equal(cm.colors.ansi[59], '#5f5f5f');
|
||||
assert.equal(cm.colors.ansi[60], '#5f5f87');
|
||||
assert.equal(cm.colors.ansi[61], '#5f5faf');
|
||||
assert.equal(cm.colors.ansi[62], '#5f5fd7');
|
||||
assert.equal(cm.colors.ansi[63], '#5f5fff');
|
||||
assert.equal(cm.colors.ansi[64], '#5f8700');
|
||||
assert.equal(cm.colors.ansi[65], '#5f875f');
|
||||
assert.equal(cm.colors.ansi[66], '#5f8787');
|
||||
assert.equal(cm.colors.ansi[67], '#5f87af');
|
||||
assert.equal(cm.colors.ansi[68], '#5f87d7');
|
||||
assert.equal(cm.colors.ansi[69], '#5f87ff');
|
||||
assert.equal(cm.colors.ansi[70], '#5faf00');
|
||||
assert.equal(cm.colors.ansi[71], '#5faf5f');
|
||||
assert.equal(cm.colors.ansi[72], '#5faf87');
|
||||
assert.equal(cm.colors.ansi[73], '#5fafaf');
|
||||
assert.equal(cm.colors.ansi[74], '#5fafd7');
|
||||
assert.equal(cm.colors.ansi[75], '#5fafff');
|
||||
assert.equal(cm.colors.ansi[76], '#5fd700');
|
||||
assert.equal(cm.colors.ansi[77], '#5fd75f');
|
||||
assert.equal(cm.colors.ansi[78], '#5fd787');
|
||||
assert.equal(cm.colors.ansi[79], '#5fd7af');
|
||||
assert.equal(cm.colors.ansi[80], '#5fd7d7');
|
||||
assert.equal(cm.colors.ansi[81], '#5fd7ff');
|
||||
assert.equal(cm.colors.ansi[82], '#5fff00');
|
||||
assert.equal(cm.colors.ansi[83], '#5fff5f');
|
||||
assert.equal(cm.colors.ansi[84], '#5fff87');
|
||||
assert.equal(cm.colors.ansi[85], '#5fffaf');
|
||||
assert.equal(cm.colors.ansi[86], '#5fffd7');
|
||||
assert.equal(cm.colors.ansi[87], '#5fffff');
|
||||
assert.equal(cm.colors.ansi[88], '#870000');
|
||||
assert.equal(cm.colors.ansi[89], '#87005f');
|
||||
assert.equal(cm.colors.ansi[90], '#870087');
|
||||
assert.equal(cm.colors.ansi[91], '#8700af');
|
||||
assert.equal(cm.colors.ansi[92], '#8700d7');
|
||||
assert.equal(cm.colors.ansi[93], '#8700ff');
|
||||
assert.equal(cm.colors.ansi[94], '#875f00');
|
||||
assert.equal(cm.colors.ansi[95], '#875f5f');
|
||||
assert.equal(cm.colors.ansi[96], '#875f87');
|
||||
assert.equal(cm.colors.ansi[97], '#875faf');
|
||||
assert.equal(cm.colors.ansi[98], '#875fd7');
|
||||
assert.equal(cm.colors.ansi[99], '#875fff');
|
||||
assert.equal(cm.colors.ansi[100], '#878700');
|
||||
assert.equal(cm.colors.ansi[101], '#87875f');
|
||||
assert.equal(cm.colors.ansi[102], '#878787');
|
||||
assert.equal(cm.colors.ansi[103], '#8787af');
|
||||
assert.equal(cm.colors.ansi[104], '#8787d7');
|
||||
assert.equal(cm.colors.ansi[105], '#8787ff');
|
||||
assert.equal(cm.colors.ansi[106], '#87af00');
|
||||
assert.equal(cm.colors.ansi[107], '#87af5f');
|
||||
assert.equal(cm.colors.ansi[108], '#87af87');
|
||||
assert.equal(cm.colors.ansi[109], '#87afaf');
|
||||
assert.equal(cm.colors.ansi[110], '#87afd7');
|
||||
assert.equal(cm.colors.ansi[111], '#87afff');
|
||||
assert.equal(cm.colors.ansi[112], '#87d700');
|
||||
assert.equal(cm.colors.ansi[113], '#87d75f');
|
||||
assert.equal(cm.colors.ansi[114], '#87d787');
|
||||
assert.equal(cm.colors.ansi[115], '#87d7af');
|
||||
assert.equal(cm.colors.ansi[116], '#87d7d7');
|
||||
assert.equal(cm.colors.ansi[117], '#87d7ff');
|
||||
assert.equal(cm.colors.ansi[118], '#87ff00');
|
||||
assert.equal(cm.colors.ansi[119], '#87ff5f');
|
||||
assert.equal(cm.colors.ansi[120], '#87ff87');
|
||||
assert.equal(cm.colors.ansi[121], '#87ffaf');
|
||||
assert.equal(cm.colors.ansi[122], '#87ffd7');
|
||||
assert.equal(cm.colors.ansi[123], '#87ffff');
|
||||
assert.equal(cm.colors.ansi[124], '#af0000');
|
||||
assert.equal(cm.colors.ansi[125], '#af005f');
|
||||
assert.equal(cm.colors.ansi[126], '#af0087');
|
||||
assert.equal(cm.colors.ansi[127], '#af00af');
|
||||
assert.equal(cm.colors.ansi[128], '#af00d7');
|
||||
assert.equal(cm.colors.ansi[129], '#af00ff');
|
||||
assert.equal(cm.colors.ansi[130], '#af5f00');
|
||||
assert.equal(cm.colors.ansi[131], '#af5f5f');
|
||||
assert.equal(cm.colors.ansi[132], '#af5f87');
|
||||
assert.equal(cm.colors.ansi[133], '#af5faf');
|
||||
assert.equal(cm.colors.ansi[134], '#af5fd7');
|
||||
assert.equal(cm.colors.ansi[135], '#af5fff');
|
||||
assert.equal(cm.colors.ansi[136], '#af8700');
|
||||
assert.equal(cm.colors.ansi[137], '#af875f');
|
||||
assert.equal(cm.colors.ansi[138], '#af8787');
|
||||
assert.equal(cm.colors.ansi[139], '#af87af');
|
||||
assert.equal(cm.colors.ansi[140], '#af87d7');
|
||||
assert.equal(cm.colors.ansi[141], '#af87ff');
|
||||
assert.equal(cm.colors.ansi[142], '#afaf00');
|
||||
assert.equal(cm.colors.ansi[143], '#afaf5f');
|
||||
assert.equal(cm.colors.ansi[144], '#afaf87');
|
||||
assert.equal(cm.colors.ansi[145], '#afafaf');
|
||||
assert.equal(cm.colors.ansi[146], '#afafd7');
|
||||
assert.equal(cm.colors.ansi[147], '#afafff');
|
||||
assert.equal(cm.colors.ansi[148], '#afd700');
|
||||
assert.equal(cm.colors.ansi[149], '#afd75f');
|
||||
assert.equal(cm.colors.ansi[150], '#afd787');
|
||||
assert.equal(cm.colors.ansi[151], '#afd7af');
|
||||
assert.equal(cm.colors.ansi[152], '#afd7d7');
|
||||
assert.equal(cm.colors.ansi[153], '#afd7ff');
|
||||
assert.equal(cm.colors.ansi[154], '#afff00');
|
||||
assert.equal(cm.colors.ansi[155], '#afff5f');
|
||||
assert.equal(cm.colors.ansi[156], '#afff87');
|
||||
assert.equal(cm.colors.ansi[157], '#afffaf');
|
||||
assert.equal(cm.colors.ansi[158], '#afffd7');
|
||||
assert.equal(cm.colors.ansi[159], '#afffff');
|
||||
assert.equal(cm.colors.ansi[160], '#d70000');
|
||||
assert.equal(cm.colors.ansi[161], '#d7005f');
|
||||
assert.equal(cm.colors.ansi[162], '#d70087');
|
||||
assert.equal(cm.colors.ansi[163], '#d700af');
|
||||
assert.equal(cm.colors.ansi[164], '#d700d7');
|
||||
assert.equal(cm.colors.ansi[165], '#d700ff');
|
||||
assert.equal(cm.colors.ansi[166], '#d75f00');
|
||||
assert.equal(cm.colors.ansi[167], '#d75f5f');
|
||||
assert.equal(cm.colors.ansi[168], '#d75f87');
|
||||
assert.equal(cm.colors.ansi[169], '#d75faf');
|
||||
assert.equal(cm.colors.ansi[170], '#d75fd7');
|
||||
assert.equal(cm.colors.ansi[171], '#d75fff');
|
||||
assert.equal(cm.colors.ansi[172], '#d78700');
|
||||
assert.equal(cm.colors.ansi[173], '#d7875f');
|
||||
assert.equal(cm.colors.ansi[174], '#d78787');
|
||||
assert.equal(cm.colors.ansi[175], '#d787af');
|
||||
assert.equal(cm.colors.ansi[176], '#d787d7');
|
||||
assert.equal(cm.colors.ansi[177], '#d787ff');
|
||||
assert.equal(cm.colors.ansi[178], '#d7af00');
|
||||
assert.equal(cm.colors.ansi[179], '#d7af5f');
|
||||
assert.equal(cm.colors.ansi[180], '#d7af87');
|
||||
assert.equal(cm.colors.ansi[181], '#d7afaf');
|
||||
assert.equal(cm.colors.ansi[182], '#d7afd7');
|
||||
assert.equal(cm.colors.ansi[183], '#d7afff');
|
||||
assert.equal(cm.colors.ansi[184], '#d7d700');
|
||||
assert.equal(cm.colors.ansi[185], '#d7d75f');
|
||||
assert.equal(cm.colors.ansi[186], '#d7d787');
|
||||
assert.equal(cm.colors.ansi[187], '#d7d7af');
|
||||
assert.equal(cm.colors.ansi[188], '#d7d7d7');
|
||||
assert.equal(cm.colors.ansi[189], '#d7d7ff');
|
||||
assert.equal(cm.colors.ansi[190], '#d7ff00');
|
||||
assert.equal(cm.colors.ansi[191], '#d7ff5f');
|
||||
assert.equal(cm.colors.ansi[192], '#d7ff87');
|
||||
assert.equal(cm.colors.ansi[193], '#d7ffaf');
|
||||
assert.equal(cm.colors.ansi[194], '#d7ffd7');
|
||||
assert.equal(cm.colors.ansi[195], '#d7ffff');
|
||||
assert.equal(cm.colors.ansi[196], '#ff0000');
|
||||
assert.equal(cm.colors.ansi[197], '#ff005f');
|
||||
assert.equal(cm.colors.ansi[198], '#ff0087');
|
||||
assert.equal(cm.colors.ansi[199], '#ff00af');
|
||||
assert.equal(cm.colors.ansi[200], '#ff00d7');
|
||||
assert.equal(cm.colors.ansi[201], '#ff00ff');
|
||||
assert.equal(cm.colors.ansi[202], '#ff5f00');
|
||||
assert.equal(cm.colors.ansi[203], '#ff5f5f');
|
||||
assert.equal(cm.colors.ansi[204], '#ff5f87');
|
||||
assert.equal(cm.colors.ansi[205], '#ff5faf');
|
||||
assert.equal(cm.colors.ansi[206], '#ff5fd7');
|
||||
assert.equal(cm.colors.ansi[207], '#ff5fff');
|
||||
assert.equal(cm.colors.ansi[208], '#ff8700');
|
||||
assert.equal(cm.colors.ansi[209], '#ff875f');
|
||||
assert.equal(cm.colors.ansi[210], '#ff8787');
|
||||
assert.equal(cm.colors.ansi[211], '#ff87af');
|
||||
assert.equal(cm.colors.ansi[212], '#ff87d7');
|
||||
assert.equal(cm.colors.ansi[213], '#ff87ff');
|
||||
assert.equal(cm.colors.ansi[214], '#ffaf00');
|
||||
assert.equal(cm.colors.ansi[215], '#ffaf5f');
|
||||
assert.equal(cm.colors.ansi[216], '#ffaf87');
|
||||
assert.equal(cm.colors.ansi[217], '#ffafaf');
|
||||
assert.equal(cm.colors.ansi[218], '#ffafd7');
|
||||
assert.equal(cm.colors.ansi[219], '#ffafff');
|
||||
assert.equal(cm.colors.ansi[220], '#ffd700');
|
||||
assert.equal(cm.colors.ansi[221], '#ffd75f');
|
||||
assert.equal(cm.colors.ansi[222], '#ffd787');
|
||||
assert.equal(cm.colors.ansi[223], '#ffd7af');
|
||||
assert.equal(cm.colors.ansi[224], '#ffd7d7');
|
||||
assert.equal(cm.colors.ansi[225], '#ffd7ff');
|
||||
assert.equal(cm.colors.ansi[226], '#ffff00');
|
||||
assert.equal(cm.colors.ansi[227], '#ffff5f');
|
||||
assert.equal(cm.colors.ansi[228], '#ffff87');
|
||||
assert.equal(cm.colors.ansi[229], '#ffffaf');
|
||||
assert.equal(cm.colors.ansi[230], '#ffffd7');
|
||||
assert.equal(cm.colors.ansi[231], '#ffffff');
|
||||
assert.equal(cm.colors.ansi[232], '#080808');
|
||||
assert.equal(cm.colors.ansi[233], '#121212');
|
||||
assert.equal(cm.colors.ansi[234], '#1c1c1c');
|
||||
assert.equal(cm.colors.ansi[235], '#262626');
|
||||
assert.equal(cm.colors.ansi[236], '#303030');
|
||||
assert.equal(cm.colors.ansi[237], '#3a3a3a');
|
||||
assert.equal(cm.colors.ansi[238], '#444444');
|
||||
assert.equal(cm.colors.ansi[239], '#4e4e4e');
|
||||
assert.equal(cm.colors.ansi[240], '#585858');
|
||||
assert.equal(cm.colors.ansi[241], '#626262');
|
||||
assert.equal(cm.colors.ansi[242], '#6c6c6c');
|
||||
assert.equal(cm.colors.ansi[243], '#767676');
|
||||
assert.equal(cm.colors.ansi[244], '#808080');
|
||||
assert.equal(cm.colors.ansi[245], '#8a8a8a');
|
||||
assert.equal(cm.colors.ansi[246], '#949494');
|
||||
assert.equal(cm.colors.ansi[247], '#9e9e9e');
|
||||
assert.equal(cm.colors.ansi[248], '#a8a8a8');
|
||||
assert.equal(cm.colors.ansi[249], '#b2b2b2');
|
||||
assert.equal(cm.colors.ansi[250], '#bcbcbc');
|
||||
assert.equal(cm.colors.ansi[251], '#c6c6c6');
|
||||
assert.equal(cm.colors.ansi[252], '#d0d0d0');
|
||||
assert.equal(cm.colors.ansi[253], '#dadada');
|
||||
assert.equal(cm.colors.ansi[254], '#e4e4e4');
|
||||
assert.equal(cm.colors.ansi[255], '#eeeeee');
|
||||
assert.equal(cm.colors.ansi[16].css, '#000000');
|
||||
assert.equal(cm.colors.ansi[17].css, '#00005f');
|
||||
assert.equal(cm.colors.ansi[18].css, '#000087');
|
||||
assert.equal(cm.colors.ansi[19].css, '#0000af');
|
||||
assert.equal(cm.colors.ansi[20].css, '#0000d7');
|
||||
assert.equal(cm.colors.ansi[21].css, '#0000ff');
|
||||
assert.equal(cm.colors.ansi[22].css, '#005f00');
|
||||
assert.equal(cm.colors.ansi[23].css, '#005f5f');
|
||||
assert.equal(cm.colors.ansi[24].css, '#005f87');
|
||||
assert.equal(cm.colors.ansi[25].css, '#005faf');
|
||||
assert.equal(cm.colors.ansi[26].css, '#005fd7');
|
||||
assert.equal(cm.colors.ansi[27].css, '#005fff');
|
||||
assert.equal(cm.colors.ansi[28].css, '#008700');
|
||||
assert.equal(cm.colors.ansi[29].css, '#00875f');
|
||||
assert.equal(cm.colors.ansi[30].css, '#008787');
|
||||
assert.equal(cm.colors.ansi[31].css, '#0087af');
|
||||
assert.equal(cm.colors.ansi[32].css, '#0087d7');
|
||||
assert.equal(cm.colors.ansi[33].css, '#0087ff');
|
||||
assert.equal(cm.colors.ansi[34].css, '#00af00');
|
||||
assert.equal(cm.colors.ansi[35].css, '#00af5f');
|
||||
assert.equal(cm.colors.ansi[36].css, '#00af87');
|
||||
assert.equal(cm.colors.ansi[37].css, '#00afaf');
|
||||
assert.equal(cm.colors.ansi[38].css, '#00afd7');
|
||||
assert.equal(cm.colors.ansi[39].css, '#00afff');
|
||||
assert.equal(cm.colors.ansi[40].css, '#00d700');
|
||||
assert.equal(cm.colors.ansi[41].css, '#00d75f');
|
||||
assert.equal(cm.colors.ansi[42].css, '#00d787');
|
||||
assert.equal(cm.colors.ansi[43].css, '#00d7af');
|
||||
assert.equal(cm.colors.ansi[44].css, '#00d7d7');
|
||||
assert.equal(cm.colors.ansi[45].css, '#00d7ff');
|
||||
assert.equal(cm.colors.ansi[46].css, '#00ff00');
|
||||
assert.equal(cm.colors.ansi[47].css, '#00ff5f');
|
||||
assert.equal(cm.colors.ansi[48].css, '#00ff87');
|
||||
assert.equal(cm.colors.ansi[49].css, '#00ffaf');
|
||||
assert.equal(cm.colors.ansi[50].css, '#00ffd7');
|
||||
assert.equal(cm.colors.ansi[51].css, '#00ffff');
|
||||
assert.equal(cm.colors.ansi[52].css, '#5f0000');
|
||||
assert.equal(cm.colors.ansi[53].css, '#5f005f');
|
||||
assert.equal(cm.colors.ansi[54].css, '#5f0087');
|
||||
assert.equal(cm.colors.ansi[55].css, '#5f00af');
|
||||
assert.equal(cm.colors.ansi[56].css, '#5f00d7');
|
||||
assert.equal(cm.colors.ansi[57].css, '#5f00ff');
|
||||
assert.equal(cm.colors.ansi[58].css, '#5f5f00');
|
||||
assert.equal(cm.colors.ansi[59].css, '#5f5f5f');
|
||||
assert.equal(cm.colors.ansi[60].css, '#5f5f87');
|
||||
assert.equal(cm.colors.ansi[61].css, '#5f5faf');
|
||||
assert.equal(cm.colors.ansi[62].css, '#5f5fd7');
|
||||
assert.equal(cm.colors.ansi[63].css, '#5f5fff');
|
||||
assert.equal(cm.colors.ansi[64].css, '#5f8700');
|
||||
assert.equal(cm.colors.ansi[65].css, '#5f875f');
|
||||
assert.equal(cm.colors.ansi[66].css, '#5f8787');
|
||||
assert.equal(cm.colors.ansi[67].css, '#5f87af');
|
||||
assert.equal(cm.colors.ansi[68].css, '#5f87d7');
|
||||
assert.equal(cm.colors.ansi[69].css, '#5f87ff');
|
||||
assert.equal(cm.colors.ansi[70].css, '#5faf00');
|
||||
assert.equal(cm.colors.ansi[71].css, '#5faf5f');
|
||||
assert.equal(cm.colors.ansi[72].css, '#5faf87');
|
||||
assert.equal(cm.colors.ansi[73].css, '#5fafaf');
|
||||
assert.equal(cm.colors.ansi[74].css, '#5fafd7');
|
||||
assert.equal(cm.colors.ansi[75].css, '#5fafff');
|
||||
assert.equal(cm.colors.ansi[76].css, '#5fd700');
|
||||
assert.equal(cm.colors.ansi[77].css, '#5fd75f');
|
||||
assert.equal(cm.colors.ansi[78].css, '#5fd787');
|
||||
assert.equal(cm.colors.ansi[79].css, '#5fd7af');
|
||||
assert.equal(cm.colors.ansi[80].css, '#5fd7d7');
|
||||
assert.equal(cm.colors.ansi[81].css, '#5fd7ff');
|
||||
assert.equal(cm.colors.ansi[82].css, '#5fff00');
|
||||
assert.equal(cm.colors.ansi[83].css, '#5fff5f');
|
||||
assert.equal(cm.colors.ansi[84].css, '#5fff87');
|
||||
assert.equal(cm.colors.ansi[85].css, '#5fffaf');
|
||||
assert.equal(cm.colors.ansi[86].css, '#5fffd7');
|
||||
assert.equal(cm.colors.ansi[87].css, '#5fffff');
|
||||
assert.equal(cm.colors.ansi[88].css, '#870000');
|
||||
assert.equal(cm.colors.ansi[89].css, '#87005f');
|
||||
assert.equal(cm.colors.ansi[90].css, '#870087');
|
||||
assert.equal(cm.colors.ansi[91].css, '#8700af');
|
||||
assert.equal(cm.colors.ansi[92].css, '#8700d7');
|
||||
assert.equal(cm.colors.ansi[93].css, '#8700ff');
|
||||
assert.equal(cm.colors.ansi[94].css, '#875f00');
|
||||
assert.equal(cm.colors.ansi[95].css, '#875f5f');
|
||||
assert.equal(cm.colors.ansi[96].css, '#875f87');
|
||||
assert.equal(cm.colors.ansi[97].css, '#875faf');
|
||||
assert.equal(cm.colors.ansi[98].css, '#875fd7');
|
||||
assert.equal(cm.colors.ansi[99].css, '#875fff');
|
||||
assert.equal(cm.colors.ansi[100].css, '#878700');
|
||||
assert.equal(cm.colors.ansi[101].css, '#87875f');
|
||||
assert.equal(cm.colors.ansi[102].css, '#878787');
|
||||
assert.equal(cm.colors.ansi[103].css, '#8787af');
|
||||
assert.equal(cm.colors.ansi[104].css, '#8787d7');
|
||||
assert.equal(cm.colors.ansi[105].css, '#8787ff');
|
||||
assert.equal(cm.colors.ansi[106].css, '#87af00');
|
||||
assert.equal(cm.colors.ansi[107].css, '#87af5f');
|
||||
assert.equal(cm.colors.ansi[108].css, '#87af87');
|
||||
assert.equal(cm.colors.ansi[109].css, '#87afaf');
|
||||
assert.equal(cm.colors.ansi[110].css, '#87afd7');
|
||||
assert.equal(cm.colors.ansi[111].css, '#87afff');
|
||||
assert.equal(cm.colors.ansi[112].css, '#87d700');
|
||||
assert.equal(cm.colors.ansi[113].css, '#87d75f');
|
||||
assert.equal(cm.colors.ansi[114].css, '#87d787');
|
||||
assert.equal(cm.colors.ansi[115].css, '#87d7af');
|
||||
assert.equal(cm.colors.ansi[116].css, '#87d7d7');
|
||||
assert.equal(cm.colors.ansi[117].css, '#87d7ff');
|
||||
assert.equal(cm.colors.ansi[118].css, '#87ff00');
|
||||
assert.equal(cm.colors.ansi[119].css, '#87ff5f');
|
||||
assert.equal(cm.colors.ansi[120].css, '#87ff87');
|
||||
assert.equal(cm.colors.ansi[121].css, '#87ffaf');
|
||||
assert.equal(cm.colors.ansi[122].css, '#87ffd7');
|
||||
assert.equal(cm.colors.ansi[123].css, '#87ffff');
|
||||
assert.equal(cm.colors.ansi[124].css, '#af0000');
|
||||
assert.equal(cm.colors.ansi[125].css, '#af005f');
|
||||
assert.equal(cm.colors.ansi[126].css, '#af0087');
|
||||
assert.equal(cm.colors.ansi[127].css, '#af00af');
|
||||
assert.equal(cm.colors.ansi[128].css, '#af00d7');
|
||||
assert.equal(cm.colors.ansi[129].css, '#af00ff');
|
||||
assert.equal(cm.colors.ansi[130].css, '#af5f00');
|
||||
assert.equal(cm.colors.ansi[131].css, '#af5f5f');
|
||||
assert.equal(cm.colors.ansi[132].css, '#af5f87');
|
||||
assert.equal(cm.colors.ansi[133].css, '#af5faf');
|
||||
assert.equal(cm.colors.ansi[134].css, '#af5fd7');
|
||||
assert.equal(cm.colors.ansi[135].css, '#af5fff');
|
||||
assert.equal(cm.colors.ansi[136].css, '#af8700');
|
||||
assert.equal(cm.colors.ansi[137].css, '#af875f');
|
||||
assert.equal(cm.colors.ansi[138].css, '#af8787');
|
||||
assert.equal(cm.colors.ansi[139].css, '#af87af');
|
||||
assert.equal(cm.colors.ansi[140].css, '#af87d7');
|
||||
assert.equal(cm.colors.ansi[141].css, '#af87ff');
|
||||
assert.equal(cm.colors.ansi[142].css, '#afaf00');
|
||||
assert.equal(cm.colors.ansi[143].css, '#afaf5f');
|
||||
assert.equal(cm.colors.ansi[144].css, '#afaf87');
|
||||
assert.equal(cm.colors.ansi[145].css, '#afafaf');
|
||||
assert.equal(cm.colors.ansi[146].css, '#afafd7');
|
||||
assert.equal(cm.colors.ansi[147].css, '#afafff');
|
||||
assert.equal(cm.colors.ansi[148].css, '#afd700');
|
||||
assert.equal(cm.colors.ansi[149].css, '#afd75f');
|
||||
assert.equal(cm.colors.ansi[150].css, '#afd787');
|
||||
assert.equal(cm.colors.ansi[151].css, '#afd7af');
|
||||
assert.equal(cm.colors.ansi[152].css, '#afd7d7');
|
||||
assert.equal(cm.colors.ansi[153].css, '#afd7ff');
|
||||
assert.equal(cm.colors.ansi[154].css, '#afff00');
|
||||
assert.equal(cm.colors.ansi[155].css, '#afff5f');
|
||||
assert.equal(cm.colors.ansi[156].css, '#afff87');
|
||||
assert.equal(cm.colors.ansi[157].css, '#afffaf');
|
||||
assert.equal(cm.colors.ansi[158].css, '#afffd7');
|
||||
assert.equal(cm.colors.ansi[159].css, '#afffff');
|
||||
assert.equal(cm.colors.ansi[160].css, '#d70000');
|
||||
assert.equal(cm.colors.ansi[161].css, '#d7005f');
|
||||
assert.equal(cm.colors.ansi[162].css, '#d70087');
|
||||
assert.equal(cm.colors.ansi[163].css, '#d700af');
|
||||
assert.equal(cm.colors.ansi[164].css, '#d700d7');
|
||||
assert.equal(cm.colors.ansi[165].css, '#d700ff');
|
||||
assert.equal(cm.colors.ansi[166].css, '#d75f00');
|
||||
assert.equal(cm.colors.ansi[167].css, '#d75f5f');
|
||||
assert.equal(cm.colors.ansi[168].css, '#d75f87');
|
||||
assert.equal(cm.colors.ansi[169].css, '#d75faf');
|
||||
assert.equal(cm.colors.ansi[170].css, '#d75fd7');
|
||||
assert.equal(cm.colors.ansi[171].css, '#d75fff');
|
||||
assert.equal(cm.colors.ansi[172].css, '#d78700');
|
||||
assert.equal(cm.colors.ansi[173].css, '#d7875f');
|
||||
assert.equal(cm.colors.ansi[174].css, '#d78787');
|
||||
assert.equal(cm.colors.ansi[175].css, '#d787af');
|
||||
assert.equal(cm.colors.ansi[176].css, '#d787d7');
|
||||
assert.equal(cm.colors.ansi[177].css, '#d787ff');
|
||||
assert.equal(cm.colors.ansi[178].css, '#d7af00');
|
||||
assert.equal(cm.colors.ansi[179].css, '#d7af5f');
|
||||
assert.equal(cm.colors.ansi[180].css, '#d7af87');
|
||||
assert.equal(cm.colors.ansi[181].css, '#d7afaf');
|
||||
assert.equal(cm.colors.ansi[182].css, '#d7afd7');
|
||||
assert.equal(cm.colors.ansi[183].css, '#d7afff');
|
||||
assert.equal(cm.colors.ansi[184].css, '#d7d700');
|
||||
assert.equal(cm.colors.ansi[185].css, '#d7d75f');
|
||||
assert.equal(cm.colors.ansi[186].css, '#d7d787');
|
||||
assert.equal(cm.colors.ansi[187].css, '#d7d7af');
|
||||
assert.equal(cm.colors.ansi[188].css, '#d7d7d7');
|
||||
assert.equal(cm.colors.ansi[189].css, '#d7d7ff');
|
||||
assert.equal(cm.colors.ansi[190].css, '#d7ff00');
|
||||
assert.equal(cm.colors.ansi[191].css, '#d7ff5f');
|
||||
assert.equal(cm.colors.ansi[192].css, '#d7ff87');
|
||||
assert.equal(cm.colors.ansi[193].css, '#d7ffaf');
|
||||
assert.equal(cm.colors.ansi[194].css, '#d7ffd7');
|
||||
assert.equal(cm.colors.ansi[195].css, '#d7ffff');
|
||||
assert.equal(cm.colors.ansi[196].css, '#ff0000');
|
||||
assert.equal(cm.colors.ansi[197].css, '#ff005f');
|
||||
assert.equal(cm.colors.ansi[198].css, '#ff0087');
|
||||
assert.equal(cm.colors.ansi[199].css, '#ff00af');
|
||||
assert.equal(cm.colors.ansi[200].css, '#ff00d7');
|
||||
assert.equal(cm.colors.ansi[201].css, '#ff00ff');
|
||||
assert.equal(cm.colors.ansi[202].css, '#ff5f00');
|
||||
assert.equal(cm.colors.ansi[203].css, '#ff5f5f');
|
||||
assert.equal(cm.colors.ansi[204].css, '#ff5f87');
|
||||
assert.equal(cm.colors.ansi[205].css, '#ff5faf');
|
||||
assert.equal(cm.colors.ansi[206].css, '#ff5fd7');
|
||||
assert.equal(cm.colors.ansi[207].css, '#ff5fff');
|
||||
assert.equal(cm.colors.ansi[208].css, '#ff8700');
|
||||
assert.equal(cm.colors.ansi[209].css, '#ff875f');
|
||||
assert.equal(cm.colors.ansi[210].css, '#ff8787');
|
||||
assert.equal(cm.colors.ansi[211].css, '#ff87af');
|
||||
assert.equal(cm.colors.ansi[212].css, '#ff87d7');
|
||||
assert.equal(cm.colors.ansi[213].css, '#ff87ff');
|
||||
assert.equal(cm.colors.ansi[214].css, '#ffaf00');
|
||||
assert.equal(cm.colors.ansi[215].css, '#ffaf5f');
|
||||
assert.equal(cm.colors.ansi[216].css, '#ffaf87');
|
||||
assert.equal(cm.colors.ansi[217].css, '#ffafaf');
|
||||
assert.equal(cm.colors.ansi[218].css, '#ffafd7');
|
||||
assert.equal(cm.colors.ansi[219].css, '#ffafff');
|
||||
assert.equal(cm.colors.ansi[220].css, '#ffd700');
|
||||
assert.equal(cm.colors.ansi[221].css, '#ffd75f');
|
||||
assert.equal(cm.colors.ansi[222].css, '#ffd787');
|
||||
assert.equal(cm.colors.ansi[223].css, '#ffd7af');
|
||||
assert.equal(cm.colors.ansi[224].css, '#ffd7d7');
|
||||
assert.equal(cm.colors.ansi[225].css, '#ffd7ff');
|
||||
assert.equal(cm.colors.ansi[226].css, '#ffff00');
|
||||
assert.equal(cm.colors.ansi[227].css, '#ffff5f');
|
||||
assert.equal(cm.colors.ansi[228].css, '#ffff87');
|
||||
assert.equal(cm.colors.ansi[229].css, '#ffffaf');
|
||||
assert.equal(cm.colors.ansi[230].css, '#ffffd7');
|
||||
assert.equal(cm.colors.ansi[231].css, '#ffffff');
|
||||
assert.equal(cm.colors.ansi[232].css, '#080808');
|
||||
assert.equal(cm.colors.ansi[233].css, '#121212');
|
||||
assert.equal(cm.colors.ansi[234].css, '#1c1c1c');
|
||||
assert.equal(cm.colors.ansi[235].css, '#262626');
|
||||
assert.equal(cm.colors.ansi[236].css, '#303030');
|
||||
assert.equal(cm.colors.ansi[237].css, '#3a3a3a');
|
||||
assert.equal(cm.colors.ansi[238].css, '#444444');
|
||||
assert.equal(cm.colors.ansi[239].css, '#4e4e4e');
|
||||
assert.equal(cm.colors.ansi[240].css, '#585858');
|
||||
assert.equal(cm.colors.ansi[241].css, '#626262');
|
||||
assert.equal(cm.colors.ansi[242].css, '#6c6c6c');
|
||||
assert.equal(cm.colors.ansi[243].css, '#767676');
|
||||
assert.equal(cm.colors.ansi[244].css, '#808080');
|
||||
assert.equal(cm.colors.ansi[245].css, '#8a8a8a');
|
||||
assert.equal(cm.colors.ansi[246].css, '#949494');
|
||||
assert.equal(cm.colors.ansi[247].css, '#9e9e9e');
|
||||
assert.equal(cm.colors.ansi[248].css, '#a8a8a8');
|
||||
assert.equal(cm.colors.ansi[249].css, '#b2b2b2');
|
||||
assert.equal(cm.colors.ansi[250].css, '#bcbcbc');
|
||||
assert.equal(cm.colors.ansi[251].css, '#c6c6c6');
|
||||
assert.equal(cm.colors.ansi[252].css, '#d0d0d0');
|
||||
assert.equal(cm.colors.ansi[253].css, '#dadada');
|
||||
assert.equal(cm.colors.ansi[254].css, '#e4e4e4');
|
||||
assert.equal(cm.colors.ansi[255].css, '#eeeeee');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -283,20 +294,20 @@ describe('ColorManager', () => {
|
||||
});
|
||||
|
||||
it('should set a partial set of colors, using the default if not present', () => {
|
||||
assert.equal(cm.colors.background, '#000000');
|
||||
assert.equal(cm.colors.foreground, '#ffffff');
|
||||
assert.equal(cm.colors.background.css, '#000000');
|
||||
assert.equal(cm.colors.foreground.css, '#ffffff');
|
||||
cm.setTheme({
|
||||
background: '#FF0000',
|
||||
foreground: '#00FF00'
|
||||
});
|
||||
assert.equal(cm.colors.background, '#FF0000');
|
||||
assert.equal(cm.colors.foreground, '#00FF00');
|
||||
assert.equal(cm.colors.background.css, '#FF0000');
|
||||
assert.equal(cm.colors.foreground.css, '#00FF00');
|
||||
cm.setTheme({
|
||||
background: '#0000FF'
|
||||
});
|
||||
assert.equal(cm.colors.background, '#0000FF');
|
||||
assert.equal(cm.colors.background.css, '#0000FF');
|
||||
// FG reverts back to default
|
||||
assert.equal(cm.colors.foreground, '#ffffff');
|
||||
assert.equal(cm.colors.foreground.css, '#ffffff');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+128
-81
@@ -3,58 +3,75 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { IColorSet, IColorManager } from './Types';
|
||||
import { IColorManager } from './Types';
|
||||
import { IColor, IColorSet } from '../shared/Types';
|
||||
import { ITheme } from 'xterm';
|
||||
|
||||
const DEFAULT_FOREGROUND = '#ffffff';
|
||||
const DEFAULT_BACKGROUND = '#000000';
|
||||
const DEFAULT_CURSOR = '#ffffff';
|
||||
const DEFAULT_CURSOR_ACCENT = '#000000';
|
||||
const DEFAULT_SELECTION = 'rgba(255, 255, 255, 0.3)';
|
||||
export const DEFAULT_ANSI_COLORS = [
|
||||
// dark:
|
||||
'#2e3436',
|
||||
'#cc0000',
|
||||
'#4e9a06',
|
||||
'#c4a000',
|
||||
'#3465a4',
|
||||
'#75507b',
|
||||
'#06989a',
|
||||
'#d3d7cf',
|
||||
// bright:
|
||||
'#555753',
|
||||
'#ef2929',
|
||||
'#8ae234',
|
||||
'#fce94f',
|
||||
'#729fcf',
|
||||
'#ad7fa8',
|
||||
'#34e2e2',
|
||||
'#eeeeec'
|
||||
];
|
||||
const DEFAULT_FOREGROUND = fromHex('#ffffff');
|
||||
const DEFAULT_BACKGROUND = fromHex('#000000');
|
||||
const DEFAULT_CURSOR = fromHex('#ffffff');
|
||||
const DEFAULT_CURSOR_ACCENT = fromHex('#000000');
|
||||
const DEFAULT_SELECTION = {
|
||||
css: 'rgba(255, 255, 255, 0.3)',
|
||||
rgba: 0xFFFFFF77
|
||||
};
|
||||
|
||||
/**
|
||||
* Fills an existing 16 length string with the remaining 240 ANSI colors.
|
||||
* @param first16Colors The first 16 ANSI colors.
|
||||
*/
|
||||
function generate256Colors(first16Colors: string[]): string[] {
|
||||
let colors = first16Colors.slice();
|
||||
// An IIFE to generate DEFAULT_ANSI_COLORS. Do not mutate DEFAULT_ANSI_COLORS, instead make a copy
|
||||
// and mutate that.
|
||||
export const DEFAULT_ANSI_COLORS = (() => {
|
||||
const colors = [
|
||||
// dark:
|
||||
fromHex('#2e3436'),
|
||||
fromHex('#cc0000'),
|
||||
fromHex('#4e9a06'),
|
||||
fromHex('#c4a000'),
|
||||
fromHex('#3465a4'),
|
||||
fromHex('#75507b'),
|
||||
fromHex('#06989a'),
|
||||
fromHex('#d3d7cf'),
|
||||
// bright:
|
||||
fromHex('#555753'),
|
||||
fromHex('#ef2929'),
|
||||
fromHex('#8ae234'),
|
||||
fromHex('#fce94f'),
|
||||
fromHex('#729fcf'),
|
||||
fromHex('#ad7fa8'),
|
||||
fromHex('#34e2e2'),
|
||||
fromHex('#eeeeec')
|
||||
];
|
||||
|
||||
// Fill in the remaining 240 ANSI colors.
|
||||
// Generate colors (16-231)
|
||||
let v = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff];
|
||||
for (let i = 0; i < 216; i++) {
|
||||
const r = toPaddedHex(v[(i / 36) % 6 | 0]);
|
||||
const g = toPaddedHex(v[(i / 6) % 6 | 0]);
|
||||
const b = toPaddedHex(v[i % 6]);
|
||||
colors.push(`#${r}${g}${b}`);
|
||||
const r = v[(i / 36) % 6 | 0];
|
||||
const g = v[(i / 6) % 6 | 0];
|
||||
const b = v[i % 6];
|
||||
colors.push({
|
||||
css: `#${toPaddedHex(r)}${toPaddedHex(g)}${toPaddedHex(b)}`,
|
||||
// Use >>> 0 to force a conversion to an unsigned int
|
||||
rgba: ((r << 24) | (g << 16) | (b << 8) | 0xFF) >>> 0
|
||||
});
|
||||
}
|
||||
|
||||
// Generate greys (232-255)
|
||||
for (let i = 0; i < 24; i++) {
|
||||
const c = toPaddedHex(8 + i * 10);
|
||||
colors.push(`#${c}${c}${c}`);
|
||||
const c = 8 + i * 10;
|
||||
const ch = toPaddedHex(c);
|
||||
colors.push({
|
||||
css: `#${ch}${ch}${ch}`,
|
||||
rgba: ((c << 24) | (c << 16) | (c << 8) | 0xFF) >>> 0
|
||||
});
|
||||
}
|
||||
|
||||
return colors;
|
||||
})();
|
||||
|
||||
function fromHex(css: string): IColor {
|
||||
return {
|
||||
css,
|
||||
rgba: parseInt(css.slice(1), 16) << 8 | 0xFF
|
||||
};
|
||||
}
|
||||
|
||||
function toPaddedHex(c: number): string {
|
||||
@@ -67,17 +84,23 @@ function toPaddedHex(c: number): string {
|
||||
*/
|
||||
export class ColorManager implements IColorManager {
|
||||
public colors: IColorSet;
|
||||
private _document: Document;
|
||||
private _ctx: CanvasRenderingContext2D;
|
||||
private _litmusColor: CanvasGradient;
|
||||
|
||||
constructor(document: Document) {
|
||||
this._document = document;
|
||||
constructor(document: Document, public allowTransparency: boolean) {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = 1;
|
||||
canvas.height = 1;
|
||||
this._ctx = canvas.getContext('2d');
|
||||
this._ctx.globalCompositeOperation = 'copy';
|
||||
this._litmusColor = this._ctx.createLinearGradient(0, 0, 1, 1);
|
||||
this.colors = {
|
||||
foreground: DEFAULT_FOREGROUND,
|
||||
background: DEFAULT_BACKGROUND,
|
||||
cursor: DEFAULT_CURSOR,
|
||||
cursorAccent: DEFAULT_CURSOR_ACCENT,
|
||||
selection: DEFAULT_SELECTION,
|
||||
ansi: generate256Colors(DEFAULT_ANSI_COLORS)
|
||||
ansi: DEFAULT_ANSI_COLORS.slice()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -87,54 +110,78 @@ export class ColorManager implements IColorManager {
|
||||
* colors will be used where colors are not defined.
|
||||
*/
|
||||
public setTheme(theme: ITheme): void {
|
||||
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]);
|
||||
this.colors.foreground = this._parseColor(theme.foreground, DEFAULT_FOREGROUND);
|
||||
this.colors.background = this._parseColor(theme.background, DEFAULT_BACKGROUND);
|
||||
this.colors.cursor = this._parseColor(theme.cursor, DEFAULT_CURSOR, true);
|
||||
this.colors.cursorAccent = this._parseColor(theme.cursorAccent, DEFAULT_CURSOR_ACCENT, true);
|
||||
this.colors.selection = this._parseColor(theme.selection, DEFAULT_SELECTION, true);
|
||||
this.colors.ansi[0] = this._parseColor(theme.black, DEFAULT_ANSI_COLORS[0]);
|
||||
this.colors.ansi[1] = this._parseColor(theme.red, DEFAULT_ANSI_COLORS[1]);
|
||||
this.colors.ansi[2] = this._parseColor(theme.green, DEFAULT_ANSI_COLORS[2]);
|
||||
this.colors.ansi[3] = this._parseColor(theme.yellow, DEFAULT_ANSI_COLORS[3]);
|
||||
this.colors.ansi[4] = this._parseColor(theme.blue, DEFAULT_ANSI_COLORS[4]);
|
||||
this.colors.ansi[5] = this._parseColor(theme.magenta, DEFAULT_ANSI_COLORS[5]);
|
||||
this.colors.ansi[6] = this._parseColor(theme.cyan, DEFAULT_ANSI_COLORS[6]);
|
||||
this.colors.ansi[7] = this._parseColor(theme.white, DEFAULT_ANSI_COLORS[7]);
|
||||
this.colors.ansi[8] = this._parseColor(theme.brightBlack, DEFAULT_ANSI_COLORS[8]);
|
||||
this.colors.ansi[9] = this._parseColor(theme.brightRed, DEFAULT_ANSI_COLORS[9]);
|
||||
this.colors.ansi[10] = this._parseColor(theme.brightGreen, DEFAULT_ANSI_COLORS[10]);
|
||||
this.colors.ansi[11] = this._parseColor(theme.brightYellow, DEFAULT_ANSI_COLORS[11]);
|
||||
this.colors.ansi[12] = this._parseColor(theme.brightBlue, DEFAULT_ANSI_COLORS[12]);
|
||||
this.colors.ansi[13] = this._parseColor(theme.brightMagenta, DEFAULT_ANSI_COLORS[13]);
|
||||
this.colors.ansi[14] = this._parseColor(theme.brightCyan, DEFAULT_ANSI_COLORS[14]);
|
||||
this.colors.ansi[15] = this._parseColor(theme.brightWhite, DEFAULT_ANSI_COLORS[15]);
|
||||
}
|
||||
|
||||
private _validateColor(color: string, fallback: string): string {
|
||||
if (!color) {
|
||||
private _parseColor(
|
||||
css: string,
|
||||
fallback: IColor,
|
||||
allowTransparency: boolean = this.allowTransparency
|
||||
): IColor {
|
||||
if (!css) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
const isColorValid = this._isColorValid(color);
|
||||
|
||||
if (!isColorValid) {
|
||||
console.warn(`Color: ${color} is invalid using fallback ${fallback}`);
|
||||
// If parsing the value results in failure, then it must be ignored, and the attribute must
|
||||
// retain its previous value.
|
||||
// -- https://html.spec.whatwg.org/multipage/canvas.html#fill-and-stroke-styles
|
||||
this._ctx.fillStyle = this._litmusColor;
|
||||
this._ctx.fillStyle = css;
|
||||
if (typeof this._ctx.fillStyle !== 'string') {
|
||||
console.warn(`Color: ${css} is invalid using fallback ${fallback.css}`);
|
||||
return fallback;
|
||||
}
|
||||
|
||||
return isColorValid ? color : fallback;
|
||||
}
|
||||
this._ctx.fillRect(0, 0, 1, 1);
|
||||
const data = this._ctx.getImageData(0, 0, 1, 1).data;
|
||||
|
||||
private _isColorValid(color: string): boolean {
|
||||
const litmus = 'red';
|
||||
const d = this._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;
|
||||
if (!allowTransparency && data[3] !== 0xFF) {
|
||||
// Ideally we'd just ignore the alpha channel, but...
|
||||
//
|
||||
// Browsers may not give back exactly the same RGB values we put in, because most/all
|
||||
// convert the color to a pre-multiplied representation. getImageData converts that back to
|
||||
// a un-premultipled representation, but the precision loss may make the RGB channels unuable
|
||||
// on their own.
|
||||
//
|
||||
// E.g. In Chrome #12345610 turns into #10305010, and in the extreme case, 0xFFFFFF00 turns
|
||||
// into 0x00000000.
|
||||
//
|
||||
// "Note: Due to the lossy nature of converting to and from premultiplied alpha color values,
|
||||
// pixels that have just been set using putImageData() might be returned to an equivalent
|
||||
// getImageData() as different values."
|
||||
// -- https://html.spec.whatwg.org/multipage/canvas.html#pixel-manipulation
|
||||
//
|
||||
// So let's just use the fallback color in this case instead.
|
||||
console.warn(
|
||||
`Color: ${css} is using transparency, but allowTransparency is false. ` +
|
||||
`Using fallback ${fallback.css}.`
|
||||
);
|
||||
return fallback;
|
||||
}
|
||||
|
||||
return true;
|
||||
return {
|
||||
css,
|
||||
rgba: (data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]) >>> 0
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ export class CursorRenderLayer extends BaseRenderLayer {
|
||||
if (!terminal.isFocused) {
|
||||
this._clearCursor();
|
||||
this._ctx.save();
|
||||
this._ctx.fillStyle = this._colors.cursor;
|
||||
this._ctx.fillStyle = this._colors.cursor.css;
|
||||
this._renderBlurCursor(terminal, terminal.buffer.x, viewportRelativeCursorY, charData);
|
||||
this._ctx.restore();
|
||||
this._state.x = terminal.buffer.x;
|
||||
@@ -190,30 +190,30 @@ export class CursorRenderLayer extends BaseRenderLayer {
|
||||
|
||||
private _renderBarCursor(terminal: ITerminal, x: number, y: number, charData: CharData): void {
|
||||
this._ctx.save();
|
||||
this._ctx.fillStyle = this._colors.cursor;
|
||||
this._ctx.fillStyle = this._colors.cursor.css;
|
||||
this.fillLeftLineAtCell(x, y);
|
||||
this._ctx.restore();
|
||||
}
|
||||
|
||||
private _renderBlockCursor(terminal: ITerminal, x: number, y: number, charData: CharData): void {
|
||||
this._ctx.save();
|
||||
this._ctx.fillStyle = this._colors.cursor;
|
||||
this._ctx.fillStyle = this._colors.cursor.css;
|
||||
this.fillCells(x, y, charData[CHAR_DATA_WIDTH_INDEX], 1);
|
||||
this._ctx.fillStyle = this._colors.cursorAccent;
|
||||
this._ctx.fillStyle = this._colors.cursorAccent.css;
|
||||
this.fillCharTrueColor(terminal, charData, x, y);
|
||||
this._ctx.restore();
|
||||
}
|
||||
|
||||
private _renderUnderlineCursor(terminal: ITerminal, x: number, y: number, charData: CharData): void {
|
||||
this._ctx.save();
|
||||
this._ctx.fillStyle = this._colors.cursor;
|
||||
this._ctx.fillStyle = this._colors.cursor.css;
|
||||
this.fillBottomLineAtCells(x, y);
|
||||
this._ctx.restore();
|
||||
}
|
||||
|
||||
private _renderBlurCursor(terminal: ITerminal, x: number, y: number, charData: CharData): void {
|
||||
this._ctx.save();
|
||||
this._ctx.strokeStyle = this._colors.cursor;
|
||||
this._ctx.strokeStyle = this._colors.cursor.css;
|
||||
this.strokeRectAtCell(x, y, charData[CHAR_DATA_WIDTH_INDEX], 1);
|
||||
this._ctx.restore();
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ export class LinkRenderLayer extends BaseRenderLayer {
|
||||
}
|
||||
|
||||
private _onLinkHover(e: ILinkHoverEvent): void {
|
||||
this._ctx.fillStyle = this._colors.foreground;
|
||||
this._ctx.fillStyle = this._colors.foreground.css;
|
||||
if (e.y1 === e.y2) {
|
||||
// Single line link
|
||||
this.fillBottomLineAtCells(e.x1, e.y1, e.x2 - e.x1);
|
||||
|
||||
@@ -29,13 +29,14 @@ export class Renderer extends EventEmitter implements IRenderer {
|
||||
|
||||
constructor(private _terminal: ITerminal, theme: ITheme) {
|
||||
super();
|
||||
this.colorManager = new ColorManager(document);
|
||||
const allowTransparency = this._terminal.options.allowTransparency;
|
||||
this.colorManager = new ColorManager(document, allowTransparency);
|
||||
if (theme) {
|
||||
this.colorManager.setTheme(theme);
|
||||
}
|
||||
|
||||
this._renderLayers = [
|
||||
new TextRenderLayer(this._terminal.screenElement, 0, this.colorManager.colors, this._terminal.options.allowTransparency),
|
||||
new TextRenderLayer(this._terminal.screenElement, 0, this.colorManager.colors, allowTransparency),
|
||||
new SelectionRenderLayer(this._terminal.screenElement, 1, this.colorManager.colors),
|
||||
new LinkRenderLayer(this._terminal.screenElement, 2, this.colorManager.colors, this._terminal),
|
||||
new CursorRenderLayer(this._terminal.screenElement, 3, this.colorManager.colors)
|
||||
|
||||
@@ -65,7 +65,7 @@ export class SelectionRenderLayer extends BaseRenderLayer {
|
||||
// Draw first row
|
||||
const startCol = viewportStartRow === viewportCappedStartRow ? start[0] : 0;
|
||||
const startRowEndCol = viewportCappedStartRow === viewportCappedEndRow ? end[0] : terminal.cols;
|
||||
this._ctx.fillStyle = this._colors.selection;
|
||||
this._ctx.fillStyle = this._colors.selection.css;
|
||||
this.fillCells(startCol, viewportCappedStartRow, startRowEndCol - startCol, 1);
|
||||
|
||||
// Draw middle rows
|
||||
|
||||
@@ -158,7 +158,7 @@ export class TextRenderLayer extends BaseRenderLayer {
|
||||
// Draw background
|
||||
if (bg < 256) {
|
||||
this._ctx.save();
|
||||
this._ctx.fillStyle = (bg === INVERTED_DEFAULT_COLOR ? this._colors.foreground : this._colors.ansi[bg]);
|
||||
this._ctx.fillStyle = (bg === INVERTED_DEFAULT_COLOR ? this._colors.foreground.css : this._colors.ansi[bg].css);
|
||||
this.fillCells(x, y, width, 1);
|
||||
this._ctx.restore();
|
||||
}
|
||||
@@ -174,12 +174,12 @@ export class TextRenderLayer extends BaseRenderLayer {
|
||||
|
||||
if (flags & FLAGS.UNDERLINE) {
|
||||
if (fg === INVERTED_DEFAULT_COLOR) {
|
||||
this._ctx.fillStyle = this._colors.background;
|
||||
this._ctx.fillStyle = this._colors.background.css;
|
||||
} else if (fg < 256) {
|
||||
// 256 color support
|
||||
this._ctx.fillStyle = this._colors.ansi[fg];
|
||||
this._ctx.fillStyle = this._colors.ansi[fg].css;
|
||||
} else {
|
||||
this._ctx.fillStyle = this._colors.foreground;
|
||||
this._ctx.fillStyle = this._colors.foreground.css;
|
||||
}
|
||||
this.fillBottomLineAtCells(x, y);
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ export function generateConfig(scaledCharWidth: number, scaledCharHeight: number
|
||||
|
||||
export function configEquals(a: ICharAtlasConfig, b: ICharAtlasConfig): boolean {
|
||||
for (let i = 0; i < a.colors.ansi.length; i++) {
|
||||
if (a.colors.ansi[i] !== b.colors.ansi[i]) {
|
||||
if (a.colors.ansi[i].rgba !== b.colors.ansi[i].rgba) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+12
-7
@@ -3,11 +3,16 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
export interface IColorSet {
|
||||
foreground: string;
|
||||
background: string;
|
||||
cursor: string;
|
||||
cursorAccent: string;
|
||||
selection: string;
|
||||
ansi: string[];
|
||||
export interface IColor {
|
||||
css: string;
|
||||
rgba: number; // 32-bit int with rgba in each byte
|
||||
}
|
||||
|
||||
export interface IColorSet {
|
||||
foreground: IColor;
|
||||
background: IColor;
|
||||
cursor: IColor;
|
||||
cursorAccent: IColor;
|
||||
selection: IColor;
|
||||
ansi: IColor[];
|
||||
}
|
||||
|
||||
@@ -31,11 +31,11 @@ export function generateCharAtlas(context: Window, canvasFactory: (width: number
|
||||
);
|
||||
const ctx = canvas.getContext('2d', {alpha: config.allowTransparency});
|
||||
|
||||
ctx.fillStyle = config.colors.background;
|
||||
ctx.fillStyle = config.colors.background.css;
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
ctx.save();
|
||||
ctx.fillStyle = config.colors.foreground;
|
||||
ctx.fillStyle = config.colors.foreground.css;
|
||||
ctx.font = getFont(config.fontWeight, config);
|
||||
ctx.textBaseline = 'top';
|
||||
|
||||
@@ -75,7 +75,7 @@ export function generateCharAtlas(context: Window, canvasFactory: (width: number
|
||||
ctx.beginPath();
|
||||
ctx.rect(i * cellWidth, y, cellWidth, cellHeight);
|
||||
ctx.clip();
|
||||
ctx.fillStyle = config.colors.ansi[colorIndex];
|
||||
ctx.fillStyle = config.colors.ansi[colorIndex].css;
|
||||
ctx.fillText(String.fromCharCode(i), i * cellWidth, y);
|
||||
ctx.restore();
|
||||
}
|
||||
@@ -100,9 +100,9 @@ export function generateCharAtlas(context: Window, canvasFactory: (width: number
|
||||
const charAtlasImageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Remove the background color from the image so characters may overlap
|
||||
const r = parseInt(config.colors.background.substr(1, 2), 16);
|
||||
const g = parseInt(config.colors.background.substr(3, 2), 16);
|
||||
const b = parseInt(config.colors.background.substr(5, 2), 16);
|
||||
const r = config.colors.background.rgba >>> 24;
|
||||
const g = config.colors.background.rgba >>> 16 & 0xFF;
|
||||
const b = config.colors.background.rgba >>> 8 & 0xFF;
|
||||
clearColor(charAtlasImageData, r, g, b);
|
||||
|
||||
return context.createImageBitmap(charAtlasImageData);
|
||||
|
||||
Reference in New Issue
Block a user