Merge branch 'master' into bufferRange

This commit is contained in:
Megan Rogge
2021-06-08 16:53:28 -05:00
committed by GitHub
40 changed files with 1678 additions and 1728 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
FROM node:10
FROM node:14
# Configure apt
ENV DEBIAN_FRONTEND=noninteractive
+2 -1
View File
@@ -43,10 +43,11 @@
"@typescript-eslint/array-type": [
"warn",
{
"default": "array-simple",
"default": "array",
"readonly": "generic"
}
],
"@typescript-eslint/consistent-type-assertions": "warn",
"@typescript-eslint/consistent-type-definitions": "warn",
"@typescript-eslint/explicit-function-return-type": [
"warn",
+68 -49
View File
@@ -1,51 +1,70 @@
{
"version": "2.0.0",
"presentation": {
"echo": false,
"reveal": "always",
"focus": false,
"panel": "dedicated",
"showReuseMessage": true
},
"tasks": [
{
"type": "npm",
"script": "test",
"group": "test",
"problemMatcher": []
},
{
"type": "npm",
"script": "watch",
"group": "build",
"isBackground": true,
"problemMatcher": [],
"presentation": {
"group": "vscode"
}
},
{
"type": "npm",
"script": "start",
"group": "build",
"isBackground": true,
"problemMatcher": [],
"presentation": {
"group": "vscode"
}
},
{
"label": "Start demo",
"dependsOn": ["npm: watch", "npm: start"],
"group": {
"kind": "build",
"isDefault": true
},
"isBackground": true,
"problemMatcher": [],
"presentation": {
"group": "vscode"
}
}
]
"version": "2.0.0",
"presentation": {
"echo": false,
"reveal": "always",
"focus": false,
"panel": "dedicated",
"showReuseMessage": true
},
"tasks": [
{
"type": "npm",
"script": "test",
"group": "test",
"problemMatcher": []
},
{
"type": "npm",
"script": "watch",
"group": "build",
"isBackground": true,
"problemMatcher": "$tsc-watch",
"presentation": {
"group": "vscode"
}
},
{
"type": "npm",
"script": "start",
"dependsOn": "npm: watch",
"group": "build",
"isBackground": true,
"problemMatcher": [],
"presentation": {
"group": "vscode"
}
},
{
"label": "Start demo",
"dependsOn": "npm: start",
"group": {
"kind": "build",
"isDefault": true
},
"isBackground": true,
"problemMatcher": {
"owner": "typescript",
"fileLocation": [
"relative",
"${workspaceFolder}"
],
"pattern": [
{
"regexp": "^([^\\\\s].*)\\\\((\\\\d+,\\\\d+)\\\\):\\\\s*(.*)$",
"file": 1,
"location": 2,
"message": 3
}
],
"background": {
"beginsPattern": "assets by",
"endsPattern": "webpack \\d+\\.\\d+\\.\\d+ compiled successfully"
}
},
"presentation": {
"group": "vscode"
}
}
]
}
+27 -25
View File
@@ -6,11 +6,11 @@ Xterm.js is a front-end component written in TypeScript that lets applications b
## Features
- **Terminal apps just work**: Xterm.js works with most terminal apps such as `bash`, `vim` and `tmux`, this includes support for curses-based apps and mouse event support.
- **Terminal apps just work**: Xterm.js works with most terminal apps such as `bash`, `vim`, and `tmux`, including support for curses-based apps and mouse events.
- **Performant**: Xterm.js is *really* fast, it even includes a GPU-accelerated renderer.
- **Rich unicode support**: Supports CJK, emojis and IMEs.
- **Rich Unicode support**: Supports CJK, emojis, and IMEs.
- **Self-contained**: Requires zero dependencies to work.
- **Accessible**: Screen reader and minimum contrast ratio support can be turned on
- **Accessible**: Screen reader and minimum contrast ratio support can be turned on.
- **And much more**: Links, theming, addons, well documented API, etc.
## What xterm.js is not
@@ -20,13 +20,13 @@ Xterm.js is a front-end component written in TypeScript that lets applications b
## Getting Started
First you need to install the module, we ship exclusively through [npm](https://www.npmjs.com/) so you need that installed and then add xterm.js as a dependency by running:
First, you need to install the module, we ship exclusively through [npm](https://www.npmjs.com/), so you need that installed and then add xterm.js as a dependency by running:
```
```bash
npm install xterm
```
To start using xterm.js on your browser, add the `xterm.js` and `xterm.css` to the head of your html page. Then create a `<div id="terminal"></div>` onto which xterm can attach itself. Finally instantiate the `Terminal` object and then call the `open` function with the DOM object of the `div`.
To start using xterm.js on your browser, add the `xterm.js` and `xterm.css` to the head of your HTML page. Then create a `<div id="terminal"></div>` onto which xterm can attach itself. Finally, instantiate the `Terminal` object and then call the `open` function with the DOM object of the `div`.
```html
<!doctype html>
@@ -58,7 +58,7 @@ import { Terminal } from 'xterm';
⚠️ *This section describes the new addon format introduced in v3.14.0, see [here](https://github.com/xtermjs/xterm.js/blob/3.14.2/README.md#addons) for the instructions on the old format*
Addons are separate modules that extend the `Terminal` by building on the [xterm.js API](https://github.com/xtermjs/xterm.js/blob/master/typings/xterm.d.ts). To use an addon you first need to install it in your project:
Addons are separate modules that extend the `Terminal` by building on the [xterm.js API](https://github.com/xtermjs/xterm.js/blob/master/typings/xterm.d.ts). To use an addon, you first need to install it in your project:
```bash
npm i -S xterm-addon-web-links
@@ -76,7 +76,7 @@ const terminal = new Terminal();
terminal.loadAddon(new WebLinksAddon());
```
The xterm.js team maintains the following addons but they can be built by anyone:
The xterm.js team maintains the following addons, but anyone can build them:
- [`xterm-addon-attach`](https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-attach): Attaches to a server running a process via a websocket
- [`xterm-addon-fit`](https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-fit): Fits the terminal to the containing element
@@ -85,23 +85,23 @@ The xterm.js team maintains the following addons but they can be built by anyone
## Browser Support
Since xterm.js is typically implemented as a developer tool, only modern browsers are supported officially. Specifically the latest versions of *Chrome*, *Edge*, *Firefox* and *Safari*.
Since xterm.js is typically implemented as a developer tool, only modern browsers are supported officially. Specifically the latest versions of *Chrome*, *Edge*, *Firefox*, and *Safari*.
We also partially support *Internet Explorer 11*, meaning xterm.js should work for the most part, but we reserve the right to not provide workarounds specifically for it unless it's absolutely necessary to get the basic input/output flow working.
Xterm.js works seamlessly in [Electron](https://electronjs.org/) apps and may even work on earlier versions of the browsers, these are the versions we strive to keep working.
Xterm.js works seamlessly in [Electron](https://electronjs.org/) apps and may even work on earlier versions of the browsers. These are the versions we strive to keep working.
## API
The full API for xterm.js is contained within the [TypeScript declaration file](https://github.com/xtermjs/xterm.js/blob/master/typings/xterm.d.ts), use the branch/tag picker in GitHub (`w`) to navigate to the correct version of the API.
Note that some APIs are marked *experimental*, these are added to enable experimentation with new ideas without committing to support it like a normal [semver](https://semver.org/) API. Note that these APIs can change radically between versions so be sure to read release notes if you plan on using experimental APIs.
Note that some APIs are marked *experimental*, these are added to enable experimentation with new ideas without committing to support it like a normal [semver](https://semver.org/) API. Note that these APIs can change radically between versions, so be sure to read release notes if you plan on using experimental APIs.
## Real-world uses
Xterm.js is used in several world-class applications to provide great terminal experiences.
- [**SourceLair**](https://www.sourcelair.com/): In-browser IDE that provides its users with fully-featured Linux terminals based on xterm.js.
- [**Microsoft Visual Studio Code**](http://code.visualstudio.com/): Modern, versatile and powerful open source code editor that provides an integrated terminal based on xterm.js.
- [**Microsoft Visual Studio Code**](http://code.visualstudio.com/): Modern, versatile, and powerful open source code editor that provides an integrated terminal based on xterm.js.
- [**ttyd**](https://github.com/tsl0922/ttyd): A command-line tool for sharing terminal over the web, with fully-featured terminal emulation based on xterm.js.
- [**Katacoda**](https://www.katacoda.com/): Katacoda is an Interactive Learning Platform for software developers, covering the latest Cloud Native technologies.
- [**Eclipse Che**](http://www.eclipse.org/che): Developer workspace server, cloud IDE, and Eclipse next-generation IDE.
@@ -113,10 +113,10 @@ Xterm.js is used in several world-class applications to provide great terminal e
- [**Next Tech**](https://next.tech "Next Tech"): Online platform for interactive coding and web development courses. Live container-backed terminal uses xterm.js.
- [**RStudio**](https://www.rstudio.com/products/RStudio "RStudio"): RStudio is an integrated development environment (IDE) for R.
- [**Terminal for Atom**](https://github.com/jsmecham/atom-terminal-tab): A simple terminal for the Atom text editor.
- [**Eclipse Orion**](https://orionhub.org): A modern, open source software development environment that runs in the cloud. Code, deploy and run in the cloud.
- [**Eclipse Orion**](https://orionhub.org): A modern, open source software development environment that runs in the cloud. Code, deploy, and run in the cloud.
- [**Gravitational Teleport**](https://github.com/gravitational/teleport): Gravitational Teleport is a modern SSH server for remotely accessing clusters of Linux servers via SSH or HTTPS.
- [**Hexlet**](https://en.hexlet.io): Practical programming courses (JavaScript, PHP, Unix, databases, functional programming). A steady path from the first line of code to the first job.
- [**Selenoid UI**](https://github.com/aerokube/selenoid-ui): Simple UI for the scallable golang implementation of Selenium Hub named Selenoid. We use XTerm for streaming logs over websockets from docker containers.
- [**Selenoid UI**](https://github.com/aerokube/selenoid-ui): Simple UI for the scalable golang implementation of Selenium Hub named Selenoid. We use XTerm for streaming logs over websockets from docker containers.
- [**Portainer**](https://portainer.io): Simple management UI for Docker.
- [**SSHy**](https://github.com/stuicey/SSHy): HTML5 Based SSHv2 Web Client with E2E encryption utilising xterm.js, SJCL & websockets.
- [**JupyterLab**](https://github.com/jupyterlab/jupyterlab): An extensible computational environment for Jupyter, supporting interactive data science and scientific computing across all programming languages.
@@ -167,17 +167,19 @@ Xterm.js is used in several world-class applications to provide great terminal e
- [**Laravel Ssh Web Client**](https://github.com/roke22/Laravel-ssh-client): Laravel server inventory with ssh web client to connect at server using xterm.js
- [**Repl.it**](https://repl.it): Collaborative browser based IDE with support for 50+ different languages.
- [**TeleType**](https://github.com/akshaykmr/TeleType): cli tool that allows you to share your terminal online conveniently. Show off mad cli-fu, help a colleague, teach, or troubleshoot.
- [**Intervue**](https://www.intervue.io): Pair programming for interviews. Multiple programming languages supported, with results displayed by xterm.js.
- [**TRASA**](https://trasa.io): Zero trust access to Web, SSH, RDP and Database services.
- [**Intervue**](https://www.intervue.io): Pair programming for interviews. Multiple programming languages are supported, with results displayed by xterm.js.
- [**TRASA**](https://trasa.io): Zero trust access to Web, SSH, RDP, and Database services.
- [**Commas**](https://github.com/CyanSalt/commas): Commas is a hackable terminal and command runner.
- [**Devtron**](https://github.com/devtron-labs/devtron): Software Delivery Workflow For Kubernetes.
- [**NxShell**](https://github.com/nxshell/nxshell): An easy to use new terminal for SSH.
- [**gifcast**](https://dstein64.github.io/gifcast/): Converts an asciinema cast to an animated GIF.
- [**WizardWebssh**](https://gitlab.com/mikeramsey/wizardwebssh): A terminal with Pyqt5 Widget for embedding which can be used as an ssh client to connect to your ssh servers. It is written in Python, based on tornado, paramiko and xterm.js.
- [**Wizard Assistant**](https://wizardassistant.com/): Wizard Assistant comes with advanced automation tools, preloaded common and special time-saving commands, and a built in SSH terminal. Now you can remotely administer, troubleshoot, and analyze any system with ease.
[And much more...](https://github.com/xtermjs/xterm.js/network/dependents)
- [**WizardWebssh**](https://gitlab.com/mikeramsey/wizardwebssh): A terminal with Pyqt5 Widget for embedding, which can be used as an ssh client to connect to your ssh servers. It is written in Python, based on tornado, paramiko, and xterm.js.
- [**Wizard Assistant**](https://wizardassistant.com/): Wizard Assistant comes with advanced automation tools, preloaded common and special time-saving commands, and a built-in SSH terminal. Now you can remotely administer, troubleshoot, and analyze any system with ease.
- [**ucli**](https://github.com/tsadarsh/ucli): Command Line for everyone :family_man_woman_girl_boy: at [www.ucli.tech](https://www.ucli.tech).
- [**Tess**](https://github.com/SquitchYT/Tess/): Simple Terminal Fully Customizable for Everyone.
- [And much more...](https://github.com/xtermjs/xterm.js/network/dependents)
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. Note: Please add any new contributions to the end of the list only.
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 on our list. Note: Please add any new contributions to the end of the list only.
## Releases
@@ -187,21 +189,21 @@ All current and past releases are available on this repo's [Releases page](https
### Beta builds
Our CI releases beta builds to npm for every change that goes into master, install the latest beta build with:
Our CI releases beta builds to npm for every change that goes into master. Install the latest beta build with:
```
```bash
npm install -S xterm@beta
```
These should generally be stable but some bugs may slip in, we recommend using the beta build primarily to test out new features and for verifying bug fixes.
These should generally be stable, but some bugs may slip in. We recommend using the beta build primarily to test out new features and to verify bug fixes.
## Contributing
You can read the [guide on the wiki](https://github.com/xtermjs/xterm.js/wiki/Contributing) to learn how to contribute and setup xterm.js for development.
You can read the [guide on the wiki](https://github.com/xtermjs/xterm.js/wiki/Contributing) to learn how to contribute and set up xterm.js for development.
## License Agreement
If you contribute code to this project, you are implicitly allowing your code to be distributed under the MIT license. You are also implicitly verifying that all code is your original work.
If you contribute code to this project, you implicitly allow your code to be distributed under the MIT license. You are also implicitly verifying that all code is your original work.
Copyright (c) 2017-2019, [The xterm.js authors](https://github.com/xtermjs/xterm.js/graphs/contributors) (MIT License)<br>
Copyright (c) 2014-2017, SourceLair, Private Company ([www.sourcelair.com](https://www.sourcelair.com/home)) (MIT License)<br>
+1 -1
View File
@@ -20,7 +20,7 @@ export class AttachAddon implements ITerminalAddon {
this._socket = socket;
// always set binary type to arraybuffer, we do not handle blobs
this._socket.binaryType = 'arraybuffer';
this._bidirectional = (options && options.bidirectional === false) ? false : true;
this._bidirectional = !(options && options.bidirectional === false);
}
public activate(terminal: Terminal): void {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "xterm-addon-ligatures",
"version": "0.4.0",
"version": "0.5.0",
"description": "Add support for programming ligatures to xterm.js",
"author": {
"name": "The xterm.js authors",
+12 -3
View File
@@ -15,6 +15,15 @@ interface IFontMetadata {
blob: () => Promise<Blob>;
}
interface IFontAccessNavigator {
fonts: {
query: () => Promise<IFontMetadata[]>;
};
permissions: {
request?: (permission: { name: string }) => Promise<{state: string}>;
};
}
let fontsPromise: Promise<FontList | Record<string, IFontMetadata[]>> | undefined = undefined;
/**
@@ -28,7 +37,7 @@ export default async function load(fontFamily: string, cacheSize: number): Promi
// Web environment that supports font access API
if (typeof navigator !== 'undefined' && 'fonts' in navigator) {
try {
const status = await (navigator as any).permissions.request?.({
const status = await (navigator as IFontAccessNavigator).permissions.request?.({
name: 'local-fonts'
});
if (status && status.state !== 'granted') {
@@ -44,8 +53,8 @@ export default async function load(fontFamily: string, cacheSize: number): Promi
}
const fonts: Record<string, IFontMetadata[]> = {};
try {
const fontsIterator: AsyncIterableIterator<IFontMetadata> = (navigator as any).fonts.query();
for await (const metadata of fontsIterator) {
const fontsIterator = await (navigator as IFontAccessNavigator).fonts.query();
for (const metadata of fontsIterator) {
if (!fonts.hasOwnProperty(metadata.family)) {
fonts[metadata.family] = [];
}
+3 -3
View File
@@ -128,9 +128,9 @@ lodash.get@^4.4.2:
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
lodash@^4.17.15:
version "4.17.19"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
lolex@^2.7.5:
version "2.7.5"
+1 -1
View File
@@ -394,7 +394,7 @@ export class SearchAddon implements ITerminalAddon {
// If it is not in the viewport then we scroll else it just gets selected
if (result.row >= (terminal.buffer.active.viewportY + terminal.rows) || result.row < terminal.buffer.active.viewportY) {
let scroll = result.row - terminal.buffer.active.viewportY;
scroll = scroll - Math.floor(terminal.rows / 2);
scroll -= Math.floor(terminal.rows / 2);
terminal.scrollLines(scroll);
}
return true;
@@ -35,7 +35,7 @@ perfContext('Terminal: sh -c "dd if=/dev/urandom count=40 bs=1k | hexdump | lolc
chunks.push(data as unknown as Buffer);
length += data.length;
});
await new Promise(resolve => p.on('exit', () => resolve()));
await new Promise<void>(resolve => p.on('exit', () => resolve()));
contentUtf8 = Buffer.concat(chunks, length);
// translate to content string
const buffer = new Uint32Array(contentUtf8.length);
@@ -487,9 +487,9 @@ function newArray<T>(initial: T | ((index: number) => T), count: number): T[] {
const array: T[] = new Array<T>(count);
for (let i = 0; i < array.length; i++) {
if (typeof initial === 'function') {
array[i] = (<(index: number) => T>initial)(i);
array[i] = (initial as (index: number) => T)(i);
} else {
array[i] = <T>initial;
array[i] = initial as T;
}
}
return array;
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "xterm-addon-webgl",
"version": "0.10.0",
"version": "0.11.1",
"author": {
"name": "The xterm.js authors",
"url": "https://xtermjs.org/"
@@ -263,7 +263,7 @@ export class GlyphRenderer {
// Get attributes from fg (excluding inverse) and resolve inverse by pullibng rgb colors
// from bg. This is needed since the inverse fg color should be based on the original bg
// color, not on the selection color
fg = (fg & ~(Attributes.CM_MASK | Attributes.RGB_MASK | FgFlags.INVERSE));
fg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK | FgFlags.INVERSE);
switch (workCell.getBgColorMode()) {
case Attributes.CM_P16:
case Attributes.CM_P256:
+3 -3
View File
@@ -24,9 +24,9 @@ export class WebglAddon implements ITerminalAddon {
throw new Error('Cannot activate WebglAddon before Terminal.open');
}
this._terminal = terminal;
const renderService: IRenderService = (<any>terminal)._core._renderService;
const characterJoinerService: ICharacterJoinerService = (<any>terminal)._core._characterJoinerService;
const colors: IColorSet = (<any>terminal)._core._colorManager.colors;
const renderService: IRenderService = (terminal as any)._core._renderService;
const characterJoinerService: ICharacterJoinerService = (terminal as any)._core._characterJoinerService;
const colors: IColorSet = (terminal as any)._core._colorManager.colors;
this._renderer = new WebglRenderer(terminal, colors, characterJoinerService, this._preserveDrawingBuffer);
this._renderer.onContextLoss(() => this._onContextLoss.fire());
renderService.setRenderer(this._renderer);
@@ -342,7 +342,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
// Flag combined chars with a bit mask so they're easily identifiable
if (chars.length > 1) {
code = code | COMBINED_CHAR_BIT_MASK;
code |= COMBINED_CHAR_BIT_MASK;
}
// Cache the results in the model
+1 -2
View File
@@ -3,8 +3,7 @@
* @license MIT
*/
import { IEvent } from 'node-pty';
import { Terminal, ITerminalAddon } from 'xterm';
import { Terminal, ITerminalAddon, IEvent } from 'xterm';
declare module 'xterm-addon-webgl' {
/**
+7 -7
View File
@@ -10,7 +10,7 @@ jobs:
steps:
- task: NodeTool@0
inputs:
versionSpec: '10.x'
versionSpec: '14.x'
displayName: 'Install Node.js'
- task: YarnInstaller@3
inputs:
@@ -43,7 +43,7 @@ jobs:
steps:
- task: NodeTool@0
inputs:
versionSpec: '10.x'
versionSpec: '14.x'
displayName: 'Install Node.js'
- task: CacheBeta@1
inputs:
@@ -63,7 +63,7 @@ jobs:
steps:
- task: NodeTool@0
inputs:
versionSpec: '10.x'
versionSpec: '14.x'
displayName: 'Install Node.js'
- task: CacheBeta@1
inputs:
@@ -92,7 +92,7 @@ jobs:
displayName: Install required packages
- task: NodeTool@0
inputs:
versionSpec: '10.x'
versionSpec: '14.x'
displayName: 'Install Node.js'
- task: YarnInstaller@3
inputs:
@@ -111,7 +111,7 @@ jobs:
steps:
- task: NodeTool@0
inputs:
versionSpec: '10.x'
versionSpec: '14.x'
displayName: 'Install Node.js'
- script: yarn --frozen-lockfile
displayName: 'Install dependencies and build'
@@ -128,7 +128,7 @@ jobs:
steps:
- task: NodeTool@0
inputs:
versionSpec: '10.x'
versionSpec: '14.x'
displayName: 'Install Node.js'
- script: yarn --frozen-lockfile
displayName: 'Install dependencies and build'
@@ -151,7 +151,7 @@ jobs:
steps:
- task: NodeTool@0
inputs:
versionSpec: '10.x'
versionSpec: '14.x'
displayName: 'Install Node.js'
- task: YarnInstaller@3
inputs:
+25 -25
View File
@@ -1,7 +1,7 @@
{
"name": "xterm",
"description": "Full xterm terminal, in your browser",
"version": "4.11.0",
"version": "4.12.0",
"main": "lib/xterm.js",
"style": "css/xterm.css",
"types": "typings/xterm.d.ts",
@@ -34,37 +34,37 @@
"vtfeatures": "node bin/extract_vtfeatures.js src/**/*.ts src/*.ts"
},
"devDependencies": {
"@types/chai": "^4.2.14",
"@types/chai": "^4.2.18",
"@types/debug": "^4.1.5",
"@types/deep-equal": "^1.0.1",
"@types/glob": "^7.1.3",
"@types/jsdom": "^16.2.5",
"@types/mocha": "^8.0.3",
"@types/node": "^10.17.17",
"@types/jsdom": "^16.2.10",
"@types/mocha": "^8.2.2",
"@types/node": "^14.14.44",
"@types/utf8": "^2.1.6",
"@types/webpack": "^4.41.24",
"@types/ws": "^7.2.9",
"@typescript-eslint/eslint-plugin": "^4.0.0",
"@typescript-eslint/parser": "^3.10.1",
"chai": "^4.2.0",
"deep-equal": "^2.0.4",
"eslint": "^7.12.1",
"@types/webpack": "^5.28.0",
"@types/ws": "^7.4.4",
"@typescript-eslint/eslint-plugin": "^4.23.0",
"@typescript-eslint/parser": "^4.23.0",
"chai": "^4.3.4",
"deep-equal": "^2.0.5",
"eslint": "^7.26.0",
"express": "^4.17.1",
"express-ws": "^4.0.0",
"glob": "^7.0.5",
"jsdom": "^16.4.0",
"mocha": "^8.2.1",
"mustache": "^4.0.1",
"node-pty": "^0.9.0",
"glob": "^7.1.7",
"jsdom": "^16.5.3",
"mocha": "^8.4.0",
"mustache": "^4.2.0",
"node-pty": "^0.10.1",
"nyc": "^15.1.0",
"playwright": "^1.5.2",
"source-map-loader": "^1.1.2",
"ts-loader": "^8.0.8",
"typescript": "4.0",
"playwright": "^1.11.0",
"source-map-loader": "^2.0.1",
"ts-loader": "^9.1.2",
"typescript": "^4.2.4",
"utf8": "^3.0.0",
"webpack": "^5.4.0",
"webpack-cli": "^4.2.0",
"ws": "^7.3.1",
"xterm-benchmark": "^0.1.3"
"webpack": "^5.37.0",
"webpack-cli": "^4.7.0",
"ws": "^7.4.5",
"xterm-benchmark": "^0.2.1"
}
}
+1 -1
View File
@@ -112,7 +112,7 @@ export class AccessibilityManager extends Disposable {
}
private _onBoundaryFocus(e: FocusEvent, position: BoundaryPosition): void {
const boundaryElement = <HTMLElement>e.target;
const boundaryElement = e.target as HTMLElement;
const beforeBoundaryElement = this._rowElements[position === BoundaryPosition.TOP ? 1 : this._rowElements.length - 2];
// Don't scroll if the buffer top has reached the end in that direction
+2 -2
View File
@@ -17,7 +17,7 @@ describe('ColorManager', () => {
dom = new jsdom.JSDOM('');
window = dom.window;
document = window.document;
(<any>window).HTMLCanvasElement.prototype.getContext = () => ({
(window as any).HTMLCanvasElement.prototype.getContext = () => ({
createLinearGradient(): any {
return null;
},
@@ -36,7 +36,7 @@ describe('ColorManager', () => {
for (const key of Object.keys(cm.colors)) {
if (key !== 'ansi' && key !== 'contrastCache') {
// A #rrggbb or rgba(...)
assert.ok((<any>cm.colors)[key].css.length >= 7);
assert.ok((cm.colors as any)[key].css.length >= 7);
}
}
assert.equal(cm.colors.ansi.length, 256);
+2 -2
View File
@@ -174,7 +174,7 @@ describe('Linkifier', () => {
assert.equal(mouseZoneManager.zones[0].y1, 1);
assert.equal(mouseZoneManager.zones[0].y2, 1);
// Fires done()
mouseZoneManager.zones[0].clickCallback(<any>{});
mouseZoneManager.zones[0].clickCallback({} as any);
}
});
linkifier.linkifyRows();
@@ -210,7 +210,7 @@ describe('Linkifier', () => {
let count = 0;
linkifier.registerLinkMatcher(/test/, () => assert.fail(), {
validationCallback: (url, cb) => {
count += 1;
count++;
if (count === 2) {
done();
}
+3 -1
View File
@@ -89,7 +89,9 @@ export class Linkifier implements ILinkifier {
if (this._rowsTimeoutId) {
clearTimeout(this._rowsTimeoutId);
}
this._rowsTimeoutId = <number><any>setTimeout(() => this._linkifyRows(), Linkifier._timeBeforeLatency);
// Cannot use window.setTimeout since tests need to run in node
this._rowsTimeoutId = setTimeout(() => this._linkifyRows(), Linkifier._timeBeforeLatency) as any as number;
}
/**
+15 -15
View File
@@ -29,10 +29,10 @@ describe('Terminal', () => {
beforeEach(() => {
term = new TestTerminal(termOptions);
term.refresh = () => { };
(<any>term).renderer = new MockRenderer();
(term as any).renderer = new MockRenderer();
term.viewport = new MockViewport();
(<any>term)._compositionHelper = new MockCompositionHelper();
(<any>term).element = {
(term as any)._compositionHelper = new MockCompositionHelper();
(term as any).element = {
classList: {
toggle: () => { },
remove: () => { }
@@ -86,12 +86,12 @@ describe('Terminal', () => {
assert.equal(e.domEvent instanceof Object, true);
done();
});
const evKeyPress = <KeyboardEvent>{
const evKeyPress = {
preventDefault: () => { },
stopPropagation: () => { },
type: 'keypress',
keyCode: 13
};
} as KeyboardEvent;
term.keyPress(evKeyPress);
});
it('should fire a key event after a keydown DOM event', (done) => {
@@ -100,13 +100,13 @@ describe('Terminal', () => {
assert.equal(e.domEvent instanceof Object, true);
done();
});
(<any>term).textarea = { value: '' };
const evKeyDown = <KeyboardEvent>{
(term as any).textarea = { value: '' };
const evKeyDown = {
preventDefault: () => { },
stopPropagation: () => { },
type: 'keydown',
keyCode: 13
};
} as KeyboardEvent;
term.keyDown(evKeyDown);
});
it('should fire the onResize event', (done) => {
@@ -140,18 +140,18 @@ describe('Terminal', () => {
});
describe('attachCustomKeyEventHandler', () => {
const evKeyDown = <KeyboardEvent>{
const evKeyDown = {
preventDefault: () => { },
stopPropagation: () => { },
type: 'keydown',
keyCode: 77
};
const evKeyPress = <KeyboardEvent>{
} as KeyboardEvent;
const evKeyPress = {
preventDefault: () => { },
stopPropagation: () => { },
type: 'keypress',
keyCode: 77
};
} as KeyboardEvent;
beforeEach(() => {
term.clearSelection = () => { };
@@ -374,13 +374,13 @@ describe('Terminal', () => {
describe('keyPress', () => {
it('should scroll down, when a key is pressed and terminal is scrolled up', () => {
const event = <KeyboardEvent>{
const event = {
type: 'keydown',
key: 'a',
keyCode: 65,
preventDefault: () => { },
stopPropagation: () => { }
};
} as KeyboardEvent;
term.buffer.ydisp = 0;
term.buffer.ybase = 40;
@@ -403,7 +403,7 @@ describe('Terminal', () => {
assert.equal(term.buffer.ydisp, startYDisp);
term.scrollLines(-1);
assert.equal(term.buffer.ydisp, startYDisp - 1);
term.keyPress(<KeyboardEvent>{ keyCode: 0 });
term.keyPress({ keyCode: 0 });
assert.equal(term.buffer.ydisp, startYDisp - 1);
});
});
+2 -2
View File
@@ -72,7 +72,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
// private _visualBellTimer: number;
public browser: IBrowser = <any>Browser;
public browser: IBrowser = Browser as any;
// TODO: We should remove options once components adopt optionsService
public get options(): IInitializedTerminalOptions { return this.optionsService.options; }
@@ -601,7 +601,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
let but: CoreMouseButton;
let action: CoreMouseAction | undefined;
switch ((<any>ev).overrideType || ev.type) {
switch ((ev as any).overrideType || ev.type) {
case 'mousemove':
action = CoreMouseAction.MOVE;
if (ev.buttons === undefined) {
+2 -2
View File
@@ -73,7 +73,7 @@ describe('Escape Sequence Files', function(): void {
// register handler to trigger viewport scraping, wait for it to finish
let content = '';
const OSC_CODE = 12345;
await new Promise(resolve => {
await new Promise<void>(resolve => {
customHandler = term.registerOscHandler(OSC_CODE, () => {
// grab terminal viewport content
content = terminalToString(term);
@@ -105,7 +105,7 @@ function formatError(input: string, output: string, expected: string): string {
function addLineNumber(start: number, color: string): (s: string) => string {
let counter = start || 0;
return (s: string): string => {
counter += 1;
counter++;
return '\x1b[33m' + (' ' + counter).slice(-2) + color + s;
};
}
+1 -1
View File
@@ -153,7 +153,7 @@ export class MockTerminal implements ITerminal {
public textarea!: HTMLTextAreaElement;
public rows!: number;
public cols!: number;
public browser: IBrowser = <any>Browser;
public browser: IBrowser = Browser as any;
public writeBuffer!: string[];
public children!: HTMLElement[];
public cursorHidden!: boolean;
+2
View File
@@ -151,6 +151,8 @@ export class Viewport extends Disposable implements IViewport {
// Ignore the event if it was flagged to ignore (when the source of the event is from Viewport)
if (this._ignoreNextScrollEvent) {
this._ignoreNextScrollEvent = false;
// Still trigger the scroll so lines get refreshed
this._scrollLines(0);
return;
}
+24 -24
View File
@@ -49,7 +49,7 @@ describe('CompositionHelper', () => {
it('Should insert simple characters', (done) => {
// First character 'ㅇ'
compositionHelper.compositionstart();
compositionHelper.compositionupdate(<CompositionEvent><CompositionEvent>{ data: 'ㅇ' });
compositionHelper.compositionupdate({ data: 'ㅇ' });
textarea.value = 'ㅇ';
setTimeout(() => { // wait for any textarea updates
compositionHelper.compositionend();
@@ -57,7 +57,7 @@ describe('CompositionHelper', () => {
assert.equal(handledText, 'ㅇ');
// Second character 'ㅇ'
compositionHelper.compositionstart();
compositionHelper.compositionupdate(<CompositionEvent><CompositionEvent>{ data: 'ㅇ' });
compositionHelper.compositionupdate({ data: 'ㅇ' });
textarea.value = 'ㅇㅇ';
setTimeout(() => { // wait for any textarea updates
compositionHelper.compositionend();
@@ -73,13 +73,13 @@ describe('CompositionHelper', () => {
it('Should insert complex characters', (done) => {
// First character '앙'
compositionHelper.compositionstart();
compositionHelper.compositionupdate(<CompositionEvent>{ data: 'ㅇ' });
compositionHelper.compositionupdate({ data: 'ㅇ' });
textarea.value = 'ㅇ';
setTimeout(() => { // wait for any textarea updates
compositionHelper.compositionupdate(<CompositionEvent>{ data: '아' });
compositionHelper.compositionupdate({ data: '아' });
textarea.value = '아';
setTimeout(() => { // wait for any textarea updates
compositionHelper.compositionupdate(<CompositionEvent>{ data: '앙' });
compositionHelper.compositionupdate({ data: '앙' });
textarea.value = '앙';
setTimeout(() => { // wait for any textarea updates
compositionHelper.compositionend();
@@ -87,13 +87,13 @@ describe('CompositionHelper', () => {
assert.equal(handledText, '앙');
// Second character '앙'
compositionHelper.compositionstart();
compositionHelper.compositionupdate(<CompositionEvent>{ data: 'ㅇ' });
compositionHelper.compositionupdate({ data: 'ㅇ' });
textarea.value = '앙ㅇ';
setTimeout(() => { // wait for any textarea updates
compositionHelper.compositionupdate(<CompositionEvent>{ data: '아' });
compositionHelper.compositionupdate({ data: '아' });
textarea.value = '앙아';
setTimeout(() => { // wait for any textarea updates
compositionHelper.compositionupdate(<CompositionEvent>{ data: '앙' });
compositionHelper.compositionupdate({ data: '앙' });
textarea.value = '앙앙';
setTimeout(() => { // wait for any textarea updates
compositionHelper.compositionend();
@@ -113,19 +113,19 @@ describe('CompositionHelper', () => {
it('Should insert complex characters that change with following character', (done) => {
// First character '아'
compositionHelper.compositionstart();
compositionHelper.compositionupdate(<CompositionEvent>{ data: 'ㅇ' });
compositionHelper.compositionupdate({ data: 'ㅇ' });
textarea.value = 'ㅇ';
setTimeout(() => { // wait for any textarea updates
compositionHelper.compositionupdate(<CompositionEvent>{ data: '아' });
compositionHelper.compositionupdate({ data: '아' });
textarea.value = '아';
setTimeout(() => { // wait for any textarea updates
// Start second character '아' in first character
compositionHelper.compositionupdate(<CompositionEvent>{ data: '앙' });
compositionHelper.compositionupdate({ data: '앙' });
textarea.value = '앙';
setTimeout(() => { // wait for any textarea updates
compositionHelper.compositionend();
compositionHelper.compositionstart();
compositionHelper.compositionupdate(<CompositionEvent>{ data: '아' });
compositionHelper.compositionupdate({ data: '아' });
textarea.value = '아아';
setTimeout(() => { // wait for any textarea updates
compositionHelper.compositionend();
@@ -142,14 +142,14 @@ describe('CompositionHelper', () => {
it('Should insert multi-characters compositions', (done) => {
// First character 'だ'
compositionHelper.compositionstart();
compositionHelper.compositionupdate(<CompositionEvent>{ data: 'd' });
compositionHelper.compositionupdate({ data: 'd' });
textarea.value = 'd';
setTimeout(() => { // wait for any textarea updates
compositionHelper.compositionupdate(<CompositionEvent>{ data: 'だ' });
compositionHelper.compositionupdate({ data: 'だ' });
textarea.value = 'だ';
setTimeout(() => { // wait for any textarea updates
// Second character 'あ'
compositionHelper.compositionupdate(<CompositionEvent>{ data: 'だあ' });
compositionHelper.compositionupdate({ data: 'だあ' });
textarea.value = 'だあ';
setTimeout(() => { // wait for any textarea updates
compositionHelper.compositionend();
@@ -165,18 +165,18 @@ describe('CompositionHelper', () => {
it('Should insert multi-character compositions that are converted to other characters with the same length', (done) => {
// First character 'だ'
compositionHelper.compositionstart();
compositionHelper.compositionupdate(<CompositionEvent>{ data: 'd' });
compositionHelper.compositionupdate({ data: 'd' });
textarea.value = 'd';
setTimeout(() => { // wait for any textarea updates
compositionHelper.compositionupdate(<CompositionEvent>{ data: 'だ' });
compositionHelper.compositionupdate({ data: 'だ' });
textarea.value = 'だ';
setTimeout(() => { // wait for any textarea updates
// Second character 'ー'
compositionHelper.compositionupdate(<CompositionEvent>{ data: 'だー' });
compositionHelper.compositionupdate({ data: 'だー' });
textarea.value = 'だー';
setTimeout(() => { // wait for any textarea updates
// Convert to katakana 'ダー'
compositionHelper.compositionupdate(<CompositionEvent>{ data: 'ダー' });
compositionHelper.compositionupdate({ data: 'ダー' });
textarea.value = 'ダー';
setTimeout(() => { // wait for any textarea updates
compositionHelper.compositionend();
@@ -193,18 +193,18 @@ describe('CompositionHelper', () => {
it('Should insert multi-character compositions that are converted to other characters with different lengths', (done) => {
// First character 'い'
compositionHelper.compositionstart();
compositionHelper.compositionupdate(<CompositionEvent>{ data: 'い' });
compositionHelper.compositionupdate({ data: 'い' });
textarea.value = 'い';
setTimeout(() => { // wait for any textarea updates
// Second character 'ま'
compositionHelper.compositionupdate(<CompositionEvent>{ data: 'いm' });
compositionHelper.compositionupdate({ data: 'いm' });
textarea.value = 'いm';
setTimeout(() => { // wait for any textarea updates
compositionHelper.compositionupdate(<CompositionEvent>{ data: 'いま' });
compositionHelper.compositionupdate({ data: 'いま' });
textarea.value = 'いま';
setTimeout(() => { // wait for any textarea updates
// Convert to kanji '今'
compositionHelper.compositionupdate(<CompositionEvent>{ data: '今' });
compositionHelper.compositionupdate({ data: '今' });
textarea.value = '今';
setTimeout(() => { // wait for any textarea updates
compositionHelper.compositionend();
@@ -221,7 +221,7 @@ describe('CompositionHelper', () => {
it('Should insert non-composition characters input immediately after composition characters', (done) => {
// First character 'ㅇ'
compositionHelper.compositionstart();
compositionHelper.compositionupdate(<CompositionEvent>{ data: 'ㅇ' });
compositionHelper.compositionupdate({ data: 'ㅇ' });
textarea.value = 'ㅇ';
setTimeout(() => { // wait for any textarea updates
compositionHelper.compositionend();
+1 -1
View File
@@ -69,7 +69,7 @@ export class CompositionHelper {
* Handles the compositionupdate event, updating the composition view.
* @param ev The event.
*/
public compositionupdate(ev: CompositionEvent): void {
public compositionupdate(ev: Pick<CompositionEvent, 'data'>): void {
this._compositionView.textContent = ev.data;
this.updateCompositionElements();
setTimeout(() => {
+1 -1
View File
@@ -31,7 +31,7 @@ export class AddonManager implements IDisposable {
};
this._addons.push(loadedAddon);
instance.dispose = () => this._wrappedAddonDispose(loadedAddon);
instance.activate(<any>terminal);
instance.activate(terminal as any);
}
private _wrappedAddonDispose(loadedAddon: ILoadedAddon): void {
+1 -1
View File
@@ -280,7 +280,7 @@ class BufferLineApiView implements IBufferLineApi {
}
if (cell) {
this._line.loadCell(x, <ICellData>cell);
this._line.loadCell(x, cell as ICellData);
return cell;
}
return this._line.loadCell(x, new CellData());
+1 -1
View File
@@ -10,7 +10,7 @@ import { ITerminalOptions } from 'common/services/Services';
export function generateConfig(scaledCharWidth: number, scaledCharHeight: number, options: ITerminalOptions, colors: IColorSet): ICharAtlasConfig {
// null out some fields that don't matter
const clonedColors = <IPartialColorSet>{
const clonedColors: IPartialColorSet = {
foreground: colors.foreground,
background: colors.background,
cursor: undefined,
+1 -1
View File
@@ -387,7 +387,7 @@ export class DomRenderer extends Disposable implements IRenderer {
if (!row) {
return;
}
const span = <HTMLElement>row.children[x];
const span = row.children[x] as HTMLElement;
if (span) {
span.style.textDecoration = enabled ? 'underline' : 'none';
}
@@ -270,7 +270,7 @@ function lineData(data: IPartialLineData[]): IBufferLine {
const tline = new BufferLine(0);
for (let i = 0; i < data.length; ++i) {
const line = data[i][0];
const attr = <number>(data[i][1] || 0);
const attr = (data[i][1] || 0) as number;
const offset = tline.length;
tline.resize(tline.length + line.split('').length, CellData.fromCharData([0, '', 0, 0]));
line.split('').map((char, idx) => tline.setCell(idx + offset, CellData.fromCharData([attr, char, 1, char.charCodeAt(0)])));
+2 -2
View File
@@ -133,8 +133,8 @@ export class SelectionService extends Disposable implements ISelectionService {
super();
// Init listeners
this._mouseMoveListener = event => this._onMouseMove(<MouseEvent>event);
this._mouseUpListener = event => this._onMouseUp(<MouseEvent>event);
this._mouseMoveListener = event => this._onMouseMove(event as MouseEvent);
this._mouseUpListener = event => this._onMouseUp(event as MouseEvent);
this._coreService.onUserInput(() => {
if (this.hasSelection) {
this.clearSelection();
+1 -1
View File
@@ -13,7 +13,7 @@ export class SoundService implements ISoundService {
public static get audioContext(): AudioContext | null {
if (!SoundService._audioContext) {
const audioContextCtor: typeof AudioContext = (<any>window).AudioContext || (<any>window).webkitAudioContext;
const audioContextCtor: typeof AudioContext = (window as any).AudioContext || (window as any).webkitAudioContext;
if (!audioContextCtor) {
console.warn('Web Audio API is not supported by this browser. Consider upgrading to the latest version');
return null;
+1 -1
View File
@@ -16,7 +16,7 @@ export function clone<T>(val: T, depth: number = 5): T {
for (const key in val) {
// Recursively clone eack item unless we're at the maximum depth
clonedObject[key] = depth <= 1 ? val[key] : (val[key] ? clone(val[key], depth - 1) : val[key]);
clonedObject[key] = depth <= 1 ? val[key] : (val[key] && clone(val[key], depth - 1));
}
return clonedObject as T;
+5 -5
View File
@@ -77,7 +77,7 @@ describe('InputHandler', () => {
optionsService.options.scrollback = 1;
bufferService.reset();
});
it('SL (scrollLeft)', async () => {
it('SL (scrollLeft)', () => {
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[ @');
assert.deepEqual(getLines(bufferService, 6), ['12345', '2345', '2345', '2345', '2345', '2345']);
@@ -86,7 +86,7 @@ describe('InputHandler', () => {
inputHandler.parseP('\x1b[2 @');
assert.deepEqual(getLines(bufferService, 6), ['12345', '5', '5', '5', '5', '5']);
});
it('SR (scrollRight)', async () => {
it('SR (scrollRight)', () => {
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[ A');
assert.deepEqual(getLines(bufferService, 6), ['12345', ' 1234', ' 1234', ' 1234', ' 1234', ' 1234']);
@@ -95,7 +95,7 @@ describe('InputHandler', () => {
inputHandler.parseP('\x1b[2 A');
assert.deepEqual(getLines(bufferService, 6), ['12345', ' 1', ' 1', ' 1', ' 1', ' 1']);
});
it('insertColumns (DECIC)', async () => {
it('insertColumns (DECIC)', () => {
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[\'}');
@@ -111,7 +111,7 @@ describe('InputHandler', () => {
inputHandler.parseP('\x1b[2\'}');
assert.deepEqual(getLines(bufferService, 6), ['12345', '12 3', '12 3', '12 3', '12 3', '12 3']);
});
it('deleteColumns (DECDC)', async () => {
it('deleteColumns (DECDC)', () => {
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[\'~');
@@ -137,7 +137,7 @@ describe('InputHandler', () => {
bufferService.reset();
});
describe('reverseWraparound set', () => {
it('should not reverse outside of scroll margins', async () => {
it('should not reverse outside of scroll margins', () => {
// prepare buffer content
inputHandler.parseP('#####abcdefghijklmnopqrstuvwxy');
assert.deepEqual(getLines(bufferService, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', 'uvwxy']);
+1 -1
View File
@@ -125,7 +125,7 @@ export class MockOptionsService implements IOptionsService {
constructor(testOptions?: IPartialTerminalOptions) {
if (testOptions) {
for (const key of Object.keys(testOptions)) {
this.options[key] = (<any>testOptions)[key];
this.options[key] = (testOptions as any)[key];
}
}
}
+1450 -1534
View File
File diff suppressed because it is too large Load Diff