Merge branch 'master' into feature-778

This commit is contained in:
Daniel Imms
2018-01-05 11:03:33 -08:00
committed by GitHub
63 changed files with 1855 additions and 911 deletions
+3
View File
@@ -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/
View File
+18
View File
@@ -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
View File
@@ -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
View File
@@ -1 +0,0 @@
web: npm run dev
+23 -35
View File
@@ -1,6 +1,6 @@
# [![xterm.js logo](logo.png)](https://xtermjs.org)
# [![xterm.js logo](logo-full.png)](https://xtermjs.org)
[![xterm.js build status](https://api.travis-ci.org/sourcelair/xterm.js.svg)](https://travis-ci.org/sourcelair/xterm.js) [![Coverage Status](https://coveralls.io/repos/github/sourcelair/xterm.js/badge.svg)](https://coveralls.io/github/sourcelair/xterm.js) [![Gitter](https://badges.gitter.im/sourcelair/xterm.js.svg)](https://gitter.im/sourcelair/xterm.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![jsDelivr Hits](https://data.jsdelivr.com/v1/package/npm/xterm/badge?style=rounded)](https://www.jsdelivr.com/package/npm/xterm)
[![xterm.js build status](https://api.travis-ci.org/xtermjs/xterm.js.svg)](https://travis-ci.org/xtermjs/xterm.js) [![Coverage Status](https://coveralls.io/repos/github/sourcelair/xterm.js/badge.svg)](https://coveralls.io/github/sourcelair/xterm.js) [![Gitter](https://badges.gitter.im/sourcelair/xterm.js.svg)](https://gitter.im/sourcelair/xterm.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![jsDelivr Hits](https://data.jsdelivr.com/v1/package/npm/xterm/badge?style=rounded)](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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
-9
View File
@@ -1,9 +0,0 @@
version: '2'
services:
web:
build: ./
volumes:
- ./:/usr/src/app
ports:
- 3000:3000
+9
View File
@@ -0,0 +1,9 @@
version: "3"
services:
web:
build: .
volumes:
- ./:/usr/src/app
ports:
- ${XTERMJS_PORT:3000}:3000
+12 -12
View File
@@ -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,8 @@ namespace methods_core {
// no arg
t.on('blur', () => {});
t.on('focus', () => {});
t.on('lineFeed', () => {});
t.on('linefeed', () => {});
t.on('selection', () => {});
// args
t.on('data', () => {});
t.on('data', (data: string) => console.log(data));
@@ -88,7 +89,8 @@ namespace methods_core {
// no arg
t.off('blur', () => {});
t.off('focus', () => {});
t.off('lineFeed', () => {});
t.off('linefeed', () => {});
t.off('selection', () => {});
// args
t.off('data', () => {});
t.off('data', (data: string) => console.log(data));
@@ -137,7 +139,6 @@ namespace methods_core {
const r14: number = t.getOption('rows');
const r15: number = t.getOption('tabStopWidth');
const r16: number = t.getOption('scrollback');
const r17: [number, number] = t.getOption('geometry');
const r18: (data: string) => void = t.getOption('handler');
const r19: string = t.getOption('bellSound');
const r20: string = t.getOption('bellStyle');
@@ -167,13 +168,12 @@ namespace methods_core {
t.setOption('rows', 1);
t.setOption('tabStopWidth', 1);
t.setOption('scrollback', 1);
t.setOption('geometry', [1, 1]);
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
View File
@@ -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
*/
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

+122 -23
View File
@@ -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"
}
}
}
}
+17 -8
View File
@@ -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",
@@ -51,6 +53,7 @@
"glob": "^7.0.5",
"gulp": "3.9.1",
"gulp-cli": "^1.2.2",
"gulp-concat": "^2.6.1",
"gulp-coveralls": "^0.1.4",
"gulp-istanbul": "^1.1.1",
"gulp-mocha": "^3.0.1",
@@ -66,17 +69,23 @@
"tslint": "^4.0.2",
"typescript": "~2.4.0",
"vinyl-buffer": "^1.0.0",
"vinyl-source-stream": "^1.1.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",
"dev": "nodemon -e js,ts,css --watch src --watch demo --exec npm start",
"prestart-zmodem": "npm run build",
"start-zmodem": "node build/addons/zmodem/demo/app",
"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": {}
}
+161
View File
@@ -0,0 +1,161 @@
/**
* Copyright (c) 2016 The xterm.js authors. All rights reserved.
* @license MIT
*/
export const wcwidth = (function(opts: {nul: number, control: number}): (ucs: number) => number {
// extracted from https://www.cl.cam.ac.uk/%7Emgk25/ucs/wcwidth.c
// combining characters
const COMBINING_BMP = [
[0x0300, 0x036F], [0x0483, 0x0486], [0x0488, 0x0489],
[0x0591, 0x05BD], [0x05BF, 0x05BF], [0x05C1, 0x05C2],
[0x05C4, 0x05C5], [0x05C7, 0x05C7], [0x0600, 0x0603],
[0x0610, 0x0615], [0x064B, 0x065E], [0x0670, 0x0670],
[0x06D6, 0x06E4], [0x06E7, 0x06E8], [0x06EA, 0x06ED],
[0x070F, 0x070F], [0x0711, 0x0711], [0x0730, 0x074A],
[0x07A6, 0x07B0], [0x07EB, 0x07F3], [0x0901, 0x0902],
[0x093C, 0x093C], [0x0941, 0x0948], [0x094D, 0x094D],
[0x0951, 0x0954], [0x0962, 0x0963], [0x0981, 0x0981],
[0x09BC, 0x09BC], [0x09C1, 0x09C4], [0x09CD, 0x09CD],
[0x09E2, 0x09E3], [0x0A01, 0x0A02], [0x0A3C, 0x0A3C],
[0x0A41, 0x0A42], [0x0A47, 0x0A48], [0x0A4B, 0x0A4D],
[0x0A70, 0x0A71], [0x0A81, 0x0A82], [0x0ABC, 0x0ABC],
[0x0AC1, 0x0AC5], [0x0AC7, 0x0AC8], [0x0ACD, 0x0ACD],
[0x0AE2, 0x0AE3], [0x0B01, 0x0B01], [0x0B3C, 0x0B3C],
[0x0B3F, 0x0B3F], [0x0B41, 0x0B43], [0x0B4D, 0x0B4D],
[0x0B56, 0x0B56], [0x0B82, 0x0B82], [0x0BC0, 0x0BC0],
[0x0BCD, 0x0BCD], [0x0C3E, 0x0C40], [0x0C46, 0x0C48],
[0x0C4A, 0x0C4D], [0x0C55, 0x0C56], [0x0CBC, 0x0CBC],
[0x0CBF, 0x0CBF], [0x0CC6, 0x0CC6], [0x0CCC, 0x0CCD],
[0x0CE2, 0x0CE3], [0x0D41, 0x0D43], [0x0D4D, 0x0D4D],
[0x0DCA, 0x0DCA], [0x0DD2, 0x0DD4], [0x0DD6, 0x0DD6],
[0x0E31, 0x0E31], [0x0E34, 0x0E3A], [0x0E47, 0x0E4E],
[0x0EB1, 0x0EB1], [0x0EB4, 0x0EB9], [0x0EBB, 0x0EBC],
[0x0EC8, 0x0ECD], [0x0F18, 0x0F19], [0x0F35, 0x0F35],
[0x0F37, 0x0F37], [0x0F39, 0x0F39], [0x0F71, 0x0F7E],
[0x0F80, 0x0F84], [0x0F86, 0x0F87], [0x0F90, 0x0F97],
[0x0F99, 0x0FBC], [0x0FC6, 0x0FC6], [0x102D, 0x1030],
[0x1032, 0x1032], [0x1036, 0x1037], [0x1039, 0x1039],
[0x1058, 0x1059], [0x1160, 0x11FF], [0x135F, 0x135F],
[0x1712, 0x1714], [0x1732, 0x1734], [0x1752, 0x1753],
[0x1772, 0x1773], [0x17B4, 0x17B5], [0x17B7, 0x17BD],
[0x17C6, 0x17C6], [0x17C9, 0x17D3], [0x17DD, 0x17DD],
[0x180B, 0x180D], [0x18A9, 0x18A9], [0x1920, 0x1922],
[0x1927, 0x1928], [0x1932, 0x1932], [0x1939, 0x193B],
[0x1A17, 0x1A18], [0x1B00, 0x1B03], [0x1B34, 0x1B34],
[0x1B36, 0x1B3A], [0x1B3C, 0x1B3C], [0x1B42, 0x1B42],
[0x1B6B, 0x1B73], [0x1DC0, 0x1DCA], [0x1DFE, 0x1DFF],
[0x200B, 0x200F], [0x202A, 0x202E], [0x2060, 0x2063],
[0x206A, 0x206F], [0x20D0, 0x20EF], [0x302A, 0x302F],
[0x3099, 0x309A], [0xA806, 0xA806], [0xA80B, 0xA80B],
[0xA825, 0xA826], [0xFB1E, 0xFB1E], [0xFE00, 0xFE0F],
[0xFE20, 0xFE23], [0xFEFF, 0xFEFF], [0xFFF9, 0xFFFB],
];
const COMBINING_HIGH = [
[0x10A01, 0x10A03], [0x10A05, 0x10A06], [0x10A0C, 0x10A0F],
[0x10A38, 0x10A3A], [0x10A3F, 0x10A3F], [0x1D167, 0x1D169],
[0x1D173, 0x1D182], [0x1D185, 0x1D18B], [0x1D1AA, 0x1D1AD],
[0x1D242, 0x1D244], [0xE0001, 0xE0001], [0xE0020, 0xE007F],
[0xE0100, 0xE01EF]
];
// binary search
function bisearch(ucs: number, data: number[][]): boolean {
let min = 0;
let max = data.length - 1;
let mid;
if (ucs < data[0][0] || ucs > data[max][1])
return false;
while (max >= min) {
mid = (min + max) >> 1;
if (ucs > data[mid][1])
min = mid + 1;
else if (ucs < data[mid][0])
max = mid - 1;
else
return true;
}
return false;
}
function wcwidthBMP(ucs: number): number {
// test for 8-bit control characters
if (ucs === 0)
return opts.nul;
if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
return opts.control;
// binary search in table of non-spacing characters
if (bisearch(ucs, COMBINING_BMP))
return 0;
// if we arrive here, ucs is not a combining or C0/C1 control character
if (isWideBMP(ucs)) {
return 2;
}
return 1;
}
function isWideBMP(ucs: number): boolean {
return (
ucs >= 0x1100 && (
ucs <= 0x115f || // Hangul Jamo init. consonants
ucs === 0x2329 ||
ucs === 0x232a ||
(ucs >= 0x2e80 && ucs <= 0xa4cf && ucs !== 0x303f) || // CJK..Yi
(ucs >= 0xac00 && ucs <= 0xd7a3) || // Hangul Syllables
(ucs >= 0xf900 && ucs <= 0xfaff) || // CJK Compat Ideographs
(ucs >= 0xfe10 && ucs <= 0xfe19) || // Vertical forms
(ucs >= 0xfe30 && ucs <= 0xfe6f) || // CJK Compat Forms
(ucs >= 0xff00 && ucs <= 0xff60) || // Fullwidth Forms
(ucs >= 0xffe0 && ucs <= 0xffe6)));
}
function wcwidthHigh(ucs: number): 0 | 1 | 2 {
if (bisearch(ucs, COMBINING_HIGH))
return 0;
if ((ucs >= 0x20000 && ucs <= 0x2fffd) || (ucs >= 0x30000 && ucs <= 0x3fffd)) {
return 2;
}
return 1;
}
const control = opts.control | 0;
let table: number[] | Uint32Array = null;
function init_table(): number[] | Uint32Array {
// lookup table for BMP
const CODEPOINTS = 65536; // BMP holds 65536 codepoints
const BITWIDTH = 2; // a codepoint can have a width of 0, 1 or 2
const ITEMSIZE = 32; // using uint32_t
const CONTAINERSIZE = CODEPOINTS * BITWIDTH / ITEMSIZE;
const CODEPOINTS_PER_ITEM = ITEMSIZE / BITWIDTH;
table = (typeof Uint32Array === 'undefined')
? new Array(CONTAINERSIZE)
: new Uint32Array(CONTAINERSIZE);
for (let i = 0; i < CONTAINERSIZE; ++i) {
let num = 0;
let pos = CODEPOINTS_PER_ITEM;
while (pos--)
num = (num << 2) | wcwidthBMP(CODEPOINTS_PER_ITEM * i + pos);
table[i] = num;
}
return table;
}
// get width from lookup table
// position in container : num / CODEPOINTS_PER_ITEM
// ==> n = table[Math.floor(num / 16)]
// ==> n = table[num >> 4]
// 16 codepoints per number: FFEEDDCCBBAA99887766554433221100
// position in number : (num % CODEPOINTS_PER_ITEM) * BITWIDTH
// ==> m = (n % 16) * 2
// ==> m = (num & 15) << 1
// right shift to position m
// ==> n = n >> m e.g. m=12 000000000000FFEEDDCCBBAA99887766
// we are only interested in 2 LSBs, cut off higher bits
// ==> n = n & 3 e.g. 000000000000000000000000000000XX
return function (num: number): number {
num = num | 0; // get asm.js like optimization under V8
if (num < 32)
return control | 0;
if (num < 127)
return 1;
let t = table || init_table();
if (num < 65536)
return t[num >> 4] >> ((num & 15) << 1) & 3;
// do a full search for high codepoints
return wcwidthHigh(num);
};
})({nul: 0, control: 0}); // configurable options
+14 -1
View File
@@ -5,7 +5,6 @@
import { assert } from 'chai';
import { InputHandler } from './InputHandler';
import { wcwidth } from './InputHandler';
import { MockInputHandlingTerminal } from './utils/TestUtils.test';
describe('InputHandler', () => {
@@ -66,4 +65,18 @@ describe('InputHandler', () => {
assert.equal(terminal.options['cursorBlink'], false);
});
});
describe('setMode', () => {
it('should toggle Terminal.bracketedPasteMode', () => {
let terminal = new MockInputHandlingTerminal();
terminal.prefix = '?';
terminal.bracketedPasteMode = false;
let inputHandler = new InputHandler(terminal);
// Set bracketed paste mode
inputHandler.setMode([2004]);
assert.equal(terminal.bracketedPasteMode, true);
// Reset bracketed paste mode
inputHandler.resetMode([2004]);
assert.equal(terminal.bracketedPasteMode, false);
});
});
});
+9 -159
View File
@@ -10,6 +10,7 @@ import { DEFAULT_CHARSET } from './Charsets';
import { CharData } from './Types';
import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX } from './Buffer';
import { FLAGS } from './renderer/Types';
import { wcwidth } from './CharWidth';
/**
* The terminal's standard implementation of IInputHandler, this handles all
@@ -133,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');
}
/**
@@ -931,6 +932,9 @@ export class InputHandler implements IInputHandler {
this._terminal.viewport.syncScrollArea();
this._terminal.showCursor();
break;
case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste)
this._terminal.bracketedPasteMode = true;
break;
}
}
}
@@ -1101,6 +1105,9 @@ export class InputHandler implements IInputHandler {
this._terminal.viewport.syncScrollArea();
this._terminal.showCursor();
break;
case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste)
this._terminal.bracketedPasteMode = false;
break;
}
}
}
@@ -1446,160 +1453,3 @@ export class InputHandler implements IInputHandler {
this._terminal.buffer.y = this._terminal.buffer.savedY || 0;
}
}
export const wcwidth = (function(opts: {nul: number, control: number}): (ucs: number) => number {
// extracted from https://www.cl.cam.ac.uk/%7Emgk25/ucs/wcwidth.c
// combining characters
const COMBINING_BMP = [
[0x0300, 0x036F], [0x0483, 0x0486], [0x0488, 0x0489],
[0x0591, 0x05BD], [0x05BF, 0x05BF], [0x05C1, 0x05C2],
[0x05C4, 0x05C5], [0x05C7, 0x05C7], [0x0600, 0x0603],
[0x0610, 0x0615], [0x064B, 0x065E], [0x0670, 0x0670],
[0x06D6, 0x06E4], [0x06E7, 0x06E8], [0x06EA, 0x06ED],
[0x070F, 0x070F], [0x0711, 0x0711], [0x0730, 0x074A],
[0x07A6, 0x07B0], [0x07EB, 0x07F3], [0x0901, 0x0902],
[0x093C, 0x093C], [0x0941, 0x0948], [0x094D, 0x094D],
[0x0951, 0x0954], [0x0962, 0x0963], [0x0981, 0x0981],
[0x09BC, 0x09BC], [0x09C1, 0x09C4], [0x09CD, 0x09CD],
[0x09E2, 0x09E3], [0x0A01, 0x0A02], [0x0A3C, 0x0A3C],
[0x0A41, 0x0A42], [0x0A47, 0x0A48], [0x0A4B, 0x0A4D],
[0x0A70, 0x0A71], [0x0A81, 0x0A82], [0x0ABC, 0x0ABC],
[0x0AC1, 0x0AC5], [0x0AC7, 0x0AC8], [0x0ACD, 0x0ACD],
[0x0AE2, 0x0AE3], [0x0B01, 0x0B01], [0x0B3C, 0x0B3C],
[0x0B3F, 0x0B3F], [0x0B41, 0x0B43], [0x0B4D, 0x0B4D],
[0x0B56, 0x0B56], [0x0B82, 0x0B82], [0x0BC0, 0x0BC0],
[0x0BCD, 0x0BCD], [0x0C3E, 0x0C40], [0x0C46, 0x0C48],
[0x0C4A, 0x0C4D], [0x0C55, 0x0C56], [0x0CBC, 0x0CBC],
[0x0CBF, 0x0CBF], [0x0CC6, 0x0CC6], [0x0CCC, 0x0CCD],
[0x0CE2, 0x0CE3], [0x0D41, 0x0D43], [0x0D4D, 0x0D4D],
[0x0DCA, 0x0DCA], [0x0DD2, 0x0DD4], [0x0DD6, 0x0DD6],
[0x0E31, 0x0E31], [0x0E34, 0x0E3A], [0x0E47, 0x0E4E],
[0x0EB1, 0x0EB1], [0x0EB4, 0x0EB9], [0x0EBB, 0x0EBC],
[0x0EC8, 0x0ECD], [0x0F18, 0x0F19], [0x0F35, 0x0F35],
[0x0F37, 0x0F37], [0x0F39, 0x0F39], [0x0F71, 0x0F7E],
[0x0F80, 0x0F84], [0x0F86, 0x0F87], [0x0F90, 0x0F97],
[0x0F99, 0x0FBC], [0x0FC6, 0x0FC6], [0x102D, 0x1030],
[0x1032, 0x1032], [0x1036, 0x1037], [0x1039, 0x1039],
[0x1058, 0x1059], [0x1160, 0x11FF], [0x135F, 0x135F],
[0x1712, 0x1714], [0x1732, 0x1734], [0x1752, 0x1753],
[0x1772, 0x1773], [0x17B4, 0x17B5], [0x17B7, 0x17BD],
[0x17C6, 0x17C6], [0x17C9, 0x17D3], [0x17DD, 0x17DD],
[0x180B, 0x180D], [0x18A9, 0x18A9], [0x1920, 0x1922],
[0x1927, 0x1928], [0x1932, 0x1932], [0x1939, 0x193B],
[0x1A17, 0x1A18], [0x1B00, 0x1B03], [0x1B34, 0x1B34],
[0x1B36, 0x1B3A], [0x1B3C, 0x1B3C], [0x1B42, 0x1B42],
[0x1B6B, 0x1B73], [0x1DC0, 0x1DCA], [0x1DFE, 0x1DFF],
[0x200B, 0x200F], [0x202A, 0x202E], [0x2060, 0x2063],
[0x206A, 0x206F], [0x20D0, 0x20EF], [0x302A, 0x302F],
[0x3099, 0x309A], [0xA806, 0xA806], [0xA80B, 0xA80B],
[0xA825, 0xA826], [0xFB1E, 0xFB1E], [0xFE00, 0xFE0F],
[0xFE20, 0xFE23], [0xFEFF, 0xFEFF], [0xFFF9, 0xFFFB],
];
const COMBINING_HIGH = [
[0x10A01, 0x10A03], [0x10A05, 0x10A06], [0x10A0C, 0x10A0F],
[0x10A38, 0x10A3A], [0x10A3F, 0x10A3F], [0x1D167, 0x1D169],
[0x1D173, 0x1D182], [0x1D185, 0x1D18B], [0x1D1AA, 0x1D1AD],
[0x1D242, 0x1D244], [0xE0001, 0xE0001], [0xE0020, 0xE007F],
[0xE0100, 0xE01EF]
];
// binary search
function bisearch(ucs: number, data: number[][]): boolean {
let min = 0;
let max = data.length - 1;
let mid;
if (ucs < data[0][0] || ucs > data[max][1])
return false;
while (max >= min) {
mid = (min + max) >> 1;
if (ucs > data[mid][1])
min = mid + 1;
else if (ucs < data[mid][0])
max = mid - 1;
else
return true;
}
return false;
}
function wcwidthBMP(ucs: number): number {
// test for 8-bit control characters
if (ucs === 0)
return opts.nul;
if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
return opts.control;
// binary search in table of non-spacing characters
if (bisearch(ucs, COMBINING_BMP))
return 0;
// if we arrive here, ucs is not a combining or C0/C1 control character
if (isWideBMP(ucs)) {
return 2;
}
return 1;
}
function isWideBMP(ucs: number): boolean {
return (
ucs >= 0x1100 && (
ucs <= 0x115f || // Hangul Jamo init. consonants
ucs === 0x2329 ||
ucs === 0x232a ||
(ucs >= 0x2e80 && ucs <= 0xa4cf && ucs !== 0x303f) || // CJK..Yi
(ucs >= 0xac00 && ucs <= 0xd7a3) || // Hangul Syllables
(ucs >= 0xf900 && ucs <= 0xfaff) || // CJK Compat Ideographs
(ucs >= 0xfe10 && ucs <= 0xfe19) || // Vertical forms
(ucs >= 0xfe30 && ucs <= 0xfe6f) || // CJK Compat Forms
(ucs >= 0xff00 && ucs <= 0xff60) || // Fullwidth Forms
(ucs >= 0xffe0 && ucs <= 0xffe6)));
}
function wcwidthHigh(ucs: number): 0 | 1 | 2 {
if (bisearch(ucs, COMBINING_HIGH))
return 0;
if ((ucs >= 0x20000 && ucs <= 0x2fffd) || (ucs >= 0x30000 && ucs <= 0x3fffd)) {
return 2;
}
return 1;
}
const control = opts.control | 0;
let table: number[] | Uint32Array = null;
function init_table(): number[] | Uint32Array {
// lookup table for BMP
const CODEPOINTS = 65536; // BMP holds 65536 codepoints
const BITWIDTH = 2; // a codepoint can have a width of 0, 1 or 2
const ITEMSIZE = 32; // using uint32_t
const CONTAINERSIZE = CODEPOINTS * BITWIDTH / ITEMSIZE;
const CODEPOINTS_PER_ITEM = ITEMSIZE / BITWIDTH;
table = (typeof Uint32Array === 'undefined')
? new Array(CONTAINERSIZE)
: new Uint32Array(CONTAINERSIZE);
for (let i = 0; i < CONTAINERSIZE; ++i) {
let num = 0;
let pos = CODEPOINTS_PER_ITEM;
while (pos--)
num = (num << 2) | wcwidthBMP(CODEPOINTS_PER_ITEM * i + pos);
table[i] = num;
}
return table;
}
// get width from lookup table
// position in container : num / CODEPOINTS_PER_ITEM
// ==> n = table[Math.floor(num / 16)]
// ==> n = table[num >> 4]
// 16 codepoints per number: FFEEDDCCBBAA99887766554433221100
// position in number : (num % CODEPOINTS_PER_ITEM) * BITWIDTH
// ==> m = (n % 16) * 2
// ==> m = (num & 15) << 1
// right shift to position m
// ==> n = n >> m e.g. m=12 000000000000FFEEDDCCBBAA99887766
// we are only interested in 2 LSBs, cut off higher bits
// ==> n = n & 3 e.g. 000000000000000000000000000000XX
return function (num: number): number {
num = num | 0; // get asm.js like optimization under V8
if (num < 32)
return control | 0;
if (num < 127)
return 1;
let t = table || init_table();
if (num < 65536)
return t[num >> 4] >> ((num & 15) << 1) & 3;
// do a full search for high codepoints
return wcwidthHigh(num);
};
})({nul: 0, control: 0}); // configurable options

Some files were not shown because too many files have changed in this diff Show More