Merge remote-tracking branch 'origin/master' into webgl2
This commit is contained in:
+1
-4
@@ -2,6 +2,7 @@ node_modules/
|
||||
*.swp
|
||||
.lock-wscript
|
||||
lib/
|
||||
out/
|
||||
Makefile.gyp
|
||||
*.Makefile
|
||||
*.target.gyp.mk
|
||||
@@ -16,10 +17,6 @@ build/
|
||||
fixtures/typings-test/*.js
|
||||
package-lock.json
|
||||
|
||||
# Directories needed for code coverage
|
||||
coverage/
|
||||
.nyc_output/
|
||||
|
||||
# Keep bundled code out of Git
|
||||
dist/
|
||||
demo/dist/
|
||||
|
||||
+4
-1
@@ -38,6 +38,8 @@
|
||||
*.test.js
|
||||
*.test.js.map
|
||||
lib/test/
|
||||
tslint.json
|
||||
webpack.config.js
|
||||
|
||||
docs/
|
||||
/.idea/
|
||||
@@ -45,5 +47,6 @@ docs/
|
||||
bin/
|
||||
build/
|
||||
fixtures/
|
||||
coverage/
|
||||
demo/
|
||||
.devcontainer/
|
||||
out/
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# [](https://xtermjs.org)
|
||||
|
||||
[](https://dev.azure.com/xtermjs/xterm.js/_build/latest?definitionId=3)
|
||||
[](https://coveralls.io/github/xtermjs/xterm.js?branch=master)
|
||||
|
||||
Xterm.js is a front-end component written in TypeScript that lets applications bring fully-featured terminals to their users in the browser. It's used by popular projects such as VS Code, Hyper and Theia.
|
||||
|
||||
|
||||
+4
-9
@@ -20,7 +20,7 @@ jobs:
|
||||
yarn
|
||||
displayName: 'Install dependencies and build'
|
||||
- script: |
|
||||
yarn mocha
|
||||
yarn test-unit
|
||||
displayName: 'Unit tests'
|
||||
- script: |
|
||||
yarn lint
|
||||
@@ -38,16 +38,11 @@ jobs:
|
||||
yarn
|
||||
displayName: 'Install dependencies and build'
|
||||
- script: |
|
||||
yarn mocha
|
||||
yarn test-unit
|
||||
displayName: 'Unit tests'
|
||||
- script: |
|
||||
yarn lint
|
||||
displayName: 'Lint'
|
||||
- script: |
|
||||
yarn test-coverage
|
||||
export COVERALLS_GIT_BRANCH=$BUILD_SOURCEBRANCHNAME
|
||||
yarn coveralls
|
||||
displayName: 'Generate and publish coverage'
|
||||
|
||||
- job: Windows
|
||||
pool:
|
||||
@@ -61,12 +56,12 @@ jobs:
|
||||
yarn
|
||||
displayName: 'Install dependencies and build'
|
||||
- script: |
|
||||
yarn mocha
|
||||
yarn test-unit
|
||||
displayName: 'Unit tests'
|
||||
- script: |
|
||||
yarn lint
|
||||
displayName: 'Lint'
|
||||
|
||||
|
||||
- job: IntegrationTests
|
||||
pool:
|
||||
vmImage: 'ubuntu-16.04'
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
#! /usr/bin/env sh
|
||||
|
||||
# Usage: ./bin/prepare-release x.y.z
|
||||
# x.y.z should be semver (e.g. 1.0.0)
|
||||
|
||||
set -e
|
||||
|
||||
NEW_VERSION=$1
|
||||
CURRENT_PACKAGE_JSON_VERSION=$(cat package.json \
|
||||
| grep version \
|
||||
| head -1 \
|
||||
| awk -F: '{ print $2 }' \
|
||||
| sed 's/[",]//g' \
|
||||
| tr -d '[[:space:]]')
|
||||
|
||||
# Build xterm.js into `dist`
|
||||
export BUILD_DIR=dist
|
||||
npm run build
|
||||
|
||||
# Update version in package.json
|
||||
sed -i "s/\"version\": \"$CURRENT_PACKAGE_JSON_VERSION\"/\"version\": \"$NEW_VERSION\"/g" package.json
|
||||
|
||||
git commit -S -s -a -m "Bump version to $NEW_VERSION"
|
||||
git tag $NEW_VERSION
|
||||
-22
@@ -1,22 +0,0 @@
|
||||
#! /usr/bin/env sh
|
||||
|
||||
# Usage: ./bin/release x.y.z
|
||||
# x.y.z should be semver (e.g. 1.0.0)
|
||||
|
||||
set -e
|
||||
|
||||
if [ -z "$1" ];
|
||||
then
|
||||
echo "No version supplied. Please a version argument\n"
|
||||
echo "Usage: $0 VERSION\n"
|
||||
echo "Example: $0 1.0.0"
|
||||
exit
|
||||
fi
|
||||
|
||||
NEW_VERSION=$1
|
||||
|
||||
./bin/prepare-release $NEW_VERSION
|
||||
|
||||
git push && \
|
||||
git push --tags && \
|
||||
npm publish
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
const cp = require('child_process');
|
||||
const path = require('path');
|
||||
|
||||
// Add `out` to the NODE_PATH so absolute paths can be resolved.
|
||||
const env = { ...process.env };
|
||||
env.NODE_PATH = path.resolve(__dirname, '../out');
|
||||
|
||||
const args = [
|
||||
'./out/*test.js',
|
||||
'./out/**/*test.js',
|
||||
'./out/*integration.js',
|
||||
'./out/**/*integration.js',
|
||||
'./lib/**/*test.js'
|
||||
];
|
||||
|
||||
cp.spawnSync(path.resolve(__dirname, '../node_modules/.bin/mocha'), args, {
|
||||
cwd: path.resolve(__dirname, '..'),
|
||||
env,
|
||||
stdio: 'inherit'
|
||||
});
|
||||
+5
-2
@@ -7,7 +7,11 @@
|
||||
|
||||
/// <reference path="../typings/xterm.d.ts"/>
|
||||
|
||||
import { Terminal } from '../lib/public/Terminal';
|
||||
// Use tsc version (yarn watch)
|
||||
import { Terminal } from '../out/public/Terminal';
|
||||
// Use webpacked version (yarn package)
|
||||
// import { Terminal } from '../lib/xterm';
|
||||
|
||||
import { AttachAddon } from 'xterm-addon-attach';
|
||||
import { SearchAddon, ISearchOptions } from 'xterm-addon-search';
|
||||
import { WebLinksAddon } from 'xterm-addon-web-links';
|
||||
@@ -211,7 +215,6 @@ function initOptions(term: TerminalType): void {
|
||||
bellSound: null,
|
||||
bellStyle: ['none', 'sound'],
|
||||
cursorStyle: ['block', 'underline', 'bar'],
|
||||
experimentalCharAtlas: ['none', 'static', 'dynamic', 'webgl'],
|
||||
fontFamily: null,
|
||||
fontWeight: ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'],
|
||||
fontWeightBold: ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'],
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>xterm.js demo</title>
|
||||
<link rel="shortcut icon" type="image/png" href="/logo.png">
|
||||
<link rel="stylesheet" href="/src/xterm.css" />
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<link rel="stylesheet" href="/xterm.css" />
|
||||
<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>
|
||||
</head>
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ function startServer() {
|
||||
var terminals = {},
|
||||
logs = {};
|
||||
|
||||
app.use('/src', express.static(__dirname + '/../src'));
|
||||
app.use('/xterm.css', express.static(__dirname + '/../css/xterm.css'));
|
||||
app.get('/logo.png', (req, res) => res.sendFile(__dirname + '/logo.png'));
|
||||
|
||||
app.get('/', function(req, res){
|
||||
|
||||
+19
-2
@@ -11,7 +11,19 @@ const startServer = require('./server.js');
|
||||
|
||||
startServer();
|
||||
|
||||
// Build/watch client source
|
||||
/**
|
||||
* This webpack config builds and watches the demo project. It works by taking the output from tsc
|
||||
* (via `yarn watch`) which is put into `out/` and then webpacks it into `demo/dist/`. The aliases
|
||||
* are used fix up the absolute paths output by tsc (because of `baseUrl` and `paths` in
|
||||
* `tsconfig.json`.
|
||||
*
|
||||
* For production builds see `webpack.config.js` in the root directory. If that is built the demo
|
||||
* can use that by switching out which `Terminal` is imported in `client.ts`, this is useful for
|
||||
* validating that the packaged version works correctly.
|
||||
*
|
||||
* The addons are not webpacked right now and are built directly to `lib/` via `tsc` as they are
|
||||
* the legacy format (`applyAddon`) and will be removed soon anyway.
|
||||
*/
|
||||
const clientConfig = {
|
||||
entry: path.resolve(__dirname, 'client.ts'),
|
||||
devtool: 'inline-source-map',
|
||||
@@ -32,7 +44,12 @@ const clientConfig = {
|
||||
},
|
||||
resolve: {
|
||||
modules: [path.resolve(__dirname, '..'), 'node_modules'],
|
||||
extensions: [ '.tsx', '.ts', '.js' ]
|
||||
extensions: [ '.tsx', '.ts', '.js' ],
|
||||
alias: {
|
||||
common: path.resolve('./out/common'),
|
||||
core: path.resolve('./out/core'),
|
||||
ui: path.resolve('./out/ui')
|
||||
}
|
||||
},
|
||||
output: {
|
||||
filename: 'client-bundle.js',
|
||||
|
||||
@@ -50,7 +50,6 @@ namespace methods_core {
|
||||
const t: Terminal = new Terminal();
|
||||
t.blur();
|
||||
t.focus();
|
||||
t.destroy();
|
||||
t.clear();
|
||||
t.refresh(0, 1);
|
||||
t.reset();
|
||||
@@ -148,7 +147,6 @@ namespace methods_core {
|
||||
const r18: (data: string) => void = t.getOption('handler');
|
||||
const r19: string = t.getOption('bellSound');
|
||||
const r20: string = t.getOption('bellStyle');
|
||||
const r21: boolean = t.getOption('enableBold');
|
||||
const r22: number = t.getOption('letterSpacing');
|
||||
const r23: boolean = t.getOption('macOptionIsMeta');
|
||||
const r24: string = t.getOption('fontWeight');
|
||||
@@ -168,7 +166,6 @@ namespace methods_core {
|
||||
t.setOption('cursorBlink', true);
|
||||
t.setOption('debug', true);
|
||||
t.setOption('disableStdin', true);
|
||||
t.setOption('enableBold', true);
|
||||
t.setOption('fontWeight', 'normal');
|
||||
t.setOption('fontWeight', 'bold');
|
||||
t.setOption('fontWeightBold', 'normal');
|
||||
|
||||
-141
@@ -1,141 +0,0 @@
|
||||
/**
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
const browserify = require('browserify');
|
||||
const buffer = require('vinyl-buffer');
|
||||
const fs = require('fs-extra');
|
||||
const gulp = require('gulp');
|
||||
const path = require('path');
|
||||
const merge = require('merge-stream');
|
||||
const mocha = require('gulp-mocha');
|
||||
const sorcery = require('sorcery');
|
||||
const source = require('vinyl-source-stream');
|
||||
const sourcemaps = require('gulp-sourcemaps');
|
||||
const ts = require('gulp-typescript');
|
||||
const util = require('gulp-util');
|
||||
|
||||
const buildDir = process.env.BUILD_DIR || 'build';
|
||||
const tsProject = ts.createProject('src/tsconfig.json');
|
||||
let srcDir = './src';
|
||||
let outDir = './lib';
|
||||
|
||||
const addons = fs.readdirSync(`${__dirname}/src/addons`);
|
||||
|
||||
const TEST_PATHS = [
|
||||
`${outDir}/*test.js`,
|
||||
`${outDir}/**/*test.js`,
|
||||
`${outDir}/*integration.js`,
|
||||
`${outDir}/**/*integration.js`
|
||||
];
|
||||
|
||||
// Under some environments like TravisCI, this comes out at absolute which can
|
||||
// break the build. This ensures that the outDir is absolute.
|
||||
if (path.normalize(outDir).indexOf(__dirname) !== 0) {
|
||||
outDir = `${__dirname}/${path.normalize(outDir)}`;
|
||||
}
|
||||
|
||||
gulp.task('css', function() {
|
||||
return gulp.src(`${srcDir}/**/*.css`).pipe(gulp.dest(outDir));
|
||||
});
|
||||
|
||||
gulp.task('watch-css', function() {
|
||||
return gulp.watch(`${srcDir}/**/*.css`, ['css']);
|
||||
});
|
||||
|
||||
/**
|
||||
* Bundle JavaScript files produced by the `tsc` task, into a single file named `xterm.js` with
|
||||
* Browserify.
|
||||
*/
|
||||
gulp.task('browserify', function() {
|
||||
// Ensure that the build directory exists
|
||||
fs.ensureDirSync(buildDir);
|
||||
|
||||
let browserifyOptions = {
|
||||
basedir: buildDir,
|
||||
debug: true,
|
||||
entries: [`${outDir}/xterm.js`],
|
||||
standalone: 'Terminal',
|
||||
cache: {},
|
||||
packageCache: {}
|
||||
};
|
||||
let bundleStream = browserify(browserifyOptions)
|
||||
.bundle()
|
||||
.pipe(source(`xterm.js`))
|
||||
.pipe(buffer())
|
||||
.pipe(sourcemaps.init({loadMaps: true, sourceRoot: '..'}))
|
||||
.pipe(sourcemaps.write('./'))
|
||||
.pipe(gulp.dest(buildDir));
|
||||
|
||||
// Copy stylesheets from ${outDir}/ to ${buildDir}/
|
||||
let copyStylesheets = gulp.src(`${outDir}/**/*.css`).pipe(gulp.dest(buildDir));
|
||||
|
||||
return merge(bundleStream, copyStylesheets);
|
||||
});
|
||||
|
||||
gulp.task('browserify-addons', function() {
|
||||
const bundles = addons.map((addon) => {
|
||||
const addonOptions = {
|
||||
basedir: `${buildDir}/addons/${addon}`,
|
||||
debug: true,
|
||||
entries: [`${outDir}/addons/${addon}/${addon}.js`],
|
||||
standalone: addon,
|
||||
cache: {},
|
||||
packageCache: {}
|
||||
};
|
||||
|
||||
const addonBundle = browserify(addonOptions)
|
||||
.external(path.join(outDir, 'Terminal.js'))
|
||||
.bundle()
|
||||
.pipe(source(`./addons/${addon}/${addon}.js`))
|
||||
.pipe(buffer())
|
||||
.pipe(sourcemaps.init({loadMaps: true, sourceRoot: ''}))
|
||||
.pipe(sourcemaps.write('./'))
|
||||
.pipe(gulp.dest(buildDir));
|
||||
|
||||
return addonBundle;
|
||||
});
|
||||
|
||||
return merge(...bundles);
|
||||
});
|
||||
|
||||
gulp.task('mocha', function () {
|
||||
return gulp.src(TEST_PATHS, {read: false})
|
||||
.pipe(mocha())
|
||||
.once('error', () => process.exit(1));
|
||||
});
|
||||
|
||||
/**
|
||||
* Run single test suite (file) by file name (without file extension). Example of the command:
|
||||
* gulp mocha-suite --test InputHandler.test
|
||||
*/
|
||||
gulp.task('mocha-suite', [], function () {
|
||||
let testName = util.env.test;
|
||||
util.log("Run test by Name: " + testName);
|
||||
return gulp.src([`${outDir}/${testName}.js`, `${outDir}/**/${testName}.js`], {read: false})
|
||||
.pipe(mocha())
|
||||
.once('error', () => process.exit(1));
|
||||
});
|
||||
|
||||
/**
|
||||
* Use `sorcery` to resolve the source map chain and point back to the TypeScript files.
|
||||
* (Without this task the source maps produced for the JavaScript bundle points into the
|
||||
* compiled JavaScript files in ${outDir}/).
|
||||
*/
|
||||
gulp.task('sorcery', ['browserify'], function () {
|
||||
let chain = sorcery.loadSync(`${buildDir}/xterm.js`);
|
||||
chain.apply();
|
||||
chain.writeSync();
|
||||
});
|
||||
|
||||
gulp.task('sorcery-addons', ['browserify-addons'], function () {
|
||||
addons.forEach((addon) => {
|
||||
const chain = sorcery.loadSync(`${buildDir}/addons/${addon}/${addon}.js`);
|
||||
chain.apply();
|
||||
chain.writeSync();
|
||||
})
|
||||
});
|
||||
|
||||
gulp.task('build', ['css', 'sorcery', 'sorcery-addons']);
|
||||
gulp.task('test', ['mocha']);
|
||||
gulp.task('default', ['build']);
|
||||
+12
-30
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "xterm",
|
||||
"description": "Full xterm terminal, in your browser",
|
||||
"version": "3.13.0",
|
||||
"main": "lib/public/Terminal.js",
|
||||
"version": "3.14.0",
|
||||
"main": "lib/xterm.js",
|
||||
"types": "typings/xterm.d.ts",
|
||||
"repository": "https://github.com/xtermjs/xterm.js",
|
||||
"license": "MIT",
|
||||
@@ -15,58 +15,40 @@
|
||||
"@types/puppeteer": "^1.12.4",
|
||||
"@types/utf8": "^2.1.6",
|
||||
"@types/webpack": "^4.4.11",
|
||||
"browserify": "^13.3.0",
|
||||
"chai": "3.5.0",
|
||||
"coveralls": "^3.0.1",
|
||||
"express": "4.13.4",
|
||||
"express-ws": "2.0.0-rc.1",
|
||||
"fs-extra": "^1.0.0",
|
||||
"glob": "^7.0.5",
|
||||
"gulp": "3.9.1",
|
||||
"gulp-cli": "^1.2.2",
|
||||
"gulp-concat": "^2.6.1",
|
||||
"gulp-mocha": "^3.0.1",
|
||||
"gulp-sourcemaps": "1.9.1",
|
||||
"gulp-typescript": "^3.1.3",
|
||||
"gulp-util": "3.0.8",
|
||||
"jsdom": "^11.11.0",
|
||||
"merge-stream": "^1.0.1",
|
||||
"mocha": "^6.1.4",
|
||||
"node-pty": "0.7.6",
|
||||
"nodemon": "1.10.2",
|
||||
"nyc": "^11.8.0",
|
||||
"puppeteer": "^1.15.0",
|
||||
"sorcery": "^0.10.0",
|
||||
"source-map-loader": "^0.2.4",
|
||||
"ts-loader": "^4.5.0",
|
||||
"tslint": "^5.9.1",
|
||||
"tslint-consistent-codestyle": "^1.13.0",
|
||||
"typescript": "3.4",
|
||||
"typescript": "3.5",
|
||||
"utf8": "^3.0.0",
|
||||
"vinyl-buffer": "^1.0.0",
|
||||
"vinyl-source-stream": "^1.1.0",
|
||||
"webpack": "^4.17.1",
|
||||
"webpack-cli": "^3.1.0",
|
||||
"xterm-addon-attach": "0.1.0-beta8",
|
||||
"xterm-addon-search": "0.1.0-beta4",
|
||||
"xterm-addon-web-links": "0.1.0-beta6",
|
||||
"zmodem.js": "^0.1.5"
|
||||
"xterm-addon-web-links": "0.1.0-beta6"
|
||||
},
|
||||
"scripts": {
|
||||
"prepackage": "npm run build",
|
||||
"package": "webpack",
|
||||
"start": "node demo/start",
|
||||
"start-debug": "node --inspect-brk demo/start",
|
||||
"start-zmodem": "node demo/zmodem/app",
|
||||
"lint": "tslint 'src/**/*.ts' './demo/**/*.ts'",
|
||||
"test": "npm run mocha",
|
||||
"test-unit": "node ./bin/test.js",
|
||||
"test": "npm run test-unit",
|
||||
"posttest": "npm run lint",
|
||||
"test-debug": "node --inspect-brk node_modules/.bin/gulp test",
|
||||
"test-suite": "gulp mocha-suite --test",
|
||||
"test-coverage": "nyc -x gulpfile.js -x '**/*test*' npm run mocha",
|
||||
"test-api": "mocha \"**/*.api.js\"",
|
||||
"mocha": "gulp test",
|
||||
"prebuild": "tsc -b ./src/tsconfig.all.json",
|
||||
"build": "gulp build",
|
||||
"prepare": "npm run prebuild",
|
||||
"prepublishOnly": "npm run build",
|
||||
"build": "tsc -b ./src/tsconfig.all.json",
|
||||
"prepare": "npm run build",
|
||||
"prepublishOnly": "npm run package",
|
||||
"coveralls": "nyc report --reporter=text-lcov | coveralls",
|
||||
"watch": "tsc -b -w ./src/tsconfig.all.json --preserveWatchOutput"
|
||||
}
|
||||
|
||||
+15
-14
@@ -5,11 +5,11 @@
|
||||
|
||||
import * as Strings from './Strings';
|
||||
import { ITerminal, IBuffer } from './Types';
|
||||
import { isMac } from './common/Platform';
|
||||
import { RenderDebouncer } from './ui/RenderDebouncer';
|
||||
import { addDisposableDomListener } from './ui/Lifecycle';
|
||||
import { Disposable } from './common/Lifecycle';
|
||||
import { ScreenDprMonitor } from './ui/ScreenDprMonitor';
|
||||
import { isMac } from 'common/Platform';
|
||||
import { RenderDebouncer } from 'ui/RenderDebouncer';
|
||||
import { addDisposableDomListener } from 'ui/Lifecycle';
|
||||
import { Disposable } from 'common/Lifecycle';
|
||||
import { ScreenDprMonitor } from 'ui/ScreenDprMonitor';
|
||||
import { IRenderDimensions } from './renderer/Types';
|
||||
|
||||
const MAX_ROWS_TO_READ = 20;
|
||||
@@ -43,6 +43,8 @@ export class AccessibilityManager extends Disposable {
|
||||
*/
|
||||
private _charsToConsume: string[] = [];
|
||||
|
||||
private _charsToAnnounce: string = '';
|
||||
|
||||
constructor(
|
||||
private _terminal: ITerminal,
|
||||
private _dimensions: IRenderDimensions
|
||||
@@ -202,10 +204,10 @@ export class AccessibilityManager extends Disposable {
|
||||
// Have the screen reader ignore the char if it was just input
|
||||
const shiftedChar = this._charsToConsume.shift();
|
||||
if (shiftedChar !== char) {
|
||||
this._announceCharacter(char);
|
||||
this._charsToAnnounce += char;
|
||||
}
|
||||
} else {
|
||||
this._announceCharacter(char);
|
||||
this._charsToAnnounce += char;
|
||||
}
|
||||
|
||||
if (char === '\n') {
|
||||
@@ -260,6 +262,7 @@ export class AccessibilityManager extends Disposable {
|
||||
element.setAttribute('aria-setsize', setSize);
|
||||
}
|
||||
}
|
||||
this._announceCharacters();
|
||||
}
|
||||
|
||||
private _refreshRowsDimensions(): void {
|
||||
@@ -283,13 +286,11 @@ export class AccessibilityManager extends Disposable {
|
||||
element.style.height = `${this._dimensions.actualCellHeight}px`;
|
||||
}
|
||||
|
||||
private _announceCharacter(char: string): void {
|
||||
if (char === ' ') {
|
||||
// Always use nbsp for spaces in order to preserve the space between characters in
|
||||
// voiceover's caption window
|
||||
this._liveRegion.innerHTML += ' ';
|
||||
} else {
|
||||
this._liveRegion.textContent += char;
|
||||
private _announceCharacters(): void {
|
||||
if (this._charsToAnnounce.length === 0) {
|
||||
return;
|
||||
}
|
||||
this._liveRegion.textContent += this._charsToAnnounce;
|
||||
this._charsToAnnounce = '';
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -6,9 +6,9 @@
|
||||
import { assert, expect } from 'chai';
|
||||
import { ITerminal } from './Types';
|
||||
import { Buffer } from './Buffer';
|
||||
import { CircularList } from './common/CircularList';
|
||||
import { CircularList } from 'common/CircularList';
|
||||
import { MockTerminal, TestTerminal } from './TestUtils.test';
|
||||
import { BufferLine, CellData, DEFAULT_ATTR_DATA } from './core/buffer/BufferLine';
|
||||
import { BufferLine, CellData, DEFAULT_ATTR_DATA } from 'core/buffer/BufferLine';
|
||||
|
||||
const INIT_COLS = 80;
|
||||
const INIT_ROWS = 24;
|
||||
|
||||
+6
-6
@@ -3,12 +3,12 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { CircularList, IInsertEvent } from './common/CircularList';
|
||||
import { CircularList, IInsertEvent } from 'common/CircularList';
|
||||
import { ITerminal, IBuffer, BufferIndex, IBufferStringIterator, IBufferStringIteratorResult } from './Types';
|
||||
import { IBufferLine, ICellData, IAttributeData } from './core/Types';
|
||||
import { BufferLine, CellData, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_WIDTH, WHITESPACE_CELL_CODE, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX, DEFAULT_ATTR_DATA } from './core/buffer/BufferLine';
|
||||
import { reflowLargerApplyNewLayout, reflowLargerCreateNewLayout, reflowLargerGetLinesToRemove, reflowSmallerGetNewLineLengths, getWrappedLineTrimmedLength } from './core/buffer/BufferReflow';
|
||||
import { Marker } from './core/buffer/Marker';
|
||||
import { IBufferLine, ICellData, IAttributeData } from 'core/Types';
|
||||
import { BufferLine, CellData, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_WIDTH, WHITESPACE_CELL_CODE, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX, DEFAULT_ATTR_DATA } from 'core/buffer/BufferLine';
|
||||
import { reflowLargerApplyNewLayout, reflowLargerCreateNewLayout, reflowLargerGetLinesToRemove, reflowSmallerGetNewLineLengths, getWrappedLineTrimmedLength } from 'core/buffer/BufferReflow';
|
||||
import { Marker } from 'core/buffer/Marker';
|
||||
|
||||
export const MAX_BUFFER_SIZE = 4294967295; // 2^32 - 1
|
||||
|
||||
@@ -294,7 +294,7 @@ export class Buffer implements IBuffer {
|
||||
for (let y = this.lines.length - 1; y >= 0; y--) {
|
||||
// Check whether this line is a problem
|
||||
let nextLine = this.lines.get(y) as BufferLine;
|
||||
if (!nextLine.isWrapped && nextLine.getTrimmedLength() <= newCols) {
|
||||
if (!nextLine || !nextLine.isWrapped && nextLine.getTrimmedLength() <= newCols) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -4,9 +4,9 @@
|
||||
*/
|
||||
|
||||
import { ITerminal, IBufferSet, IBuffer } from './Types';
|
||||
import { IAttributeData } from './core/Types';
|
||||
import { IAttributeData } from 'core/Types';
|
||||
import { Buffer } from './Buffer';
|
||||
import { EventEmitter2, IEvent } from './common/EventEmitter2';
|
||||
import { EventEmitter2, IEvent } from 'common/EventEmitter2';
|
||||
|
||||
/**
|
||||
* The BufferSet represents the set of two buffers used by xterm terminals (normal and alt) and
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { ICharMeasure, ITerminalOptions } from './Types';
|
||||
import { EventEmitter2, IEvent } from './common/EventEmitter2';
|
||||
import { EventEmitter2, IEvent } from 'common/EventEmitter2';
|
||||
|
||||
/**
|
||||
* Utility class that measures the size of a character. Measurements are done in
|
||||
|
||||
@@ -7,7 +7,7 @@ import { TestTerminal } from './TestUtils.test';
|
||||
import { assert } from 'chai';
|
||||
import { getStringCellWidth, wcwidth } from './CharWidth';
|
||||
import { IBuffer } from './Types';
|
||||
import { CellData, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from './core/buffer/BufferLine';
|
||||
import { CellData, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from 'core/buffer/BufferLine';
|
||||
|
||||
|
||||
describe('getStringCellWidth', function(): void {
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { fill } from './common/TypedArrayUtils';
|
||||
import { fill } from 'common/TypedArrayUtils';
|
||||
|
||||
export const wcwidth = (function(opts: {nul: number, control: number}): (ucs: number) => number {
|
||||
// extracted from https://www.cl.cam.ac.uk/%7Emgk25/ucs/wcwidth.c
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { ParserState, IDcsHandler, IParsingState } from './Types';
|
||||
import { EscapeSequenceParser, TransitionTable, VT500_TRANSITION_TABLE } from './EscapeSequenceParser';
|
||||
import * as chai from 'chai';
|
||||
import { StringToUtf32, stringFromCodePoint } from './core/input/TextDecoder';
|
||||
import { StringToUtf32, stringFromCodePoint } from 'core/input/TextDecoder';
|
||||
|
||||
function r(a: number, b: number): string[] {
|
||||
let c = b - a;
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
import { ParserState, ParserAction, IParsingState, IDcsHandler, IEscapeSequenceParser } from './Types';
|
||||
import { IDisposable } from 'xterm';
|
||||
import { Disposable } from './common/Lifecycle';
|
||||
import { utf32ToString } from './core/input/TextDecoder';
|
||||
import { Disposable } from 'common/Lifecycle';
|
||||
import { utf32ToString } from 'core/input/TextDecoder';
|
||||
|
||||
interface IHandlerCollection<T> {
|
||||
[key: string]: T[];
|
||||
|
||||
+198
-31
@@ -15,7 +15,7 @@ const width = 800;
|
||||
const height = 600;
|
||||
|
||||
describe('InputHandler Integration Tests', function(): void {
|
||||
this.timeout(10000);
|
||||
this.timeout(20000);
|
||||
|
||||
before(async function(): Promise<any> {
|
||||
browser = await puppeteer.launch({
|
||||
@@ -25,50 +25,209 @@ describe('InputHandler Integration Tests', function(): void {
|
||||
});
|
||||
page = (await browser.pages())[0];
|
||||
await page.setViewport({ width, height });
|
||||
await page.goto(APP);
|
||||
await openTerminal();
|
||||
});
|
||||
|
||||
after(() => {
|
||||
browser.close();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await page.goto(APP);
|
||||
});
|
||||
|
||||
describe('Device Status Report (DSR)', () => {
|
||||
it('Status Report - CSI 5 n', async function(): Promise<any> {
|
||||
await openTerminal();
|
||||
await page.evaluate(`
|
||||
window.term.onData(e => window.result = e);
|
||||
window.term.write('\\x1b[5n');
|
||||
`);
|
||||
assert.equal(await page.evaluate(`window.result`), '\x1b[0n');
|
||||
describe('CSI', () => {
|
||||
beforeEach(async () => {
|
||||
await page.evaluate(`window.term.reset()`);
|
||||
});
|
||||
|
||||
it('Report Cursor Position (CPR) - CSI 6 n', async function(): Promise<any> {
|
||||
await openTerminal();
|
||||
await page.evaluate(`window.term.write('\\n\\nfoo')`);
|
||||
assert.deepEqual(await page.evaluate(`
|
||||
[window.term.buffer.cursorY, window.term.buffer.cursorX]
|
||||
`), [2, 3]);
|
||||
it('ICH: Insert Ps (Blank) Character(s) (default = 1) - CSI Ps @', async function(): Promise<any> {
|
||||
await page.evaluate(`
|
||||
window.term.onData(e => window.result = e);
|
||||
window.term.write('\\x1b[6n');
|
||||
// Default
|
||||
window.term.write('foo\\x1b[3D\\x1b[@\\n\\r')
|
||||
// Explicit
|
||||
window.term.write('bar\\x1b[3D\\x1b[4@')
|
||||
`);
|
||||
assert.equal(await page.evaluate(`window.result`), '\x1b[3;4R');
|
||||
assert.deepEqual(await getLinesAsArray(2), [' foo', ' bar']);
|
||||
});
|
||||
|
||||
it('Report Cursor Position (DECXCPR) - CSI ? 6 n', async function(): Promise<any> {
|
||||
await openTerminal();
|
||||
await page.evaluate(`window.term.write('\\n\\nfoo')`);
|
||||
assert.deepEqual(await page.evaluate(`
|
||||
[window.term.buffer.cursorY, window.term.buffer.cursorX]
|
||||
`), [2, 3]);
|
||||
it('CUU: Cursor Up Ps Times (default = 1) - CSI Ps A', async function(): Promise<any> {
|
||||
await page.evaluate(`
|
||||
window.term.onData(e => window.result = e);
|
||||
window.term.write('\\x1b[?6n');
|
||||
// Default
|
||||
window.term.write('\\n\\n\\n\\n\x1b[Aa')
|
||||
// Explicit
|
||||
window.term.write('\x1b[2Ab')
|
||||
`);
|
||||
assert.equal(await page.evaluate(`window.result`), '\x1b[?3;4R');
|
||||
assert.deepEqual(await getLinesAsArray(4), ['', ' b', '', 'a']);
|
||||
});
|
||||
|
||||
it('CUD: Cursor Down Ps Times (default = 1) - CSI Ps B', async function(): Promise<any> {
|
||||
await page.evaluate(`
|
||||
// Default
|
||||
window.term.write('\x1b[Ba')
|
||||
// Explicit
|
||||
window.term.write('\x1b[2Bb')
|
||||
`);
|
||||
assert.deepEqual(await getLinesAsArray(4), ['', 'a', '', ' b']);
|
||||
});
|
||||
|
||||
it('CUF: Cursor Forward Ps Times (default = 1) - CSI Ps C', async function(): Promise<any> {
|
||||
await page.evaluate(`
|
||||
// Default
|
||||
window.term.write('\x1b[Ca')
|
||||
// Explicit
|
||||
window.term.write('\x1b[2Cb')
|
||||
`);
|
||||
assert.deepEqual(await getLinesAsArray(1), [' a b']);
|
||||
});
|
||||
|
||||
it('CUB: Cursor Backward Ps Times (default = 1) - CSI Ps D', async function(): Promise<any> {
|
||||
await page.evaluate(`
|
||||
// Default
|
||||
window.term.write('foo\x1b[Da')
|
||||
// Explicit
|
||||
window.term.write('\x1b[2Db')
|
||||
`);
|
||||
assert.deepEqual(await getLinesAsArray(1), ['fba']);
|
||||
});
|
||||
|
||||
it('CNL: Cursor Next Line Ps Times (default = 1) - CSI Ps E', async function(): Promise<any> {
|
||||
await page.evaluate(`
|
||||
// Default
|
||||
window.term.write('\x1b[Ea')
|
||||
// Explicit
|
||||
window.term.write('\x1b[2Eb')
|
||||
`);
|
||||
assert.deepEqual(await getLinesAsArray(4), ['', 'a', '', 'b']);
|
||||
});
|
||||
|
||||
it('CPL: Cursor Preceding Line Ps Times (default = 1) - CSI Ps F', async function(): Promise<any> {
|
||||
await page.evaluate(`
|
||||
// Default
|
||||
window.term.write('\\n\\n\\n\\n\x1b[Fa')
|
||||
// Explicit
|
||||
window.term.write('\x1b[2Fb')
|
||||
`);
|
||||
assert.deepEqual(await getLinesAsArray(5), ['', 'b', '', 'a', '']);
|
||||
});
|
||||
|
||||
it('CHA: Cursor Character Absolute [column] (default = [row,1]) - CSI Ps G', async function(): Promise<any> {
|
||||
await page.evaluate(`
|
||||
// Default
|
||||
window.term.write('foo\x1b[Ga')
|
||||
// Explicit
|
||||
window.term.write('\x1b[10Gb')
|
||||
`);
|
||||
assert.deepEqual(await getLinesAsArray(1), ['aoo b']);
|
||||
});
|
||||
|
||||
it('CUP: Cursor Position [row;column] (default = [1,1]) - CSI Ps ; Ps H', async function(): Promise<any> {
|
||||
await page.evaluate(`
|
||||
// Default
|
||||
window.term.write('foo\x1b[Ha')
|
||||
// Explicit
|
||||
window.term.write('\x1b[3;3Hb')
|
||||
`);
|
||||
assert.deepEqual(await getLinesAsArray(3), ['aoo', '', ' b']);
|
||||
});
|
||||
|
||||
it('CHT: Cursor Forward Tabulation Ps tab stops (default = 1) - CSI Ps I', async function(): Promise<any> {
|
||||
await page.evaluate(`
|
||||
// Default
|
||||
window.term.write('\x1b[Ia')
|
||||
// Explicit
|
||||
window.term.write('\\n\\r\x1b[2Ib')
|
||||
`);
|
||||
assert.deepEqual(await getLinesAsArray(2), [' a', ' b']);
|
||||
});
|
||||
|
||||
it('ED: Erase in Display, VT100 - CSI Ps J', async function(): Promise<any> {
|
||||
const fixture = 'abc\\n\\rdef\\n\\rghi\x1b[2;2H';
|
||||
await page.evaluate(`
|
||||
// Default: Erase Below
|
||||
window.term.resize(5, 5);
|
||||
window.term.write('${fixture}\x1b[J')
|
||||
`);
|
||||
assert.deepEqual(await getLinesAsArray(3), ['abc', 'd', '']);
|
||||
await page.evaluate(`
|
||||
// 0: Erase Below
|
||||
window.term.reset()
|
||||
window.term.write('${fixture}\x1b[0J')
|
||||
`);
|
||||
assert.deepEqual(await getLinesAsArray(3), ['abc', 'd', '']);
|
||||
await page.evaluate(`
|
||||
// 1: Erase Above
|
||||
window.term.reset()
|
||||
window.term.write('${fixture}\x1b[1J')
|
||||
`);
|
||||
assert.deepEqual(await getLinesAsArray(3), ['', ' f', 'ghi']);
|
||||
await page.evaluate(`
|
||||
// 2: Erase Saved Lines (scrollback)
|
||||
window.term.reset()
|
||||
window.term.write('1\\n2\\n3\\n4\\n5${fixture}\x1b[3J')
|
||||
`);
|
||||
assert.equal(await page.evaluate(`window.term.buffer.length`), 5);
|
||||
assert.deepEqual(await getLinesAsArray(5), [' 4', ' 5', 'abc', 'def', 'ghi']);
|
||||
});
|
||||
|
||||
it('DECSED: Erase in Display, VT220 - CSI ? Ps J', async function(): Promise<any> {
|
||||
const fixture = 'abc\\n\\rdef\\n\\rghi\x1b[2;2H';
|
||||
await page.evaluate(`
|
||||
// Default: Erase Below
|
||||
window.term.resize(5, 5);
|
||||
window.term.write('${fixture}\x1b[?J')
|
||||
`);
|
||||
assert.deepEqual(await getLinesAsArray(3), ['abc', 'd', '']);
|
||||
await page.evaluate(`
|
||||
// 0: Erase Below
|
||||
window.term.reset()
|
||||
window.term.write('${fixture}\x1b[?0J')
|
||||
`);
|
||||
assert.deepEqual(await getLinesAsArray(3), ['abc', 'd', '']);
|
||||
await page.evaluate(`
|
||||
// 1: Erase Above
|
||||
window.term.reset()
|
||||
window.term.write('${fixture}\x1b[?1J')
|
||||
`);
|
||||
assert.deepEqual(await getLinesAsArray(3), ['', ' f', 'ghi']);
|
||||
await page.evaluate(`
|
||||
// 2: Erase Saved Lines (scrollback)
|
||||
window.term.reset()
|
||||
window.term.write('1\\n2\\n3\\n4\\n5${fixture}\x1b[?3J')
|
||||
`);
|
||||
assert.equal(await page.evaluate(`window.term.buffer.length`), 5);
|
||||
assert.deepEqual(await getLinesAsArray(5), [' 4', ' 5', 'abc', 'def', 'ghi']);
|
||||
});
|
||||
|
||||
describe('DSR: Device Status Report', () => {
|
||||
it('Status Report - CSI 5 n', async function(): Promise<any> {
|
||||
await page.evaluate(`
|
||||
window.term.onData(e => window.result = e);
|
||||
window.term.write('\\x1b[5n');
|
||||
`);
|
||||
assert.equal(await page.evaluate(`window.result`), '\x1b[0n');
|
||||
});
|
||||
|
||||
it('Report Cursor Position (CPR) - CSI 6 n', async function(): Promise<any> {
|
||||
await page.evaluate(`window.term.write('\\n\\nfoo')`);
|
||||
assert.deepEqual(await page.evaluate(`
|
||||
[window.term.buffer.cursorY, window.term.buffer.cursorX]
|
||||
`), [2, 3]);
|
||||
await page.evaluate(`
|
||||
window.term.onData(e => window.result = e);
|
||||
window.term.write('\\x1b[6n');
|
||||
`);
|
||||
assert.equal(await page.evaluate(`window.result`), '\x1b[3;4R');
|
||||
});
|
||||
|
||||
it('Report Cursor Position (DECXCPR) - CSI ? 6 n', async function(): Promise<any> {
|
||||
await page.evaluate(`window.term.write('\\n\\nfoo')`);
|
||||
assert.deepEqual(await page.evaluate(`
|
||||
[window.term.buffer.cursorY, window.term.buffer.cursorX]
|
||||
`), [2, 3]);
|
||||
await page.evaluate(`
|
||||
window.term.onData(e => window.result = e);
|
||||
window.term.write('\\x1b[?6n');
|
||||
`);
|
||||
assert.equal(await page.evaluate(`window.result`), '\x1b[?3;4R');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -82,3 +241,11 @@ async function openTerminal(options: ITerminalOptions = {}): Promise<void> {
|
||||
await page.waitForSelector('.xterm-text-layer');
|
||||
}
|
||||
}
|
||||
|
||||
async function getLinesAsArray(count: number, start: number = 0): Promise<string[]> {
|
||||
let text = '';
|
||||
for (let i = start; i < start + count; i++) {
|
||||
text += `window.term.buffer.getLine(${i}).translateToString(true),`;
|
||||
}
|
||||
return await page.evaluate(`[${text}]`);
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ import { assert, expect } from 'chai';
|
||||
import { InputHandler } from './InputHandler';
|
||||
import { MockInputHandlingTerminal, TestTerminal } from './TestUtils.test';
|
||||
import { Terminal } from './Terminal';
|
||||
import { IBufferLine } from './core/Types';
|
||||
import { CellData, Attributes, AttributeData, DEFAULT_ATTR_DATA } from './core/buffer/BufferLine';
|
||||
import { IBufferLine } from 'core/Types';
|
||||
import { CellData, Attributes, AttributeData, DEFAULT_ATTR_DATA } from 'core/buffer/BufferLine';
|
||||
|
||||
describe('InputHandler', () => {
|
||||
describe('save and restore cursor', () => {
|
||||
@@ -495,6 +495,46 @@ describe('InputHandler', () => {
|
||||
assert.equal(term.curAttrData.getBgColorMode(), 0);
|
||||
assert.equal(term.curAttrData.getBgColor(), -1);
|
||||
});
|
||||
it('colormode transition RGB to 256', () => {
|
||||
// enter RGB for FG and BG
|
||||
term.writeSync(`\x1b[38;2;1;2;3;48;2;4;5;6m`);
|
||||
// enter 256 for FG and BG
|
||||
term.writeSync(`\x1b[38;5;255;48;5;255m`);
|
||||
assert.equal(term.curAttrData.getFgColorMode(), Attributes.CM_P256);
|
||||
assert.equal(term.curAttrData.getFgColor(), 255);
|
||||
assert.equal(term.curAttrData.getBgColorMode(), Attributes.CM_P256);
|
||||
assert.equal(term.curAttrData.getBgColor(), 255);
|
||||
});
|
||||
it('colormode transition RGB to 16', () => {
|
||||
// enter RGB for FG and BG
|
||||
term.writeSync(`\x1b[38;2;1;2;3;48;2;4;5;6m`);
|
||||
// enter 16 for FG and BG
|
||||
term.writeSync(`\x1b[37;47m`);
|
||||
assert.equal(term.curAttrData.getFgColorMode(), Attributes.CM_P16);
|
||||
assert.equal(term.curAttrData.getFgColor(), 7);
|
||||
assert.equal(term.curAttrData.getBgColorMode(), Attributes.CM_P16);
|
||||
assert.equal(term.curAttrData.getBgColor(), 7);
|
||||
});
|
||||
it('colormode transition 16 to 256', () => {
|
||||
// enter 16 for FG and BG
|
||||
term.writeSync(`\x1b[37;47m`);
|
||||
// enter 256 for FG and BG
|
||||
term.writeSync(`\x1b[38;5;255;48;5;255m`);
|
||||
assert.equal(term.curAttrData.getFgColorMode(), Attributes.CM_P256);
|
||||
assert.equal(term.curAttrData.getFgColor(), 255);
|
||||
assert.equal(term.curAttrData.getBgColorMode(), Attributes.CM_P256);
|
||||
assert.equal(term.curAttrData.getBgColor(), 255);
|
||||
});
|
||||
it('colormode transition 256 to 16', () => {
|
||||
// enter 256 for FG and BG
|
||||
term.writeSync(`\x1b[38;5;255;48;5;255m`);
|
||||
// enter 16 for FG and BG
|
||||
term.writeSync(`\x1b[37;47m`);
|
||||
assert.equal(term.curAttrData.getFgColorMode(), Attributes.CM_P16);
|
||||
assert.equal(term.curAttrData.getFgColor(), 7);
|
||||
assert.equal(term.curAttrData.getBgColorMode(), Attributes.CM_P16);
|
||||
assert.equal(term.curAttrData.getBgColor(), 7);
|
||||
});
|
||||
it('should zero missing RGB values', () => {
|
||||
term.writeSync(`\x1b[38;2;1;2;3m`);
|
||||
term.writeSync(`\x1b[38;2;5m`);
|
||||
|
||||
+12
-11
@@ -5,16 +5,16 @@
|
||||
*/
|
||||
|
||||
import { IInputHandler, IDcsHandler, IEscapeSequenceParser, IInputHandlingTerminal } from './Types';
|
||||
import { C0, C1 } from './common/data/EscapeSequences';
|
||||
import { CHARSETS, DEFAULT_CHARSET } from './core/data/Charsets';
|
||||
import { C0, C1 } from 'common/data/EscapeSequences';
|
||||
import { CHARSETS, DEFAULT_CHARSET } from 'core/data/Charsets';
|
||||
import { wcwidth } from './CharWidth';
|
||||
import { EscapeSequenceParser } from './EscapeSequenceParser';
|
||||
import { IDisposable } from 'xterm';
|
||||
import { Disposable } from './common/Lifecycle';
|
||||
import { concat } from './common/TypedArrayUtils';
|
||||
import { StringToUtf32, stringFromCodePoint, utf32ToString, Utf8ToUtf32 } from './core/input/TextDecoder';
|
||||
import { CellData, Attributes, FgFlags, BgFlags, AttributeData, NULL_CELL_WIDTH, NULL_CELL_CODE, DEFAULT_ATTR_DATA } from './core/buffer/BufferLine';
|
||||
import { EventEmitter2, IEvent } from './common/EventEmitter2';
|
||||
import { Disposable } from 'common/Lifecycle';
|
||||
import { concat } from 'common/TypedArrayUtils';
|
||||
import { StringToUtf32, stringFromCodePoint, utf32ToString, Utf8ToUtf32 } from 'core/input/TextDecoder';
|
||||
import { CellData, Attributes, FgFlags, BgFlags, AttributeData, NULL_CELL_WIDTH, NULL_CELL_CODE, DEFAULT_ATTR_DATA } from 'core/buffer/BufferLine';
|
||||
import { EventEmitter2, IEvent } from 'common/EventEmitter2';
|
||||
|
||||
/**
|
||||
* Map collect to glevel. Used in `selectCharset`.
|
||||
@@ -953,6 +953,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
this._terminal.buffer.x + (params[0] || 1),
|
||||
this._terminal.buffer.getNullCell(this._terminal.eraseAttrData())
|
||||
);
|
||||
this._terminal.updateRange(this._terminal.buffer.y);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1693,7 +1694,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
attr.bg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
|
||||
attr.bg |= DEFAULT_ATTR_DATA.bg & (Attributes.PCOLOR_MASK | Attributes.RGB_MASK);
|
||||
} else if (p === 38) {
|
||||
// fg color 256
|
||||
// fg color 256 and RGB
|
||||
if (params[i + 1] === 2) {
|
||||
i += 2;
|
||||
attr.fg |= Attributes.CM_RGB;
|
||||
@@ -1703,11 +1704,11 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
} else if (params[i + 1] === 5) {
|
||||
i += 2;
|
||||
p = params[i] & 0xff;
|
||||
attr.fg &= ~Attributes.PCOLOR_MASK;
|
||||
attr.fg &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);
|
||||
attr.fg |= Attributes.CM_P256 | p;
|
||||
}
|
||||
} else if (p === 48) {
|
||||
// bg color 256
|
||||
// bg color 256 and RGB
|
||||
if (params[i + 1] === 2) {
|
||||
i += 2;
|
||||
attr.bg |= Attributes.CM_RGB;
|
||||
@@ -1717,7 +1718,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
} else if (params[i + 1] === 5) {
|
||||
i += 2;
|
||||
p = params[i] & 0xff;
|
||||
attr.bg &= ~Attributes.PCOLOR_MASK;
|
||||
attr.bg &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);
|
||||
attr.bg |= Attributes.CM_P256 | p;
|
||||
}
|
||||
} else if (p === 100) {
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
|
||||
import { assert } from 'chai';
|
||||
import { IMouseZoneManager, IMouseZone, ILinkMatcher, ITerminal } from './Types';
|
||||
import { IBufferLine } from './core/Types';
|
||||
import { IBufferLine } from 'core/Types';
|
||||
import { Linkifier } from './Linkifier';
|
||||
import { MockBuffer, MockTerminal, TestTerminal } from './TestUtils.test';
|
||||
import { CircularList } from './common/CircularList';
|
||||
import { BufferLine, CellData } from './core/buffer/BufferLine';
|
||||
import { CircularList } from 'common/CircularList';
|
||||
import { BufferLine, CellData } from 'core/buffer/BufferLine';
|
||||
|
||||
class TestLinkifier extends Linkifier {
|
||||
constructor(terminal: ITerminal) {
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
import { ILinkifierEvent, ILinkMatcher, LinkMatcherHandler, ILinkMatcherOptions, ILinkifier, ITerminal, IBufferStringIteratorResult, IMouseZoneManager } from './Types';
|
||||
import { MouseZone } from './MouseZoneManager';
|
||||
import { getStringCellWidth } from './CharWidth';
|
||||
import { EventEmitter2, IEvent } from './common/EventEmitter2';
|
||||
import { EventEmitter2, IEvent } from 'common/EventEmitter2';
|
||||
|
||||
/**
|
||||
* The Linkifier applies links to rows shortly after they have been refreshed.
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
*/
|
||||
|
||||
import { ITerminal, IMouseZoneManager, IMouseZone } from './Types';
|
||||
import { Disposable } from './common/Lifecycle';
|
||||
import { addDisposableDomListener } from './ui/Lifecycle';
|
||||
import { Disposable } from 'common/Lifecycle';
|
||||
import { addDisposableDomListener } from 'ui/Lifecycle';
|
||||
|
||||
const HOVER_DURATION = 500;
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@ import { SelectionManager, SelectionMode } from './SelectionManager';
|
||||
import { SelectionModel } from './SelectionModel';
|
||||
import { BufferSet } from './BufferSet';
|
||||
import { ITerminal, IBuffer } from './Types';
|
||||
import { IBufferLine } from './core/Types';
|
||||
import { IBufferLine } from 'core/Types';
|
||||
import { MockTerminal } from './TestUtils.test';
|
||||
import { BufferLine, CellData } from './core/buffer/BufferLine';
|
||||
import { BufferLine, CellData } from 'core/buffer/BufferLine';
|
||||
|
||||
class TestMockTerminal extends MockTerminal {
|
||||
emit(event: string, data: any): void {}
|
||||
|
||||
@@ -4,15 +4,15 @@
|
||||
*/
|
||||
|
||||
import { ITerminal, ISelectionManager, IBuffer, ISelectionRedrawRequestEvent } from './Types';
|
||||
import { IBufferLine } from './core/Types';
|
||||
import { IBufferLine } from 'core/Types';
|
||||
import { MouseHelper } from './MouseHelper';
|
||||
import * as Browser from './common/Platform';
|
||||
import * as Browser from 'common/Platform';
|
||||
import { CharMeasure } from './CharMeasure';
|
||||
import { SelectionModel } from './SelectionModel';
|
||||
import { AltClickHandler } from './handlers/AltClickHandler';
|
||||
import { CellData } from './core/buffer/BufferLine';
|
||||
import { CellData } from 'core/buffer/BufferLine';
|
||||
import { IDisposable } from 'xterm';
|
||||
import { EventEmitter2, IEvent } from './common/EventEmitter2';
|
||||
import { EventEmitter2, IEvent } from 'common/EventEmitter2';
|
||||
|
||||
/**
|
||||
* The number of pixels the mouse needs to be above or below the viewport in
|
||||
|
||||
@@ -14,7 +14,7 @@ import * as pty from 'node-pty';
|
||||
import { assert } from 'chai';
|
||||
import { Terminal } from './Terminal';
|
||||
import { IViewport } from './Types';
|
||||
import { CellData, WHITESPACE_CELL_CHAR } from './core/buffer/BufferLine';
|
||||
import { CellData, WHITESPACE_CELL_CHAR } from 'core/buffer/BufferLine';
|
||||
|
||||
class TestTerminal extends Terminal {
|
||||
innerWrite(): void { this._innerWrite(); }
|
||||
@@ -91,7 +91,8 @@ if (os.platform() !== 'win32') {
|
||||
primitivePty = (<any>pty).native.open(cols, rows);
|
||||
|
||||
/** tests */
|
||||
describe('xterm output comparison', () => {
|
||||
describe('xterm output comparison', function(): void {
|
||||
this.timeout(10000);
|
||||
let xterm: TestTerminal;
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { assert, expect } from 'chai';
|
||||
import { Terminal } from './Terminal';
|
||||
import { MockViewport, MockCompositionHelper, MockRenderer } from './TestUtils.test';
|
||||
import { CellData, DEFAULT_ATTR_DATA } from './core/buffer/BufferLine';
|
||||
import { CellData, DEFAULT_ATTR_DATA } from 'core/buffer/BufferLine';
|
||||
|
||||
const INIT_COLS = 80;
|
||||
const INIT_ROWS = 24;
|
||||
|
||||
+41
-22
@@ -26,17 +26,17 @@ import { IRenderer } from './renderer/Types';
|
||||
import { BufferSet } from './BufferSet';
|
||||
import { Buffer, MAX_BUFFER_SIZE } from './Buffer';
|
||||
import { CompositionHelper } from './CompositionHelper';
|
||||
import { EventEmitter } from './common/EventEmitter';
|
||||
import { EventEmitter } from 'common/EventEmitter';
|
||||
import { Viewport } from './Viewport';
|
||||
import { rightClickHandler, moveTextAreaUnderMouseCursor, pasteHandler, copyHandler } from './Clipboard';
|
||||
import { C0 } from './common/data/EscapeSequences';
|
||||
import { C0 } from 'common/data/EscapeSequences';
|
||||
import { InputHandler } from './InputHandler';
|
||||
import { Renderer } from './renderer/Renderer';
|
||||
import { Linkifier } from './Linkifier';
|
||||
import { SelectionManager } from './SelectionManager';
|
||||
import { CharMeasure } from './CharMeasure';
|
||||
import * as Browser from './common/Platform';
|
||||
import { addDisposableDomListener } from './ui/Lifecycle';
|
||||
import * as Browser from 'common/Platform';
|
||||
import { addDisposableDomListener } from 'ui/Lifecycle';
|
||||
import * as Strings from './Strings';
|
||||
import { MouseHelper } from './MouseHelper';
|
||||
import { DEFAULT_BELL_SOUND, SoundManager } from './SoundManager';
|
||||
@@ -45,14 +45,14 @@ import { AccessibilityManager } from './AccessibilityManager';
|
||||
import { ITheme, IMarker, IDisposable, ISelectionPosition } from 'xterm';
|
||||
import { removeTerminalFromCache } from './renderer/atlas/CharAtlasCache';
|
||||
import { DomRenderer } from './renderer/dom/DomRenderer';
|
||||
import { IKeyboardEvent } from './common/Types';
|
||||
import { evaluateKeyboardEvent } from './core/input/Keyboard';
|
||||
import { KeyboardResultType, ICharset, IBufferLine, IAttributeData } from './core/Types';
|
||||
import { clone } from './common/Clone';
|
||||
import { EventEmitter2, IEvent } from './common/EventEmitter2';
|
||||
import { Attributes, DEFAULT_ATTR_DATA } from './core/buffer/BufferLine';
|
||||
import { IKeyboardEvent } from 'common/Types';
|
||||
import { evaluateKeyboardEvent } from 'core/input/Keyboard';
|
||||
import { KeyboardResultType, ICharset, IBufferLine, IAttributeData } from 'core/Types';
|
||||
import { clone } from 'common/Clone';
|
||||
import { EventEmitter2, IEvent } from 'common/EventEmitter2';
|
||||
import { Attributes, DEFAULT_ATTR_DATA } from 'core/buffer/BufferLine';
|
||||
import { applyWindowsMode } from './WindowsMode';
|
||||
import { ColorManager } from './ui/ColorManager';
|
||||
import { ColorManager } from 'ui/ColorManager';
|
||||
import { RenderCoordinator } from './renderer/RenderCoordinator';
|
||||
|
||||
// Let it work inside Node.js for automated testing purposes.
|
||||
@@ -72,6 +72,7 @@ const WRITE_BUFFER_PAUSE_THRESHOLD = 5;
|
||||
* depends on the time it takes for the renderer to draw the frame.
|
||||
*/
|
||||
const WRITE_TIMEOUT_MS = 12;
|
||||
const WRITE_BUFFER_LENGTH_THRESHOLD = 50;
|
||||
|
||||
const MINIMUM_COLS = 2; // Less than 2 can mess with wide chars
|
||||
const MINIMUM_ROWS = 1;
|
||||
@@ -91,8 +92,6 @@ const DEFAULT_OPTIONS: ITerminalOptions = {
|
||||
bellSound: DEFAULT_BELL_SOUND,
|
||||
bellStyle: 'none',
|
||||
drawBoldTextInBrightColors: true,
|
||||
enableBold: true,
|
||||
experimentalCharAtlas: 'static',
|
||||
fontFamily: 'courier-new, courier, monospace',
|
||||
fontSize: 15,
|
||||
fontWeight: 'normal',
|
||||
@@ -289,13 +288,6 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use dispose instead.
|
||||
*/
|
||||
public destroy(): void {
|
||||
this.dispose();
|
||||
}
|
||||
|
||||
private _setup(): void {
|
||||
Object.keys(DEFAULT_OPTIONS).forEach((key) => {
|
||||
if (this.options[key] === null || this.options[key] === undefined) {
|
||||
@@ -502,8 +494,6 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
|
||||
}
|
||||
break;
|
||||
case 'drawBoldTextInBrightColors':
|
||||
case 'experimentalCharAtlas':
|
||||
case 'enableBold':
|
||||
case 'letterSpacing':
|
||||
case 'lineHeight':
|
||||
case 'fontWeight':
|
||||
@@ -1436,6 +1426,11 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
|
||||
}
|
||||
if (this.writeBufferUtf8.length > bufferOffset) {
|
||||
// Allow renderer to catch up before processing the next batch
|
||||
// trim already processed chunks if we are above threshold
|
||||
if (bufferOffset > WRITE_BUFFER_LENGTH_THRESHOLD) {
|
||||
this.writeBufferUtf8 = this.writeBufferUtf8.slice(bufferOffset);
|
||||
bufferOffset = 0;
|
||||
}
|
||||
setTimeout(() => this._innerWriteUtf8(bufferOffset), 0);
|
||||
} else {
|
||||
this._writeInProgress = false;
|
||||
@@ -1518,6 +1513,11 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
|
||||
}
|
||||
if (this.writeBuffer.length > bufferOffset) {
|
||||
// Allow renderer to catch up before processing the next batch
|
||||
// trim already processed chunks if we are above threshold
|
||||
if (bufferOffset > WRITE_BUFFER_LENGTH_THRESHOLD) {
|
||||
this.writeBuffer = this.writeBuffer.slice(bufferOffset);
|
||||
bufferOffset = 0;
|
||||
}
|
||||
setTimeout(() => this._innerWrite(bufferOffset), 0);
|
||||
} else {
|
||||
this._writeInProgress = false;
|
||||
@@ -2003,15 +2003,34 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
|
||||
* ESC c Full Reset (RIS).
|
||||
*/
|
||||
public reset(): void {
|
||||
/**
|
||||
* Since _setup handles a full terminal creation, we have to carry forward
|
||||
* a few things that should not reset.
|
||||
*/
|
||||
this.options.rows = this.rows;
|
||||
this.options.cols = this.cols;
|
||||
const customKeyEventHandler = this._customKeyEventHandler;
|
||||
const inputHandler = this._inputHandler;
|
||||
const cursorState = this.cursorState;
|
||||
const writeBuffer = this.writeBuffer;
|
||||
const writeBufferUtf8 = this.writeBufferUtf8;
|
||||
const writeInProgress = this._writeInProgress;
|
||||
const xoffSentToCatchUp = this._xoffSentToCatchUp;
|
||||
const userScrolling = this._userScrolling;
|
||||
|
||||
this._setup();
|
||||
|
||||
// reattach
|
||||
this._customKeyEventHandler = customKeyEventHandler;
|
||||
this._inputHandler = inputHandler;
|
||||
this.cursorState = cursorState;
|
||||
this.writeBuffer = writeBuffer;
|
||||
this.writeBufferUtf8 = writeBufferUtf8;
|
||||
this._writeInProgress = writeInProgress;
|
||||
this._xoffSentToCatchUp = xoffSentToCatchUp;
|
||||
this._userScrolling = userScrolling;
|
||||
|
||||
// do a full screen refresh
|
||||
this.refresh(0, this.rows - 1);
|
||||
if (this.viewport) {
|
||||
this.viewport.syncScrollArea();
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
|
||||
import { IRenderer, IRenderDimensions } from './renderer/Types';
|
||||
import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminal, IBuffer, IBufferSet, IBrowser, ICharMeasure, ISelectionManager, ITerminalOptions, ILinkifier, IMouseHelper, ILinkMatcherOptions, CharacterJoinerHandler, IBufferStringIterator } from './Types';
|
||||
import { IBufferLine, ICellData, IAttributeData } from './core/Types';
|
||||
import { ICircularList, XtermListener } from './common/Types';
|
||||
import { IBufferLine, ICellData, IAttributeData } from 'core/Types';
|
||||
import { ICircularList, XtermListener } from 'common/Types';
|
||||
import { Buffer } from './Buffer';
|
||||
import * as Browser from './common/Platform';
|
||||
import * as Browser from 'common/Platform';
|
||||
import { IDisposable, IMarker, IEvent, ISelectionPosition } from 'xterm';
|
||||
import { Terminal } from './Terminal';
|
||||
import { AttributeData } from './core/buffer/BufferLine';
|
||||
import { IColorManager, IColorSet } from './ui/Types';
|
||||
import { AttributeData } from 'core/buffer/BufferLine';
|
||||
import { IColorManager, IColorSet } from 'ui/Types';
|
||||
|
||||
export class TestTerminal extends Terminal {
|
||||
writeSync(data: string): void {
|
||||
@@ -102,9 +102,6 @@ export class MockTerminal implements ITerminal {
|
||||
dispose(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
destroy(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
scrollPages(pageCount: number): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
+4
-5
@@ -4,10 +4,10 @@
|
||||
*/
|
||||
|
||||
import { ITerminalOptions as IPublicTerminalOptions, IEventEmitter, IDisposable, IMarker, ISelectionPosition } from 'xterm';
|
||||
import { ICharset, IAttributeData, ICellData, IBufferLine, CharData } from './core/Types';
|
||||
import { ICircularList } from './common/Types';
|
||||
import { IEvent } from './common/EventEmitter2';
|
||||
import { IColorSet } from './ui/Types';
|
||||
import { ICharset, IAttributeData, ICellData, IBufferLine, CharData } from 'core/Types';
|
||||
import { ICircularList } from 'common/Types';
|
||||
import { IEvent } from 'common/EventEmitter2';
|
||||
import { IColorSet } from 'ui/Types';
|
||||
|
||||
export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean;
|
||||
|
||||
@@ -257,7 +257,6 @@ export interface IPublicTerminal extends IDisposable, IEventEmitter {
|
||||
selectAll(): void;
|
||||
selectLines(start: number, end: number): void;
|
||||
dispose(): void;
|
||||
destroy(): void;
|
||||
scrollLines(amount: number): void;
|
||||
scrollPages(pageCount: number): void;
|
||||
scrollToTop(): void;
|
||||
|
||||
+3
-3
@@ -5,9 +5,9 @@
|
||||
|
||||
import { ITerminal, IViewport } from './Types';
|
||||
import { CharMeasure } from './CharMeasure';
|
||||
import { Disposable } from './common/Lifecycle';
|
||||
import { addDisposableDomListener } from './ui/Lifecycle';
|
||||
import { IColorSet } from './ui/Types';
|
||||
import { Disposable } from 'common/Lifecycle';
|
||||
import { addDisposableDomListener } from 'ui/Lifecycle';
|
||||
import { IColorSet } from 'ui/Types';
|
||||
import { IRenderDimensions } from './renderer/Types';
|
||||
|
||||
const FALLBACK_SCROLL_BAR_WIDTH = 15;
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
|
||||
import { IDisposable } from 'xterm';
|
||||
import { ITerminal } from './Types';
|
||||
import { CHAR_DATA_CODE_INDEX, NULL_CELL_CODE, WHITESPACE_CELL_CODE } from './core/buffer/BufferLine';
|
||||
import { CHAR_DATA_CODE_INDEX, NULL_CELL_CODE, WHITESPACE_CELL_CODE } from 'core/buffer/BufferLine';
|
||||
|
||||
export function applyWindowsMode(terminal: ITerminal): IDisposable {
|
||||
// Winpty does not support wraparound mode which means that lines will never
|
||||
|
||||
@@ -16,7 +16,7 @@ class MockTerminal {
|
||||
public searchHelper: TestSearchHelper;
|
||||
public cols: number;
|
||||
constructor(options: any) {
|
||||
this._core = new (require('../../../lib/Terminal')).Terminal(options);
|
||||
this._core = new (require('../../../out/Terminal')).Terminal(options);
|
||||
this.searchHelper = new TestSearchHelper(this as any);
|
||||
this.cols = options.cols;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { assert } from 'chai';
|
||||
import { CircularList } from './CircularList';
|
||||
import { CircularList } from 'common/CircularList';
|
||||
|
||||
describe('CircularList', () => {
|
||||
describe('push', () => {
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { ICircularList } from './Types';
|
||||
import { EventEmitter2, IEvent } from './EventEmitter2';
|
||||
import { ICircularList } from 'common/Types';
|
||||
import { EventEmitter2, IEvent } from 'common/EventEmitter2';
|
||||
|
||||
export interface IInsertEvent {
|
||||
index: number;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { assert, expect } from 'chai';
|
||||
import { clone } from './Clone';
|
||||
import { clone } from 'common/Clone';
|
||||
|
||||
describe('clone', () => {
|
||||
it('should clone simple objects', () => {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { assert } from 'chai';
|
||||
import { EventEmitter } from './EventEmitter';
|
||||
import { EventEmitter } from 'common/EventEmitter';
|
||||
|
||||
describe('EventEmitter', () => {
|
||||
let eventEmitter: EventEmitter;
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { IDisposable, IEventEmitter, XtermListener } from './Types';
|
||||
import { Disposable } from './Lifecycle';
|
||||
import { IDisposable, IEventEmitter, XtermListener } from 'common/Types';
|
||||
import { Disposable } from 'common/Lifecycle';
|
||||
|
||||
export class EventEmitter extends Disposable implements IEventEmitter, IDisposable {
|
||||
private _events: {[type: string]: XtermListener[]};
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { assert } from 'chai';
|
||||
import { EventEmitter2 } from './EventEmitter2';
|
||||
import { EventEmitter2 } from 'common/EventEmitter2';
|
||||
|
||||
describe('EventEmitter2', () => {
|
||||
it('should fire listeners multiple times', () => {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { IDisposable } from './Types';
|
||||
import { IDisposable } from 'common/Types';
|
||||
|
||||
interface IListener<T> {
|
||||
(e: T): void;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { assert } from 'chai';
|
||||
import { Disposable } from './Lifecycle';
|
||||
import { Disposable } from 'common/Lifecycle';
|
||||
|
||||
class TestDisposable extends Disposable {
|
||||
public get isDisposed(): boolean {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { IDisposable } from './Types';
|
||||
import { IDisposable } from 'common/Types';
|
||||
|
||||
/**
|
||||
* A base class that can be extended to provide convenience methods for managing the lifecycle of an
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
import { assert } from 'chai';
|
||||
import { fillFallback, concat } from './TypedArrayUtils';
|
||||
import { fillFallback, concat } from 'common/TypedArrayUtils';
|
||||
|
||||
type TypedArray = Uint8Array | Uint16Array | Uint32Array | Uint8ClampedArray
|
||||
| Int8Array | Int16Array | Int32Array
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { IEvent, EventEmitter2 } from './EventEmitter2';
|
||||
import { IDeleteEvent, IInsertEvent } from './CircularList';
|
||||
import { IEvent, EventEmitter2 } from 'common/EventEmitter2';
|
||||
import { IDeleteEvent, IInsertEvent } from 'common/CircularList';
|
||||
|
||||
export const DEFAULT_COLOR = 256;
|
||||
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
{
|
||||
"extends": "../tsconfig-library-base",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../lib",
|
||||
"outDir": "../../out",
|
||||
"types": [
|
||||
"../../node_modules/@types/mocha"
|
||||
]
|
||||
],
|
||||
"baseUrl": "..",
|
||||
"paths": {
|
||||
"common/*": [ "./common/*" ]
|
||||
}
|
||||
},
|
||||
"include": [ "./**/*" ]
|
||||
}
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { IDisposable } from '../common/Types';
|
||||
import { IDisposable } from 'common/Types';
|
||||
|
||||
export const enum KeyboardResultType {
|
||||
SEND_KEY,
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { CharData, IBufferLine, ICellData, IColorRGB, IAttributeData } from '../Types';
|
||||
import { stringFromCodePoint } from '../input/TextDecoder';
|
||||
import { DEFAULT_COLOR } from '../../common/Types';
|
||||
import { CharData, IBufferLine, ICellData, IColorRGB, IAttributeData } from 'core/Types';
|
||||
import { stringFromCodePoint } from 'core/input/TextDecoder';
|
||||
import { DEFAULT_COLOR } from 'common/Types';
|
||||
|
||||
export const DEFAULT_ATTR = (0 << 18) | (DEFAULT_COLOR << 9) | (256 << 0);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
* @license MIT
|
||||
*/
|
||||
import { assert } from 'chai';
|
||||
import { BufferLine, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE } from './BufferLine';
|
||||
import { reflowSmallerGetNewLineLengths } from './BufferReflow';
|
||||
import { BufferLine, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE } from 'core/buffer/BufferLine';
|
||||
import { reflowSmallerGetNewLineLengths } from 'core/buffer/BufferReflow';
|
||||
|
||||
describe('BufferReflow', () => {
|
||||
describe('reflowSmallerGetNewLineLengths', () => {
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { BufferLine } from './BufferLine';
|
||||
import { CircularList } from '../../common/CircularList';
|
||||
import { IBufferLine, ICellData } from '../Types';
|
||||
import { BufferLine } from 'core/buffer/BufferLine';
|
||||
import { CircularList } from 'common/CircularList';
|
||||
import { IBufferLine, ICellData } from 'core/Types';
|
||||
|
||||
export interface INewLayoutResult {
|
||||
layout: number[];
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { EventEmitter2, IEvent } from '../../common/EventEmitter2';
|
||||
import { Disposable } from '../../common/Lifecycle';
|
||||
import { IMarker } from '../Types';
|
||||
import { EventEmitter2, IEvent } from 'common/EventEmitter2';
|
||||
import { Disposable } from 'common/Lifecycle';
|
||||
import { IMarker } from 'core/Types';
|
||||
|
||||
export class Marker extends Disposable implements IMarker {
|
||||
private static _nextId = 1;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { ICharset } from '../Types';
|
||||
import { ICharset } from 'core/Types';
|
||||
|
||||
/**
|
||||
* The character sets supported by the terminal. These enable several languages
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
import { assert } from 'chai';
|
||||
import { evaluateKeyboardEvent } from './Keyboard';
|
||||
import { IKeyboardResult } from '../Types';
|
||||
import { IKeyboardEvent } from '../../common/Types';
|
||||
import { evaluateKeyboardEvent } from 'core/input/Keyboard';
|
||||
import { IKeyboardResult } from 'core/Types';
|
||||
import { IKeyboardEvent } from 'common/Types';
|
||||
|
||||
/**
|
||||
* A helper function for testing which allows passing in a partial event and defaults will be filled
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { IKeyboardEvent } from '../../common/Types';
|
||||
import { IKeyboardResult, KeyboardResultType } from '../Types';
|
||||
import { C0 } from '../../common/data/EscapeSequences';
|
||||
import { IKeyboardEvent } from 'common/Types';
|
||||
import { IKeyboardResult, KeyboardResultType } from 'core/Types';
|
||||
import { C0 } from 'common/data/EscapeSequences';
|
||||
|
||||
// reg + shift key mappings for digits and special chars
|
||||
const KEYCODE_KEY_MAPPINGS: { [key: number]: [string, string]} = {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { assert } from 'chai';
|
||||
import { StringToUtf32, stringFromCodePoint, Utf8ToUtf32, utf32ToString } from './TextDecoder';
|
||||
import { StringToUtf32, stringFromCodePoint, Utf8ToUtf32, utf32ToString } from 'core/input/TextDecoder';
|
||||
import { encode } from 'utf8';
|
||||
|
||||
// convert UTF32 codepoints to string
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
{
|
||||
"extends": "../tsconfig-library-base",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../lib",
|
||||
"outDir": "../../out",
|
||||
"types": [
|
||||
"../../node_modules/@types/mocha"
|
||||
]
|
||||
],
|
||||
"baseUrl": "..",
|
||||
"paths": {
|
||||
"common/*": [ "./common/*" ],
|
||||
"core/*": [ "./core/*" ]
|
||||
}
|
||||
},
|
||||
"include": [ "./**/*" ],
|
||||
"references": [
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
*/
|
||||
|
||||
import { ITerminal } from '../Types';
|
||||
import { IBufferLine } from '../core/Types';
|
||||
import { ICircularList } from '../common/Types';
|
||||
import { C0 } from '../common/data/EscapeSequences';
|
||||
import { IBufferLine } from 'core/Types';
|
||||
import { ICircularList } from 'common/Types';
|
||||
import { C0 } from 'common/data/EscapeSequences';
|
||||
|
||||
const enum Direction {
|
||||
UP = 'A',
|
||||
|
||||
@@ -50,7 +50,7 @@ export class AddonManager implements IDisposable {
|
||||
throw new Error('Could not dispose an addon that has not been loaded');
|
||||
}
|
||||
loadedAddon.isDisposed = true;
|
||||
loadedAddon.dispose();
|
||||
loadedAddon.dispose.apply(loadedAddon.instance);
|
||||
this._addons.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ const width = 800;
|
||||
const height = 600;
|
||||
|
||||
describe('API Integration Tests', function(): void {
|
||||
this.timeout(10000);
|
||||
this.timeout(20000);
|
||||
|
||||
before(async function(): Promise<any> {
|
||||
browser = await puppeteer.launch({
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
|
||||
import { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings, ITerminalAddon, ISelectionPosition, IBuffer as IBufferApi, IBufferLine as IBufferLineApi, IBufferCell as IBufferCellApi } from 'xterm';
|
||||
import { ITerminal, IBuffer } from '../Types';
|
||||
import { IBufferLine } from '../core/Types';
|
||||
import { IBufferLine } from 'core/Types';
|
||||
import { Terminal as TerminalCore } from '../Terminal';
|
||||
import * as Strings from '../Strings';
|
||||
import { IEvent } from '../common/EventEmitter2';
|
||||
import { IEvent } from 'common/EventEmitter2';
|
||||
import { AddonManager } from './AddonManager';
|
||||
import { WebglRendererAddon } from '../renderer/webgl/WebglRendererAddon';
|
||||
|
||||
@@ -123,9 +123,6 @@ export class Terminal implements ITerminalApi {
|
||||
this._addonManager.dispose();
|
||||
this._core.dispose();
|
||||
}
|
||||
public destroy(): void {
|
||||
this._core.destroy();
|
||||
}
|
||||
public scrollLines(amount: number): void {
|
||||
this._core.scrollLines(amount);
|
||||
}
|
||||
@@ -151,7 +148,7 @@ export class Terminal implements ITerminalApi {
|
||||
this._core.writeUtf8(data);
|
||||
}
|
||||
public getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'fontWeight' | 'fontWeightBold' | 'rendererType' | 'termName'): string;
|
||||
public getOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell'): boolean;
|
||||
public getOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell'): boolean;
|
||||
public getOption(key: 'colors'): string[];
|
||||
public getOption(key: 'cols' | 'fontSize' | 'letterSpacing' | 'lineHeight' | 'rows' | 'tabStopWidth' | 'scrollback'): number;
|
||||
public getOption(key: 'handler'): (data: string) => void;
|
||||
@@ -163,7 +160,7 @@ export class Terminal implements ITerminalApi {
|
||||
public setOption(key: 'fontWeight' | 'fontWeightBold', value: 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'): void;
|
||||
public setOption(key: 'bellStyle', value: 'none' | 'visual' | 'sound' | 'both'): void;
|
||||
public setOption(key: 'cursorStyle', value: 'block' | 'underline' | 'bar'): void;
|
||||
public setOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell', value: boolean): void;
|
||||
public setOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell', value: boolean): void;
|
||||
public setOption(key: 'colors', value: string[]): void;
|
||||
public setOption(key: 'fontSize' | 'letterSpacing' | 'lineHeight' | 'tabStopWidth' | 'scrollback', value: number): void;
|
||||
public setOption(key: 'handler', value: (data: string) => void): void;
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
|
||||
import { IRenderLayer, IRenderDimensions } from './Types';
|
||||
import { ITerminal } from '../Types';
|
||||
import { ICellData } from '../core/Types';
|
||||
import { DEFAULT_COLOR } from '../common/Types';
|
||||
import { ICellData } from 'core/Types';
|
||||
import { DEFAULT_COLOR } from 'common/Types';
|
||||
import { DIM_OPACITY, INVERTED_DEFAULT_COLOR, IGlyphIdentifier } from './atlas/Types';
|
||||
import BaseCharAtlas from './atlas/BaseCharAtlas';
|
||||
import { BaseCharAtlas } from './atlas/BaseCharAtlas';
|
||||
import { acquireCharAtlas } from './atlas/CharAtlasCache';
|
||||
import { CellData, AttributeData, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_CODE } from '../core/buffer/BufferLine';
|
||||
import { IColorSet } from '../ui/Types';
|
||||
import { CellData, AttributeData, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_CODE } from 'core/buffer/BufferLine';
|
||||
import { IColorSet } from 'ui/Types';
|
||||
|
||||
export abstract class BaseRenderLayer implements IRenderLayer {
|
||||
private _canvas: HTMLCanvasElement;
|
||||
@@ -288,7 +288,7 @@ export abstract class BaseRenderLayer implements IRenderLayer {
|
||||
this._currentGlyphIdentifier.code = cell.getCode() || WHITESPACE_CELL_CODE;
|
||||
this._currentGlyphIdentifier.bg = bg;
|
||||
this._currentGlyphIdentifier.fg = fg;
|
||||
this._currentGlyphIdentifier.bold = cell.isBold() && terminal.options.enableBold;
|
||||
this._currentGlyphIdentifier.bold = !!cell.isBold();
|
||||
this._currentGlyphIdentifier.dim = !!cell.isDim();
|
||||
this._currentGlyphIdentifier.italic = !!cell.isItalic();
|
||||
const atlasDidDraw = this._charAtlas && this._charAtlas.draw(
|
||||
@@ -316,7 +316,7 @@ export abstract class BaseRenderLayer implements IRenderLayer {
|
||||
*/
|
||||
private _drawUncachedChars(terminal: ITerminal, cell: ICellData, x: number, y: number): void {
|
||||
this._ctx.save();
|
||||
this._ctx.font = this._getFont(terminal, cell.isBold() && terminal.options.enableBold, !!cell.isItalic());
|
||||
this._ctx.font = this._getFont(terminal, !!cell.isBold(), !!cell.isItalic());
|
||||
this._ctx.textBaseline = 'middle';
|
||||
|
||||
if (cell.isInverse()) {
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
import { assert } from 'chai';
|
||||
|
||||
import { MockTerminal, MockBuffer } from '../TestUtils.test';
|
||||
import { CircularList } from '../common/CircularList';
|
||||
import { CircularList } from 'common/CircularList';
|
||||
|
||||
import { ICharacterJoinerRegistry } from './Types';
|
||||
import { CharacterJoinerRegistry } from './CharacterJoinerRegistry';
|
||||
import { BufferLine, CellData } from '../core/buffer/BufferLine';
|
||||
import { IBufferLine } from '../core/Types';
|
||||
import { BufferLine, CellData } from 'core/buffer/BufferLine';
|
||||
import { IBufferLine } from 'core/Types';
|
||||
|
||||
describe('CharacterJoinerRegistry', () => {
|
||||
let registry: ICharacterJoinerRegistry;
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
*/
|
||||
|
||||
import { ITerminal } from '../Types';
|
||||
import { IBufferLine, ICellData, CharData } from '../core/Types';
|
||||
import { IBufferLine, ICellData, CharData } from 'core/Types';
|
||||
import { ICharacterJoinerRegistry, ICharacterJoiner } from './Types';
|
||||
import { CellData, Content, AttributeData, WHITESPACE_CELL_CHAR } from '../core/buffer/BufferLine';
|
||||
import { CellData, Content, AttributeData, WHITESPACE_CELL_CHAR } from 'core/buffer/BufferLine';
|
||||
|
||||
export class JoinedCellData extends AttributeData implements ICellData {
|
||||
private _width: number;
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
import { IRenderDimensions } from './Types';
|
||||
import { BaseRenderLayer } from './BaseRenderLayer';
|
||||
import { ITerminal } from '../Types';
|
||||
import { ICellData } from '../core/Types';
|
||||
import { CellData } from '../core/buffer/BufferLine';
|
||||
import { IColorSet } from '../ui/Types';
|
||||
import { ICellData } from 'core/Types';
|
||||
import { CellData } from 'core/buffer/BufferLine';
|
||||
import { IColorSet } from 'ui/Types';
|
||||
|
||||
interface ICursorState {
|
||||
x: number;
|
||||
|
||||
@@ -8,7 +8,7 @@ import { IRenderDimensions } from './Types';
|
||||
import { BaseRenderLayer } from './BaseRenderLayer';
|
||||
import { INVERTED_DEFAULT_COLOR } from './atlas/Types';
|
||||
import { is256Color } from './atlas/CharAtlasUtils';
|
||||
import { IColorSet } from '../ui/Types';
|
||||
import { IColorSet } from 'ui/Types';
|
||||
|
||||
export class LinkRenderLayer extends BaseRenderLayer {
|
||||
private _state: ILinkifierEvent = null;
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
*/
|
||||
|
||||
import { IRenderer, IRenderDimensions } from './Types';
|
||||
import { RenderDebouncer } from '../ui/RenderDebouncer';
|
||||
import { EventEmitter2, IEvent } from '../common/EventEmitter2';
|
||||
import { Disposable } from '../common/Lifecycle';
|
||||
import { ScreenDprMonitor } from '../ui/ScreenDprMonitor';
|
||||
import { addDisposableDomListener } from '../ui/Lifecycle';
|
||||
import { IColorSet } from '..//ui/Types';
|
||||
import { RenderDebouncer } from 'ui/RenderDebouncer';
|
||||
import { EventEmitter2, IEvent } from 'common/EventEmitter2';
|
||||
import { Disposable } from 'common/Lifecycle';
|
||||
import { ScreenDprMonitor } from 'ui/ScreenDprMonitor';
|
||||
import { addDisposableDomListener } from 'ui/Lifecycle';
|
||||
import { IColorSet } from 'ui/Types';
|
||||
import { CharacterJoinerHandler } from '../Types';
|
||||
|
||||
export class RenderCoordinator extends Disposable {
|
||||
|
||||
@@ -10,8 +10,8 @@ import { IRenderLayer, IRenderer, IRenderDimensions, ICharacterJoinerRegistry }
|
||||
import { ITerminal, CharacterJoinerHandler } from '../Types';
|
||||
import { LinkRenderLayer } from './LinkRenderLayer';
|
||||
import { CharacterJoinerRegistry } from '../renderer/CharacterJoinerRegistry';
|
||||
import { Disposable } from '../common/Lifecycle';
|
||||
import { IColorSet } from '../ui/Types';
|
||||
import { Disposable } from 'common/Lifecycle';
|
||||
import { IColorSet } from 'ui/Types';
|
||||
|
||||
export class Renderer extends Disposable implements IRenderer {
|
||||
private _renderLayers: IRenderLayer[];
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { ITerminal } from '../Types';
|
||||
import { IRenderDimensions } from './Types';
|
||||
import { BaseRenderLayer } from './BaseRenderLayer';
|
||||
import { IColorSet } from '../ui/Types';
|
||||
import { IColorSet } from 'ui/Types';
|
||||
|
||||
interface ISelectionState {
|
||||
start: [number, number];
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
|
||||
import { IRenderDimensions, ICharacterJoinerRegistry } from './Types';
|
||||
import { ITerminal } from '../Types';
|
||||
import { CharData, ICellData } from '../core/Types';
|
||||
import { CharData, ICellData } from 'core/Types';
|
||||
import { GridCache } from './GridCache';
|
||||
import { BaseRenderLayer } from './BaseRenderLayer';
|
||||
import { CellData, AttributeData, Content, NULL_CELL_CODE } from '../core/buffer/BufferLine';
|
||||
import { CellData, AttributeData, Content, NULL_CELL_CODE } from 'core/buffer/BufferLine';
|
||||
import { JoinedCellData } from './CharacterJoinerRegistry';
|
||||
import { IColorSet } from '../ui/Types';
|
||||
import { IColorSet } from 'ui/Types';
|
||||
|
||||
/**
|
||||
* This CharData looks like a null character, which will forc a clear and render
|
||||
@@ -205,6 +205,7 @@ export class TextRenderLayer extends BaseRenderLayer {
|
||||
if (cell.isInvisible()) {
|
||||
return;
|
||||
}
|
||||
this.drawChars(terminal, cell, x, y);
|
||||
if (cell.isUnderline()) {
|
||||
this._ctx.save();
|
||||
|
||||
@@ -233,7 +234,6 @@ export class TextRenderLayer extends BaseRenderLayer {
|
||||
this.fillBottomLineAtCells(x, y, cell.getWidth());
|
||||
this._ctx.restore();
|
||||
}
|
||||
this.drawChars(terminal, cell, x, y);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { ITerminal, CharacterJoinerHandler } from '../Types';
|
||||
import { IDisposable } from 'xterm';
|
||||
import { IColorSet } from '../ui/Types';
|
||||
import { IColorSet } from 'ui/Types';
|
||||
|
||||
/**
|
||||
* Flags used to render terminal text properly.
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { IGlyphIdentifier } from './Types';
|
||||
import { IDisposable } from 'xterm';
|
||||
|
||||
export default abstract class BaseCharAtlas implements IDisposable {
|
||||
export abstract class BaseCharAtlas implements IDisposable {
|
||||
private _didWarmUp: boolean = false;
|
||||
|
||||
public dispose(): void { }
|
||||
|
||||
@@ -5,18 +5,10 @@
|
||||
|
||||
import { ITerminal } from '../../Types';
|
||||
import { generateConfig, configEquals } from './CharAtlasUtils';
|
||||
import BaseCharAtlas from './BaseCharAtlas';
|
||||
import DynamicCharAtlas from './DynamicCharAtlas';
|
||||
import NoneCharAtlas from './NoneCharAtlas';
|
||||
import StaticCharAtlas from './StaticCharAtlas';
|
||||
import { BaseCharAtlas } from './BaseCharAtlas';
|
||||
import { DynamicCharAtlas } from './DynamicCharAtlas';
|
||||
import { ICharAtlasConfig } from './Types';
|
||||
import { IColorSet } from '../../ui/Types';
|
||||
|
||||
const charAtlasImplementations = {
|
||||
'none': NoneCharAtlas,
|
||||
'static': StaticCharAtlas,
|
||||
'dynamic': DynamicCharAtlas
|
||||
};
|
||||
import { IColorSet } from 'ui/Types';
|
||||
|
||||
interface ICharAtlasCacheEntry {
|
||||
atlas: BaseCharAtlas;
|
||||
@@ -72,7 +64,7 @@ export function acquireCharAtlas(
|
||||
}
|
||||
|
||||
const newEntry: ICharAtlasCacheEntry = {
|
||||
atlas: new charAtlasImplementations[terminal.options.experimentalCharAtlas](
|
||||
atlas: new DynamicCharAtlas(
|
||||
document,
|
||||
newConfig
|
||||
),
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { FontWeight } from 'xterm';
|
||||
import { isFirefox, isSafari } from '../../common/Platform';
|
||||
import { ICharAtlasConfig, CHAR_ATLAS_CELL_SPACING } from './Types';
|
||||
import { IColor } from '../../ui/Types';
|
||||
|
||||
/**
|
||||
* Generates a char atlas.
|
||||
* @param context The window or worker context.
|
||||
* @param canvasFactory A function to generate a canvas with a width or height.
|
||||
* @param config The config for the new char atlas.
|
||||
*/
|
||||
export function generateStaticCharAtlasTexture(context: Window, canvasFactory: (width: number, height: number) => HTMLCanvasElement, config: ICharAtlasConfig): HTMLCanvasElement | Promise<ImageBitmap> {
|
||||
const cellWidth = config.scaledCharWidth + CHAR_ATLAS_CELL_SPACING;
|
||||
const cellHeight = config.scaledCharHeight + CHAR_ATLAS_CELL_SPACING;
|
||||
const canvas = canvasFactory(
|
||||
/*255 ascii chars*/255 * cellWidth,
|
||||
(/*default+default bold*/2 + /*0-15*/16 + /*0-15 bold*/16) * cellHeight
|
||||
);
|
||||
const ctx = canvas.getContext('2d', {alpha: config.allowTransparency});
|
||||
|
||||
ctx.fillStyle = config.colors.background.css;
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
ctx.save();
|
||||
ctx.fillStyle = config.colors.foreground.css;
|
||||
ctx.font = getFont(config.fontWeight, config);
|
||||
ctx.textBaseline = 'middle';
|
||||
|
||||
// Default color
|
||||
for (let i = 0; i < 256; i++) {
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.rect(i * cellWidth, 0, cellWidth, cellHeight);
|
||||
ctx.clip();
|
||||
ctx.fillText(String.fromCharCode(i), i * cellWidth, cellHeight / 2);
|
||||
ctx.restore();
|
||||
}
|
||||
// Default color bold
|
||||
ctx.save();
|
||||
ctx.font = getFont(config.fontWeightBold, config);
|
||||
for (let i = 0; i < 256; i++) {
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.rect(i * cellWidth, cellHeight, cellWidth, cellHeight);
|
||||
ctx.clip();
|
||||
ctx.fillText(String.fromCharCode(i), i * cellWidth, cellHeight * 1.5);
|
||||
ctx.restore();
|
||||
}
|
||||
ctx.restore();
|
||||
|
||||
// Colors 0-15
|
||||
ctx.font = getFont(config.fontWeight, config);
|
||||
for (let colorIndex = 0; colorIndex < 16; colorIndex++) {
|
||||
const y = (colorIndex + 2) * cellHeight;
|
||||
// Draw ascii characters
|
||||
for (let i = 0; i < 256; i++) {
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.rect(i * cellWidth, y, cellWidth, cellHeight);
|
||||
ctx.clip();
|
||||
ctx.fillStyle = config.colors.ansi[colorIndex].css;
|
||||
ctx.fillText(String.fromCharCode(i), i * cellWidth, y + cellHeight / 2);
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
|
||||
// Colors 0-15 bold
|
||||
ctx.font = getFont(config.fontWeightBold, config);
|
||||
for (let colorIndex = 0; colorIndex < 16; colorIndex++) {
|
||||
const y = (colorIndex + 2 + 16) * cellHeight;
|
||||
// Draw ascii characters
|
||||
for (let i = 0; i < 256; i++) {
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.rect(i * cellWidth, y, cellWidth, cellHeight);
|
||||
ctx.clip();
|
||||
ctx.fillStyle = config.colors.ansi[colorIndex].css;
|
||||
ctx.fillText(String.fromCharCode(i), i * cellWidth, y + cellHeight / 2);
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
ctx.restore();
|
||||
|
||||
// Support is patchy for createImageBitmap at the moment, pass a canvas back
|
||||
// if support is lacking as drawImage works there too. Firefox is also
|
||||
// included here as ImageBitmap appears both buggy and has horrible
|
||||
// performance (tested on v55).
|
||||
if (!('createImageBitmap' in context) || isFirefox || isSafari) {
|
||||
// Don't attempt to clear background colors if createImageBitmap is not supported
|
||||
return canvas;
|
||||
}
|
||||
|
||||
const charAtlasImageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Remove the background color from the image so characters may overlap
|
||||
clearColor(charAtlasImageData, config.colors.background);
|
||||
|
||||
return context.createImageBitmap(charAtlasImageData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a partiicular rgb color in an ImageData completely transparent.
|
||||
* @returns True if the result is "empty", meaning all pixels are fully transparent.
|
||||
*/
|
||||
export function clearColor(imageData: ImageData, color: IColor): boolean {
|
||||
let isEmpty = true;
|
||||
const r = color.rgba >>> 24;
|
||||
const g = color.rgba >>> 16 & 0xFF;
|
||||
const b = color.rgba >>> 8 & 0xFF;
|
||||
for (let offset = 0; offset < imageData.data.length; offset += 4) {
|
||||
if (imageData.data[offset] === r &&
|
||||
imageData.data[offset + 1] === g &&
|
||||
imageData.data[offset + 2] === b) {
|
||||
imageData.data[offset + 3] = 0;
|
||||
} else {
|
||||
isEmpty = false;
|
||||
}
|
||||
}
|
||||
return isEmpty;
|
||||
}
|
||||
|
||||
function getFont(fontWeight: FontWeight, config: ICharAtlasConfig): string {
|
||||
return `${fontWeight} ${config.fontSize * config.devicePixelRatio}px ${config.fontFamily}`;
|
||||
}
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
import { ITerminal } from '../../Types';
|
||||
import { ICharAtlasConfig } from './Types';
|
||||
import { DEFAULT_COLOR } from '../../common/Types';
|
||||
import { IColorSet } from '../../ui/Types';
|
||||
import { DEFAULT_COLOR } from 'common/Types';
|
||||
import { IColorSet } from 'ui/Types';
|
||||
|
||||
export function generateConfig(scaledCharWidth: number, scaledCharHeight: number, terminal: ITerminal, colors: IColorSet): ICharAtlasConfig {
|
||||
// null out some fields that don't matter
|
||||
@@ -21,7 +21,6 @@ export function generateConfig(scaledCharWidth: number, scaledCharHeight: number
|
||||
ansi: colors.ansi.slice(0, 16)
|
||||
};
|
||||
return {
|
||||
type: terminal.options.experimentalCharAtlas,
|
||||
devicePixelRatio: window.devicePixelRatio,
|
||||
scaledCharWidth,
|
||||
scaledCharHeight,
|
||||
@@ -40,8 +39,7 @@ export function configEquals(a: ICharAtlasConfig, b: ICharAtlasConfig): boolean
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return a.type === b.type &&
|
||||
a.devicePixelRatio === b.devicePixelRatio &&
|
||||
return a.devicePixelRatio === b.devicePixelRatio &&
|
||||
a.fontFamily === b.fontFamily &&
|
||||
a.fontSize === b.fontSize &&
|
||||
a.fontWeight === b.fontWeight &&
|
||||
|
||||
@@ -4,12 +4,11 @@
|
||||
*/
|
||||
|
||||
import { DIM_OPACITY, IGlyphIdentifier, INVERTED_DEFAULT_COLOR, ICharAtlasConfig } from './Types';
|
||||
import BaseCharAtlas from './BaseCharAtlas';
|
||||
import { DEFAULT_ANSI_COLORS } from '../../ui/ColorManager';
|
||||
import { clearColor } from './CharAtlasGenerator';
|
||||
import LRUMap from './LRUMap';
|
||||
import { isFirefox, isSafari } from '../../common/Platform';
|
||||
import { IColor } from '../../ui/Types';
|
||||
import { BaseCharAtlas } from './BaseCharAtlas';
|
||||
import { DEFAULT_ANSI_COLORS } from 'ui/ColorManager';
|
||||
import { LRUMap } from './LRUMap';
|
||||
import { isFirefox, isSafari } from 'common/Platform';
|
||||
import { IColor } from 'ui/Types';
|
||||
|
||||
// In practice we're probably never going to exhaust a texture this large. For debugging purposes,
|
||||
// however, it can be useful to set this to a really tiny value, to verify that LRU eviction works.
|
||||
@@ -54,7 +53,7 @@ export function getGlyphCacheKey(glyph: IGlyphIdentifier): number {
|
||||
return glyph.code << 21 | glyph.bg << 12 | glyph.fg << 3 | (glyph.bold ? 0 : 4) + (glyph.dim ? 0 : 2) + (glyph.italic ? 0 : 1);
|
||||
}
|
||||
|
||||
export default class DynamicCharAtlas extends BaseCharAtlas {
|
||||
export class DynamicCharAtlas extends BaseCharAtlas {
|
||||
// An ordered map that we're using to keep track of where each glyph is in the atlas texture.
|
||||
// It's ordered so that we can determine when to remove the old entries.
|
||||
private _cacheMap: LRUMap<IGlyphCacheValue>;
|
||||
@@ -328,3 +327,41 @@ export default class DynamicCharAtlas extends BaseCharAtlas {
|
||||
this._bitmapCommitTimeout = null;
|
||||
}
|
||||
}
|
||||
|
||||
// This is used for debugging the renderer, just swap out `new DynamicCharAtlas` with
|
||||
// `new NoneCharAtlas`.
|
||||
export class NoneCharAtlas extends BaseCharAtlas {
|
||||
constructor(document: Document, config: ICharAtlasConfig) {
|
||||
super();
|
||||
}
|
||||
|
||||
public draw(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
glyph: IGlyphIdentifier,
|
||||
x: number,
|
||||
y: number
|
||||
): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a partiicular rgb color in an ImageData completely transparent.
|
||||
* @returns True if the result is "empty", meaning all pixels are fully transparent.
|
||||
*/
|
||||
function clearColor(imageData: ImageData, color: IColor): boolean {
|
||||
let isEmpty = true;
|
||||
const r = color.rgba >>> 24;
|
||||
const g = color.rgba >>> 16 & 0xFF;
|
||||
const b = color.rgba >>> 8 & 0xFF;
|
||||
for (let offset = 0; offset < imageData.data.length; offset += 4) {
|
||||
if (imageData.data[offset] === r &&
|
||||
imageData.data[offset + 1] === g &&
|
||||
imageData.data[offset + 2] === b) {
|
||||
imageData.data[offset + 3] = 0;
|
||||
} else {
|
||||
isEmpty = false;
|
||||
}
|
||||
}
|
||||
return isEmpty;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { assert } from 'chai';
|
||||
import LRUMap from './LRUMap';
|
||||
import { LRUMap } from './LRUMap';
|
||||
|
||||
describe('LRUMap', () => {
|
||||
it('can be used to store and retrieve values', () => {
|
||||
|
||||
@@ -10,7 +10,7 @@ interface ILinkedListNode<T> {
|
||||
value: T;
|
||||
}
|
||||
|
||||
export default class LRUMap<T> {
|
||||
export class LRUMap<T> {
|
||||
private _map: { [key: number]: ILinkedListNode<T> } = {};
|
||||
private _head: ILinkedListNode<T> = null;
|
||||
private _tail: ILinkedListNode<T> = null;
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*
|
||||
* A dummy CharAtlas implementation that always fails to draw characters.
|
||||
*/
|
||||
|
||||
import { IGlyphIdentifier, ICharAtlasConfig } from './Types';
|
||||
import BaseCharAtlas from './BaseCharAtlas';
|
||||
|
||||
export default class NoneCharAtlas extends BaseCharAtlas {
|
||||
constructor(document: Document, config: ICharAtlasConfig) {
|
||||
super();
|
||||
}
|
||||
|
||||
public draw(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
glyph: IGlyphIdentifier,
|
||||
x: number,
|
||||
y: number
|
||||
): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { DIM_OPACITY, IGlyphIdentifier, ICharAtlasConfig, CHAR_ATLAS_CELL_SPACING } from './Types';
|
||||
import { generateStaticCharAtlasTexture } from './CharAtlasGenerator';
|
||||
import BaseCharAtlas from './BaseCharAtlas';
|
||||
import { is256Color } from './CharAtlasUtils';
|
||||
import { DEFAULT_COLOR } from '../../common/Types';
|
||||
|
||||
export default class StaticCharAtlas extends BaseCharAtlas {
|
||||
private _texture: HTMLCanvasElement | ImageBitmap;
|
||||
|
||||
constructor(private _document: Document, private _config: ICharAtlasConfig) {
|
||||
super();
|
||||
}
|
||||
|
||||
private _canvasFactory = (width: number, height: number) => {
|
||||
const canvas = this._document.createElement('canvas');
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
// This is useful for debugging
|
||||
// document.body.appendChild(canvas);
|
||||
|
||||
return canvas;
|
||||
}
|
||||
|
||||
protected _doWarmUp(): void {
|
||||
const result = generateStaticCharAtlasTexture(window, this._canvasFactory, this._config);
|
||||
if (result instanceof HTMLCanvasElement) {
|
||||
this._texture = result;
|
||||
} else {
|
||||
result.then(texture => {
|
||||
this._texture = texture;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private _isCached(glyph: IGlyphIdentifier, colorIndex: number): boolean {
|
||||
const isAscii = glyph.code < 256;
|
||||
// A color is basic if it is one of the 4 bit ANSI colors.
|
||||
const isBasicColor = glyph.fg < 16;
|
||||
const isDefaultColor = glyph.fg === DEFAULT_COLOR;
|
||||
const isDefaultBackground = glyph.bg === DEFAULT_COLOR;
|
||||
return isAscii && (isBasicColor || isDefaultColor) && isDefaultBackground && !glyph.italic;
|
||||
}
|
||||
|
||||
public draw(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
glyph: IGlyphIdentifier,
|
||||
x: number,
|
||||
y: number
|
||||
): boolean {
|
||||
// we're not warmed up yet
|
||||
if (this._texture === null || this._texture === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let colorIndex = 0;
|
||||
if (is256Color(glyph.fg)) {
|
||||
colorIndex = 2 + glyph.fg + (glyph.bold ? 16 : 0);
|
||||
} else if (glyph.fg === DEFAULT_COLOR) {
|
||||
// If default color and bold
|
||||
if (glyph.bold) {
|
||||
colorIndex = 1;
|
||||
}
|
||||
}
|
||||
if (!this._isCached(glyph, colorIndex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx.save();
|
||||
|
||||
// ImageBitmap's draw about twice as fast as from a canvas
|
||||
const charAtlasCellWidth = this._config.scaledCharWidth + CHAR_ATLAS_CELL_SPACING;
|
||||
const charAtlasCellHeight = this._config.scaledCharHeight + CHAR_ATLAS_CELL_SPACING;
|
||||
|
||||
// Apply alpha to dim the character
|
||||
if (glyph.dim) {
|
||||
ctx.globalAlpha = DIM_OPACITY;
|
||||
}
|
||||
|
||||
ctx.drawImage(
|
||||
this._texture,
|
||||
glyph.code * charAtlasCellWidth,
|
||||
colorIndex * charAtlasCellHeight,
|
||||
charAtlasCellWidth,
|
||||
this._config.scaledCharHeight,
|
||||
x,
|
||||
y,
|
||||
charAtlasCellWidth,
|
||||
this._config.scaledCharHeight
|
||||
);
|
||||
|
||||
ctx.restore();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { FontWeight } from 'xterm';
|
||||
import { IColorSet } from '../../ui/Types';
|
||||
import { IColorSet } from 'ui/Types';
|
||||
|
||||
export const INVERTED_DEFAULT_COLOR = 257;
|
||||
export const DIM_OPACITY = 0.5;
|
||||
@@ -22,7 +22,6 @@ export interface IGlyphIdentifier {
|
||||
}
|
||||
|
||||
export interface ICharAtlasConfig {
|
||||
type: 'none' | 'static' | 'dynamic' | 'webgl';
|
||||
devicePixelRatio: number;
|
||||
fontSize: number;
|
||||
fontFamily: string;
|
||||
|
||||
@@ -7,8 +7,8 @@ import { IRenderer, IRenderDimensions } from '../Types';
|
||||
import { ILinkifierEvent, ITerminal, CharacterJoinerHandler } from '../../Types';
|
||||
import { BOLD_CLASS, ITALIC_CLASS, CURSOR_CLASS, CURSOR_STYLE_BLOCK_CLASS, CURSOR_BLINK_CLASS, CURSOR_STYLE_BAR_CLASS, CURSOR_STYLE_UNDERLINE_CLASS, DomRendererRowFactory } from './DomRendererRowFactory';
|
||||
import { INVERTED_DEFAULT_COLOR } from '../atlas/Types';
|
||||
import { Disposable } from '../../common/Lifecycle';
|
||||
import { IColorSet } from '../../ui/Types';
|
||||
import { Disposable } from 'common/Lifecycle';
|
||||
import { IColorSet } from 'ui/Types';
|
||||
|
||||
const TERMINAL_CLASS_PREFIX = 'xterm-dom-renderer-owner-';
|
||||
const ROW_CONTAINER_CLASS = 'xterm-rows';
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
import jsdom = require('jsdom');
|
||||
import { assert } from 'chai';
|
||||
import { DomRendererRowFactory } from './DomRendererRowFactory';
|
||||
import { BufferLine, CellData, FgFlags, BgFlags, Attributes, NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR, DEFAULT_ATTR, DEFAULT_ATTR_DATA } from '../../core/buffer/BufferLine';
|
||||
import { BufferLine, CellData, FgFlags, BgFlags, Attributes, NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR, DEFAULT_ATTR, DEFAULT_ATTR_DATA } from 'core/buffer/BufferLine';
|
||||
import { ITerminalOptions } from '../../Types';
|
||||
import { IBufferLine } from '../../core/Types';
|
||||
import { IBufferLine } from 'core/Types';
|
||||
|
||||
describe('DomRendererRowFactory', () => {
|
||||
let dom: jsdom.JSDOM;
|
||||
@@ -19,7 +19,6 @@ describe('DomRendererRowFactory', () => {
|
||||
beforeEach(() => {
|
||||
dom = new jsdom.JSDOM('');
|
||||
|
||||
options.enableBold = true;
|
||||
options.drawBoldTextInBrightColors = true;
|
||||
|
||||
rowFactory = new DomRendererRowFactory(options, dom.window.document);
|
||||
|
||||
@@ -77,7 +77,7 @@ export class DomRendererRowFactory {
|
||||
}
|
||||
}
|
||||
|
||||
if (this._workCell.isBold() && this._terminalOptions.enableBold) {
|
||||
if (this._workCell.isBold()) {
|
||||
charElement.classList.add(BOLD_CLASS);
|
||||
}
|
||||
|
||||
@@ -104,8 +104,7 @@ export class DomRendererRowFactory {
|
||||
charElement.setAttribute('style', style);
|
||||
} else if (this._workCell.isFgPalette()) {
|
||||
let fg = this._workCell.getFgColor();
|
||||
if (this._workCell.isBold() && fg < 8 && !swapColor &&
|
||||
this._terminalOptions.enableBold && this._terminalOptions.drawBoldTextInBrightColors) {
|
||||
if (this._workCell.isBold() && fg < 8 && !swapColor && this._terminalOptions.drawBoldTextInBrightColors) {
|
||||
fg += 8;
|
||||
}
|
||||
charElement.classList.add(`xterm-${swapColor ? 'b' : 'f'}g-${fg}`);
|
||||
|
||||
+7
-1
@@ -10,7 +10,13 @@
|
||||
"es2015.promise"
|
||||
],
|
||||
"rootDir": ".",
|
||||
"outDir": "../lib",
|
||||
"outDir": "../out",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"common/*": [ "./common/*" ],
|
||||
"core/*": [ "./core/*" ],
|
||||
"ui/*": [ "./ui/*" ]
|
||||
},
|
||||
|
||||
"noUnusedLocals": true,
|
||||
"noImplicitAny": true
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import jsdom = require('jsdom');
|
||||
import { assert } from 'chai';
|
||||
import { ColorManager } from './ColorManager';
|
||||
import { ColorManager } from 'ui/ColorManager';
|
||||
|
||||
describe('ColorManager', () => {
|
||||
let cm: ColorManager;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { IColorManager, IColor, IColorSet, ITheme } from './Types';
|
||||
import { IColorManager, IColor, IColorSet, ITheme } from 'ui/Types';
|
||||
|
||||
const DEFAULT_FOREGROUND = fromHex('#ffffff');
|
||||
const DEFAULT_BACKGROUND = fromHex('#000000');
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { IDisposable } from '../common/Types';
|
||||
import { IDisposable } from 'common/Types';
|
||||
|
||||
/**
|
||||
* Adds a disposable listener to a node in the DOM, returning the disposable.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { IDisposable } from '../common/Types';
|
||||
import { IDisposable } from 'common/Types';
|
||||
|
||||
/**
|
||||
* Debounces calls to render terminal rows using animation frames.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { Disposable } from '../common/Lifecycle';
|
||||
import { Disposable } from 'common/Lifecycle';
|
||||
|
||||
export type ScreenDprListener = (newDevicePixelRatio?: number, oldDevicePixelRatio?: number) => void;
|
||||
|
||||
|
||||
@@ -5,10 +5,15 @@
|
||||
"dom",
|
||||
"es5",
|
||||
],
|
||||
"outDir": "../../lib",
|
||||
"outDir": "../../out",
|
||||
"types": [
|
||||
"../../node_modules/@types/mocha"
|
||||
]
|
||||
],
|
||||
"baseUrl": "..",
|
||||
"paths": {
|
||||
"common/*": [ "./common/*" ],
|
||||
"ui/*": [ "./ui/*" ]
|
||||
}
|
||||
},
|
||||
"include": [ "./**/*" ],
|
||||
"references": [
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*
|
||||
* This file is the entry point for browserify.
|
||||
*/
|
||||
|
||||
import { Terminal } from './public/Terminal';
|
||||
|
||||
module.exports = Terminal;
|
||||
Vendored
+2
-34
@@ -76,31 +76,6 @@ declare module 'xterm' {
|
||||
*/
|
||||
drawBoldTextInBrightColors?: boolean;
|
||||
|
||||
/**
|
||||
* Whether to enable the rendering of bold text.
|
||||
*
|
||||
* @deprecated Use fontWeight and fontWeightBold instead.
|
||||
*/
|
||||
enableBold?: boolean;
|
||||
|
||||
/**
|
||||
* What character atlas implementation to use. The character atlas caches drawn characters,
|
||||
* speeding up rendering significantly. However, it can introduce some minor rendering
|
||||
* artifacts.
|
||||
*
|
||||
* - 'none': Don't use an atlas.
|
||||
* - 'static': Generate an atlas when the terminal starts or is reconfigured. This atlas will
|
||||
* only contain ASCII characters in 16 colors.
|
||||
* - 'dynamic': Generate an atlas using a LRU cache as characters are requested. Limited to
|
||||
* ASCII characters (for now), but supports 256 colors. For characters covered by the static
|
||||
* cache, it's slightly slower in comparison, since there's more overhead involved in
|
||||
* managing the cache.
|
||||
*
|
||||
* Currently defaults to 'static'. This option may be removed in the future. If it is, passed
|
||||
* parameters will be ignored.
|
||||
*/
|
||||
experimentalCharAtlas?: 'none' | 'static' | 'dynamic';
|
||||
|
||||
/**
|
||||
* The font size used to render text.
|
||||
*/
|
||||
@@ -706,13 +681,6 @@ declare module 'xterm' {
|
||||
*/
|
||||
dispose(): void;
|
||||
|
||||
/**
|
||||
* Destroys the terminal and detaches it from the DOM.
|
||||
*
|
||||
* @deprecated Use dispose() instead.
|
||||
*/
|
||||
destroy(): void;
|
||||
|
||||
/**
|
||||
* Scroll the display of the terminal
|
||||
* @param amount The number of lines to scroll down (negative scroll up).
|
||||
@@ -775,7 +743,7 @@ declare module 'xterm' {
|
||||
* Retrieves an option's value from the terminal.
|
||||
* @param key The option key.
|
||||
*/
|
||||
getOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell' | 'windowsMode'): boolean;
|
||||
getOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell' | 'windowsMode'): boolean;
|
||||
/**
|
||||
* Retrieves an option's value from the terminal.
|
||||
* @param key The option key.
|
||||
@@ -826,7 +794,7 @@ declare module 'xterm' {
|
||||
* @param key The option key.
|
||||
* @param value The option value.
|
||||
*/
|
||||
setOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'macOptionIsMeta' | 'popOnBell' | 'rightClickSelectsWord' | 'screenKeys' | 'useFlowControl' | 'visualBell' | 'windowsMode', value: boolean): void;
|
||||
setOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'macOptionIsMeta' | 'popOnBell' | 'rightClickSelectsWord' | 'screenKeys' | 'useFlowControl' | 'visualBell' | 'windowsMode', value: boolean): void;
|
||||
/**
|
||||
* Sets an option on the terminal.
|
||||
* @param key The option key.
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
|
||||
/**
|
||||
* This webpack config does a production build for xterm.js. It works by taking the output from tsc
|
||||
* (via `yarn watch` or `yarn prebuild`) which are put into `out/` and webpacks them into a
|
||||
* production mode umd library module in `lib/`. The aliases are used fix up the absolute paths
|
||||
* output by tsc (because of `baseUrl` and `paths` in `tsconfig.json`.
|
||||
*/
|
||||
module.exports = {
|
||||
entry: './out/public/Terminal.js',
|
||||
devtool: 'source-map',
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
use: ["source-map-loader"],
|
||||
enforce: "pre",
|
||||
exclude: /node_modules/
|
||||
}
|
||||
]
|
||||
},
|
||||
resolve: {
|
||||
modules: ['./node_modules'],
|
||||
extensions: [ '.js' ],
|
||||
alias: {
|
||||
common: path.resolve('./out/common'),
|
||||
core: path.resolve('./out/core'),
|
||||
ui: path.resolve('./out/ui')
|
||||
}
|
||||
},
|
||||
output: {
|
||||
filename: 'xterm.js',
|
||||
path: path.resolve('./lib'),
|
||||
library: 'Terminal',
|
||||
libraryTarget: 'umd'
|
||||
},
|
||||
mode: 'production'
|
||||
};
|
||||
Reference in New Issue
Block a user