diff --git a/README.md b/README.md index 85c2ac18..730fc9af 100644 --- a/README.md +++ b/README.md @@ -166,6 +166,10 @@ Xterm.js is maintained by [SourceLair](https://www.sourcelair.com/) and a few ex To contribute either code, documentation or issues to xterm.js please read the [Contributing document](CONTRIBUTING.md) beforehand. The development of xterm.js does not require any special tool. All you need is an editor that supports JavaScript/TypeScript and a browser. You will need Node.js installed locally to get all the features working in the demo. +### Code structure + +`src/` is roughly split up into areas of functionality such as `renderer/` that handles all rendering and `utils/` which provides general utility functions. The `shared/` folder contains code that can be used from either the main thread or a web worker thread, all code inside a `shared/` folder should only ever import other code from a `shared/` folder to minimize the amount of code run what launching a web worker. + ## License Agreement If you contribute code to this project, you are implicitly allowing your code to be distributed under the MIT license. You are also implicitly verifying that all code is your original work. diff --git a/fixtures/typings-test/typings-test.ts b/fixtures/typings-test/typings-test.ts index 2f244422..7bbaf214 100644 --- a/fixtures/typings-test/typings-test.ts +++ b/fixtures/typings-test/typings-test.ts @@ -160,6 +160,7 @@ namespace methods_core { t.setOption('cursorBlink', true); t.setOption('debug', true); t.setOption('disableStdin', true); + t.setOption('enableBold', true); t.setOption('fontWeight', 'normal'); t.setOption('fontWeight', 'bold'); t.setOption('fontWeightBold', 'normal'); diff --git a/package.json b/package.json index 6b1eb230..cf3df57b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "xterm", "description": "Full xterm terminal, in your browser", - "version": "3.0.0", + "version": "3.1.0-master", "ignore": [ "demo", "test", diff --git a/src/Buffer.ts b/src/Buffer.ts index 3e7d6122..39b0726c 100644 --- a/src/Buffer.ts +++ b/src/Buffer.ts @@ -177,16 +177,13 @@ export class Buffer implements IBuffer { } // Make sure that the cursor stays on screen - if (this.y >= newRows) { - this.y = newRows - 1; - } + this.x = Math.min(this.x, newCols - 1); + this.y = Math.min(this.y, newRows - 1); if (addToY) { this.y += addToY; } - - if (this.x >= newCols) { - this.x = newCols - 1; - } + this.savedY = Math.min(this.savedY, newRows - 1); + this.savedX = Math.min(this.savedX, newCols - 1); this.scrollTop = 0; } diff --git a/src/Interfaces.ts b/src/Interfaces.ts index ab7f999d..affba429 100644 --- a/src/Interfaces.ts +++ b/src/Interfaces.ts @@ -4,9 +4,10 @@ */ import { ICharset, ILinkMatcherOptions } from './Interfaces'; -import { LinkMatcherHandler, LinkMatcherValidationCallback, LineData, FontWeight } from './Types'; +import { LinkMatcherHandler, LinkMatcherValidationCallback, LineData } from './Types'; import { IColorSet, IRenderer } from './renderer/Interfaces'; import { IMouseZoneManager } from './input/Interfaces'; +import { FontWeight } from './shared/Types'; export interface IBrowser { isNode: boolean; @@ -137,6 +138,7 @@ export interface ITerminalOptions { cursorStyle?: string; debug?: boolean; disableStdin?: boolean; + enableBold?: boolean; fontSize?: number; fontFamily?: string; fontWeight?: FontWeight; diff --git a/src/SelectionManager.ts b/src/SelectionManager.ts index 608ca412..934f6c6b 100644 --- a/src/SelectionManager.ts +++ b/src/SelectionManager.ts @@ -4,7 +4,7 @@ */ import { MouseHelper } from './utils/MouseHelper'; -import * as Browser from './utils/Browser'; +import * as Browser from './shared/utils/Browser'; import { CharMeasure } from './utils/CharMeasure'; import { CircularList } from './utils/CircularList'; import { EventEmitter } from './EventEmitter'; diff --git a/src/Terminal.ts b/src/Terminal.ts index 865261a1..a715fa68 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -35,7 +35,7 @@ import { Renderer } from './renderer/Renderer'; import { Linkifier } from './Linkifier'; import { SelectionManager } from './SelectionManager'; import { CharMeasure } from './utils/CharMeasure'; -import * as Browser from './utils/Browser'; +import * as Browser from './shared/utils/Browser'; import { MouseHelper } from './utils/MouseHelper'; import { CHARSETS } from './Charsets'; import { CustomKeyEventHandler, LinkMatcherHandler, LinkMatcherValidationCallback, CharData, LineData } from './Types'; @@ -44,7 +44,6 @@ import { BELL_SOUND } from './utils/Sounds'; import { DEFAULT_ANSI_COLORS } from './renderer/ColorManager'; import { IMouseZoneManager } from './input/Interfaces'; import { MouseZoneManager } from './input/MouseZoneManager'; -import { initialize as initializeCharAtlas } from './renderer/CharAtlas'; import { IRenderer } from './renderer/Interfaces'; // Let it work inside Node.js for automated testing purposes. @@ -72,6 +71,7 @@ const DEFAULT_OPTIONS: ITerminalOptions = { cursorStyle: 'block', bellSound: BELL_SOUND, bellStyle: 'none', + enableBold: true, fontFamily: 'courier-new, courier, monospace', fontSize: 15, fontWeight: 'normal', @@ -425,11 +425,12 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT this.renderer.clear(); this.charMeasure.measure(this.options); break; + case 'enableBold': case 'letterSpacing': case 'lineHeight': case 'fontWeight': case 'fontWeightBold': - const didCharSizeChange = (key === 'fontWeight' || key === 'fontWeightBold'); + const didCharSizeChange = (key === 'fontWeight' || key === 'fontWeightBold' || key === 'enableBold'); // When the font changes the size of the cells may change which requires a renderer clear this.renderer.clear(); @@ -590,8 +591,6 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT this.document = this.parent.ownerDocument; this.body = this.document.body; - initializeCharAtlas(this.document, this.options.allowTransparency); - // Create main element container this.element = this.document.createElement('div'); this.element.classList.add('terminal'); diff --git a/src/Types.ts b/src/Types.ts index 336ac5cc..3263282e 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -16,5 +16,3 @@ export enum LinkHoverEventTypes { TOOLTIP = 'linktooltip', LEAVE = 'linkleave' } - -export type FontWeight = 'normal' | 'bold' | 'bolder' | 'lighter' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'; diff --git a/src/addons/attach/Intefaces.ts b/src/addons/attach/Interfaces.ts similarity index 100% rename from src/addons/attach/Intefaces.ts rename to src/addons/attach/Interfaces.ts diff --git a/src/addons/attach/attach.ts b/src/addons/attach/attach.ts index d963a658..cbfd4a24 100644 --- a/src/addons/attach/attach.ts +++ b/src/addons/attach/attach.ts @@ -8,7 +8,7 @@ /// import { Terminal } from 'xterm'; -import { IAttachAddonTerminal } from './Intefaces'; +import { IAttachAddonTerminal } from './Interfaces'; /** * Attaches the given terminal to the given socket. diff --git a/src/addons/search/SearchHelper.ts b/src/addons/search/SearchHelper.ts index dd941682..2abc3b38 100644 --- a/src/addons/search/SearchHelper.ts +++ b/src/addons/search/SearchHelper.ts @@ -113,8 +113,23 @@ export class SearchHelper implements ISearchHelper { private _findInLine(term: string, y: number): ISearchResult { const lowerStringLine = this._terminal.buffer.translateBufferLineToString(y, true).toLowerCase(); const lowerTerm = term.toLowerCase(); - const searchIndex = lowerStringLine.indexOf(lowerTerm); + let searchIndex = lowerStringLine.indexOf(lowerTerm); if (searchIndex >= 0) { + const line = this._terminal.buffer.lines.get(y); + for (let i = 0; i < searchIndex; i++) { + const charData = line[i]; + // Adjust the searchIndex to normalize emoji into single chars + const char = charData[1/*CHAR_DATA_CHAR_INDEX*/]; + if (char.length > 1) { + searchIndex -= char.length - 1; + } + // Adjust the searchIndex for empty characters following wide unicode + // chars (eg. CJK) + const charWidth = charData[2/*CHAR_DATA_WIDTH_INDEX*/]; + if (charWidth === 0) { + searchIndex++; + } + } return { term, col: searchIndex, diff --git a/src/addons/terminado/Intefaces.ts b/src/addons/terminado/Interfaces.ts similarity index 100% rename from src/addons/terminado/Intefaces.ts rename to src/addons/terminado/Interfaces.ts diff --git a/src/addons/terminado/terminado.ts b/src/addons/terminado/terminado.ts index d5cf72d1..4acf9dd8 100644 --- a/src/addons/terminado/terminado.ts +++ b/src/addons/terminado/terminado.ts @@ -9,7 +9,7 @@ /// import { Terminal } from 'xterm'; -import { ITerminadoAddonTerminal } from './Intefaces'; +import { ITerminadoAddonTerminal } from './Interfaces'; /** * Attaches the given terminal to the given socket. diff --git a/src/renderer/BaseRenderLayer.ts b/src/renderer/BaseRenderLayer.ts index 977cbf52..bf952d06 100644 --- a/src/renderer/BaseRenderLayer.ts +++ b/src/renderer/BaseRenderLayer.ts @@ -230,7 +230,7 @@ export abstract class BaseRenderLayer implements IRenderLayer { colorIndex = fg + 2; } else { // If default color and bold - if (bold) { + if (bold && terminal.options.enableBold) { colorIndex = 1; } } @@ -251,6 +251,13 @@ export abstract class BaseRenderLayer implements IRenderLayer { this._ctx.globalAlpha = DIM_OPACITY; } + // Draw the non-bold version of the same color if bold is not enabled + if (bold && !terminal.options.enableBold) { + // Ignore default color as it's not touched above + if (colorIndex > 1) { + colorIndex -= 8; + } + } this._ctx.drawImage(this._charAtlas, code * charAtlasCellWidth, @@ -262,7 +269,7 @@ export abstract class BaseRenderLayer implements IRenderLayer { charAtlasCellWidth, this._scaledCharHeight); } else { - this._drawUncachedChar(terminal, char, width, fg, x, y, bold, dim); + this._drawUncachedChar(terminal, char, width, fg, x, y, bold && terminal.options.enableBold, dim); } // This draws the atlas (for debugging purposes) // this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height); diff --git a/src/renderer/CharAtlas.ts b/src/renderer/CharAtlas.ts index f1ada6a3..f5a13492 100644 --- a/src/renderer/CharAtlas.ts +++ b/src/renderer/CharAtlas.ts @@ -5,7 +5,8 @@ import { ITerminal, ITheme } from '../Interfaces'; import { IColorSet } from '../renderer/Interfaces'; -import { isFirefox } from '../utils/Browser'; +import { isFirefox } from '../shared/utils/Browser'; +import { generateCharAtlas, ICharAtlasRequest } from '../shared/CharAtlasGenerator'; export const CHAR_ATLAS_CELL_SPACING = 1; @@ -65,8 +66,29 @@ export function acquireCharAtlas(terminal: ITerminal, colors: IColorSet, scaledC } } + const canvasFactory = (width: number, height: number) => { + const canvas = document.createElement('canvas'); + canvas.width = width; + canvas.height = height; + return canvas; + }; + + const charAtlasConfig: ICharAtlasRequest = { + scaledCharWidth, + scaledCharHeight, + fontSize: terminal.options.fontSize, + fontFamily: terminal.options.fontFamily, + fontWeight: terminal.options.fontWeight, + fontWeightBold: terminal.options.fontWeightBold, + background: colors.background, + foreground: colors.foreground, + ansiColors: colors.ansi, + devicePixelRatio: window.devicePixelRatio, + allowTransparency: terminal.options.allowTransparency + }; + const newEntry: ICharAtlasCacheEntry = { - bitmap: generator.generate(scaledCharWidth, scaledCharHeight, terminal.options.fontSize, terminal.options.fontFamily, terminal.options.fontWeight, terminal.options.fontWeightBold, colors.background, colors.foreground, colors.ansi), + bitmap: generateCharAtlas(window, canvasFactory, charAtlasConfig), config: newConfig, ownedBy: [terminal] }; @@ -109,124 +131,3 @@ function configEquals(a: ICharAtlasConfig, b: ICharAtlasConfig): boolean { a.colors.foreground === b.colors.foreground && a.colors.background === b.colors.background; } - -let generator: CharAtlasGenerator; - -/** - * Initializes the char atlas generator. - * @param document The document. - */ -export function initialize(document: Document, alpha: boolean): void { - if (!generator) { - generator = new CharAtlasGenerator(document, alpha); - } -} - -class CharAtlasGenerator { - private _canvas: HTMLCanvasElement; - private _ctx: CanvasRenderingContext2D; - - constructor(private _document: Document, alpha: boolean) { - this._canvas = this._document.createElement('canvas'); - this._ctx = this._canvas.getContext('2d', {alpha}); - this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio); - } - - public generate(scaledCharWidth: number, scaledCharHeight: number, fontSize: number, fontFamily: string, fontWeight: string, fontWeightBold: string, background: string, foreground: string, ansiColors: string[]): HTMLCanvasElement | Promise { - const cellWidth = scaledCharWidth + CHAR_ATLAS_CELL_SPACING; - const cellHeight = scaledCharHeight + CHAR_ATLAS_CELL_SPACING; - this._canvas.width = 255 * cellWidth; - this._canvas.height = (/*default+default bold*/2 + /*0-15*/16) * cellHeight; - - this._ctx.fillStyle = background; - this._ctx.fillRect(0, 0, this._canvas.width, this._canvas.height); - - this._ctx.save(); - this._ctx.fillStyle = foreground; - this._ctx.font = this._getFont(fontWeight, fontSize, fontFamily); - this._ctx.textBaseline = 'top'; - - // Default color - for (let i = 0; i < 256; i++) { - this._ctx.save(); - this._ctx.beginPath(); - this._ctx.rect(i * cellWidth, 0, cellWidth, cellHeight); - this._ctx.clip(); - this._ctx.fillText(String.fromCharCode(i), i * cellWidth, 0); - this._ctx.restore(); - } - // Default color bold - this._ctx.save(); - this._ctx.font = this._getFont(fontWeightBold, fontSize, fontFamily); - for (let i = 0; i < 256; i++) { - this._ctx.save(); - this._ctx.beginPath(); - this._ctx.rect(i * cellWidth, cellHeight, cellWidth, cellHeight); - this._ctx.clip(); - this._ctx.fillText(String.fromCharCode(i), i * cellWidth, cellHeight); - this._ctx.restore(); - } - this._ctx.restore(); - - // Colors 0-15 - this._ctx.font = this._getFont(fontWeight, fontSize, fontFamily); - for (let colorIndex = 0; colorIndex < 16; colorIndex++) { - // colors 8-15 are bold - if (colorIndex === 8) { - this._ctx.font = this._getFont(fontWeightBold, fontSize, fontFamily); - } - const y = (colorIndex + 2) * cellHeight; - // Draw ascii characters - for (let i = 0; i < 256; i++) { - this._ctx.save(); - this._ctx.beginPath(); - this._ctx.rect(i * cellWidth, y, cellWidth, cellHeight); - this._ctx.clip(); - this._ctx.fillStyle = ansiColors[colorIndex]; - this._ctx.fillText(String.fromCharCode(i), i * cellWidth, y); - this._ctx.restore(); - } - } - this._ctx.restore(); - - // Support is patchy for createImageBitmap at the moment, pass a canvas back - // if support is lacking as drawImage works there too. Firefox is also - // included here as ImageBitmap appears both buggy and has horrible - // performance (tested on v55). - if (!('createImageBitmap' in window) || isFirefox) { - // Regenerate canvas and context as they are now owned by the char atlas - const result = this._canvas; - this._canvas = this._document.createElement('canvas'); - this._ctx = this._canvas.getContext('2d'); - this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio); - return result; - } - - const charAtlasImageData = this._ctx.getImageData(0, 0, this._canvas.width, this._canvas.height); - - // Remove the background color from the image so characters may overlap - const r = parseInt(background.substr(1, 2), 16); - const g = parseInt(background.substr(3, 2), 16); - const b = parseInt(background.substr(5, 2), 16); - this._clearColor(charAtlasImageData, r, g, b); - - const promise = window.createImageBitmap(charAtlasImageData); - // Clear the rect while the promise is in progress - this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height); - return promise; - } - - private _clearColor(imageData: ImageData, r: number, g: number, b: number): void { - for (let offset = 0; offset < imageData.data.length; offset += 4) { - if (imageData.data[offset] === r && - imageData.data[offset + 1] === g && - imageData.data[offset + 2] === b) { - imageData.data[offset + 3] = 0; - } - } - } - - private _getFont(fontWeight: string, fontSize: number, fontFamily: string): string { - return `${fontWeight} ${fontSize * window.devicePixelRatio}px ${fontFamily}`; - } -} diff --git a/src/shared/CharAtlasGenerator.ts b/src/shared/CharAtlasGenerator.ts new file mode 100644 index 00000000..83da1823 --- /dev/null +++ b/src/shared/CharAtlasGenerator.ts @@ -0,0 +1,141 @@ +/** + * Copyright (c) 2018 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { isFirefox } from './utils/Browser'; +import { FontWeight } from './Types'; + +declare const Promise: any; + +export interface IOffscreenCanvas { + width: number; + height: number; + getContext(type: '2d', config?: Canvas2DContextAttributes): CanvasRenderingContext2D; + transferToImageBitmap(): ImageBitmap; +} + +export interface ICharAtlasRequest { + scaledCharWidth: number; + scaledCharHeight: number; + fontSize: number; + fontFamily: string; + fontWeight: FontWeight; + fontWeightBold: FontWeight; + background: string; + foreground: string; + ansiColors: string[]; + devicePixelRatio: number; + allowTransparency: boolean; +} + +export const CHAR_ATLAS_CELL_SPACING = 1; + +/** + * Generates a char atlas. + * @param context The window or worker context. + * @param canvasFactory A function to generate a canvas with a width or height. + * @param request The config for the new char atlas. + */ +export function generateCharAtlas(context: Window, canvasFactory: (width: number, height: number) => HTMLCanvasElement | IOffscreenCanvas, request: ICharAtlasRequest): HTMLCanvasElement | Promise { + const cellWidth = request.scaledCharWidth + CHAR_ATLAS_CELL_SPACING; + const cellHeight = request.scaledCharHeight + CHAR_ATLAS_CELL_SPACING; + const canvas = canvasFactory( + /*255 ascii chars*/255 * cellWidth, + (/*default+default bold*/2 + /*0-15*/16) * cellHeight + ); + const ctx = canvas.getContext('2d', {alpha: request.allowTransparency}); + + ctx.fillStyle = request.background; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + ctx.save(); + ctx.fillStyle = request.foreground; + ctx.font = getFont(request.fontWeight, request); + ctx.textBaseline = 'top'; + + // Default color + for (let i = 0; i < 256; i++) { + ctx.save(); + ctx.beginPath(); + ctx.rect(i * cellWidth, 0, cellWidth, cellHeight); + ctx.clip(); + ctx.fillText(String.fromCharCode(i), i * cellWidth, 0); + ctx.restore(); + } + // Default color bold + ctx.save(); + ctx.font = getFont(request.fontWeightBold, request); + for (let i = 0; i < 256; i++) { + ctx.save(); + ctx.beginPath(); + ctx.rect(i * cellWidth, cellHeight, cellWidth, cellHeight); + ctx.clip(); + ctx.fillText(String.fromCharCode(i), i * cellWidth, cellHeight); + ctx.restore(); + } + ctx.restore(); + + // Colors 0-15 + ctx.font = getFont(request.fontWeight, request); + for (let colorIndex = 0; colorIndex < 16; colorIndex++) { + // colors 8-15 are bold + if (colorIndex === 8) { + ctx.font = getFont(request.fontWeightBold, request); + } + const y = (colorIndex + 2) * cellHeight; + // Draw ascii characters + for (let i = 0; i < 256; i++) { + ctx.save(); + ctx.beginPath(); + ctx.rect(i * cellWidth, y, cellWidth, cellHeight); + ctx.clip(); + ctx.fillStyle = request.ansiColors[colorIndex]; + ctx.fillText(String.fromCharCode(i), i * cellWidth, y); + ctx.restore(); + } + } + ctx.restore(); + + // Support is patchy for createImageBitmap at the moment, pass a canvas back + // if support is lacking as drawImage works there too. Firefox is also + // included here as ImageBitmap appears both buggy and has horrible + // performance (tested on v55). + if (!('createImageBitmap' in context) || isFirefox) { + // Don't attempt to clear background colors if createImageBitmap is not supported + if (canvas instanceof HTMLCanvasElement) { + // Just return the HTMLCanvas if it's a HTMLCanvasElement + return canvas; + } else { + // Transfer to an ImageBitmap is this is an OffscreenCanvas + return new Promise(r => r(canvas.transferToImageBitmap())); + } + } + + const charAtlasImageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + + // Remove the background color from the image so characters may overlap + const r = parseInt(request.background.substr(1, 2), 16); + const g = parseInt(request.background.substr(3, 2), 16); + const b = parseInt(request.background.substr(5, 2), 16); + clearColor(charAtlasImageData, r, g, b); + + return context.createImageBitmap(charAtlasImageData); +} + +/** + * Makes a partiicular rgb color in an ImageData completely transparent. + */ +function clearColor(imageData: ImageData, r: number, g: number, b: number): void { + for (let offset = 0; offset < imageData.data.length; offset += 4) { + if (imageData.data[offset] === r && + imageData.data[offset + 1] === g && + imageData.data[offset + 2] === b) { + imageData.data[offset + 3] = 0; + } + } +} + +function getFont(fontWeight: FontWeight, request: ICharAtlasRequest): string { + return `${fontWeight} ${request.fontSize * request.devicePixelRatio}px ${request.fontFamily}`; +} diff --git a/src/shared/Types.ts b/src/shared/Types.ts new file mode 100644 index 00000000..b61525bd --- /dev/null +++ b/src/shared/Types.ts @@ -0,0 +1,6 @@ +/** + * Copyright (c) 2018 The xterm.js authors. All rights reserved. + * @license MIT + */ + + export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'; diff --git a/src/utils/Browser.ts b/src/shared/utils/Browser.ts similarity index 75% rename from src/utils/Browser.ts rename to src/shared/utils/Browser.ts index 48c0c374..1d4774d2 100644 --- a/src/utils/Browser.ts +++ b/src/shared/utils/Browser.ts @@ -3,8 +3,6 @@ * @license MIT */ -import { contains } from './Generic'; - const isNode = (typeof navigator === 'undefined') ? true : false; const userAgent = (isNode) ? 'node' : navigator.userAgent; const platform = (isNode) ? 'node' : navigator.platform; @@ -20,3 +18,12 @@ export const isIpad = platform === 'iPad'; export const isIphone = platform === 'iPhone'; export const isMSWindows = contains(['Windows', 'Win16', 'Win32', 'WinCE'], platform); export const isLinux = platform.indexOf('Linux') >= 0; + +/** + * Return if the given array contains the given element + * @param {Array} array The array to search for the given element. + * @param {Object} el The element to look for into the array + */ +export function contains(arr: any[], el: any): boolean { + return arr.indexOf(el) >= 0; +}; diff --git a/src/utils/Generic.ts b/src/utils/Generic.ts deleted file mode 100644 index 4bc6c487..00000000 --- a/src/utils/Generic.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Copyright (c) 2016 The xterm.js authors. All rights reserved. - * @license MIT - */ - -/** - * Return if the given array contains the given element - * @param {Array} array The array to search for the given element. - * @param {Object} el The element to look for into the array - */ -export function contains(arr: any[], el: any): boolean { - return arr.indexOf(el) >= 0; -} diff --git a/src/utils/TestUtils.test.ts b/src/utils/TestUtils.test.ts index 80e25277..8e8900a1 100644 --- a/src/utils/TestUtils.test.ts +++ b/src/utils/TestUtils.test.ts @@ -6,7 +6,7 @@ import { ITerminal, IBuffer, IBufferSet, IBrowser, ICharMeasure, ISelectionManager, ITerminalOptions, IListenerType, IInputHandlingTerminal, IViewport, ICircularList, ICompositionHelper, ITheme, ILinkifier, IMouseHelper } from '../Interfaces'; import { LineData } from '../Types'; import { Buffer } from '../Buffer'; -import * as Browser from './Browser'; +import * as Browser from '../shared/utils/Browser'; import { IColorSet, IRenderer, IRenderDimensions, IColorManager } from '../renderer/Interfaces'; export class MockTerminal implements ITerminal { diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index b7f0afcb..55042e63 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -8,12 +8,17 @@ */ declare module 'xterm' { + /** + * A string representing text font weight. + */ + export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'; + /** * An object containing start up options for the terminal. */ export interface ITerminalOptions { /** - * Whether background should support non-opaque color. It must be set before + * Whether background should support non-opaque color. It must be set before * executing open() method and can't be changed later without excuting it again. * Warning: Enabling this option can reduce performances somewhat. */ @@ -63,6 +68,16 @@ declare module 'xterm' { */ fontFamily?: string; + /** + * The font weight used to render non-bold text. + */ + fontWeight?: FontWeight; + + /** + * The font weight used to render bold text. + */ + fontWeightBold?: FontWeight; + /** * The spacing in whole pixels between characters.. */ @@ -73,6 +88,11 @@ declare module 'xterm' { */ lineHeight?: number; + /** + * Whether to treat option as the meta key. + */ + macOptionIsMeta?: boolean; + /** * The number of rows in the terminal. */ @@ -415,7 +435,7 @@ declare module 'xterm' { * Retrieves an option's value from the terminal. * @param key The option key. */ - getOption(key: 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell' | 'allowTransparency'): boolean; + getOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'macOptionIsMeta' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell'): boolean; /** * Retrieves an option's value from the terminal. * @param key The option key. @@ -448,7 +468,7 @@ declare module 'xterm' { * @param key The option key. * @param value The option value. */ - setOption(key: 'fontWeight' | 'fontWeightBold', value: null | 'normal' | 'bold' | 'bolder' | 'lighter' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'): void; + setOption(key: 'fontWeight' | 'fontWeightBold', value: null | 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'): void; /** * Sets an option on the terminal. * @param key The option key.