diff --git a/.eslintrc.json b/.eslintrc.json index 0ccafafbf4..9ba5012081 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -14,29 +14,29 @@ "test/api/tsconfig.json", "test/benchmark/tsconfig.json", "test/playwright/tsconfig.json", - "addons/xterm-addon-attach/src/tsconfig.json", - "addons/xterm-addon-attach/test/tsconfig.json", - "addons/xterm-addon-canvas/src/tsconfig.json", - "addons/xterm-addon-canvas/test/tsconfig.json", - "addons/xterm-addon-fit/src/tsconfig.json", - "addons/xterm-addon-fit/test/tsconfig.json", - "addons/xterm-addon-image/src/tsconfig.json", - "addons/xterm-addon-image/test/tsconfig.json", - "addons/xterm-addon-ligatures/src/tsconfig.json", - "addons/xterm-addon-search/src/tsconfig.json", - "addons/xterm-addon-search/test/tsconfig.json", - "addons/xterm-addon-serialize/src/tsconfig.json", - "addons/xterm-addon-serialize/test/tsconfig.json", - "addons/xterm-addon-serialize/benchmark/tsconfig.json", - "addons/xterm-addon-unicode11/src/tsconfig.json", - "addons/xterm-addon-unicode11/test/tsconfig.json", - "addons/xterm-addon-unicode-graphemes/src/tsconfig.json", - "addons/xterm-addon-unicode-graphemes/test/tsconfig.json", - "addons/xterm-addon-unicode-graphemes/benchmark/tsconfig.json", - "addons/xterm-addon-web-links/src/tsconfig.json", - "addons/xterm-addon-web-links/test/tsconfig.json", - "addons/xterm-addon-webgl/src/tsconfig.json", - "addons/xterm-addon-webgl/test/tsconfig.json" + "addons/addon-attach/src/tsconfig.json", + "addons/addon-attach/test/tsconfig.json", + "addons/addon-canvas/src/tsconfig.json", + "addons/addon-canvas/test/tsconfig.json", + "addons/addon-fit/src/tsconfig.json", + "addons/addon-fit/test/tsconfig.json", + "addons/addon-image/src/tsconfig.json", + "addons/addon-image/test/tsconfig.json", + "addons/addon-ligatures/src/tsconfig.json", + "addons/addon-search/src/tsconfig.json", + "addons/addon-search/test/tsconfig.json", + "addons/addon-serialize/src/tsconfig.json", + "addons/addon-serialize/test/tsconfig.json", + "addons/addon-serialize/benchmark/tsconfig.json", + "addons/addon-unicode11/src/tsconfig.json", + "addons/addon-unicode11/test/tsconfig.json", + "addons/addon-unicode-graphemes/src/tsconfig.json", + "addons/addon-unicode-graphemes/test/tsconfig.json", + "addons/addon-unicode-graphemes/benchmark/tsconfig.json", + "addons/addon-web-links/src/tsconfig.json", + "addons/addon-web-links/test/tsconfig.json", + "addons/addon-webgl/src/tsconfig.json", + "addons/addon-webgl/test/tsconfig.json" ], "sourceType": "module" }, diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eea525d063..0a64b6a7cc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,28 +26,28 @@ jobs: zip -r compressed-build \ ./out/* \ ./out-test/* \ - ./addons/xterm-addon-attach/out/* \ - ./addons/xterm-addon-attach/out-test/* \ - ./addons/xterm-addon-canvas/out/* \ - ./addons/xterm-addon-canvas/out-test/* \ - ./addons/xterm-addon-fit/out/* \ - ./addons/xterm-addon-fit/out-test/* \ - ./addons/xterm-addon-image/out/* \ - ./addons/xterm-addon-image/out-test/* \ - ./addons/xterm-addon-ligatures/out/* \ - ./addons/xterm-addon-ligatures/out-test/* \ - ./addons/xterm-addon-search/out/* \ - ./addons/xterm-addon-search/out-test/* \ - ./addons/xterm-addon-serialize/out/* \ - ./addons/xterm-addon-serialize/out-test/* \ - ./addons/xterm-addon-unicode11/out/* \ - ./addons/xterm-addon-unicode11/out-test/* \ - ./addons/xterm-addon-unicode-graphemes/out/* \ - ./addons/xterm-addon-unicode-graphemes/out-test/* \ - ./addons/xterm-addon-web-links/out/* \ - ./addons/xterm-addon-web-links/out-test/* \ - ./addons/xterm-addon-webgl/out/* \ - ./addons/xterm-addon-webgl/out-test/* + ./addons/addon-attach/out/* \ + ./addons/addon-attach/out-test/* \ + ./addons/addon-canvas/out/* \ + ./addons/addon-canvas/out-test/* \ + ./addons/addon-fit/out/* \ + ./addons/addon-fit/out-test/* \ + ./addons/addon-image/out/* \ + ./addons/addon-image/out-test/* \ + ./addons/addon-ligatures/out/* \ + ./addons/addon-ligatures/out-test/* \ + ./addons/addon-search/out/* \ + ./addons/addon-search/out-test/* \ + ./addons/addon-serialize/out/* \ + ./addons/addon-serialize/out-test/* \ + ./addons/addon-unicode11/out/* \ + ./addons/addon-unicode11/out-test/* \ + ./addons/addon-unicode-graphemes/out/* \ + ./addons/addon-unicode-graphemes/out-test/* \ + ./addons/addon-web-links/out/* \ + ./addons/addon-web-links/out-test/* \ + ./addons/addon-webgl/out/* \ + ./addons/addon-webgl/out-test/* - name: Upload artifacts uses: actions/upload-artifact@v3 with: @@ -265,10 +265,10 @@ jobs: run: yarn build-demo - name: Integration tests (core) # Tests use 50% workers to reduce flakiness run: yarn test-playwright-${{ matrix.browser }} --workers=50% --forbid-only --suite=core - - name: Integration tests (xterm-addon-canvas) - run: yarn test-playwright-${{ matrix.browser }} --workers=50% --forbid-only --suite=xterm-addon-canvas - - name: Integration tests (xterm-addon-webgl) - run: yarn test-playwright-${{ matrix.browser }} --workers=50% --forbid-only --suite=xterm-addon-webgl + - name: Integration tests (addon-canvas) + run: yarn test-playwright-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-canvas + - name: Integration tests (addon-webgl) + run: yarn test-playwright-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-webgl test-api: needs: build @@ -306,3 +306,41 @@ jobs: ls -R - name: Integration tests (${{ matrix.browser }}) run: yarn test-api-${{ matrix.browser }} --headless --forbid-only + + release-dry-run: + needs: build + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [18] + steps: + - uses: actions/checkout@v3 + - name: Use Node.js ${{ matrix.node-version }}.x + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }}.x + cache: 'yarn' + - name: Install dependencies + run: | + yarn --frozen-lockfile + yarn install-addons + - name: Install playwright + run: npx playwright install + - uses: actions/download-artifact@v3 + with: + name: build-artifacts + - name: Unzip artifacts + shell: bash + run: | + if [ "$RUNNER_OS" == "Windows" ]; then + pwsh -Command "7z x compressed-build.zip -aoa -o${{ github.workspace }}" + else + unzip -o compressed-build.zip + fi + ls -R + - name: Package headless + run: | + yarn package-headless + node ./bin/package_headless.js + - name: Publish to npm (dry run) + run: node ./bin/publish.js --dry diff --git a/README.md b/README.md index 0abcd32cf5..7514e76c4e 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ To start using xterm.js on your browser, add the `xterm.js` and `xterm.css` to t The recommended way to load xterm.js is via the ES6 module syntax: ```javascript -import { Terminal } from 'xterm'; +import { Terminal } from '@xterm/xterm'; ``` ### Addons @@ -59,14 +59,14 @@ import { Terminal } from 'xterm'; Addons are separate modules that extend the `Terminal` by building on the [xterm.js API](https://github.com/xtermjs/xterm.js/blob/master/typings/xterm.d.ts). To use an addon, you first need to install it in your project: ```bash -npm i -S xterm-addon-web-links +npm i -S @xterm/addon-web-links ``` Then import the addon, instantiate it and call `Terminal.loadAddon`: ```ts -import { Terminal } from 'xterm'; -import { WebLinksAddon } from 'xterm-addon-web-links'; +import { Terminal } from '@xterm/xterm'; +import { WebLinksAddon } from '@xterm/addon-web-links'; const terminal = new Terminal(); // Load WebLinksAddon on terminal, this is all that's needed to get web links @@ -76,10 +76,15 @@ terminal.loadAddon(new WebLinksAddon()); The xterm.js team maintains the following addons, but anyone can build them: -- [`xterm-addon-attach`](https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-attach): Attaches to a server running a process via a websocket -- [`xterm-addon-fit`](https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-fit): Fits the terminal to the containing element -- [`xterm-addon-search`](https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-search): Adds search functionality -- [`xterm-addon-web-links`](https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-web-links): Adds web link detection and interaction +- [`@xterm/addon-attach`](https://github.com/xtermjs/xterm.js/tree/master/addons/addon-attach): Attaches to a server running a process via a websocket +- [`@xterm/addon-canvas`](https://github.com/xtermjs/xterm.js/tree/master/addons/addon-canvas): Renders xterm.js using a `canvas` element's 2d context +- [`@xterm/addon-fit`](https://github.com/xtermjs/xterm.js/tree/master/addons/addon-fit): Fits the terminal to the containing element +- [`@xterm/addon-image`](https://github.com/xtermjs/xterm.js/tree/master/addons/addon-image): Adds image support +- [`@xterm/addon-search`](https://github.com/xtermjs/xterm.js/tree/master/addons/addon-search): Adds search functionality +- [`@xterm/addon-serialize`](https://github.com/xtermjs/xterm.js/tree/master/addons/addon-serialize): Serializes the terminal's buffer to a VT sequences or HTML +- [`@xterm/addon-unicode11`](https://github.com/xtermjs/xterm.js/tree/master/addons/addon-unicode11): Updates character widths to their unicode11 values +- [`@xterm/addon-web-links`](https://github.com/xtermjs/xterm.js/tree/master/addons/addon-web-links): Adds web link detection and interaction +- [`@xterm/addon-webgl`](https://github.com/xtermjs/xterm.js/tree/master/addons/addon-webgl): Renders xterm.js using a `canvas` element's webgl2 context ## Browser Support diff --git a/addons/xterm-addon-attach/.gitignore b/addons/addon-attach/.gitignore similarity index 100% rename from addons/xterm-addon-attach/.gitignore rename to addons/addon-attach/.gitignore diff --git a/addons/xterm-addon-attach/.npmignore b/addons/addon-attach/.npmignore similarity index 100% rename from addons/xterm-addon-attach/.npmignore rename to addons/addon-attach/.npmignore diff --git a/addons/xterm-addon-attach/LICENSE b/addons/addon-attach/LICENSE similarity index 100% rename from addons/xterm-addon-attach/LICENSE rename to addons/addon-attach/LICENSE diff --git a/addons/xterm-addon-attach/README.md b/addons/addon-attach/README.md similarity index 61% rename from addons/xterm-addon-attach/README.md rename to addons/addon-attach/README.md index 67ebf17b0e..fa123fe288 100644 --- a/addons/xterm-addon-attach/README.md +++ b/addons/addon-attach/README.md @@ -1,22 +1,22 @@ -## xterm-addon-attach +## @xterm/addon-attach An addon for [xterm.js](https://github.com/xtermjs/xterm.js) that enables attaching to a web socket. This addon requires xterm.js v4+. ### Install ```bash -npm install --save xterm-addon-attach +npm install --save @xterm/addon-attach ``` ### Usage ```ts -import { Terminal } from 'xterm'; -import { AttachAddon } from 'xterm-addon-attach'; +import { Terminal } from '@xterm/xterm'; +import { AttachAddon } from '@xterm/addon-attach'; const terminal = new Terminal(); const attachAddon = new AttachAddon(webSocket); terminal.loadAddon(attachAddon); ``` -See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/xterm-addon-attach/typings/xterm-addon-attach.d.ts) for more advanced usage. +See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/addon-attach/typings/addon-attach.d.ts) for more advanced usage. diff --git a/addons/xterm-addon-attach/package.json b/addons/addon-attach/package.json similarity index 74% rename from addons/xterm-addon-attach/package.json rename to addons/addon-attach/package.json index be92fc66ea..94b483dd87 100644 --- a/addons/xterm-addon-attach/package.json +++ b/addons/addon-attach/package.json @@ -1,13 +1,13 @@ { - "name": "xterm-addon-attach", + "name": "@xterm/addon-attach", "version": "0.9.0", "author": { "name": "The xterm.js authors", "url": "https://xtermjs.org/" }, - "main": "lib/xterm-addon-attach.js", - "types": "typings/xterm-addon-attach.d.ts", - "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-attach", + "main": "lib/addon-attach.js", + "types": "typings/addon-attach.d.ts", + "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/addon-attach", "license": "MIT", "keywords": [ "terminal", @@ -21,6 +21,6 @@ "prepublishOnly": "npm run package" }, "peerDependencies": { - "xterm": "^5.0.0" + "@xterm/xterm": "^5.0.0" } } diff --git a/addons/xterm-addon-attach/src/AttachAddon.ts b/addons/addon-attach/src/AttachAddon.ts similarity index 92% rename from addons/xterm-addon-attach/src/AttachAddon.ts rename to addons/addon-attach/src/AttachAddon.ts index 7fd8df29ab..37a10d170b 100644 --- a/addons/xterm-addon-attach/src/AttachAddon.ts +++ b/addons/addon-attach/src/AttachAddon.ts @@ -5,13 +5,14 @@ * Implements the attach method, that attaches the terminal to a WebSocket stream. */ -import { Terminal, IDisposable, ITerminalAddon } from 'xterm'; +import type { Terminal, IDisposable, ITerminalAddon } from '@xterm/xterm'; +import type { AttachAddon as IAttachApi } from '@xterm/addon-attach'; interface IAttachOptions { bidirectional?: boolean; } -export class AttachAddon implements ITerminalAddon { +export class AttachAddon implements ITerminalAddon , IAttachApi { private _socket: WebSocket; private _bidirectional: boolean; private _disposables: IDisposable[] = []; diff --git a/addons/xterm-addon-attach/src/tsconfig.json b/addons/addon-attach/src/tsconfig.json similarity index 77% rename from addons/xterm-addon-attach/src/tsconfig.json rename to addons/addon-attach/src/tsconfig.json index 7e68574d95..9838a3c50f 100644 --- a/addons/xterm-addon-attach/src/tsconfig.json +++ b/addons/addon-attach/src/tsconfig.json @@ -13,7 +13,12 @@ "strict": true, "types": [ "../../../node_modules/@types/mocha" - ] + ], + "paths": { + "@xterm/addon-attach": [ + "../typings/addon-attach.d.ts" + ] + } }, "include": [ "./**/*", diff --git a/addons/xterm-addon-attach/test/AttachAddon.api.ts b/addons/addon-attach/test/AttachAddon.api.ts similarity index 100% rename from addons/xterm-addon-attach/test/AttachAddon.api.ts rename to addons/addon-attach/test/AttachAddon.api.ts diff --git a/addons/xterm-addon-attach/test/tsconfig.json b/addons/addon-attach/test/tsconfig.json similarity index 100% rename from addons/xterm-addon-attach/test/tsconfig.json rename to addons/addon-attach/test/tsconfig.json diff --git a/addons/xterm-addon-attach/tsconfig.json b/addons/addon-attach/tsconfig.json similarity index 100% rename from addons/xterm-addon-attach/tsconfig.json rename to addons/addon-attach/tsconfig.json diff --git a/addons/xterm-addon-attach/typings/xterm-addon-attach.d.ts b/addons/addon-attach/typings/addon-attach.d.ts similarity index 82% rename from addons/xterm-addon-attach/typings/xterm-addon-attach.d.ts rename to addons/addon-attach/typings/addon-attach.d.ts index 2956b9d906..4e1b2fc3ba 100644 --- a/addons/xterm-addon-attach/typings/xterm-addon-attach.d.ts +++ b/addons/addon-attach/typings/addon-attach.d.ts @@ -3,9 +3,9 @@ * @license MIT */ -import { Terminal, ITerminalAddon } from 'xterm'; +import { Terminal, ITerminalAddon } from '@xterm/xterm'; -declare module 'xterm-addon-attach' { +declare module '@xterm/addon-attach' { export interface IAttachOptions { /** * Whether input should be written to the backend. Defaults to `true`. diff --git a/addons/xterm-addon-attach/webpack.config.js b/addons/addon-attach/webpack.config.js similarity index 92% rename from addons/xterm-addon-attach/webpack.config.js rename to addons/addon-attach/webpack.config.js index 65996f19cf..599bb14204 100644 --- a/addons/xterm-addon-attach/webpack.config.js +++ b/addons/addon-attach/webpack.config.js @@ -6,7 +6,7 @@ const path = require('path'); const addonName = 'AttachAddon'; -const mainFile = 'xterm-addon-attach.js'; +const mainFile = 'addon-attach.js'; module.exports = { entry: `./out/${addonName}.js`, diff --git a/addons/xterm-addon-canvas/.gitignore b/addons/addon-canvas/.gitignore similarity index 100% rename from addons/xterm-addon-canvas/.gitignore rename to addons/addon-canvas/.gitignore diff --git a/addons/xterm-addon-canvas/.npmignore b/addons/addon-canvas/.npmignore similarity index 100% rename from addons/xterm-addon-canvas/.npmignore rename to addons/addon-canvas/.npmignore diff --git a/addons/xterm-addon-canvas/LICENSE b/addons/addon-canvas/LICENSE similarity index 100% rename from addons/xterm-addon-canvas/LICENSE rename to addons/addon-canvas/LICENSE diff --git a/addons/addon-canvas/README.md b/addons/addon-canvas/README.md new file mode 100644 index 0000000000..502ade258e --- /dev/null +++ b/addons/addon-canvas/README.md @@ -0,0 +1,28 @@ +## @xterm/addon-canvas + +An addon for [xterm.js](https://github.com/xtermjs/xterm.js) that enables a canvas-based renderer using a 2d context to draw. This addon requires xterm.js v5+. + +The purpose of this addon is to be used as a fallback for the [webgl addon](https://www.npmjs.com/package/@xterm/addon-webgl) when better performance is desired over the default DOM renderer, but WebGL2 isn't supported or performant for some reason. + +### Install + +```bash +npm install --save @xterm/addon-canvas +``` + +### Usage + +```ts +import { Terminal } from '@xterm/xterm'; +import { CanvasAddon } from '@xterm/addon-canvas'; + +const terminal = new Terminal(); +terminal.open(element); +terminal.loadAddon(new CanvasAddon()); +``` + +See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/addon-canvas/typings/addon-canvas.d.ts) for more advanced usage. + +### See also + +- [@xterm/addon-webgl](https://www.npmjs.com/package/@xterm/addon-webgl) A renderer for xterm.js that uses WebGL diff --git a/addons/xterm-addon-canvas/package.json b/addons/addon-canvas/package.json similarity index 76% rename from addons/xterm-addon-canvas/package.json rename to addons/addon-canvas/package.json index eefdf3751d..9aabb001fb 100644 --- a/addons/xterm-addon-canvas/package.json +++ b/addons/addon-canvas/package.json @@ -1,13 +1,13 @@ { - "name": "xterm-addon-canvas", + "name": "@xterm/addon-canvas", "version": "0.5.0", "author": { "name": "The xterm.js authors", "url": "https://xtermjs.org/" }, - "main": "lib/xterm-addon-canvas.js", - "types": "typings/xterm-addon-canvas.d.ts", - "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-canvas", + "main": "lib/addon-canvas.js", + "types": "typings/addon-canvas.d.ts", + "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/addon-canvas", "license": "MIT", "keywords": [ "terminal", @@ -23,6 +23,6 @@ "start-server-only": "node ../../demo/start-server-only" }, "peerDependencies": { - "xterm": "^5.0.0" + "@xterm/xterm": "^5.0.0" } } diff --git a/addons/xterm-addon-canvas/src/BaseRenderLayer.ts b/addons/addon-canvas/src/BaseRenderLayer.ts similarity index 98% rename from addons/xterm-addon-canvas/src/BaseRenderLayer.ts rename to addons/addon-canvas/src/BaseRenderLayer.ts index 8c1993366a..e7e234003e 100644 --- a/addons/xterm-addon-canvas/src/BaseRenderLayer.ts +++ b/addons/addon-canvas/src/BaseRenderLayer.ts @@ -19,7 +19,7 @@ import { ICellData } from 'common/Types'; import { CellData } from 'common/buffer/CellData'; import { WHITESPACE_CELL_CODE } from 'common/buffer/Constants'; import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services'; -import { Terminal } from 'xterm'; +import { Terminal } from '@xterm/xterm'; import { IRenderLayer } from './Types'; export abstract class BaseRenderLayer extends Disposable implements IRenderLayer { @@ -58,8 +58,8 @@ export abstract class BaseRenderLayer extends Disposable implements IRenderLayer protected readonly _coreBrowserService: ICoreBrowserService ) { super(); - this._cellColorResolver = new CellColorResolver(this._terminal, this._selectionModel, this._decorationService, this._coreBrowserService, this._themeService); - this._canvas = document.createElement('canvas'); + this._cellColorResolver = new CellColorResolver(this._terminal, this._optionsService, this._selectionModel, this._decorationService, this._coreBrowserService, this._themeService); + this._canvas = this._coreBrowserService.mainDocument.createElement('canvas'); this._canvas.classList.add(`xterm-${id}-layer`); this._canvas.style.zIndex = zIndex.toString(); this._initCanvas(); @@ -91,7 +91,7 @@ export abstract class BaseRenderLayer extends Disposable implements IRenderLayer public handleGridChanged(startRow: number, endRow: number): void {} public handleSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean = false): void { - this._selectionModel.update(this._terminal, start, end, columnSelectMode); + this._selectionModel.update((this._terminal as any)._core, start, end, columnSelectMode); } protected _setTransparency(alpha: boolean): void { @@ -365,7 +365,7 @@ export abstract class BaseRenderLayer extends Disposable implements IRenderLayer */ protected _drawChars(cell: ICellData, x: number, y: number): void { const chars = cell.getChars(); - this._cellColorResolver.resolve(cell, x, this._bufferService.buffer.ydisp + y); + this._cellColorResolver.resolve(cell, x, this._bufferService.buffer.ydisp + y, this._deviceCellWidth); if (!this._charAtlas) { return; diff --git a/addons/xterm-addon-canvas/src/CanvasAddon.ts b/addons/addon-canvas/src/CanvasAddon.ts similarity index 93% rename from addons/xterm-addon-canvas/src/CanvasAddon.ts rename to addons/addon-canvas/src/CanvasAddon.ts index 91438a4c87..7f7f679bc1 100644 --- a/addons/xterm-addon-canvas/src/CanvasAddon.ts +++ b/addons/addon-canvas/src/CanvasAddon.ts @@ -3,16 +3,17 @@ * @license MIT */ +import type { ITerminalAddon, Terminal } from '@xterm/xterm'; +import type { CanvasAddon as ICanvasApi } from '@xterm/addon-canvas'; import { ICharacterJoinerService, ICharSizeService, ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services'; import { ITerminal } from 'browser/Types'; import { EventEmitter, forwardEvent } from 'common/EventEmitter'; import { Disposable, toDisposable } from 'common/Lifecycle'; import { setTraceLogger } from 'common/services/LogService'; import { IBufferService, IDecorationService, ILogService } from 'common/services/Services'; -import { ITerminalAddon, Terminal } from 'xterm'; import { CanvasRenderer } from './CanvasRenderer'; -export class CanvasAddon extends Disposable implements ITerminalAddon { +export class CanvasAddon extends Disposable implements ITerminalAddon , ICanvasApi { private _terminal?: Terminal; private _renderer?: CanvasRenderer; @@ -65,4 +66,8 @@ export class CanvasAddon extends Disposable implements ITerminalAddon { this._renderer = undefined; })); } + + public clearTextureAtlas(): void { + this._renderer?.clearTextureAtlas(); + } } diff --git a/addons/xterm-addon-canvas/src/CanvasRenderer.ts b/addons/addon-canvas/src/CanvasRenderer.ts similarity index 99% rename from addons/xterm-addon-canvas/src/CanvasRenderer.ts rename to addons/addon-canvas/src/CanvasRenderer.ts index cd05f92169..40b89546fc 100644 --- a/addons/xterm-addon-canvas/src/CanvasRenderer.ts +++ b/addons/addon-canvas/src/CanvasRenderer.ts @@ -12,7 +12,7 @@ import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, IThemeS import { EventEmitter, forwardEvent } from 'common/EventEmitter'; import { Disposable, toDisposable } from 'common/Lifecycle'; import { IBufferService, ICoreService, IDecorationService, IOptionsService } from 'common/services/Services'; -import { Terminal } from 'xterm'; +import { Terminal } from '@xterm/xterm'; import { CursorRenderLayer } from './CursorRenderLayer'; import { LinkRenderLayer } from './LinkRenderLayer'; import { SelectionRenderLayer } from './SelectionRenderLayer'; diff --git a/addons/xterm-addon-canvas/src/CursorRenderLayer.ts b/addons/addon-canvas/src/CursorRenderLayer.ts similarity index 99% rename from addons/xterm-addon-canvas/src/CursorRenderLayer.ts rename to addons/addon-canvas/src/CursorRenderLayer.ts index c5174f8659..adc1db189f 100644 --- a/addons/xterm-addon-canvas/src/CursorRenderLayer.ts +++ b/addons/addon-canvas/src/CursorRenderLayer.ts @@ -12,7 +12,7 @@ import { isFirefox } from 'common/Platform'; import { ICellData } from 'common/Types'; import { CellData } from 'common/buffer/CellData'; import { IBufferService, ICoreService, IDecorationService, IOptionsService } from 'common/services/Services'; -import { Terminal } from 'xterm'; +import { Terminal } from '@xterm/xterm'; import { BaseRenderLayer } from './BaseRenderLayer'; interface ICursorState { diff --git a/addons/xterm-addon-canvas/src/GridCache.test.ts b/addons/addon-canvas/src/GridCache.test.ts similarity index 100% rename from addons/xterm-addon-canvas/src/GridCache.test.ts rename to addons/addon-canvas/src/GridCache.test.ts diff --git a/addons/xterm-addon-canvas/src/GridCache.ts b/addons/addon-canvas/src/GridCache.ts similarity index 100% rename from addons/xterm-addon-canvas/src/GridCache.ts rename to addons/addon-canvas/src/GridCache.ts diff --git a/addons/xterm-addon-canvas/src/LinkRenderLayer.ts b/addons/addon-canvas/src/LinkRenderLayer.ts similarity index 98% rename from addons/xterm-addon-canvas/src/LinkRenderLayer.ts rename to addons/addon-canvas/src/LinkRenderLayer.ts index 882f7d8c2e..1cdf71c2fc 100644 --- a/addons/xterm-addon-canvas/src/LinkRenderLayer.ts +++ b/addons/addon-canvas/src/LinkRenderLayer.ts @@ -9,7 +9,7 @@ import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/shared/Constants'; import { IRenderDimensions } from 'browser/renderer/shared/Types'; import { ICoreBrowserService, IThemeService } from 'browser/services/Services'; import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services'; -import { Terminal } from 'xterm'; +import { Terminal } from '@xterm/xterm'; import { BaseRenderLayer } from './BaseRenderLayer'; export class LinkRenderLayer extends BaseRenderLayer { diff --git a/addons/xterm-addon-canvas/src/SelectionRenderLayer.ts b/addons/addon-canvas/src/SelectionRenderLayer.ts similarity index 99% rename from addons/xterm-addon-canvas/src/SelectionRenderLayer.ts rename to addons/addon-canvas/src/SelectionRenderLayer.ts index 10950868fb..01612a1d29 100644 --- a/addons/xterm-addon-canvas/src/SelectionRenderLayer.ts +++ b/addons/addon-canvas/src/SelectionRenderLayer.ts @@ -7,7 +7,7 @@ import { IRenderDimensions } from 'browser/renderer/shared/Types'; import { BaseRenderLayer } from './BaseRenderLayer'; import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services'; import { ICoreBrowserService, IThemeService } from 'browser/services/Services'; -import { Terminal } from 'xterm'; +import { Terminal } from '@xterm/xterm'; interface ISelectionState { start?: [number, number]; diff --git a/addons/xterm-addon-canvas/src/TextRenderLayer.ts b/addons/addon-canvas/src/TextRenderLayer.ts similarity index 99% rename from addons/xterm-addon-canvas/src/TextRenderLayer.ts rename to addons/addon-canvas/src/TextRenderLayer.ts index 46d052f30b..43c33d64ae 100644 --- a/addons/xterm-addon-canvas/src/TextRenderLayer.ts +++ b/addons/addon-canvas/src/TextRenderLayer.ts @@ -11,7 +11,7 @@ import { AttributeData } from 'common/buffer/AttributeData'; import { CellData } from 'common/buffer/CellData'; import { Content, NULL_CELL_CODE } from 'common/buffer/Constants'; import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services'; -import { Terminal } from 'xterm'; +import { Terminal } from '@xterm/xterm'; import { BaseRenderLayer } from './BaseRenderLayer'; import { GridCache } from './GridCache'; diff --git a/addons/xterm-addon-canvas/src/Types.d.ts b/addons/addon-canvas/src/Types.d.ts similarity index 100% rename from addons/xterm-addon-canvas/src/Types.d.ts rename to addons/addon-canvas/src/Types.d.ts diff --git a/addons/xterm-addon-canvas/src/tsconfig.json b/addons/addon-canvas/src/tsconfig.json similarity index 89% rename from addons/xterm-addon-canvas/src/tsconfig.json rename to addons/addon-canvas/src/tsconfig.json index f6fb08a7a0..1ed8c2ac68 100644 --- a/addons/xterm-addon-canvas/src/tsconfig.json +++ b/addons/addon-canvas/src/tsconfig.json @@ -17,6 +17,9 @@ ], "browser/*": [ "../../../src/browser/*" + ], + "@xterm/addon-canvas": [ + "../typings/addon-canvas.d.ts" ] }, "strict": true, diff --git a/addons/xterm-addon-canvas/test/CanvasRenderer.test.ts b/addons/addon-canvas/test/CanvasRenderer.test.ts similarity index 100% rename from addons/xterm-addon-canvas/test/CanvasRenderer.test.ts rename to addons/addon-canvas/test/CanvasRenderer.test.ts diff --git a/addons/xterm-addon-canvas/test/playwright.config.ts b/addons/addon-canvas/test/playwright.config.ts similarity index 100% rename from addons/xterm-addon-canvas/test/playwright.config.ts rename to addons/addon-canvas/test/playwright.config.ts diff --git a/addons/xterm-addon-canvas/test/tsconfig.json b/addons/addon-canvas/test/tsconfig.json similarity index 100% rename from addons/xterm-addon-canvas/test/tsconfig.json rename to addons/addon-canvas/test/tsconfig.json diff --git a/addons/xterm-addon-canvas/tsconfig.json b/addons/addon-canvas/tsconfig.json similarity index 100% rename from addons/xterm-addon-canvas/tsconfig.json rename to addons/addon-canvas/tsconfig.json diff --git a/addons/xterm-addon-canvas/typings/xterm-addon-canvas.d.ts b/addons/addon-canvas/typings/addon-canvas.d.ts similarity index 90% rename from addons/xterm-addon-canvas/typings/xterm-addon-canvas.d.ts rename to addons/addon-canvas/typings/addon-canvas.d.ts index c983825c27..a679f0a5ca 100644 --- a/addons/xterm-addon-canvas/typings/xterm-addon-canvas.d.ts +++ b/addons/addon-canvas/typings/addon-canvas.d.ts @@ -3,9 +3,9 @@ * @license MIT */ -import { Terminal, ITerminalAddon, IEvent } from 'xterm'; +import { Terminal, ITerminalAddon, IEvent } from '@xterm/xterm'; -declare module 'xterm-addon-canvas' { +declare module '@xterm/addon-canvas' { /** * An xterm.js addon that provides search functionality. */ diff --git a/addons/xterm-addon-canvas/webpack.config.js b/addons/addon-canvas/webpack.config.js similarity index 94% rename from addons/xterm-addon-canvas/webpack.config.js rename to addons/addon-canvas/webpack.config.js index 9c98760a1e..9daa08f9b2 100644 --- a/addons/xterm-addon-canvas/webpack.config.js +++ b/addons/addon-canvas/webpack.config.js @@ -6,7 +6,7 @@ const path = require('path'); const addonName = 'CanvasAddon'; -const mainFile = 'xterm-addon-canvas.js'; +const mainFile = 'addon-canvas.js'; module.exports = { entry: `./out/${addonName}.js`, diff --git a/addons/xterm-addon-fit/.gitignore b/addons/addon-fit/.gitignore similarity index 100% rename from addons/xterm-addon-fit/.gitignore rename to addons/addon-fit/.gitignore diff --git a/addons/xterm-addon-fit/.npmignore b/addons/addon-fit/.npmignore similarity index 100% rename from addons/xterm-addon-fit/.npmignore rename to addons/addon-fit/.npmignore diff --git a/addons/xterm-addon-fit/LICENSE b/addons/addon-fit/LICENSE similarity index 100% rename from addons/xterm-addon-fit/LICENSE rename to addons/addon-fit/LICENSE diff --git a/addons/xterm-addon-fit/README.md b/addons/addon-fit/README.md similarity index 66% rename from addons/xterm-addon-fit/README.md rename to addons/addon-fit/README.md index 321b2cf709..076e512716 100644 --- a/addons/xterm-addon-fit/README.md +++ b/addons/addon-fit/README.md @@ -1,18 +1,18 @@ -## xterm-addon-fit +## @xterm/addon-fit An addon for [xterm.js](https://github.com/xtermjs/xterm.js) that enables fitting the terminal's dimensions to a containing element. This addon requires xterm.js v4+. ### Install ```bash -npm install --save xterm-addon-fit +npm install --save @xterm/addon-fit ``` ### Usage ```ts -import { Terminal } from 'xterm'; -import { FitAddon } from 'xterm-addon-fit'; +import { Terminal } from '@xterm/xterm'; +import { FitAddon } from '@xterm/addon-fit'; const terminal = new Terminal(); const fitAddon = new FitAddon(); @@ -21,4 +21,4 @@ terminal.open(containerElement); fitAddon.fit(); ``` -See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/xterm-addon-fit/typings/xterm-addon-fit.d.ts) for more advanced usage. +See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/addon-fit/typings/addon-fit.d.ts) for more advanced usage. diff --git a/addons/xterm-addon-fit/package.json b/addons/addon-fit/package.json similarity index 75% rename from addons/xterm-addon-fit/package.json rename to addons/addon-fit/package.json index b2652aaeaf..585f3621c5 100644 --- a/addons/xterm-addon-fit/package.json +++ b/addons/addon-fit/package.json @@ -1,13 +1,13 @@ { - "name": "xterm-addon-fit", + "name": "@xterm/addon-fit", "version": "0.8.0", "author": { "name": "The xterm.js authors", "url": "https://xtermjs.org/" }, - "main": "lib/xterm-addon-fit.js", - "types": "typings/xterm-addon-fit.d.ts", - "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-fit", + "main": "lib/addon-fit.js", + "types": "typings/addon-fit.d.ts", + "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/addon-fit", "license": "MIT", "keywords": [ "terminal", @@ -21,6 +21,6 @@ "prepublishOnly": "npm run package" }, "peerDependencies": { - "xterm": "^5.0.0" + "@xterm/xterm": "^5.0.0" } } diff --git a/addons/xterm-addon-fit/src/FitAddon.ts b/addons/addon-fit/src/FitAddon.ts similarity index 93% rename from addons/xterm-addon-fit/src/FitAddon.ts rename to addons/addon-fit/src/FitAddon.ts index f724546218..2087e6146a 100644 --- a/addons/xterm-addon-fit/src/FitAddon.ts +++ b/addons/addon-fit/src/FitAddon.ts @@ -3,7 +3,8 @@ * @license MIT */ -import { Terminal, ITerminalAddon } from 'xterm'; +import type { Terminal, ITerminalAddon } from '@xterm/xterm'; +import type { FitAddon as IFitApi } from '@xterm/addon-fit'; import { IRenderDimensions } from 'browser/renderer/shared/Types'; interface ITerminalDimensions { @@ -21,7 +22,7 @@ interface ITerminalDimensions { const MINIMUM_COLS = 2; const MINIMUM_ROWS = 1; -export class FitAddon implements ITerminalAddon { +export class FitAddon implements ITerminalAddon , IFitApi { private _terminal: Terminal | undefined; public activate(terminal: Terminal): void { diff --git a/addons/xterm-addon-fit/src/tsconfig.json b/addons/addon-fit/src/tsconfig.json similarity index 87% rename from addons/xterm-addon-fit/src/tsconfig.json rename to addons/addon-fit/src/tsconfig.json index 668f910be7..068b43370b 100644 --- a/addons/xterm-addon-fit/src/tsconfig.json +++ b/addons/addon-fit/src/tsconfig.json @@ -17,6 +17,9 @@ "paths": { "browser/*": [ "../../../src/browser/*" + ], + "@xterm/addon-fit": [ + "../typings/addon-fit.d.ts" ] } }, diff --git a/addons/xterm-addon-fit/test/FitAddon.api.ts b/addons/addon-fit/test/FitAddon.api.ts similarity index 100% rename from addons/xterm-addon-fit/test/FitAddon.api.ts rename to addons/addon-fit/test/FitAddon.api.ts diff --git a/addons/xterm-addon-fit/test/tsconfig.json b/addons/addon-fit/test/tsconfig.json similarity index 100% rename from addons/xterm-addon-fit/test/tsconfig.json rename to addons/addon-fit/test/tsconfig.json diff --git a/addons/xterm-addon-fit/tsconfig.json b/addons/addon-fit/tsconfig.json similarity index 100% rename from addons/xterm-addon-fit/tsconfig.json rename to addons/addon-fit/tsconfig.json diff --git a/addons/xterm-addon-fit/typings/xterm-addon-fit.d.ts b/addons/addon-fit/typings/addon-fit.d.ts similarity index 92% rename from addons/xterm-addon-fit/typings/xterm-addon-fit.d.ts rename to addons/addon-fit/typings/addon-fit.d.ts index 2d1b8f1df6..e3d20e29f5 100644 --- a/addons/xterm-addon-fit/typings/xterm-addon-fit.d.ts +++ b/addons/addon-fit/typings/addon-fit.d.ts @@ -3,9 +3,9 @@ * @license MIT */ -import { Terminal, ITerminalAddon } from 'xterm'; +import { Terminal, ITerminalAddon } from '@xterm/xterm'; -declare module 'xterm-addon-fit' { +declare module '@xterm/addon-fit' { /** * An xterm.js addon that enables resizing the terminal to the dimensions of * its containing element. diff --git a/addons/xterm-addon-fit/webpack.config.js b/addons/addon-fit/webpack.config.js similarity index 93% rename from addons/xterm-addon-fit/webpack.config.js rename to addons/addon-fit/webpack.config.js index 4b5421504d..e220668c74 100644 --- a/addons/xterm-addon-fit/webpack.config.js +++ b/addons/addon-fit/webpack.config.js @@ -6,7 +6,7 @@ const path = require('path'); const addonName = 'FitAddon'; -const mainFile = 'xterm-addon-fit.js'; +const mainFile = 'addon-fit.js'; module.exports = { entry: `./out/${addonName}.js`, diff --git a/addons/xterm-addon-image/.gitignore b/addons/addon-image/.gitignore similarity index 100% rename from addons/xterm-addon-image/.gitignore rename to addons/addon-image/.gitignore diff --git a/addons/xterm-addon-image/.npmignore b/addons/addon-image/.npmignore similarity index 100% rename from addons/xterm-addon-image/.npmignore rename to addons/addon-image/.npmignore diff --git a/addons/xterm-addon-image/LICENSE b/addons/addon-image/LICENSE similarity index 100% rename from addons/xterm-addon-image/LICENSE rename to addons/addon-image/LICENSE diff --git a/addons/xterm-addon-image/README.md b/addons/addon-image/README.md similarity index 98% rename from addons/xterm-addon-image/README.md rename to addons/addon-image/README.md index 686df9b48e..9fd327e380 100644 --- a/addons/xterm-addon-image/README.md +++ b/addons/addon-image/README.md @@ -1,4 +1,4 @@ -## xterm-addon-image +## @xterm/addon-image Inline image output in xterm.js. Supports SIXEL and iTerm's inline image protocol (IIP). @@ -9,15 +9,15 @@ Inline image output in xterm.js. Supports SIXEL and iTerm's inline image protoco ### Install from npm ```bash -npm install --save xterm-addon-image +npm install --save @xterm/addon-image ``` ### Usage ```ts -import { Terminal } from 'xterm'; -import { ImageAddon, IImageAddonOptions } from 'xterm-addon-image'; +import { Terminal } from '@xterm/xterm'; +import { ImageAddon, IImageAddonOptions } from '@xterm/addon-image'; // customize as needed (showing addon defaults) const customSettings: IImageAddonOptions = { @@ -227,5 +227,5 @@ _How can I adjust the memory usage?_ - 0.1.2 bugfix: reset clear flag - 0.1.1 bugfixes: - clear sticky image tiles on render - - create xterm-addon-image folder from bootstrap.sh + - create folder from bootstrap.sh - fix peer dependency in package.json diff --git a/addons/xterm-addon-image/fixture/endless.sh b/addons/addon-image/fixture/endless.sh old mode 100755 new mode 100644 similarity index 100% rename from addons/xterm-addon-image/fixture/endless.sh rename to addons/addon-image/fixture/endless.sh diff --git a/addons/xterm-addon-image/fixture/example.png b/addons/addon-image/fixture/example.png similarity index 100% rename from addons/xterm-addon-image/fixture/example.png rename to addons/addon-image/fixture/example.png diff --git a/addons/xterm-addon-image/fixture/gcrglf.sh b/addons/addon-image/fixture/gcrglf.sh old mode 100755 new mode 100644 similarity index 100% rename from addons/xterm-addon-image/fixture/gcrglf.sh rename to addons/addon-image/fixture/gcrglf.sh diff --git a/addons/xterm-addon-image/fixture/growing_rect.js b/addons/addon-image/fixture/growing_rect.js similarity index 100% rename from addons/xterm-addon-image/fixture/growing_rect.js rename to addons/addon-image/fixture/growing_rect.js diff --git a/addons/xterm-addon-image/fixture/iip/palette.iip b/addons/addon-image/fixture/iip/palette.iip similarity index 100% rename from addons/xterm-addon-image/fixture/iip/palette.iip rename to addons/addon-image/fixture/iip/palette.iip diff --git a/addons/xterm-addon-image/fixture/iip/spinfox.iip b/addons/addon-image/fixture/iip/spinfox.iip similarity index 100% rename from addons/xterm-addon-image/fixture/iip/spinfox.iip rename to addons/addon-image/fixture/iip/spinfox.iip diff --git a/addons/xterm-addon-image/fixture/iip/w3c_gif.iip b/addons/addon-image/fixture/iip/w3c_gif.iip similarity index 100% rename from addons/xterm-addon-image/fixture/iip/w3c_gif.iip rename to addons/addon-image/fixture/iip/w3c_gif.iip diff --git a/addons/xterm-addon-image/fixture/iip/w3c_jpg.iip b/addons/addon-image/fixture/iip/w3c_jpg.iip similarity index 100% rename from addons/xterm-addon-image/fixture/iip/w3c_jpg.iip rename to addons/addon-image/fixture/iip/w3c_jpg.iip diff --git a/addons/xterm-addon-image/fixture/iip/w3c_png.iip b/addons/addon-image/fixture/iip/w3c_png.iip similarity index 100% rename from addons/xterm-addon-image/fixture/iip/w3c_png.iip rename to addons/addon-image/fixture/iip/w3c_png.iip diff --git a/addons/xterm-addon-image/fixture/inspect_palette.sh b/addons/addon-image/fixture/inspect_palette.sh old mode 100755 new mode 100644 similarity index 100% rename from addons/xterm-addon-image/fixture/inspect_palette.sh rename to addons/addon-image/fixture/inspect_palette.sh diff --git a/addons/xterm-addon-image/fixture/overdraw.sh b/addons/addon-image/fixture/overdraw.sh old mode 100755 new mode 100644 similarity index 100% rename from addons/xterm-addon-image/fixture/overdraw.sh rename to addons/addon-image/fixture/overdraw.sh diff --git a/addons/xterm-addon-image/fixture/palette.blob b/addons/addon-image/fixture/palette.blob similarity index 100% rename from addons/xterm-addon-image/fixture/palette.blob rename to addons/addon-image/fixture/palette.blob diff --git a/addons/xterm-addon-image/fixture/palette.png b/addons/addon-image/fixture/palette.png similarity index 100% rename from addons/xterm-addon-image/fixture/palette.png rename to addons/addon-image/fixture/palette.png diff --git a/addons/xterm-addon-image/fixture/palette.sixel b/addons/addon-image/fixture/palette.sixel similarity index 100% rename from addons/xterm-addon-image/fixture/palette.sixel rename to addons/addon-image/fixture/palette.sixel diff --git a/addons/xterm-addon-image/fixture/testimages/agfa-makernotes.jpg b/addons/addon-image/fixture/testimages/agfa-makernotes.jpg similarity index 100% rename from addons/xterm-addon-image/fixture/testimages/agfa-makernotes.jpg rename to addons/addon-image/fixture/testimages/agfa-makernotes.jpg diff --git a/addons/xterm-addon-image/fixture/testimages/iphone_hdr_YES.jpg b/addons/addon-image/fixture/testimages/iphone_hdr_YES.jpg similarity index 100% rename from addons/xterm-addon-image/fixture/testimages/iphone_hdr_YES.jpg rename to addons/addon-image/fixture/testimages/iphone_hdr_YES.jpg diff --git a/addons/xterm-addon-image/fixture/testimages/nikon-e950.jpg b/addons/addon-image/fixture/testimages/nikon-e950.jpg similarity index 100% rename from addons/xterm-addon-image/fixture/testimages/nikon-e950.jpg rename to addons/addon-image/fixture/testimages/nikon-e950.jpg diff --git a/addons/xterm-addon-image/fixture/testimages/sony-alpha-6000.jpg b/addons/addon-image/fixture/testimages/sony-alpha-6000.jpg similarity index 100% rename from addons/xterm-addon-image/fixture/testimages/sony-alpha-6000.jpg rename to addons/addon-image/fixture/testimages/sony-alpha-6000.jpg diff --git a/addons/xterm-addon-image/fixture/testimages/spinfox.png b/addons/addon-image/fixture/testimages/spinfox.png similarity index 100% rename from addons/xterm-addon-image/fixture/testimages/spinfox.png rename to addons/addon-image/fixture/testimages/spinfox.png diff --git a/addons/xterm-addon-image/fixture/testimages/w3c_home.gif b/addons/addon-image/fixture/testimages/w3c_home.gif similarity index 100% rename from addons/xterm-addon-image/fixture/testimages/w3c_home.gif rename to addons/addon-image/fixture/testimages/w3c_home.gif diff --git a/addons/xterm-addon-image/fixture/testimages/w3c_home.jpg b/addons/addon-image/fixture/testimages/w3c_home.jpg similarity index 100% rename from addons/xterm-addon-image/fixture/testimages/w3c_home.jpg rename to addons/addon-image/fixture/testimages/w3c_home.jpg diff --git a/addons/xterm-addon-image/fixture/testimages/w3c_home.png b/addons/addon-image/fixture/testimages/w3c_home.png similarity index 100% rename from addons/xterm-addon-image/fixture/testimages/w3c_home.png rename to addons/addon-image/fixture/testimages/w3c_home.png diff --git a/addons/xterm-addon-image/fixture/testimages/w3c_home_2.gif b/addons/addon-image/fixture/testimages/w3c_home_2.gif similarity index 100% rename from addons/xterm-addon-image/fixture/testimages/w3c_home_2.gif rename to addons/addon-image/fixture/testimages/w3c_home_2.gif diff --git a/addons/xterm-addon-image/fixture/testimages/w3c_home_2.jpg b/addons/addon-image/fixture/testimages/w3c_home_2.jpg similarity index 100% rename from addons/xterm-addon-image/fixture/testimages/w3c_home_2.jpg rename to addons/addon-image/fixture/testimages/w3c_home_2.jpg diff --git a/addons/xterm-addon-image/fixture/testimages/w3c_home_2.png b/addons/addon-image/fixture/testimages/w3c_home_2.png similarity index 100% rename from addons/xterm-addon-image/fixture/testimages/w3c_home_2.png rename to addons/addon-image/fixture/testimages/w3c_home_2.png diff --git a/addons/xterm-addon-image/fixture/testimages/w3c_home_256.gif b/addons/addon-image/fixture/testimages/w3c_home_256.gif similarity index 100% rename from addons/xterm-addon-image/fixture/testimages/w3c_home_256.gif rename to addons/addon-image/fixture/testimages/w3c_home_256.gif diff --git a/addons/xterm-addon-image/fixture/testimages/w3c_home_256.jpg b/addons/addon-image/fixture/testimages/w3c_home_256.jpg similarity index 100% rename from addons/xterm-addon-image/fixture/testimages/w3c_home_256.jpg rename to addons/addon-image/fixture/testimages/w3c_home_256.jpg diff --git a/addons/xterm-addon-image/fixture/testimages/w3c_home_256.png b/addons/addon-image/fixture/testimages/w3c_home_256.png similarity index 100% rename from addons/xterm-addon-image/fixture/testimages/w3c_home_256.png rename to addons/addon-image/fixture/testimages/w3c_home_256.png diff --git a/addons/xterm-addon-image/fixture/testimages/w3c_home_animation.gif b/addons/addon-image/fixture/testimages/w3c_home_animation.gif similarity index 100% rename from addons/xterm-addon-image/fixture/testimages/w3c_home_animation.gif rename to addons/addon-image/fixture/testimages/w3c_home_animation.gif diff --git a/addons/xterm-addon-image/fixture/testimages/w3c_home_gray.gif b/addons/addon-image/fixture/testimages/w3c_home_gray.gif similarity index 100% rename from addons/xterm-addon-image/fixture/testimages/w3c_home_gray.gif rename to addons/addon-image/fixture/testimages/w3c_home_gray.gif diff --git a/addons/xterm-addon-image/fixture/testimages/w3c_home_gray.jpg b/addons/addon-image/fixture/testimages/w3c_home_gray.jpg similarity index 100% rename from addons/xterm-addon-image/fixture/testimages/w3c_home_gray.jpg rename to addons/addon-image/fixture/testimages/w3c_home_gray.jpg diff --git a/addons/xterm-addon-image/fixture/testimages/w3c_home_gray.png b/addons/addon-image/fixture/testimages/w3c_home_gray.png similarity index 100% rename from addons/xterm-addon-image/fixture/testimages/w3c_home_gray.png rename to addons/addon-image/fixture/testimages/w3c_home_gray.png diff --git a/addons/xterm-addon-image/fixture/textcursor.sh b/addons/addon-image/fixture/textcursor.sh old mode 100755 new mode 100644 similarity index 100% rename from addons/xterm-addon-image/fixture/textcursor.sh rename to addons/addon-image/fixture/textcursor.sh diff --git a/addons/xterm-addon-image/package.json b/addons/addon-image/package.json similarity index 77% rename from addons/xterm-addon-image/package.json rename to addons/addon-image/package.json index b07b5b6bdc..8572e3300f 100644 --- a/addons/xterm-addon-image/package.json +++ b/addons/addon-image/package.json @@ -1,13 +1,13 @@ { - "name": "xterm-addon-image", + "name": "@xterm/addon-image", "version": "0.6.0", "author": { "name": "The xterm.js authors", "url": "https://xtermjs.org/" }, - "main": "lib/xterm-addon-image.js", - "types": "typings/xterm-addon-image.d.ts", - "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-image", + "main": "lib/addon-image.js", + "types": "typings/addon-image.d.ts", + "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/addon-image", "license": "MIT", "keywords": [ "terminal", @@ -22,7 +22,7 @@ "prepublishOnly": "npm run package" }, "peerDependencies": { - "xterm": "^5.2.0" + "@xterm/xterm": "^5.2.0" }, "devDependencies": { "sixel": "^0.16.0", diff --git a/addons/xterm-addon-image/src/IIPHandler.ts b/addons/addon-image/src/IIPHandler.ts similarity index 100% rename from addons/xterm-addon-image/src/IIPHandler.ts rename to addons/addon-image/src/IIPHandler.ts diff --git a/addons/xterm-addon-image/src/IIPHeaderParser.test.ts b/addons/addon-image/src/IIPHeaderParser.test.ts similarity index 100% rename from addons/xterm-addon-image/src/IIPHeaderParser.test.ts rename to addons/addon-image/src/IIPHeaderParser.test.ts diff --git a/addons/xterm-addon-image/src/IIPHeaderParser.ts b/addons/addon-image/src/IIPHeaderParser.ts similarity index 100% rename from addons/xterm-addon-image/src/IIPHeaderParser.ts rename to addons/addon-image/src/IIPHeaderParser.ts diff --git a/addons/xterm-addon-image/src/IIPMetrics.test.ts b/addons/addon-image/src/IIPMetrics.test.ts similarity index 94% rename from addons/xterm-addon-image/src/IIPMetrics.test.ts rename to addons/addon-image/src/IIPMetrics.test.ts index 688d8d3921..8ad5f05c85 100644 --- a/addons/xterm-addon-image/src/IIPMetrics.test.ts +++ b/addons/addon-image/src/IIPMetrics.test.ts @@ -36,7 +36,7 @@ const TEST_IMAGES: [string, IMetrics][] = [ describe('IIPMetrics', () => { it('bunch of testimages', () => { for (let i = 0; i < TEST_IMAGES.length; ++i) { - const imageData = fs.readFileSync('./addons/xterm-addon-image/fixture/testimages/' + TEST_IMAGES[i][0]); + const imageData = fs.readFileSync('./addons/addon-image/fixture/testimages/' + TEST_IMAGES[i][0]); assert.deepStrictEqual(imageType(imageData), TEST_IMAGES[i][1]); } }); diff --git a/addons/xterm-addon-image/src/IIPMetrics.ts b/addons/addon-image/src/IIPMetrics.ts similarity index 100% rename from addons/xterm-addon-image/src/IIPMetrics.ts rename to addons/addon-image/src/IIPMetrics.ts diff --git a/addons/xterm-addon-image/src/ImageAddon.ts b/addons/addon-image/src/ImageAddon.ts similarity index 98% rename from addons/xterm-addon-image/src/ImageAddon.ts rename to addons/addon-image/src/ImageAddon.ts index bb633e6b25..167e93a791 100644 --- a/addons/xterm-addon-image/src/ImageAddon.ts +++ b/addons/addon-image/src/ImageAddon.ts @@ -3,14 +3,14 @@ * @license MIT */ +import type { ITerminalAddon, IDisposable } from '@xterm/xterm'; +import type { ImageAddon as IImageApi } from '@xterm/addon-image'; import { IIPHandler } from './IIPHandler'; -import { ITerminalAddon, IDisposable } from 'xterm'; import { ImageRenderer } from './ImageRenderer'; import { ImageStorage, CELL_SIZE_DEFAULT } from './ImageStorage'; import { SixelHandler } from './SixelHandler'; import { ITerminalExt, IImageAddonOptions, IResetHandler } from './Types'; - // default values of addon ctor options const DEFAULT_OPTIONS: IImageAddonOptions = { enableSizeReports: true, @@ -48,7 +48,7 @@ const enum GaStatus { } -export class ImageAddon implements ITerminalAddon { +export class ImageAddon implements ITerminalAddon , IImageApi { private _opts: IImageAddonOptions; private _defaultOpts: IImageAddonOptions; private _storage: ImageStorage | undefined; diff --git a/addons/xterm-addon-image/src/ImageRenderer.ts b/addons/addon-image/src/ImageRenderer.ts similarity index 99% rename from addons/xterm-addon-image/src/ImageRenderer.ts rename to addons/addon-image/src/ImageRenderer.ts index 9b528efed1..214a2e6bd0 100644 --- a/addons/xterm-addon-image/src/ImageRenderer.ts +++ b/addons/addon-image/src/ImageRenderer.ts @@ -4,7 +4,7 @@ */ import { toRGBA8888 } from 'sixel/lib/Colors'; -import { IDisposable } from 'xterm'; +import { IDisposable } from '@xterm/xterm'; import { ICellSize, ITerminalExt, IImageSpec, IRenderDimensions, IRenderService } from './Types'; import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle'; diff --git a/addons/xterm-addon-image/src/ImageStorage.ts b/addons/addon-image/src/ImageStorage.ts similarity index 97% rename from addons/xterm-addon-image/src/ImageStorage.ts rename to addons/addon-image/src/ImageStorage.ts index 97eef8521a..f9b6eef68f 100644 --- a/addons/xterm-addon-image/src/ImageStorage.ts +++ b/addons/addon-image/src/ImageStorage.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { IDisposable } from 'xterm'; +import { IDisposable } from '@xterm/xterm'; import { ImageRenderer } from './ImageRenderer'; import { ITerminalExt, IExtendedAttrsImage, IImageAddonOptions, IImageSpec, IBufferLineExt, BgFlags, Cell, Content, ICellSize, ExtFlags, Attributes, UnderlineStyle } from './Types'; @@ -53,6 +53,18 @@ class ExtendedAttrsImage implements IExtendedAttrsImage { this._ext |= value & (Attributes.CM_MASK | Attributes.RGB_MASK); } + public get underlineVariantOffset(): number { + const val = (this._ext & ExtFlags.VARIANT_OFFSET) >> 29; + if (val < 0) { + return val ^ 0xFFFFFFF8; + } + return val; + } + public set underlineVariantOffset(value: number) { + this._ext &= ~ExtFlags.VARIANT_OFFSET; + this._ext |= (value << 29) & ExtFlags.VARIANT_OFFSET; + } + private _urlId: number = 0; public get urlId(): number { return this._urlId; diff --git a/addons/xterm-addon-image/src/SixelHandler.ts b/addons/addon-image/src/SixelHandler.ts similarity index 100% rename from addons/xterm-addon-image/src/SixelHandler.ts rename to addons/addon-image/src/SixelHandler.ts diff --git a/addons/xterm-addon-image/src/Types.d.ts b/addons/addon-image/src/Types.d.ts similarity index 98% rename from addons/xterm-addon-image/src/Types.d.ts rename to addons/addon-image/src/Types.d.ts index 62f4481ae6..60de0f3d2e 100644 --- a/addons/xterm-addon-image/src/Types.d.ts +++ b/addons/addon-image/src/Types.d.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { IDisposable, IMarker, Terminal } from 'xterm'; +import { IDisposable, IMarker, Terminal } from '@xterm/xterm'; // private imports from base repo we build against import { Attributes, BgFlags, Content, ExtFlags, UnderlineStyle } from 'common/buffer/Constants'; diff --git a/addons/xterm-addon-image/src/tsconfig.json b/addons/addon-image/src/tsconfig.json similarity index 83% rename from addons/xterm-addon-image/src/tsconfig.json rename to addons/addon-image/src/tsconfig.json index da519e17d9..a18b47c9ce 100644 --- a/addons/xterm-addon-image/src/tsconfig.json +++ b/addons/addon-image/src/tsconfig.json @@ -14,7 +14,8 @@ "baseUrl": ".", "paths": { "browser/*": [ "../../../src/browser/*" ], - "common/*": [ "../../../src/common/*" ] + "common/*": [ "../../../src/common/*" ], + "@xterm/addon-image": [ "../typings/addon-image.d.ts" ] } }, "include": [ diff --git a/addons/xterm-addon-image/test/ImageAddon.api.ts b/addons/addon-image/test/ImageAddon.api.ts similarity index 95% rename from addons/xterm-addon-image/test/ImageAddon.api.ts rename to addons/addon-image/test/ImageAddon.api.ts index 43334bbb09..776e96bfd0 100644 --- a/addons/xterm-addon-image/test/ImageAddon.api.ts +++ b/addons/addon-image/test/ImageAddon.api.ts @@ -39,7 +39,7 @@ interface IDimensions { // image: 640 x 80, 512 color const TESTDATA: ITestData = (() => { - const data8 = readFileSync('./addons/xterm-addon-image/fixture/palette.blob'); + const data8 = readFileSync('./addons/addon-image/fixture/palette.blob'); const data32 = new Uint32Array(data8.buffer); const palette = new Set(); for (let i = 0; i < data32.length; ++i) palette.add(data32[i]); @@ -58,11 +58,11 @@ const SIXEL_SEQ_0 = introducer(0) + TESTDATA.sixel + FINALIZER; // NOTE: the data is loaded as string for easier transport through playwright const TESTDATA_IIP: [string, [number, number]][] = [ - [readFileSync('./addons/xterm-addon-image/fixture/iip/palette.iip', { encoding: 'utf-8' }), [640, 80]], - [readFileSync('./addons/xterm-addon-image/fixture/iip/spinfox.iip', { encoding: 'utf-8' }), [148, 148]], - [readFileSync('./addons/xterm-addon-image/fixture/iip/w3c_gif.iip', { encoding: 'utf-8' }), [72, 48]], - [readFileSync('./addons/xterm-addon-image/fixture/iip/w3c_jpg.iip', { encoding: 'utf-8' }), [72, 48]], - [readFileSync('./addons/xterm-addon-image/fixture/iip/w3c_png.iip', { encoding: 'utf-8' }), [72, 48]] + [readFileSync('./addons/addon-image/fixture/iip/palette.iip', { encoding: 'utf-8' }), [640, 80]], + [readFileSync('./addons/addon-image/fixture/iip/spinfox.iip', { encoding: 'utf-8' }), [148, 148]], + [readFileSync('./addons/addon-image/fixture/iip/w3c_gif.iip', { encoding: 'utf-8' }), [72, 48]], + [readFileSync('./addons/addon-image/fixture/iip/w3c_jpg.iip', { encoding: 'utf-8' }), [72, 48]], + [readFileSync('./addons/addon-image/fixture/iip/w3c_png.iip', { encoding: 'utf-8' }), [72, 48]] ]; describe('ImageAddon', () => { diff --git a/addons/xterm-addon-image/test/tsconfig.json b/addons/addon-image/test/tsconfig.json similarity index 100% rename from addons/xterm-addon-image/test/tsconfig.json rename to addons/addon-image/test/tsconfig.json diff --git a/addons/xterm-addon-image/tsconfig.json b/addons/addon-image/tsconfig.json similarity index 100% rename from addons/xterm-addon-image/tsconfig.json rename to addons/addon-image/tsconfig.json diff --git a/addons/xterm-addon-image/typings/xterm-addon-image.d.ts b/addons/addon-image/typings/addon-image.d.ts similarity index 97% rename from addons/xterm-addon-image/typings/xterm-addon-image.d.ts rename to addons/addon-image/typings/addon-image.d.ts index 94dc6f6587..48ba488cfa 100644 --- a/addons/xterm-addon-image/typings/xterm-addon-image.d.ts +++ b/addons/addon-image/typings/addon-image.d.ts @@ -3,9 +3,9 @@ * @license MIT */ -import { Terminal, ITerminalAddon } from 'xterm'; +import { Terminal, ITerminalAddon } from '@xterm/xterm'; -declare module 'xterm-addon-image' { +declare module '@xterm/addon-image' { export interface IImageAddonOptions { /** * Enable size reports in windowOptions: @@ -37,7 +37,7 @@ declare module 'xterm-addon-image' { * * Note: `storageLimit` bytes are calculated from images by multiplying the pixels with 4 * (4 channels with one byte, images are stored as RGBA8888). - * + * * Default is 2^16 (4096 x 4096 pixels). */ pixelLimit?: number; diff --git a/addons/xterm-addon-image/webpack.config.js b/addons/addon-image/webpack.config.js similarity index 71% rename from addons/xterm-addon-image/webpack.config.js rename to addons/addon-image/webpack.config.js index fff66bec50..b4283b66e3 100644 --- a/addons/xterm-addon-image/webpack.config.js +++ b/addons/addon-image/webpack.config.js @@ -6,7 +6,7 @@ const path = require('path'); const addonName = 'ImageAddon'; -const mainFile = 'xterm-addon-image.js'; +const mainFile = 'addon-image.js'; const addon = { entry: `./out/${addonName}.js`, @@ -21,6 +21,14 @@ const addon = { } ] }, + resolve: { + modules: ['./node_modules'], + extensions: [ '.js' ], + alias: { + common: path.resolve('../../out/common'), + browser: path.resolve('../../out/browser') + } + }, output: { filename: mainFile, path: path.resolve('./lib'), diff --git a/addons/xterm-addon-ligatures/.gitignore b/addons/addon-ligatures/.gitignore similarity index 100% rename from addons/xterm-addon-ligatures/.gitignore rename to addons/addon-ligatures/.gitignore diff --git a/addons/xterm-addon-ligatures/.npmignore b/addons/addon-ligatures/.npmignore similarity index 100% rename from addons/xterm-addon-ligatures/.npmignore rename to addons/addon-ligatures/.npmignore diff --git a/addons/xterm-addon-ligatures/LICENSE b/addons/addon-ligatures/LICENSE similarity index 100% rename from addons/xterm-addon-ligatures/LICENSE rename to addons/addon-ligatures/LICENSE diff --git a/addons/xterm-addon-ligatures/README.md b/addons/addon-ligatures/README.md similarity index 93% rename from addons/xterm-addon-ligatures/README.md rename to addons/addon-ligatures/README.md index fad2a7efab..3b5521e0d9 100644 --- a/addons/xterm-addon-ligatures/README.md +++ b/addons/addon-ligatures/README.md @@ -1,4 +1,4 @@ -## xterm-addon-ligatures +## @xterm/addon-ligatures Add support for programming ligatures to [xterm.js] when running in environments with access to [Node.js] APIs (such as [Electron]). @@ -10,14 +10,14 @@ Add support for programming ligatures to [xterm.js] when running in environments ### Install ```bash -npm install --save xterm-addon-ligatures +npm install --save @xterm/addon-ligatures ``` ### Usage ```ts -import { Terminal } from 'xterm'; -import { LigaturesAddon } from 'xterm-addon-ligatures'; +import { Terminal } from '@xterm/xterm'; +import { LigaturesAddon } from '@xterm/addon-ligatures'; const terminal = new Terminal(); const ligaturesAddon = new LigaturesAddon(); diff --git a/addons/xterm-addon-ligatures/bin/download-fonts.js b/addons/addon-ligatures/bin/download-fonts.js similarity index 100% rename from addons/xterm-addon-ligatures/bin/download-fonts.js rename to addons/addon-ligatures/bin/download-fonts.js diff --git a/addons/xterm-addon-ligatures/package.json b/addons/addon-ligatures/package.json similarity index 84% rename from addons/xterm-addon-ligatures/package.json rename to addons/addon-ligatures/package.json index 57c0cd5653..3025188828 100644 --- a/addons/xterm-addon-ligatures/package.json +++ b/addons/addon-ligatures/package.json @@ -1,14 +1,14 @@ { - "name": "xterm-addon-ligatures", + "name": "@xterm/addon-ligatures", "version": "0.7.0", "description": "Add support for programming ligatures to xterm.js", "author": { "name": "The xterm.js authors", "url": "https://xtermjs.org/" }, - "main": "lib/xterm-addon-ligatures.js", - "types": "typings/xterm-addon-ligatures.d.ts", - "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-ligatures", + "main": "lib/addon-ligatures.js", + "types": "typings/addon-ligatures.d.ts", + "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/addon-ligatures", "engines": { "node": ">8.0.0" }, @@ -42,6 +42,6 @@ "yauzl": "^2.10.0" }, "peerDependencies": { - "xterm": "^5.0.0" + "@xterm/xterm": "^5.0.0" } } diff --git a/addons/xterm-addon-ligatures/src/LigaturesAddon.ts b/addons/addon-ligatures/src/LigaturesAddon.ts similarity index 87% rename from addons/xterm-addon-ligatures/src/LigaturesAddon.ts rename to addons/addon-ligatures/src/LigaturesAddon.ts index c4586b3890..cb58930359 100644 --- a/addons/xterm-addon-ligatures/src/LigaturesAddon.ts +++ b/addons/addon-ligatures/src/LigaturesAddon.ts @@ -3,7 +3,8 @@ * @license MIT */ -import { Terminal } from 'xterm'; +import type { Terminal } from '@xterm/xterm'; +import type { LigaturesAddon as ILigaturesApi } from '@xterm/addon-ligatures'; import { enableLigatures } from '.'; import { ILigatureOptions } from './Types'; @@ -12,7 +13,7 @@ export interface ITerminalAddon { dispose(): void; } -export class LigaturesAddon implements ITerminalAddon { +export class LigaturesAddon implements ITerminalAddon , ILigaturesApi { private readonly _fallbackLigatures: string[]; private _terminal: Terminal | undefined; diff --git a/addons/xterm-addon-ligatures/src/Types.d.ts b/addons/addon-ligatures/src/Types.d.ts similarity index 100% rename from addons/xterm-addon-ligatures/src/Types.d.ts rename to addons/addon-ligatures/src/Types.d.ts diff --git a/addons/xterm-addon-ligatures/src/font.ts b/addons/addon-ligatures/src/font.ts similarity index 100% rename from addons/xterm-addon-ligatures/src/font.ts rename to addons/addon-ligatures/src/font.ts diff --git a/addons/xterm-addon-ligatures/src/index.test.ts b/addons/addon-ligatures/src/index.test.ts similarity index 99% rename from addons/xterm-addon-ligatures/src/index.test.ts rename to addons/addon-ligatures/src/index.test.ts index c7bf09cefd..c6aead98a4 100644 --- a/addons/xterm-addon-ligatures/src/index.test.ts +++ b/addons/addon-ligatures/src/index.test.ts @@ -11,7 +11,7 @@ import * as fontLigatures from 'font-ligatures'; import * as ligatureSupport from '.'; -describe('xterm-addon-ligatures', () => { +describe('LigaturesAddon', () => { let onRefresh: sinon.SinonStub; let term: MockTerminal; diff --git a/addons/xterm-addon-ligatures/src/index.ts b/addons/addon-ligatures/src/index.ts similarity index 98% rename from addons/xterm-addon-ligatures/src/index.ts rename to addons/addon-ligatures/src/index.ts index 8267562658..bd8ff215f3 100644 --- a/addons/xterm-addon-ligatures/src/index.ts +++ b/addons/addon-ligatures/src/index.ts @@ -3,7 +3,7 @@ * @license MIT */ -import type { Terminal } from 'xterm'; +import type { Terminal } from '@xterm/xterm'; import { Font } from 'font-ligatures'; import load from './font'; diff --git a/addons/xterm-addon-ligatures/src/parse.test.ts b/addons/addon-ligatures/src/parse.test.ts similarity index 100% rename from addons/xterm-addon-ligatures/src/parse.test.ts rename to addons/addon-ligatures/src/parse.test.ts diff --git a/addons/xterm-addon-ligatures/src/parse.ts b/addons/addon-ligatures/src/parse.ts similarity index 100% rename from addons/xterm-addon-ligatures/src/parse.ts rename to addons/addon-ligatures/src/parse.ts diff --git a/addons/xterm-addon-ligatures/src/tsconfig.json b/addons/addon-ligatures/src/tsconfig.json similarity index 75% rename from addons/xterm-addon-ligatures/src/tsconfig.json rename to addons/addon-ligatures/src/tsconfig.json index 28969f977e..cc9a9befa9 100644 --- a/addons/xterm-addon-ligatures/src/tsconfig.json +++ b/addons/addon-ligatures/src/tsconfig.json @@ -10,7 +10,12 @@ "preserveWatchOutput": true, "types": [ "../../../node_modules/@types/mocha" - ] + ], + "paths": { + "@xterm/addon-ligatures" : [ + "../typings/addon-ligatures.d.ts" + ] + } }, "include": [ "./**/*", diff --git a/addons/xterm-addon-ligatures/tsconfig.json b/addons/addon-ligatures/tsconfig.json similarity index 100% rename from addons/xterm-addon-ligatures/tsconfig.json rename to addons/addon-ligatures/tsconfig.json diff --git a/addons/xterm-addon-ligatures/typings/xterm-addon-ligatures.d.ts b/addons/addon-ligatures/typings/addon-ligatures.d.ts similarity index 89% rename from addons/xterm-addon-ligatures/typings/xterm-addon-ligatures.d.ts rename to addons/addon-ligatures/typings/addon-ligatures.d.ts index 4d8fbdf0ef..2fd4f3e741 100644 --- a/addons/xterm-addon-ligatures/typings/xterm-addon-ligatures.d.ts +++ b/addons/addon-ligatures/typings/addon-ligatures.d.ts @@ -2,15 +2,15 @@ * Copyright (c) 2018 The xterm.js authors. All rights reserved. * @license MIT * - * This contains the type declarations for the xterm-addon-ligatures library. + * This contains the type declarations for the @xterm/addon-ligatures library. * Note that some interfaces may differ between this file and the actual * implementation in src/, that's because this file declares the *public* API * which is intended to be stable and consumed by external programs. */ -import { Terminal, ITerminalAddon } from 'xterm'; +import { Terminal, ITerminalAddon } from '@xterm/xterm'; -declare module 'xterm-addon-ligatures' { +declare module '@xterm/addon-ligatures' { /** * An xterm.js addon that enables web links. */ diff --git a/addons/xterm-addon-ligatures/webpack.config.js b/addons/addon-ligatures/webpack.config.js similarity index 95% rename from addons/xterm-addon-ligatures/webpack.config.js rename to addons/addon-ligatures/webpack.config.js index 5aeebe2e96..6ec7f42d02 100644 --- a/addons/xterm-addon-ligatures/webpack.config.js +++ b/addons/addon-ligatures/webpack.config.js @@ -6,7 +6,7 @@ const path = require('path'); const addonName = 'LigaturesAddon'; -const mainFile = 'xterm-addon-ligatures.js'; +const mainFile = 'addon-ligatures.js'; module.exports = { entry: `./out/${addonName}.js`, diff --git a/addons/xterm-addon-ligatures/yarn.lock b/addons/addon-ligatures/yarn.lock similarity index 100% rename from addons/xterm-addon-ligatures/yarn.lock rename to addons/addon-ligatures/yarn.lock diff --git a/addons/xterm-addon-search/.gitignore b/addons/addon-search/.gitignore similarity index 100% rename from addons/xterm-addon-search/.gitignore rename to addons/addon-search/.gitignore diff --git a/addons/xterm-addon-search/.npmignore b/addons/addon-search/.npmignore similarity index 100% rename from addons/xterm-addon-search/.npmignore rename to addons/addon-search/.npmignore diff --git a/addons/xterm-addon-search/LICENSE b/addons/addon-search/LICENSE similarity index 100% rename from addons/xterm-addon-search/LICENSE rename to addons/addon-search/LICENSE diff --git a/addons/xterm-addon-search/README.md b/addons/addon-search/README.md similarity index 62% rename from addons/xterm-addon-search/README.md rename to addons/addon-search/README.md index 91bcc34b67..fab0b03f59 100644 --- a/addons/xterm-addon-search/README.md +++ b/addons/addon-search/README.md @@ -1,18 +1,18 @@ -## xterm-addon-search +## @xterm/addon-search An addon for [xterm.js](https://github.com/xtermjs/xterm.js) that enables searching the buffer. This addon requires xterm.js v4+. ### Install ```bash -npm install --save xterm-addon-search +npm install --save @xterm/addon-search ``` ### Usage ```ts -import { Terminal } from 'xterm'; -import { SearchAddon } from 'xterm-addon-search'; +import { Terminal } from '@xterm/xterm'; +import { SearchAddon } from '@xterm/addon-search'; const terminal = new Terminal(); const searchAddon = new SearchAddon(); @@ -20,4 +20,4 @@ terminal.loadAddon(searchAddon); searchAddon.findNext('foo'); ``` -See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/xterm-addon-search/typings/xterm-addon-search.d.ts) for more advanced usage. +See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/addon-search/typings/addon-search.d.ts) for more advanced usage. diff --git a/addons/xterm-addon-search/fixtures/issue-2444 b/addons/addon-search/fixtures/issue-2444 similarity index 100% rename from addons/xterm-addon-search/fixtures/issue-2444 rename to addons/addon-search/fixtures/issue-2444 diff --git a/addons/xterm-addon-search/package.json b/addons/addon-search/package.json similarity index 61% rename from addons/xterm-addon-search/package.json rename to addons/addon-search/package.json index f846874df3..369d11c34c 100644 --- a/addons/xterm-addon-search/package.json +++ b/addons/addon-search/package.json @@ -1,13 +1,13 @@ { - "name": "xterm-addon-search", + "name": "@xterm/addon-search", "version": "0.13.0", "author": { "name": "The xterm.js authors", "url": "https://xtermjs.org/" }, - "main": "lib/xterm-addon-search.js", - "types": "typings/xterm-addon-search.d.ts", - "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-search", + "main": "lib/addon-search.js", + "types": "typings/addon-search.d.ts", + "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/addon-search", "license": "MIT", "keywords": [ "terminal", @@ -15,12 +15,11 @@ "xterm.js" ], "scripts": { - "build": "../../node_modules/.bin/tsc -p .", - "prepackage": "npm run build", + "prepackage": "../../node_modules/.bin/tsc -p .", "package": "../../node_modules/.bin/webpack", "prepublishOnly": "npm run package" }, "peerDependencies": { - "xterm": "^5.0.0" + "@xterm/xterm": "^5.0.0" } } diff --git a/addons/xterm-addon-search/src/SearchAddon.ts b/addons/addon-search/src/SearchAddon.ts similarity index 96% rename from addons/xterm-addon-search/src/SearchAddon.ts rename to addons/addon-search/src/SearchAddon.ts index 959214c950..3fae737399 100644 --- a/addons/xterm-addon-search/src/SearchAddon.ts +++ b/addons/addon-search/src/SearchAddon.ts @@ -3,7 +3,8 @@ * @license MIT */ -import { Terminal, IDisposable, ITerminalAddon, IDecoration } from 'xterm'; +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'; @@ -61,7 +62,7 @@ const NON_WORD_CHARACTERS = ' ~!@#$%^&*()+`-=[]{}|\\;:"\',./<>?'; const LINES_CACHE_TIME_TO_LIVE = 15 * 1000; // 15 secs const DEFAULT_HIGHLIGHT_LIMIT = 1000; -export class SearchAddon extends Disposable implements ITerminalAddon { +export class SearchAddon extends Disposable implements ITerminalAddon , ISearchApi { private _terminal: Terminal | undefined; private _cachedSearchTerm: string | undefined; private _highlightedLines: Set = new Set(); @@ -134,9 +135,10 @@ export class SearchAddon extends Disposable implements ITerminalAddon { if (!this._terminal) { throw new Error('Cannot use addon until it has been loaded'); } + const didOptionsChanged = this._lastSearchOptions ? this._didOptionsChange(this._lastSearchOptions, searchOptions) : true; this._lastSearchOptions = searchOptions; if (searchOptions?.decorations) { - if (this._cachedSearchTerm === undefined || term !== this._cachedSearchTerm) { + if (this._cachedSearchTerm === undefined || term !== this._cachedSearchTerm || didOptionsChanged) { this._highlightAllMatches(term, searchOptions); } } @@ -302,9 +304,10 @@ export class SearchAddon extends Disposable implements ITerminalAddon { if (!this._terminal) { throw new Error('Cannot use addon until it has been loaded'); } + const didOptionsChanged = this._lastSearchOptions ? this._didOptionsChange(this._lastSearchOptions, searchOptions) : true; this._lastSearchOptions = searchOptions; if (searchOptions?.decorations) { - if (this._cachedSearchTerm === undefined || term !== this._cachedSearchTerm) { + if (this._cachedSearchTerm === undefined || term !== this._cachedSearchTerm || didOptionsChanged) { this._highlightAllMatches(term, searchOptions); } } @@ -316,6 +319,22 @@ export class SearchAddon extends Disposable implements ITerminalAddon { return found; } + private _didOptionsChange(lastSearchOptions: ISearchOptions, searchOptions?: ISearchOptions): boolean { + if (!searchOptions) { + return false; + } + if (lastSearchOptions.caseSensitive !== searchOptions.caseSensitive) { + return true; + } + if (lastSearchOptions.regex !== searchOptions.regex) { + return true; + } + if (lastSearchOptions.wholeWord !== searchOptions.wholeWord) { + return true; + } + return false; + } + private _fireResults(searchOptions?: ISearchOptions): void { if (searchOptions?.decorations) { let resultIndex = -1; diff --git a/addons/xterm-addon-search/src/tsconfig.json b/addons/addon-search/src/tsconfig.json similarity index 86% rename from addons/xterm-addon-search/src/tsconfig.json rename to addons/addon-search/src/tsconfig.json index 1f08b12dcc..bd3e48adfe 100644 --- a/addons/xterm-addon-search/src/tsconfig.json +++ b/addons/addon-search/src/tsconfig.json @@ -17,6 +17,9 @@ "paths": { "common/*": [ "../../../src/common/*" + ], + "@xterm/addon-search" : [ + "../typings/addon-search.d.ts" ] } }, diff --git a/addons/xterm-addon-search/test/SearchAddon.api.ts b/addons/addon-search/test/SearchAddon.api.ts similarity index 100% rename from addons/xterm-addon-search/test/SearchAddon.api.ts rename to addons/addon-search/test/SearchAddon.api.ts diff --git a/addons/xterm-addon-search/test/tsconfig.json b/addons/addon-search/test/tsconfig.json similarity index 100% rename from addons/xterm-addon-search/test/tsconfig.json rename to addons/addon-search/test/tsconfig.json diff --git a/addons/xterm-addon-search/tsconfig.json b/addons/addon-search/tsconfig.json similarity index 100% rename from addons/xterm-addon-search/tsconfig.json rename to addons/addon-search/tsconfig.json diff --git a/addons/xterm-addon-search/typings/xterm-addon-search.d.ts b/addons/addon-search/typings/addon-search.d.ts similarity index 97% rename from addons/xterm-addon-search/typings/xterm-addon-search.d.ts rename to addons/addon-search/typings/addon-search.d.ts index 3a3b7c89b4..282004a2ae 100644 --- a/addons/xterm-addon-search/typings/xterm-addon-search.d.ts +++ b/addons/addon-search/typings/addon-search.d.ts @@ -3,9 +3,9 @@ * @license MIT */ -import { Terminal, ITerminalAddon, IEvent } from 'xterm'; +import { Terminal, ITerminalAddon, IEvent } from '@xterm/xterm'; -declare module 'xterm-addon-search' { +declare module '@xterm/addon-search' { /** * Options for a search. */ diff --git a/addons/xterm-addon-search/webpack.config.js b/addons/addon-search/webpack.config.js similarity index 94% rename from addons/xterm-addon-search/webpack.config.js rename to addons/addon-search/webpack.config.js index 30526812e4..a770f93f50 100644 --- a/addons/xterm-addon-search/webpack.config.js +++ b/addons/addon-search/webpack.config.js @@ -6,7 +6,7 @@ const path = require('path'); const addonName = 'SearchAddon'; -const mainFile = 'xterm-addon-search.js'; +const mainFile = 'addon-search.js'; module.exports = { entry: `./out/${addonName}.js`, diff --git a/addons/xterm-addon-serialize/.gitignore b/addons/addon-serialize/.gitignore similarity index 100% rename from addons/xterm-addon-serialize/.gitignore rename to addons/addon-serialize/.gitignore diff --git a/addons/xterm-addon-serialize/.npmignore b/addons/addon-serialize/.npmignore similarity index 100% rename from addons/xterm-addon-serialize/.npmignore rename to addons/addon-serialize/.npmignore diff --git a/addons/xterm-addon-serialize/README.md b/addons/addon-serialize/README.md similarity index 71% rename from addons/xterm-addon-serialize/README.md rename to addons/addon-serialize/README.md index 12e0ac8761..862ebac3e4 100644 --- a/addons/xterm-addon-serialize/README.md +++ b/addons/addon-serialize/README.md @@ -1,4 +1,4 @@ -## xterm-addon-serialize +## @xterm/addon-serialize An addon for [xterm.js](https://github.com/xtermjs/xterm.js) that enables xterm.js to serialize a terminal framebuffer into string or html. This addon requires xterm.js v4+. @@ -7,14 +7,14 @@ An addon for [xterm.js](https://github.com/xtermjs/xterm.js) that enables xterm. ### Install ```bash -npm install --save xterm-addon-serialize +npm install --save @xterm/addon-serialize ``` ### Usage ```ts -import { Terminal } from "xterm"; -import { SerializeAddon } from "xterm-addon-serialize"; +import { Terminal } from "@xterm/xterm"; +import { SerializeAddon } from "@xterm/addon-serialize"; const terminal = new Terminal(); const serializeAddon = new SerializeAddon(); @@ -25,7 +25,7 @@ terminal.write("something...", () => { }); ``` -See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/xterm-addon-serialize/typings/xterm-addon-serialize.d.ts) for more advanced usage. +See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/addon-serialize/typings/addon-serialize.d.ts) for more advanced usage. ### Benchmark @@ -35,8 +35,8 @@ See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/xterm- $ git clone https://github.com/xtermjs/xterm.js.git $ cd xterm.js $ yarn -$ cd addons/xterm-addon-serialize +$ cd addons/addon-serialize $ yarn benchmark && yarn benchmark-baseline -$ # change some code in `xterm-addon-serialize` +$ # change some code in `@xterm/addon-serialize` $ yarn benchmark-eval ``` diff --git a/addons/xterm-addon-serialize/benchmark/SerializeAddon.benchmark.ts b/addons/addon-serialize/benchmark/SerializeAddon.benchmark.ts similarity index 100% rename from addons/xterm-addon-serialize/benchmark/SerializeAddon.benchmark.ts rename to addons/addon-serialize/benchmark/SerializeAddon.benchmark.ts diff --git a/addons/xterm-addon-serialize/benchmark/benchmark.json b/addons/addon-serialize/benchmark/benchmark.json similarity index 100% rename from addons/xterm-addon-serialize/benchmark/benchmark.json rename to addons/addon-serialize/benchmark/benchmark.json diff --git a/addons/xterm-addon-serialize/benchmark/tsconfig.json b/addons/addon-serialize/benchmark/tsconfig.json similarity index 82% rename from addons/xterm-addon-serialize/benchmark/tsconfig.json rename to addons/addon-serialize/benchmark/tsconfig.json index 6bbb2a4b78..1f6429f6e9 100644 --- a/addons/xterm-addon-serialize/benchmark/tsconfig.json +++ b/addons/addon-serialize/benchmark/tsconfig.json @@ -14,7 +14,10 @@ "paths": { "common/*": ["../../../src/common/*"], "browser/*": ["../../../src/browser/*"], - "SerializeAddon": ["../src/SerializeAddon"] + "SerializeAddon": ["../src/SerializeAddon"], + "@xterm/addon-serialize": [ + "../typings/addon-serialize.d.ts" + ] } }, "include": ["../**/*", "../../../typings/xterm.d.ts"], diff --git a/addons/xterm-addon-serialize/package.json b/addons/addon-serialize/package.json similarity index 84% rename from addons/xterm-addon-serialize/package.json rename to addons/addon-serialize/package.json index 8f9148659a..763c52ca94 100644 --- a/addons/xterm-addon-serialize/package.json +++ b/addons/addon-serialize/package.json @@ -1,13 +1,13 @@ { - "name": "xterm-addon-serialize", + "name": "@xterm/addon-serialize", "version": "0.11.0", "author": { "name": "The xterm.js authors", "url": "https://xtermjs.org/" }, - "main": "lib/xterm-addon-serialize.js", - "types": "typings/xterm-addon-serialize.d.ts", - "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-serialize", + "main": "lib/addon-serialize.js", + "types": "typings/addon-serialize.d.ts", + "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/addon-serialize", "license": "MIT", "keywords": [ "terminal", @@ -24,6 +24,6 @@ "benchmark-eval": "NODE_PATH=../../out:./out:./out-benchmark/ ../../node_modules/.bin/xterm-benchmark -r 5 -c benchmark/benchmark.json --eval out-benchmark/benchmark/*benchmark.js" }, "peerDependencies": { - "xterm": "^5.0.0" + "@xterm/xterm": "^5.0.0" } } diff --git a/addons/xterm-addon-serialize/src/SerializeAddon.test.ts b/addons/addon-serialize/src/SerializeAddon.test.ts similarity index 99% rename from addons/xterm-addon-serialize/src/SerializeAddon.test.ts rename to addons/addon-serialize/src/SerializeAddon.test.ts index 75148ab9c4..d41cfa12ed 100644 --- a/addons/xterm-addon-serialize/src/SerializeAddon.test.ts +++ b/addons/addon-serialize/src/SerializeAddon.test.ts @@ -44,7 +44,7 @@ class TestSelectionService { } } -describe('xterm-addon-serialize', () => { +describe('SerializeAddon', () => { let dom: jsdom.JSDOM; let window: jsdom.DOMWindow; diff --git a/addons/xterm-addon-serialize/src/SerializeAddon.ts b/addons/addon-serialize/src/SerializeAddon.ts similarity index 98% rename from addons/xterm-addon-serialize/src/SerializeAddon.ts rename to addons/addon-serialize/src/SerializeAddon.ts index 7a2db0893b..961d8546e6 100644 --- a/addons/xterm-addon-serialize/src/SerializeAddon.ts +++ b/addons/addon-serialize/src/SerializeAddon.ts @@ -5,9 +5,10 @@ * (EXPERIMENTAL) This Addon is still under development */ +import type { IBuffer, IBufferCell, IBufferRange, ITerminalAddon, Terminal } from '@xterm/xterm'; +import type { SerializeAddon as ISerializeApi } from '@xterm/addon-serialize'; import { DEFAULT_ANSI_COLORS } from 'browser/services/ThemeService'; import { IAttributeData, IColor } from 'common/Types'; -import { IBuffer, IBufferCell, IBufferRange, ITerminalAddon, Terminal } from 'xterm'; function constrain(value: number, low: number, high: number): number { return Math.max(low, Math.min(value, high)); @@ -411,7 +412,7 @@ class StringSerializeHandler extends BaseSerializeHandler { } } -export class SerializeAddon implements ITerminalAddon { +export class SerializeAddon implements ITerminalAddon , ISerializeApi { private _terminal: Terminal | undefined; public activate(terminal: Terminal): void { @@ -604,7 +605,7 @@ export class HTMLSerializeHandler extends BaseSerializeHandler { (color >> 8) & 255, (color ) & 255 ]; - return rgb.map(x => this._padStart(x.toString(16), 2, '0')).join(''); + return '#' + rgb.map(x => this._padStart(x.toString(16), 2, '0')).join(''); } if (isFg ? cell.isFgPalette() : cell.isBgPalette()) { return this._ansiColors[color].css; diff --git a/addons/xterm-addon-serialize/src/tsconfig.json b/addons/addon-serialize/src/tsconfig.json similarity index 88% rename from addons/xterm-addon-serialize/src/tsconfig.json rename to addons/addon-serialize/src/tsconfig.json index 22ffe53e0f..6fb641ef40 100644 --- a/addons/xterm-addon-serialize/src/tsconfig.json +++ b/addons/addon-serialize/src/tsconfig.json @@ -17,6 +17,9 @@ ], "browser/*": [ "../../../src/browser/*" + ], + "@xterm/addon-serialize": [ + "../typings/addon-serialize.d.ts" ] }, "strict": true, diff --git a/addons/xterm-addon-serialize/test/SerializeAddon.api.ts b/addons/addon-serialize/test/SerializeAddon.api.ts similarity index 100% rename from addons/xterm-addon-serialize/test/SerializeAddon.api.ts rename to addons/addon-serialize/test/SerializeAddon.api.ts diff --git a/addons/xterm-addon-serialize/test/tsconfig.json b/addons/addon-serialize/test/tsconfig.json similarity index 100% rename from addons/xterm-addon-serialize/test/tsconfig.json rename to addons/addon-serialize/test/tsconfig.json diff --git a/addons/xterm-addon-serialize/tsconfig.json b/addons/addon-serialize/tsconfig.json similarity index 100% rename from addons/xterm-addon-serialize/tsconfig.json rename to addons/addon-serialize/tsconfig.json diff --git a/addons/xterm-addon-serialize/typings/xterm-addon-serialize.d.ts b/addons/addon-serialize/typings/addon-serialize.d.ts similarity index 96% rename from addons/xterm-addon-serialize/typings/xterm-addon-serialize.d.ts rename to addons/addon-serialize/typings/addon-serialize.d.ts index 4cb6283db0..0b127b5061 100644 --- a/addons/xterm-addon-serialize/typings/xterm-addon-serialize.d.ts +++ b/addons/addon-serialize/typings/addon-serialize.d.ts @@ -3,9 +3,9 @@ * @license MIT */ -import { Terminal, ITerminalAddon } from 'xterm'; +import { Terminal, ITerminalAddon } from '@xterm/xterm'; -declare module 'xterm-addon-serialize' { +declare module '@xterm/addon-serialize' { /** * An xterm.js addon that enables serialization of terminal contents. */ diff --git a/addons/xterm-addon-serialize/webpack.config.js b/addons/addon-serialize/webpack.config.js similarity index 94% rename from addons/xterm-addon-serialize/webpack.config.js rename to addons/addon-serialize/webpack.config.js index fee297d85a..bd08ca3745 100644 --- a/addons/xterm-addon-serialize/webpack.config.js +++ b/addons/addon-serialize/webpack.config.js @@ -6,7 +6,7 @@ const path = require('path'); const addonName = 'SerializeAddon'; -const mainFile = 'xterm-addon-serialize.js'; +const mainFile = 'addon-serialize.js'; module.exports = { entry: `./out/${addonName}.js`, diff --git a/addons/xterm-addon-unicode-graphemes/.gitignore b/addons/addon-unicode-graphemes/.gitignore similarity index 100% rename from addons/xterm-addon-unicode-graphemes/.gitignore rename to addons/addon-unicode-graphemes/.gitignore diff --git a/addons/xterm-addon-unicode-graphemes/.npmignore b/addons/addon-unicode-graphemes/.npmignore similarity index 100% rename from addons/xterm-addon-unicode-graphemes/.npmignore rename to addons/addon-unicode-graphemes/.npmignore diff --git a/addons/xterm-addon-unicode-graphemes/LICENSE b/addons/addon-unicode-graphemes/LICENSE similarity index 100% rename from addons/xterm-addon-unicode-graphemes/LICENSE rename to addons/addon-unicode-graphemes/LICENSE diff --git a/addons/xterm-addon-unicode-graphemes/README.md b/addons/addon-unicode-graphemes/README.md similarity index 74% rename from addons/xterm-addon-unicode-graphemes/README.md rename to addons/addon-unicode-graphemes/README.md index 2f5639fcc1..6e717c2694 100644 --- a/addons/xterm-addon-unicode-graphemes/README.md +++ b/addons/addon-unicode-graphemes/README.md @@ -1,4 +1,4 @@ -## xterm-addon-unicode-graphemes +## @xterm/addon-unicode-graphemes ⚠️ **This addon is currently experimental and may introduce unexpected and non-standard behavior** @@ -8,15 +8,13 @@ The file `src/UnicodeProperties.ts` is generated and depends on the Unicode vers ### Install -```bash -npm install --save xterm-addon-unicode-graphemes -``` +This addon is not yet published to npm ### Usage ```ts -import { Terminal } from 'xterm'; -import { UnicodeGraphemesAddon } from 'xterm-addon-unicode-graphemes'; +import { Terminal } from '@xterm/xterm'; +import { UnicodeGraphemesAddon } from '@xterm/addon-unicode-graphemes'; const terminal = new Terminal(); const unicodeGraphemesAddon = new UnicodeGraphemesAddon(); diff --git a/addons/xterm-addon-unicode-graphemes/benchmark/UnicodeGraphemeAddon.benchmark.ts b/addons/addon-unicode-graphemes/benchmark/UnicodeGraphemeAddon.benchmark.ts similarity index 100% rename from addons/xterm-addon-unicode-graphemes/benchmark/UnicodeGraphemeAddon.benchmark.ts rename to addons/addon-unicode-graphemes/benchmark/UnicodeGraphemeAddon.benchmark.ts diff --git a/addons/xterm-addon-unicode-graphemes/benchmark/benchmark.json b/addons/addon-unicode-graphemes/benchmark/benchmark.json similarity index 100% rename from addons/xterm-addon-unicode-graphemes/benchmark/benchmark.json rename to addons/addon-unicode-graphemes/benchmark/benchmark.json diff --git a/addons/xterm-addon-unicode-graphemes/benchmark/tsconfig.json b/addons/addon-unicode-graphemes/benchmark/tsconfig.json similarity index 86% rename from addons/xterm-addon-unicode-graphemes/benchmark/tsconfig.json rename to addons/addon-unicode-graphemes/benchmark/tsconfig.json index 9bc532d3fe..c6f37a6ce3 100644 --- a/addons/xterm-addon-unicode-graphemes/benchmark/tsconfig.json +++ b/addons/addon-unicode-graphemes/benchmark/tsconfig.json @@ -11,7 +11,10 @@ "paths": { "common/*": ["../../../src/common/*"], "browser/*": ["../../../src/browser/*"], - "UnicodeGraphemeProvider": ["../src/UnicodeGraphemeProvider"] + "UnicodeGraphemeProvider": ["../src/UnicodeGraphemeProvider"], + "@xterm/addon-unicode-graphemes": [ + "../typings/addon-unicode-graphemes.d.ts" + ] } }, "include": ["../**/*", "../../../typings/xterm.d.ts"], diff --git a/addons/xterm-addon-unicode-graphemes/package.json b/addons/addon-unicode-graphemes/package.json similarity index 83% rename from addons/xterm-addon-unicode-graphemes/package.json rename to addons/addon-unicode-graphemes/package.json index 38ea7271f2..d49eda8733 100644 --- a/addons/xterm-addon-unicode-graphemes/package.json +++ b/addons/addon-unicode-graphemes/package.json @@ -1,13 +1,13 @@ { - "name": "xterm-addon-unicode-graphemes", + "name": "@xterm/addon-unicode-graphemes", "version": "0.1.0", "author": { "name": "The xterm.js authors", "url": "https://xtermjs.org/" }, - "main": "lib/xterm-addon-unicode-graphemes.js", - "types": "typings/xterm-addon-unicode-graphemes.d.ts", - "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-unicode-graphemes", + "main": "lib/addon-unicode-graphemes.js", + "types": "typings/addon-unicode-graphemes.d.ts", + "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/addon-unicode-graphemes", "license": "MIT", "keywords": [ "terminal", @@ -24,6 +24,6 @@ "benchmark-eval": "NODE_PATH=../../out:./out:./out-benchmark/ ../../node_modules/.bin/xterm-benchmark -r 5 -c benchmark/benchmark.json --eval out-benchmark/benchmark/*benchmark.js" }, "peerDependencies": { - "xterm": "^5.0.0" + "@xterm/xterm": "^5.0.0" } } diff --git a/addons/xterm-addon-unicode-graphemes/src/UnicodeGraphemeProvider.ts b/addons/addon-unicode-graphemes/src/UnicodeGraphemeProvider.ts similarity index 97% rename from addons/xterm-addon-unicode-graphemes/src/UnicodeGraphemeProvider.ts rename to addons/addon-unicode-graphemes/src/UnicodeGraphemeProvider.ts index 39fbec8407..3d5717a0f6 100644 --- a/addons/xterm-addon-unicode-graphemes/src/UnicodeGraphemeProvider.ts +++ b/addons/addon-unicode-graphemes/src/UnicodeGraphemeProvider.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { IUnicodeVersionProvider } from 'xterm'; +import { IUnicodeVersionProvider } from '@xterm/xterm'; import { UnicodeCharProperties, UnicodeCharWidth } from 'common/services/Services'; import { UnicodeService } from 'common/services/UnicodeService'; import * as UC from './third-party/UnicodeProperties'; diff --git a/addons/xterm-addon-unicode-graphemes/src/UnicodeGraphemesAddon.ts b/addons/addon-unicode-graphemes/src/UnicodeGraphemesAddon.ts similarity index 79% rename from addons/xterm-addon-unicode-graphemes/src/UnicodeGraphemesAddon.ts rename to addons/addon-unicode-graphemes/src/UnicodeGraphemesAddon.ts index 80290edfd6..6e4d226604 100644 --- a/addons/xterm-addon-unicode-graphemes/src/UnicodeGraphemesAddon.ts +++ b/addons/addon-unicode-graphemes/src/UnicodeGraphemesAddon.ts @@ -5,11 +5,11 @@ * UnicodeVersionProvider for V15 with grapeme cluster handleing. */ -import { Terminal, ITerminalAddon, IUnicodeHandling } from 'xterm'; +import type { Terminal, ITerminalAddon, IUnicodeHandling } from '@xterm/xterm'; +import type { UnicodeGraphemesAddon as IUnicodeGraphemesApi } from '@xterm/addon-unicode-graphemes'; import { UnicodeGraphemeProvider } from './UnicodeGraphemeProvider'; - -export class UnicodeGraphemesAddon implements ITerminalAddon { +export class UnicodeGraphemesAddon implements ITerminalAddon , IUnicodeGraphemesApi { private _provider15Graphemes?: UnicodeGraphemeProvider; private _provider15?: UnicodeGraphemeProvider; private _unicode?: IUnicodeHandling; diff --git a/addons/xterm-addon-unicode-graphemes/src/third-party/UnicodeProperties.ts b/addons/addon-unicode-graphemes/src/third-party/UnicodeProperties.ts similarity index 100% rename from addons/xterm-addon-unicode-graphemes/src/third-party/UnicodeProperties.ts rename to addons/addon-unicode-graphemes/src/third-party/UnicodeProperties.ts diff --git a/addons/xterm-addon-unicode-graphemes/src/third-party/tiny-inflate.ts b/addons/addon-unicode-graphemes/src/third-party/tiny-inflate.ts similarity index 100% rename from addons/xterm-addon-unicode-graphemes/src/third-party/tiny-inflate.ts rename to addons/addon-unicode-graphemes/src/third-party/tiny-inflate.ts diff --git a/addons/xterm-addon-unicode-graphemes/src/third-party/unicode-trie.ts b/addons/addon-unicode-graphemes/src/third-party/unicode-trie.ts similarity index 100% rename from addons/xterm-addon-unicode-graphemes/src/third-party/unicode-trie.ts rename to addons/addon-unicode-graphemes/src/third-party/unicode-trie.ts diff --git a/addons/xterm-addon-unicode-graphemes/src/tsconfig.json b/addons/addon-unicode-graphemes/src/tsconfig.json similarity index 84% rename from addons/xterm-addon-unicode-graphemes/src/tsconfig.json rename to addons/addon-unicode-graphemes/src/tsconfig.json index 60824fee94..e9967bbe2e 100644 --- a/addons/xterm-addon-unicode-graphemes/src/tsconfig.json +++ b/addons/addon-unicode-graphemes/src/tsconfig.json @@ -15,6 +15,9 @@ "paths": { "common/*": [ "../../../src/common/*" + ], + "@xterm/addon-unicode-graphemes": [ + "../typings/addon-unicode-graphemes.d.ts" ] }, "types": [ diff --git a/addons/xterm-addon-unicode-graphemes/test/UnicodeGraphemesAddon.api.ts b/addons/addon-unicode-graphemes/test/UnicodeGraphemesAddon.api.ts similarity index 100% rename from addons/xterm-addon-unicode-graphemes/test/UnicodeGraphemesAddon.api.ts rename to addons/addon-unicode-graphemes/test/UnicodeGraphemesAddon.api.ts diff --git a/addons/xterm-addon-unicode-graphemes/test/tsconfig.json b/addons/addon-unicode-graphemes/test/tsconfig.json similarity index 100% rename from addons/xterm-addon-unicode-graphemes/test/tsconfig.json rename to addons/addon-unicode-graphemes/test/tsconfig.json diff --git a/addons/xterm-addon-unicode-graphemes/tsconfig.json b/addons/addon-unicode-graphemes/tsconfig.json similarity index 100% rename from addons/xterm-addon-unicode-graphemes/tsconfig.json rename to addons/addon-unicode-graphemes/tsconfig.json diff --git a/addons/xterm-addon-unicode-graphemes/typings/xterm-addon-unicode-graphemes.d.ts b/addons/addon-unicode-graphemes/typings/addon-unicode-graphemes.d.ts similarity index 70% rename from addons/xterm-addon-unicode-graphemes/typings/xterm-addon-unicode-graphemes.d.ts rename to addons/addon-unicode-graphemes/typings/addon-unicode-graphemes.d.ts index 3ab25aa007..9443f1c885 100644 --- a/addons/xterm-addon-unicode-graphemes/typings/xterm-addon-unicode-graphemes.d.ts +++ b/addons/addon-unicode-graphemes/typings/addon-unicode-graphemes.d.ts @@ -3,9 +3,9 @@ * @license MIT */ -import { Terminal, ITerminalAddon } from 'xterm'; +import { Terminal, ITerminalAddon } from '@xterm/xterm'; -declare module 'xterm-addon-unicode-graphemes' { +declare module '@xterm/addon-unicode-graphemes' { export class UnicodeGraphemesAddon implements ITerminalAddon { constructor(); public activate(terminal: Terminal): void; diff --git a/addons/xterm-addon-unicode-graphemes/webpack.config.js b/addons/addon-unicode-graphemes/webpack.config.js similarity index 92% rename from addons/xterm-addon-unicode-graphemes/webpack.config.js rename to addons/addon-unicode-graphemes/webpack.config.js index 89abf53aad..6a80bdea60 100644 --- a/addons/xterm-addon-unicode-graphemes/webpack.config.js +++ b/addons/addon-unicode-graphemes/webpack.config.js @@ -6,7 +6,7 @@ const path = require('path'); const addonName = 'UnicodeGraphemesAddon'; -const mainFile = 'xterm-addon-unicode-graphemes.js'; +const mainFile = 'addon-unicode-graphemes.js'; module.exports = { entry: `./out/${addonName}.js`, diff --git a/addons/xterm-addon-unicode11/.gitignore b/addons/addon-unicode11/.gitignore similarity index 100% rename from addons/xterm-addon-unicode11/.gitignore rename to addons/addon-unicode11/.gitignore diff --git a/addons/xterm-addon-unicode11/.npmignore b/addons/addon-unicode11/.npmignore similarity index 100% rename from addons/xterm-addon-unicode11/.npmignore rename to addons/addon-unicode11/.npmignore diff --git a/addons/xterm-addon-unicode11/LICENSE b/addons/addon-unicode11/LICENSE similarity index 100% rename from addons/xterm-addon-unicode11/LICENSE rename to addons/addon-unicode11/LICENSE diff --git a/addons/xterm-addon-unicode11/README.md b/addons/addon-unicode11/README.md similarity index 63% rename from addons/xterm-addon-unicode11/README.md rename to addons/addon-unicode11/README.md index ec01203e91..ccfe77cf76 100644 --- a/addons/xterm-addon-unicode11/README.md +++ b/addons/addon-unicode11/README.md @@ -1,18 +1,18 @@ -## xterm-addon-unicode11 +## @xterm/addon-unicode11 An addon providing Unicode version 11 rules for xterm.js. ### Install ```bash -npm install --save xterm-addon-unicode11 +npm install --save @xterm/addon-unicode11 ``` ### Usage ```ts -import { Terminal } from 'xterm'; -import { Unicode11Addon } from 'xterm-addon-unicode11'; +import { Terminal } from '@xterm/xterm'; +import { Unicode11Addon } from '@xterm/addon-unicode11'; const terminal = new Terminal(); const unicode11Addon = new Unicode11Addon(); diff --git a/addons/xterm-addon-unicode11/package.json b/addons/addon-unicode11/package.json similarity index 72% rename from addons/xterm-addon-unicode11/package.json rename to addons/addon-unicode11/package.json index d187d8edc8..ad6a489249 100644 --- a/addons/xterm-addon-unicode11/package.json +++ b/addons/addon-unicode11/package.json @@ -1,13 +1,13 @@ { - "name": "xterm-addon-unicode11", + "name": "@xterm/addon-unicode11", "version": "0.6.0", "author": { "name": "The xterm.js authors", "url": "https://xtermjs.org/" }, - "main": "lib/xterm-addon-unicode11.js", - "types": "typings/xterm-addon-unicode11.d.ts", - "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-unicode11", + "main": "lib/addon-unicode11.js", + "types": "typings/addon-unicode11.d.ts", + "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/addon-unicode11", "license": "MIT", "keywords": [ "terminal", @@ -21,6 +21,6 @@ "prepublishOnly": "npm run package" }, "peerDependencies": { - "xterm": "^5.0.0" + "@xterm/xterm": "^5.0.0" } } diff --git a/addons/xterm-addon-unicode11/src/Unicode11Addon.ts b/addons/addon-unicode11/src/Unicode11Addon.ts similarity index 58% rename from addons/xterm-addon-unicode11/src/Unicode11Addon.ts rename to addons/addon-unicode11/src/Unicode11Addon.ts index d4ddf77eed..301145eed4 100644 --- a/addons/xterm-addon-unicode11/src/Unicode11Addon.ts +++ b/addons/addon-unicode11/src/Unicode11Addon.ts @@ -5,11 +5,11 @@ * UnicodeVersionProvider for V11. */ -import { Terminal, ITerminalAddon } from 'xterm'; +import type { Terminal, ITerminalAddon } from '@xterm/xterm'; +import type { Unicode11Addon as IUnicode11Api } from '@xterm/addon-unicode11'; import { UnicodeV11 } from './UnicodeV11'; - -export class Unicode11Addon implements ITerminalAddon { +export class Unicode11Addon implements ITerminalAddon , IUnicode11Api { public activate(terminal: Terminal): void { terminal.unicode.register(new UnicodeV11()); } diff --git a/addons/xterm-addon-unicode11/src/UnicodeV11.ts b/addons/addon-unicode11/src/UnicodeV11.ts similarity index 99% rename from addons/xterm-addon-unicode11/src/UnicodeV11.ts rename to addons/addon-unicode11/src/UnicodeV11.ts index c1ef08c169..79568960a0 100644 --- a/addons/xterm-addon-unicode11/src/UnicodeV11.ts +++ b/addons/addon-unicode11/src/UnicodeV11.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { IUnicodeVersionProvider } from 'xterm'; +import { IUnicodeVersionProvider } from '@xterm/xterm'; import { UnicodeCharProperties, UnicodeCharWidth } from 'common/services/Services'; import { UnicodeService } from 'common/services/UnicodeService'; diff --git a/addons/xterm-addon-unicode11/src/tsconfig.json b/addons/addon-unicode11/src/tsconfig.json similarity index 86% rename from addons/xterm-addon-unicode11/src/tsconfig.json rename to addons/addon-unicode11/src/tsconfig.json index e2c1464e6e..8eb7752bd0 100644 --- a/addons/xterm-addon-unicode11/src/tsconfig.json +++ b/addons/addon-unicode11/src/tsconfig.json @@ -15,6 +15,9 @@ "paths": { "common/*": [ "../../../src/common/*" + ], + "@xterm/addon-unicode11": [ + "../typings/addon-unicode11.d.ts" ] }, "types": [ diff --git a/addons/xterm-addon-unicode11/test/Unicode11Addon.api.ts b/addons/addon-unicode11/test/Unicode11Addon.api.ts similarity index 100% rename from addons/xterm-addon-unicode11/test/Unicode11Addon.api.ts rename to addons/addon-unicode11/test/Unicode11Addon.api.ts diff --git a/addons/xterm-addon-unicode11/test/tsconfig.json b/addons/addon-unicode11/test/tsconfig.json similarity index 100% rename from addons/xterm-addon-unicode11/test/tsconfig.json rename to addons/addon-unicode11/test/tsconfig.json diff --git a/addons/xterm-addon-unicode11/tsconfig.json b/addons/addon-unicode11/tsconfig.json similarity index 100% rename from addons/xterm-addon-unicode11/tsconfig.json rename to addons/addon-unicode11/tsconfig.json diff --git a/addons/xterm-addon-unicode11/typings/xterm-addon-unicode11.d.ts b/addons/addon-unicode11/typings/addon-unicode11.d.ts similarity index 71% rename from addons/xterm-addon-unicode11/typings/xterm-addon-unicode11.d.ts rename to addons/addon-unicode11/typings/addon-unicode11.d.ts index 1d0dce1b1b..74bd288dda 100644 --- a/addons/xterm-addon-unicode11/typings/xterm-addon-unicode11.d.ts +++ b/addons/addon-unicode11/typings/addon-unicode11.d.ts @@ -3,9 +3,9 @@ * @license MIT */ -import { Terminal, ITerminalAddon } from 'xterm'; +import { Terminal, ITerminalAddon } from '@xterm/xterm'; -declare module 'xterm-addon-unicode11' { +declare module '@xterm/addon-unicode11' { export class Unicode11Addon implements ITerminalAddon { constructor(); public activate(terminal: Terminal): void; diff --git a/addons/xterm-addon-unicode11/webpack.config.js b/addons/addon-unicode11/webpack.config.js similarity index 94% rename from addons/xterm-addon-unicode11/webpack.config.js rename to addons/addon-unicode11/webpack.config.js index 10c0adc3c3..1913481d2c 100644 --- a/addons/xterm-addon-unicode11/webpack.config.js +++ b/addons/addon-unicode11/webpack.config.js @@ -6,7 +6,7 @@ const path = require('path'); const addonName = 'Unicode11Addon'; -const mainFile = 'xterm-addon-unicode11.js'; +const mainFile = 'addon-unicode11.js'; module.exports = { entry: `./out/${addonName}.js`, diff --git a/addons/xterm-addon-web-links/.gitignore b/addons/addon-web-links/.gitignore similarity index 100% rename from addons/xterm-addon-web-links/.gitignore rename to addons/addon-web-links/.gitignore diff --git a/addons/xterm-addon-web-links/.npmignore b/addons/addon-web-links/.npmignore similarity index 100% rename from addons/xterm-addon-web-links/.npmignore rename to addons/addon-web-links/.npmignore diff --git a/addons/xterm-addon-web-links/LICENSE b/addons/addon-web-links/LICENSE similarity index 100% rename from addons/xterm-addon-web-links/LICENSE rename to addons/addon-web-links/LICENSE diff --git a/addons/xterm-addon-web-links/README.md b/addons/addon-web-links/README.md similarity index 55% rename from addons/xterm-addon-web-links/README.md rename to addons/addon-web-links/README.md index e53f4edf79..16dfa57181 100644 --- a/addons/xterm-addon-web-links/README.md +++ b/addons/addon-web-links/README.md @@ -1,21 +1,21 @@ -## xterm-addon-web-links +## @xterm/addon-web-links An addon for [xterm.js](https://github.com/xtermjs/xterm.js) that enables web links. This addon requires xterm.js v4+. ### Install ```bash -npm install --save xterm-addon-web-links +npm install --save @xterm/addon-web-links ``` ### Usage ```ts -import { Terminal } from 'xterm'; -import { WebLinksAddon } from 'xterm-addon-web-links'; +import { Terminal } from '@xterm/xterm'; +import { WebLinksAddon } from '@xterm/addon-web-links'; const terminal = new Terminal(); terminal.loadAddon(new WebLinksAddon()); ``` -See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/xterm-addon-web-links/typings/xterm-addon-web-links.d.ts) for more advanced usage. +See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/addon-web-links/typings/addon-web-links.d.ts) for more advanced usage. diff --git a/addons/xterm-addon-web-links/package.json b/addons/addon-web-links/package.json similarity index 73% rename from addons/xterm-addon-web-links/package.json rename to addons/addon-web-links/package.json index 783ee7e01a..6367907aac 100644 --- a/addons/xterm-addon-web-links/package.json +++ b/addons/addon-web-links/package.json @@ -1,13 +1,13 @@ { - "name": "xterm-addon-web-links", + "name": "@xterm/addon-web-links", "version": "0.9.0", "author": { "name": "The xterm.js authors", "url": "https://xtermjs.org/" }, - "main": "lib/xterm-addon-web-links.js", - "types": "typings/xterm-addon-web-links.d.ts", - "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-web-links", + "main": "lib/addon-web-links.js", + "types": "typings/addon-web-links.d.ts", + "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/addon-web-links", "license": "MIT", "keywords": [ "terminal", @@ -21,7 +21,7 @@ "prepublishOnly": "npm run package" }, "peerDependencies": { - "xterm": "^5.0.0" + "@xterm/xterm": "^5.0.0" } } diff --git a/addons/xterm-addon-web-links/src/WebLinkProvider.ts b/addons/addon-web-links/src/WebLinkProvider.ts similarity index 99% rename from addons/xterm-addon-web-links/src/WebLinkProvider.ts rename to addons/addon-web-links/src/WebLinkProvider.ts index 1c9486f5b4..25dd983c9b 100644 --- a/addons/xterm-addon-web-links/src/WebLinkProvider.ts +++ b/addons/addon-web-links/src/WebLinkProvider.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { ILinkProvider, ILink, Terminal, IViewportRange, IBufferLine } from 'xterm'; +import { ILinkProvider, ILink, Terminal, IViewportRange, IBufferLine } from '@xterm/xterm'; export interface ILinkProviderOptions { hover?(event: MouseEvent, text: string, location: IViewportRange): void; diff --git a/addons/xterm-addon-web-links/src/WebLinksAddon.ts b/addons/addon-web-links/src/WebLinksAddon.ts similarity index 89% rename from addons/xterm-addon-web-links/src/WebLinksAddon.ts rename to addons/addon-web-links/src/WebLinksAddon.ts index 5c956cec36..8902d8e0ad 100644 --- a/addons/xterm-addon-web-links/src/WebLinksAddon.ts +++ b/addons/addon-web-links/src/WebLinksAddon.ts @@ -3,7 +3,8 @@ * @license MIT */ -import { Terminal, ITerminalAddon, IDisposable } from 'xterm'; +import type { Terminal, ITerminalAddon, IDisposable } from '@xterm/xterm'; +import type { WebLinksAddon as IWebLinksApi } from '@xterm/addon-web-links'; import { ILinkProviderOptions, WebLinkProvider } from './WebLinkProvider'; // consider everthing starting with http:// or https:// @@ -34,7 +35,7 @@ function handleLink(event: MouseEvent, uri: string): void { } } -export class WebLinksAddon implements ITerminalAddon { +export class WebLinksAddon implements ITerminalAddon , IWebLinksApi { private _terminal: Terminal | undefined; private _linkProvider: IDisposable | undefined; diff --git a/addons/xterm-addon-web-links/src/tsconfig.json b/addons/addon-web-links/src/tsconfig.json similarity index 76% rename from addons/xterm-addon-web-links/src/tsconfig.json rename to addons/addon-web-links/src/tsconfig.json index 7e68574d95..217402de12 100644 --- a/addons/xterm-addon-web-links/src/tsconfig.json +++ b/addons/addon-web-links/src/tsconfig.json @@ -13,7 +13,12 @@ "strict": true, "types": [ "../../../node_modules/@types/mocha" - ] + ], + "paths": { + "@xterm/addon-web-links": [ + "../typings/addon-web-links.d.ts" + ] + } }, "include": [ "./**/*", diff --git a/addons/xterm-addon-web-links/test/WebLinksAddon.api.ts b/addons/addon-web-links/test/WebLinksAddon.api.ts similarity index 100% rename from addons/xterm-addon-web-links/test/WebLinksAddon.api.ts rename to addons/addon-web-links/test/WebLinksAddon.api.ts diff --git a/addons/xterm-addon-web-links/test/tsconfig.json b/addons/addon-web-links/test/tsconfig.json similarity index 100% rename from addons/xterm-addon-web-links/test/tsconfig.json rename to addons/addon-web-links/test/tsconfig.json diff --git a/addons/xterm-addon-web-links/tsconfig.json b/addons/addon-web-links/tsconfig.json similarity index 100% rename from addons/xterm-addon-web-links/tsconfig.json rename to addons/addon-web-links/tsconfig.json diff --git a/addons/xterm-addon-web-links/typings/xterm-addon-web-links.d.ts b/addons/addon-web-links/typings/addon-web-links.d.ts similarity index 91% rename from addons/xterm-addon-web-links/typings/xterm-addon-web-links.d.ts rename to addons/addon-web-links/typings/addon-web-links.d.ts index dc69d73240..4ae4934ef5 100644 --- a/addons/xterm-addon-web-links/typings/xterm-addon-web-links.d.ts +++ b/addons/addon-web-links/typings/addon-web-links.d.ts @@ -4,9 +4,9 @@ */ -import { Terminal, ITerminalAddon, IViewportRange } from 'xterm'; +import { Terminal, ITerminalAddon, IViewportRange } from '@xterm/xterm'; -declare module 'xterm-addon-web-links' { +declare module '@xterm/addon-web-links' { /** * An xterm.js addon that enables web links. */ diff --git a/addons/xterm-addon-web-links/webpack.config.js b/addons/addon-web-links/webpack.config.js similarity index 92% rename from addons/xterm-addon-web-links/webpack.config.js rename to addons/addon-web-links/webpack.config.js index fd87d07e82..4484dbf604 100644 --- a/addons/xterm-addon-web-links/webpack.config.js +++ b/addons/addon-web-links/webpack.config.js @@ -6,7 +6,7 @@ const path = require('path'); const addonName = 'WebLinksAddon'; -const mainFile = 'xterm-addon-web-links.js'; +const mainFile = 'addon-web-links.js'; module.exports = { entry: `./out/${addonName}.js`, diff --git a/addons/xterm-addon-webgl/.gitignore b/addons/addon-webgl/.gitignore similarity index 100% rename from addons/xterm-addon-webgl/.gitignore rename to addons/addon-webgl/.gitignore diff --git a/addons/xterm-addon-webgl/.npmignore b/addons/addon-webgl/.npmignore similarity index 100% rename from addons/xterm-addon-webgl/.npmignore rename to addons/addon-webgl/.npmignore diff --git a/addons/xterm-addon-webgl/LICENSE b/addons/addon-webgl/LICENSE similarity index 100% rename from addons/xterm-addon-webgl/LICENSE rename to addons/addon-webgl/LICENSE diff --git a/addons/xterm-addon-webgl/README.md b/addons/addon-webgl/README.md similarity index 71% rename from addons/xterm-addon-webgl/README.md rename to addons/addon-webgl/README.md index 5dee6b622c..05d753e86e 100644 --- a/addons/xterm-addon-webgl/README.md +++ b/addons/addon-webgl/README.md @@ -1,25 +1,25 @@ -## xterm-addon-webgl +## @xterm/addon-webgl An addon for [xterm.js](https://github.com/xtermjs/xterm.js) that enables a WebGL2-based renderer. This addon requires xterm.js v4+. ### Install ```bash -npm install --save xterm-addon-webgl +npm install --save @xterm/addon-webgl ``` ### Usage ```ts -import { Terminal } from 'xterm'; -import { WebglAddon } from 'xterm-addon-webgl'; +import { Terminal } from '@xterm/xterm'; +import { WebglAddon } from '@xterm/addon-webgl'; const terminal = new Terminal(); terminal.open(element); terminal.loadAddon(new WebglAddon()); ``` -See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/xterm-addon-webgl/typings/xterm-addon-webgl.d.ts) for more advanced usage. +See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/addon-webgl/typings/addon-webgl.d.ts) for more advanced usage. ### Handling Context Loss @@ -38,4 +38,4 @@ Read more about handling WebGL context losses on the [Khronos wiki](https://www. ### See also -- [xterm-addon-canvas](https://www.npmjs.com/package/xterm-addon-canvas) A renderer for xterm.js that uses a 2d canvas that can be used as a fallback when WebGL is not available +- [@xterm/addon-canvas](https://www.npmjs.com/package/@xterm/addon-canvas) A renderer for xterm.js that uses a 2d canvas that can be used as a fallback when WebGL is not available diff --git a/addons/xterm-addon-webgl/package.json b/addons/addon-webgl/package.json similarity index 77% rename from addons/xterm-addon-webgl/package.json rename to addons/addon-webgl/package.json index 1458effc52..9a31c306c6 100644 --- a/addons/xterm-addon-webgl/package.json +++ b/addons/addon-webgl/package.json @@ -1,13 +1,13 @@ { - "name": "xterm-addon-webgl", + "name": "@xterm/addon-webgl", "version": "0.16.0", "author": { "name": "The xterm.js authors", "url": "https://xtermjs.org/" }, - "main": "lib/xterm-addon-webgl.js", - "types": "typings/xterm-addon-webgl.d.ts", - "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-webgl", + "main": "lib/addon-webgl.js", + "types": "typings/addon-webgl.d.ts", + "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/addon-webgl", "license": "MIT", "keywords": [ "terminal", @@ -23,7 +23,6 @@ "start-server-only": "node ../../demo/start-server-only" }, "peerDependencies": { - "xterm": "^5.0.0" + "@xterm/xterm": "^5.0.0" } - } diff --git a/addons/xterm-addon-webgl/src/GlyphRenderer.ts b/addons/addon-webgl/src/GlyphRenderer.ts similarity index 99% rename from addons/xterm-addon-webgl/src/GlyphRenderer.ts rename to addons/addon-webgl/src/GlyphRenderer.ts index e0669102d5..1fb0e18c54 100644 --- a/addons/xterm-addon-webgl/src/GlyphRenderer.ts +++ b/addons/addon-webgl/src/GlyphRenderer.ts @@ -8,7 +8,7 @@ import { TextureAtlas } from 'browser/renderer/shared/TextureAtlas'; import { IRasterizedGlyph, IRenderDimensions, ITextureAtlas } from 'browser/renderer/shared/Types'; import { NULL_CELL_CODE } from 'common/buffer/Constants'; import { Disposable, toDisposable } from 'common/Lifecycle'; -import { Terminal } from 'xterm'; +import { Terminal } from '@xterm/xterm'; import { IRenderModel, IWebGL2RenderingContext, IWebGLVertexArrayObject } from './Types'; import { createProgram, GLTexture, PROJECTION_MATRIX } from './WebglUtils'; diff --git a/addons/xterm-addon-webgl/src/RectangleRenderer.ts b/addons/addon-webgl/src/RectangleRenderer.ts similarity index 99% rename from addons/xterm-addon-webgl/src/RectangleRenderer.ts rename to addons/addon-webgl/src/RectangleRenderer.ts index 5e9c364eb4..2a1f53928c 100644 --- a/addons/xterm-addon-webgl/src/RectangleRenderer.ts +++ b/addons/addon-webgl/src/RectangleRenderer.ts @@ -10,7 +10,7 @@ import { ReadonlyColorSet } from 'browser/Types'; import { Attributes, FgFlags } from 'common/buffer/Constants'; import { Disposable, toDisposable } from 'common/Lifecycle'; import { IColor } from 'common/Types'; -import { Terminal } from 'xterm'; +import { Terminal } from '@xterm/xterm'; import { RENDER_MODEL_BG_OFFSET, RENDER_MODEL_FG_OFFSET, RENDER_MODEL_INDICIES_PER_CELL } from './RenderModel'; import { IRenderModel, IWebGL2RenderingContext, IWebGLVertexArrayObject } from './Types'; import { createProgram, expandFloat32Array, PROJECTION_MATRIX } from './WebglUtils'; diff --git a/addons/xterm-addon-webgl/src/RenderModel.ts b/addons/addon-webgl/src/RenderModel.ts similarity index 100% rename from addons/xterm-addon-webgl/src/RenderModel.ts rename to addons/addon-webgl/src/RenderModel.ts diff --git a/addons/xterm-addon-webgl/src/TypedArray.test.ts b/addons/addon-webgl/src/TypedArray.test.ts similarity index 100% rename from addons/xterm-addon-webgl/src/TypedArray.test.ts rename to addons/addon-webgl/src/TypedArray.test.ts diff --git a/addons/xterm-addon-webgl/src/TypedArray.ts b/addons/addon-webgl/src/TypedArray.ts similarity index 100% rename from addons/xterm-addon-webgl/src/TypedArray.ts rename to addons/addon-webgl/src/TypedArray.ts diff --git a/addons/xterm-addon-webgl/src/Types.d.ts b/addons/addon-webgl/src/Types.d.ts similarity index 100% rename from addons/xterm-addon-webgl/src/Types.d.ts rename to addons/addon-webgl/src/Types.d.ts diff --git a/addons/xterm-addon-webgl/src/WebglAddon.ts b/addons/addon-webgl/src/WebglAddon.ts similarity index 86% rename from addons/xterm-addon-webgl/src/WebglAddon.ts rename to addons/addon-webgl/src/WebglAddon.ts index 3e091f0b87..2b3a7f9658 100644 --- a/addons/xterm-addon-webgl/src/WebglAddon.ts +++ b/addons/addon-webgl/src/WebglAddon.ts @@ -3,17 +3,19 @@ * @license MIT */ +import type { ITerminalAddon, Terminal } from '@xterm/xterm'; +import type { WebglAddon as IWebglApi } from '@xterm/addon-webgl'; import { ICharacterJoinerService, ICharSizeService, ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services'; import { ITerminal } from 'browser/Types'; import { EventEmitter, forwardEvent } from 'common/EventEmitter'; import { Disposable, toDisposable } from 'common/Lifecycle'; import { getSafariVersion, isSafari } from 'common/Platform'; import { ICoreService, IDecorationService, ILogService, IOptionsService } from 'common/services/Services'; -import { ITerminalAddon, Terminal } from 'xterm'; +import { IWebGL2RenderingContext } from './Types'; import { WebglRenderer } from './WebglRenderer'; import { setTraceLogger } from 'common/services/LogService'; -export class WebglAddon extends Disposable implements ITerminalAddon { +export class WebglAddon extends Disposable implements ITerminalAddon , IWebglApi { private _terminal?: Terminal; private _renderer?: WebglRenderer; @@ -30,7 +32,16 @@ export class WebglAddon extends Disposable implements ITerminalAddon { private _preserveDrawingBuffer?: boolean ) { if (isSafari && getSafariVersion() < 16) { - throw new Error('Webgl2 is only supported on Safari 16 and above'); + // Perform an extra check to determine if Webgl2 is manually enabled in developer settings + const contextAttributes = { + antialias: false, + depth: false, + preserveDrawingBuffer: true + }; + const gl = document.createElement('canvas').getContext('webgl2', contextAttributes) as IWebGL2RenderingContext; + if (!gl) { + throw new Error('Webgl2 is only supported on Safari 16 and above'); + } } super(); } diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.ts b/addons/addon-webgl/src/WebglRenderer.ts similarity index 98% rename from addons/xterm-addon-webgl/src/WebglRenderer.ts rename to addons/addon-webgl/src/WebglRenderer.ts index 8cc81b92cd..2bccc9b7c9 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.ts +++ b/addons/addon-webgl/src/WebglRenderer.ts @@ -19,7 +19,7 @@ import { AttributeData } from 'common/buffer/AttributeData'; import { CellData } from 'common/buffer/CellData'; import { Attributes, Content, NULL_CELL_CHAR, NULL_CELL_CODE } from 'common/buffer/Constants'; import { ICoreService, IDecorationService, IOptionsService } from 'common/services/Services'; -import { Terminal } from 'xterm'; +import { Terminal } from '@xterm/xterm'; import { GlyphRenderer } from './GlyphRenderer'; import { RectangleRenderer } from './RectangleRenderer'; import { COMBINED_CHAR_BIT_MASK, RENDER_MODEL_BG_OFFSET, RENDER_MODEL_EXT_OFFSET, RENDER_MODEL_FG_OFFSET, RENDER_MODEL_INDICIES_PER_CELL, RenderModel } from './RenderModel'; @@ -75,7 +75,7 @@ export class WebglRenderer extends Disposable implements IRenderer { this.register(this._themeService.onChangeColors(() => this._handleColorChange())); - this._cellColorResolver = new CellColorResolver(this._terminal, this._model.selection, this._decorationService, this._coreBrowserService, this._themeService); + this._cellColorResolver = new CellColorResolver(this._terminal, this._optionsService, this._model.selection, this._decorationService, this._coreBrowserService, this._themeService); this._core = (this._terminal as any)._core; @@ -88,7 +88,7 @@ export class WebglRenderer extends Disposable implements IRenderer { this._updateCursorBlink(); this.register(_optionsService.onOptionChange(() => this._handleOptionsChanged())); - this._canvas = document.createElement('canvas'); + this._canvas = this._coreBrowserService.mainDocument.createElement('canvas'); const contextAttributes = { antialias: false, @@ -219,7 +219,7 @@ export class WebglRenderer extends Disposable implements IRenderer { for (const l of this._renderLayers) { l.handleSelectionChanged(this._terminal, start, end, columnSelectMode); } - this._model.selection.update(this._terminal, start, end, columnSelectMode); + this._model.selection.update(this._core, start, end, columnSelectMode); this._requestRedrawViewport(); } @@ -391,6 +391,7 @@ export class WebglRenderer extends Disposable implements IRenderer { end = clamp(end, terminal.rows - 1, 0); const cursorY = this._terminal.buffer.active.baseY + this._terminal.buffer.active.cursorY; + const viewportRelativeCursorY = cursorY - terminal.buffer.ydisp; // in case cursor.x == cols adjust visual cursor to cols - 1 const cursorX = Math.min(this._terminal.buffer.active.cursorX, terminal.cols - 1); let lastCursorX = -1; @@ -442,14 +443,14 @@ export class WebglRenderer extends Disposable implements IRenderer { i = ((y * terminal.cols) + x) * RENDER_MODEL_INDICIES_PER_CELL; // Load colors/resolve overrides into work colors - this._cellColorResolver.resolve(cell, x, row); + this._cellColorResolver.resolve(cell, x, row, this.dimensions.device.cell.width); // Override colors for cursor cell if (isCursorVisible && row === cursorY) { if (x === cursorX) { this._model.cursor = { x: cursorX, - y: this._terminal.buffer.active.cursorY, + y: viewportRelativeCursorY, width: cell.getWidth(), style: this._coreBrowserService.isFocused ? (terminal.options.cursorStyle || 'block') : terminal.options.cursorInactiveStyle, diff --git a/addons/xterm-addon-webgl/src/WebglUtils.ts b/addons/addon-webgl/src/WebglUtils.ts similarity index 100% rename from addons/xterm-addon-webgl/src/WebglUtils.ts rename to addons/addon-webgl/src/WebglUtils.ts diff --git a/addons/xterm-addon-webgl/src/renderLayer/BaseRenderLayer.ts b/addons/addon-webgl/src/renderLayer/BaseRenderLayer.ts similarity index 98% rename from addons/xterm-addon-webgl/src/renderLayer/BaseRenderLayer.ts rename to addons/addon-webgl/src/renderLayer/BaseRenderLayer.ts index 3aaac435be..93e0fcb1ad 100644 --- a/addons/xterm-addon-webgl/src/renderLayer/BaseRenderLayer.ts +++ b/addons/addon-webgl/src/renderLayer/BaseRenderLayer.ts @@ -12,7 +12,7 @@ import { ICoreBrowserService, IThemeService } from 'browser/services/Services'; import { Disposable, toDisposable } from 'common/Lifecycle'; import { CellData } from 'common/buffer/CellData'; import { IOptionsService } from 'common/services/Services'; -import { Terminal } from 'xterm'; +import { Terminal } from '@xterm/xterm'; import { IRenderLayer } from './Types'; export abstract class BaseRenderLayer extends Disposable implements IRenderLayer { @@ -38,7 +38,7 @@ export abstract class BaseRenderLayer extends Disposable implements IRenderLayer protected readonly _themeService: IThemeService ) { super(); - this._canvas = document.createElement('canvas'); + this._canvas = this._coreBrowserService.mainDocument.createElement('canvas'); this._canvas.classList.add(`xterm-${id}-layer`); this._canvas.style.zIndex = zIndex.toString(); this._initCanvas(); diff --git a/addons/xterm-addon-webgl/src/renderLayer/LinkRenderLayer.ts b/addons/addon-webgl/src/renderLayer/LinkRenderLayer.ts similarity index 98% rename from addons/xterm-addon-webgl/src/renderLayer/LinkRenderLayer.ts rename to addons/addon-webgl/src/renderLayer/LinkRenderLayer.ts index aefc9f6ed9..0aaf5e70e3 100644 --- a/addons/xterm-addon-webgl/src/renderLayer/LinkRenderLayer.ts +++ b/addons/addon-webgl/src/renderLayer/LinkRenderLayer.ts @@ -9,7 +9,7 @@ import { IRenderDimensions } from 'browser/renderer/shared/Types'; import { ICoreBrowserService, IThemeService } from 'browser/services/Services'; import { ILinkifier2, ILinkifierEvent } from 'browser/Types'; import { IOptionsService } from 'common/services/Services'; -import { Terminal } from 'xterm'; +import { Terminal } from '@xterm/xterm'; import { BaseRenderLayer } from './BaseRenderLayer'; export class LinkRenderLayer extends BaseRenderLayer { diff --git a/addons/xterm-addon-webgl/src/renderLayer/Types.ts b/addons/addon-webgl/src/renderLayer/Types.ts similarity index 96% rename from addons/xterm-addon-webgl/src/renderLayer/Types.ts rename to addons/addon-webgl/src/renderLayer/Types.ts index 3dbdfd9c53..feeceb145b 100644 --- a/addons/xterm-addon-webgl/src/renderLayer/Types.ts +++ b/addons/addon-webgl/src/renderLayer/Types.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { IDisposable, Terminal } from 'xterm'; +import { IDisposable, Terminal } from '@xterm/xterm'; import { IRenderDimensions } from 'browser/renderer/shared/Types'; export interface IRenderLayer extends IDisposable { diff --git a/addons/xterm-addon-webgl/src/tsconfig.json b/addons/addon-webgl/src/tsconfig.json similarity index 90% rename from addons/xterm-addon-webgl/src/tsconfig.json rename to addons/addon-webgl/src/tsconfig.json index 4d4194db45..924d3762d5 100644 --- a/addons/xterm-addon-webgl/src/tsconfig.json +++ b/addons/addon-webgl/src/tsconfig.json @@ -17,6 +17,9 @@ ], "browser/*": [ "../../../src/browser/*" + ], + "@xterm/addon-webgl": [ + "../typings/addon-webgl.d.ts" ] }, "strict": true, diff --git a/addons/xterm-addon-webgl/test/WebglRenderer.test.ts b/addons/addon-webgl/test/WebglRenderer.test.ts similarity index 100% rename from addons/xterm-addon-webgl/test/WebglRenderer.test.ts rename to addons/addon-webgl/test/WebglRenderer.test.ts diff --git a/addons/xterm-addon-webgl/test/playwright.config.ts b/addons/addon-webgl/test/playwright.config.ts similarity index 100% rename from addons/xterm-addon-webgl/test/playwright.config.ts rename to addons/addon-webgl/test/playwright.config.ts diff --git a/addons/xterm-addon-webgl/test/tsconfig.json b/addons/addon-webgl/test/tsconfig.json similarity index 100% rename from addons/xterm-addon-webgl/test/tsconfig.json rename to addons/addon-webgl/test/tsconfig.json diff --git a/addons/xterm-addon-webgl/tsconfig.json b/addons/addon-webgl/tsconfig.json similarity index 100% rename from addons/xterm-addon-webgl/tsconfig.json rename to addons/addon-webgl/tsconfig.json diff --git a/addons/xterm-addon-webgl/typings/xterm-addon-webgl.d.ts b/addons/addon-webgl/typings/addon-webgl.d.ts similarity index 91% rename from addons/xterm-addon-webgl/typings/xterm-addon-webgl.d.ts rename to addons/addon-webgl/typings/addon-webgl.d.ts index 79108e0de0..8c5604210a 100644 --- a/addons/xterm-addon-webgl/typings/xterm-addon-webgl.d.ts +++ b/addons/addon-webgl/typings/addon-webgl.d.ts @@ -3,9 +3,9 @@ * @license MIT */ -import { Terminal, ITerminalAddon, IEvent } from 'xterm'; +import { Terminal, ITerminalAddon, IEvent } from '@xterm/xterm'; -declare module 'xterm-addon-webgl' { +declare module '@xterm/addon-webgl' { /** * An xterm.js addon that provides search functionality. */ diff --git a/addons/xterm-addon-webgl/webpack.config.js b/addons/addon-webgl/webpack.config.js similarity index 94% rename from addons/xterm-addon-webgl/webpack.config.js rename to addons/addon-webgl/webpack.config.js index 578b110263..f31ffd513e 100644 --- a/addons/xterm-addon-webgl/webpack.config.js +++ b/addons/addon-webgl/webpack.config.js @@ -6,7 +6,7 @@ const path = require('path'); const addonName = 'WebglAddon'; -const mainFile = 'xterm-addon-webgl.js'; +const mainFile = 'addon-webgl.js'; module.exports = { entry: `./out/${addonName}.js`, diff --git a/addons/xterm-addon-canvas/README.md b/addons/xterm-addon-canvas/README.md deleted file mode 100644 index bffac96ed9..0000000000 --- a/addons/xterm-addon-canvas/README.md +++ /dev/null @@ -1,28 +0,0 @@ -## xterm-addon-canvas - -An addon for [xterm.js](https://github.com/xtermjs/xterm.js) that enables a canvas-based renderer using a 2d context to draw. This addon requires xterm.js v5+. - -The purpose of this addon is to be used as a fallback for the [webgl addon](https://www.npmjs.com/package/xterm-addon-webgl) when better performance is desired over the default DOM renderer, but WebGL2 isn't supported or performant for some reason. - -### Install - -```bash -npm install --save xterm-addon-canvas -``` - -### Usage - -```ts -import { Terminal } from 'xterm'; -import { CanvasAddon } from 'xterm-addon-canvas'; - -const terminal = new Terminal(); -terminal.open(element); -terminal.loadAddon(new CanvasAddon()); -``` - -See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/xterm-addon-canvas/typings/xterm-addon-canvas.d.ts) for more advanced usage. - -### See also - -- [xterm-addon-webgl](https://www.npmjs.com/package/xterm-addon-webgl) A renderer for xterm.js that uses WebGL diff --git a/bin/package_headless.js b/bin/package_headless.js index d002a95ecd..6f891f05c9 100644 --- a/bin/package_headless.js +++ b/bin/package_headless.js @@ -14,7 +14,7 @@ console.log('> headless/package.json'); const xtermPackageJson = require('../package.json'); const xtermHeadlessPackageJson = { ...xtermPackageJson, - name: 'xterm-headless', + name: '@xterm/headless', description: 'A headless terminal component that runs in Node.js', main: 'lib-headless/xterm-headless.js', types: 'typings/xterm-headless.d.ts', diff --git a/bin/publish.js b/bin/publish.js index e9c7c3e810..360e09fe6e 100644 --- a/bin/publish.js +++ b/bin/publish.js @@ -27,16 +27,17 @@ if (changedFiles.some(e => e.search(/^addons\//) === -1)) { // Publish addons if any files were changed inside of the addon const addonPackageDirs = [ - path.resolve(__dirname, '../addons/xterm-addon-attach'), - path.resolve(__dirname, '../addons/xterm-addon-canvas'), - path.resolve(__dirname, '../addons/xterm-addon-fit'), - // path.resolve(__dirname, '../addons/xterm-addon-image'), - path.resolve(__dirname, '../addons/xterm-addon-ligatures'), - path.resolve(__dirname, '../addons/xterm-addon-search'), - path.resolve(__dirname, '../addons/xterm-addon-serialize'), - path.resolve(__dirname, '../addons/xterm-addon-unicode11'), - path.resolve(__dirname, '../addons/xterm-addon-web-links'), - path.resolve(__dirname, '../addons/xterm-addon-webgl') + path.resolve(__dirname, '../addons/addon-attach'), + path.resolve(__dirname, '../addons/addon-canvas'), + path.resolve(__dirname, '../addons/addon-fit'), + path.resolve(__dirname, '../addons/addon-image'), + path.resolve(__dirname, '../addons/addon-ligatures'), + path.resolve(__dirname, '../addons/addon-search'), + path.resolve(__dirname, '../addons/addon-serialize'), + path.resolve(__dirname, '../addons/addon-unicode11'), + // path.resolve(__dirname, '../addons/addon-unicode-graphemes'), + path.resolve(__dirname, '../addons/addon-web-links'), + path.resolve(__dirname, '../addons/addon-webgl') ]; console.log(`Checking if addons need to be published`); for (const p of addonPackageDirs) { @@ -56,8 +57,9 @@ function checkAndPublishPackage(packageDir) { const packageJson = require(path.join(packageDir, 'package.json')); // Determine if this is a stable or beta release - const publishedVersions = getPublishedVersions(packageJson); - const isStableRelease = !publishedVersions.includes(packageJson.version); + // TODO: Uncomment when publishing 5.4 + // const publishedVersions = getPublishedVersions(packageJson); + const isStableRelease = false; //!publishedVersions.includes(packageJson.version); // Get the next version let nextVersion = isStableRelease ? packageJson.version : getNextBetaVersion(packageJson); @@ -70,7 +72,7 @@ function checkAndPublishPackage(packageDir) { fs.writeFileSync(packageJsonFile, JSON.stringify(packageJson, null, 2)); // Publish - const args = ['publish']; + const args = ['publish', '--access', 'public']; if (!isStableRelease) { args.push('--tag', 'beta'); } @@ -94,8 +96,7 @@ function checkAndPublishPackage(packageDir) { function getNextBetaVersion(packageJson) { if (!/^\d+\.\d+\.\d+$/.exec(packageJson.version)) { - console.error('The package.json version must be of the form x.y.z'); - process.exit(1); + throw new Error('The package.json version must be of the form x.y.z'); } const tag = 'beta'; const stableVersion = packageJson.version.split('.'); @@ -113,9 +114,30 @@ function getNextBetaVersion(packageJson) { return `${nextStableVersion}-${tag}.${latestTagVersion + 1}`; } +function asArray(value) { + return Array.isArray(value) ? value : [value]; +} + function getPublishedVersions(packageJson, version, tag) { - const versionsProcess = cp.spawnSync('npm', ['view', packageJson.name, 'versions', '--json']); - const versionsJson = JSON.parse(versionsProcess.stdout); + const versionsProcess = cp.spawnSync(os.platform === 'win32' ? 'npm.cmd' : 'npm', ['view', packageJson.name, 'versions', '--json']); + if (versionsProcess.stdout.length === 0 && versionsProcess.stderr) { + const err = versionsProcess.stderr.toString(); + if (err.indexOf('404 Not Found - GET https://registry.npmjs.org/@xterm') > 0) { + return []; + } + throw new Error('Could not get published versions\n' + err); + } + const output = JSON.parse(versionsProcess.stdout); + if (typeof output === 'object' && !Array.isArray(output)) { + if (output.error?.code === 'E404') { + return []; + } + throw new Error('Could not get published versions\n' + output); + } + if (!output || Array.isArray(output) && output.length === 0) { + return []; + } + const versionsJson = asArray(output); if (tag) { return versionsJson.filter(v => !v.search(new RegExp(`${version}-${tag}.[0-9]+`))); } diff --git a/bin/test_playwright.js b/bin/test_playwright.js index 02c2a76327..0cd6f85cf6 100644 --- a/bin/test_playwright.js +++ b/bin/test_playwright.js @@ -19,8 +19,8 @@ while (argv.some(e => e.startsWith('--suite='))) { let configs = [ { name: 'core', path: 'out-test/playwright/playwright.config.js' }, - { name: 'xterm-addon-canvas', path: 'addons/xterm-addon-canvas/out-test/playwright.config.js' }, - { name: 'xterm-addon-webgl', path: 'addons/xterm-addon-webgl/out-test/playwright.config.js' } + { name: 'addon-canvas', path: 'addons/addon-canvas/out-test/playwright.config.js' }, + { name: 'addon-webgl', path: 'addons/addon-webgl/out-test/playwright.config.js' } ]; if (suiteFilter) { diff --git a/demo/client.ts b/demo/client.ts index a1145ab9a8..7e0830a583 100644 --- a/demo/client.ts +++ b/demo/client.ts @@ -10,41 +10,41 @@ // Use tsc version (yarn watch) import { Terminal } from '../out/browser/public/Terminal'; -import { AttachAddon } from '../addons/xterm-addon-attach/out/AttachAddon'; -import { CanvasAddon } from '../addons/xterm-addon-canvas/out/CanvasAddon'; -import { FitAddon } from '../addons/xterm-addon-fit/out/FitAddon'; -import { SearchAddon, ISearchOptions } from '../addons/xterm-addon-search/out/SearchAddon'; -import { SerializeAddon } from '../addons/xterm-addon-serialize/out/SerializeAddon'; -import { WebLinksAddon } from '../addons/xterm-addon-web-links/out/WebLinksAddon'; -import { WebglAddon } from '../addons/xterm-addon-webgl/out/WebglAddon'; -import { Unicode11Addon } from '../addons/xterm-addon-unicode11/out/Unicode11Addon'; -import { UnicodeGraphemesAddon } from '../addons/xterm-addon-unicode-graphemes/out/UnicodeGraphemesAddon'; -import { LigaturesAddon } from '../addons/xterm-addon-ligatures/out/LigaturesAddon'; +import { AttachAddon } from '../addons/addon-attach/out/AttachAddon'; +import { CanvasAddon } from '../addons/addon-canvas/out/CanvasAddon'; +import { FitAddon } from '../addons/addon-fit/out/FitAddon'; +import { SearchAddon, ISearchOptions } from '../addons/addon-search/out/SearchAddon'; +import { SerializeAddon } from '../addons/addon-serialize/out/SerializeAddon'; +import { WebLinksAddon } from '../addons/addon-web-links/out/WebLinksAddon'; +import { WebglAddon } from '../addons/addon-webgl/out/WebglAddon'; +import { Unicode11Addon } from '../addons/addon-unicode11/out/Unicode11Addon'; +import { UnicodeGraphemesAddon } from '../addons/addon-unicode-graphemes/out/UnicodeGraphemesAddon'; +import { LigaturesAddon } from '../addons/addon-ligatures/out/LigaturesAddon'; // Playwright/WebKit on Windows does not support WebAssembly https://stackoverflow.com/q/62311688/1156119 -import type { ImageAddonType, IImageAddonOptions } from '../addons/xterm-addon-image/out/ImageAddon'; +import type { ImageAddonType, IImageAddonOptions } from '../addons/addon-image/out/ImageAddon'; let ImageAddon: ImageAddonType | undefined; // eslint-disable-line @typescript-eslint/naming-convention if ('WebAssembly' in window) { - const imageAddon = require('../addons/xterm-addon-image/out/ImageAddon'); + const imageAddon = require('../addons/addon-image/out/ImageAddon'); ImageAddon = imageAddon.ImageAddon; } // Use webpacked version (yarn package) // import { Terminal } from '../lib/xterm'; -// import { AttachAddon } from 'xterm-addon-attach'; -// import { FitAddon } from 'xterm-addon-fit'; -// import { ImageAddon } from 'xterm-addon-image'; -// import { SearchAddon, ISearchOptions } from 'xterm-addon-search'; -// import { SerializeAddon } from 'xterm-addon-serialize'; -// import { WebLinksAddon } from 'xterm-addon-web-links'; -// import { WebglAddon } from 'xterm-addon-webgl'; -// import { Unicode11Addon } from 'xterm-addon-unicode11'; -// import { UnicodeGraphemesAddon } from 'xterm-addon-unicode-graphemes'; -// import { LigaturesAddon } from 'xterm-addon-ligatures'; +// import { AttachAddon } from '@xterm/addon-attach'; +// import { FitAddon } from '@xterm/addon-fit'; +// import { ImageAddon } from '@xterm/addon-image'; +// import { SearchAddon, ISearchOptions } from '@xterm/addon-search'; +// import { SerializeAddon } from '@xterm/addon-serialize'; +// import { WebLinksAddon } from '@xterm/addon-web-links'; +// import { WebglAddon } from '@@xterm/addon-webgl'; +// import { Unicode11Addon } from '@xterm/addon-unicode11'; +// import { UnicodeGraphemesAddon } from '@xterm/addon-unicode-graphemes'; +// import { LigaturesAddon } from '@xterm/addon-ligatures'; // Pulling in the module's types relies on the above, it's looks a // little weird here as we're importing "this" module -import { Terminal as TerminalType, ITerminalOptions } from 'xterm'; +import { Terminal as TerminalType, ITerminalOptions } from '@xterm/xterm'; export interface IWindowWithTerminal extends Window { term: TerminalType; diff --git a/demo/tsconfig.json b/demo/tsconfig.json index f728f20e9c..f0aebb1f3b 100644 --- a/demo/tsconfig.json +++ b/demo/tsconfig.json @@ -6,13 +6,13 @@ "sourceMap": true, "baseUrl": ".", "paths": { - "xterm-addon-attach": ["../addons/xterm-addon-attach"], - "xterm-addon-fit": ["../addons/xterm-addon-fit"], - "xterm-addon-image": ["../addons/xterm-addon-image"], - "xterm-addon-search": ["../addons/xterm-addon-search"], - "xterm-addon-serialize": ["../addons/xterm-addon-serialize"], - "xterm-addon-web-links": ["../addons/xterm-addon-web-links"], - "xterm-addon-webgl": ["../addons/xterm-addon-webgl"] + "addon-attach": ["../addons/addon-attach"], + "addon-fit": ["../addons/addon-fit"], + "addon-image": ["../addons/addon-image"], + "addon-search": ["../addons/addon-search"], + "addon-serialize": ["../addons/addon-serialize"], + "addon-web-links": ["../addons/addon-web-links"], + "addon-webgl": ["../addons/addon-webgl"] } }, "include": [ diff --git a/headless/README.md b/headless/README.md index 1d2d61568c..205fd79c55 100644 --- a/headless/README.md +++ b/headless/README.md @@ -15,7 +15,7 @@ npm install xterm-headless Then import as you would a regular node package. The recommended way to load `xterm-headless` is with TypeScript and the ES6 module syntax: ```javascript -import { Terminal } from 'xterm-headless'; +import { Terminal } from '@xterm/headless'; ``` ## API diff --git a/package.json b/package.json index 70e0f4a961..d0510e5d1a 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "xterm", + "name": "@xterm/xterm", "description": "Full xterm terminal, in your browser", "version": "5.3.0", "main": "lib/xterm.js", diff --git a/src/browser/AccessibilityManager.ts b/src/browser/AccessibilityManager.ts index 1b964d1bbe..68c65ebd87 100644 --- a/src/browser/AccessibilityManager.ts +++ b/src/browser/AccessibilityManager.ts @@ -7,10 +7,10 @@ import * as Strings from 'browser/LocalizableStrings'; import { ITerminal, IRenderDebouncer } from 'browser/Types'; import { TimeBasedDebouncer } from 'browser/TimeBasedDebouncer'; import { Disposable, toDisposable } from 'common/Lifecycle'; -import { ScreenDprMonitor } from 'browser/ScreenDprMonitor'; -import { IRenderService } from 'browser/services/Services'; -import { addDisposableDomListener } from 'browser/Lifecycle'; +import { ICoreBrowserService, IRenderService } from 'browser/services/Services'; import { IBuffer } from 'common/buffer/Types'; +import { IInstantiationService } from 'common/services/Services'; +import { addDisposableDomListener } from 'browser/Lifecycle'; const MAX_ROWS_TO_READ = 20; @@ -35,8 +35,6 @@ export class AccessibilityManager extends Disposable { private _liveRegionLineCount: number = 0; private _liveRegionDebouncer: IRenderDebouncer; - private _screenDprMonitor: ScreenDprMonitor; - private _topBoundaryFocusListener: (e: FocusEvent) => void; private _bottomBoundaryFocusListener: (e: FocusEvent) => void; @@ -55,13 +53,15 @@ export class AccessibilityManager extends Disposable { constructor( private readonly _terminal: ITerminal, + @IInstantiationService instantiationService: IInstantiationService, + @ICoreBrowserService private readonly _coreBrowserService: ICoreBrowserService, @IRenderService private readonly _renderService: IRenderService ) { super(); - this._accessibilityContainer = document.createElement('div'); + this._accessibilityContainer = this._coreBrowserService.mainDocument.createElement('div'); this._accessibilityContainer.classList.add('xterm-accessibility'); - this._rowContainer = document.createElement('div'); + this._rowContainer = this._coreBrowserService.mainDocument.createElement('div'); this._rowContainer.setAttribute('role', 'list'); this._rowContainer.classList.add('xterm-accessibility-tree'); this._rowElements = []; @@ -78,7 +78,7 @@ export class AccessibilityManager extends Disposable { this._refreshRowsDimensions(); this._accessibilityContainer.appendChild(this._rowContainer); - this._liveRegion = document.createElement('div'); + this._liveRegion = this._coreBrowserService.mainDocument.createElement('div'); this._liveRegion.classList.add('live-region'); this._liveRegion.setAttribute('aria-live', 'assertive'); this._accessibilityContainer.appendChild(this._liveRegion); @@ -116,13 +116,7 @@ export class AccessibilityManager extends Disposable { this.register(this._terminal.onBlur(() => this._clearLiveRegion())); this.register(this._renderService.onDimensionsChange(() => this._refreshRowsDimensions())); this.register(addDisposableDomListener(document, 'selectionchange', () => this._handleSelectionChange())); - - this._screenDprMonitor = new ScreenDprMonitor(window); - this.register(this._screenDprMonitor); - this._screenDprMonitor.setListener(() => this._refreshRowsDimensions()); - // This shouldn't be needed on modern browsers but is present in case the - // media query that drives the ScreenDprMonitor isn't supported - this.register(addDisposableDomListener(window, 'resize', () => this._refreshRowsDimensions())); + this.register(this._coreBrowserService.onDprChange(() => this._refreshRowsDimensions())); this._refreshRows(); this.register(toDisposable(() => { @@ -389,7 +383,7 @@ export class AccessibilityManager extends Disposable { } private _createAccessibilityTreeNode(): HTMLElement { - const element = document.createElement('div'); + const element = this._coreBrowserService.mainDocument.createElement('div'); element.setAttribute('role', 'listitem'); element.tabIndex = -1; this._refreshRowDimensions(element); diff --git a/src/browser/ScreenDprMonitor.ts b/src/browser/ScreenDprMonitor.ts deleted file mode 100644 index 1c3f31b753..0000000000 --- a/src/browser/ScreenDprMonitor.ts +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Copyright (c) 2017 The xterm.js authors. All rights reserved. - * @license MIT - */ - -import { Disposable, toDisposable } from 'common/Lifecycle'; - -export type ScreenDprListener = (newDevicePixelRatio?: number, oldDevicePixelRatio?: number) => void; - -/** - * The screen device pixel ratio monitor allows listening for when the - * window.devicePixelRatio value changes. This is done not with polling but with - * the use of window.matchMedia to watch media queries. When the event fires, - * the listener will be reattached using a different media query to ensure that - * any further changes will register. - * - * The listener should fire on both window zoom changes and switching to a - * monitor with a different DPI. - */ -export class ScreenDprMonitor extends Disposable { - private _currentDevicePixelRatio: number; - private _outerListener: ((this: MediaQueryList, ev: MediaQueryListEvent) => any) | undefined; - private _listener: ScreenDprListener | undefined; - private _resolutionMediaMatchList: MediaQueryList | undefined; - - constructor(private _parentWindow: Window) { - super(); - this._currentDevicePixelRatio = this._parentWindow.devicePixelRatio; - this.register(toDisposable(() => { - this.clearListener(); - })); - } - - public setListener(listener: ScreenDprListener): void { - if (this._listener) { - this.clearListener(); - } - this._listener = listener; - this._outerListener = () => { - if (!this._listener) { - return; - } - this._listener(this._parentWindow.devicePixelRatio, this._currentDevicePixelRatio); - this._updateDpr(); - }; - this._updateDpr(); - } - - private _updateDpr(): void { - if (!this._outerListener) { - return; - } - - // Clear listeners for old DPR - this._resolutionMediaMatchList?.removeListener(this._outerListener); - - // Add listeners for new DPR - this._currentDevicePixelRatio = this._parentWindow.devicePixelRatio; - this._resolutionMediaMatchList = this._parentWindow.matchMedia(`screen and (resolution: ${this._parentWindow.devicePixelRatio}dppx)`); - this._resolutionMediaMatchList.addListener(this._outerListener); - } - - public clearListener(): void { - if (!this._resolutionMediaMatchList || !this._listener || !this._outerListener) { - return; - } - this._resolutionMediaMatchList.removeListener(this._outerListener); - this._resolutionMediaMatchList = undefined; - this._listener = undefined; - this._outerListener = undefined; - } -} diff --git a/src/browser/Terminal.ts b/src/browser/Terminal.ts index 18af3e4e2a..fad2d80b83 100644 --- a/src/browser/Terminal.ts +++ b/src/browser/Terminal.ts @@ -54,13 +54,10 @@ import { evaluateKeyboardEvent } from 'common/input/Keyboard'; import { toRgbString } from 'common/input/XParseColor'; import { DecorationService } from 'common/services/DecorationService'; import { IDecorationService } from 'common/services/Services'; -import { IDecoration, IDecorationOptions, IDisposable, ILinkProvider, IMarker } from 'xterm'; +import { IDecoration, IDecorationOptions, IDisposable, ILinkProvider, IMarker } from '@xterm/xterm'; import { WindowsOptionsReportType } from '../common/InputHandler'; import { AccessibilityManager } from './AccessibilityManager'; -// Let it work inside Node.js for automated testing purposes. -const document: Document = (typeof window !== 'undefined') ? window.document : null as any; - export class Terminal extends CoreTerminal implements ITerminal { public textarea: HTMLTextAreaElement | undefined; public element: HTMLElement | undefined; @@ -397,7 +394,19 @@ export class Terminal extends CoreTerminal implements ITerminal { this._logService.debug('Terminal.open was called on an element that was not attached to the DOM'); } - this._document = parent.ownerDocument!; + // If the terminal is already opened + if (this.element?.ownerDocument.defaultView && this._coreBrowserService) { + // Adjust the window if needed + if (this.element.ownerDocument.defaultView !== this._coreBrowserService.window) { + this._coreBrowserService.window = this.element.ownerDocument.defaultView; + } + return; + } + + this._document = parent.ownerDocument; + if (this.options.documentOverride && this.options.documentOverride instanceof Document) { + this._document = this.optionsService.rawOptions.documentOverride as Document; + } // Create main element container this.element = this._document.createElement('div'); @@ -408,25 +417,25 @@ export class Terminal extends CoreTerminal implements ITerminal { // Performance: Use a document fragment to build the terminal // viewport and helper elements detached from the DOM - const fragment = document.createDocumentFragment(); - this._viewportElement = document.createElement('div'); + const fragment = this._document.createDocumentFragment(); + this._viewportElement = this._document.createElement('div'); this._viewportElement.classList.add('xterm-viewport'); fragment.appendChild(this._viewportElement); - this._viewportScrollArea = document.createElement('div'); + this._viewportScrollArea = this._document.createElement('div'); this._viewportScrollArea.classList.add('xterm-scroll-area'); this._viewportElement.appendChild(this._viewportScrollArea); - this.screenElement = document.createElement('div'); + this.screenElement = this._document.createElement('div'); this.screenElement.classList.add('xterm-screen'); // Create the container that will hold helpers like the textarea for // capturing DOM Events. Then produce the helpers. - this._helperContainer = document.createElement('div'); + this._helperContainer = this._document.createElement('div'); this._helperContainer.classList.add('xterm-helpers'); this.screenElement.appendChild(this._helperContainer); fragment.appendChild(this.screenElement); - this.textarea = document.createElement('textarea'); + this.textarea = this._document.createElement('textarea'); this.textarea.classList.add('xterm-helper-textarea'); this.textarea.setAttribute('aria-label', Strings.promptLabel); if (!Browser.isChromeOS) { @@ -441,7 +450,12 @@ export class Terminal extends CoreTerminal implements ITerminal { // Register the core browser service before the generic textarea handlers are registered so it // handles them first. Otherwise the renderers may use the wrong focus state. - this._coreBrowserService = this._instantiationService.createInstance(CoreBrowserService, this.textarea, this._document.defaultView ?? window); + this._coreBrowserService = this.register(this._instantiationService.createInstance(CoreBrowserService, + this.textarea, + parent.ownerDocument.defaultView ?? window, + // Force unsafe null in node.js environment for tests + this._document ?? (typeof window !== 'undefined') ? window.document : null as any + )); this._instantiationService.setService(ICoreBrowserService, this._coreBrowserService); this.register(addDisposableDomListener(this.textarea, 'focus', (ev: KeyboardEvent) => this._handleTextAreaFocus(ev))); @@ -463,7 +477,7 @@ export class Terminal extends CoreTerminal implements ITerminal { this.register(this._renderService.onRenderedViewportChange(e => this._onRender.fire(e))); this.onResize(e => this._renderService!.resize(e.cols, e.rows)); - this._compositionView = document.createElement('div'); + this._compositionView = this._document.createElement('div'); this._compositionView.classList.add('composition-view'); this._compositionHelper = this._instantiationService.createInstance(CompositionHelper, this.textarea, this._compositionView); this._helperContainer.appendChild(this._compositionView); @@ -561,7 +575,7 @@ export class Terminal extends CoreTerminal implements ITerminal { } private _createRenderer(): IRenderer { - return this._instantiationService.createInstance(DomRenderer, this._document!, this.element!, this.screenElement!, this._viewportElement!, this._helperContainer!, this.linkifier2); + return this._instantiationService.createInstance(DomRenderer, this, this._document!, this.element!, this.screenElement!, this._viewportElement!, this._helperContainer!, this.linkifier2); } /** diff --git a/src/browser/Terminal2.test.ts b/src/browser/Terminal2.test.ts index 4965e8f361..abbb42d3cd 100644 --- a/src/browser/Terminal2.test.ts +++ b/src/browser/Terminal2.test.ts @@ -9,7 +9,7 @@ import * as os from 'os'; import * as fs from 'fs'; import * as pty from 'node-pty'; import { Terminal } from 'browser/Terminal'; -import { IDisposable } from 'xterm'; +import { IDisposable } from '@xterm/xterm'; // all test files expect terminal in 80x25 const COLS = 80; diff --git a/src/browser/TestUtils.test.ts b/src/browser/TestUtils.test.ts index 7b464a3387..7e43017a0c 100644 --- a/src/browser/TestUtils.test.ts +++ b/src/browser/TestUtils.test.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { IDisposable, IMarker, ILinkProvider, IDecorationOptions, IDecoration } from 'xterm'; +import { IDisposable, IMarker, ILinkProvider, IDecorationOptions, IDecoration } from '@xterm/xterm'; import { IEvent, EventEmitter } from 'common/EventEmitter'; import { ICharacterJoinerService, ICharSizeService, ICoreBrowserService, IMouseService, IRenderService, ISelectionService, IThemeService } from 'browser/services/Services'; import { IRenderDimensions, IRenderer, IRequestRedrawEvent } from 'browser/renderer/shared/Types'; @@ -350,11 +350,16 @@ export class MockCompositionHelper implements ICompositionHelper { } export class MockCoreBrowserService implements ICoreBrowserService { + public onDprChange = new EventEmitter().event; + public onWindowChange = new EventEmitter().event; public serviceBrand: undefined; public isFocused: boolean = true; public get window(): Window & typeof globalThis { throw Error('Window object not available in tests'); } + public get mainDocument(): Document { + throw Error('Document object not available in tests'); + } public dpr: number = 1; } diff --git a/src/browser/Types.d.ts b/src/browser/Types.d.ts index f2b5e220f4..b1f31b205b 100644 --- a/src/browser/Types.d.ts +++ b/src/browser/Types.d.ts @@ -6,7 +6,7 @@ import { IEvent } from 'common/EventEmitter'; import { CharData, IColor, ICoreTerminal, ITerminalOptions } from 'common/Types'; import { IBuffer } from 'common/buffer/Types'; -import { IDisposable, Terminal as ITerminalApi } from 'xterm'; +import { IDisposable, Terminal as ITerminalApi } from '@xterm/xterm'; import { IMouseService, IRenderService } from './services/Services'; /** diff --git a/src/browser/decorations/BufferDecorationRenderer.ts b/src/browser/decorations/BufferDecorationRenderer.ts index ba4f6ca8f1..6ba9ae1ece 100644 --- a/src/browser/decorations/BufferDecorationRenderer.ts +++ b/src/browser/decorations/BufferDecorationRenderer.ts @@ -3,8 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { addDisposableDomListener } from 'browser/Lifecycle'; -import { IRenderService } from 'browser/services/Services'; +import { ICoreBrowserService, IRenderService } from 'browser/services/Services'; import { Disposable, toDisposable } from 'common/Lifecycle'; import { IBufferService, IDecorationService, IInternalDecoration } from 'common/services/Services'; @@ -19,6 +18,7 @@ export class BufferDecorationRenderer extends Disposable { constructor( private readonly _screenElement: HTMLElement, @IBufferService private readonly _bufferService: IBufferService, + @ICoreBrowserService private readonly _coreBrowserService: ICoreBrowserService, @IDecorationService private readonly _decorationService: IDecorationService, @IRenderService private readonly _renderService: IRenderService ) { @@ -33,7 +33,7 @@ export class BufferDecorationRenderer extends Disposable { this._dimensionsChanged = true; this._queueRefresh(); })); - this.register(addDisposableDomListener(window, 'resize', () => this._queueRefresh())); + this.register(this._coreBrowserService.onDprChange(() => this._queueRefresh())); this.register(this._bufferService.buffers.onBufferActivate(() => { this._altBufferIsActive = this._bufferService.buffer === this._bufferService.buffers.alt; })); @@ -70,7 +70,7 @@ export class BufferDecorationRenderer extends Disposable { } private _createElement(decoration: IInternalDecoration): HTMLElement { - const element = document.createElement('div'); + const element = this._coreBrowserService.mainDocument.createElement('div'); element.classList.add('xterm-decoration'); element.classList.toggle('xterm-decoration-top-layer', decoration?.options?.layer === 'top'); element.style.width = `${Math.round((decoration.options.width || 1) * this._renderService.dimensions.css.cell.width)}px`; diff --git a/src/browser/decorations/OverviewRulerRenderer.ts b/src/browser/decorations/OverviewRulerRenderer.ts index d57653859e..103d5d9a61 100644 --- a/src/browser/decorations/OverviewRulerRenderer.ts +++ b/src/browser/decorations/OverviewRulerRenderer.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { ColorZoneStore, IColorZone, IColorZoneStore } from 'browser/decorations/ColorZoneStore'; -import { addDisposableDomListener } from 'browser/Lifecycle'; import { ICoreBrowserService, IRenderService } from 'browser/services/Services'; import { Disposable, toDisposable } from 'common/Lifecycle'; import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services'; @@ -52,10 +51,10 @@ export class OverviewRulerRenderer extends Disposable { @IDecorationService private readonly _decorationService: IDecorationService, @IRenderService private readonly _renderService: IRenderService, @IOptionsService private readonly _optionsService: IOptionsService, - @ICoreBrowserService private readonly _coreBrowseService: ICoreBrowserService + @ICoreBrowserService private readonly _coreBrowserService: ICoreBrowserService ) { super(); - this._canvas = document.createElement('canvas'); + this._canvas = this._coreBrowserService.mainDocument.createElement('canvas'); this._canvas.classList.add('xterm-decoration-overview-ruler'); this._refreshCanvasDimensions(); this._viewportElement.parentElement?.insertBefore(this._canvas, this._viewportElement); @@ -112,7 +111,7 @@ export class OverviewRulerRenderer extends Disposable { // overview ruler width changed this.register(this._optionsService.onSpecificOptionChange('overviewRulerWidth', () => this._queueRefresh(true))); // device pixel ratio changed - this.register(addDisposableDomListener(this._coreBrowseService.window, 'resize', () => this._queueRefresh(true))); + this.register(this._coreBrowserService.onDprChange(() => this._queueRefresh(true))); // set the canvas dimensions this._queueRefresh(true); } @@ -135,11 +134,11 @@ export class OverviewRulerRenderer extends Disposable { } private _refreshDrawHeightConstants(): void { - drawHeight.full = Math.round(2 * this._coreBrowseService.dpr); + drawHeight.full = Math.round(2 * this._coreBrowserService.dpr); // Calculate actual pixels per line const pixelsPerLine = this._canvas.height / this._bufferService.buffer.lines.length; // Clamp actual pixels within a range - const nonFullHeight = Math.round(Math.max(Math.min(pixelsPerLine, 12), 6) * this._coreBrowseService.dpr); + const nonFullHeight = Math.round(Math.max(Math.min(pixelsPerLine, 12), 6) * this._coreBrowserService.dpr); drawHeight.left = nonFullHeight; drawHeight.center = nonFullHeight; drawHeight.right = nonFullHeight; @@ -157,9 +156,9 @@ export class OverviewRulerRenderer extends Disposable { private _refreshCanvasDimensions(): void { this._canvas.style.width = `${this._width}px`; - this._canvas.width = Math.round(this._width * this._coreBrowseService.dpr); + this._canvas.width = Math.round(this._width * this._coreBrowserService.dpr); this._canvas.style.height = `${this._screenElement.clientHeight}px`; - this._canvas.height = Math.round(this._screenElement.clientHeight * this._coreBrowseService.dpr); + this._canvas.height = Math.round(this._screenElement.clientHeight * this._coreBrowserService.dpr); this._refreshDrawConstants(); this._refreshColorZonePadding(); } @@ -211,7 +210,7 @@ export class OverviewRulerRenderer extends Disposable { if (this._animationFrame !== undefined) { return; } - this._animationFrame = this._coreBrowseService.window.requestAnimationFrame(() => { + this._animationFrame = this._coreBrowserService.window.requestAnimationFrame(() => { this._refreshDecorations(); this._animationFrame = undefined; }); diff --git a/src/browser/public/Terminal.ts b/src/browser/public/Terminal.ts index 2c75d7b808..6f009f74f2 100644 --- a/src/browser/public/Terminal.ts +++ b/src/browser/public/Terminal.ts @@ -13,7 +13,7 @@ import { AddonManager } from 'common/public/AddonManager'; import { BufferNamespaceApi } from 'common/public/BufferNamespaceApi'; import { ParserApi } from 'common/public/ParserApi'; import { UnicodeApi } from 'common/public/UnicodeApi'; -import { IBufferNamespace as IBufferNamespaceApi, IDecoration, IDecorationOptions, IDisposable, ILinkProvider, ILocalizableStrings, IMarker, IModes, IParser, ITerminalAddon, Terminal as ITerminalApi, ITerminalInitOnlyOptions, IUnicodeHandling } from 'xterm'; +import { IBufferNamespace as IBufferNamespaceApi, IDecoration, IDecorationOptions, IDisposable, ILinkProvider, ILocalizableStrings, IMarker, IModes, IParser, ITerminalAddon, Terminal as ITerminalApi, ITerminalInitOnlyOptions, IUnicodeHandling } from '@xterm/xterm'; /** * The set of options that only have an effect when set in the Terminal constructor. diff --git a/src/browser/renderer/dom/DomRenderer.ts b/src/browser/renderer/dom/DomRenderer.ts index 2e9f3701e9..1549b1307c 100644 --- a/src/browser/renderer/dom/DomRenderer.ts +++ b/src/browser/renderer/dom/DomRenderer.ts @@ -7,9 +7,10 @@ import { DomRendererRowFactory, RowCss } from 'browser/renderer/dom/DomRendererR import { WidthCache } from 'browser/renderer/dom/WidthCache'; import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/shared/Constants'; import { createRenderDimensions } from 'browser/renderer/shared/RendererUtils'; -import { IRenderDimensions, IRenderer, IRequestRedrawEvent } from 'browser/renderer/shared/Types'; +import { createSelectionRenderModel } from 'browser/renderer/shared/SelectionRenderModel'; +import { IRenderDimensions, IRenderer, IRequestRedrawEvent, ISelectionRenderModel } from 'browser/renderer/shared/Types'; import { ICharSizeService, ICoreBrowserService, IThemeService } from 'browser/services/Services'; -import { ILinkifier2, ILinkifierEvent, ReadonlyColorSet } from 'browser/Types'; +import { ILinkifier2, ILinkifierEvent, ITerminal, ReadonlyColorSet } from 'browser/Types'; import { color } from 'common/Color'; import { EventEmitter } from 'common/EventEmitter'; import { Disposable, toDisposable } from 'common/Lifecycle'; @@ -25,7 +26,6 @@ const SELECTION_CLASS = 'xterm-selection'; let nextTerminalId = 1; - /** * A fallback renderer for when canvas is slow. This is not meant to be * particularly fast or feature complete, more just stable and usable for when @@ -41,12 +41,14 @@ export class DomRenderer extends Disposable implements IRenderer { private _rowElements: HTMLElement[] = []; private _selectionContainer: HTMLElement; private _widthCache: WidthCache; + private _selectionRenderModel: ISelectionRenderModel = createSelectionRenderModel(); public dimensions: IRenderDimensions; public readonly onRequestRedraw = this.register(new EventEmitter()).event; constructor( + private readonly _terminal: ITerminal, private readonly _document: Document, private readonly _element: HTMLElement, private readonly _screenElement: HTMLElement, @@ -291,6 +293,7 @@ export class DomRenderer extends Disposable implements IRenderer { public handleResize(cols: number, rows: number): void { this._refreshRowElements(cols, rows); this._updateDimensions(); + this.handleSelectionChanged(this._selectionRenderModel.selectionStart, this._selectionRenderModel.selectionEnd, this._selectionRenderModel.columnSelectMode); } public handleCharSizeChanged(): void { @@ -320,11 +323,13 @@ export class DomRenderer extends Disposable implements IRenderer { return; } + this._selectionRenderModel.update(this._terminal, start, end, columnSelectMode); + // Translate from buffer position to viewport position - const viewportStartRow = start[1] - this._bufferService.buffer.ydisp; - const viewportEndRow = end[1] - this._bufferService.buffer.ydisp; - const viewportCappedStartRow = Math.max(viewportStartRow, 0); - const viewportCappedEndRow = Math.min(viewportEndRow, this._bufferService.rows - 1); + const viewportStartRow = this._selectionRenderModel.viewportStartRow; + const viewportEndRow = this._selectionRenderModel.viewportEndRow; + const viewportCappedStartRow = this._selectionRenderModel.viewportCappedStartRow; + const viewportCappedEndRow = this._selectionRenderModel.viewportCappedEndRow; // No need to draw the selection if (viewportCappedStartRow >= this._bufferService.rows || viewportCappedEndRow < 0) { @@ -365,10 +370,16 @@ export class DomRenderer extends Disposable implements IRenderer { */ private _createSelectionElement(row: number, colStart: number, colEnd: number, rowCount: number = 1): HTMLElement { const element = this._document.createElement('div'); + const left = colStart * this.dimensions.css.cell.width; + let width = this.dimensions.css.cell.width * (colEnd - colStart); + if (left + width > this.dimensions.css.canvas.width) { + width = this.dimensions.css.canvas.width - left; + } + element.style.height = `${rowCount * this.dimensions.css.cell.height}px`; element.style.top = `${row * this.dimensions.css.cell.height}px`; - element.style.left = `${colStart * this.dimensions.css.cell.width}px`; - element.style.width = `${this.dimensions.css.cell.width * (colEnd - colStart)}px`; + element.style.left = `${left}px`; + element.style.width = `${width}px`; return element; } diff --git a/src/browser/renderer/shared/CellColorResolver.ts b/src/browser/renderer/shared/CellColorResolver.ts index 66e6a344e0..5837a675b2 100644 --- a/src/browser/renderer/shared/CellColorResolver.ts +++ b/src/browser/renderer/shared/CellColorResolver.ts @@ -1,10 +1,10 @@ import { ISelectionRenderModel } from 'browser/renderer/shared/Types'; import { ICoreBrowserService, IThemeService } from 'browser/services/Services'; import { ReadonlyColorSet } from 'browser/Types'; -import { Attributes, BgFlags, FgFlags } from 'common/buffer/Constants'; -import { IDecorationService } from 'common/services/Services'; +import { Attributes, BgFlags, ExtFlags, FgFlags, NULL_CELL_CODE, UnderlineStyle } from 'common/buffer/Constants'; +import { IDecorationService, IOptionsService } from 'common/services/Services'; import { ICellData } from 'common/Types'; -import { Terminal } from 'xterm'; +import { Terminal } from '@xterm/xterm'; // Work variables to avoid garbage collection let $fg = 0; @@ -13,6 +13,7 @@ let $hasFg = false; let $hasBg = false; let $isSelected = false; let $colors: ReadonlyColorSet | undefined; +let $variantOffset = 0; export class CellColorResolver { /** @@ -27,6 +28,7 @@ export class CellColorResolver { constructor( private readonly _terminal: Terminal, + private readonly _optionService: IOptionsService, private readonly _selectionRenderModel: ISelectionRenderModel, private readonly _decorationService: IDecorationService, private readonly _coreBrowserService: ICoreBrowserService, @@ -38,7 +40,7 @@ export class CellColorResolver { * Resolves colors for the cell, putting the result into the shared {@link result}. This resolves * overrides, inverse and selection for the cell which can then be used to feed into the renderer. */ - public resolve(cell: ICellData, x: number, y: number): void { + public resolve(cell: ICellData, x: number, y: number, deviceCellWidth: number): void { this.result.bg = cell.bg; this.result.fg = cell.fg; this.result.ext = cell.bg & BgFlags.HAS_EXTENDED ? cell.extended.ext : 0; @@ -52,6 +54,13 @@ export class CellColorResolver { $hasFg = false; $isSelected = false; $colors = this._themeService.colors; + $variantOffset = 0; + + const code = cell.getCode(); + if (code !== NULL_CELL_CODE && cell.extended.underlineStyle === UnderlineStyle.DOTTED) { + const lineWidth = Math.max(1, Math.floor(this._optionService.rawOptions.fontSize * this._coreBrowserService.dpr / 15)); + $variantOffset = x * deviceCellWidth % (Math.round(lineWidth) * 2); + } // Apply decorations on the bottom layer this._decorationService.forEachDecorationAtCell(x, y, 'bottom', d => { @@ -133,5 +142,9 @@ export class CellColorResolver { // Use the override if it exists this.result.bg = $hasBg ? $bg : this.result.bg; this.result.fg = $hasFg ? $fg : this.result.fg; + + // Reset overrides variantOffset + this.result.ext &= ~ExtFlags.VARIANT_OFFSET; + this.result.ext |= ($variantOffset << 29) & ExtFlags.VARIANT_OFFSET; } } diff --git a/src/browser/renderer/shared/CharAtlasCache.ts b/src/browser/renderer/shared/CharAtlasCache.ts index 6734391295..0a8714832a 100644 --- a/src/browser/renderer/shared/CharAtlasCache.ts +++ b/src/browser/renderer/shared/CharAtlasCache.ts @@ -4,7 +4,7 @@ */ import { TextureAtlas } from 'browser/renderer/shared/TextureAtlas'; -import { ITerminalOptions, Terminal } from 'xterm'; +import { ITerminalOptions, Terminal } from '@xterm/xterm'; import { ITerminal, ReadonlyColorSet } from 'browser/Types'; import { ICharAtlasConfig, ITextureAtlas } from 'browser/renderer/shared/Types'; import { generateConfig, configEquals } from 'browser/renderer/shared/CharAtlasUtils'; diff --git a/src/browser/renderer/shared/CharAtlasUtils.ts b/src/browser/renderer/shared/CharAtlasUtils.ts index 955bd4e6e2..f8fe9104fb 100644 --- a/src/browser/renderer/shared/CharAtlasUtils.ts +++ b/src/browser/renderer/shared/CharAtlasUtils.ts @@ -5,7 +5,7 @@ import { ICharAtlasConfig } from './Types'; import { Attributes } from 'common/buffer/Constants'; -import { ITerminalOptions } from 'xterm'; +import { ITerminalOptions } from '@xterm/xterm'; import { IColorSet, ReadonlyColorSet } from 'browser/Types'; import { NULL_COLOR } from 'common/Color'; diff --git a/src/browser/renderer/shared/CustomGlyphs.ts b/src/browser/renderer/shared/CustomGlyphs.ts index c08bc4b168..cf6292af47 100644 --- a/src/browser/renderer/shared/CustomGlyphs.ts +++ b/src/browser/renderer/shared/CustomGlyphs.ts @@ -474,7 +474,7 @@ function drawPatternChar( if (!pattern) { const width = charDefinition[0].length; const height = charDefinition.length; - const tmpCanvas = document.createElement('canvas'); + const tmpCanvas = ctx.canvas.ownerDocument.createElement('canvas'); tmpCanvas.width = width; tmpCanvas.height = height; const tmpCtx = throwIfFalsy(tmpCanvas.getContext('2d')); diff --git a/src/browser/renderer/shared/RendererUtils.test.ts b/src/browser/renderer/shared/RendererUtils.test.ts new file mode 100644 index 0000000000..a050e8a94f --- /dev/null +++ b/src/browser/renderer/shared/RendererUtils.test.ts @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2023 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { computeNextVariantOffset } from 'browser/renderer/shared/RendererUtils'; +import { assert } from 'chai'; + +describe('RendererUtils', () => { + it('computeNextVariantOffset', () => { + const cellWidth = 11; + const doubleCellWidth = 22; + let line = 1; + let variantOffset = 0; + + // should line 1 + // =,_,=_,=_, + let cells = [cellWidth, cellWidth, doubleCellWidth, doubleCellWidth]; + let result = [1, 0, 0, 0]; + for (let index = 0; index < cells.length; index++) { + const cell = cells[index]; + variantOffset = computeNextVariantOffset(cell, line, variantOffset); + assert.equal(variantOffset, result[index]); + } + + // should line 2 + // ==__==__==_,_==__==__==,__==__==__==__==__==__,==__==__==__==__==__==, + line = 2; + variantOffset = 0; + cells = [cellWidth, cellWidth, doubleCellWidth, doubleCellWidth]; + result = [3, 2, 0 ,2]; + for (let index = 0; index < cells.length; index++) { + const cell = cells[index]; + variantOffset = computeNextVariantOffset(cell, line, variantOffset); + assert.equal(variantOffset, result[index]); + } + + // should line 3 + // ===___===__,_===___===_,__===___===___===___==,=___===___===___===___, + line = 3; + variantOffset = 0; + cells = [cellWidth, cellWidth, doubleCellWidth, doubleCellWidth]; + result = [5, 4, 2, 0]; + for (let index = 0; index < cells.length; index++) { + const cell = cells[index]; + variantOffset = computeNextVariantOffset(cell, line, variantOffset); + assert.equal(variantOffset, result[index]); + } + }); +}); diff --git a/src/browser/renderer/shared/RendererUtils.ts b/src/browser/renderer/shared/RendererUtils.ts index 70c9ad86ca..59b87b0e30 100644 --- a/src/browser/renderer/shared/RendererUtils.ts +++ b/src/browser/renderer/shared/RendererUtils.ts @@ -56,3 +56,7 @@ function createDimension(): IDimensions { height: 0 }; } + +export function computeNextVariantOffset(cellWidth: number, lineWidth: number, currentOffset: number = 0): number { + return (cellWidth - (Math.round(lineWidth) * 2 - currentOffset)) % (Math.round(lineWidth) * 2); +} diff --git a/src/browser/renderer/shared/SelectionRenderModel.ts b/src/browser/renderer/shared/SelectionRenderModel.ts index db37577885..d3b7a99c46 100644 --- a/src/browser/renderer/shared/SelectionRenderModel.ts +++ b/src/browser/renderer/shared/SelectionRenderModel.ts @@ -3,8 +3,9 @@ * @license MIT */ +import { ITerminal } from 'browser/Types'; import { ISelectionRenderModel } from 'browser/renderer/shared/Types'; -import { Terminal } from 'xterm'; +import { Terminal } from '@xterm/xterm'; class SelectionRenderModel implements ISelectionRenderModel { public hasSelection!: boolean; @@ -35,7 +36,7 @@ class SelectionRenderModel implements ISelectionRenderModel { this.selectionEnd = undefined; } - public update(terminal: Terminal, start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean = false): void { + public update(terminal: ITerminal, start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean = false): void { this.selectionStart = start; this.selectionEnd = end; // Selection does not exist @@ -45,8 +46,9 @@ class SelectionRenderModel implements ISelectionRenderModel { } // Translate from buffer position to viewport position - const viewportStartRow = start[1] - terminal.buffer.active.viewportY; - const viewportEndRow = end[1] - terminal.buffer.active.viewportY; + const viewportY = terminal.buffers.active.ydisp; + const viewportStartRow = start[1] - viewportY; + const viewportEndRow = end[1] - viewportY; const viewportCappedStartRow = Math.max(viewportStartRow, 0); const viewportCappedEndRow = Math.min(viewportEndRow, terminal.rows - 1); diff --git a/src/browser/renderer/shared/TextureAtlas.ts b/src/browser/renderer/shared/TextureAtlas.ts index 56c77b6835..d7f65d0034 100644 --- a/src/browser/renderer/shared/TextureAtlas.ts +++ b/src/browser/renderer/shared/TextureAtlas.ts @@ -6,7 +6,7 @@ import { IColorContrastCache } from 'browser/Types'; import { DIM_OPACITY, TEXT_BASELINE } from 'browser/renderer/shared/Constants'; import { tryDrawCustomChar } from 'browser/renderer/shared/CustomGlyphs'; -import { excludeFromContrastRatioDemands, isPowerlineGlyph, isRestrictedPowerlineGlyph, throwIfFalsy } from 'browser/renderer/shared/RendererUtils'; +import { computeNextVariantOffset, excludeFromContrastRatioDemands, isPowerlineGlyph, isRestrictedPowerlineGlyph, throwIfFalsy } from 'browser/renderer/shared/RendererUtils'; import { IBoundingBox, ICharAtlasConfig, IRasterizedGlyph, ITextureAtlas } from 'browser/renderer/shared/Types'; import { NULL_COLOR, color, rgba } from 'common/Color'; import { EventEmitter } from 'common/EventEmitter'; @@ -545,6 +545,7 @@ export class TextureAtlas implements ITextureAtlas { const yTop = Math.ceil(padding + this._config.deviceCharHeight) - yOffset - (restrictToCellHeight ? lineWidth * 2 : 0); const yMid = yTop + lineWidth; const yBot = yTop + lineWidth * 2; + let nextOffset = this._workAttributeData.getUnderlineVariantOffset(); for (let i = 0; i < chWidth; i++) { this._tmpCtx.save(); @@ -594,9 +595,22 @@ export class TextureAtlas implements ITextureAtlas { ); break; case UnderlineStyle.DOTTED: - this._tmpCtx.setLineDash([Math.round(lineWidth), Math.round(lineWidth)]); - this._tmpCtx.moveTo(xChLeft, yTop); - this._tmpCtx.lineTo(xChRight, yTop); + const offsetWidth = nextOffset === 0 ? 0 : + (nextOffset >= lineWidth ? lineWidth * 2 - nextOffset : lineWidth - nextOffset); + // a line and a gap. + const isLineStart = nextOffset >= lineWidth ? false : true; + if (isLineStart === false || offsetWidth === 0) { + this._tmpCtx.setLineDash([Math.round(lineWidth), Math.round(lineWidth)]); + this._tmpCtx.moveTo(xChLeft + offsetWidth, yTop); + this._tmpCtx.lineTo(xChRight, yTop); + } else { + this._tmpCtx.setLineDash([Math.round(lineWidth), Math.round(lineWidth)]); + this._tmpCtx.moveTo(xChLeft, yTop); + this._tmpCtx.lineTo(xChLeft + offsetWidth, yTop); + this._tmpCtx.moveTo(xChLeft + offsetWidth + lineWidth, yTop); + this._tmpCtx.lineTo(xChRight, yTop); + } + nextOffset = computeNextVariantOffset(xChRight - xChLeft, lineWidth, nextOffset); break; case UnderlineStyle.DASHED: this._tmpCtx.setLineDash([this._config.devicePixelRatio * 4, this._config.devicePixelRatio * 3]); diff --git a/src/browser/renderer/shared/Types.d.ts b/src/browser/renderer/shared/Types.d.ts index a7e55e72cd..c0d5e9d656 100644 --- a/src/browser/renderer/shared/Types.d.ts +++ b/src/browser/renderer/shared/Types.d.ts @@ -3,8 +3,8 @@ * @license MIT */ -import { FontWeight, Terminal } from 'xterm'; -import { IColorSet } from 'browser/Types'; +import { FontWeight, Terminal } from '@xterm/xterm'; +import { IColorSet, ITerminal } from 'browser/Types'; import { IDisposable } from 'common/Types'; import { IEvent } from 'common/EventEmitter'; @@ -168,6 +168,6 @@ export interface ISelectionRenderModel { readonly selectionStart: [number, number] | undefined; readonly selectionEnd: [number, number] | undefined; clear(): void; - update(terminal: Terminal, start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode?: boolean): void; + update(terminal: ITerminal, start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode?: boolean): void; isCellSelected(terminal: Terminal, x: number, y: number): boolean; } diff --git a/src/browser/services/CoreBrowserService.ts b/src/browser/services/CoreBrowserService.ts index e992f2554a..575b62b63c 100644 --- a/src/browser/services/CoreBrowserService.ts +++ b/src/browser/services/CoreBrowserService.ts @@ -3,22 +3,49 @@ * @license MIT */ +import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle'; import { ICoreBrowserService } from './Services'; +import { EventEmitter, forwardEvent } from 'common/EventEmitter'; +import { addDisposableDomListener } from 'browser/Lifecycle'; -export class CoreBrowserService implements ICoreBrowserService { +export class CoreBrowserService extends Disposable implements ICoreBrowserService { public serviceBrand: undefined; private _isFocused = false; private _cachedIsFocused: boolean | undefined = undefined; + private _screenDprMonitor = new ScreenDprMonitor(this._window); + + private readonly _onDprChange = this.register(new EventEmitter()); + public readonly onDprChange = this._onDprChange.event; + private readonly _onWindowChange = this.register(new EventEmitter()); + public readonly onWindowChange = this._onWindowChange.event; constructor( private _textarea: HTMLTextAreaElement, - public readonly window: Window & typeof globalThis + private _window: Window & typeof globalThis, + public readonly mainDocument: Document ) { + super(); + + // Monitor device pixel ratio + this.register(this.onWindowChange(w => this._screenDprMonitor.setWindow(w))); + this.register(forwardEvent(this._screenDprMonitor.onDprChange, this._onDprChange)); + this._textarea.addEventListener('focus', () => this._isFocused = true); this._textarea.addEventListener('blur', () => this._isFocused = false); } + public get window(): Window & typeof globalThis { + return this._window; + } + + public set window(value: Window & typeof globalThis) { + if (this._window !== value) { + this._window = value; + this._onWindowChange.fire(this._window); + } + } + public get dpr(): number { return this.window.devicePixelRatio; } @@ -31,3 +58,80 @@ export class CoreBrowserService implements ICoreBrowserService { return this._cachedIsFocused; } } + + +/** + * The screen device pixel ratio monitor allows listening for when the + * window.devicePixelRatio value changes. This is done not with polling but with + * the use of window.matchMedia to watch media queries. When the event fires, + * the listener will be reattached using a different media query to ensure that + * any further changes will register. + * + * The listener should fire on both window zoom changes and switching to a + * monitor with a different DPI. + */ +class ScreenDprMonitor extends Disposable { + private _currentDevicePixelRatio: number; + private _outerListener: ((this: MediaQueryList, ev: MediaQueryListEvent) => any) | undefined; + private _resolutionMediaMatchList: MediaQueryList | undefined; + private _windowResizeListener = this.register(new MutableDisposable()); + + private readonly _onDprChange = this.register(new EventEmitter()); + public readonly onDprChange = this._onDprChange.event; + + constructor(private _parentWindow: Window) { + super(); + + // Initialize listener and dpr value + this._outerListener = () => this._setDprAndFireIfDiffers(); + this._currentDevicePixelRatio = this._parentWindow.devicePixelRatio; + this._updateDpr(); + + // Monitor active window resize + this._setWindowResizeListener(); + + // Setup additional disposables + this.register(toDisposable(() => this.clearListener())); + } + + + public setWindow(parentWindow: Window): void { + this._parentWindow = parentWindow; + this._setWindowResizeListener(); + this._setDprAndFireIfDiffers(); + } + + private _setWindowResizeListener(): void { + this._windowResizeListener.value = addDisposableDomListener(this._parentWindow, 'resize', () => this._setDprAndFireIfDiffers()); + } + + private _setDprAndFireIfDiffers(): void { + if (this._parentWindow.devicePixelRatio !== this._currentDevicePixelRatio) { + this._onDprChange.fire(this._parentWindow.devicePixelRatio); + } + this._updateDpr(); + } + + private _updateDpr(): void { + if (!this._outerListener) { + return; + } + + // Clear listeners for old DPR + this._resolutionMediaMatchList?.removeListener(this._outerListener); + + // Add listeners for new DPR + this._currentDevicePixelRatio = this._parentWindow.devicePixelRatio; + this._resolutionMediaMatchList = this._parentWindow.matchMedia(`screen and (resolution: ${this._parentWindow.devicePixelRatio}dppx)`); + this._resolutionMediaMatchList.addListener(this._outerListener); + } + + public clearListener(): void { + if (!this._resolutionMediaMatchList || !this._outerListener) { + return; + } + this._resolutionMediaMatchList.removeListener(this._outerListener); + this._resolutionMediaMatchList = undefined; + this._outerListener = undefined; + } +} diff --git a/src/browser/services/RenderService.ts b/src/browser/services/RenderService.ts index e6d259c289..9fa8d234c6 100644 --- a/src/browser/services/RenderService.ts +++ b/src/browser/services/RenderService.ts @@ -3,16 +3,14 @@ * @license MIT */ -import { addDisposableDomListener } from 'browser/Lifecycle'; import { RenderDebouncer } from 'browser/RenderDebouncer'; -import { ScreenDprMonitor } from 'browser/ScreenDprMonitor'; import { IRenderDebouncerWithCallback } from 'browser/Types'; import { IRenderDimensions, IRenderer } from 'browser/renderer/shared/Types'; import { ICharSizeService, ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services'; import { EventEmitter } from 'common/EventEmitter'; import { Disposable, MutableDisposable } from 'common/Lifecycle'; import { DebouncedIdleTask } from 'common/TaskQueue'; -import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services'; +import { IBufferService, IDecorationService, IInstantiationService, IOptionsService } from 'common/services/Services'; interface ISelectionState { start: [number, number] | undefined; @@ -25,7 +23,6 @@ export class RenderService extends Disposable implements IRenderService { private _renderer: MutableDisposable = this.register(new MutableDisposable()); private _renderDebouncer: IRenderDebouncerWithCallback; - private _screenDprMonitor: ScreenDprMonitor; private _pausedResizeTask = new DebouncedIdleTask(); private _isPaused: boolean = false; @@ -59,6 +56,7 @@ export class RenderService extends Disposable implements IRenderService { @IDecorationService decorationService: IDecorationService, @IBufferService bufferService: IBufferService, @ICoreBrowserService coreBrowserService: ICoreBrowserService, + @IInstantiationService instantiationService: IInstantiationService, @IThemeService themeService: IThemeService ) { super(); @@ -66,9 +64,7 @@ export class RenderService extends Disposable implements IRenderService { this._renderDebouncer = new RenderDebouncer(coreBrowserService.window, (start, end) => this._renderRows(start, end)); this.register(this._renderDebouncer); - this._screenDprMonitor = new ScreenDprMonitor(coreBrowserService.window); - this._screenDprMonitor.setListener(() => this.handleDevicePixelRatioChange()); - this.register(this._screenDprMonitor); + this.register(coreBrowserService.onDprChange(() => this.handleDevicePixelRatioChange())); this.register(bufferService.onResize(() => this._fullRefresh())); this.register(bufferService.buffers.onBufferActivate(() => this._renderer.value?.clear())); @@ -104,10 +100,6 @@ export class RenderService extends Disposable implements IRenderService { 'cursorStyle' ], () => this.refreshRows(bufferService.buffer.y, bufferService.buffer.y, true))); - // dprchange should handle this case, we need this as well for browsers that don't support the - // matchMedia query. - this.register(addDisposableDomListener(coreBrowserService.window, 'resize', () => this.handleDevicePixelRatioChange())); - this.register(themeService.onChangeColors(() => this._fullRefresh())); // Detect whether IntersectionObserver is detected and enable renderer pause diff --git a/src/browser/services/Services.ts b/src/browser/services/Services.ts index d96285f79d..5c14fa8af6 100644 --- a/src/browser/services/Services.ts +++ b/src/browser/services/Services.ts @@ -28,12 +28,21 @@ export interface ICoreBrowserService { serviceBrand: undefined; readonly isFocused: boolean; + + readonly onDprChange: IEvent; + readonly onWindowChange: IEvent; + + /** + * Gets or sets the parent window that the terminal is rendered into. DOM and rendering APIs (e.g. + * requestAnimationFrame) should be invoked in the context of this window. This should be set when + * the window hosting the xterm.js instance changes. + */ + window: Window & typeof globalThis; /** - * Parent window that the terminal is rendered into. DOM and rendering APIs - * (e.g. requestAnimationFrame) should be invoked in the context of this - * window. + * The document of the primary window to be used to create elements when working with multiple + * windows. This is defined by the documentOverride setting. */ - readonly window: Window & typeof globalThis; + readonly mainDocument: Document; /** * Helper for getting the devicePixelRatio of the parent window. */ diff --git a/src/common/Color.ts b/src/common/Color.ts index 108d72f36c..9bfed4e645 100644 --- a/src/common/Color.ts +++ b/src/common/Color.ts @@ -113,6 +113,7 @@ export namespace css { let $ctx: CanvasRenderingContext2D | undefined; let $litmusColor: CanvasGradient | undefined; if (!isNode) { + // This is guaranteed to run in the first window, so document should be correct const canvas = document.createElement('canvas'); canvas.width = 1; canvas.height = 1; diff --git a/src/common/EventEmitter.ts b/src/common/EventEmitter.ts index fd95904245..589748a30f 100644 --- a/src/common/EventEmitter.ts +++ b/src/common/EventEmitter.ts @@ -71,3 +71,8 @@ export class EventEmitter implements IEventEmitter { export function forwardEvent(from: IEvent, to: IEventEmitter): IDisposable { return from(e => to.fire(e)); } + +export function runAndSubscribe(event: IEvent, handler: (e: T | undefined) => any): IDisposable { + handler(undefined); + return event(e => handler(e)); +} diff --git a/src/common/InputHandler.ts b/src/common/InputHandler.ts index b5c91bfba7..a4b8c64b02 100644 --- a/src/common/InputHandler.ts +++ b/src/common/InputHandler.ts @@ -49,7 +49,7 @@ const GLEVEL: { [key: string]: number } = { '(': 0, ')': 1, '*': 2, '+': 3, '-': /** * Document xterm VT features here that are currently unsupported */ -// @vt: #E[Supported via xterm-addon-image.] DCS SIXEL "SIXEL Graphics" "DCS Ps ; Ps ; Ps ; q Pt ST" "Draw SIXEL image." +// @vt: #E[Supported via @xterm/addon-image.] DCS SIXEL "SIXEL Graphics" "DCS Ps ; Ps ; Ps ; q Pt ST" "Draw SIXEL image." // @vt: #N DCS DECUDK "User Defined Keys" "DCS Ps ; Ps \| Pt ST" "Definitions for user-defined keys." // @vt: #N DCS XTGETTCAP "Request Terminfo String" "DCS + q Pt ST" "Request Terminfo String." // @vt: #N DCS XTSETTCAP "Set Terminfo Data" "DCS + p Pt ST" "Set Terminfo Data." @@ -519,7 +519,7 @@ export class InputHandler extends Disposable implements IInputHandler { // handle wide chars: reset start_cell-1 if we would overwrite the second cell of a wide char if (this._activeBuffer.x && end - start > 0 && bufferRow.getWidth(this._activeBuffer.x - 1) === 2) { - bufferRow.setCellFromCodePoint(this._activeBuffer.x - 1, 0, 1, curAttr.fg, curAttr.bg, curAttr.extended); + bufferRow.setCellFromCodepoint(this._activeBuffer.x - 1, 0, 1, curAttr); } let precedingJoinState = this._parser.precedingJoinState; @@ -581,7 +581,7 @@ export class InputHandler extends Disposable implements IInputHandler { } // clear left over cells to the right while (oldCol < cols) { - oldRow.setCellFromCodePoint(oldCol++, 0, 1, curAttr.fg, curAttr.bg, curAttr.extended); + oldRow.setCellFromCodepoint(oldCol++, 0, 1, curAttr); } } else { this._activeBuffer.x = cols - 1; @@ -605,7 +605,7 @@ export class InputHandler extends Disposable implements IInputHandler { bufferRow.addCodepointToCell(this._activeBuffer.x - offset, code, chWidth); for (let delta = chWidth - oldWidth; --delta >= 0; ) { - bufferRow.setCellFromCodePoint(this._activeBuffer.x++, 0, 0, curAttr.fg, curAttr.bg, curAttr.extended); + bufferRow.setCellFromCodepoint(this._activeBuffer.x++, 0, 0, curAttr); } continue; } @@ -613,17 +613,17 @@ export class InputHandler extends Disposable implements IInputHandler { // insert mode: move characters to right if (insertMode) { // right shift cells according to the width - bufferRow.insertCells(this._activeBuffer.x, chWidth - oldWidth, this._activeBuffer.getNullCell(curAttr), curAttr); + bufferRow.insertCells(this._activeBuffer.x, chWidth - oldWidth, this._activeBuffer.getNullCell(curAttr)); // test last cell - since the last cell has only room for // a halfwidth char any fullwidth shifted there is lost // and will be set to empty cell if (bufferRow.getWidth(cols - 1) === 2) { - bufferRow.setCellFromCodePoint(cols - 1, NULL_CELL_CODE, NULL_CELL_WIDTH, curAttr.fg, curAttr.bg, curAttr.extended); + bufferRow.setCellFromCodepoint(cols - 1, NULL_CELL_CODE, NULL_CELL_WIDTH, curAttr); } } // write current char to buffer and advance cursor - bufferRow.setCellFromCodePoint(this._activeBuffer.x++, code, chWidth, curAttr.fg, curAttr.bg, curAttr.extended); + bufferRow.setCellFromCodepoint(this._activeBuffer.x++, code, chWidth, curAttr); // fullwidth char - also set next cell to placeholder stub and advance cursor // for graphemes bigger than fullwidth we can simply loop to zero @@ -631,7 +631,7 @@ export class InputHandler extends Disposable implements IInputHandler { if (chWidth > 0) { while (--chWidth) { // other than a regular empty cell a cell following a wide char has no width - bufferRow.setCellFromCodePoint(this._activeBuffer.x++, 0, 0, curAttr.fg, curAttr.bg, curAttr.extended); + bufferRow.setCellFromCodepoint(this._activeBuffer.x++, 0, 0, curAttr); } } } @@ -640,7 +640,7 @@ export class InputHandler extends Disposable implements IInputHandler { // handle wide chars: reset cell to the right if it is second cell of a wide char if (this._activeBuffer.x < cols && end - start > 0 && bufferRow.getWidth(this._activeBuffer.x) === 0 && !bufferRow.hasContent(this._activeBuffer.x)) { - bufferRow.setCellFromCodePoint(this._activeBuffer.x, 0, 1, curAttr.fg, curAttr.bg, curAttr.extended); + bufferRow.setCellFromCodepoint(this._activeBuffer.x, 0, 1, curAttr); } this._dirtyRowTracker.markDirty(this._activeBuffer.y); @@ -1145,7 +1145,6 @@ export class InputHandler extends Disposable implements IInputHandler { start, end, this._activeBuffer.getNullCell(this._eraseAttrData()), - this._eraseAttrData(), respectProtect ); if (clearWrap) { @@ -1366,8 +1365,7 @@ export class InputHandler extends Disposable implements IInputHandler { line.insertCells( this._activeBuffer.x, params.params[0] || 1, - this._activeBuffer.getNullCell(this._eraseAttrData()), - this._eraseAttrData() + this._activeBuffer.getNullCell(this._eraseAttrData()) ); this._dirtyRowTracker.markDirty(this._activeBuffer.y); } @@ -1393,8 +1391,7 @@ export class InputHandler extends Disposable implements IInputHandler { line.deleteCells( this._activeBuffer.x, params.params[0] || 1, - this._activeBuffer.getNullCell(this._eraseAttrData()), - this._eraseAttrData() + this._activeBuffer.getNullCell(this._eraseAttrData()) ); this._dirtyRowTracker.markDirty(this._activeBuffer.y); } @@ -1461,7 +1458,7 @@ export class InputHandler extends Disposable implements IInputHandler { const param = params.params[0] || 1; for (let y = this._activeBuffer.scrollTop; y <= this._activeBuffer.scrollBottom; ++y) { const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y)!; - line.deleteCells(0, param, this._activeBuffer.getNullCell(this._eraseAttrData()), this._eraseAttrData()); + line.deleteCells(0, param, this._activeBuffer.getNullCell(this._eraseAttrData())); line.isWrapped = false; } this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom); @@ -1494,7 +1491,7 @@ export class InputHandler extends Disposable implements IInputHandler { const param = params.params[0] || 1; for (let y = this._activeBuffer.scrollTop; y <= this._activeBuffer.scrollBottom; ++y) { const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y)!; - line.insertCells(0, param, this._activeBuffer.getNullCell(this._eraseAttrData()), this._eraseAttrData()); + line.insertCells(0, param, this._activeBuffer.getNullCell(this._eraseAttrData())); line.isWrapped = false; } this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom); @@ -1517,7 +1514,7 @@ export class InputHandler extends Disposable implements IInputHandler { const param = params.params[0] || 1; for (let y = this._activeBuffer.scrollTop; y <= this._activeBuffer.scrollBottom; ++y) { const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y)!; - line.insertCells(this._activeBuffer.x, param, this._activeBuffer.getNullCell(this._eraseAttrData()), this._eraseAttrData()); + line.insertCells(this._activeBuffer.x, param, this._activeBuffer.getNullCell(this._eraseAttrData())); line.isWrapped = false; } this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom); @@ -1540,7 +1537,7 @@ export class InputHandler extends Disposable implements IInputHandler { const param = params.params[0] || 1; for (let y = this._activeBuffer.scrollTop; y <= this._activeBuffer.scrollBottom; ++y) { const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y)!; - line.deleteCells(this._activeBuffer.x, param, this._activeBuffer.getNullCell(this._eraseAttrData()), this._eraseAttrData()); + line.deleteCells(this._activeBuffer.x, param, this._activeBuffer.getNullCell(this._eraseAttrData())); line.isWrapped = false; } this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom); @@ -1562,8 +1559,7 @@ export class InputHandler extends Disposable implements IInputHandler { line.replaceCells( this._activeBuffer.x, this._activeBuffer.x + (params.params[0] || 1), - this._activeBuffer.getNullCell(this._eraseAttrData()), - this._eraseAttrData() + this._activeBuffer.getNullCell(this._eraseAttrData()) ); this._dirtyRowTracker.markDirty(this._activeBuffer.y); } diff --git a/src/common/Platform.ts b/src/common/Platform.ts index 41d8552e49..1007fc0a3f 100644 --- a/src/common/Platform.ts +++ b/src/common/Platform.ts @@ -12,8 +12,9 @@ interface INavigator { // We're declaring a navigator global here as we expect it in all runtimes (node and browser), but // we want this module to live in common. declare const navigator: INavigator; +declare const process: unknown; -export const isNode = (typeof navigator === 'undefined') ? true : false; +export const isNode = (typeof process !== 'undefined') ? true : false; const userAgent = (isNode) ? 'node' : navigator.userAgent; const platform = (isNode) ? 'node' : navigator.platform; diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index 8e57664e97..39e13fbac3 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -12,7 +12,7 @@ import { IBufferSet, IBuffer } from 'common/buffer/Types'; import { BufferSet } from 'common/buffer/BufferSet'; import { IDecPrivateModes, ICoreMouseEvent, CoreMouseEventType, ICharset, IModes, IAttributeData, IOscLinkData, IDisposable } from 'common/Types'; import { UnicodeV6 } from 'common/input/UnicodeV6'; -import { IDecorationOptions, IDecoration } from 'xterm'; +import { IDecorationOptions, IDecoration } from '@xterm/xterm'; export class MockBufferService implements IBufferService { public serviceBrand: any; diff --git a/src/common/Types.d.ts b/src/common/Types.d.ts index f76e0feef2..175c47c318 100644 --- a/src/common/Types.d.ts +++ b/src/common/Types.d.ts @@ -9,7 +9,7 @@ import { Attributes, UnderlineStyle } from 'common/buffer/Constants'; // eslint- import { IBufferSet } from 'common/buffer/Types'; import { IParams } from 'common/parser/Types'; import { ICoreMouseService, ICoreService, IOptionsService, IUnicodeService } from 'common/services/Services'; -import { IFunctionIdentifier, ITerminalOptions as IPublicTerminalOptions } from 'xterm'; +import { IFunctionIdentifier, ITerminalOptions as IPublicTerminalOptions } from '@xterm/xterm'; export interface ICoreTerminal { coreMouseService: ICoreMouseService; @@ -119,6 +119,7 @@ export interface IExtendedAttrs { ext: number; underlineStyle: UnderlineStyle; underlineColor: number; + underlineVariantOffset: number; urlId: number; clone(): IExtendedAttrs; isEmpty(): boolean; @@ -209,6 +210,7 @@ export interface IAttributeData { isUnderlineColorPalette(): boolean; isUnderlineColorDefault(): boolean; getUnderlineStyle(): number; + getUnderlineVariantOffset(): number; } /** Cell data */ @@ -233,11 +235,11 @@ export interface IBufferLine { set(index: number, value: CharData): void; loadCell(index: number, cell: ICellData): ICellData; setCell(index: number, cell: ICellData): void; - setCellFromCodePoint(index: number, codePoint: number, width: number, fg: number, bg: number, eAttrs: IExtendedAttrs): void; + setCellFromCodepoint(index: number, codePoint: number, width: number, attrs: IAttributeData): void; addCodepointToCell(index: number, codePoint: number, width: number): void; - insertCells(pos: number, n: number, ch: ICellData, eraseAttr?: IAttributeData): void; - deleteCells(pos: number, n: number, fill: ICellData, eraseAttr?: IAttributeData): void; - replaceCells(start: number, end: number, fill: ICellData, eraseAttr?: IAttributeData, respectProtect?: boolean): void; + insertCells(pos: number, n: number, ch: ICellData): void; + deleteCells(pos: number, n: number, fill: ICellData): void; + replaceCells(start: number, end: number, fill: ICellData, respectProtect?: boolean): void; resize(cols: number, fill: ICellData): boolean; cleanupMemory(): number; fill(fillCellData: ICellData, respectProtect?: boolean): void; diff --git a/src/common/buffer/AttributeData.ts b/src/common/buffer/AttributeData.ts index f4d12c2bcc..6221fb81d2 100644 --- a/src/common/buffer/AttributeData.ts +++ b/src/common/buffer/AttributeData.ts @@ -126,6 +126,9 @@ export class AttributeData implements IAttributeData { ? (this.bg & BgFlags.HAS_EXTENDED ? this.extended.underlineStyle : UnderlineStyle.SINGLE) : UnderlineStyle.NONE; } + public getUnderlineVariantOffset(): number { + return this.extended.underlineVariantOffset; + } } @@ -174,6 +177,18 @@ export class ExtendedAttrs implements IExtendedAttrs { this._urlId = value; } + public get underlineVariantOffset(): number { + const val = (this._ext & ExtFlags.VARIANT_OFFSET) >> 29; + if (val < 0) { + return val ^ 0xFFFFFFF8; + } + return val; + } + public set underlineVariantOffset(value: number) { + this._ext &= ~ExtFlags.VARIANT_OFFSET; + this._ext |= (value << 29) & ExtFlags.VARIANT_OFFSET; + } + constructor( ext: number = 0, urlId: number = 0 diff --git a/src/common/buffer/BufferLine.test.ts b/src/common/buffer/BufferLine.test.ts index 8461f57153..9d08c2bef6 100644 --- a/src/common/buffer/BufferLine.test.ts +++ b/src/common/buffer/BufferLine.test.ts @@ -119,6 +119,18 @@ describe('AttributeData', () => { attrs.fg &= ~FgFlags.UNDERLINE; assert.equal(attrs.getUnderlineStyle(), UnderlineStyle.NONE); }); + it('getUnderlineVariantOffset', () => { + const attrs = new AttributeData(); + + // defaults to no offset + assert.equal(attrs.getUnderlineVariantOffset(), 0); + + // should return 0 - 7 + for (let i = 0; i < 8; ++i) { + attrs.extended.underlineVariantOffset = i; + assert.equal(attrs.getUnderlineVariantOffset(), i); + } + }); }); }); diff --git a/src/common/buffer/BufferLine.ts b/src/common/buffer/BufferLine.ts index e078d5ed90..9a58327735 100644 --- a/src/common/buffer/BufferLine.ts +++ b/src/common/buffer/BufferLine.ts @@ -4,7 +4,7 @@ */ import { CharData, IAttributeData, IBufferLine, ICellData, IExtendedAttrs } from 'common/Types'; -import { AttributeData, ExtendedAttrs } from 'common/buffer/AttributeData'; +import { AttributeData } from 'common/buffer/AttributeData'; import { CellData } from 'common/buffer/CellData'; import { Attributes, BgFlags, CHAR_DATA_ATTR_INDEX, CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, Content, NULL_CELL_CHAR, NULL_CELL_CODE, NULL_CELL_WIDTH, WHITESPACE_CELL_CHAR } from 'common/buffer/Constants'; import { stringFromCodePoint } from 'common/input/TextDecoder'; @@ -212,13 +212,13 @@ export class BufferLine implements IBufferLine { * Since the input handler see the incoming chars as UTF32 codepoints, * it gets an optimized access method. */ - public setCellFromCodePoint(index: number, codePoint: number, width: number, fg: number, bg: number, eAttrs: IExtendedAttrs): void { - if (bg & BgFlags.HAS_EXTENDED) { - this._extendedAttrs[index] = eAttrs; + public setCellFromCodepoint(index: number, codePoint: number, width: number, attrs: IAttributeData): void { + if (attrs.bg & BgFlags.HAS_EXTENDED) { + this._extendedAttrs[index] = attrs.extended; } this._data[index * CELL_SIZE + Cell.CONTENT] = codePoint | (width << Content.WIDTH_SHIFT); - this._data[index * CELL_SIZE + Cell.FG] = fg; - this._data[index * CELL_SIZE + Cell.BG] = bg; + this._data[index * CELL_SIZE + Cell.FG] = attrs.fg; + this._data[index * CELL_SIZE + Cell.BG] = attrs.bg; } /** @@ -253,12 +253,12 @@ export class BufferLine implements IBufferLine { this._data[index * CELL_SIZE + Cell.CONTENT] = content; } - public insertCells(pos: number, n: number, fillCellData: ICellData, eraseAttr?: IAttributeData): void { + public insertCells(pos: number, n: number, fillCellData: ICellData): void { pos %= this.length; // handle fullwidth at pos: reset cell one to the left if pos is second cell of a wide char if (pos && this.getWidth(pos - 1) === 2) { - this.setCellFromCodePoint(pos - 1, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs()); + this.setCellFromCodepoint(pos - 1, 0, 1, fillCellData); } if (n < this.length - pos) { @@ -277,11 +277,11 @@ export class BufferLine implements IBufferLine { // handle fullwidth at line end: reset last cell if it is first cell of a wide char if (this.getWidth(this.length - 1) === 2) { - this.setCellFromCodePoint(this.length - 1, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs()); + this.setCellFromCodepoint(this.length - 1, 0, 1, fillCellData); } } - public deleteCells(pos: number, n: number, fillCellData: ICellData, eraseAttr?: IAttributeData): void { + public deleteCells(pos: number, n: number, fillCellData: ICellData): void { pos %= this.length; if (n < this.length - pos) { const cell = new CellData(); @@ -301,21 +301,21 @@ export class BufferLine implements IBufferLine { // - reset pos-1 if wide char // - reset pos if width==0 (previous second cell of a wide char) if (pos && this.getWidth(pos - 1) === 2) { - this.setCellFromCodePoint(pos - 1, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs()); + this.setCellFromCodepoint(pos - 1, 0, 1, fillCellData); } if (this.getWidth(pos) === 0 && !this.hasContent(pos)) { - this.setCellFromCodePoint(pos, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs()); + this.setCellFromCodepoint(pos, 0, 1, fillCellData); } } - public replaceCells(start: number, end: number, fillCellData: ICellData, eraseAttr?: IAttributeData, respectProtect: boolean = false): void { + public replaceCells(start: number, end: number, fillCellData: ICellData, respectProtect: boolean = false): void { // full branching on respectProtect==true, hopefully getting fast JIT for standard case if (respectProtect) { if (start && this.getWidth(start - 1) === 2 && !this.isProtected(start - 1)) { - this.setCellFromCodePoint(start - 1, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs()); + this.setCellFromCodepoint(start - 1, 0, 1, fillCellData); } if (end < this.length && this.getWidth(end - 1) === 2 && !this.isProtected(end)) { - this.setCellFromCodePoint(end, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs()); + this.setCellFromCodepoint(end, 0, 1, fillCellData); } while (start < end && start < this.length) { if (!this.isProtected(start)) { @@ -328,11 +328,11 @@ export class BufferLine implements IBufferLine { // handle fullwidth at start: reset cell one to the left if start is second cell of a wide char if (start && this.getWidth(start - 1) === 2) { - this.setCellFromCodePoint(start - 1, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs()); + this.setCellFromCodepoint(start - 1, 0, 1, fillCellData); } // handle fullwidth at last cell + 1: reset to empty cell if it is second part of a wide char if (end < this.length && this.getWidth(end - 1) === 2) { - this.setCellFromCodePoint(end, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0, eraseAttr?.extended || new ExtendedAttrs()); + this.setCellFromCodepoint(end, 0, 1, fillCellData); } while (start < end && start < this.length) { diff --git a/src/common/buffer/BufferRange.test.ts b/src/common/buffer/BufferRange.test.ts index 69aacd994e..15d1b83176 100644 --- a/src/common/buffer/BufferRange.test.ts +++ b/src/common/buffer/BufferRange.test.ts @@ -5,7 +5,7 @@ import { assert } from 'chai'; import { getRangeLength } from 'common/buffer/BufferRange'; -import { IBufferRange } from 'xterm'; +import { IBufferRange } from '@xterm/xterm'; describe('BufferRange', () => { describe('getRangeLength', () => { diff --git a/src/common/buffer/BufferRange.ts b/src/common/buffer/BufferRange.ts index a49cf48112..aa7ee4050a 100644 --- a/src/common/buffer/BufferRange.ts +++ b/src/common/buffer/BufferRange.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { IBufferRange } from 'xterm'; +import { IBufferRange } from '@xterm/xterm'; export function getRangeLength(range: IBufferRange, bufferCols: number): number { if (range.start.y > range.end.y) { diff --git a/src/common/buffer/Constants.ts b/src/common/buffer/Constants.ts index f6a31be7b9..5ce075cf78 100644 --- a/src/common/buffer/Constants.ts +++ b/src/common/buffer/Constants.ts @@ -134,9 +134,17 @@ export const enum BgFlags { export const enum ExtFlags { /** - * bit 27..32 (upper 3 unused) + * bit 27..29 */ - UNDERLINE_STYLE = 0x1C000000 + UNDERLINE_STYLE = 0x1C000000, + + /** + * bit 30..32 + * + * An optional variant for the glyph, this can be used for example to offset underlines by a + * number of pixels to create a perfect pattern. + */ + VARIANT_OFFSET = 0xE0000000 } export const enum UnderlineStyle { diff --git a/src/common/input/Keyboard.test.ts b/src/common/input/Keyboard.test.ts index f2d0936b3e..c598fc58c0 100644 --- a/src/common/input/Keyboard.test.ts +++ b/src/common/input/Keyboard.test.ts @@ -106,6 +106,21 @@ describe('Keyboard', () => { it('should return \\x1b[5B for ctrl+down', () => { assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, keyCode: 40 }).key, '\x1b[1;5B'); // CSI 5 B }); + it('should return \\x08 for ctrl+backspace', () => { + assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, keyCode: 8 }).key, '\x08'); + }); + it('should return \\x1b\\x7f for alt+backspace', () => { + assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 8 }).key, '\x1b\x7f'); + }); + it('should return \\x1b\\x08 for ctrl+alt+backspace', () => { + assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, altKey: true, keyCode: 8 }).key, '\x1b\x08'); + }); + it('should return \\x1b[3;2~ for shift+delete', () => { + assert.equal(testEvaluateKeyboardEvent({ shiftKey: true, keyCode: 46 }).key, '\x1b[3;2~'); + }); + it('should return \\x1b[3;3~ for alt+delete', () => { + assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 46 }).key, '\x1b[3;3~'); + }); describe('On non-macOS platforms', () => { // Evalueate alt + arrow key movement, which is a feature of terminal emulators but not VT100 diff --git a/src/common/input/Keyboard.ts b/src/common/input/Keyboard.ts index 9420a974dc..b86eeac468 100644 --- a/src/common/input/Keyboard.ts +++ b/src/common/input/Keyboard.ts @@ -83,11 +83,10 @@ export function evaluateKeyboardEvent( break; case 8: // backspace + result.key = ev.ctrlKey ? '\b' : C0.DEL; // ^H or ^? if (ev.altKey) { - result.key = C0.ESC + C0.DEL; // \e ^? - break; + result.key = C0.ESC + result.key; } - result.key = C0.DEL; // ^? break; case 9: // tab diff --git a/src/common/public/AddonManager.test.ts b/src/common/public/AddonManager.test.ts index e947976ac3..239952eec6 100644 --- a/src/common/public/AddonManager.test.ts +++ b/src/common/public/AddonManager.test.ts @@ -5,7 +5,7 @@ import { assert } from 'chai'; import { AddonManager, ILoadedAddon } from './AddonManager'; -import { ITerminalAddon } from 'xterm'; +import { ITerminalAddon } from '@xterm/xterm'; class TestAddonManager extends AddonManager { public get addons(): ILoadedAddon[] { diff --git a/src/common/public/AddonManager.ts b/src/common/public/AddonManager.ts index af04a26964..9a36e2a0ee 100644 --- a/src/common/public/AddonManager.ts +++ b/src/common/public/AddonManager.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { ITerminalAddon, IDisposable, Terminal } from 'xterm'; +import { ITerminalAddon, IDisposable, Terminal } from '@xterm/xterm'; export interface ILoadedAddon { instance: ITerminalAddon; diff --git a/src/common/public/BufferApiView.ts b/src/common/public/BufferApiView.ts index ca9ef2d8f4..834cedbee4 100644 --- a/src/common/public/BufferApiView.ts +++ b/src/common/public/BufferApiView.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { IBuffer as IBufferApi, IBufferLine as IBufferLineApi, IBufferCell as IBufferCellApi } from 'xterm'; +import { IBuffer as IBufferApi, IBufferLine as IBufferLineApi, IBufferCell as IBufferCellApi } from '@xterm/xterm'; import { IBuffer } from 'common/buffer/Types'; import { BufferLineApiView } from 'common/public/BufferLineApiView'; import { CellData } from 'common/buffer/CellData'; diff --git a/src/common/public/BufferLineApiView.ts b/src/common/public/BufferLineApiView.ts index 60375015d6..560dd0bfd9 100644 --- a/src/common/public/BufferLineApiView.ts +++ b/src/common/public/BufferLineApiView.ts @@ -5,7 +5,7 @@ import { CellData } from 'common/buffer/CellData'; import { IBufferLine, ICellData } from 'common/Types'; -import { IBufferCell as IBufferCellApi, IBufferLine as IBufferLineApi } from 'xterm'; +import { IBufferCell as IBufferCellApi, IBufferLine as IBufferLineApi } from '@xterm/xterm'; export class BufferLineApiView implements IBufferLineApi { constructor(private _line: IBufferLine) { } diff --git a/src/common/public/BufferNamespaceApi.ts b/src/common/public/BufferNamespaceApi.ts index aeaa4ac841..cef0ed164b 100644 --- a/src/common/public/BufferNamespaceApi.ts +++ b/src/common/public/BufferNamespaceApi.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { IBuffer as IBufferApi, IBufferNamespace as IBufferNamespaceApi } from 'xterm'; +import { IBuffer as IBufferApi, IBufferNamespace as IBufferNamespaceApi } from '@xterm/xterm'; import { BufferApiView } from 'common/public/BufferApiView'; import { EventEmitter } from 'common/EventEmitter'; import { ICoreTerminal } from 'common/Types'; diff --git a/src/common/public/ParserApi.ts b/src/common/public/ParserApi.ts index 67df4be532..afcc01beb9 100644 --- a/src/common/public/ParserApi.ts +++ b/src/common/public/ParserApi.ts @@ -4,7 +4,7 @@ */ import { IParams } from 'common/parser/Types'; -import { IDisposable, IFunctionIdentifier, IParser } from 'xterm'; +import { IDisposable, IFunctionIdentifier, IParser } from '@xterm/xterm'; import { ICoreTerminal } from 'common/Types'; export class ParserApi implements IParser { diff --git a/src/common/public/UnicodeApi.ts b/src/common/public/UnicodeApi.ts index 8a669a0528..ec9bd1f776 100644 --- a/src/common/public/UnicodeApi.ts +++ b/src/common/public/UnicodeApi.ts @@ -4,7 +4,7 @@ */ import { ICoreTerminal } from 'common/Types'; -import { IUnicodeHandling, IUnicodeVersionProvider } from 'xterm'; +import { IUnicodeHandling, IUnicodeVersionProvider } from '@xterm/xterm'; export class UnicodeApi implements IUnicodeHandling { constructor(private _core: ICoreTerminal) { } diff --git a/src/common/services/DecorationService.ts b/src/common/services/DecorationService.ts index 36faa5094b..da75915276 100644 --- a/src/common/services/DecorationService.ts +++ b/src/common/services/DecorationService.ts @@ -9,7 +9,7 @@ import { Disposable, toDisposable } from 'common/Lifecycle'; import { IDecorationService, IInternalDecoration } from 'common/services/Services'; import { SortedList } from 'common/SortedList'; import { IColor } from 'common/Types'; -import { IDecoration, IDecorationOptions, IMarker } from 'xterm'; +import { IDecoration, IDecorationOptions, IMarker } from '@xterm/xterm'; // Work variables to avoid garbage collection let $xmin = 0; diff --git a/src/common/services/OptionsService.ts b/src/common/services/OptionsService.ts index 3c572445ed..eb9dbfa8c2 100644 --- a/src/common/services/OptionsService.ts +++ b/src/common/services/OptionsService.ts @@ -18,6 +18,7 @@ export const DEFAULT_OPTIONS: Readonly> = { cursorInactiveStyle: 'outline', customGlyphs: true, drawBoldTextInBrightColors: true, + documentOverride: null, fastScrollModifier: 'alt', fastScrollSensitivity: 5, fontFamily: 'courier-new, courier, monospace', diff --git a/src/common/services/Services.ts b/src/common/services/Services.ts index 52c2a79fae..304e8cbb4c 100644 --- a/src/common/services/Services.ts +++ b/src/common/services/Services.ts @@ -7,7 +7,7 @@ import { IEvent, IEventEmitter } from 'common/EventEmitter'; import { IBuffer, IBufferSet } from 'common/buffer/Types'; import { IDecPrivateModes, ICoreMouseEvent, CoreMouseEncoding, ICoreMouseProtocol, CoreMouseEventType, ICharset, IWindowOptions, IModes, IAttributeData, ScrollSource, IDisposable, IColor, CursorStyle, CursorInactiveStyle, IOscLinkData } from 'common/Types'; import { createDecorator } from 'common/services/ServiceRegistry'; -import { IDecorationOptions, IDecoration, ILinkHandler, IWindowsPty, ILogger } from 'xterm'; +import { IDecorationOptions, IDecoration, ILinkHandler, IWindowsPty, ILogger } from '@xterm/xterm'; export const IBufferService = createDecorator('BufferService'); export interface IBufferService { @@ -217,6 +217,7 @@ export interface ITerminalOptions { cursorInactiveStyle?: CursorInactiveStyle; customGlyphs?: boolean; disableStdin?: boolean; + documentOverride?: any | null; drawBoldTextInBrightColors?: boolean; fastScrollModifier?: 'none' | 'alt' | 'ctrl' | 'shift'; fastScrollSensitivity?: number; diff --git a/src/headless/public/Terminal.test.ts b/src/headless/public/Terminal.test.ts index f869a991d2..2175c6684f 100644 --- a/src/headless/public/Terminal.test.ts +++ b/src/headless/public/Terminal.test.ts @@ -5,7 +5,7 @@ import { deepStrictEqual, strictEqual, throws } from 'assert'; import { Terminal } from 'headless/public/Terminal'; -import { ITerminalOptions } from 'xterm-headless'; +import { ITerminalOptions } from '@xterm/headless'; let term: Terminal; diff --git a/src/headless/public/Terminal.ts b/src/headless/public/Terminal.ts index b018d37caf..df202660f8 100644 --- a/src/headless/public/Terminal.ts +++ b/src/headless/public/Terminal.ts @@ -7,7 +7,7 @@ import { IEvent } from 'common/EventEmitter'; import { BufferNamespaceApi } from 'common/public/BufferNamespaceApi'; import { ParserApi } from 'common/public/ParserApi'; import { UnicodeApi } from 'common/public/UnicodeApi'; -import { IBufferNamespace as IBufferNamespaceApi, IMarker, IModes, IParser, ITerminalAddon, ITerminalInitOnlyOptions, IUnicodeHandling, Terminal as ITerminalApi } from 'xterm-headless'; +import { IBufferNamespace as IBufferNamespaceApi, IMarker, IModes, IParser, ITerminalAddon, ITerminalInitOnlyOptions, IUnicodeHandling, Terminal as ITerminalApi } from '@xterm/headless'; import { Terminal as TerminalCore } from 'headless/Terminal'; import { AddonManager } from 'common/public/AddonManager'; import { ITerminalOptions } from 'common/Types'; diff --git a/src/headless/tsconfig.json b/src/headless/tsconfig.json index b579af97c0..e48c4fd5b6 100644 --- a/src/headless/tsconfig.json +++ b/src/headless/tsconfig.json @@ -17,7 +17,7 @@ }, "include": [ "./**/*", - "../../typings/xterm.d.ts", // common/Types.d.ts imports from 'xterm' + "../../typings/xterm.d.ts", // common/Types.d.ts imports from '@xterm/xterm' "../../typings/xterm-headless.d.ts" ], "references": [ diff --git a/test/api/TestUtils.ts b/test/api/TestUtils.ts index 288a3c0719..9ebf67b6a1 100644 --- a/test/api/TestUtils.ts +++ b/test/api/TestUtils.ts @@ -5,7 +5,7 @@ import * as playwright from '@playwright/test'; import deepEqual = require('deep-equal'); -import { ITerminalInitOnlyOptions, ITerminalOptions } from 'xterm'; +import { ITerminalInitOnlyOptions, ITerminalOptions } from '@xterm/xterm'; import { deepStrictEqual } from 'assert'; export async function pollFor(page: playwright.Page, evalOrFn: string | (() => Promise), val: T, preFn?: () => Promise, maxDuration?: number): Promise { diff --git a/test/playwright/MouseTracking.test.ts b/test/playwright/MouseTracking.test.ts index dbce55cde8..1cefd7cd19 100644 --- a/test/playwright/MouseTracking.test.ts +++ b/test/playwright/MouseTracking.test.ts @@ -4,7 +4,7 @@ */ import { test } from '@playwright/test'; import { deepStrictEqual, ok, strictEqual } from 'assert'; -import type { IDisposable } from 'xterm'; +import type { IDisposable } from '@xterm/xterm'; import { createTestContext, ITestContext, openTerminal, pollFor } from './TestUtils'; let ctx: ITestContext; diff --git a/test/playwright/Parser.test.ts b/test/playwright/Parser.test.ts index 42406270b4..b793b00eef 100644 --- a/test/playwright/Parser.test.ts +++ b/test/playwright/Parser.test.ts @@ -4,7 +4,7 @@ */ import { test } from '@playwright/test'; import { deepStrictEqual, ok, strictEqual } from 'assert'; -import type { IDisposable } from 'xterm'; +import type { IDisposable } from '@xterm/xterm'; import { createTestContext, ITestContext, openTerminal, pollFor } from './TestUtils'; let ctx: ITestContext; diff --git a/test/playwright/SharedRendererTests.ts b/test/playwright/SharedRendererTests.ts index eaa54d129f..aa747277f7 100644 --- a/test/playwright/SharedRendererTests.ts +++ b/test/playwright/SharedRendererTests.ts @@ -5,7 +5,7 @@ import { IImage32, decodePng } from '@lunapaint/png-codec'; import { LocatorScreenshotOptions, test } from '@playwright/test'; -import { ITheme } from 'xterm'; +import { ITheme } from '@xterm/xterm'; import { ITestContext, MaybeAsync, openTerminal, pollFor, pollForApproximate } from './TestUtils'; export interface ISharedRendererTestContext { @@ -1171,9 +1171,35 @@ export function injectSharedRendererTests(ctx: ISharedRendererTestContext): void await ctx.value.proxy.selectAll(); await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 0, 255, 255]); }); + test('#4799: cursor should be in the correct position', async () => { + const theme: ITheme = { + cursor: '#0000FF' + }; + await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`); + for (let index = 0; index < 160; index++) { + await ctx.value.proxy.writeln(``); + } + await ctx.value.proxy.focus(); + await ctx.value.proxy.write('\x1b[A'); + await ctx.value.proxy.write('\x1b[A'); + await ctx.value.proxy.scrollLines(-2); + const rows = await ctx.value.proxy.rows; + // block cursor style + await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, rows), [0, 0, 255, 255]); + await ctx.value.proxy.blur(); + frameDetails = undefined; + // outlink cursor style + await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, rows), [0, 0, 0, 255]); + await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, rows, CellColorPosition.FIRST), [0, 0, 255, 255]); + }); }); } +enum CellColorPosition { + CENTER = 0, + FIRST = 1 +} + /** * Injects shared renderer tests where it's required to re-initialize the terminal for each test. * This is much slower than just calling `Terminal.reset` but testing some features needs this @@ -1214,11 +1240,16 @@ export function injectSharedRendererTestsStandalone(ctx: ISharedRendererTestCont * @param col The 1-based column index to get the color for. * @param row The 1-based row index to get the color for. */ -function getCellColor(ctx: ITestContext, col: number, row: number): MaybeAsync<[red: number, green: number, blue: number, alpha: number]> { +function getCellColor(ctx: ITestContext, col: number, row: number, position: CellColorPosition = CellColorPosition.CENTER): MaybeAsync<[red: number, green: number, blue: number, alpha: number]> { if (!frameDetails) { return getFrameDetails(ctx).then(frameDetails => getCellColorInner(frameDetails, col, row)); } - return getCellColorInner(frameDetails, col, row); + switch (position) { + case CellColorPosition.CENTER: + return getCellColorInner(frameDetails, col, row); + case CellColorPosition.FIRST: + return getCellColorFirstPoint(frameDetails, col, row); + } } let frameDetails: { cols: number, rows: number, decoded: IImage32 } | undefined = undefined; @@ -1244,6 +1275,17 @@ function getCellColorInner(frameDetails: { cols: number, rows: number, decoded: return Array.from(frameDetails.decoded.data.slice(i, i + 4)) as [number, number, number, number]; } +function getCellColorFirstPoint(frameDetails: { cols: number, rows: number, decoded: IImage32 }, col: number, row: number): [red: number, green: number, blue: number, alpha: number] { + const cellSize = { + width: frameDetails.decoded.width / frameDetails.cols, + height: frameDetails.decoded.height / frameDetails.rows + }; + const x = Math.floor((col - 1/* 1- to 0-based index */) * cellSize.width); + const y = Math.floor((row - 1/* 1- to 0-based index */) * cellSize.height); + const i = (y * frameDetails.decoded.width + x) * 4/* 4 channels per pixel */; + return Array.from(frameDetails.decoded.data.slice(i, i + 4)) as [number, number, number, number]; +} + const COLORS_16_TO_255 = [ '#000000', '#00005f', '#000087', '#0000af', '#0000d7', '#0000ff', '#005f00', '#005f5f', '#005f87', '#005faf', '#005fd7', '#005fff', '#008700', '#00875f', '#008787', '#0087af', '#0087d7', '#0087ff', '#00af00', '#00af5f', '#00af87', '#00afaf', '#00afd7', '#00afff', '#00d700', '#00d75f', '#00d787', '#00d7af', '#00d7d7', '#00d7ff', '#00ff00', '#00ff5f', diff --git a/test/playwright/TestUtils.ts b/test/playwright/TestUtils.ts index 0a51757fac..3e925f79c9 100644 --- a/test/playwright/TestUtils.ts +++ b/test/playwright/TestUtils.ts @@ -10,7 +10,7 @@ import type { IRenderService } from 'browser/services/Services'; import type { ICoreTerminal, IMarker } from 'common/Types'; import * as playwright from '@playwright/test'; import { PageFunction } from 'playwright-core/types/structs'; -import { IBuffer, IBufferCell, IBufferLine, IBufferNamespace, IBufferRange, IDecoration, IDecorationOptions, IModes, ITerminalInitOnlyOptions, ITerminalOptions, Terminal } from 'xterm'; +import { IBuffer, IBufferCell, IBufferLine, IBufferNamespace, IBufferRange, IDecoration, IDecorationOptions, IModes, ITerminalInitOnlyOptions, ITerminalOptions, Terminal } from '@xterm/xterm'; import { EventEmitter } from '../../out/common/EventEmitter'; export interface ITestContext { diff --git a/tsconfig.all.json b/tsconfig.all.json index 5d8af629c0..e2028479d5 100644 --- a/tsconfig.all.json +++ b/tsconfig.all.json @@ -7,16 +7,16 @@ { "path": "./test/api" }, { "path": "./test/benchmark" }, { "path": "./test/playwright" }, - { "path": "./addons/xterm-addon-attach" }, - { "path": "./addons/xterm-addon-canvas" }, - { "path": "./addons/xterm-addon-fit" }, - { "path": "./addons/xterm-addon-image" }, - { "path": "./addons/xterm-addon-ligatures" }, - { "path": "./addons/xterm-addon-search" }, - { "path": "./addons/xterm-addon-serialize" }, - { "path": "./addons/xterm-addon-unicode11" }, - { "path": "./addons/xterm-addon-unicode-graphemes" }, - { "path": "./addons/xterm-addon-web-links" }, - { "path": "./addons/xterm-addon-webgl" } + { "path": "./addons/addon-attach" }, + { "path": "./addons/addon-canvas" }, + { "path": "./addons/addon-fit" }, + { "path": "./addons/addon-image" }, + { "path": "./addons/addon-ligatures" }, + { "path": "./addons/addon-search" }, + { "path": "./addons/addon-serialize" }, + { "path": "./addons/addon-unicode11" }, + { "path": "./addons/addon-unicode-graphemes" }, + { "path": "./addons/addon-web-links" }, + { "path": "./addons/addon-webgl" } ] } diff --git a/typings/xterm-headless.d.ts b/typings/xterm-headless.d.ts index 99aa8237fe..f8cef382f3 100644 --- a/typings/xterm-headless.d.ts +++ b/typings/xterm-headless.d.ts @@ -7,7 +7,7 @@ * to be stable and consumed by external programs. */ -declare module 'xterm-headless' { +declare module '@xterm/headless' { /** * A string representing log level. */ diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 3f603b9e19..70b0c6d71f 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -9,7 +9,7 @@ /// -declare module 'xterm' { +declare module '@xterm/xterm' { /** * A string or number representing text font weight. */ @@ -89,6 +89,17 @@ declare module 'xterm' { */ disableStdin?: boolean; + /** + * A {@link Document} to use instead of the one that xterm.js was attached + * to. The purpose of this is to improve support in multi-window + * applications where HTML elements may be references across multiple + * windows which can cause problems with `instanceof`. + * + * The type is `any` because using `Document` can cause TS to have + * performance/compiler problems. + */ + documentOverride?: any | null; + /** * Whether to draw bold text in bright colors. The default is true. */ @@ -962,7 +973,8 @@ declare module 'xterm' { resize(columns: number, rows: number): void; /** - * Opens the terminal within an element. + * Opens the terminal within an element. This should also be called if the + * xterm.js element ever changes browser window. * @param parent The element to create the terminal within. This element * must be visible (have dimensions) when `open` is called as several DOM- * based measurements need to be performed when this function is called. diff --git a/webpack.config.js b/webpack.config.js index ca7c059aec..3769bfb0fb 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -39,8 +39,10 @@ const config = { output: { filename: 'xterm.js', path: path.resolve('./lib'), - libraryTarget: 'umd' + libraryTarget: 'umd', + // Force usage of globalThis instead of global / self. (This is cross-env compatible) + globalObject: 'globalThis', }, - mode: 'production' + mode: 'production', }; module.exports = config; diff --git a/yarn.lock b/yarn.lock index ffebb5c5dc..a0cb39da57 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15,6 +15,14 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" +"@babel/code-frame@^7.22.13": + version "7.22.13" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e" + integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== + dependencies: + "@babel/highlight" "^7.22.13" + chalk "^2.4.2" + "@babel/code-frame@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.5.tgz#234d98e1551960604f1246e6475891a570ad5658" @@ -48,7 +56,7 @@ json5 "^2.2.2" semver "^6.3.1" -"@babel/generator@^7.22.7", "@babel/generator@^7.22.9": +"@babel/generator@^7.22.9": version "7.22.9" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.9.tgz#572ecfa7a31002fa1de2a9d91621fd895da8493d" integrity sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw== @@ -58,6 +66,16 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" +"@babel/generator@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420" + integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g== + dependencies: + "@babel/types" "^7.23.0" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + "@babel/helper-compilation-targets@^7.22.9": version "7.22.9" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz#f9d0a7aaaa7cd32a3f31c9316a69f5a9bcacb892" @@ -69,18 +87,23 @@ lru-cache "^5.1.1" semver "^6.3.1" +"@babel/helper-environment-visitor@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== + "@babel/helper-environment-visitor@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98" integrity sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q== -"@babel/helper-function-name@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz#ede300828905bb15e582c037162f99d5183af1be" - integrity sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ== +"@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== dependencies: - "@babel/template" "^7.22.5" - "@babel/types" "^7.22.5" + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" "@babel/helper-hoist-variables@^7.22.5": version "7.22.5" @@ -126,6 +149,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + "@babel/helper-validator-identifier@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" @@ -145,6 +173,15 @@ "@babel/traverse" "^7.22.6" "@babel/types" "^7.22.5" +"@babel/highlight@^7.22.13": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54" + integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + "@babel/highlight@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.5.tgz#aa6c05c5407a67ebce408162b7ede789b4d22031" @@ -154,6 +191,11 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/parser@^7.22.15", "@babel/parser@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719" + integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw== + "@babel/parser@^7.22.5", "@babel/parser@^7.22.7": version "7.22.7" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.7.tgz#df8cf085ce92ddbdbf668a7f186ce848c9036cae" @@ -166,6 +208,15 @@ dependencies: regenerator-runtime "^0.13.11" +"@babel/template@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" + integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/parser" "^7.22.15" + "@babel/types" "^7.22.15" + "@babel/template@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec" @@ -176,21 +227,30 @@ "@babel/types" "^7.22.5" "@babel/traverse@^7.22.6", "@babel/traverse@^7.22.8": - version "7.22.8" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.8.tgz#4d4451d31bc34efeae01eac222b514a77aa4000e" - integrity sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw== - dependencies: - "@babel/code-frame" "^7.22.5" - "@babel/generator" "^7.22.7" - "@babel/helper-environment-visitor" "^7.22.5" - "@babel/helper-function-name" "^7.22.5" + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8" + integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.23.0" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" "@babel/helper-hoist-variables" "^7.22.5" "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.22.7" - "@babel/types" "^7.22.5" + "@babel/parser" "^7.23.0" + "@babel/types" "^7.23.0" debug "^4.1.0" globals "^11.1.0" +"@babel/types@^7.22.15", "@babel/types@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb" + integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg== + dependencies: + "@babel/helper-string-parser" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + "@babel/types@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe" @@ -1145,7 +1205,7 @@ chai@^4.3.4: pathval "^1.1.1" type-detect "^4.0.5" -chalk@^2.0.0: +chalk@^2.0.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==