From 2571a0654f87e4663ac8eb4cbddaa6dd4075d15a Mon Sep 17 00:00:00 2001 From: javacs3 Date: Sun, 7 Jul 2019 22:59:15 +0800 Subject: [PATCH 1/7] add SerializeAddon --- addons/xterm-addon-serialize/.gitignore | 2 + addons/xterm-addon-serialize/.npmignore | 5 + addons/xterm-addon-serialize/package.json | 20 +++ .../src/SerializeAddon.api.ts | 134 ++++++++++++++++++ .../src/SerializeAddon.ts | 42 ++++++ .../xterm-addon-serialize/src/tsconfig.json | 19 +++ .../typings/xterm-addon-serialize.d.ts | 30 ++++ .../xterm-addon-serialize/webpack.config.js | 31 ++++ demo/client.ts | 3 + package.json | 1 + tsconfig.all.json | 3 +- 11 files changed, 289 insertions(+), 1 deletion(-) create mode 100644 addons/xterm-addon-serialize/.gitignore create mode 100644 addons/xterm-addon-serialize/.npmignore create mode 100644 addons/xterm-addon-serialize/package.json create mode 100644 addons/xterm-addon-serialize/src/SerializeAddon.api.ts create mode 100644 addons/xterm-addon-serialize/src/SerializeAddon.ts create mode 100644 addons/xterm-addon-serialize/src/tsconfig.json create mode 100644 addons/xterm-addon-serialize/typings/xterm-addon-serialize.d.ts create mode 100644 addons/xterm-addon-serialize/webpack.config.js diff --git a/addons/xterm-addon-serialize/.gitignore b/addons/xterm-addon-serialize/.gitignore new file mode 100644 index 00000000..3063f07d --- /dev/null +++ b/addons/xterm-addon-serialize/.gitignore @@ -0,0 +1,2 @@ +lib +node_modules diff --git a/addons/xterm-addon-serialize/.npmignore b/addons/xterm-addon-serialize/.npmignore new file mode 100644 index 00000000..1c794445 --- /dev/null +++ b/addons/xterm-addon-serialize/.npmignore @@ -0,0 +1,5 @@ +**/*.api.js +**/*.api.ts +tsconfig.json +.yarnrc +webpack.config.js diff --git a/addons/xterm-addon-serialize/package.json b/addons/xterm-addon-serialize/package.json new file mode 100644 index 00000000..c8a66c4b --- /dev/null +++ b/addons/xterm-addon-serialize/package.json @@ -0,0 +1,20 @@ +{ + "name": "xterm-addon-serialize", + "version": "0.1.0", + "author": { + "name": "The xterm.js authors", + "url": "https://xtermjs.org/" + }, + "main": "lib/xterm-addon-serialize.js", + "types": "typings/xterm-addon-serialize.d.ts", + "license": "MIT", + "scripts": { + "build": "../../node_modules/.bin/tsc -p src", + "prepackage": "npm run build", + "package": "../../node_modules/.bin/webpack", + "prepublishOnly": "npm run package" + }, + "peerDependencies": { + "xterm": "^3.14.0" + } +} diff --git a/addons/xterm-addon-serialize/src/SerializeAddon.api.ts b/addons/xterm-addon-serialize/src/SerializeAddon.api.ts new file mode 100644 index 00000000..88e4503e --- /dev/null +++ b/addons/xterm-addon-serialize/src/SerializeAddon.api.ts @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2019 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import * as puppeteer from 'puppeteer'; +import * as util from 'util'; +import { assert } from 'chai'; +import { ITerminalOptions } from 'xterm'; + +const APP = 'http://127.0.0.1:3000/test'; + +let browser: puppeteer.Browser; +let page: puppeteer.Page; +const width = 800; +const height = 600; + +describe('SerializeAddon', () => { + before(async function (): Promise { + this.timeout(20000); + browser = await puppeteer.launch({ + headless: process.argv.indexOf('--headless') !== -1, + slowMo: 80, + args: [`--window-size=${width},${height}`] + }); + page = (await browser.pages())[0]; + await page.setViewport({ width, height }); + }); + + after(async () => { + await browser.close(); + }); + + beforeEach(async function (): Promise { + this.timeout(20000); + await page.goto(APP); + }); + + it('empty content', async function (): Promise { + this.timeout(20000); + const rows = 10; + const cols = 10; + const blankline = ' '.repeat(cols); + const lines = newArray(blankline, rows); + + await openTerminal({ rows: rows, cols: cols, rendererType: 'dom' }); + await page.evaluate(` + window.serializeAddon = new SerializeAddon(); + window.term.loadAddon(window.serializeAddon); + `) + + assert.equal(await page.evaluate(`serializeAddon.serialize();`), lines.join('\r\n')); + }); + + it('digits content', async function (): Promise { + this.timeout(20000); + const rows = 10; + const cols = 10; + const digitsLine = digitsString(cols); + const lines = newArray(digitsLine, rows); + + await openTerminal({ rows: rows, cols: cols, rendererType: 'dom' }); + await page.evaluate(` + window.serializeAddon = new SerializeAddon(); + window.term.loadAddon(window.serializeAddon); + window.term.write(${util.inspect(lines.join('\r\n'))}); + `) + + assert.equal(await page.evaluate(`serializeAddon.serialize();`), lines.join('\r\n')); + }); + + it('serialize n rows of content', async function (): Promise { + this.timeout(20000); + const rows = 10; + const halfRows = rows >> 1; + const cols = 10; + const lines = newArray((index: number) => digitsString(cols, index), rows); + + await openTerminal({ rows: rows, cols: cols, rendererType: 'dom' }); + await page.evaluate(` + window.serializeAddon = new SerializeAddon(); + window.term.loadAddon(window.serializeAddon); + window.term.write(${util.inspect(lines.join('\r\n'))}); + `) + + assert.equal(await page.evaluate(`serializeAddon.serialize(${halfRows});`), lines.slice(0, halfRows).join('\r\n')); + }); + + it('serialize 0 rows of content', async function (): Promise { + this.timeout(20000); + const rows = 10; + const cols = 10; + const lines = newArray((index: number) => digitsString(cols, index), rows); + + await openTerminal({ rows: rows, cols: cols, rendererType: 'dom' }); + await page.evaluate(` + window.serializeAddon = new SerializeAddon(); + window.term.loadAddon(window.serializeAddon); + window.term.write(${util.inspect(lines.join('\r\n'))}); + `) + + assert.equal(await page.evaluate(`serializeAddon.serialize(0);`), ''); + }); +}); + +async function openTerminal(options: ITerminalOptions = {}): Promise { + await page.evaluate(`window.term = new Terminal(${JSON.stringify(options)})`); + await page.evaluate(`window.term.open(document.querySelector('#terminal-container'))`); + if (options.rendererType === 'dom') { + await page.waitForSelector('.xterm-rows'); + } else { + await page.waitForSelector('.xterm-text-layer'); + } +} + +function newArray(initial: T | ((index: number) => T), count: number): T[] { + const array: T[] = new Array(count); + for (let i = 0; i < array.length; i++) { + if (typeof initial === 'function') { + array[i] = (<(index: number) => T>initial)(i); + } else { + array[i] = initial; + } + } + return array; +} + +function digitsString(length: number, from: number = 0) { + let s = ''; + for (let i = 0; i < length; i++) { + s += (from++) % 10; + } + return s; +} diff --git a/addons/xterm-addon-serialize/src/SerializeAddon.ts b/addons/xterm-addon-serialize/src/SerializeAddon.ts new file mode 100644 index 00000000..8dd5b194 --- /dev/null +++ b/addons/xterm-addon-serialize/src/SerializeAddon.ts @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2019 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { Terminal, ITerminalAddon } from 'xterm'; + +export class SerializeAddon implements ITerminalAddon { + private _terminal: Terminal | undefined; + + constructor() { } + + public activate(terminal: Terminal): void { + this._terminal = terminal; + } + + public serialize(rows?: number): string { + if (!this._terminal) { + return ''; + } + const buffer = this._terminal.buffer; + const length = Math.max(0, Math.min((rows === undefined ? buffer.length : rows), buffer.length)); + let data = ''; + + for (let i = 0; i < length; i++) { + const line = buffer.getLine(i); + const last = i === length - 1; + if (line) { + data += line.translateToString(); + } + if (!last) { + data += '\r\n'; + } + } + + return data; + } + + public dispose(): void { + if (this._terminal !== undefined) { } + } +} diff --git a/addons/xterm-addon-serialize/src/tsconfig.json b/addons/xterm-addon-serialize/src/tsconfig.json new file mode 100644 index 00000000..5539aa56 --- /dev/null +++ b/addons/xterm-addon-serialize/src/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "lib": [ + "dom", + "es2015" + ], + "rootDir": ".", + "outDir": "../out", + "sourceMap": true, + "removeComments": true, + "strict": true + }, + "include": [ + "./**/*", + "../../../typings/xterm.d.ts" + ] +} diff --git a/addons/xterm-addon-serialize/typings/xterm-addon-serialize.d.ts b/addons/xterm-addon-serialize/typings/xterm-addon-serialize.d.ts new file mode 100644 index 00000000..e36e724a --- /dev/null +++ b/addons/xterm-addon-serialize/typings/xterm-addon-serialize.d.ts @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + + +import { Terminal, ITerminalAddon } from 'xterm'; + +declare module 'xterm-addon-serialize' { + /** + * An xterm.js addon that enables web links. + */ + export class SerializeAddon implements ITerminalAddon { + + constructor(); + + /** + * Activates the addon + * @param terminal The terminal the addon is being loaded in. + */ + public activate(terminal: Terminal): void; + + public serialize(rows?: number): string; + + /** + * Disposes the addon. + */ + public dispose(): void; + } +} diff --git a/addons/xterm-addon-serialize/webpack.config.js b/addons/xterm-addon-serialize/webpack.config.js new file mode 100644 index 00000000..4cabbad9 --- /dev/null +++ b/addons/xterm-addon-serialize/webpack.config.js @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2019 The xterm.js authors. All rights reserved. + * @license MIT + */ + +const path = require('path'); + +const addonName = 'SerializeAddon'; +const mainFile = 'xterm-addon-serialize.js'; + +module.exports = { + entry: `./out/${addonName}.js`, + devtool: 'source-map', + module: { + rules: [ + { + test: /\.js$/, + use: ["source-map-loader"], + enforce: "pre", + exclude: /node_modules/ + } + ] + }, + output: { + filename: mainFile, + path: path.resolve('./lib'), + library: addonName, + libraryTarget: 'umd' + }, + mode: 'production' +}; diff --git a/demo/client.ts b/demo/client.ts index e2259841..eb8b1053 100644 --- a/demo/client.ts +++ b/demo/client.ts @@ -14,6 +14,7 @@ import { FitAddon } from '../addons/xterm-addon-fit/out/FitAddon'; import { SearchAddon, ISearchOptions } from '../addons/xterm-addon-search/out/SearchAddon'; import { WebLinksAddon } from '../addons/xterm-addon-web-links/out/WebLinksAddon'; import { WebglAddon } from '../addons/xterm-addon-webgl/out/WebglAddon'; +import { SerializeAddon } from '../addons/xterm-addon-serialize/out/SerializeAddon'; // Use webpacked version (yarn package) // import { Terminal } from '../lib/xterm'; @@ -35,6 +36,7 @@ export interface IWindowWithTerminal extends Window { SearchAddon?: typeof SearchAddon; WebLinksAddon?: typeof WebLinksAddon; WebglAddon?: typeof WebglAddon; + SerializeAddon?: typeof SerializeAddon; } declare let window: IWindowWithTerminal; @@ -88,6 +90,7 @@ if (document.location.pathname === '/test') { window.SearchAddon = SearchAddon; window.WebLinksAddon = WebLinksAddon; window.WebglAddon = WebglAddon; + window.SerializeAddon = SerializeAddon; } else { createTerminal(); document.getElementById('dispose').addEventListener('click', disposeRecreateButtonHandler); diff --git a/package.json b/package.json index f26c010f..1ee4986d 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "test": "npm run test-unit", "posttest": "npm run lint", "test-api": "mocha \"**/*.api.js\"", + "test-addons": "mocha \"**/*.test.js\"", "test-unit": "node ./bin/test.js", "build": "tsc -b ./tsconfig.all.json", "prepare": "npm run build", diff --git a/tsconfig.all.json b/tsconfig.all.json index 7ddf33d5..5a7ae05b 100644 --- a/tsconfig.all.json +++ b/tsconfig.all.json @@ -9,6 +9,7 @@ { "path": "./addons/xterm-addon-fit/src" }, { "path": "./addons/xterm-addon-search/src" }, { "path": "./addons/xterm-addon-web-links/src" }, - { "path": "./addons/xterm-addon-webgl/src" } + { "path": "./addons/xterm-addon-webgl/src" }, + { "path": "./addons/xterm-addon-serialize/src" } ] } From 3ba6ffe5f499aad1c57c78e89530aa6e1fc068f4 Mon Sep 17 00:00:00 2001 From: javacs3 Date: Wed, 10 Jul 2019 21:57:50 +0800 Subject: [PATCH 2/7] fix lint error --- addons/xterm-addon-serialize/src/SerializeAddon.api.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/xterm-addon-serialize/src/SerializeAddon.api.ts b/addons/xterm-addon-serialize/src/SerializeAddon.api.ts index 88e4503e..464316c3 100644 --- a/addons/xterm-addon-serialize/src/SerializeAddon.api.ts +++ b/addons/xterm-addon-serialize/src/SerializeAddon.api.ts @@ -47,7 +47,7 @@ describe('SerializeAddon', () => { await page.evaluate(` window.serializeAddon = new SerializeAddon(); window.term.loadAddon(window.serializeAddon); - `) + `); assert.equal(await page.evaluate(`serializeAddon.serialize();`), lines.join('\r\n')); }); @@ -64,7 +64,7 @@ describe('SerializeAddon', () => { window.serializeAddon = new SerializeAddon(); window.term.loadAddon(window.serializeAddon); window.term.write(${util.inspect(lines.join('\r\n'))}); - `) + `); assert.equal(await page.evaluate(`serializeAddon.serialize();`), lines.join('\r\n')); }); @@ -81,7 +81,7 @@ describe('SerializeAddon', () => { window.serializeAddon = new SerializeAddon(); window.term.loadAddon(window.serializeAddon); window.term.write(${util.inspect(lines.join('\r\n'))}); - `) + `); assert.equal(await page.evaluate(`serializeAddon.serialize(${halfRows});`), lines.slice(0, halfRows).join('\r\n')); }); @@ -97,7 +97,7 @@ describe('SerializeAddon', () => { window.serializeAddon = new SerializeAddon(); window.term.loadAddon(window.serializeAddon); window.term.write(${util.inspect(lines.join('\r\n'))}); - `) + `); assert.equal(await page.evaluate(`serializeAddon.serialize(0);`), ''); }); @@ -125,7 +125,7 @@ function newArray(initial: T | ((index: number) => T), count: number): T[] { return array; } -function digitsString(length: number, from: number = 0) { +function digitsString(length: number, from: number = 0): string { let s = ''; for (let i = 0; i < length; i++) { s += (from++) % 10; From 57a82556547d5c352a12f39112360c7bfa5f6f66 Mon Sep 17 00:00:00 2001 From: javacs3 Date: Fri, 12 Jul 2019 23:03:49 +0800 Subject: [PATCH 3/7] add test files from addons folder --- bin/test.js | 3 ++- package.json | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/test.js b/bin/test.js index 89f0d61e..2d816097 100644 --- a/bin/test.js +++ b/bin/test.js @@ -12,7 +12,8 @@ env.NODE_PATH = path.resolve(__dirname, '../out'); let testFiles = [ './out/*test.js', - './out/**/*test.js' + './out/**/*test.js', + './addons/**/out/*test.js', ]; // ability to inject particular test files via diff --git a/package.json b/package.json index 1ee4986d..f26c010f 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,6 @@ "test": "npm run test-unit", "posttest": "npm run lint", "test-api": "mocha \"**/*.api.js\"", - "test-addons": "mocha \"**/*.test.js\"", "test-unit": "node ./bin/test.js", "build": "tsc -b ./tsconfig.all.json", "prepare": "npm run build", From 31f812cf94c3514f2749b8183c3e2e50ae8e0f41 Mon Sep 17 00:00:00 2001 From: javacs3 Date: Fri, 12 Jul 2019 23:21:48 +0800 Subject: [PATCH 4/7] add missing api docs and refactor serialize implementation by using list join instead and some code clean up --- .../src/SerializeAddon.ts | 19 ++++++------------- .../typings/xterm-addon-serialize.d.ts | 8 ++++++++ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/addons/xterm-addon-serialize/src/SerializeAddon.ts b/addons/xterm-addon-serialize/src/SerializeAddon.ts index 8dd5b194..720da58b 100644 --- a/addons/xterm-addon-serialize/src/SerializeAddon.ts +++ b/addons/xterm-addon-serialize/src/SerializeAddon.ts @@ -15,28 +15,21 @@ export class SerializeAddon implements ITerminalAddon { } public serialize(rows?: number): string { + // TODO: Add frontground/background color support later if (!this._terminal) { - return ''; + throw new Error('No terminal found!'); } const buffer = this._terminal.buffer; const length = Math.max(0, Math.min((rows === undefined ? buffer.length : rows), buffer.length)); - let data = ''; + const lines: string[] = new Array(length); for (let i = 0; i < length; i++) { const line = buffer.getLine(i); - const last = i === length - 1; - if (line) { - data += line.translateToString(); - } - if (!last) { - data += '\r\n'; - } + lines[i] = line ? line.translateToString() : ''; } - return data; + return lines.join('\r\n'); } - public dispose(): void { - if (this._terminal !== undefined) { } - } + public dispose(): void { } } diff --git a/addons/xterm-addon-serialize/typings/xterm-addon-serialize.d.ts b/addons/xterm-addon-serialize/typings/xterm-addon-serialize.d.ts index e36e724a..78b615d7 100644 --- a/addons/xterm-addon-serialize/typings/xterm-addon-serialize.d.ts +++ b/addons/xterm-addon-serialize/typings/xterm-addon-serialize.d.ts @@ -20,6 +20,14 @@ declare module 'xterm-addon-serialize' { */ public activate(terminal: Terminal): void; + /** + * Serializes terminal rows into a string that can be written back to the terminal + * to restore the state. The cursor will also be positioned to the correct cell. + * When restoring a terminal it is best to do before `Terminal.open` is called + * to avoid wasting CPU cycles rendering incomplete frames. + * @param rows The number of rows to serialize, starting from the top of the + * terminal. This defaults to the number of rows in the viewport. + */ public serialize(rows?: number): string; /** From fe3520c68587a6e538bdd75ed8f280d628b9d4fc Mon Sep 17 00:00:00 2001 From: javacs3 Date: Sat, 13 Jul 2019 17:25:18 +0800 Subject: [PATCH 5/7] change exception message --- addons/xterm-addon-serialize/src/SerializeAddon.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/xterm-addon-serialize/src/SerializeAddon.ts b/addons/xterm-addon-serialize/src/SerializeAddon.ts index 720da58b..10d920cd 100644 --- a/addons/xterm-addon-serialize/src/SerializeAddon.ts +++ b/addons/xterm-addon-serialize/src/SerializeAddon.ts @@ -17,7 +17,7 @@ export class SerializeAddon implements ITerminalAddon { public serialize(rows?: number): string { // TODO: Add frontground/background color support later if (!this._terminal) { - throw new Error('No terminal found!'); + throw new Error('Cannot use addon until it has been loaded'); } const buffer = this._terminal.buffer; const length = Math.max(0, Math.min((rows === undefined ? buffer.length : rows), buffer.length)); From bca90245c8ff900353770a38b0155cfcb2dcfdaa Mon Sep 17 00:00:00 2001 From: javacs3 Date: Sun, 14 Jul 2019 23:22:20 +0800 Subject: [PATCH 6/7] serialize from the bottom of the terminal --- .../src/SerializeAddon.api.ts | 2 +- .../src/SerializeAddon.ts | 19 ++++++++++++++----- .../typings/xterm-addon-serialize.d.ts | 2 +- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/addons/xterm-addon-serialize/src/SerializeAddon.api.ts b/addons/xterm-addon-serialize/src/SerializeAddon.api.ts index 464316c3..5543696b 100644 --- a/addons/xterm-addon-serialize/src/SerializeAddon.api.ts +++ b/addons/xterm-addon-serialize/src/SerializeAddon.api.ts @@ -83,7 +83,7 @@ describe('SerializeAddon', () => { window.term.write(${util.inspect(lines.join('\r\n'))}); `); - assert.equal(await page.evaluate(`serializeAddon.serialize(${halfRows});`), lines.slice(0, halfRows).join('\r\n')); + assert.equal(await page.evaluate(`serializeAddon.serialize(${halfRows});`), lines.slice(halfRows, 2 * halfRows).join('\r\n')); }); it('serialize 0 rows of content', async function (): Promise { diff --git a/addons/xterm-addon-serialize/src/SerializeAddon.ts b/addons/xterm-addon-serialize/src/SerializeAddon.ts index 10d920cd..5d060949 100644 --- a/addons/xterm-addon-serialize/src/SerializeAddon.ts +++ b/addons/xterm-addon-serialize/src/SerializeAddon.ts @@ -5,6 +5,10 @@ import { Terminal, ITerminalAddon } from 'xterm'; +function crop(value: number, from: number, to: number) { + return Math.max(from, Math.min(value, to)) +} + export class SerializeAddon implements ITerminalAddon { private _terminal: Terminal | undefined; @@ -19,13 +23,18 @@ export class SerializeAddon implements ITerminalAddon { if (!this._terminal) { throw new Error('Cannot use addon until it has been loaded'); } - const buffer = this._terminal.buffer; - const length = Math.max(0, Math.min((rows === undefined ? buffer.length : rows), buffer.length)); - const lines: string[] = new Array(length); + const terminalRows = this._terminal.rows; + if (rows === undefined) { + rows = terminalRows; + } + rows = crop(rows, 0, terminalRows); - for (let i = 0; i < length; i++) { + const buffer = this._terminal.buffer; + const lines: string[] = new Array(rows); + + for (let i = terminalRows - rows; i < terminalRows; i++) { const line = buffer.getLine(i); - lines[i] = line ? line.translateToString() : ''; + lines[i - terminalRows + rows] = line ? line.translateToString() : ''; } return lines.join('\r\n'); diff --git a/addons/xterm-addon-serialize/typings/xterm-addon-serialize.d.ts b/addons/xterm-addon-serialize/typings/xterm-addon-serialize.d.ts index 78b615d7..9e7b500a 100644 --- a/addons/xterm-addon-serialize/typings/xterm-addon-serialize.d.ts +++ b/addons/xterm-addon-serialize/typings/xterm-addon-serialize.d.ts @@ -25,7 +25,7 @@ declare module 'xterm-addon-serialize' { * to restore the state. The cursor will also be positioned to the correct cell. * When restoring a terminal it is best to do before `Terminal.open` is called * to avoid wasting CPU cycles rendering incomplete frames. - * @param rows The number of rows to serialize, starting from the top of the + * @param rows The number of rows to serialize, starting from the bottom of the * terminal. This defaults to the number of rows in the viewport. */ public serialize(rows?: number): string; From f859bffa749b1dd6ccdd401e89d15964e3bc63ee Mon Sep 17 00:00:00 2001 From: javacs3 Date: Mon, 15 Jul 2019 09:42:56 +0800 Subject: [PATCH 7/7] fix lint error --- addons/xterm-addon-serialize/src/SerializeAddon.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/xterm-addon-serialize/src/SerializeAddon.ts b/addons/xterm-addon-serialize/src/SerializeAddon.ts index 5d060949..9328e674 100644 --- a/addons/xterm-addon-serialize/src/SerializeAddon.ts +++ b/addons/xterm-addon-serialize/src/SerializeAddon.ts @@ -5,8 +5,8 @@ import { Terminal, ITerminalAddon } from 'xterm'; -function crop(value: number, from: number, to: number) { - return Math.max(from, Math.min(value, to)) +function crop(value: number, from: number, to: number): number { + return Math.max(from, Math.min(value, to)); } export class SerializeAddon implements ITerminalAddon {