mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Merge branch 'master' into transparency
This commit is contained in:
@@ -23,3 +23,6 @@ fixtures/typings-test/*.js
|
||||
dist/
|
||||
src/utils/TestUtils.ts
|
||||
src/xterm.js
|
||||
|
||||
# Keep the demo builds out of Git
|
||||
demo/dist/
|
||||
|
||||
@@ -19,45 +19,63 @@ Bill Church <billchurch@users.noreply.github.com>
|
||||
Bob Reid <bobreid@Bobs-MacBook-Pro.local>
|
||||
bottleofwater <nison.mael+bottleofwater@gmail.com>
|
||||
Brian Mock <brian@mockbrian.com>
|
||||
Bruno Ribeito <b.m.fernandes.ribeiro@gmail.com>
|
||||
Carson Anderson <carson@betterservers.com>
|
||||
CHaBou <chabup@delean.fr>
|
||||
Christian Budde Christensen <budde377@gmail.com>
|
||||
Christof Marti <chrmarti@microsoft.com>
|
||||
Christopher Jeffrey <chjjeffrey@gmail.com>
|
||||
coderaiser <mnemonic.enemy@gmail.com>
|
||||
Dan Brown <jdanbrown@gmail.com>
|
||||
Daniel Griffen <daniel@griffen.io>
|
||||
Daniel Imms <daimms@microsoft.com>
|
||||
Daniel Risacher <drisacher@gmail.com>
|
||||
Dan Kaplun <dbkaplun@twitch.tv>
|
||||
Darin Morrison <freebroccolo@users.noreply.github.com>
|
||||
dcylabs <dcylabs@gmail.com>
|
||||
Dominik Csapak <d.csapak@proxmox.com>
|
||||
Edgar Andrés Margffoy Tuay <andfoy@gmail.com>
|
||||
Elliot Saba <staticfloat@gmail.com>
|
||||
Exile <exile@chamber.ee>
|
||||
Felipe Gasper <felipe@felipegasper.com>
|
||||
ficristo <ficristo.work@gmail.com>
|
||||
Gary Ritchie <gary@rstudio.com>
|
||||
hiro-su <h.sugipon@gmail.com>
|
||||
Ian Lewis <ianlewis@google.com>
|
||||
imoses <ido@twiggle.com>
|
||||
InDieTasten <indietasten@gmail.com>
|
||||
irokas <akasidiari@inf.uth.gr>
|
||||
Jakob Gillich <jakob@gillich.me>
|
||||
Jean Bruenn <himself@jeanbruenn.info>
|
||||
Jeremy Danyow <jedanyow@microsoft.com>
|
||||
Joao Moreno <jomo@microsoft.com>
|
||||
Joao Moreno <mail@joaomoreno.com>
|
||||
Johannes Zellner <johannes@nebulon.de>
|
||||
Jon Masters <jon.masters@sky.com>
|
||||
Jörg Breitbart <jerch@rockborn.de>
|
||||
Justin Mecham <justin@mecham.me>
|
||||
Kirill Merkushev <lanwen@yandex.ru>
|
||||
Luca <LucaT1@users.noreply.github.com>
|
||||
Lucian Buzzo <lucian.buzzo@gmail.com>
|
||||
Lukas Drgon <lukas.drgon@gmail.com>
|
||||
Maël Nison <nison.mael@gmail.com>
|
||||
Marc Dumais <marc.dumais@ericsson.com>
|
||||
Martin Chloride <i@martincl2.me>
|
||||
Martin Koppehel <martin.koppehel@st.ovgu.de>
|
||||
Martin Wang <jiahaow@ca.ibm.com>
|
||||
Matt Bierner <matb@microsoft.com>
|
||||
Michael Irwin <mikesir87@gmail.com>
|
||||
Mikko Karvonen <mikko.karvonen@arm.com>
|
||||
mofux <t.zilz@mofux.org>
|
||||
Nicolas Ramz <nicolas.ramz@gmail.com>
|
||||
npezza93 <npezza93@gmail.com>
|
||||
Oleksandr Andriienko <oandriie@redhat.com>
|
||||
Paris Kasidiaris <pariskasidiaris@gmail.com>
|
||||
Paris Kasidiaris <paris@sourcelair.com>
|
||||
Peter Baumgarten <me@peterbaumgarten.com>
|
||||
Rick Baker <rick@ricktbaker.com>
|
||||
runarberg <runar@greenqloud.com>
|
||||
Samuel Williams <samuel.williams@oriontransfer.co.nz>
|
||||
Saswat Das <saswatds@users.noreply.github.com>
|
||||
Saul Costa <saul@codevolve.com>
|
||||
Shuanglei Tao <tsl0922@gmail.com>
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
FROM node:6.9
|
||||
FROM node:6
|
||||
MAINTAINER Paris Kasidiaris <paris@sourcelair.com>
|
||||
|
||||
# Set the working directory
|
||||
@@ -6,7 +6,7 @@ WORKDIR /usr/src/app
|
||||
|
||||
# Set an entrypoint, to automatically install node modules
|
||||
ENTRYPOINT ["/bin/bash", "-c", "if [[ ! -d node_modules ]]; then npm install; fi; exec \"${@:0}\";"]
|
||||
CMD ["npm", "run", "dev"]
|
||||
CMD ["npm", "run", "start"]
|
||||
|
||||
# First, install dependencies to improve layer caching
|
||||
COPY package.json /usr/src/app/
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
web: npm run dev
|
||||
@@ -1,6 +1,6 @@
|
||||
# [](https://xtermjs.org)
|
||||
|
||||
[](https://travis-ci.org/sourcelair/xterm.js) [](https://coveralls.io/github/sourcelair/xterm.js) [](https://gitter.im/sourcelair/xterm.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [](https://www.jsdelivr.com/package/npm/xterm)
|
||||
[](https://travis-ci.org/xtermjs/xterm.js) [](https://coveralls.io/github/sourcelair/xterm.js) [](https://gitter.im/sourcelair/xterm.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [](https://www.jsdelivr.com/package/npm/xterm)
|
||||
|
||||
Xterm.js is a terminal front-end component written in JavaScript that works in the browser.
|
||||
|
||||
@@ -49,50 +49,33 @@ To start using xterm.js on your browser, add the `xterm.js` and `xterm.css` to t
|
||||
|
||||
Finally instantiate the `Terminal` object and then call the `open` function with the DOM object of the `div`.
|
||||
|
||||
### Addons
|
||||
|
||||
Addons are JavaScript modules that attach functions to the `Terminal` prototype to extend its functionality. There are a handful available in the main repository in the `dist/addons` directory, you can even write your own (though they may break when the internals of xterm.js change across versions).
|
||||
|
||||
To use an addon, just include the JavaScript file after xterm.js and before the `Terminal` object has been instantiated. The function should then be exposed on the `Terminal` object:
|
||||
|
||||
```html
|
||||
<script src="node_modules/xterm/dist/xterm.js"></script>
|
||||
<script src="node_modules/xterm/dist/addons/fit/fit.js"></script>
|
||||
```
|
||||
|
||||
```js
|
||||
// Instantiate the terminal and call fit
|
||||
var xterm = new Terminal();
|
||||
xterm.fit();
|
||||
```
|
||||
|
||||
### Importing
|
||||
|
||||
If the environment allows it, you can import xterm.js like so:
|
||||
The proposed way to load xterm.js is via the ES6 module syntax.
|
||||
|
||||
```ts
|
||||
// CommonJS
|
||||
var Terminal = require('xterm').Terminal;
|
||||
|
||||
// ES6 / TypeScript
|
||||
```javascript
|
||||
import { Terminal } from 'xterm';
|
||||
```
|
||||
|
||||
Importing addons in this environment can be done using a `Terminal.loadAddon` call:
|
||||
*Note: There are currently no typings for addons so you will need to upcast if using TypeScript, eg. `(<any>xterm).fit()`.*
|
||||
|
||||
```ts
|
||||
import { Terminal } from 'xterm';
|
||||
### Addons
|
||||
|
||||
// Notice it's called statically on the type, not an object
|
||||
Terminal.loadAddon('fit');
|
||||
Addons are JavaScript modules that extend the `Terminal` prototype with new methods and attributes to provide additional functionality. There are a handful available in the main repository in the `src/addons` directory and you can even write your own, by using xterm.js' public API.
|
||||
|
||||
// Instantiate the terminal and call fit
|
||||
var xterm = new Terminal();
|
||||
xterm.fit();
|
||||
To use an addon, just import the JavaScript module and pass it to `Terminal`'s `applyAddon` method:
|
||||
|
||||
```javascript
|
||||
import { Terminal } from xterm;
|
||||
import * as fit from 'xterm/lib/addons/fit/fit';
|
||||
|
||||
|
||||
Terminal.applyAddon(fit);
|
||||
|
||||
var xterm = new Terminal(); // Instantiate the terminal
|
||||
xterm.fit(); // Use the `fit` method, provided by the `fit` addon
|
||||
```
|
||||
|
||||
*Note: There are currently no typings for addons so you will need to upcast if using TypeScript, eg. `(<any>xterm).fit()`*
|
||||
|
||||
## Browser Support
|
||||
|
||||
Since xterm.js is typically implemented as a developer tool, only modern browsers are supported officially. Here is a list of the versions we aim to support:
|
||||
@@ -131,6 +114,11 @@ Xterm.js is used in several world-class applications to provide great terminal e
|
||||
computational environment for Jupyter, supporting interactive data science and scientific computing across all programming languages.
|
||||
- [**Theia**](https://github.com/theia-ide/theia): Theia is a cloud & desktop IDE framework implemented in TypeScript.
|
||||
- [**Opshell**](https://github.com/ricktbaker/opshell) Ops Helper tool to make life easier working with AWS instances across multiple organizations.
|
||||
- [**Proxmox VE**](https://www.proxmox.com/en/proxmox-ve): Proxmox VE is a complete open-source platform for enterprise virtualization. It uses xterm.js for container terminals and the host shell.
|
||||
- [**Script Runner**](https://github.com/ioquatix/script-runner): Run scripts (or a shell) in Atom.
|
||||
- [**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.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
+6
-2
@@ -17,8 +17,12 @@ app.get('/style.css', function(req, res){
|
||||
res.sendFile(__dirname + '/style.css');
|
||||
});
|
||||
|
||||
app.get('/main.js', function(req, res){
|
||||
res.sendFile(__dirname + '/main.js');
|
||||
app.get('/dist/bundle.js', function(req, res){
|
||||
res.sendFile(__dirname + '/dist/bundle.js');
|
||||
});
|
||||
|
||||
app.get('/dist/bundle.js.map', function(req, res){
|
||||
res.sendFile(__dirname + '/dist/bundle.js.map');
|
||||
});
|
||||
|
||||
app.post('/terminals', function (req, res) {
|
||||
|
||||
+1
-7
@@ -7,12 +7,6 @@
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-promise/4.1.1/es6-promise.auto.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/fetch/1.0.0/fetch.min.js"></script>
|
||||
<script src="/build/xterm.js" ></script>
|
||||
<script src="/build/addons/attach/attach.js" ></script>
|
||||
<script src="/build/addons/fit/fit.js" ></script>
|
||||
<script src="/build/addons/fullscreen/fullscreen.js" ></script>
|
||||
<script src="/build/addons/search/search.js" ></script>
|
||||
<script src="/build/addons/winptyCompat/winptyCompat.js" ></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>xterm.js: xterm, in the browser</h1>
|
||||
@@ -71,6 +65,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<p><strong>Attention:</strong> The demo is a barebones implementation and is designed for xterm.js evaluation purposes only. Exposing the demo to the public as is would introduce security risks for the host.</p>
|
||||
<script src="main.js" defer ></script>
|
||||
<script src="dist/bundle.js" defer ></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+23
-6
@@ -1,3 +1,18 @@
|
||||
import * as Terminal from '../build/xterm';
|
||||
import * as attach from '../build/addons/attach/attach';
|
||||
import * as fit from '../build/addons/fit/fit';
|
||||
import * as fullscreen from '../build/addons/fullscreen/fullscreen';
|
||||
import * as search from '../build/addons/search/search';
|
||||
import * as winptyCompat from '../build/addons/winptyCompat/winptyCompat';
|
||||
|
||||
|
||||
Terminal.applyAddon(attach);
|
||||
Terminal.applyAddon(fit);
|
||||
Terminal.applyAddon(fullscreen);
|
||||
Terminal.applyAddon(search);
|
||||
Terminal.applyAddon(winptyCompat);
|
||||
|
||||
|
||||
var term,
|
||||
protocol,
|
||||
socketURL,
|
||||
@@ -24,8 +39,8 @@ function setTerminalSize() {
|
||||
var rows = parseInt(rowsElement.value, 10);
|
||||
var viewportElement = document.querySelector('.xterm-viewport');
|
||||
var scrollBarWidth = viewportElement.offsetWidth - viewportElement.clientWidth;
|
||||
var width = (cols * term.charMeasure.width + 20 /*room for scrollbar*/).toString() + 'px';
|
||||
var height = (rows * term.charMeasure.height).toString() + 'px';
|
||||
var width = (cols * term.renderer.dimensions.actualCellWidth + 20 /*room for scrollbar*/).toString() + 'px';
|
||||
var height = (rows * term.renderer.dimensions.actualCellHeight).toString() + 'px';
|
||||
|
||||
terminalContainer.style.width = width;
|
||||
terminalContainer.style.height = height;
|
||||
@@ -76,6 +91,7 @@ function createTerminal() {
|
||||
scrollback: parseInt(optionElements.scrollback.value, 10),
|
||||
tabStopWidth: parseInt(optionElements.tabstopwidth.value, 10)
|
||||
});
|
||||
window.term = term; // Expose `term` to window for debugging purposes
|
||||
term.on('resize', function (size) {
|
||||
if (!pid) {
|
||||
return;
|
||||
@@ -90,8 +106,9 @@ function createTerminal() {
|
||||
socketURL = protocol + location.hostname + ((location.port) ? (':' + location.port) : '') + '/terminals/';
|
||||
|
||||
term.open(terminalContainer);
|
||||
term.fit();
|
||||
term.winptyCompatInit();
|
||||
term.fit();
|
||||
term.focus();
|
||||
|
||||
// fit is called within a setTimeout, cols and rows need this.
|
||||
setTimeout(function () {
|
||||
@@ -103,9 +120,9 @@ function createTerminal() {
|
||||
|
||||
fetch('/terminals?cols=' + term.cols + '&rows=' + term.rows, {method: 'POST'}).then(function (res) {
|
||||
|
||||
res.text().then(function (pid) {
|
||||
window.pid = pid;
|
||||
socketURL += pid;
|
||||
res.text().then(function (processId) {
|
||||
pid = processId;
|
||||
socketURL += processId;
|
||||
socket = new WebSocket(socketURL);
|
||||
socket.onopen = runRealTerminal;
|
||||
socket.onclose = runFakeTerminal;
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
version: '2'
|
||||
|
||||
services:
|
||||
web:
|
||||
build: ./
|
||||
volumes:
|
||||
- ./:/usr/src/app
|
||||
ports:
|
||||
- 3000:3000
|
||||
@@ -0,0 +1,9 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
web:
|
||||
build: .
|
||||
volumes:
|
||||
- ./:/usr/src/app
|
||||
ports:
|
||||
- ${XTERMJS_PORT:3000}:3000
|
||||
@@ -36,12 +36,12 @@ namespace properties {
|
||||
|
||||
namespace static_methods {
|
||||
{
|
||||
Terminal.loadAddon('attach');
|
||||
Terminal.loadAddon('fit');
|
||||
Terminal.loadAddon('fullscreen');
|
||||
Terminal.loadAddon('search');
|
||||
Terminal.loadAddon('terminado');
|
||||
Terminal.loadAddon('winptyCompat');
|
||||
Terminal.applyAddon({});
|
||||
Terminal.applyAddon({});
|
||||
Terminal.applyAddon({});
|
||||
Terminal.applyAddon({});
|
||||
Terminal.applyAddon({});
|
||||
Terminal.applyAddon({});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace methods_core {
|
||||
// no arg
|
||||
t.on('blur', () => {});
|
||||
t.on('focus', () => {});
|
||||
t.on('lineFeed', () => {});
|
||||
t.on('linefeed', () => {});
|
||||
t.on('selection', () => {});
|
||||
// args
|
||||
t.on('data', () => {});
|
||||
@@ -89,7 +89,7 @@ namespace methods_core {
|
||||
// no arg
|
||||
t.off('blur', () => {});
|
||||
t.off('focus', () => {});
|
||||
t.off('lineFeed', () => {});
|
||||
t.off('linefeed', () => {});
|
||||
t.off('selection', () => {});
|
||||
// args
|
||||
t.off('data', () => {});
|
||||
@@ -172,9 +172,9 @@ namespace methods_core {
|
||||
t.setOption('handler', (data: string) => console.log(data));
|
||||
t.setOption('bellSound', 'foo');
|
||||
t.setOption('bellStyle', 'none');
|
||||
t.setOption('bellStyle', 'visual');
|
||||
// t.setOption('bellStyle', 'visual');
|
||||
t.setOption('bellStyle', 'sound');
|
||||
t.setOption('bellStyle', 'both');
|
||||
// t.setOption('bellStyle', 'both');
|
||||
t.setOption('fontSize', 1);
|
||||
t.setOption('lineHeight', 1);
|
||||
t.setOption('fontFamily', 'foo');
|
||||
|
||||
+23
-18
@@ -16,6 +16,7 @@ const source = require('vinyl-source-stream');
|
||||
const sourcemaps = require('gulp-sourcemaps');
|
||||
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');
|
||||
@@ -44,30 +45,31 @@ gulp.task('tsc', function () {
|
||||
tsResult.dts.pipe(sourcemaps.write('.', {includeContent: false, sourceRoot: ''})).pipe(gulp.dest(outDir))
|
||||
);
|
||||
|
||||
fs.emptyDirSync(`${outDir}/addons/search`);
|
||||
fs.emptyDirSync(`${outDir}/addons/winptyCompat`);
|
||||
let addons = ['attach', 'fit', 'fullscreen', 'search', 'terminado', 'winptyCompat', 'zmodem'];
|
||||
let addonStreams = addons.map(function(addon) {
|
||||
fs.emptyDirSync(`${outDir}/addons/${addon}`);
|
||||
|
||||
let tsProjectSearchAddon = ts.createProject('./src/addons/search/tsconfig.json');
|
||||
let tsResultSearchAddon = tsProjectSearchAddon.src().pipe(sourcemaps.init()).pipe(tsProjectSearchAddon());
|
||||
let tscSearchAddon = tsResultSearchAddon.js.pipe(sourcemaps.write('.', {includeContent: false, sourceRoot: ''})).pipe(gulp.dest(`${outDir}/addons/search`));
|
||||
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 tsProjectWinptyCompatAddon = ts.createProject('./src/addons/winptyCompat/tsconfig.json');
|
||||
let tsResultWinptyCompatAddon = tsProjectWinptyCompatAddon.src().pipe(sourcemaps.init()).pipe(tsProjectWinptyCompatAddon());
|
||||
let tscWinptyCompatAddon = tsResultWinptyCompatAddon.js.pipe(sourcemaps.write('.', {includeContent: false, sourceRoot: ''})).pipe(gulp.dest(`${outDir}/addons/winptyCompat`));
|
||||
return tscAddon;
|
||||
});
|
||||
|
||||
// Copy all addons from ${srcDir}/ to ${outDir}/
|
||||
let copyAddons = gulp.src([
|
||||
`${srcDir}/addons/**/*`,
|
||||
`!${srcDir}/addons/search`,
|
||||
`!${srcDir}/addons/search/**`,
|
||||
`!${srcDir}/addons/winptyCompat`,
|
||||
`!${srcDir}/addons/winptyCompat/**`
|
||||
`${srcDir}/addons/**/**`
|
||||
]).pipe(gulp.dest(`${outDir}/addons`));
|
||||
|
||||
// Copy stylesheets from ${srcDir}/ to ${outDir}/
|
||||
let copyStylesheets = gulp.src(`${srcDir}/**/*.css`).pipe(gulp.dest(outDir));
|
||||
|
||||
return merge(tsc, tscSearchAddon, tscWinptyCompatAddon, copyAddons, copyStylesheets);
|
||||
// Join all streams into a single array
|
||||
let streams = [tsc].concat(addonStreams).concat([copyAddons, copyStylesheets]);
|
||||
|
||||
return merge.apply(this, streams);
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -136,10 +138,7 @@ gulp.task('browserify-addons', ['tsc'], function() {
|
||||
// Copy all add-ons from outDir to buildDir
|
||||
let copyAddons = gulp.src([
|
||||
// Copy JS addons
|
||||
`${outDir}/addons/**/*`,
|
||||
// Exclude TS addons from copy as they are being built via browserify
|
||||
`!${outDir}/addons/search`,
|
||||
`!${outDir}/addons/search/**`,
|
||||
`${outDir}/addons/**/*`
|
||||
]).pipe(gulp.dest(`${buildDir}/addons`));
|
||||
|
||||
return merge(searchBundle, winptyCompatBundle, copyAddons);
|
||||
@@ -195,6 +194,12 @@ gulp.task('sorcery-addons', ['browserify-addons'], function () {
|
||||
chain.writeSync();
|
||||
});
|
||||
|
||||
gulp.task('webpack', ['build'], function() {
|
||||
return gulp.src('demo/main.js')
|
||||
.pipe(webpack(require('./webpack.config.js')))
|
||||
.pipe(gulp.dest('demo/dist/'));
|
||||
});
|
||||
|
||||
/**
|
||||
* Submit coverage results to coveralls.io
|
||||
*/
|
||||
|
||||
Generated
+122
-23
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xterm",
|
||||
"version": "2.8.1",
|
||||
"version": "2.9.1",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -44,6 +44,12 @@
|
||||
"integrity": "sha512-7F3/P6MkTPA0QxOstRqfcnoReCUy5V/QG92cyBoZSPnqdX44L8TtNELSVfN56gAttm3YWj9cEi8FRIPVq0WmeQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/text-encoding": {
|
||||
"version": "0.0.32",
|
||||
"resolved": "https://registry.npmjs.org/@types/text-encoding/-/text-encoding-0.0.32.tgz",
|
||||
"integrity": "sha512-kQ79aFmYcD/DR3QKo6wXyvNrKi7PunY0KYTBUhHjHl0SXwWuLRl9Leh73YtnsSJMBi9qSiK+fxWhdJNQPbhc9A==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/tough-cookie": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.0.tgz",
|
||||
@@ -555,12 +561,29 @@
|
||||
"integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=",
|
||||
"dev": true
|
||||
},
|
||||
"clone-buffer": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz",
|
||||
"integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=",
|
||||
"dev": true
|
||||
},
|
||||
"clone-stats": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz",
|
||||
"integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=",
|
||||
"dev": true
|
||||
},
|
||||
"cloneable-readable": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz",
|
||||
"integrity": "sha1-pikNQT8hemEjL5XkWP84QYz7ARc=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"inherits": "2.0.3",
|
||||
"process-nextick-args": "1.0.7",
|
||||
"through2": "2.0.3"
|
||||
}
|
||||
},
|
||||
"combine-source-map": {
|
||||
"version": "0.7.2",
|
||||
"resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.7.2.tgz",
|
||||
@@ -620,6 +643,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"concat-with-sourcemaps": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.4.tgz",
|
||||
"integrity": "sha1-9Vs74q60dgGxCi1SWcz7cP0vHdY=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"source-map": "0.5.6"
|
||||
}
|
||||
},
|
||||
"console-browserify": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
|
||||
@@ -662,6 +694,16 @@
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
|
||||
"dev": true
|
||||
},
|
||||
"crc-32": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.1.1.tgz",
|
||||
"integrity": "sha1-XXOdXkxuNSrYME1zIj1IP+Va240=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"exit-on-epipe": "1.0.1",
|
||||
"printj": "1.1.0"
|
||||
}
|
||||
},
|
||||
"create-ecdh": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz",
|
||||
@@ -1021,6 +1063,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"exit-on-epipe": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz",
|
||||
"integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==",
|
||||
"dev": true
|
||||
},
|
||||
"express": {
|
||||
"version": "4.13.4",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.13.4.tgz",
|
||||
@@ -4190,6 +4238,51 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"gulp-concat": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz",
|
||||
"integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"concat-with-sourcemaps": "1.0.4",
|
||||
"through2": "2.0.3",
|
||||
"vinyl": "2.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"clone": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz",
|
||||
"integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=",
|
||||
"dev": true
|
||||
},
|
||||
"clone-stats": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz",
|
||||
"integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=",
|
||||
"dev": true
|
||||
},
|
||||
"replace-ext": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz",
|
||||
"integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=",
|
||||
"dev": true
|
||||
},
|
||||
"vinyl": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz",
|
||||
"integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"clone": "2.1.1",
|
||||
"clone-buffer": "1.0.0",
|
||||
"clone-stats": "1.0.0",
|
||||
"cloneable-readable": "1.0.0",
|
||||
"remove-trailing-separator": "1.0.2",
|
||||
"replace-ext": "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"gulp-coveralls": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/gulp-coveralls/-/gulp-coveralls-0.1.4.tgz",
|
||||
@@ -9519,28 +9612,19 @@
|
||||
"duplexer2": "0.0.2"
|
||||
}
|
||||
},
|
||||
"nan": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz",
|
||||
"integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=",
|
||||
"dev": true
|
||||
},
|
||||
"node-pty": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/node-pty/-/node-pty-0.4.1.tgz",
|
||||
"integrity": "sha1-qAs1/le2TwVasZsteqYE2DYVXAQ=",
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/node-pty/-/node-pty-0.7.3.tgz",
|
||||
"integrity": "sha1-S7NqJKYu6fMzLi4jENZkLZ2u0fc=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"extend": "1.2.1",
|
||||
"nan": "2.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"extend": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-1.2.1.tgz",
|
||||
"integrity": "sha1-oPX9bPyDpf5J72mNYOyKYk3UV2w=",
|
||||
"dev": true
|
||||
},
|
||||
"nan": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.2.1.tgz",
|
||||
"integrity": "sha1-1oaT9rNLtB1mvGizpPne/HnXFJs=",
|
||||
"dev": true
|
||||
}
|
||||
"nan": "2.8.0"
|
||||
}
|
||||
},
|
||||
"nodemon": {
|
||||
@@ -10899,6 +10983,12 @@
|
||||
"integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
|
||||
"dev": true
|
||||
},
|
||||
"printj": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/printj/-/printj-1.1.0.tgz",
|
||||
"integrity": "sha512-NbiNBOQ0GioHyeD3ni8wZB7ZmfU7mxIrqhWR5XSreX3rUVvk5UOwpzxOnWqrLdCtoBbdQ40sEwC+nXxxjlUo0A==",
|
||||
"dev": true
|
||||
},
|
||||
"process": {
|
||||
"version": "0.11.10",
|
||||
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
||||
@@ -12271,9 +12361,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"typescript": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-2.2.2.tgz",
|
||||
"integrity": "sha1-YGAiUIR5tV/6NotY/uljoD39eww=",
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-2.4.2.tgz",
|
||||
"integrity": "sha1-+DlfhdRZJ2BnyYiqQYN6j4KHCEQ=",
|
||||
"dev": true
|
||||
},
|
||||
"umd": {
|
||||
@@ -12547,6 +12637,15 @@
|
||||
"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",
|
||||
"integrity": "sha1-QNeLS0uYQiBo5CB5II/wgFcLrdk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"crc-32": "1.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-6
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "xterm",
|
||||
"description": "Full xterm terminal, in your browser",
|
||||
"version": "2.9.1",
|
||||
"version": "3.0.0",
|
||||
"ignore": [
|
||||
"demo",
|
||||
"test",
|
||||
@@ -9,7 +9,7 @@
|
||||
],
|
||||
"main": "lib/Terminal.js",
|
||||
"types": "typings/xterm.d.ts",
|
||||
"repository": "https://github.com/sourcelair/xterm.js",
|
||||
"repository": "https://github.com/xtermjs/xterm.js",
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
"*.js",
|
||||
@@ -35,13 +35,15 @@
|
||||
"src/*.ts",
|
||||
"src/**/*.js",
|
||||
"src/**/*.js.map",
|
||||
"src/**/*.ts"
|
||||
"src/**/*.ts",
|
||||
"typings/*.d.ts"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@types/chai": "^3.4.34",
|
||||
"@types/jsdom": "^11.0.1",
|
||||
"@types/mocha": "^2.2.33",
|
||||
"@types/node": "^6.0.41",
|
||||
"@types/text-encoding": "0.0.32",
|
||||
"browserify": "^13.3.0",
|
||||
"chai": "3.5.0",
|
||||
"docdash": "0.4.0",
|
||||
@@ -68,20 +70,22 @@
|
||||
"typescript": "~2.4.0",
|
||||
"vinyl-buffer": "^1.0.0",
|
||||
"vinyl-source-stream": "^1.1.0",
|
||||
"webpack": "^3.10.0",
|
||||
"webpack-stream": "^4.0.0",
|
||||
"zmodem.js": "^0.1.5"
|
||||
},
|
||||
"scripts": {
|
||||
"prestart": "npm run build",
|
||||
"prestart": "gulp webpack",
|
||||
"start": "node demo/app",
|
||||
"prestart-zmodem": "npm run build",
|
||||
"start-zmodem": "node build/addons/zmodem/demo/app",
|
||||
"dev": "nodemon -e js,ts,css --watch src --watch demo --exec npm start",
|
||||
"lint": "tslint src/*.ts src/**/*.ts",
|
||||
"test": "gulp test",
|
||||
"build:docs": "jsdoc -c jsdoc.json",
|
||||
"build": "gulp build",
|
||||
"prepublish": "npm run build",
|
||||
"coveralls": "gulp coveralls"
|
||||
"coveralls": "gulp coveralls",
|
||||
"webpack": "gulp webpack"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
|
||||
+2
-2
@@ -134,9 +134,9 @@ export class InputHandler implements IInputHandler {
|
||||
/**
|
||||
* This event is emitted whenever the terminal outputs a LF or NL.
|
||||
*
|
||||
* @event lineFeed
|
||||
* @event linefeed
|
||||
*/
|
||||
this._terminal.emit('lineFeed');
|
||||
this._terminal.emit('linefeed');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,6 +14,10 @@ import { BufferSet } from './BufferSet';
|
||||
import { MockTerminal } from './utils/TestUtils.test';
|
||||
import { LineData, CharData } from './Types';
|
||||
|
||||
class TestMockTerminal extends MockTerminal {
|
||||
emit(event: string, data: any): void {}
|
||||
}
|
||||
|
||||
class TestSelectionManager extends SelectionManager {
|
||||
constructor(
|
||||
terminal: ITerminal,
|
||||
@@ -48,7 +52,7 @@ describe('SelectionManager', () => {
|
||||
dom = new jsdom.JSDOM('');
|
||||
window = dom.window;
|
||||
document = window.document;
|
||||
terminal = new MockTerminal();
|
||||
terminal = new TestMockTerminal();
|
||||
terminal.cols = 80;
|
||||
terminal.rows = 2;
|
||||
terminal.options.scrollback = 100;
|
||||
|
||||
@@ -255,7 +255,7 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
|
||||
public selectAll(): void {
|
||||
this._model.isSelectAllActive = true;
|
||||
this.refresh();
|
||||
this.emit('selection');
|
||||
this._terminal.emit('selection');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -528,7 +528,7 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
|
||||
this._terminal.scrollLines(this._dragScrollAmount, false);
|
||||
// Re-evaluate selection
|
||||
if (this._dragScrollAmount > 0) {
|
||||
this._model.selectionEnd = [this._terminal.cols - 1, this._terminal.buffer.ydisp + this._terminal.rows];
|
||||
this._model.selectionEnd = [this._terminal.cols - 1, Math.min(this._terminal.buffer.ydisp + this._terminal.rows, this._terminal.buffer.lines.length - 1)];
|
||||
} else {
|
||||
this._model.selectionEnd = [0, this._terminal.buffer.ydisp];
|
||||
}
|
||||
@@ -544,7 +544,7 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
|
||||
this._removeMouseDownListeners();
|
||||
|
||||
if (this.hasSelection)
|
||||
this.emit('selection');
|
||||
this._terminal.emit('selection');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { assert, expect } from 'chai';
|
||||
import { assert, expect } from 'chai';
|
||||
import { Terminal } from './Terminal';
|
||||
import * as attach from './addons/attach/attach';
|
||||
import { MockViewport, MockCompositionHelper, MockRenderer } from './utils/TestUtils.test';
|
||||
import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX } from './Buffer';
|
||||
|
||||
@@ -42,9 +43,9 @@ describe('term.js addons', () => {
|
||||
};
|
||||
});
|
||||
|
||||
it('should load addons with Terminal.loadAddon', () => {
|
||||
Terminal.loadAddon('attach');
|
||||
// Test that addon was loaded successfully, adding attach to Terminal's
|
||||
it('should apply addons with Terminal.applyAddon', () => {
|
||||
Terminal.applyAddon(attach);
|
||||
// Test that addon was applied successfully, adding attach to Terminal's
|
||||
// prototype.
|
||||
assert.equal(typeof (<any>Terminal).prototype.attach, 'function');
|
||||
});
|
||||
|
||||
+29
-32
@@ -47,12 +47,6 @@ import { MouseZoneManager } from './input/MouseZoneManager';
|
||||
import { initialize as initializeCharAtlas } from './renderer/CharAtlas';
|
||||
import { IRenderer } from './renderer/Interfaces';
|
||||
|
||||
// Declares required for loadAddon
|
||||
declare var exports: any;
|
||||
declare var module: any;
|
||||
declare var define: any;
|
||||
declare var require: any;
|
||||
|
||||
// Let it work inside Node.js for automated testing purposes.
|
||||
const document = (typeof window !== 'undefined') ? window.document : null;
|
||||
|
||||
@@ -323,7 +317,9 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
|
||||
* Focus the terminal. Delegates focus handling to the terminal's DOM element.
|
||||
*/
|
||||
public focus(): void {
|
||||
this.textarea.focus();
|
||||
if (this.textarea) {
|
||||
this.textarea.focus();
|
||||
}
|
||||
}
|
||||
|
||||
public get isFocused(): boolean {
|
||||
@@ -585,19 +581,19 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
|
||||
this.element = this.document.createElement('div');
|
||||
this.element.classList.add('terminal');
|
||||
this.element.classList.add('xterm');
|
||||
|
||||
this.element.setAttribute('tabindex', '0');
|
||||
this.parent.appendChild(this.element);
|
||||
|
||||
// Performance: Use a document fragment to build the terminal
|
||||
// viewport and helper elements detached from the DOM
|
||||
const fragment = document.createDocumentFragment();
|
||||
this.viewportElement = document.createElement('div');
|
||||
this.viewportElement.classList.add('xterm-viewport');
|
||||
this.element.appendChild(this.viewportElement);
|
||||
fragment.appendChild(this.viewportElement);
|
||||
this.viewportScrollArea = document.createElement('div');
|
||||
this.viewportScrollArea.classList.add('xterm-scroll-area');
|
||||
this.viewportElement.appendChild(this.viewportScrollArea);
|
||||
|
||||
// preload audio
|
||||
this.syncBellSound();
|
||||
|
||||
this._mouseZoneManager = new MouseZoneManager(this);
|
||||
this.on('scroll', () => this._mouseZoneManager.clearAll());
|
||||
this.linkifier.attachToDom(this._mouseZoneManager);
|
||||
@@ -606,8 +602,8 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
|
||||
// capturing DOM Events. Then produce the helpers.
|
||||
this.helperContainer = document.createElement('div');
|
||||
this.helperContainer.classList.add('xterm-helpers');
|
||||
// TODO: This should probably be inserted once it's filled to prevent an additional layout
|
||||
this.element.appendChild(this.helperContainer);
|
||||
fragment.appendChild(this.helperContainer);
|
||||
|
||||
this.textarea = document.createElement('textarea');
|
||||
this.textarea.classList.add('xterm-helper-textarea');
|
||||
this.textarea.setAttribute('autocorrect', 'off');
|
||||
@@ -625,11 +621,14 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
|
||||
|
||||
this.charSizeStyleElement = document.createElement('style');
|
||||
this.helperContainer.appendChild(this.charSizeStyleElement);
|
||||
|
||||
this.parent.appendChild(this.element);
|
||||
|
||||
this.charMeasure = new CharMeasure(document, this.helperContainer);
|
||||
|
||||
// Preload audio, this relied on helperContainer
|
||||
this.syncBellSound();
|
||||
|
||||
// Performance: Add viewport and helper elements from the fragment
|
||||
this.element.appendChild(fragment);
|
||||
|
||||
this.renderer = new Renderer(this, this.options.theme);
|
||||
this.options.theme = null;
|
||||
this.viewport = new Viewport(this, this.viewportElement, this.viewportScrollArea, this.charMeasure);
|
||||
@@ -674,6 +673,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
|
||||
// Listen for mouse events and translate
|
||||
// them into terminal mouse protocols.
|
||||
this.bindMouse();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -688,22 +688,11 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to load an add-on using CommonJS or RequireJS (whichever is available).
|
||||
* @param {string} addon The name of the addon to load
|
||||
* @static
|
||||
* Apply the provided addon on the `Terminal` class.
|
||||
* @param addon The addon to apply.
|
||||
*/
|
||||
public static loadAddon(addon: string, callback?: Function): boolean | any {
|
||||
// TODO: Improve return type and documentation
|
||||
if (typeof exports === 'object' && typeof module === 'object') {
|
||||
// CommonJS
|
||||
return require('./addons/' + addon + '/' + addon);
|
||||
} else if (typeof define === 'function') {
|
||||
// RequireJS
|
||||
return (<any>require)(['./addons/' + addon + '/' + addon], callback);
|
||||
} else {
|
||||
console.error('Cannot load a module without a CommonJS or RequireJS environment.');
|
||||
return false;
|
||||
}
|
||||
public static applyAddon(addon: any): void {
|
||||
addon.apply(Terminal);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1461,6 +1450,9 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
|
||||
if (ev.shiftKey) {
|
||||
result.key = C0.BS; // ^H
|
||||
break;
|
||||
} else if (ev.altKey) {
|
||||
result.key = C0.ESC + C0.DEL; // \e ^?
|
||||
break;
|
||||
}
|
||||
result.key = C0.DEL; // ^?
|
||||
break;
|
||||
@@ -2128,6 +2120,11 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
|
||||
}
|
||||
|
||||
private syncBellSound(): void {
|
||||
// Don't update anything if the terminal has not been opened yet
|
||||
if (!this.element) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.soundBell() && this.bellAudioElement) {
|
||||
this.bellAudioElement.setAttribute('src', this.options.bellSound);
|
||||
} else if (this.soundBell()) {
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*
|
||||
* Implements the attach method, that attaches the terminal to a WebSocket stream.
|
||||
*/
|
||||
|
||||
(function (attach) {
|
||||
if (typeof exports === 'object' && typeof module === 'object') {
|
||||
/*
|
||||
* CommonJS environment
|
||||
*/
|
||||
module.exports = attach(require('../../Terminal').Terminal);
|
||||
} else if (typeof define == 'function') {
|
||||
/*
|
||||
* Require.js is available
|
||||
*/
|
||||
define(['../../xterm'], attach);
|
||||
} else {
|
||||
/*
|
||||
* Plain browser environment
|
||||
*/
|
||||
attach(window.Terminal);
|
||||
}
|
||||
})(function (Terminal) {
|
||||
'use strict';
|
||||
|
||||
var exports = {};
|
||||
|
||||
/**
|
||||
* Attaches the given terminal to the given socket.
|
||||
*
|
||||
* @param {Terminal} term - The terminal to be attached to the given socket.
|
||||
* @param {WebSocket} socket - The socket to attach the current terminal.
|
||||
* @param {boolean} bidirectional - Whether the terminal should send data
|
||||
* to the socket as well.
|
||||
* @param {boolean} buffered - Whether the rendering of incoming data
|
||||
* should happen instantly or at a maximum
|
||||
* frequency of 1 rendering per 10ms.
|
||||
*/
|
||||
exports.attach = function (term, socket, bidirectional, buffered) {
|
||||
bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional;
|
||||
term.socket = socket;
|
||||
|
||||
term._flushBuffer = function () {
|
||||
term.write(term._attachSocketBuffer);
|
||||
term._attachSocketBuffer = null;
|
||||
};
|
||||
|
||||
term._pushToBuffer = function (data) {
|
||||
if (term._attachSocketBuffer) {
|
||||
term._attachSocketBuffer += data;
|
||||
} else {
|
||||
term._attachSocketBuffer = data;
|
||||
setTimeout(term._flushBuffer, 10);
|
||||
}
|
||||
};
|
||||
|
||||
var myTextDecoder;
|
||||
|
||||
term._getMessage = function (ev) {
|
||||
var 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?";
|
||||
}
|
||||
}
|
||||
|
||||
if (buffered) {
|
||||
term._pushToBuffer(str || ev.data);
|
||||
} else {
|
||||
term.write(str || ev.data);
|
||||
}
|
||||
};
|
||||
|
||||
term._sendData = function (data) {
|
||||
socket.send(data);
|
||||
};
|
||||
|
||||
socket.addEventListener('message', term._getMessage);
|
||||
|
||||
if (bidirectional) {
|
||||
term.on('data', term._sendData);
|
||||
}
|
||||
|
||||
socket.addEventListener('close', term.detach.bind(term, socket));
|
||||
socket.addEventListener('error', term.detach.bind(term, socket));
|
||||
};
|
||||
|
||||
/**
|
||||
* Detaches the given terminal from the given socket
|
||||
*
|
||||
* @param {Terminal} term - The terminal to be detached from the given socket.
|
||||
* @param {WebSocket} socket - The socket from which to detach the current
|
||||
* terminal.
|
||||
*/
|
||||
exports.detach = function (term, socket) {
|
||||
term.off('data', term._sendData);
|
||||
|
||||
socket = (typeof socket == 'undefined') ? term.socket : socket;
|
||||
|
||||
if (socket) {
|
||||
socket.removeEventListener('message', term._getMessage);
|
||||
}
|
||||
|
||||
delete term.socket;
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaches the current terminal to the given socket
|
||||
*
|
||||
* @param {WebSocket} socket - The socket to attach the current terminal.
|
||||
* @param {boolean} bidirectional - Whether the terminal should send data
|
||||
* to the socket as well.
|
||||
* @param {boolean} buffered - Whether the rendering of incoming data
|
||||
* should happen instantly or at a maximum
|
||||
* frequency of 1 rendering per 10ms.
|
||||
*/
|
||||
Terminal.prototype.attach = function (socket, bidirectional, buffered) {
|
||||
return exports.attach(this, socket, bidirectional, buffered);
|
||||
};
|
||||
|
||||
/**
|
||||
* Detaches the current terminal from the given socket.
|
||||
*
|
||||
* @param {WebSocket} socket - The socket from which to detach the current
|
||||
* terminal.
|
||||
*/
|
||||
Terminal.prototype.detach = function (socket) {
|
||||
return exports.detach(this, socket);
|
||||
};
|
||||
|
||||
return exports;
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user