mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Merge branch 'master' into patch-1
This commit is contained in:
@@ -1,13 +1,15 @@
|
||||
{
|
||||
"name": "xterm.js",
|
||||
"image": "mcr.microsoft.com/devcontainers/typescript-node:0-18-buster",
|
||||
"image": "mcr.microsoft.com/devcontainers/typescript-node:18-bookworm",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/node:1": {} // yarn
|
||||
"ghcr.io/devcontainers/features/node:1": {
|
||||
"version": 18
|
||||
} // yarn
|
||||
},
|
||||
"forwardPorts": [
|
||||
3000
|
||||
],
|
||||
"postCreateCommand": "yarn install",
|
||||
"postCreateCommand": "yarn install && yarn setup",
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
|
||||
Vendored
+1
-1
@@ -61,7 +61,7 @@
|
||||
"runtimeExecutable": "npm",
|
||||
"runtimeArgs": ["start"],
|
||||
"stopOnEntry": true,
|
||||
"runtimeVersion": "16",
|
||||
"runtimeVersion": "18",
|
||||
"serverReadyAction": {
|
||||
"action": "openExternally",
|
||||
"pattern": "App listening to (http://.*?:[0-9]+)"
|
||||
|
||||
@@ -21,7 +21,7 @@ Xterm.js is a front-end component written in TypeScript that lets applications b
|
||||
First, you need to install the module, we ship exclusively through [npm](https://www.npmjs.com/), so you need that installed and then add xterm.js as a dependency by running:
|
||||
|
||||
```bash
|
||||
npm install xterm
|
||||
npm install @xterm/xterm
|
||||
```
|
||||
|
||||
To start using xterm.js on your browser, add the `xterm.js` and `xterm.css` to the head of your HTML page. Then create a `<div id="terminal"></div>` onto which xterm can attach itself. Finally, instantiate the `Terminal` object and then call the `open` function with the DOM object of the `div`.
|
||||
@@ -30,8 +30,8 @@ To start using xterm.js on your browser, add the `xterm.js` and `xterm.css` to t
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="node_modules/xterm/css/xterm.css" />
|
||||
<script src="node_modules/xterm/lib/xterm.js"></script>
|
||||
<link rel="stylesheet" href="node_modules/@xterm/xterm/css/xterm.css" />
|
||||
<script src="node_modules/@xterm/xterm/lib/xterm.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="terminal"></div>
|
||||
@@ -113,7 +113,7 @@ All current and past releases are available on this repo's [Releases page](https
|
||||
Our CI releases beta builds to npm for every change that goes into master. Install the latest beta build with:
|
||||
|
||||
```bash
|
||||
npm install -S xterm@beta
|
||||
npm install -S @xterm/xterm@beta
|
||||
```
|
||||
|
||||
These should generally be stable, but some bugs may slip in. We recommend using the beta build primarily to test out new features and to verify bug fixes.
|
||||
@@ -222,6 +222,7 @@ Xterm.js is used in several world-class applications to provide great terminal e
|
||||
- [**Cloudtutor.io**](https://cloudtutor.io): innovative online learning platform that offers users access to an interactive lab.
|
||||
- [**Helix Editor Playground**](https://github.com/tomgroenwoldt/helix-editor-playground): Online playground for the terminal based helix editor.
|
||||
- [**Coder**](https://github.com/coder/coder): Self-Hosted Remote Development Environments
|
||||
- [**Wave Terminal**](https://waveterm.dev): An open-source, ai-native, terminal built for seamless workflows.
|
||||
- [And much more...](https://github.com/xtermjs/xterm.js/network/dependents?package_id=UGFja2FnZS0xNjYzMjc4OQ%3D%3D)
|
||||
|
||||
Do you use xterm.js in your application as well? Please [open a Pull Request](https://github.com/sourcelair/xterm.js/pulls) to include it here. We would love to have it on our list. Note: Please add any new contributions to the end of the list only.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xterm/addon-attach",
|
||||
"version": "0.9.0",
|
||||
"version": "0.11.0",
|
||||
"author": {
|
||||
"name": "The xterm.js authors",
|
||||
"url": "https://xtermjs.org/"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xterm/addon-canvas",
|
||||
"version": "0.5.0",
|
||||
"version": "0.7.0",
|
||||
"author": {
|
||||
"name": "The xterm.js authors",
|
||||
"url": "https://xtermjs.org/"
|
||||
|
||||
@@ -8,7 +8,7 @@ import { CellColorResolver } from 'browser/renderer/shared/CellColorResolver';
|
||||
import { acquireTextureAtlas } from 'browser/renderer/shared/CharAtlasCache';
|
||||
import { TEXT_BASELINE } from 'browser/renderer/shared/Constants';
|
||||
import { tryDrawCustomChar } from 'browser/renderer/shared/CustomGlyphs';
|
||||
import { throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
|
||||
import { allowRescaling, throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
|
||||
import { createSelectionRenderModel } from 'browser/renderer/shared/SelectionRenderModel';
|
||||
import { IRasterizedGlyph, IRenderDimensions, ISelectionRenderModel, ITextureAtlas } from 'browser/renderer/shared/Types';
|
||||
import { ICoreBrowserService, IThemeService } from 'browser/services/Services';
|
||||
@@ -365,6 +365,8 @@ export abstract class BaseRenderLayer extends Disposable implements IRenderLayer
|
||||
*/
|
||||
protected _drawChars(cell: ICellData, x: number, y: number): void {
|
||||
const chars = cell.getChars();
|
||||
const code = cell.getCode();
|
||||
const width = cell.getWidth();
|
||||
this._cellColorResolver.resolve(cell, x, this._bufferService.buffer.ydisp + y, this._deviceCellWidth);
|
||||
|
||||
if (!this._charAtlas) {
|
||||
@@ -400,6 +402,16 @@ export abstract class BaseRenderLayer extends Disposable implements IRenderLayer
|
||||
this._bitmapGenerator[glyph.texturePage]!.refresh();
|
||||
this._bitmapGenerator[glyph.texturePage]!.version = this._charAtlas.pages[glyph.texturePage].version;
|
||||
}
|
||||
|
||||
// Reduce scale horizontally for wide glyphs printed in cells that would overlap with the
|
||||
// following cell (ie. the width is not 2).
|
||||
let renderWidth = glyph.size.x;
|
||||
if (this._optionsService.rawOptions.rescaleOverlappingGlyphs) {
|
||||
if (allowRescaling(code, width, glyph.size.x, this._deviceCellWidth)) {
|
||||
renderWidth = this._deviceCellWidth - 1; // - 1 to improve readability
|
||||
}
|
||||
}
|
||||
|
||||
this._ctx.drawImage(
|
||||
this._bitmapGenerator[glyph.texturePage]?.bitmap || this._charAtlas!.pages[glyph.texturePage].canvas,
|
||||
glyph.texturePosition.x,
|
||||
@@ -408,7 +420,7 @@ export abstract class BaseRenderLayer extends Disposable implements IRenderLayer
|
||||
glyph.size.y,
|
||||
x * this._deviceCellWidth + this._deviceCharLeft - glyph.offset.x,
|
||||
y * this._deviceCellHeight + this._deviceCharTop - glyph.offset.y,
|
||||
glyph.size.x,
|
||||
renderWidth,
|
||||
glyph.size.y
|
||||
);
|
||||
this._ctx.restore();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xterm/addon-fit",
|
||||
"version": "0.8.0",
|
||||
"version": "0.10.0",
|
||||
"author": {
|
||||
"name": "The xterm.js authors",
|
||||
"url": "https://xtermjs.org/"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xterm/addon-image",
|
||||
"version": "0.6.0",
|
||||
"version": "0.8.0",
|
||||
"author": {
|
||||
"name": "The xterm.js authors",
|
||||
"url": "https://xtermjs.org/"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xterm/addon-ligatures",
|
||||
"version": "0.7.0",
|
||||
"version": "0.9.0",
|
||||
"description": "Add support for programming ligatures to xterm.js",
|
||||
"author": {
|
||||
"name": "The xterm.js authors",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xterm/addon-search",
|
||||
"version": "0.13.0",
|
||||
"version": "0.15.0",
|
||||
"author": {
|
||||
"name": "The xterm.js authors",
|
||||
"url": "https://xtermjs.org/"
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import type { Terminal, IDisposable, ITerminalAddon, IDecoration } from '@xterm/xterm';
|
||||
import type { SearchAddon as ISearchApi } from '@xterm/addon-search';
|
||||
import { EventEmitter } from 'common/EventEmitter';
|
||||
import { Disposable, toDisposable, disposeArray, MutableDisposable } from 'common/Lifecycle';
|
||||
import { Disposable, toDisposable, disposeArray, MutableDisposable, getDisposeArrayDisposable } from 'common/Lifecycle';
|
||||
|
||||
export interface ISearchOptions {
|
||||
regex?: boolean;
|
||||
@@ -78,8 +78,7 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
|
||||
*/
|
||||
private _linesCache: LineCacheEntry[] | undefined;
|
||||
private _linesCacheTimeoutId = 0;
|
||||
private _cursorMoveListener: IDisposable | undefined;
|
||||
private _resizeListener: IDisposable | undefined;
|
||||
private _linesCacheDisposables = new MutableDisposable();
|
||||
|
||||
private readonly _onDidChangeResults = this.register(new EventEmitter<{ resultIndex: number, resultCount: number }>());
|
||||
public readonly onDidChangeResults = this._onDidChangeResults.event;
|
||||
@@ -427,8 +426,11 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
|
||||
const terminal = this._terminal!;
|
||||
if (!this._linesCache) {
|
||||
this._linesCache = new Array(terminal.buffer.active.length);
|
||||
this._cursorMoveListener = terminal.onCursorMove(() => this._destroyLinesCache());
|
||||
this._resizeListener = terminal.onResize(() => this._destroyLinesCache());
|
||||
this._linesCacheDisposables.value = getDisposeArrayDisposable([
|
||||
terminal.onLineFeed(() => this._destroyLinesCache()),
|
||||
terminal.onCursorMove(() => this._destroyLinesCache()),
|
||||
terminal.onResize(() => this._destroyLinesCache())
|
||||
]);
|
||||
}
|
||||
|
||||
window.clearTimeout(this._linesCacheTimeoutId);
|
||||
@@ -437,14 +439,7 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
|
||||
|
||||
private _destroyLinesCache(): void {
|
||||
this._linesCache = undefined;
|
||||
if (this._cursorMoveListener) {
|
||||
this._cursorMoveListener.dispose();
|
||||
this._cursorMoveListener = undefined;
|
||||
}
|
||||
if (this._resizeListener) {
|
||||
this._resizeListener.dispose();
|
||||
this._resizeListener = undefined;
|
||||
}
|
||||
this._linesCacheDisposables.clear();
|
||||
if (this._linesCacheTimeoutId) {
|
||||
window.clearTimeout(this._linesCacheTimeoutId);
|
||||
this._linesCacheTimeoutId = 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xterm/addon-serialize",
|
||||
"version": "0.11.0",
|
||||
"version": "0.13.0",
|
||||
"author": {
|
||||
"name": "The xterm.js authors",
|
||||
"url": "https://xtermjs.org/"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xterm/addon-unicode-graphemes",
|
||||
"version": "0.1.0",
|
||||
"version": "0.3.0",
|
||||
"author": {
|
||||
"name": "The xterm.js authors",
|
||||
"url": "https://xtermjs.org/"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xterm/addon-unicode11",
|
||||
"version": "0.6.0",
|
||||
"version": "0.8.0",
|
||||
"author": {
|
||||
"name": "The xterm.js authors",
|
||||
"url": "https://xtermjs.org/"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xterm/addon-web-links",
|
||||
"version": "0.9.0",
|
||||
"version": "0.11.0",
|
||||
"author": {
|
||||
"name": "The xterm.js authors",
|
||||
"url": "https://xtermjs.org/"
|
||||
|
||||
@@ -41,16 +41,18 @@ export class WebLinkProvider implements ILinkProvider {
|
||||
}
|
||||
}
|
||||
|
||||
function baseUrlString(url: URL): string {
|
||||
if (url.password && url.username) {
|
||||
return `${url.protocol}//${url.username}:${url.password}@${url.host}`;
|
||||
function isUrl(urlString: string): boolean {
|
||||
try {
|
||||
const url = new URL(urlString);
|
||||
const parsedBase = url.password && url.username
|
||||
? `${url.protocol}//${url.username}:${url.password}@${url.host}`
|
||||
: url.username
|
||||
? `${url.protocol}//${url.username}@${url.host}`
|
||||
: `${url.protocol}//${url.host}`;
|
||||
return urlString.toLocaleLowerCase().startsWith(parsedBase.toLocaleLowerCase());
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (url.username) {
|
||||
return `${url.protocol}//${url.username}@${url.host}`;
|
||||
}
|
||||
|
||||
return `${url.protocol}//${url.host}`;
|
||||
}
|
||||
|
||||
export class LinkComputer {
|
||||
@@ -67,15 +69,7 @@ export class LinkComputer {
|
||||
const text = match[0];
|
||||
|
||||
// check via URL if the matched text would form a proper url
|
||||
// NOTE: This outsources the ugly url parsing to the browser.
|
||||
// we check if the provided string resembles the URL-parsed one
|
||||
// up to the end of the domain name (ignoring path and params)
|
||||
try {
|
||||
const url = new URL(text);
|
||||
if (!text.startsWith(baseUrlString(url))) {
|
||||
continue;
|
||||
}
|
||||
} catch (e) {
|
||||
if (!isUrl(text)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import { ILinkProviderOptions, WebLinkProvider } from './WebLinkProvider';
|
||||
// - final interpunction like ,.!?
|
||||
// - any sort of brackets <>()[]{} (not spec conform, but often used to enclose urls)
|
||||
// - unsafe chars from rfc1738: {}|\^~[]`
|
||||
const strictUrlRegex = /https?:[/]{2}[^\s"'!*(){}|\\\^<>`]*[^\s"':,.!?{}|\\\^~\[\]`()<>]/;
|
||||
const strictUrlRegex = /(https?|HTTPS?):[/]{2}[^\s"'!*(){}|\\\^<>`]*[^\s"':,.!?{}|\\\^~\[\]`()<>]/;
|
||||
|
||||
|
||||
function handleLink(event: MouseEvent, uri: string): void {
|
||||
|
||||
@@ -123,6 +123,21 @@ describe('WebLinksAddon', () => {
|
||||
await evalLinkStateData('http://test:password@example.com/some_path?param=1%202%3', { start: { x: 12, y: 1 }, end: { x: 27, y: 2 } });
|
||||
});
|
||||
});
|
||||
|
||||
// issue #4964
|
||||
it('uppercase in protocol and host, default ports', async () => {
|
||||
const data = ` HTTP://EXAMPLE.COM \\r\\n` +
|
||||
` HTTPS://Example.com \\r\\n` +
|
||||
` HTTP://Example.com:80 \\r\\n` +
|
||||
` HTTP://Example.com:80/staysUpper \\r\\n` +
|
||||
` HTTP://Ab:xY@abc.com:80/staysUpper \\r\\n`;
|
||||
await writeSync(page, data);
|
||||
await pollForLinkAtCell(3, 0, `HTTP://EXAMPLE.COM`);
|
||||
await pollForLinkAtCell(3, 1, `HTTPS://Example.com`);
|
||||
await pollForLinkAtCell(3, 2, `HTTP://Example.com:80`);
|
||||
await pollForLinkAtCell(3, 3, `HTTP://Example.com:80/staysUpper`);
|
||||
await pollForLinkAtCell(3, 4, `HTTP://Ab:xY@abc.com:80/staysUpper`);
|
||||
});
|
||||
});
|
||||
|
||||
async function testHostName(hostname: string): Promise<void> {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xterm/addon-webgl",
|
||||
"version": "0.16.0",
|
||||
"version": "0.18.0",
|
||||
"author": {
|
||||
"name": "The xterm.js authors",
|
||||
"url": "https://xtermjs.org/"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user