From 47a50acc55151a75ec1f21b8bb3a86b3c40b0c06 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 11 Dec 2017 15:16:13 -0800 Subject: [PATCH 01/19] Use IntersectionObserver to turn off renderer when hidden Fixes #880 --- src/renderer/Renderer.ts | 52 +++++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/src/renderer/Renderer.ts b/src/renderer/Renderer.ts index ea373e5e..adfe22c1 100644 --- a/src/renderer/Renderer.ts +++ b/src/renderer/Renderer.ts @@ -21,6 +21,8 @@ export class Renderer extends EventEmitter implements IRenderer { private _renderLayers: IRenderLayer[]; private _devicePixelRatio: number; + private _isPaused: boolean = false; + private _needsFullRefresh: boolean = false; public colorManager: ColorManager; public dimensions: IRenderDimensions; @@ -52,6 +54,20 @@ export class Renderer extends EventEmitter implements IRenderer { actualCellHeight: null }; this._devicePixelRatio = window.devicePixelRatio; + + // Detect whether IntersectionObserver is detected and enable renderer pause + // and resume based on terminal visibility if so + if ('IntersectionObserver' in window) { + const observer = new IntersectionObserver(e => this.onIntersectionChange(e[0]), {threshold: 0}); + observer.observe(this._terminal.element); + } + } + + public onIntersectionChange(entry: IntersectionObserverEntry): void { + this._isPaused = entry.intersectionRatio === 0; + if (!this._isPaused && this._needsFullRefresh) { + this._terminal.refresh(0, this._terminal.rows - 1); + } } public onWindowResize(devicePixelRatio: number): void { @@ -72,7 +88,11 @@ export class Renderer extends EventEmitter implements IRenderer { l.reset(this._terminal); }); - this._terminal.refresh(0, this._terminal.rows - 1); + if (this._isPaused) { + this._needsFullRefresh = true; + } else { + this._terminal.refresh(0, this._terminal.rows - 1); + } return this.colorManager.colors; } @@ -136,7 +156,11 @@ export class Renderer extends EventEmitter implements IRenderer { this._renderLayers.forEach(l => l.resize(this._terminal, this.dimensions, didCharSizeChange)); // Force a refresh - this._terminal.refresh(0, this._terminal.rows - 1); + if (this._isPaused) { + this._needsFullRefresh = true; + } else { + this._terminal.refresh(0, this._terminal.rows - 1); + } this.emit('resize', { width: this.dimensions.canvasWidth, @@ -149,27 +173,35 @@ export class Renderer extends EventEmitter implements IRenderer { } public onBlur(): void { - this._renderLayers.forEach(l => l.onBlur(this._terminal)); + this._runOperation(l => l.onBlur(this._terminal)); } public onFocus(): void { - this._renderLayers.forEach(l => l.onFocus(this._terminal)); + this._runOperation(l => l.onFocus(this._terminal)); } public onSelectionChanged(start: [number, number], end: [number, number]): void { - this._renderLayers.forEach(l => l.onSelectionChanged(this._terminal, start, end)); + this._runOperation(l => l.onSelectionChanged(this._terminal, start, end)); } public onCursorMove(): void { - this._renderLayers.forEach(l => l.onCursorMove(this._terminal)); + this._runOperation(l => l.onCursorMove(this._terminal)); } public onOptionsChanged(): void { - this._renderLayers.forEach(l => l.onOptionsChanged(this._terminal)); + this._runOperation(l => l.onOptionsChanged(this._terminal)); } public clear(): void { - this._renderLayers.forEach(l => l.reset(this._terminal)); + this._runOperation(l => l.reset(this._terminal)); + } + + private _runOperation(operation: (layer: IRenderLayer) => void): void { + if (this._isPaused) { + this._needsFullRefresh = true; + } else { + this._renderLayers.forEach(l => operation(l)); + } } /** @@ -179,6 +211,10 @@ export class Renderer extends EventEmitter implements IRenderer { * @param {number} end The end row. */ public queueRefresh(start: number, end: number): void { + if (this._isPaused) { + this._needsFullRefresh = true; + return; + } this._refreshRowsQueue.push({ start: start, end: end }); if (!this._refreshAnimationFrame) { this._refreshAnimationFrame = window.requestAnimationFrame(this._refreshLoop.bind(this)); From ef5beb670678c8bcda1bb226d91bfbfd89518598 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 29 Dec 2017 08:30:13 -0800 Subject: [PATCH 02/19] Update charatlas when monitor DPI changes Fixes #1118 --- src/Terminal.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index afea5e90..3026c9a3 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -637,7 +637,11 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT this.on('resize', () => this.renderer.onResize(this.cols, this.rows, false)); this.on('blur', () => this.renderer.onBlur()); this.on('focus', () => this.renderer.onFocus()); - window.addEventListener('resize', () => this.renderer.onWindowResize(window.devicePixelRatio)); + const rendererResizeListener = () => this.renderer.onWindowResize(window.devicePixelRatio); + // Listen for window zoom + window.addEventListener('resize', () => rendererResizeListener); + // Listen for monitor DPI change + window.matchMedia('screen and (-webkit-min-device-pixel-ratio: 1.5)').addListener(rendererResizeListener); this.charMeasure.on('charsizechanged', () => this.renderer.onResize(this.cols, this.rows, true)); this.renderer.on('resize', (dimensions) => this.viewport.syncScrollArea()); From 72d946e089a4014e510f5d60751c391444e5f891 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 29 Dec 2017 13:54:01 -0800 Subject: [PATCH 03/19] Use a more robust solution to changing devicePixelRatio --- src/Terminal.ts | 5 --- src/renderer/Renderer.ts | 5 +++ src/utils/ScreenDprMonitor.ts | 62 +++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 src/utils/ScreenDprMonitor.ts diff --git a/src/Terminal.ts b/src/Terminal.ts index 3026c9a3..dd2bf405 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -637,11 +637,6 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT this.on('resize', () => this.renderer.onResize(this.cols, this.rows, false)); this.on('blur', () => this.renderer.onBlur()); this.on('focus', () => this.renderer.onFocus()); - const rendererResizeListener = () => this.renderer.onWindowResize(window.devicePixelRatio); - // Listen for window zoom - window.addEventListener('resize', () => rendererResizeListener); - // Listen for monitor DPI change - window.matchMedia('screen and (-webkit-min-device-pixel-ratio: 1.5)').addListener(rendererResizeListener); this.charMeasure.on('charsizechanged', () => this.renderer.onResize(this.cols, this.rows, true)); this.renderer.on('resize', (dimensions) => this.viewport.syncScrollArea()); diff --git a/src/renderer/Renderer.ts b/src/renderer/Renderer.ts index 36727eac..422d424c 100644 --- a/src/renderer/Renderer.ts +++ b/src/renderer/Renderer.ts @@ -13,6 +13,7 @@ import { BaseRenderLayer } from './BaseRenderLayer'; import { IRenderLayer, IColorSet, IRenderer, IRenderDimensions } from './Interfaces'; import { LinkRenderLayer } from './LinkRenderLayer'; import { EventEmitter } from '../EventEmitter'; +import { ScreenDprMonitor } from '../utils/ScreenDprMonitor'; export class Renderer extends EventEmitter implements IRenderer { /** A queue of the rows to be refreshed */ @@ -21,6 +22,7 @@ export class Renderer extends EventEmitter implements IRenderer { private _renderLayers: IRenderLayer[]; private _devicePixelRatio: number; + private _screenDprMonitor: ScreenDprMonitor; public colorManager: ColorManager; public dimensions: IRenderDimensions; @@ -53,6 +55,9 @@ export class Renderer extends EventEmitter implements IRenderer { }; this._devicePixelRatio = window.devicePixelRatio; this._updateDimensions(); + + this._screenDprMonitor = new ScreenDprMonitor(); + this._screenDprMonitor.setListener(() => this.onWindowResize(window.devicePixelRatio)); } public onWindowResize(devicePixelRatio: number): void { diff --git a/src/utils/ScreenDprMonitor.ts b/src/utils/ScreenDprMonitor.ts new file mode 100644 index 00000000..5c5f762c --- /dev/null +++ b/src/utils/ScreenDprMonitor.ts @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +export type ScreenDprListener = (newDevicePixelRatio?: number, oldDevicePixelRatio?: number) => void; + +/** + * The screen device pixel ratio monitor allows listening for when the + * window.devicePixelRatio value changes. This is done not with polling but with + * the use of window.matchMedia to watch media queries. When the event fires, + * the listener will be reattached using a different media query to ensure that + * any further changes will register. + * + * The listener should fire on both window zoom changes and switching to a + * monitor with a different DPI. + */ +export class ScreenDprMonitor { + private _currentDevicePixelRatio: number; + private _outerListener: MediaQueryListListener; + private _listener: ScreenDprListener; + private _minMediaMatchList: MediaQueryList; + private _maxMediaMatchList: MediaQueryList; + + public setListener(listener: ScreenDprListener): void { + if (this._listener) { + this.clearListener(); + } + this._listener = listener; + this._outerListener = () => { + this._listener(window.devicePixelRatio, this._currentDevicePixelRatio); + this._updateDpr(); + }; + this._updateDpr(); + } + + private _updateDpr(): void { + // Clear listeners for old DPR + if (this._minMediaMatchList) { + this._minMediaMatchList.removeListener(this._outerListener); + } + if (this._maxMediaMatchList) { + this._maxMediaMatchList.removeListener(this._outerListener); + } + // Add listeners for new DPR + this._currentDevicePixelRatio = window.devicePixelRatio; + this._minMediaMatchList = window.matchMedia(`screen and (-webkit-min-device-pixel-ratio: ${window.devicePixelRatio})`); + this._maxMediaMatchList = window.matchMedia(`screen and (-webkit-max-device-pixel-ratio: ${window.devicePixelRatio})`); + this._minMediaMatchList.addListener(this._outerListener); + this._maxMediaMatchList.addListener(this._outerListener); + } + + public clearListener(): void { + if (!this._listener) { + return; + } + this._minMediaMatchList.removeListener(this._outerListener); + this._maxMediaMatchList.removeListener(this._outerListener); + this._listener = null; + this._outerListener = null; + } +} From ecc1055c10c8842b0104a19509aba552513cc7dc Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 2 Jan 2018 10:11:24 -0800 Subject: [PATCH 04/19] Listen to resolution media query --- src/utils/ScreenDprMonitor.ts | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/utils/ScreenDprMonitor.ts b/src/utils/ScreenDprMonitor.ts index 5c5f762c..405a18f8 100644 --- a/src/utils/ScreenDprMonitor.ts +++ b/src/utils/ScreenDprMonitor.ts @@ -19,8 +19,7 @@ export class ScreenDprMonitor { private _currentDevicePixelRatio: number; private _outerListener: MediaQueryListListener; private _listener: ScreenDprListener; - private _minMediaMatchList: MediaQueryList; - private _maxMediaMatchList: MediaQueryList; + private _resolutionMediaMatchList: MediaQueryList; public setListener(listener: ScreenDprListener): void { if (this._listener) { @@ -28,6 +27,7 @@ export class ScreenDprMonitor { } this._listener = listener; this._outerListener = () => { + console.log('change!'); this._listener(window.devicePixelRatio, this._currentDevicePixelRatio); this._updateDpr(); }; @@ -36,26 +36,20 @@ export class ScreenDprMonitor { private _updateDpr(): void { // Clear listeners for old DPR - if (this._minMediaMatchList) { - this._minMediaMatchList.removeListener(this._outerListener); - } - if (this._maxMediaMatchList) { - this._maxMediaMatchList.removeListener(this._outerListener); + if (this._resolutionMediaMatchList) { + this._resolutionMediaMatchList.removeListener(this._outerListener); } // Add listeners for new DPR this._currentDevicePixelRatio = window.devicePixelRatio; - this._minMediaMatchList = window.matchMedia(`screen and (-webkit-min-device-pixel-ratio: ${window.devicePixelRatio})`); - this._maxMediaMatchList = window.matchMedia(`screen and (-webkit-max-device-pixel-ratio: ${window.devicePixelRatio})`); - this._minMediaMatchList.addListener(this._outerListener); - this._maxMediaMatchList.addListener(this._outerListener); + this._resolutionMediaMatchList = window.matchMedia(`screen and (resolution: ${window.devicePixelRatio}dppx)`); + this._resolutionMediaMatchList.addListener(this._outerListener); } public clearListener(): void { if (!this._listener) { return; } - this._minMediaMatchList.removeListener(this._outerListener); - this._maxMediaMatchList.removeListener(this._outerListener); + this._resolutionMediaMatchList.removeListener(this._outerListener); this._listener = null; this._outerListener = null; } From 82e7fe5a1b21959cfc111f43a40fdc4a63116383 Mon Sep 17 00:00:00 2001 From: Antonin Stefanutti Date: Fri, 5 Jan 2018 22:12:32 +0100 Subject: [PATCH 05/19] Add Kubebox to real-world uses --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5a77806f..1719efb2 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,7 @@ computational environment for Jupyter, supporting interactive data science and s - [**Whack Whack Terminal**](https://github.com/Microsoft/WhackWhackTerminal): Terminal emulator for Visual Studio 2017. - [**VTerm**](https://github.com/vterm/vterm): Extensible terminal emulator based on Electron and React. - [**electerm**](http://electerm.html5beta.com): electerm is a terminal/ssh/sftp client(mac, win, linux) based on electron/node-pty/xterm. +- [**Kubebox**](https://github.com/astefanutti/kubebox): Terminal console for Kubernetes clusters. Do you use xterm.js in your application as well? Please [open a Pull Request](https://github.com/sourcelair/xterm.js/pulls) to include it here. We would love to have it in our list. From 248fbccfd9c9bcb124bd0930867178e5b534ce91 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 5 Jan 2018 14:18:16 -0800 Subject: [PATCH 06/19] Remove console.log --- src/utils/ScreenDprMonitor.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils/ScreenDprMonitor.ts b/src/utils/ScreenDprMonitor.ts index 405a18f8..15f3ac00 100644 --- a/src/utils/ScreenDprMonitor.ts +++ b/src/utils/ScreenDprMonitor.ts @@ -27,7 +27,6 @@ export class ScreenDprMonitor { } this._listener = listener; this._outerListener = () => { - console.log('change!'); this._listener(window.devicePixelRatio, this._currentDevicePixelRatio); this._updateDpr(); }; From a36a17928dc3ccf027c81832b3cadff0d3818d3e Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Sat, 6 Jan 2018 07:18:07 -0600 Subject: [PATCH 07/19] Ship the declaration files --- gulpfile.js | 11 ++++++++--- src/addons/attach/tsconfig.json | 3 ++- src/addons/fit/tsconfig.json | 3 ++- src/addons/fullscreen/tsconfig.json | 3 ++- src/addons/search/tsconfig.json | 3 ++- src/addons/terminado/tsconfig.json | 3 ++- src/addons/winptyCompat/tsconfig.json | 3 ++- src/addons/zmodem/tsconfig.json | 3 ++- tsconfig.json | 3 ++- 9 files changed, 24 insertions(+), 11 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 49d67ed6..804cad35 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -51,9 +51,14 @@ gulp.task('tsc', function () { let tsProjectAddon = ts.createProject(`./src/addons/${addon}/tsconfig.json`); let tsResultAddon = tsProjectAddon.src().pipe(sourcemaps.init()).pipe(tsProjectAddon()); - let tscAddon = tsResultAddon.js - .pipe(sourcemaps.write('.', {includeContent: false, sourceRoot: ''})) - .pipe(gulp.dest(`${outDir}/addons/${addon}`)); + let tscAddon = merge( + tsResultAddon.js + .pipe(sourcemaps.write('.', {includeContent: false, sourceRoot: ''})) + .pipe(gulp.dest(`${outDir}/addons/${addon}`)), + tsResultAddon.dts + .pipe(sourcemaps.write('.', {includeContent: false, sourceRoot: ''})) + .pipe(gulp.dest(`${outDir}/addons/${addon}`)) + ) return tscAddon; }); diff --git a/src/addons/attach/tsconfig.json b/src/addons/attach/tsconfig.json index 97722324..a4e8e78b 100644 --- a/src/addons/attach/tsconfig.json +++ b/src/addons/attach/tsconfig.json @@ -5,6 +5,7 @@ "rootDir": ".", "outDir": "../../../lib/addons/attach/", "sourceMap": true, - "removeComments": true + "removeComments": true, + "declaration": true } } diff --git a/src/addons/fit/tsconfig.json b/src/addons/fit/tsconfig.json index 949f8b60..78b3c410 100644 --- a/src/addons/fit/tsconfig.json +++ b/src/addons/fit/tsconfig.json @@ -5,6 +5,7 @@ "rootDir": ".", "outDir": "../../../lib/addons/fit/", "sourceMap": true, - "removeComments": true + "removeComments": true, + "declaration": true } } diff --git a/src/addons/fullscreen/tsconfig.json b/src/addons/fullscreen/tsconfig.json index b04144c1..35ecb7ce 100644 --- a/src/addons/fullscreen/tsconfig.json +++ b/src/addons/fullscreen/tsconfig.json @@ -5,6 +5,7 @@ "rootDir": ".", "outDir": "../../../lib/addons/fullscreen/", "sourceMap": true, - "removeComments": true + "removeComments": true, + "declaration": true } } diff --git a/src/addons/search/tsconfig.json b/src/addons/search/tsconfig.json index 7f72e47f..d1c3d7e0 100644 --- a/src/addons/search/tsconfig.json +++ b/src/addons/search/tsconfig.json @@ -5,6 +5,7 @@ "rootDir": ".", "outDir": "../../../lib/addons/search/", "sourceMap": true, - "removeComments": true + "removeComments": true, + "declaration": true } } diff --git a/src/addons/terminado/tsconfig.json b/src/addons/terminado/tsconfig.json index 775b20d5..84e3ac32 100644 --- a/src/addons/terminado/tsconfig.json +++ b/src/addons/terminado/tsconfig.json @@ -5,6 +5,7 @@ "rootDir": ".", "outDir": "../../../lib/addons/terminado/", "sourceMap": true, - "removeComments": true + "removeComments": true, + "declaration": true } } diff --git a/src/addons/winptyCompat/tsconfig.json b/src/addons/winptyCompat/tsconfig.json index e15a09a8..a51f7332 100644 --- a/src/addons/winptyCompat/tsconfig.json +++ b/src/addons/winptyCompat/tsconfig.json @@ -5,6 +5,7 @@ "rootDir": ".", "outDir": "../../../lib/addons/winptyCompat/", "sourceMap": true, - "removeComments": true + "removeComments": true, + "declaration": true } } diff --git a/src/addons/zmodem/tsconfig.json b/src/addons/zmodem/tsconfig.json index 9ded72e5..abae1238 100644 --- a/src/addons/zmodem/tsconfig.json +++ b/src/addons/zmodem/tsconfig.json @@ -5,6 +5,7 @@ "rootDir": ".", "outDir": "../../../lib/addons/zmodem/", "sourceMap": true, - "removeComments": true + "removeComments": true, + "declaration": true } } diff --git a/tsconfig.json b/tsconfig.json index 38bfd2fa..a3aa790c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,7 +5,8 @@ "rootDir": "src", "outDir": "lib", "sourceMap": true, - "removeComments": true + "removeComments": true, + "declaration": true }, "include": [ "src/**/*" From b7c0ca11fe8340f1baead1e954092131e11eb3b3 Mon Sep 17 00:00:00 2001 From: ficristo Date: Sun, 7 Jan 2018 09:02:41 +0100 Subject: [PATCH 08/19] Make addons UMD compatible --- gulpfile.js | 73 ++++++++++++++++++++++------------------------------- 1 file changed, 30 insertions(+), 43 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 49d67ed6..4a4be8b0 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -18,11 +18,13 @@ const ts = require('gulp-typescript'); const util = require('gulp-util'); const webpack = require('webpack-stream'); -let buildDir = process.env.BUILD_DIR || 'build'; -let tsProject = ts.createProject('tsconfig.json'); -let srcDir = tsProject.config.compilerOptions.rootDir; +const buildDir = process.env.BUILD_DIR || 'build'; +const tsProject = ts.createProject('tsconfig.json'); +const srcDir = tsProject.config.compilerOptions.rootDir; let outDir = tsProject.config.compilerOptions.outDir; +const addons = ['attach', 'fit', 'fullscreen', 'search', 'terminado', 'winptyCompat', 'zmodem']; + // Under some environments like TravisCI, this comes out at absolute which can // break the build. This ensures that the outDir is absolute. if (path.normalize(outDir).indexOf(__dirname) !== 0) { @@ -45,7 +47,6 @@ gulp.task('tsc', function () { tsResult.dts.pipe(sourcemaps.write('.', {includeContent: false, sourceRoot: ''})).pipe(gulp.dest(outDir)) ); - let addons = ['attach', 'fit', 'fullscreen', 'search', 'terminado', 'winptyCompat', 'zmodem']; let addonStreams = addons.map(function(addon) { fs.emptyDirSync(`${outDir}/addons/${addon}`); @@ -103,45 +104,29 @@ gulp.task('browserify', ['tsc'], function() { }); gulp.task('browserify-addons', ['tsc'], function() { - let searchOptions = { - basedir: `${buildDir}/addons/search`, - debug: true, - entries: [`${outDir}/addons/search/search.js`], - cache: {}, - packageCache: {} - }; - let searchBundle = browserify(searchOptions) - .external(path.join(outDir, 'Terminal.js')) - .bundle() - .pipe(source('./addons/search/search.js')) - .pipe(buffer()) - .pipe(sourcemaps.init({loadMaps: true, sourceRoot: ''})) - .pipe(sourcemaps.write('./')) - .pipe(gulp.dest(buildDir)); + const bundles = addons.map((addon) => { + const addonOptions = { + basedir: `${buildDir}/addons/${addon}`, + debug: true, + entries: [`${outDir}/addons/${addon}/${addon}.js`], + standalone: addon, + cache: {}, + packageCache: {} + }; - let winptyCompatOptions = { - basedir: `${buildDir}/addons/winptyCompat`, - debug: true, - entries: [`${outDir}/addons/winptyCompat/winptyCompat.js`], - cache: {}, - packageCache: {} - }; - let winptyCompatBundle = browserify(winptyCompatOptions) - .external(path.join(outDir, 'Terminal.js')) - .bundle() - .pipe(source('./addons/winptyCompat/winptyCompat.js')) - .pipe(buffer()) - .pipe(sourcemaps.init({loadMaps: true, sourceRoot: ''})) - .pipe(sourcemaps.write('./')) - .pipe(gulp.dest(buildDir)); + const addonBundle = browserify(addonOptions) + .external(path.join(outDir, 'Terminal.js')) + .bundle() + .pipe(source(`./addons/${addon}/${addon}.js`)) + .pipe(buffer()) + .pipe(sourcemaps.init({loadMaps: true, sourceRoot: ''})) + .pipe(sourcemaps.write('./')) + .pipe(gulp.dest(buildDir)); - // Copy all add-ons from outDir to buildDir - let copyAddons = gulp.src([ - // Copy JS addons - `${outDir}/addons/**/*` - ]).pipe(gulp.dest(`${buildDir}/addons`)); + return addonBundle; + }); - return merge(searchBundle, winptyCompatBundle, copyAddons); + return merge(...bundles); }); gulp.task('instrument-test', function () { @@ -189,9 +174,11 @@ gulp.task('sorcery', ['browserify'], function () { }); gulp.task('sorcery-addons', ['browserify-addons'], function () { - var chain = sorcery.loadSync(`${buildDir}/addons/search/search.js`); - chain.apply(); - chain.writeSync(); + addons.forEach((addon) => { + const chain = sorcery.loadSync(`${buildDir}/addons/${addon}/${addon}.js`); + chain.apply(); + chain.writeSync(); + }) }); gulp.task('webpack', ['build'], function() { From 5a147f201f476cc59947d51194dc09b6f9c6466c Mon Sep 17 00:00:00 2001 From: Justin Luk Date: Fri, 12 Jan 2018 15:13:19 -0800 Subject: [PATCH 09/19] Include cloud shell in xterm applications --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 1719efb2..2cf99749 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,7 @@ computational environment for Jupyter, supporting interactive data science and s - [**VTerm**](https://github.com/vterm/vterm): Extensible terminal emulator based on Electron and React. - [**electerm**](http://electerm.html5beta.com): electerm is a terminal/ssh/sftp client(mac, win, linux) based on electron/node-pty/xterm. - [**Kubebox**](https://github.com/astefanutti/kubebox): Terminal console for Kubernetes clusters. +- [**Azure Cloud Shell**](https://shell.azure.com): Azure Cloud Shell is a Microsoft-managed admin machine built on Azure, for Azure. Do you use xterm.js in your application as well? Please [open a Pull Request](https://github.com/sourcelair/xterm.js/pulls) to include it here. We would love to have it in our list. From a7101b5bcb89870f7620e352551d6c03f6643928 Mon Sep 17 00:00:00 2001 From: Andres Mejia Date: Sat, 13 Jan 2018 15:34:05 -0500 Subject: [PATCH 10/19] Add use case for atom-xterm. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2cf99749..93e7f262 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,7 @@ computational environment for Jupyter, supporting interactive data science and s - [**electerm**](http://electerm.html5beta.com): electerm is a terminal/ssh/sftp client(mac, win, linux) based on electron/node-pty/xterm. - [**Kubebox**](https://github.com/astefanutti/kubebox): Terminal console for Kubernetes clusters. - [**Azure Cloud Shell**](https://shell.azure.com): Azure Cloud Shell is a Microsoft-managed admin machine built on Azure, for Azure. +- [**atom-xterm**](https://atom.io/packages/atom-xterm): Atom plugin for providing terminals inside your Atom workspace. Do you use xterm.js in your application as well? Please [open a Pull Request](https://github.com/sourcelair/xterm.js/pulls) to include it here. We would love to have it in our list. From 80f13792a375002a0d7154b92d38ff3acea67ead Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 16 Jan 2018 06:34:22 -0800 Subject: [PATCH 11/19] Ensure renderer uses latest options at open Fixes #1194 --- src/renderer/Renderer.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/renderer/Renderer.ts b/src/renderer/Renderer.ts index 31547da4..680d9490 100644 --- a/src/renderer/Renderer.ts +++ b/src/renderer/Renderer.ts @@ -57,6 +57,7 @@ export class Renderer extends EventEmitter implements IRenderer { }; this._devicePixelRatio = window.devicePixelRatio; this._updateDimensions(); + this.onOptionsChanged(); this._screenDprMonitor = new ScreenDprMonitor(); this._screenDprMonitor.setListener(() => this.onWindowResize(window.devicePixelRatio)); From 70236f68185da13e9b2a1da898a532866dc6111b Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 17 Jan 2018 10:20:04 -0800 Subject: [PATCH 12/19] Fix addon lint --- src/addons/attach/attach.test.ts | 2 +- src/addons/attach/attach.ts | 35 +++++++-------- src/addons/fit/fit.test.ts | 2 +- src/addons/fit/fit.ts | 43 ++++++++++-------- src/addons/fullscreen/fullscreen.test.ts | 2 +- src/addons/fullscreen/fullscreen.ts | 12 ++--- src/addons/search/search.ts | 10 ++--- src/addons/terminado/terminado.test.ts | 2 +- src/addons/terminado/terminado.ts | 28 ++++++------ src/addons/winptyCompat/winptyCompat.test.ts | 2 +- src/addons/winptyCompat/winptyCompat.ts | 4 +- src/addons/zmodem/zmodem.test.ts | 2 +- src/addons/zmodem/zmodem.ts | 47 +++++++++----------- 13 files changed, 94 insertions(+), 97 deletions(-) diff --git a/src/addons/attach/attach.test.ts b/src/addons/attach/attach.test.ts index 9bf0e070..a13885bb 100644 --- a/src/addons/attach/attach.test.ts +++ b/src/addons/attach/attach.test.ts @@ -5,7 +5,7 @@ import { assert, expect } from 'chai'; -import * as attach from './attach' +import * as attach from './attach'; class MockTerminal {} diff --git a/src/addons/attach/attach.ts b/src/addons/attach/attach.ts index 4e0d5941..349a03dd 100644 --- a/src/addons/attach/attach.ts +++ b/src/addons/attach/attach.ts @@ -16,16 +16,16 @@ * should happen instantly or at a maximum * frequency of 1 rendering per 10ms. */ -export function attach(term, socket, bidirectional, buffered) { - bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional; +export function attach(term: any, socket: WebSocket, bidirectional: boolean, buffered: boolean): void { + bidirectional = (typeof bidirectional === 'undefined') ? true : bidirectional; term.socket = socket; - term._flushBuffer = function() { + term._flushBuffer = () => { term.write(term._attachSocketBuffer); term._attachSocketBuffer = null; }; - term._pushToBuffer = function(data) { + term._pushToBuffer = (data: string) => { if (term._attachSocketBuffer) { term._attachSocketBuffer += data; } else { @@ -34,20 +34,19 @@ export function attach(term, socket, bidirectional, buffered) { } }; - var myTextDecoder; + let myTextDecoder; - term._getMessage = function(ev) { - var str; - if (typeof ev.data === "object") { + term._getMessage = function(ev: MessageEvent): void { + let str; + if (typeof ev.data === 'object') { if (ev.data instanceof ArrayBuffer) { if (!myTextDecoder) { myTextDecoder = new TextDecoder(); } str = myTextDecoder.decode( ev.data ); - } - else { - throw "TODO: handle Blob?"; + } else { + throw 'TODO: handle Blob?'; } } @@ -58,7 +57,7 @@ export function attach(term, socket, bidirectional, buffered) { } }; - term._sendData = function(data) { + term._sendData = (data: string) => { if (socket.readyState !== 1) { return; } @@ -82,10 +81,10 @@ export function attach(term, socket, bidirectional, buffered) { * @param {WebSocket} socket - The socket from which to detach the current * terminal. */ -export function detach(term, socket) { +export function detach(term: any, socket: WebSocket): void { term.off('data', term._sendData); - socket = (typeof socket == 'undefined') ? term.socket : socket; + socket = (typeof socket === 'undefined') ? term.socket : socket; if (socket) { socket.removeEventListener('message', term._getMessage); @@ -95,7 +94,7 @@ export function detach(term, socket) { }; -export function apply(terminalConstructor) { +export function apply(terminalConstructor: any): void { /** * Attaches the current terminal to the given socket * @@ -106,7 +105,7 @@ export function apply(terminalConstructor) { * should happen instantly or at a maximum * frequency of 1 rendering per 10ms. */ - terminalConstructor.prototype.attach = function(socket, bidirectional, buffered) { + terminalConstructor.prototype.attach = (socket: WebSocket, bidirectional: boolean, buffered: boolean) => { return attach(this, socket, bidirectional, buffered); }; @@ -116,7 +115,7 @@ export function apply(terminalConstructor) { * @param {WebSocket} socket - The socket from which to detach the current * terminal. */ - terminalConstructor.prototype.detach = function(socket) { + terminalConstructor.prototype.detach = (socket: WebSocket) => { return detach(this, socket); }; -} +}; diff --git a/src/addons/fit/fit.test.ts b/src/addons/fit/fit.test.ts index 159cc987..0dc17963 100644 --- a/src/addons/fit/fit.test.ts +++ b/src/addons/fit/fit.test.ts @@ -5,7 +5,7 @@ import { assert, expect } from 'chai'; -import * as fit from './fit' +import * as fit from './fit'; class MockTerminal {} diff --git a/src/addons/fit/fit.ts b/src/addons/fit/fit.ts index b87ccc07..f037b540 100644 --- a/src/addons/fit/fit.ts +++ b/src/addons/fit/fit.ts @@ -13,28 +13,33 @@ * row and truncate its width with the current number of columns). */ -export function proposeGeometry(term) { +export interface IGeometry { + rows: number; + cols: number; +} + +export function proposeGeometry(term: any): IGeometry { if (!term.element.parentElement) { return null; } - var parentElementStyle = window.getComputedStyle(term.element.parentElement); - var parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')); - var parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')) - 17); - var elementStyle = window.getComputedStyle(term.element); - var elementPaddingVer = parseInt(elementStyle.getPropertyValue('padding-top')) + parseInt(elementStyle.getPropertyValue('padding-bottom')); - var elementPaddingHor = parseInt(elementStyle.getPropertyValue('padding-right')) + parseInt(elementStyle.getPropertyValue('padding-left')); - var availableHeight = parentElementHeight - elementPaddingVer; - var availableWidth = parentElementWidth - elementPaddingHor; - var geometry = { + const parentElementStyle = window.getComputedStyle(term.element.parentElement); + const parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')); + const parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')) - 17); + const elementStyle = window.getComputedStyle(term.element); + const elementPaddingVer = parseInt(elementStyle.getPropertyValue('padding-top')) + parseInt(elementStyle.getPropertyValue('padding-bottom')); + const elementPaddingHor = parseInt(elementStyle.getPropertyValue('padding-right')) + parseInt(elementStyle.getPropertyValue('padding-left')); + const availableHeight = parentElementHeight - elementPaddingVer; + const availableWidth = parentElementWidth - elementPaddingHor; + const geometry = { cols: Math.floor(availableWidth / term.renderer.dimensions.actualCellWidth), rows: Math.floor(availableHeight / term.renderer.dimensions.actualCellHeight) }; return geometry; -}; +} -export function fit(term) { - var geometry = proposeGeometry(term); +export function fit(term: any): void { + const geometry = proposeGeometry(term); if (geometry) { // Force a full render if (term.rows !== geometry.rows || term.cols !== geometry.cols) { @@ -44,12 +49,12 @@ export function fit(term) { } }; -export function apply(terminalConstructor) { - terminalConstructor.prototype.proposeGeometry = function() { +export function apply(terminalConstructor: any): void { + terminalConstructor.prototype.proposeGeometry = function (): IGeometry { return proposeGeometry(this); - } + }; - terminalConstructor.prototype.fit = function() { - return fit(this); - } + terminalConstructor.prototype.fit = function (): void { + fit(this); + }; } diff --git a/src/addons/fullscreen/fullscreen.test.ts b/src/addons/fullscreen/fullscreen.test.ts index c77ea75c..9326ac4e 100644 --- a/src/addons/fullscreen/fullscreen.test.ts +++ b/src/addons/fullscreen/fullscreen.test.ts @@ -5,7 +5,7 @@ import { assert, expect } from 'chai'; -import * as fullscreen from './fullscreen' +import * as fullscreen from './fullscreen'; class MockTerminal {} diff --git a/src/addons/fullscreen/fullscreen.ts b/src/addons/fullscreen/fullscreen.ts index 31ab5189..0eb61ea1 100644 --- a/src/addons/fullscreen/fullscreen.ts +++ b/src/addons/fullscreen/fullscreen.ts @@ -8,10 +8,10 @@ * @param {Terminal} term - The terminal to toggle full screen mode * @param {boolean} fullscreen - Toggle fullscreen on (true) or off (false) */ -export function toggleFullScreen(term, fullscreen) { - var fn; +export function toggleFullScreen(term: any, fullscreen: boolean): void { + let fn; - if (typeof fullscreen == 'undefined') { + if (typeof fullscreen === 'undefined') { fn = (term.element.classList.contains('fullscreen')) ? 'remove' : 'add'; } else if (!fullscreen) { fn = 'remove'; @@ -22,8 +22,8 @@ export function toggleFullScreen(term, fullscreen) { term.element.classList[fn]('fullscreen'); }; -export function apply(terminalConstructor) { - terminalConstructor.prototype.toggleFullScreen = function (fullscreen) { - return toggleFullScreen(this, fullscreen); +export function apply(terminalConstructor: any): void { + terminalConstructor.prototype.toggleFullScreen = function (fullscreen: boolean): void { + toggleFullScreen(this, fullscreen); }; } diff --git a/src/addons/search/search.ts b/src/addons/search/search.ts index 480fea7f..375b86f4 100644 --- a/src/addons/search/search.ts +++ b/src/addons/search/search.ts @@ -32,12 +32,12 @@ export function findPrevious(terminal: any, term: string): boolean { return (terminal.searchHelper).findPrevious(term); }; -export function apply(terminalConstructor) { - terminalConstructor.prototype.findNext = function(term) { +export function apply(terminalConstructor: any): void { + terminalConstructor.prototype.findNext = function(term: any): boolean { return findNext(this, term); - } + }; - terminalConstructor.prototype.findPrevious = function(term) { + terminalConstructor.prototype.findPrevious = function(term: any): boolean { return findPrevious(this, term); - } + }; } diff --git a/src/addons/terminado/terminado.test.ts b/src/addons/terminado/terminado.test.ts index fe059898..e258bd7c 100644 --- a/src/addons/terminado/terminado.test.ts +++ b/src/addons/terminado/terminado.test.ts @@ -5,7 +5,7 @@ import { assert, expect } from 'chai'; -import * as terminado from './terminado' +import * as terminado from './terminado'; class MockTerminal {} diff --git a/src/addons/terminado/terminado.ts b/src/addons/terminado/terminado.ts index 9a7c7ad6..afd7277c 100644 --- a/src/addons/terminado/terminado.ts +++ b/src/addons/terminado/terminado.ts @@ -17,16 +17,16 @@ * should happen instantly or at a maximum * frequency of 1 rendering per 10ms. */ -export function terminadoAttach(term, socket, bidirectional, buffered) { - bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional; +export function terminadoAttach(term: any, socket: WebSocket, bidirectional: boolean, buffered: boolean): void { + bidirectional = (typeof bidirectional === 'undefined') ? true : bidirectional; term.socket = socket; - term._flushBuffer = function() { + term._flushBuffer = () => { term.write(term._attachSocketBuffer); term._attachSocketBuffer = null; }; - term._pushToBuffer = function(data) { + term._pushToBuffer = (data) => { if (term._attachSocketBuffer) { term._attachSocketBuffer += data; } else { @@ -35,9 +35,9 @@ export function terminadoAttach(term, socket, bidirectional, buffered) { } }; - term._getMessage = function(ev) { - var data = JSON.parse(ev.data) - if( data[0] == "stdout" ) { + term._getMessage = (ev: MessageEvent) => { + const data = JSON.parse(ev.data); + if (data[0] === 'stdout') { if (buffered) { term._pushToBuffer(data[1]); } else { @@ -46,11 +46,11 @@ export function terminadoAttach(term, socket, bidirectional, buffered) { } }; - term._sendData = function(data) { + term._sendData = (data: string) => { socket.send(JSON.stringify(['stdin', data])); }; - term._setSize = function(size) { + term._setSize = (size: {rows: number, cols: number}) => { socket.send(JSON.stringify(['set_size', size.rows, size.cols])); }; @@ -72,10 +72,10 @@ export function terminadoAttach(term, socket, bidirectional, buffered) { * @param {WebSocket} socket - The socket from which to detach the current * terminal. */ -export function terminadoDetach(term, socket) { +export function terminadoDetach(term: any, socket: WebSocket): void { term.off('data', term._sendData); - socket = (typeof socket == 'undefined') ? term.socket : socket; + socket = (typeof socket === 'undefined') ? term.socket : socket; if (socket) { socket.removeEventListener('message', term._getMessage); @@ -84,7 +84,7 @@ export function terminadoDetach(term, socket) { delete term.socket; }; -export function apply(terminalConstructor) { +export function apply(terminalConstructor: any): void { /** * Attaches the current terminal to the given socket * @@ -95,7 +95,7 @@ export function apply(terminalConstructor) { * should happen instantly or at a maximum * frequency of 1 rendering per 10ms. */ - terminalConstructor.prototype.terminadoAttach = function(socket, bidirectional, buffered) { + terminalConstructor.prototype.terminadoAttach = function(socket: WebSocket, bidirectional: boolean, buffered: boolean): void { return terminadoAttach(this, socket, bidirectional, buffered); }; @@ -105,7 +105,7 @@ export function apply(terminalConstructor) { * @param {WebSocket} socket - The socket from which to detach the current * terminal. */ - terminalConstructor.prototype.terminadoDetach = function(socket) { + terminalConstructor.prototype.terminadoDetach = function(socket: WebSocket): void { return terminadoDetach(this, socket); }; } diff --git a/src/addons/winptyCompat/winptyCompat.test.ts b/src/addons/winptyCompat/winptyCompat.test.ts index 21e54e56..73761fc9 100644 --- a/src/addons/winptyCompat/winptyCompat.test.ts +++ b/src/addons/winptyCompat/winptyCompat.test.ts @@ -5,7 +5,7 @@ import { assert, expect } from 'chai'; -import * as winptyCompat from './winptyCompat' +import * as winptyCompat from './winptyCompat'; class MockTerminal {} diff --git a/src/addons/winptyCompat/winptyCompat.ts b/src/addons/winptyCompat/winptyCompat.ts index 723bf011..b594355b 100644 --- a/src/addons/winptyCompat/winptyCompat.ts +++ b/src/addons/winptyCompat/winptyCompat.ts @@ -3,7 +3,7 @@ * @license MIT */ -export function winptyCompatInit(terminal): void { +export function winptyCompatInit(terminal: any): void { // Don't do anything when the platform is not Windows const isWindows = ['Windows', 'Win16', 'Win32', 'WinCE'].indexOf(navigator.platform) >= 0; if (!isWindows) { @@ -31,7 +31,7 @@ export function winptyCompatInit(terminal): void { }); } -export function apply(terminalConstructor) { +export function apply(terminalConstructor: any): void { terminalConstructor.prototype.winptyCompatInit = function(): void { winptyCompatInit(this); }; diff --git a/src/addons/zmodem/zmodem.test.ts b/src/addons/zmodem/zmodem.test.ts index 3cb28316..7646b7cc 100644 --- a/src/addons/zmodem/zmodem.test.ts +++ b/src/addons/zmodem/zmodem.test.ts @@ -5,7 +5,7 @@ import { assert, expect } from 'chai'; -import * as zmodem from './zmodem' +import * as zmodem from './zmodem'; class MockTerminal {} diff --git a/src/addons/zmodem/zmodem.ts b/src/addons/zmodem/zmodem.ts index 57bdde3c..f1e6050f 100644 --- a/src/addons/zmodem/zmodem.ts +++ b/src/addons/zmodem/zmodem.ts @@ -29,45 +29,38 @@ let Zmodem; -export function zmodemAttach(term, ws, opts) { - if (!opts) opts = {}; +export interface IZModemOptions { + noTerminalWriteOutsideSession?: boolean; +} - var senderFunc = function _ws_sender_func(octets) { - ws.send(new Uint8Array(octets)); - }; +export function zmodemAttach(term: any, ws: WebSocket, opts: IZModemOptions = {}): void { + const senderFunc = (octets: ArrayLike) => ws.send(new Uint8Array(octets)); - var zsentry; + let zsentry; - function _shouldWrite() { + function _shouldWrite(): boolean { return !!zsentry.get_confirmed_session() || !opts.noTerminalWriteOutsideSession; } - zsentry = new Zmodem.Sentry( { - to_terminal: function _to_terminal(octets) { + zsentry = new Zmodem.Sentry({ + to_terminal: (octets: ArrayLike) => { if (_shouldWrite()) { term.write( String.fromCharCode.apply(String, octets) ); } }, - sender: senderFunc, + on_retract: () => term.emit('zmodemRetract'), + on_detect: (detection: any) => term.emit('zmodemDetect', detection) + }); - on_retract: function _on_retract() { - term.emit('zmodemRetract'); - }, + function handleWSMessage(evt: MessageEvent): void { - on_detect: function _on_detect(detection) { - term.emit('zmodemDetect', detection); - }, - } ); - - function handleWSMessage(evt) { - - //In testing with xterm.js’s demo the first message was - //always text even if the rest were binary. While that - //may be specific to xterm.js’s demo, ultimately we - //should reject anything that isn’t binary. + // In testing with xterm.js’s demo the first message was + // always text even if the rest were binary. While that + // may be specific to xterm.js’s demo, ultimately we + // should reject anything that isn’t binary. if (typeof evt.data === 'string') { if (_shouldWrite()) { term.write(evt.data); @@ -82,9 +75,9 @@ export function zmodemAttach(term, ws, opts) { ws.addEventListener('message', handleWSMessage); } -export function apply(terminalConstructor) { - Zmodem = (typeof window == 'object') ? (window).ZModem : {Browser: null}; // Nullify browser for tests +export function apply(terminalConstructor: any): void { + Zmodem = (typeof window === 'object') ? (window).ZModem : {Browser: null}; // Nullify browser for tests terminalConstructor.prototype.zmodemAttach = zmodemAttach.bind(this, this); - terminalConstructor.prototype.zmodemBrowser = Zmodem.Browser + terminalConstructor.prototype.zmodemBrowser = Zmodem.Browser; } From 53e1f83bb55cc5f2fbada8f3f123bae09e448ea5 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 17 Jan 2018 10:23:27 -0800 Subject: [PATCH 13/19] Update tslint, fix lint --- package-lock.json | 1010 +++++++-------------------- package.json | 2 +- src/CompositionHelper.ts | 4 +- src/EscapeSequences.ts | 2 +- src/Interfaces.ts | 2 +- src/Terminal.ts | 4 +- src/Types.ts | 2 +- src/Viewport.ts | 6 +- src/addons/attach/attach.ts | 6 +- src/addons/fit/fit.ts | 2 +- src/addons/fullscreen/fullscreen.ts | 2 +- src/addons/search/search.ts | 4 +- src/addons/terminado/terminado.ts | 4 +- src/input/MouseZoneManager.ts | 2 +- src/renderer/TextRenderLayer.ts | 6 +- src/renderer/Types.ts | 2 +- src/utils/Generic.ts | 2 +- 17 files changed, 277 insertions(+), 785 deletions(-) diff --git a/package-lock.json b/package-lock.json index c83a4d9a..f7c01276 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "xterm", - "version": "2.9.1", + "version": "3.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -56,6 +56,16 @@ "integrity": "sha512-bJgf+gJF+zohYkhOOdY7cXVKa0jMZGICqIcdPRb1SFyPHI4sKau0tXTRLmT2T4S5bjx6cY9AuoMkB5v+TIL4wA==", "dev": true }, + "JSONStream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.1.tgz", + "integrity": "sha1-cH92HgHa6eFvG8+TcDt4xwlmV5o=", + "dev": true, + "requires": { + "jsonparse": "1.3.1", + "through": "2.3.8" + } + }, "abab": { "version": "https://registry.npmjs.org/abab/-/abab-1.0.3.tgz", "integrity": "sha1-uB3l9ydOxOdW15fNg08wNkJyTl0=", @@ -98,6 +108,15 @@ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, "array-differ": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", @@ -199,6 +218,86 @@ "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", "dev": true }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, "base64-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", @@ -234,6 +333,16 @@ "hoek": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" } }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, "brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", @@ -246,9 +355,9 @@ "integrity": "sha1-+GzWzvT1MAyOY+B6TVEvZfv/RTE=", "dev": true, "requires": { + "JSONStream": "1.3.1", "combine-source-map": "0.7.2", "defined": "1.0.0", - "JSONStream": "1.3.1", "through2": "2.0.3", "umd": "3.0.1" } @@ -276,6 +385,7 @@ "integrity": "sha1-tanJAgJD8McORnW+yCI7xifkFc4=", "dev": true, "requires": { + "JSONStream": "1.3.1", "assert": "1.4.1", "browser-pack": "6.0.2", "browser-resolve": "1.11.2", @@ -297,7 +407,6 @@ "https-browserify": "0.0.1", "inherits": "2.0.3", "insert-module-globals": "7.0.1", - "JSONStream": "1.3.1", "labeled-stream-splicer": "2.0.0", "module-deps": "4.1.1", "os-browserify": "0.1.2", @@ -474,6 +583,12 @@ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, "builtin-status-codes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", @@ -584,6 +699,21 @@ "through2": "2.0.3" } }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, "combine-source-map": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.7.2.tgz", @@ -610,6 +740,12 @@ "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", "dev": true }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, "concat-stream": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", @@ -740,43 +876,6 @@ "sha.js": "2.4.8" } }, - "cross-spawn-async": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz", - "integrity": "sha1-hF/wwINKPe2dFg2sptOQkGuyiMw=", - "dev": true, - "requires": { - "lru-cache": "4.1.1", - "which": "1.2.14" - }, - "dependencies": { - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "lru-cache": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", - "dev": true, - "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" - } - }, - "which": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", - "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", - "dev": true, - "requires": { - "isexe": "2.0.0" - } - } - } - }, "cryptiles": { "version": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", @@ -803,12 +902,6 @@ "randombytes": "2.0.5" } }, - "crypto-random-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", - "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", - "dev": true - }, "cssom": { "version": "https://registry.npmjs.org/cssom/-/cssom-0.3.2.tgz", "integrity": "sha1-uANhcMefB6kP8vFuIihAJ6JDhIs=", @@ -897,6 +990,12 @@ "defined": "1.0.0" } }, + "diff": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", + "integrity": "sha512-QpVuMTEoJMF7cKzi6bvWhRulU1fZqZnvyVQgNhPaxxuTYwyjn/j1v9falseQ/uXWwPnO56RBfwtg4h/EQXmucA==", + "dev": true + }, "diffie-hellman": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", @@ -929,12 +1028,6 @@ "readable-stream": "1.1.14" } }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, "each-props": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.0.tgz", @@ -1035,34 +1128,6 @@ "create-hash": "1.1.3" } }, - "execa": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.4.0.tgz", - "integrity": "sha1-TrZGejaglfq7KXD/nV4/t7zm68M=", - "dev": true, - "requires": { - "cross-spawn-async": "2.2.5", - "is-stream": "1.1.0", - "npm-run-path": "1.0.0", - "object-assign": "4.1.1", - "path-key": "1.0.0", - "strip-eof": "1.0.0" - }, - "dependencies": { - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - } - } - }, "exit-on-epipe": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", @@ -1596,12 +1661,6 @@ "is-property": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz" } }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, "getpass": { "version": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz", "integrity": "sha1-KD/9n8ElaECHUxHBtg6MQBhxEOY=", @@ -8461,6 +8520,12 @@ "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" } }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, "has-gulplog": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", @@ -8589,12 +8654,6 @@ "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", "dev": true }, - "import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", - "dev": true - }, "indexof": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", @@ -8622,10 +8681,10 @@ "integrity": "sha1-wDv04BywhtW15azorQr+eInWOMM=", "dev": true, "requires": { + "JSONStream": "1.3.1", "combine-source-map": "0.7.2", "concat-stream": "1.5.2", "is-buffer": "1.1.5", - "JSONStream": "1.3.1", "lexical-scope": "1.2.0", "process": "0.11.10", "through2": "2.0.3", @@ -8704,6 +8763,30 @@ "jsbn": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz" } }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + } + } + }, "jsbn": { "version": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", @@ -8972,16 +9055,6 @@ "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", "dev": true }, - "JSONStream": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.1.tgz", - "integrity": "sha1-cH92HgHa6eFvG8+TcDt4xwlmV5o=", - "dev": true, - "requires": { - "jsonparse": "1.3.1", - "through": "2.3.8" - } - }, "jsprim": { "version": "https://registry.npmjs.org/jsprim/-/jsprim-1.3.1.tgz", "integrity": "sha1-KnJW9wQSop7jZwqspiWZTE3P8lI=", @@ -9151,15 +9224,6 @@ "lodash.escape": "3.2.0" } }, - "make-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.0.0.tgz", - "integrity": "sha1-l6ARdR6R3YfPre9Ygy67BJNt6Xg=", - "dev": true, - "requires": { - "pify": "2.3.0" - } - }, "merge-stream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", @@ -9260,6 +9324,15 @@ "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", "dev": true }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", @@ -9539,6 +9612,7 @@ "integrity": "sha1-IyFYM/HaE/1gbMuAh7RIUty4If0=", "dev": true, "requires": { + "JSONStream": "1.3.1", "browser-resolve": "1.11.2", "cached-path-relative": "1.0.1", "concat-stream": "1.5.2", @@ -9546,7 +9620,6 @@ "detective": "4.5.0", "duplexer2": "0.1.4", "inherits": "2.0.3", - "JSONStream": "1.3.1", "parents": "1.0.1", "readable-stream": "2.3.3", "resolve": "1.4.0", @@ -10660,15 +10733,6 @@ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", "dev": true }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, "string-length": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/string-length/-/string-length-1.0.1.tgz", @@ -10678,6 +10742,15 @@ "strip-ansi": "3.0.1" } }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", @@ -10781,15 +10854,6 @@ } } }, - "npm-run-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz", - "integrity": "sha1-9cMr9ZX+ga6Sfa7FLoL4sACsPI8=", - "dev": true, - "requires": { - "path-key": "1.0.0" - } - }, "oauth-sign": { "version": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", @@ -10922,12 +10986,6 @@ "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", "dev": true }, - "path-key": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", - "integrity": "sha1-XVPVeAGWRsDWiADbThRua9wqx68=", - "dev": true - }, "path-parse": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", @@ -10953,12 +11011,6 @@ "sha.js": "2.4.8" } }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, "pinkie": { "version": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", @@ -11001,12 +11053,6 @@ "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", "dev": true }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, "public-encrypt": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", @@ -11208,6 +11254,12 @@ "integrity": "sha1-/YYxojvHgmvvXYcb24c3jJVkeCg=", "dev": true }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, "sha.js": { "version": "2.4.8", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.8.tgz", @@ -11350,6 +11402,12 @@ "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", "dev": true }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, "sshpk": { "version": "https://registry.npmjs.org/sshpk/-/sshpk-1.10.2.tgz", "integrity": "sha1-1agEziJpVRVjjnmNviMnPeBwpfo=", @@ -11584,12 +11642,6 @@ "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" } }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, "subarg": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", @@ -11618,15 +11670,6 @@ "acorn": "4.0.13" } }, - "term-size": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-0.1.1.tgz", - "integrity": "sha1-hzYLljlsq1dgljcUzaDQy+7K2co=", - "dev": true, - "requires": { - "execa": "0.4.0" - } - }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -11715,619 +11758,83 @@ "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", "dev": true }, + "tslib": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.8.1.tgz", + "integrity": "sha1-aUavLR1lGnsYY7Ux1uWvpBqkTqw=", + "dev": true + }, "tslint": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-4.5.1.tgz", - "integrity": "sha1-BTVocb7yOkNJBnNABvwYgza6gks=", + "version": "5.9.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.9.1.tgz", + "integrity": "sha1-ElX4ej/1frCw4fDmEKi0dIBGya4=", "dev": true, "requires": { - "babel-code-frame": "6.22.0", - "colors": "1.1.2", - "diff": "3.3.0", - "findup-sync": "0.3.0", + "babel-code-frame": "6.26.0", + "builtin-modules": "1.1.1", + "chalk": "2.3.0", + "commander": "2.13.0", + "diff": "3.4.0", "glob": "7.1.2", - "optimist": "0.6.1", - "resolve": "1.3.3", - "tsutils": "1.9.1", - "update-notifier": "2.2.0" + "js-yaml": "3.10.0", + "minimatch": "3.0.4", + "resolve": "1.4.0", + "semver": "5.5.0", + "tslib": "1.8.1", + "tsutils": "2.19.0" }, "dependencies": { - "ansi-align": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", - "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", - "dev": true, - "requires": { - "string-width": "2.1.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "babel-code-frame": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", - "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", "dev": true, "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" + "color-convert": "1.9.1" } }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "boxen": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.1.0.tgz", - "integrity": "sha1-sbad1SIwXoB6md7ud329blFnsQI=", - "dev": true, - "requires": { - "ansi-align": "2.0.0", - "camelcase": "4.1.0", - "chalk": "1.1.3", - "cli-boxes": "1.0.0", - "string-width": "2.1.0", - "term-size": "0.1.1", - "widest-line": "1.0.0" - } - }, - "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "dev": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "capture-stack-trace": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", - "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=", - "dev": true - }, "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", "dev": true, "requires": { - "ansi-styles": "2.2.1", + "ansi-styles": "3.2.0", "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "supports-color": "4.5.0" } }, - "cli-boxes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", - "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", + "commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", "dev": true }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "configstore": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.0.tgz", - "integrity": "sha1-Rd+QcHPibfoc9LLVL1tgVF6qEdE=", - "dev": true, - "requires": { - "dot-prop": "4.1.1", - "graceful-fs": "4.1.11", - "make-dir": "1.0.0", - "unique-string": "1.0.0", - "write-file-atomic": "2.1.0", - "xdg-basedir": "3.0.0" - } - }, - "create-error-class": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", - "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", - "dev": true, - "requires": { - "capture-stack-trace": "1.0.0" - } - }, - "deep-extend": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", - "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", - "dev": true - }, - "diff": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.0.tgz", - "integrity": "sha512-w0XZubFWn0Adlsapj9EAWX0FqWdO4tz8kc3RiYdWLh4k/V8PTb6i0SMgXt0vRM3zyKnT8tKO7mUlieRQHIjMNg==", - "dev": true - }, - "dot-prop": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.1.1.tgz", - "integrity": "sha1-qEk/C3te7sglJbXHWH+n3nyoWcE=", - "dev": true, - "requires": { - "is-obj": "1.0.1" - } - }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "findup-sync": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", - "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", - "dev": true, - "requires": { - "glob": "5.0.15" - }, - "dependencies": { - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - } - } - }, - "got": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", - "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", - "dev": true, - "requires": { - "create-error-class": "3.0.2", - "duplexer3": "0.1.4", - "get-stream": "3.0.0", - "is-redirect": "1.0.0", - "is-retry-allowed": "1.1.0", - "is-stream": "1.1.0", - "lowercase-keys": "1.0.0", - "safe-buffer": "5.1.1", - "timed-out": "4.0.1", - "unzip-response": "2.0.1", - "url-parse-lax": "1.0.0" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "ini": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", - "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "is-npm": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", - "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", - "dev": true - }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, - "is-redirect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", - "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", - "dev": true - }, - "is-retry-allowed": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "latest-version": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", - "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", - "dev": true, - "requires": { - "package-json": "4.0.1" - } - }, - "lowercase-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", - "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "1.1.8" - } - }, - "minimist": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", - "dev": true - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "0.0.10", - "wordwrap": "0.0.3" - } - }, - "package-json": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", - "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", - "dev": true, - "requires": { - "got": "6.7.1", - "registry-auth-token": "3.3.1", - "registry-url": "3.1.0", - "semver": "5.3.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true - }, - "rc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", - "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", - "dev": true, - "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.4", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "registry-auth-token": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.1.tgz", - "integrity": "sha1-+w0yie4Nmtosu1KvXf5mywcNMAY=", - "dev": true, - "requires": { - "rc": "1.2.1", - "safe-buffer": "5.1.1" - } - }, - "registry-url": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", - "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", - "dev": true, - "requires": { - "rc": "1.2.1" - } - }, - "resolve": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.3.3.tgz", - "integrity": "sha1-ZVkHw0aahoDcLeOidaj91paR8OU=", - "dev": true, - "requires": { - "path-parse": "1.0.5" - } - }, - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "dev": true - }, - "semver-diff": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", - "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", - "dev": true, - "requires": { - "semver": "5.3.0" - } - }, - "slide": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", - "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", - "dev": true - }, - "string-width": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.0.tgz", - "integrity": "sha1-AwZkVh/BRslCPsfZeP4kV0N/5tA=", - "dev": true, - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", - "dev": true - }, - "unzip-response": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", - "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", - "dev": true - }, - "update-notifier": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.2.0.tgz", - "integrity": "sha1-G1g3z5DAc22IYncytmHBOPht5y8=", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", "dev": true, "requires": { - "boxen": "1.1.0", - "chalk": "1.1.3", - "configstore": "3.1.0", - "import-lazy": "2.1.0", - "is-npm": "1.0.0", - "latest-version": "3.1.0", - "semver-diff": "2.1.0", - "xdg-basedir": "3.0.0" + "has-flag": "2.0.0" } - }, - "url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "dev": true, - "requires": { - "prepend-http": "1.0.4" - } - }, - "widest-line": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-1.0.0.tgz", - "integrity": "sha1-DAnIXCqUaD0Nfq+O4JfVZL8OEFw=", - "dev": true, - "requires": { - "string-width": "1.0.2" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - } - } - }, - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write-file-atomic": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.1.0.tgz", - "integrity": "sha512-0TZ20a+xcIl4u0+Mj5xDH2yOWdmQiXlKf9Hm+TgDXjTMsEYb+gDrmb8e8UNAzMCitX8NBqG4Z/FUQIyzv/R1JQ==", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "imurmurhash": "0.1.4", - "slide": "1.1.6" - } - }, - "xdg-basedir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", - "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", - "dev": true } } }, "tsutils": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-1.9.1.tgz", - "integrity": "sha1-ufmrROVa+WgYMdXyjQrur1x1DLA=", - "dev": true + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.19.0.tgz", + "integrity": "sha512-qjgvrvtzRUtOmqlZTfBFtep6s+ymuBLsHOC4ee9JNA+AZIbnR/x4C2Y7QFhOGpD2R3lDp0BBcnxb0vnMVrU7Aw==", + "dev": true, + "requires": { + "tslib": "1.8.1" + } }, "tty-browserify": { "version": "0.0.0", @@ -12372,15 +11879,6 @@ "integrity": "sha1-iuVW4RAR9jwllnCKiDclnwGz1g4=", "dev": true }, - "unique-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", - "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", - "dev": true, - "requires": { - "crypto-random-string": "1.0.0" - } - }, "url": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", @@ -12632,12 +12130,6 @@ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, "zmodem.js": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/zmodem.js/-/zmodem.js-0.1.6.tgz", diff --git a/package.json b/package.json index 1dfadf9f..6b1eb230 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "node-pty": "^0.7.2", "nodemon": "1.10.2", "sorcery": "^0.10.0", - "tslint": "^4.0.2", + "tslint": "^5.9.1", "typescript": "~2.4.0", "vinyl-buffer": "^1.0.0", "vinyl-source-stream": "^1.1.0", diff --git a/src/CompositionHelper.ts b/src/CompositionHelper.ts index ca5b4f4b..e588be78 100644 --- a/src/CompositionHelper.ts +++ b/src/CompositionHelper.ts @@ -217,7 +217,7 @@ export class CompositionHelper { if (!dontRecurse) { setTimeout(() => this.updateCompositionElements(true), 0); } - }; + } /** * Clears the textarea's position so that the cursor does not blink on IE. @@ -226,5 +226,5 @@ export class CompositionHelper { private clearTextareaPosition(): void { this.textarea.style.left = ''; this.textarea.style.top = ''; - }; + } } diff --git a/src/EscapeSequences.ts b/src/EscapeSequences.ts index cb97c368..11cbd84e 100644 --- a/src/EscapeSequences.ts +++ b/src/EscapeSequences.ts @@ -76,4 +76,4 @@ export namespace C0 { export const SP = '\x20'; /** Delete (Caret = ^?) */ export const DEL = '\x7f'; -}; +} diff --git a/src/Interfaces.ts b/src/Interfaces.ts index f90cb8c0..e209c4dc 100644 --- a/src/Interfaces.ts +++ b/src/Interfaces.ts @@ -248,7 +248,7 @@ export interface IEventEmitter { export interface IListenerType { (data?: any): void; listener?: (data?: any) => void; -}; +} export interface ILinkMatcherOptions { /** diff --git a/src/Terminal.ts b/src/Terminal.ts index f95cc0ea..1a1694f4 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -443,7 +443,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT this.element.classList.add('focus'); this.showCursor(); this.emit('focus'); - }; + } /** * Blur the terminal, calling the blur function on the terminal's underlying @@ -2220,7 +2220,7 @@ function matchColorDistance(r1: number, g1: number, b1: number, r2: number, g2: return Math.pow(30 * (r1 - r2), 2) + Math.pow(59 * (g1 - g2), 2) + Math.pow(11 * (b1 - b2), 2); -}; +} function matchColor_(r1: number, g1: number, b1: number): number { diff --git a/src/Types.ts b/src/Types.ts index a0c03fdd..4a2b99ed 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -32,4 +32,4 @@ export enum LinkHoverEventTypes { HOVER = 'linkhover', TOOLTIP = 'linktooltip', LEAVE = 'linkleave' -}; +} diff --git a/src/Viewport.ts b/src/Viewport.ts index 1ea7fa0b..fcac68ad 100644 --- a/src/Viewport.ts +++ b/src/Viewport.ts @@ -119,7 +119,7 @@ export class Viewport implements IViewport { this.viewportElement.scrollTop += ev.deltaY * multiplier; // Prevent the page from scrolling when the terminal scrolls ev.preventDefault(); - }; + } /** * Handles the touchstart event, recording the touch occurred. @@ -127,7 +127,7 @@ export class Viewport implements IViewport { */ public onTouchStart(ev: TouchEvent): void { this.lastTouchY = ev.touches[0].pageY; - }; + } /** * Handles the touchmove event, scrolling the viewport if the position shifted. @@ -141,5 +141,5 @@ export class Viewport implements IViewport { } this.viewportElement.scrollTop += deltaY; ev.preventDefault(); - }; + } } diff --git a/src/addons/attach/attach.ts b/src/addons/attach/attach.ts index 349a03dd..21645c8a 100644 --- a/src/addons/attach/attach.ts +++ b/src/addons/attach/attach.ts @@ -72,7 +72,7 @@ export function attach(term: any, socket: WebSocket, bidirectional: boolean, buf socket.addEventListener('close', term.detach.bind(term, socket)); socket.addEventListener('error', term.detach.bind(term, socket)); -}; +} /** * Detaches the given terminal from the given socket @@ -91,7 +91,7 @@ export function detach(term: any, socket: WebSocket): void { } delete term.socket; -}; +} export function apply(terminalConstructor: any): void { @@ -118,4 +118,4 @@ export function apply(terminalConstructor: any): void { terminalConstructor.prototype.detach = (socket: WebSocket) => { return detach(this, socket); }; -}; +} diff --git a/src/addons/fit/fit.ts b/src/addons/fit/fit.ts index f037b540..63111094 100644 --- a/src/addons/fit/fit.ts +++ b/src/addons/fit/fit.ts @@ -47,7 +47,7 @@ export function fit(term: any): void { term.resize(geometry.cols, geometry.rows); } } -}; +} export function apply(terminalConstructor: any): void { terminalConstructor.prototype.proposeGeometry = function (): IGeometry { diff --git a/src/addons/fullscreen/fullscreen.ts b/src/addons/fullscreen/fullscreen.ts index 0eb61ea1..2e5b72e1 100644 --- a/src/addons/fullscreen/fullscreen.ts +++ b/src/addons/fullscreen/fullscreen.ts @@ -20,7 +20,7 @@ export function toggleFullScreen(term: any, fullscreen: boolean): void { } term.element.classList[fn]('fullscreen'); -}; +} export function apply(terminalConstructor: any): void { terminalConstructor.prototype.toggleFullScreen = function (fullscreen: boolean): void { diff --git a/src/addons/search/search.ts b/src/addons/search/search.ts index 375b86f4..473c78fc 100644 --- a/src/addons/search/search.ts +++ b/src/addons/search/search.ts @@ -17,7 +17,7 @@ export function findNext(terminal: any, term: string): boolean { terminal.searchHelper = new SearchHelper(terminal); } return (terminal.searchHelper).findNext(term); -}; +} /** * Find the previous instance of the term, then scroll to and select it. If it @@ -30,7 +30,7 @@ export function findPrevious(terminal: any, term: string): boolean { terminal.searchHelper = new SearchHelper(terminal); } return (terminal.searchHelper).findPrevious(term); -}; +} export function apply(terminalConstructor: any): void { terminalConstructor.prototype.findNext = function(term: any): boolean { diff --git a/src/addons/terminado/terminado.ts b/src/addons/terminado/terminado.ts index afd7277c..e703198f 100644 --- a/src/addons/terminado/terminado.ts +++ b/src/addons/terminado/terminado.ts @@ -63,7 +63,7 @@ export function terminadoAttach(term: any, socket: WebSocket, bidirectional: boo socket.addEventListener('close', term.terminadoDetach.bind(term, socket)); socket.addEventListener('error', term.terminadoDetach.bind(term, socket)); -}; +} /** * Detaches the given terminal from the given socket @@ -82,7 +82,7 @@ export function terminadoDetach(term: any, socket: WebSocket): void { } delete term.socket; -}; +} export function apply(terminalConstructor: any): void { /** diff --git a/src/input/MouseZoneManager.ts b/src/input/MouseZoneManager.ts index 8fae3171..6fbe1c67 100644 --- a/src/input/MouseZoneManager.ts +++ b/src/input/MouseZoneManager.ts @@ -178,7 +178,7 @@ export class MouseZoneManager implements IMouseZoneManager { if (zone.y === coords[1] && zone.x1 <= coords[0] && zone.x2 > coords[0]) { return zone; } - }; + } return null; } } diff --git a/src/renderer/TextRenderLayer.ts b/src/renderer/TextRenderLayer.ts index 2ecb6ec6..99a6feae 100644 --- a/src/renderer/TextRenderLayer.ts +++ b/src/renderer/TextRenderLayer.ts @@ -192,9 +192,9 @@ export class TextRenderLayer extends BaseRenderLayer { } } - /** - * Whether a character is overlapping to the next cell. - */ + /** + * Whether a character is overlapping to the next cell. + */ private _isOverlapping(charData: CharData): boolean { // Only single cell characters can be overlapping, rendering issues can // occur without this check diff --git a/src/renderer/Types.ts b/src/renderer/Types.ts index 31705a3f..834f8813 100644 --- a/src/renderer/Types.ts +++ b/src/renderer/Types.ts @@ -13,4 +13,4 @@ export enum FLAGS { INVERSE = 8, INVISIBLE = 16, DIM = 32 -}; +} diff --git a/src/utils/Generic.ts b/src/utils/Generic.ts index 82373617..4bc6c487 100644 --- a/src/utils/Generic.ts +++ b/src/utils/Generic.ts @@ -10,4 +10,4 @@ */ export function contains(arr: any[], el: any): boolean { return arr.indexOf(el) >= 0; -}; +} From 307dd0fd6874f4951b677ab94b131c9a00ba987b Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 17 Jan 2018 10:32:35 -0800 Subject: [PATCH 14/19] Add several tslint rules --- src/InputHandler.ts | 14 +++++++------- src/SelectionModel.test.ts | 2 +- src/Terminal.integration.ts | 36 ++++++++++++++++++------------------ src/Terminal.ts | 8 ++++---- src/addons/zmodem/zmodem.ts | 8 ++++---- src/utils/Sounds.ts | 2 +- tslint.json | 19 +++++++++++++------ 7 files changed, 48 insertions(+), 41 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 1ba6dc7a..7d3a4d24 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -26,7 +26,7 @@ export class InputHandler implements IInputHandler { if (char >= ' ') { // calculate print space // expensive call, therefore we save width in line buffer - const ch_width = wcwidth(code); + const chWidth = wcwidth(code); if (this._terminal.charset && this._terminal.charset[char]) { char = this._terminal.charset[char]; @@ -36,7 +36,7 @@ export class InputHandler implements IInputHandler { // insert combining char in last cell // FIXME: needs handling after cursor jumps - if (!ch_width && this._terminal.buffer.x) { + if (!chWidth && this._terminal.buffer.x) { // dont overflow left if (this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1]) { if (!this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][CHAR_DATA_WIDTH_INDEX]) { @@ -56,7 +56,7 @@ export class InputHandler implements IInputHandler { // goto next line if ch would overflow // TODO: needs a global min terminal width of 2 - if (this._terminal.buffer.x + ch_width - 1 >= this._terminal.cols) { + if (this._terminal.buffer.x + chWidth - 1 >= this._terminal.cols) { // autowrap - DECAWM if (this._terminal.wraparoundMode) { this._terminal.buffer.x = 0; @@ -70,7 +70,7 @@ export class InputHandler implements IInputHandler { (this._terminal.buffer.lines.get(this._terminal.buffer.y)).isWrapped = true; } } else { - if (ch_width === 2) // FIXME: check for xterm behavior + if (chWidth === 2) // FIXME: check for xterm behavior return; } } @@ -79,7 +79,7 @@ export class InputHandler implements IInputHandler { // insert mode: move characters to right if (this._terminal.insertMode) { // do this twice for a fullwidth char - for (let moves = 0; moves < ch_width; ++moves) { + for (let moves = 0; moves < chWidth; ++moves) { // remove last cell, if it's width is 0 // we have to adjust the second last cell as well const removed = this._terminal.buffer.lines.get(this._terminal.buffer.y + this._terminal.buffer.ybase).pop(); @@ -94,12 +94,12 @@ export class InputHandler implements IInputHandler { } } - this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, char, ch_width, char.charCodeAt(0)]; + this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, char, chWidth, char.charCodeAt(0)]; this._terminal.buffer.x++; this._terminal.updateRange(this._terminal.buffer.y); // fullwidth char - set next cell width to zero and advance cursor - if (ch_width === 2) { + if (chWidth === 2) { this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, '', 0, undefined]; this._terminal.buffer.x++; } diff --git a/src/SelectionModel.test.ts b/src/SelectionModel.test.ts index e195d6bd..eda94718 100644 --- a/src/SelectionModel.test.ts +++ b/src/SelectionModel.test.ts @@ -6,7 +6,7 @@ import { assert } from 'chai'; import { ITerminal } from './Interfaces'; import { SelectionModel } from './SelectionModel'; -import {BufferSet} from './BufferSet'; +import { BufferSet } from './BufferSet'; import { MockTerminal } from './utils/TestUtils.test'; class TestSelectionModel extends SelectionModel { diff --git a/src/Terminal.integration.ts b/src/Terminal.integration.ts index 00db4dd6..283c5bc0 100644 --- a/src/Terminal.integration.ts +++ b/src/Terminal.integration.ts @@ -15,17 +15,17 @@ import { assert } from 'chai'; import { Terminal } from './Terminal'; import { CHAR_DATA_CHAR_INDEX } from './Buffer'; -let primitive_pty: any; +let primitivePty: any; // fake sychronous pty write - read // we just pipe the data from slave to master as a child program would do // pty.js opens pipe fds with O_NONBLOCK // just wait 10ms instead of setting fds to blocking mode function ptyWriteRead(data: string, cb: (result: string) => void): void { - fs.writeSync(primitive_pty.slave, data); + fs.writeSync(primitivePty.slave, data); setTimeout(() => { let b = new Buffer(64000); - let bytes = fs.readSync(primitive_pty.master, b, 0, 64000, null); + let bytes = fs.readSync(primitivePty.master, b, 0, 64000, null); cb(b.toString('utf8', 0, bytes)); }); } @@ -37,7 +37,7 @@ function ptyReset(cb: (result: string) => void): void { /* debug helpers */ // generate colorful noisy output to compare xterm and emulator cell states -function formatError(in_: string, out_: string, expected: string): string { +function formatError(input: string, output: string, expected: string): string { function addLineNumber(start: number, color: string): (s: string) => string { let counter = start || 0; return function(s: string): string { @@ -47,9 +47,9 @@ function formatError(in_: string, out_: string, expected: string): string { } let line80 = '12345678901234567890123456789012345678901234567890123456789012345678901234567890'; let s = ''; - s += '\n\x1b[34m' + JSON.stringify(in_); + s += '\n\x1b[34m' + JSON.stringify(input); s += '\n\x1b[33m ' + line80 + '\n'; - s += out_.split('\n').map(addLineNumber(0, '\x1b[31m')).join('\n'); + s += output.split('\n').map(addLineNumber(0, '\x1b[31m')).join('\n'); s += '\n\x1b[33m ' + line80 + '\n'; s += expected.split('\n').map(addLineNumber(0, '\x1b[32m')).join('\n'); return s; @@ -58,15 +58,15 @@ function formatError(in_: string, out_: string, expected: string): string { // simple debug output of terminal cells function terminalToString(term: Terminal): string { let result = ''; - let line_s = ''; + let lineText = ''; for (let line = term.buffer.ybase; line < term.buffer.ybase + term.rows; line++) { - line_s = ''; + lineText = ''; for (let cell = 0; cell < term.cols; ++cell) { - line_s += term.buffer.lines.get(line)[cell][CHAR_DATA_CHAR_INDEX]; + lineText += term.buffer.lines.get(line)[cell][CHAR_DATA_CHAR_INDEX]; } // rtrim empty cells as xterm does - line_s = line_s.replace(/\s+$/, ''); - result += line_s; + lineText = lineText.replace(/\s+$/, ''); + result += lineText; result += '\n'; } return result; @@ -83,7 +83,7 @@ if (os.platform() !== 'win32') { /** some helpers for pty interaction */ // we need a pty in between to get the termios decorations // for the basic test cases a raw pty device is enough - primitive_pty = pty.native.open(COLS, ROWS); + primitivePty = pty.native.open(COLS, ROWS); /** tests */ describe('xterm output comparison', () => { @@ -118,24 +118,24 @@ if (os.platform() !== 'win32') { ((filename: string) => { it(filename.split('/').slice(-1)[0], done => { ptyReset(() => { - let in_file = fs.readFileSync(filename, 'utf8'); - ptyWriteRead(in_file, from_pty => { + let inFile = fs.readFileSync(filename, 'utf8'); + ptyWriteRead(inFile, fromPty => { // uncomment this to get log from terminal // console.log = function(){}; // Perform a synchronous .write(data) - xterm.writeBuffer.push(from_pty); + xterm.writeBuffer.push(fromPty); xterm.innerWrite(); - let from_emulator = terminalToString(xterm); + let fromEmulator = terminalToString(xterm); console.log = CONSOLE_LOG; let expected = fs.readFileSync(filename.split('.')[0] + '.text', 'utf8'); // Some of the tests have whitespace on the right of lines, we trim all the linex // from xterm.js so ignore this for now at least. let expectedRightTrimmed = expected.split('\n').map(l => l.replace(/\s+$/, '')).join('\n'); - if (from_emulator !== expectedRightTrimmed) { + if (fromEmulator !== expectedRightTrimmed) { // uncomment to get noisy output - throw new Error(formatError(in_file, from_emulator, expected)); + throw new Error(formatError(inFile, fromEmulator, expected)); // throw new Error('mismatch'); } done(); diff --git a/src/Terminal.ts b/src/Terminal.ts index 1a1694f4..8c0a3793 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -40,7 +40,7 @@ import { MouseHelper } from './utils/MouseHelper'; import { CHARSETS } from './Charsets'; import { CustomKeyEventHandler, Charset, LinkMatcherHandler, LinkMatcherValidationCallback, CharData, LineData } from './Types'; import { ITerminal, IBrowser, ITerminalOptions, IInputHandlingTerminal, ILinkMatcherOptions, IViewport, ICompositionHelper, ITheme, ILinkifier } from './Interfaces'; -import { BellSound } from './utils/Sounds'; +import { BELL_SOUND } from './utils/Sounds'; import { DEFAULT_ANSI_COLORS } from './renderer/ColorManager'; import { IMouseZoneManager } from './input/Interfaces'; import { MouseZoneManager } from './input/MouseZoneManager'; @@ -70,7 +70,7 @@ const DEFAULT_OPTIONS: ITerminalOptions = { termName: 'xterm', cursorBlink: false, cursorStyle: 'block', - bellSound: BellSound, + bellSound: BELL_SOUND, bellStyle: 'none', enableBold: true, fontFamily: 'courier-new, courier, monospace', @@ -181,7 +181,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT private writeStopped: boolean; // leftover surrogate high from previous write invocation - private surrogate_high: string; + private surrogateHigh: string; // Store if user went browsing history in scrollback private userScrolling: boolean; @@ -280,7 +280,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT this.xoffSentToCatchUp = false; this.writeStopped = false; - this.surrogate_high = ''; + this.surrogateHigh = ''; this.userScrolling = false; this.inputHandler = new InputHandler(this); diff --git a/src/addons/zmodem/zmodem.ts b/src/addons/zmodem/zmodem.ts index f1e6050f..4713f111 100644 --- a/src/addons/zmodem/zmodem.ts +++ b/src/addons/zmodem/zmodem.ts @@ -27,7 +27,7 @@ * via `detach()` and a re-`attach()`.) */ -let Zmodem; +let zmodem; export interface IZModemOptions { noTerminalWriteOutsideSession?: boolean; @@ -42,7 +42,7 @@ export function zmodemAttach(term: any, ws: WebSocket, opts: IZModemOptions = {} return !!zsentry.get_confirmed_session() || !opts.noTerminalWriteOutsideSession; } - zsentry = new Zmodem.Sentry({ + zsentry = new zmodem.Sentry({ to_terminal: (octets: ArrayLike) => { if (_shouldWrite()) { term.write( @@ -76,8 +76,8 @@ export function zmodemAttach(term: any, ws: WebSocket, opts: IZModemOptions = {} } export function apply(terminalConstructor: any): void { - Zmodem = (typeof window === 'object') ? (window).ZModem : {Browser: null}; // Nullify browser for tests + zmodem = (typeof window === 'object') ? (window).ZModem : {Browser: null}; // Nullify browser for tests terminalConstructor.prototype.zmodemAttach = zmodemAttach.bind(this, this); - terminalConstructor.prototype.zmodemBrowser = Zmodem.Browser; + terminalConstructor.prototype.zmodemBrowser = zmodem.Browser; } diff --git a/src/utils/Sounds.ts b/src/utils/Sounds.ts index 03f36f42..be26d4a5 100644 --- a/src/utils/Sounds.ts +++ b/src/utils/Sounds.ts @@ -7,4 +7,4 @@ // This sound is released under the Creative Commons Attribution 3.0 Unported // (CC BY 3.0) license. It was created by 'altemark'. No modifications have been // made, apart from the conversion to base64. -export const BellSound = 'data:audio/wav;base64,UklGRigBAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQQBAADpAFgCwAMlBZoG/wdmCcoKRAypDQ8PbRDBEQQTOxRtFYcWlBePGIUZXhoiG88bcBz7HHIdzh0WHlMeZx51HmkeUx4WHs8dah0AHXwc3hs9G4saxRnyGBIYGBcQFv8U4RPAEoYRQBACD70NWwwHC6gJOwjWBloF7gOBAhABkf8b/qv8R/ve+Xf4Ife79W/0JfPZ8Z/wde9N7ijtE+wU6xvqM+lb6H7nw+YX5mrlxuQz5Mzje+Ma49fioeKD4nXiYeJy4pHitOL04j/jn+MN5IPkFOWs5U3mDefM55/ogOl36m7rdOyE7abuyu8D8Unyj/Pg9D/2qfcb+Yn6/vuK/Qj/lAAlAg=='; +export const BELL_SOUND = 'data:audio/wav;base64,UklGRigBAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQQBAADpAFgCwAMlBZoG/wdmCcoKRAypDQ8PbRDBEQQTOxRtFYcWlBePGIUZXhoiG88bcBz7HHIdzh0WHlMeZx51HmkeUx4WHs8dah0AHXwc3hs9G4saxRnyGBIYGBcQFv8U4RPAEoYRQBACD70NWwwHC6gJOwjWBloF7gOBAhABkf8b/qv8R/ve+Xf4Ife79W/0JfPZ8Z/wde9N7ijtE+wU6xvqM+lb6H7nw+YX5mrlxuQz5Mzje+Ma49fioeKD4nXiYeJy4pHitOL04j/jn+MN5IPkFOWs5U3mDefM55/ogOl36m7rdOyE7abuyu8D8Unyj/Pg9D/2qfcb+Yn6/vuK/Qj/lAAlAg=='; diff --git a/tslint.json b/tslint.json index 4d4d4aa5..31c9ec84 100644 --- a/tslint.json +++ b/tslint.json @@ -1,5 +1,9 @@ { "rules": { + "array-type": [ + true, + "array" + ], "class-name": true, "comment-format": [ true, @@ -18,10 +22,7 @@ "no-eval": true, "no-internal-module": true, "no-trailing-whitespace": true, - "one-variable-per-declaration": [ - true, - true - ], + "one-variable-per-declaration": true, "no-unsafe-finally": true, "no-var-keyword": true, "quotemark": [ @@ -48,15 +49,21 @@ ], "variable-name": [ true, - "ban-keywords" + "ban-keywords", + "check-format", + "allow-leading-underscore" ], "whitespace": [ true, "check-branch", "check-decl", + "check-module", "check-operator", + "check-rest-spread", "check-separator", - "check-type" + "check-type", + "check-type-operator", + "check-preblock" ] } } From 4588d1573892c0b49ad030c9df6934d521b68135 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 17 Jan 2018 10:40:42 -0800 Subject: [PATCH 15/19] Add more tslint rules, fix attach addon --- src/Charsets.ts | 6 +++--- src/Interfaces.ts | 30 +++++++++++++++++++++++++----- src/Linkifier.test.ts | 6 +++--- src/Linkifier.ts | 20 ++++++++++---------- src/Terminal.ts | 10 +++++----- src/Types.ts | 17 ----------------- src/addons/attach/attach.ts | 8 ++++---- src/renderer/CursorRenderLayer.ts | 4 ++-- src/renderer/LinkRenderLayer.ts | 14 +++++++------- tslint.json | 5 +++++ 10 files changed, 64 insertions(+), 56 deletions(-) diff --git a/src/Charsets.ts b/src/Charsets.ts index 0ee91d32..e62e3f9c 100644 --- a/src/Charsets.ts +++ b/src/Charsets.ts @@ -3,19 +3,19 @@ * @license MIT */ -import { Charset } from './Types'; +import { ICharset } from './Interfaces'; /** * The character sets supported by the terminal. These enable several languages * to be represented within the terminal with only 8-bit encoding. See ISO 2022 * for a discussion on character sets. Only VT100 character sets are supported. */ -export const CHARSETS: { [key: string]: Charset } = {}; +export const CHARSETS: { [key: string]: ICharset } = {}; /** * The default character set, US. */ -export const DEFAULT_CHARSET: Charset = CHARSETS['B']; +export const DEFAULT_CHARSET: ICharset = CHARSETS['B']; /** * DEC Special Character and Line Drawing Set. diff --git a/src/Interfaces.ts b/src/Interfaces.ts index e209c4dc..5947f10b 100644 --- a/src/Interfaces.ts +++ b/src/Interfaces.ts @@ -3,8 +3,8 @@ * @license MIT */ -import { ILinkMatcherOptions } from './Interfaces'; -import { LinkMatcherHandler, LinkMatcherValidationCallback, Charset, LineData } from './Types'; +import { ICharset, ILinkMatcherOptions } from './Interfaces'; +import { LinkMatcherHandler, LinkMatcherValidationCallback, LineData } from './Types'; import { IColorSet, IRenderer } from './renderer/Interfaces'; import { IMouseZoneManager } from './input/Interfaces'; @@ -74,10 +74,10 @@ export interface IInputHandlingTerminal extends IEventEmitter { options: ITerminalOptions; cols: number; rows: number; - charset: Charset; + charset: ICharset; gcharset: number; glevel: number; - charsets: Charset[]; + charsets: ICharset[]; applicationKeypad: boolean; applicationCursor: boolean; originMode: boolean; @@ -116,7 +116,7 @@ export interface IInputHandlingTerminal extends IEventEmitter { blankLine(cur?: boolean, isWrapped?: boolean): LineData; is(term: string): boolean; send(data: string): void; - setgCharset(g: number, charset: Charset): void; + setgCharset(g: number, charset: ICharset): void; resize(x: number, y: number): void; log(text: string, data?: any): void; reset(): void; @@ -352,3 +352,23 @@ export interface ITheme { brightCyan?: string; brightWhite?: string; } + +export interface ILinkMatcher { + id: number; + regex: RegExp; + handler: LinkMatcherHandler; + hoverTooltipCallback?: LinkMatcherHandler; + hoverLeaveCallback?: () => void; + matchIndex?: number; + validationCallback?: LinkMatcherValidationCallback; + priority?: number; +} +export interface ICharset { + [key: string]: string; +} + +export interface ILinkHoverEvent { + x: number; + y: number; + length: number; +} diff --git a/src/Linkifier.test.ts b/src/Linkifier.test.ts index 0878aafc..8b66dcaa 100644 --- a/src/Linkifier.test.ts +++ b/src/Linkifier.test.ts @@ -4,9 +4,9 @@ */ import { assert } from 'chai'; -import { ITerminal, ILinkifier, IBuffer, IBufferAccessor, IElementAccessor } from './Interfaces'; +import { ITerminal, ILinkifier, ILinkMatcher, IBuffer, IBufferAccessor, IElementAccessor } from './Interfaces'; import { Linkifier } from './Linkifier'; -import { LinkMatcher, LineData } from './Types'; +import { LineData } from './Types'; import { IMouseZoneManager, IMouseZone } from './input/Interfaces'; import { MockBuffer } from './utils/TestUtils.test'; import { CircularList } from './utils/CircularList'; @@ -17,7 +17,7 @@ class TestLinkifier extends Linkifier { Linkifier.TIME_BEFORE_LINKIFY = 0; } - public get linkMatchers(): LinkMatcher[] { return this._linkMatchers; } + public get linkMatchers(): ILinkMatcher[] { return this._linkMatchers; } public linkifyRows(): void { super.linkifyRows(0, this._terminal.buffer.lines.length - 1); } } diff --git a/src/Linkifier.ts b/src/Linkifier.ts index e6a63b5c..76771930 100644 --- a/src/Linkifier.ts +++ b/src/Linkifier.ts @@ -3,8 +3,8 @@ * @license MIT */ -import { ILinkMatcherOptions, ITerminal, IBufferAccessor, ILinkifier, IElementAccessor } from './Interfaces'; -import { LinkMatcher, LinkMatcherHandler, LinkMatcherValidationCallback, LineData, LinkHoverEvent, LinkHoverEventTypes } from './Types'; +import { ILinkHoverEvent, ILinkMatcher, ILinkMatcherOptions, ITerminal, IBufferAccessor, ILinkifier, IElementAccessor } from './Interfaces'; +import { LinkMatcherHandler, LinkMatcherValidationCallback, LineData, LinkHoverEventTypes } from './Types'; import { IMouseZoneManager } from './input/Interfaces'; import { MouseZone } from './input/MouseZoneManager'; import { EventEmitter } from './EventEmitter'; @@ -44,7 +44,7 @@ export class Linkifier extends EventEmitter implements ILinkifier { */ protected static TIME_BEFORE_LINKIFY = 200; - protected _linkMatchers: LinkMatcher[] = []; + protected _linkMatchers: ILinkMatcher[] = []; private _mouseZoneManager: IMouseZoneManager; private _rowsTimeoutId: number; @@ -143,7 +143,7 @@ export class Linkifier extends EventEmitter implements ILinkifier { if (this._nextLinkMatcherId !== HYPERTEXT_LINK_MATCHER_ID && !handler) { throw new Error('handler must be defined'); } - const matcher: LinkMatcher = { + const matcher: ILinkMatcher = { id: this._nextLinkMatcherId++, regex, handler, @@ -163,7 +163,7 @@ export class Linkifier extends EventEmitter implements ILinkifier { * considered after older link matchers. * @param matcher The link matcher to be added. */ - private _addLinkMatcherToList(matcher: LinkMatcher): void { + private _addLinkMatcherToList(matcher: ILinkMatcher): void { if (this._linkMatchers.length === 0) { this._linkMatchers.push(matcher); return; @@ -219,7 +219,7 @@ export class Linkifier extends EventEmitter implements ILinkifier { * @param offset The how much of the row has already been linkified. * @return The link element(s) that were added. */ - private _doLinkifyRow(rowIndex: number, text: string, matcher: LinkMatcher, offset: number = 0): void { + private _doLinkifyRow(rowIndex: number, text: string, matcher: ILinkMatcher, offset: number = 0): void { // Iterate over nodes as we want to consider text nodes let result = []; const isHttpLinkMatcher = matcher.id === HYPERTEXT_LINK_MATCHER_ID; @@ -264,7 +264,7 @@ export class Linkifier extends EventEmitter implements ILinkifier { * @param uri The URI of the link. * @param matcher The link matcher for the link. */ - private _addLink(x: number, y: number, uri: string, matcher: LinkMatcher): void { + private _addLink(x: number, y: number, uri: string, matcher: ILinkMatcher): void { this._mouseZoneManager.add(new MouseZone( x + 1, x + 1 + uri.length, @@ -276,17 +276,17 @@ export class Linkifier extends EventEmitter implements ILinkifier { window.open(uri, '_blank'); }, e => { - this.emit(LinkHoverEventTypes.HOVER, { x, y, length: uri.length}); + this.emit(LinkHoverEventTypes.HOVER, { x, y, length: uri.length}); this._terminal.element.style.cursor = 'pointer'; }, e => { - this.emit(LinkHoverEventTypes.TOOLTIP, { x, y, length: uri.length}); + this.emit(LinkHoverEventTypes.TOOLTIP, { x, y, length: uri.length}); if (matcher.hoverTooltipCallback) { matcher.hoverTooltipCallback(e, uri); } }, () => { - this.emit(LinkHoverEventTypes.LEAVE, { x, y, length: uri.length}); + this.emit(LinkHoverEventTypes.LEAVE, { x, y, length: uri.length}); this._terminal.element.style.cursor = ''; if (matcher.hoverLeaveCallback) { matcher.hoverLeaveCallback(); diff --git a/src/Terminal.ts b/src/Terminal.ts index 8c0a3793..2280be8e 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -38,8 +38,8 @@ import { CharMeasure } from './utils/CharMeasure'; import * as Browser from './utils/Browser'; import { MouseHelper } from './utils/MouseHelper'; import { CHARSETS } from './Charsets'; -import { CustomKeyEventHandler, Charset, LinkMatcherHandler, LinkMatcherValidationCallback, CharData, LineData } from './Types'; -import { ITerminal, IBrowser, ITerminalOptions, IInputHandlingTerminal, ILinkMatcherOptions, IViewport, ICompositionHelper, ITheme, ILinkifier } from './Interfaces'; +import { CustomKeyEventHandler, LinkMatcherHandler, LinkMatcherValidationCallback, CharData, LineData } from './Types'; +import { ITerminal, IBrowser, ICharset, ITerminalOptions, IInputHandlingTerminal, ILinkMatcherOptions, IViewport, ICompositionHelper, ITheme, ILinkifier } from './Interfaces'; import { BELL_SOUND } from './utils/Sounds'; import { DEFAULT_ANSI_COLORS } from './renderer/ColorManager'; import { IMouseZoneManager } from './input/Interfaces'; @@ -131,10 +131,10 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT // charset // The current charset - public charset: Charset; + public charset: ICharset; public gcharset: number; public glevel: number; - public charsets: Charset[]; + public charsets: ICharset[]; // mouse properties private decLocator: boolean; // This is unstable and never set @@ -1728,7 +1728,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT * @param g * @param charset */ - public setgCharset(g: number, charset: Charset): void { + public setgCharset(g: number, charset: ICharset): void { this.charsets[g] = charset; if (this.glevel === g) { this.charset = charset; diff --git a/src/Types.ts b/src/Types.ts index 4a2b99ed..3263282e 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -3,31 +3,14 @@ * @license MIT */ -export type LinkMatcher = { - id: number, - regex: RegExp, - handler: LinkMatcherHandler, - hoverTooltipCallback?: LinkMatcherHandler, - hoverLeaveCallback?: () => void, - matchIndex?: number, - validationCallback?: LinkMatcherValidationCallback, - priority?: number -}; export type LinkMatcherHandler = (event: MouseEvent, uri: string) => boolean | void; export type LinkMatcherValidationCallback = (uri: string, callback: (isValid: boolean) => void) => void; export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean; -export type Charset = {[key: string]: string}; export type CharData = [number, string, number, number]; export type LineData = CharData[]; -export type LinkHoverEvent = { - x: number, - y: number, - length: number -}; - export enum LinkHoverEventTypes { HOVER = 'linkhover', TOOLTIP = 'linktooltip', diff --git a/src/addons/attach/attach.ts b/src/addons/attach/attach.ts index 21645c8a..ba938695 100644 --- a/src/addons/attach/attach.ts +++ b/src/addons/attach/attach.ts @@ -105,8 +105,8 @@ export function apply(terminalConstructor: any): void { * should happen instantly or at a maximum * frequency of 1 rendering per 10ms. */ - terminalConstructor.prototype.attach = (socket: WebSocket, bidirectional: boolean, buffered: boolean) => { - return attach(this, socket, bidirectional, buffered); + terminalConstructor.prototype.attach = function (socket: WebSocket, bidirectional: boolean, buffered: boolean): void { + attach(this, socket, bidirectional, buffered); }; /** @@ -115,7 +115,7 @@ export function apply(terminalConstructor: any): void { * @param {WebSocket} socket - The socket from which to detach the current * terminal. */ - terminalConstructor.prototype.detach = (socket: WebSocket) => { - return detach(this, socket); + terminalConstructor.prototype.detach = function (socket: WebSocket): void { + detach(this, socket); }; } diff --git a/src/renderer/CursorRenderLayer.ts b/src/renderer/CursorRenderLayer.ts index 689d6914..2706085f 100644 --- a/src/renderer/CursorRenderLayer.ts +++ b/src/renderer/CursorRenderLayer.ts @@ -11,7 +11,7 @@ import { FLAGS } from './Types'; import { BaseRenderLayer } from './BaseRenderLayer'; import { CharData } from '../Types'; -interface CursorState { +interface ICursorState { x: number; y: number; isFocused: boolean; @@ -25,7 +25,7 @@ interface CursorState { const BLINK_INTERVAL = 600; export class CursorRenderLayer extends BaseRenderLayer { - private _state: CursorState; + private _state: ICursorState; private _cursorRenderers: {[key: string]: (terminal: ITerminal, x: number, y: number, charData: CharData) => void}; private _cursorBlinkStateManager: CursorBlinkStateManager; private _isFocused: boolean; diff --git a/src/renderer/LinkRenderLayer.ts b/src/renderer/LinkRenderLayer.ts index 8f3b63a5..87fbddbd 100644 --- a/src/renderer/LinkRenderLayer.ts +++ b/src/renderer/LinkRenderLayer.ts @@ -4,20 +4,20 @@ */ import { IColorSet, IRenderDimensions } from './Interfaces'; -import { IBuffer, ICharMeasure, ITerminal, ILinkifierAccessor } from '../Interfaces'; +import { IBuffer, ICharMeasure, ILinkHoverEvent, ITerminal, ILinkifierAccessor } from '../Interfaces'; import { CHAR_DATA_ATTR_INDEX } from '../Buffer'; import { GridCache } from './GridCache'; import { FLAGS } from './Types'; import { BaseRenderLayer, INVERTED_DEFAULT_COLOR } from './BaseRenderLayer'; -import { LinkHoverEvent, LinkHoverEventTypes } from '../Types'; +import { LinkHoverEventTypes } from '../Types'; export class LinkRenderLayer extends BaseRenderLayer { - private _state: LinkHoverEvent = null; + private _state: ILinkHoverEvent = null; constructor(container: HTMLElement, zIndex: number, colors: IColorSet, terminal: ILinkifierAccessor) { super(container, 'link', zIndex, true, colors); - terminal.linkifier.on(LinkHoverEventTypes.HOVER, (e: LinkHoverEvent) => this._onLinkHover(e)); - terminal.linkifier.on(LinkHoverEventTypes.LEAVE, (e: LinkHoverEvent) => this._onLinkLeave(e)); + terminal.linkifier.on(LinkHoverEventTypes.HOVER, (e: ILinkHoverEvent) => this._onLinkHover(e)); + terminal.linkifier.on(LinkHoverEventTypes.LEAVE, (e: ILinkHoverEvent) => this._onLinkLeave(e)); } public resize(terminal: ITerminal, dim: IRenderDimensions, charSizeChanged: boolean): void { @@ -37,13 +37,13 @@ export class LinkRenderLayer extends BaseRenderLayer { } } - private _onLinkHover(e: LinkHoverEvent): void { + private _onLinkHover(e: ILinkHoverEvent): void { this._ctx.fillStyle = this._colors.foreground; this.fillBottomLineAtCells(e.x, e.y, e.length); this._state = e; } - private _onLinkLeave(e: LinkHoverEvent): void { + private _onLinkLeave(e: ILinkHoverEvent): void { this._clearCurrentLink(); } } diff --git a/tslint.json b/tslint.json index 31c9ec84..b5367f6a 100644 --- a/tslint.json +++ b/tslint.json @@ -13,6 +13,11 @@ true, "spaces" ], + "interface-name": [ + true, + "always-prefix" + ], + "interface-over-type-literal": true, "typedef": [ true, "call-signature", From 83921c0b26874216ee9c28ebab8d523acf5ff63e Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Thu, 18 Jan 2018 09:23:05 +0100 Subject: [PATCH 16/19] Add support for modifiers for PageUp / PageDown keys. This allows using Ctrl-PageUp/Down and Alt-PageUp/Down. --- src/Terminal.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Terminal.ts b/src/Terminal.ts index f95cc0ea..6e4d1aa0 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -1573,6 +1573,8 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT // page up if (ev.shiftKey) { result.scrollLines = -(this.rows - 1); + } else if (modifiers) { + result.key = C0.ESC + '[5;' + (modifiers + 1) + '~'; } else { result.key = C0.ESC + '[5~'; } @@ -1581,6 +1583,8 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT // page down if (ev.shiftKey) { result.scrollLines = this.rows - 1; + } else if (modifiers) { + result.key = C0.ESC + '[6;' + (modifiers + 1) + '~'; } else { result.key = C0.ESC + '[6~'; } From b1beee3595067600d9cacc462fa85286f57c9978 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 18 Jan 2018 07:54:45 -0800 Subject: [PATCH 17/19] Fix cursor lagging behind when blink is on Fixes #1216 --- src/renderer/CursorRenderLayer.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/renderer/CursorRenderLayer.ts b/src/renderer/CursorRenderLayer.ts index 689d6914..f4e3c54f 100644 --- a/src/renderer/CursorRenderLayer.ts +++ b/src/renderer/CursorRenderLayer.ts @@ -108,9 +108,10 @@ export class CursorRenderLayer extends BaseRenderLayer { } public onGridChanged(terminal: ITerminal, startRow: number, endRow: number): void { - // Only render if the animation frame is not active if (!this._cursorBlinkStateManager || this._cursorBlinkStateManager.isPaused) { this._render(terminal, false); + } else { + this._cursorBlinkStateManager.restartBlinkAnimation(terminal); } } From 2253e666e72770275fd1cb6c79fff42bdf92323f Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 18 Jan 2018 09:39:32 -0800 Subject: [PATCH 18/19] Remove OSX from travis Builds take too long on free tier --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1878c3a4..7a37af1e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: node_js os: - linux - - osx node_js: - 6 before_install: From 0645fe582ffdc0d1e5890e63a9b95075dbcfebc7 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 18 Jan 2018 12:27:07 -0800 Subject: [PATCH 19/19] Fix missing space --- src/Interfaces.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Interfaces.ts b/src/Interfaces.ts index 5947f10b..8f0baa2f 100644 --- a/src/Interfaces.ts +++ b/src/Interfaces.ts @@ -363,6 +363,7 @@ export interface ILinkMatcher { validationCallback?: LinkMatcherValidationCallback; priority?: number; } + export interface ICharset { [key: string]: string; }