add SerializeAddon

This commit is contained in:
javacs3
2019-07-10 21:46:51 +08:00
parent 44a843bbe6
commit 2571a0654f
11 changed files with 289 additions and 1 deletions
+2
View File
@@ -0,0 +1,2 @@
lib
node_modules
+5
View File
@@ -0,0 +1,5 @@
**/*.api.js
**/*.api.ts
tsconfig.json
.yarnrc
webpack.config.js
+20
View File
@@ -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"
}
}
@@ -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<any> {
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<any> {
this.timeout(20000);
await page.goto(APP);
});
it('empty content', async function (): Promise<any> {
this.timeout(20000);
const rows = 10;
const cols = 10;
const blankline = ' '.repeat(cols);
const lines = newArray<string>(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<any> {
this.timeout(20000);
const rows = 10;
const cols = 10;
const digitsLine = digitsString(cols);
const lines = newArray<string>(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<any> {
this.timeout(20000);
const rows = 10;
const halfRows = rows >> 1;
const cols = 10;
const lines = newArray<string>((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<any> {
this.timeout(20000);
const rows = 10;
const cols = 10;
const lines = newArray<string>((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<void> {
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<T>(initial: T | ((index: number) => T), count: number): T[] {
const array: T[] = new Array<T>(count);
for (let i = 0; i < array.length; i++) {
if (typeof initial === 'function') {
array[i] = (<(index: number) => T>initial)(i);
} else {
array[i] = <T>initial;
}
}
return array;
}
function digitsString(length: number, from: number = 0) {
let s = '';
for (let i = 0; i < length; i++) {
s += (from++) % 10;
}
return s;
}
@@ -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) { }
}
}
@@ -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"
]
}
@@ -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;
}
}
@@ -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'
};
+3
View File
@@ -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);
+1
View File
@@ -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",
+2 -1
View File
@@ -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" }
]
}