mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Merge branch 'master' into isWrappedEraseInBufferline
This commit is contained in:
@@ -179,7 +179,7 @@ Xterm.js is used in several world-class applications to provide great terminal e
|
||||
- [**WizardWebssh**](https://gitlab.com/mikeramsey/wizardwebssh): A terminal with Pyqt5 Widget for embedding, which can be used as an ssh client to connect to your ssh servers. It is written in Python, based on tornado, paramiko, and xterm.js.
|
||||
- [**Wizard Assistant**](https://wizardassistant.com/): Wizard Assistant comes with advanced automation tools, preloaded common and special time-saving commands, and a built-in SSH terminal. Now you can remotely administer, troubleshoot, and analyze any system with ease.
|
||||
- [**ucli**](https://github.com/tsadarsh/ucli): Command Line for everyone :family_man_woman_girl_boy: at [www.ucli.tech](https://www.ucli.tech).
|
||||
- [**Tess**](https://github.com/SquitchYT/Tess/): Simple Terminal Fully Customizable for Everyone.
|
||||
- [**Tess**](https://github.com/SquitchYT/Tess/): Simple Terminal Fully Customizable for Everyone. Discover more at [tessapp.dev](https://tessapp.dev)
|
||||
- [**HashiCorp Nomad**](https://www.nomadproject.io/): A container orchestrator with the ability to connect to remote tasks via a web interface using websockets and xterm.js.
|
||||
- [**TermPair**](https://github.com/cs01/termpair): View and control terminals from your browser with end-to-end encryption
|
||||
- [**gdbgui**](https://github.com/cs01/gdbgui): Browser-based frontend to gdb (gnu debugger)
|
||||
|
||||
@@ -33,7 +33,7 @@ export class FitAddon implements ITerminalAddon {
|
||||
|
||||
public fit(): void {
|
||||
const dims = this.proposeDimensions();
|
||||
if (!dims || !this._terminal) {
|
||||
if (!dims || !this._terminal || isNaN(dims.cols) || isNaN(dims.rows)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ export default async function load(fontFamily: string, cacheSize: number): Promi
|
||||
if (status && status.state !== 'granted') {
|
||||
throw new Error('Permission to access local fonts not granted.');
|
||||
}
|
||||
} catch (err) {
|
||||
} catch (err: any) {
|
||||
// A `TypeError` indicates the 'local-fonts'
|
||||
// permission is not yet implemented, so
|
||||
// only `throw` if this is _not_ the problem.
|
||||
@@ -61,7 +61,7 @@ export default async function load(fontFamily: string, cacheSize: number): Promi
|
||||
fonts[metadata.family].push(metadata);
|
||||
}
|
||||
fontsPromise = Promise.resolve(fonts);
|
||||
} catch (err) {
|
||||
} catch (err: any) {
|
||||
console.error(err.name, err.message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"SerializeAddon": ["../src/SerializeAddon"]
|
||||
}
|
||||
},
|
||||
"include": ["../**/*", "../../../typings/xterm.d.ts", "../../../out/**/*"],
|
||||
"include": ["../**/*", "../../../typings/xterm.d.ts"],
|
||||
"exclude": ["../../../**/*test.ts", "../../**/*api.ts"],
|
||||
"references": [
|
||||
{ "path": "../../../src/common" },
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xterm-addon-serialize",
|
||||
"version": "0.6.0",
|
||||
"version": "0.6.1",
|
||||
"author": {
|
||||
"name": "The xterm.js authors",
|
||||
"url": "https://xtermjs.org/"
|
||||
|
||||
@@ -43,6 +43,7 @@ function handleLink(event: MouseEvent, uri: string): void {
|
||||
interface ILinkProviderOptions {
|
||||
hover?(event: MouseEvent, text: string, location: IViewportRange): void;
|
||||
leave?(event: MouseEvent, text: string): void;
|
||||
urlRegex?: RegExp;
|
||||
}
|
||||
|
||||
export class WebLinksAddon implements ITerminalAddon {
|
||||
@@ -62,7 +63,8 @@ export class WebLinksAddon implements ITerminalAddon {
|
||||
|
||||
if (this._useLinkProvider && 'registerLinkProvider' in this._terminal) {
|
||||
const options = this._options as ILinkProviderOptions;
|
||||
this._linkProvider = this._terminal.registerLinkProvider(new WebLinkProvider(this._terminal, strictUrlRegex, this._handler, options));
|
||||
const regex = options.urlRegex || strictUrlRegex;
|
||||
this._linkProvider = this._terminal.registerLinkProvider(new WebLinkProvider(this._terminal, regex, this._handler, options));
|
||||
} else {
|
||||
// TODO: This should be removed eventually
|
||||
const options = this._options as ILinkMatcherOptions;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xterm-addon-webgl",
|
||||
"version": "0.11.2",
|
||||
"version": "0.11.3",
|
||||
"author": {
|
||||
"name": "The xterm.js authors",
|
||||
"url": "https://xtermjs.org/"
|
||||
|
||||
@@ -14,8 +14,8 @@ import { AttributeData } from 'common/buffer/AttributeData';
|
||||
import { channels, rgba } from 'browser/Color';
|
||||
import { tryDrawCustomChar } from 'browser/renderer/CustomGlyphs';
|
||||
|
||||
// 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.
|
||||
// For debugging purposes, it can be useful to set this to a really tiny value,
|
||||
// to verify that LRU eviction works.
|
||||
const TEXTURE_WIDTH = 1024;
|
||||
const TEXTURE_HEIGHT = 1024;
|
||||
|
||||
@@ -463,7 +463,7 @@ export class WebglCharAtlas implements IDisposable {
|
||||
const clippedImageData = this._clipImageData(imageData, this._workBoundingBox);
|
||||
|
||||
// Check if there is enough room in the current row and go to next if needed
|
||||
if (this._currentRowX + this._config.scaledCharWidth > TEXTURE_WIDTH) {
|
||||
if (this._currentRowX + rasterizedGlyph.size.x > TEXTURE_WIDTH) {
|
||||
this._currentRowX = 0;
|
||||
this._currentRowY += this._currentRowHeight;
|
||||
this._currentRowHeight = 0;
|
||||
|
||||
+2
-2
@@ -59,7 +59,7 @@ jobs:
|
||||
|
||||
- job: Windows
|
||||
pool:
|
||||
vmImage: 'vs2017-win2016'
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
@@ -124,7 +124,7 @@ jobs:
|
||||
|
||||
- job: Windows_IntegrationTests
|
||||
pool:
|
||||
vmImage: 'vs2017-win2016'
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
|
||||
@@ -11,13 +11,13 @@ const Mustache = require('mustache');
|
||||
* regexp to fetch all comments
|
||||
* Fetches all multiline comments and single lines containing '// @vt:'.
|
||||
*/
|
||||
const REX_COMMENTS = /^\s*?[/][*][*]([\s\S]*?)[*][/]|^\s*?\/\/ ([@]vt[:].*?)$/mug;
|
||||
const REX_COMMENTS = /^\s*?\/\*\*([\S\s]*?)\*\/|^\s*?\/\/ (@vt:.*?)$/mug;
|
||||
|
||||
/**
|
||||
* regexp to parse the @vt line
|
||||
* expected data - "@vt: <status> <kind> <mnemonic> "<name>" "<sequence>" "<short description>"
|
||||
*/
|
||||
const REX_VT_LINE = /^[@]vt\:\s*(\w+|#\w+|#\w+\[.*?\])\s*(\w+)\s*(\w+)\s*"(.*?)"\s*"(.*?)"\s*"(.*?)".*$/;
|
||||
const REX_VT_LINE = /^@vt:\s*(\w+|#\w+|#\w+\[.*?\])\s*(\w+)\s*(\w+)\s*"(.*?)"\s*"(.*?)"\s*"(.*?)".*$/;
|
||||
|
||||
// known vt command types
|
||||
const TYPES = [
|
||||
@@ -362,7 +362,7 @@ function* parseMultiLineGen(filename, s) {
|
||||
if (!s.includes('@vt:')) {
|
||||
return;
|
||||
}
|
||||
const lines = s.split('\n').map(el => el.trim().replace(/[*]/, '').replace(/\s/, ''));
|
||||
const lines = s.split('\n').map(el => el.trim().replace(/\*/, '').replace(/\s/, ''));
|
||||
let grabLine = false;
|
||||
let longDescription = [];
|
||||
let feature = undefined;
|
||||
|
||||
+4
-4
@@ -92,7 +92,7 @@ function checkAndPublishPackage(packageDir) {
|
||||
}
|
||||
|
||||
function getNextBetaVersion(packageJson) {
|
||||
if (!/^[0-9]+\.[0-9]+\.[0-9]+$/.exec(packageJson.version)) {
|
||||
if (!/^\d+\.\d+\.\d+$/.exec(packageJson.version)) {
|
||||
console.error('The package.json version must be of the form x.y.z');
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -104,11 +104,11 @@ function getNextBetaVersion(packageJson) {
|
||||
return `${nextStableVersion}-${tag}.1`;
|
||||
}
|
||||
const latestPublishedVersion = publishedVersions.sort((a, b) => {
|
||||
const aVersion = parseInt(a.substr(a.search(/[0-9]+$/)));
|
||||
const bVersion = parseInt(b.substr(b.search(/[0-9]+$/)));
|
||||
const aVersion = parseInt(a.substr(a.search(/\d+$/)));
|
||||
const bVersion = parseInt(b.substr(b.search(/\d+$/)));
|
||||
return aVersion > bVersion ? -1 : 1;
|
||||
})[0];
|
||||
const latestTagVersion = parseInt(latestPublishedVersion.substr(latestPublishedVersion.search(/[0-9]+$/)), 10);
|
||||
const latestTagVersion = parseInt(latestPublishedVersion.substr(latestPublishedVersion.search(/\d+$/)), 10);
|
||||
return `${nextStableVersion}-${tag}.${latestTagVersion + 1}`;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@ let flagArgs = [];
|
||||
|
||||
if (process.argv.length > 2) {
|
||||
const args = process.argv.slice(2);
|
||||
flagArgs = args.filter(e => e.startsWith('--')).map(arg => arg.split('=')).reduce((arr, val) => arr.concat([...val], []));
|
||||
flagArgs = args.filter(e => e.startsWith('--')).map(arg => arg.split('=')).reduce((arr, val) => arr.concat(val.slice(), []));
|
||||
console.info(flagArgs);
|
||||
// ability to inject particular test files via
|
||||
// yarn test [testFileA testFileB ...]
|
||||
@@ -44,7 +44,7 @@ const server = cp.spawn('node', ['demo/start'], {
|
||||
|
||||
server.stdout.on('data', (data) => {
|
||||
// await for the server to fully start
|
||||
if (data.indexOf("successfully") !== -1) {
|
||||
if (data.includes("successfully")) {
|
||||
const run = cp.spawnSync(
|
||||
npmBinScript('mocha'),
|
||||
[...testFiles, ...flagArgs], {
|
||||
|
||||
+2
-1
@@ -133,7 +133,8 @@
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.xterm.xterm-cursor-pointer {
|
||||
.xterm.xterm-cursor-pointer,
|
||||
.xterm .xterm-cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
+23
-23
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "xterm",
|
||||
"description": "Full xterm terminal, in your browser",
|
||||
"version": "4.14.1",
|
||||
"version": "4.15.0",
|
||||
"main": "lib/xterm.js",
|
||||
"style": "css/xterm.css",
|
||||
"types": "typings/xterm.d.ts",
|
||||
@@ -37,39 +37,39 @@
|
||||
"vtfeatures": "node bin/extract_vtfeatures.js src/**/*.ts src/*.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.2.18",
|
||||
"@types/debug": "^4.1.5",
|
||||
"@types/chai": "^4.2.22",
|
||||
"@types/debug": "^4.1.7",
|
||||
"@types/deep-equal": "^1.0.1",
|
||||
"@types/glob": "^7.1.3",
|
||||
"@types/jsdom": "^16.2.10",
|
||||
"@types/mocha": "^8.2.2",
|
||||
"@types/glob": "^7.2.0",
|
||||
"@types/jsdom": "^16.2.13",
|
||||
"@types/mocha": "^9.0.0",
|
||||
"@types/node": "^14.14.44",
|
||||
"@types/utf8": "^2.1.6",
|
||||
"@types/utf8": "^3.0.0",
|
||||
"@types/webpack": "^5.28.0",
|
||||
"@types/ws": "^7.4.4",
|
||||
"@typescript-eslint/eslint-plugin": "^4.23.0",
|
||||
"@typescript-eslint/parser": "^4.23.0",
|
||||
"@types/ws": "^8.2.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.3.0",
|
||||
"@typescript-eslint/parser": "^5.3.0",
|
||||
"chai": "^4.3.4",
|
||||
"cross-env": "^7.0.3",
|
||||
"deep-equal": "^2.0.5",
|
||||
"eslint": "^7.26.0",
|
||||
"eslint": "^8.1.0",
|
||||
"express": "^4.17.1",
|
||||
"express-ws": "^4.0.0",
|
||||
"glob": "^7.1.7",
|
||||
"jsdom": "^16.5.3",
|
||||
"mocha": "^8.4.0",
|
||||
"express-ws": "^5.0.2",
|
||||
"glob": "^7.2.0",
|
||||
"jsdom": "^18.0.1",
|
||||
"mocha": "^9.1.3",
|
||||
"mustache": "^4.2.0",
|
||||
"node-pty": "^0.10.1",
|
||||
"nyc": "^15.1.0",
|
||||
"playwright": "^1.11.0",
|
||||
"source-map-loader": "^2.0.1",
|
||||
"source-map-support": "^0.5.19",
|
||||
"playwright": "^1.16.2",
|
||||
"source-map-loader": "^3.0.0",
|
||||
"source-map-support": "^0.5.20",
|
||||
"ts-loader": "^9.1.2",
|
||||
"typescript": "^4.2.4",
|
||||
"typescript": "^4.4.4",
|
||||
"utf8": "^3.0.0",
|
||||
"webpack": "^5.37.0",
|
||||
"webpack-cli": "^4.7.0",
|
||||
"ws": "^7.4.5",
|
||||
"xterm-benchmark": "^0.2.1"
|
||||
"webpack": "^5.61.0",
|
||||
"webpack-cli": "^4.9.1",
|
||||
"ws": "^8.2.3",
|
||||
"xterm-benchmark": "^0.3.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ export class AccessibilityManager extends Disposable {
|
||||
this._accessibilityTreeRoot = document.createElement('div');
|
||||
this._accessibilityTreeRoot.setAttribute('role', 'document');
|
||||
this._accessibilityTreeRoot.classList.add('xterm-accessibility');
|
||||
this._accessibilityTreeRoot.tabIndex = 0;
|
||||
|
||||
this._rowContainer = document.createElement('div');
|
||||
this._rowContainer.setAttribute('role', 'list');
|
||||
|
||||
+11
-3
@@ -537,7 +537,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
||||
this.register(this._mouseZoneManager);
|
||||
this.register(this.onScroll(() => this._mouseZoneManager!.clearAll()));
|
||||
this.linkifier.attachToDom(this.element, this._mouseZoneManager);
|
||||
this.linkifier2.attachToDom(this.element, this._mouseService, this._renderService);
|
||||
this.linkifier2.attachToDom(this.screenElement, this._mouseService, this._renderService);
|
||||
|
||||
// This event listener must be registered aftre MouseZoneManager is created
|
||||
this.register(addDisposableDomListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.onMouseDown(e)));
|
||||
@@ -820,7 +820,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
||||
|
||||
// normal viewport scrolling
|
||||
// conditionally stop event, if the viewport still had rows to scroll within
|
||||
if (!this.viewport!.onWheel(ev)) {
|
||||
if (this.viewport!.onWheel(ev)) {
|
||||
return this.cancel(ev);
|
||||
}
|
||||
}, { passive: false }));
|
||||
@@ -1169,6 +1169,10 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
||||
|
||||
this._keyPressHandled = true;
|
||||
|
||||
// The key was handled so clear the dead key state, otherwise certain keystrokes like arrow
|
||||
// keys could be ignored
|
||||
this._unprocessedDeadKey = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1181,11 +1185,15 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
||||
protected _inputEvent(ev: InputEvent): boolean {
|
||||
// Only support emoji IMEs when screen reader mode is disabled as the event must bubble up to
|
||||
// support reading out character input which can doubling up input characters
|
||||
if (ev.data && ev.inputType === 'insertText' && !this.optionsService.options.screenReaderMode) {
|
||||
if (ev.data && ev.inputType === 'insertText' && !ev.composed && !this.optionsService.options.screenReaderMode) {
|
||||
if (this._keyPressHandled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The key was handled so clear the dead key state, otherwise certain keystrokes like arrow
|
||||
// keys could be ignored
|
||||
this._unprocessedDeadKey = false;
|
||||
|
||||
const text = ev.data;
|
||||
this.coreService.triggerDataEvent(text, true);
|
||||
|
||||
|
||||
@@ -220,7 +220,7 @@ export class Viewport extends Disposable implements IViewport {
|
||||
|
||||
private _getPixelsScrolled(ev: WheelEvent): number {
|
||||
// Do nothing if it's not a vertical scroll event
|
||||
if (ev.deltaY === 0) {
|
||||
if (ev.deltaY === 0 || ev.shiftKey) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ export class Viewport extends Disposable implements IViewport {
|
||||
*/
|
||||
public getLinesScrolled(ev: WheelEvent): number {
|
||||
// Do nothing if it's not a vertical scroll event
|
||||
if (ev.deltaY === 0) {
|
||||
if (ev.deltaY === 0 || ev.shiftKey) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ function wrappedRowsCount(startY: number, targetY: number, bufferService: IBuffe
|
||||
for (let i = 0; i < Math.abs(startRow - endRow); i++) {
|
||||
const direction = verticalDirection(startY, targetY) === Direction.UP ? -1 : 1;
|
||||
const line = bufferService.buffer.lines.get(startRow + (direction * i));
|
||||
if (line && line.isWrapped) {
|
||||
if (line?.isWrapped) {
|
||||
wrappedRows++;
|
||||
}
|
||||
}
|
||||
@@ -136,12 +136,12 @@ function wrappedRowsCount(startY: number, targetY: number, bufferService: IBuffe
|
||||
function wrappedRowsForRow(bufferService: IBufferService, currentRow: number): number {
|
||||
let rowCount = 0;
|
||||
let line = bufferService.buffer.lines.get(currentRow);
|
||||
let lineWraps = line && line.isWrapped;
|
||||
let lineWraps = line?.isWrapped;
|
||||
|
||||
while (lineWraps && currentRow >= 0 && currentRow < bufferService.rows) {
|
||||
rowCount++;
|
||||
line = bufferService.buffer.lines.get(--currentRow);
|
||||
lineWraps = line && line.isWrapped;
|
||||
lineWraps = line?.isWrapped;
|
||||
}
|
||||
|
||||
return rowCount;
|
||||
|
||||
@@ -325,12 +325,7 @@ export abstract class BaseRenderLayer implements IRenderLayer {
|
||||
this._currentGlyphIdentifier.bold = !!cell.isBold();
|
||||
this._currentGlyphIdentifier.dim = !!cell.isDim();
|
||||
this._currentGlyphIdentifier.italic = !!cell.isItalic();
|
||||
const atlasDidDraw = this._charAtlas && this._charAtlas.draw(
|
||||
this._ctx,
|
||||
this._currentGlyphIdentifier,
|
||||
x * this._scaledCellWidth + this._scaledCharLeft,
|
||||
y * this._scaledCellHeight + this._scaledCharTop
|
||||
);
|
||||
const atlasDidDraw = this._charAtlas?.draw(this._ctx, this._currentGlyphIdentifier, x * this._scaledCellWidth + this._scaledCharLeft, y * this._scaledCellHeight + this._scaledCharTop);
|
||||
|
||||
if (!atlasDidDraw) {
|
||||
this._drawUncachedChars(cell, x, y);
|
||||
|
||||
@@ -16,7 +16,7 @@ export function generateConfig(scaledCharWidth: number, scaledCharHeight: number
|
||||
cursor: undefined,
|
||||
cursorAccent: undefined,
|
||||
selection: undefined,
|
||||
ansi: colors.ansi
|
||||
ansi: [...colors.ansi]
|
||||
};
|
||||
return {
|
||||
devicePixelRatio: window.devicePixelRatio,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user