From c57dc5fdafac9cc006523ed0f27ea3a0c1077f1d Mon Sep 17 00:00:00 2001 From: meganrogge Date: Mon, 6 Feb 2023 13:17:07 -0600 Subject: [PATCH 1/7] add basics --- css/xterm.css | 2 +- src/browser/AccessibleBuffer.ts | 25 +++++++++++++++++++++---- src/browser/Terminal.ts | 7 +++++++ src/browser/TestUtils.test.ts | 3 +++ src/browser/Types.d.ts | 2 ++ src/browser/public/Terminal.ts | 3 +++ typings/xterm.d.ts | 7 +++++++ 7 files changed, 44 insertions(+), 5 deletions(-) diff --git a/css/xterm.css b/css/xterm.css index 85da42bcc9..55b5bbe61b 100644 --- a/css/xterm.css +++ b/css/xterm.css @@ -165,7 +165,7 @@ overflow-x: hidden; } -.xterm .xterm-accessibility-buffer:focus { +.xterm .xterm-accessibility-buffer:focus-within { opacity: 1; z-index: 20; } diff --git a/src/browser/AccessibleBuffer.ts b/src/browser/AccessibleBuffer.ts index 118fc0f04f..9e4dbaea53 100644 --- a/src/browser/AccessibleBuffer.ts +++ b/src/browser/AccessibleBuffer.ts @@ -39,10 +39,15 @@ export class AccessibleBuffer extends Disposable { this.register(addDisposableDomListener(this._accessiblityBuffer, 'keydown', (ev: KeyboardEvent) => { if (ev.key === 'Tab') { this._isAccessibilityBufferActive = false; - }} + } + } )); - this.register(addDisposableDomListener(this._accessiblityBuffer, 'focus',() => this._refreshAccessibilityBuffer())); - this.register(addDisposableDomListener(this._accessiblityBuffer, 'focusout',() => this._isAccessibilityBufferActive = false)); + this.register(addDisposableDomListener(this._accessiblityBuffer, 'focus', () => this._refreshAccessibilityBuffer())); + this.register(addDisposableDomListener(this._accessiblityBuffer, 'focusout', (e) => { + if (!this._accessiblityBuffer.contains(e.element)) { + this._isAccessibilityBufferActive = false + } + })); this._handleColorChange(themeService.colors); this.register(themeService.onChangeColors(e => this._handleColorChange(e))); @@ -51,11 +56,24 @@ export class AccessibleBuffer extends Disposable { this.register(toDisposable(() => this._accessiblityBuffer.remove())); } + public setElements(elements: HTMLElement[]): DocumentFragment { + const fragment = document.createDocumentFragment(); + for (const element of elements) { + fragment.appendChild(element); + } + this._accessiblityBuffer.replaceChildren(fragment); + return fragment; + } + private _refreshAccessibilityBuffer(): void { if (!this._terminal.viewport) { return; } this._isAccessibilityBufferActive = true; + this._accessiblityBuffer.scrollTop = this._accessiblityBuffer.scrollHeight; + if (this._terminal.options.screenReaderMode) { + return; + } const { bufferElements } = this._terminal.viewport.getBufferElements(0); for (const element of bufferElements) { if (element.textContent) { @@ -63,7 +81,6 @@ export class AccessibleBuffer extends Disposable { } } this._accessiblityBuffer.replaceChildren(...bufferElements); - this._accessiblityBuffer.scrollTop = this._accessiblityBuffer.scrollHeight; } private _handleColorChange(colorSet: ReadonlyColorSet): void { diff --git a/src/browser/Terminal.ts b/src/browser/Terminal.ts index 92f9554779..cf2494c77d 100644 --- a/src/browser/Terminal.ts +++ b/src/browser/Terminal.ts @@ -992,6 +992,13 @@ export class Terminal extends CoreTerminal implements ITerminal { this._selectionService?.selectLines(start, end); } + public setAccessibilityBufferElements(elements: HTMLElement[]): DocumentFragment { + if (!this._accessibleBuffer) { + throw new Error('No accessible buffer'); + } + return this._accessibleBuffer.setElements(elements); + } + /** * Handle a keydown [KeyboardEvent]. * diff --git a/src/browser/TestUtils.test.ts b/src/browser/TestUtils.test.ts index a3464ffdad..5a613076af 100644 --- a/src/browser/TestUtils.test.ts +++ b/src/browser/TestUtils.test.ts @@ -143,6 +143,9 @@ export class MockTerminal implements ITerminal { public getBufferElements(startLine: number, endLine?: number | undefined): { bufferElements: HTMLElement[], cursorElement?: HTMLElement | undefined } { throw new Error('Method not implemented.'); } + public setAccessibilityBufferElements(elements: HTMLElement[]): DocumentFragment { + throw new Error('Method not implemented.'); + } public bracketedPasteMode!: boolean; public renderer!: IRenderer; public linkifier2!: ILinkifier2; diff --git a/src/browser/Types.d.ts b/src/browser/Types.d.ts index f89b34ded6..ae6fe14441 100644 --- a/src/browser/Types.d.ts +++ b/src/browser/Types.d.ts @@ -79,6 +79,8 @@ export interface IPublicTerminal extends IDisposable { paste(data: string): void; refresh(start: number, end: number): void; clearTextureAtlas(): void; + setAccessibilityBufferElements(elements: HTMLElement[]): DocumentFragment + reset(): void; } diff --git a/src/browser/public/Terminal.ts b/src/browser/public/Terminal.ts index 7263d06dde..cb1bac22d7 100644 --- a/src/browser/public/Terminal.ts +++ b/src/browser/public/Terminal.ts @@ -236,6 +236,9 @@ export class Terminal implements ITerminalApi { public loadAddon(addon: ITerminalAddon): void { return this._addonManager.loadAddon(this, addon); } + public setAccessibilityBufferElements(elements: HTMLElement[]): DocumentFragment { + return this._core.setAccessibilityBufferElements(elements); + } public static get strings(): ILocalizableStrings { return Strings; } diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 401be2213c..1907d3eb20 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -1108,6 +1108,13 @@ declare module 'xterm' { * @param addon The addon to load. */ loadAddon(addon: ITerminalAddon): void; + + + /** + * Sets the accessibility buffer children. + * @param elements The elements to add to the accessibility buffer. + */ + setAccessibilityBufferElements(elements: HTMLElement[]): DocumentFragment; } /** From f8579793a38288223d5ea3c03d90e2bd0f0a972b Mon Sep 17 00:00:00 2001 From: meganrogge Date: Mon, 6 Feb 2023 13:37:31 -0600 Subject: [PATCH 2/7] fix line issue --- css/xterm.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/css/xterm.css b/css/xterm.css index 55b5bbe61b..6122fa4060 100644 --- a/css/xterm.css +++ b/css/xterm.css @@ -151,6 +151,10 @@ color: transparent; } +.xterm .xterm-accessibility-buffer div { + white-space: pre-wrap; +} + .xterm .xterm-accessibility-buffer { position: absolute; left: 0; From f6cc5f78d303778dcacafc91ba7937ebf2dd6931 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Mon, 6 Feb 2023 13:44:35 -0600 Subject: [PATCH 3/7] fix lint --- src/browser/AccessibleBuffer.ts | 2 +- src/browser/Types.d.ts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/browser/AccessibleBuffer.ts b/src/browser/AccessibleBuffer.ts index 9e4dbaea53..b3beb14e03 100644 --- a/src/browser/AccessibleBuffer.ts +++ b/src/browser/AccessibleBuffer.ts @@ -45,7 +45,7 @@ export class AccessibleBuffer extends Disposable { this.register(addDisposableDomListener(this._accessiblityBuffer, 'focus', () => this._refreshAccessibilityBuffer())); this.register(addDisposableDomListener(this._accessiblityBuffer, 'focusout', (e) => { if (!this._accessiblityBuffer.contains(e.element)) { - this._isAccessibilityBufferActive = false + this._isAccessibilityBufferActive = false; } })); diff --git a/src/browser/Types.d.ts b/src/browser/Types.d.ts index ae6fe14441..a8ec2808ea 100644 --- a/src/browser/Types.d.ts +++ b/src/browser/Types.d.ts @@ -79,8 +79,7 @@ export interface IPublicTerminal extends IDisposable { paste(data: string): void; refresh(start: number, end: number): void; clearTextureAtlas(): void; - setAccessibilityBufferElements(elements: HTMLElement[]): DocumentFragment - + setAccessibilityBufferElements(elements: HTMLElement[]): DocumentFragment; reset(): void; } From b84f01ae9728c5f84d79f585f8a0322b96fb2968 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Mon, 6 Feb 2023 13:46:25 -0600 Subject: [PATCH 4/7] Update typings/xterm.d.ts --- typings/xterm.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 1907d3eb20..72123e0f2e 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -1111,7 +1111,7 @@ declare module 'xterm' { /** - * Sets the accessibility buffer children. + * Sets the accessibility buffer's child elements. * @param elements The elements to add to the accessibility buffer. */ setAccessibilityBufferElements(elements: HTMLElement[]): DocumentFragment; From a32bbfb1a4df87e191fa3dc094a4dfe643b39f7b Mon Sep 17 00:00:00 2001 From: meganrogge Date: Mon, 6 Feb 2023 16:02:59 -0600 Subject: [PATCH 5/7] revise approach --- src/browser/AccessibleBuffer.ts | 43 +++++++++++++++++++++------------ src/browser/Terminal.ts | 16 ++++++------ src/browser/TestUtils.test.ts | 4 +-- src/browser/Types.d.ts | 6 ++++- src/browser/public/Terminal.ts | 6 ++--- typings/xterm.d.ts | 18 ++++++++++---- 6 files changed, 58 insertions(+), 35 deletions(-) diff --git a/src/browser/AccessibleBuffer.ts b/src/browser/AccessibleBuffer.ts index b3beb14e03..bb96b5db30 100644 --- a/src/browser/AccessibleBuffer.ts +++ b/src/browser/AccessibleBuffer.ts @@ -4,20 +4,19 @@ */ import * as Strings from 'browser/LocalizableStrings'; -import { ITerminal, IRenderDebouncer, ReadonlyColorSet } from 'browser/Types'; -import { isMac } from 'common/Platform'; -import { TimeBasedDebouncer } from 'browser/TimeBasedDebouncer'; +import { IBufferElementProvider, ITerminal, ReadonlyColorSet } from 'browser/Types'; import { addDisposableDomListener } from 'browser/Lifecycle'; import { Disposable, toDisposable } from 'common/Lifecycle'; import { IRenderService, IThemeService } from 'browser/services/Services'; import { IOptionsService } from 'common/services/Services'; import { ITerminalOptions } from 'xterm'; +import { IDisposable } from 'common/Types'; export class AccessibleBuffer extends Disposable { private _accessiblityBuffer: HTMLElement; private _isAccessibilityBufferActive: boolean = false; public get isAccessibilityBufferActive(): boolean { return this._isAccessibilityBufferActive; } - + private _providers: IBufferElementProvider[] = []; constructor( private readonly _terminal: ITerminal, @IOptionsService optionsService: IOptionsService, @@ -56,13 +55,17 @@ export class AccessibleBuffer extends Disposable { this.register(toDisposable(() => this._accessiblityBuffer.remove())); } - public setElements(elements: HTMLElement[]): DocumentFragment { - const fragment = document.createDocumentFragment(); - for (const element of elements) { - fragment.appendChild(element); - } - this._accessiblityBuffer.replaceChildren(fragment); - return fragment; + public registerBufferElementProvider(bufferProvider: IBufferElementProvider): IDisposable { + this._providers.push(bufferProvider); + return { + dispose: () => { + const providerIndex = this._providers.indexOf(bufferProvider); + + if (providerIndex !== -1) { + this._providers.splice(providerIndex, 1); + } + } + }; } private _refreshAccessibilityBuffer(): void { @@ -74,13 +77,21 @@ export class AccessibleBuffer extends Disposable { if (this._terminal.options.screenReaderMode) { return; } - const { bufferElements } = this._terminal.viewport.getBufferElements(0); - for (const element of bufferElements) { - if (element.textContent) { - element.textContent = element.textContent.replace(new RegExp(' ', 'g'), '\xA0'); + if (!this._providers.length) { + const { bufferElements } = this._terminal.viewport.getBufferElements(0); + for (const element of bufferElements) { + if (element.textContent) { + element.textContent = element.textContent.replace(new RegExp(' ', 'g'), '\xA0'); + } + } + this._accessiblityBuffer.replaceChildren(...bufferElements); + } else { + const fragment = document.createDocumentFragment(); + for (const provider of this._providers) { + provider.provideBufferElements((f) => fragment.appendChild(f)); } + this._accessiblityBuffer.replaceChildren(fragment); } - this._accessiblityBuffer.replaceChildren(...bufferElements); } private _handleColorChange(colorSet: ReadonlyColorSet): void { diff --git a/src/browser/Terminal.ts b/src/browser/Terminal.ts index cf2494c77d..3e609c7bf0 100644 --- a/src/browser/Terminal.ts +++ b/src/browser/Terminal.ts @@ -21,7 +21,7 @@ * http://linux.die.net/man/7/urxvt */ -import { ICompositionHelper, ITerminal, IBrowser, CustomKeyEventHandler, IViewport, ILinkifier2, CharacterJoinerHandler, IBufferRange } from 'browser/Types'; +import { ICompositionHelper, ITerminal, IBrowser, CustomKeyEventHandler, IViewport, ILinkifier2, CharacterJoinerHandler, IBufferRange, IBufferElementProvider } from 'browser/Types'; import { IRenderer } from 'browser/renderer/shared/Types'; import { CompositionHelper } from 'browser/input/CompositionHelper'; import { Viewport } from 'browser/Viewport'; @@ -193,6 +193,13 @@ export class Terminal extends CoreTerminal implements ITerminal { })); } + public registerBufferElementProvider(bufferProvider: IBufferElementProvider): IDisposable { + if (!this._accessibleBuffer) { + throw new Error ('No accessible buffer'); + } + return this._accessibleBuffer.registerBufferElementProvider(bufferProvider); + } + /** * Handle color event from inputhandler for OSC 4|104 | 10|110 | 11|111 | 12|112. * An event from OSC 4|104 may contain multiple set or report requests, and multiple @@ -992,13 +999,6 @@ export class Terminal extends CoreTerminal implements ITerminal { this._selectionService?.selectLines(start, end); } - public setAccessibilityBufferElements(elements: HTMLElement[]): DocumentFragment { - if (!this._accessibleBuffer) { - throw new Error('No accessible buffer'); - } - return this._accessibleBuffer.setElements(elements); - } - /** * Handle a keydown [KeyboardEvent]. * diff --git a/src/browser/TestUtils.test.ts b/src/browser/TestUtils.test.ts index 5a613076af..89494755f0 100644 --- a/src/browser/TestUtils.test.ts +++ b/src/browser/TestUtils.test.ts @@ -7,7 +7,7 @@ import { IDisposable, IMarker, ILinkProvider, IDecorationOptions, IDecoration } 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'; -import { IColorSet, ITerminal, ILinkifier2, IBrowser, IViewport, ICompositionHelper, CharacterJoinerHandler, IBufferRange, ReadonlyColorSet } from 'browser/Types'; +import { IColorSet, ITerminal, ILinkifier2, IBrowser, IViewport, ICompositionHelper, CharacterJoinerHandler, IBufferRange, ReadonlyColorSet, IBufferElementProvider } from 'browser/Types'; import { IBuffer, IBufferSet } from 'common/buffer/Types'; import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener, ICharset, ITerminalOptions, ColorIndex } from 'common/Types'; import { Buffer } from 'common/buffer/Buffer'; @@ -143,7 +143,7 @@ export class MockTerminal implements ITerminal { public getBufferElements(startLine: number, endLine?: number | undefined): { bufferElements: HTMLElement[], cursorElement?: HTMLElement | undefined } { throw new Error('Method not implemented.'); } - public setAccessibilityBufferElements(elements: HTMLElement[]): DocumentFragment { + public registerBufferElementProvider(bufferProvider: IBufferElementProvider): IDisposable { throw new Error('Method not implemented.'); } public bracketedPasteMode!: boolean; diff --git a/src/browser/Types.d.ts b/src/browser/Types.d.ts index a8ec2808ea..343c2fe515 100644 --- a/src/browser/Types.d.ts +++ b/src/browser/Types.d.ts @@ -79,8 +79,8 @@ export interface IPublicTerminal extends IDisposable { paste(data: string): void; refresh(start: number, end: number): void; clearTextureAtlas(): void; - setAccessibilityBufferElements(elements: HTMLElement[]): DocumentFragment; reset(): void; + registerBufferElementProvider(bufferProvider: IBufferElementProvider): IDisposable; } export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean; @@ -221,3 +221,7 @@ export interface IRenderDebouncer extends IDisposable { export interface IRenderDebouncerWithCallback extends IRenderDebouncer { addRefreshCallback(callback: FrameRequestCallback): number; } + +export interface IBufferElementProvider { + provideBufferElements(callback: (fragment: DocumentFragment) => void): void; +} \ No newline at end of file diff --git a/src/browser/public/Terminal.ts b/src/browser/public/Terminal.ts index cb1bac22d7..43e92cf61c 100644 --- a/src/browser/public/Terminal.ts +++ b/src/browser/public/Terminal.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { Terminal as ITerminalApi, IMarker, IDisposable, ILocalizableStrings, ITerminalAddon, IBufferNamespace as IBufferNamespaceApi, IParser, ILinkProvider, IUnicodeHandling, IModes, IDecorationOptions, IDecoration } from 'xterm'; +import { Terminal as ITerminalApi, IMarker, IDisposable, ILocalizableStrings, ITerminalAddon, IBufferNamespace as IBufferNamespaceApi, IParser, ILinkProvider, IUnicodeHandling, IModes, IDecorationOptions, IDecoration, IBufferElementProvider } from 'xterm'; import { IBufferRange, ITerminal } from 'browser/Types'; import { Terminal as TerminalCore } from 'browser/Terminal'; import * as Strings from 'browser/LocalizableStrings'; @@ -236,8 +236,8 @@ export class Terminal implements ITerminalApi { public loadAddon(addon: ITerminalAddon): void { return this._addonManager.loadAddon(this, addon); } - public setAccessibilityBufferElements(elements: HTMLElement[]): DocumentFragment { - return this._core.setAccessibilityBufferElements(elements); + public registerBufferElementProvider(bufferProvider: IBufferElementProvider): IDisposable { + return this._core.registerBufferElementProvider(bufferProvider); } public static get strings(): ILocalizableStrings { return Strings; diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 1907d3eb20..da11077fc3 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -1110,11 +1110,11 @@ declare module 'xterm' { loadAddon(addon: ITerminalAddon): void; - /** - * Sets the accessibility buffer children. - * @param elements The elements to add to the accessibility buffer. - */ - setAccessibilityBufferElements(elements: HTMLElement[]): DocumentFragment; + /** + * Registers a buffer element provider + * @param bufferProvider + */ + registerBufferElementProvider(bufferProvider: IBufferElementProvider): IDisposable; } /** @@ -1367,6 +1367,14 @@ declare module 'xterm' { getNullCell(): IBufferCell; } + export interface IBufferElementProvider { + /** + * Provides a buffer element provider + * @param callback The callback to be fired when the buffer elements are requested + */ + provideBufferElements(callback: (fragment: DocumentFragment) => void): void; + } + /** * Represents the terminal's set of buffers. */ From 9d9d83e086ab481606ff1a601667150b3bdaf04e Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 7 Feb 2023 11:18:57 -0600 Subject: [PATCH 6/7] fix --- src/browser/AccessibleBuffer.ts | 22 ++++++---------------- src/browser/Types.d.ts | 2 +- typings/xterm.d.ts | 7 +++---- 3 files changed, 10 insertions(+), 21 deletions(-) diff --git a/src/browser/AccessibleBuffer.ts b/src/browser/AccessibleBuffer.ts index bb96b5db30..5c58d76211 100644 --- a/src/browser/AccessibleBuffer.ts +++ b/src/browser/AccessibleBuffer.ts @@ -16,7 +16,7 @@ export class AccessibleBuffer extends Disposable { private _accessiblityBuffer: HTMLElement; private _isAccessibilityBufferActive: boolean = false; public get isAccessibilityBufferActive(): boolean { return this._isAccessibilityBufferActive; } - private _providers: IBufferElementProvider[] = []; + private _provider: IBufferElementProvider | undefined;; constructor( private readonly _terminal: ITerminal, @IOptionsService optionsService: IOptionsService, @@ -56,14 +56,10 @@ export class AccessibleBuffer extends Disposable { } public registerBufferElementProvider(bufferProvider: IBufferElementProvider): IDisposable { - this._providers.push(bufferProvider); + this._provider = bufferProvider; return { dispose: () => { - const providerIndex = this._providers.indexOf(bufferProvider); - - if (providerIndex !== -1) { - this._providers.splice(providerIndex, 1); - } + this._provider = undefined; } }; } @@ -74,10 +70,8 @@ export class AccessibleBuffer extends Disposable { } this._isAccessibilityBufferActive = true; this._accessiblityBuffer.scrollTop = this._accessiblityBuffer.scrollHeight; - if (this._terminal.options.screenReaderMode) { - return; - } - if (!this._providers.length) { + const bufferElements = this._provider?.provideBufferElements(); + if (!bufferElements) { const { bufferElements } = this._terminal.viewport.getBufferElements(0); for (const element of bufferElements) { if (element.textContent) { @@ -86,11 +80,7 @@ export class AccessibleBuffer extends Disposable { } this._accessiblityBuffer.replaceChildren(...bufferElements); } else { - const fragment = document.createDocumentFragment(); - for (const provider of this._providers) { - provider.provideBufferElements((f) => fragment.appendChild(f)); - } - this._accessiblityBuffer.replaceChildren(fragment); + this._accessiblityBuffer.replaceChildren(bufferElements); } } diff --git a/src/browser/Types.d.ts b/src/browser/Types.d.ts index 343c2fe515..8999058f0d 100644 --- a/src/browser/Types.d.ts +++ b/src/browser/Types.d.ts @@ -223,5 +223,5 @@ export interface IRenderDebouncerWithCallback extends IRenderDebouncer { } export interface IBufferElementProvider { - provideBufferElements(callback: (fragment: DocumentFragment) => void): void; + provideBufferElements(): DocumentFragment; } \ No newline at end of file diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index da11077fc3..066f143c0b 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -1112,7 +1112,7 @@ declare module 'xterm' { /** * Registers a buffer element provider - * @param bufferProvider + * @param bufferProvider */ registerBufferElementProvider(bufferProvider: IBufferElementProvider): IDisposable; } @@ -1369,10 +1369,9 @@ declare module 'xterm' { export interface IBufferElementProvider { /** - * Provides a buffer element provider - * @param callback The callback to be fired when the buffer elements are requested + * Provides a document fragment containing the buffer elements. */ - provideBufferElements(callback: (fragment: DocumentFragment) => void): void; + provideBufferElements(): DocumentFragment; } /** From b77410c7b2a9b000f92d6e3e132856246ff6c05f Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 7 Feb 2023 11:34:56 -0600 Subject: [PATCH 7/7] address feedback + lint --- src/browser/AccessibleBuffer.ts | 7 +++++-- src/browser/Terminal.ts | 4 ++-- src/browser/Types.d.ts | 2 +- typings/xterm.d.ts | 9 +++++---- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/browser/AccessibleBuffer.ts b/src/browser/AccessibleBuffer.ts index 5c58d76211..b2d160d96d 100644 --- a/src/browser/AccessibleBuffer.ts +++ b/src/browser/AccessibleBuffer.ts @@ -16,7 +16,7 @@ export class AccessibleBuffer extends Disposable { private _accessiblityBuffer: HTMLElement; private _isAccessibilityBufferActive: boolean = false; public get isAccessibilityBufferActive(): boolean { return this._isAccessibilityBufferActive; } - private _provider: IBufferElementProvider | undefined;; + private _provider: IBufferElementProvider | undefined; constructor( private readonly _terminal: ITerminal, @IOptionsService optionsService: IOptionsService, @@ -25,7 +25,7 @@ export class AccessibleBuffer extends Disposable { ) { super(); if (!this._terminal.element) { - throw new Error('Cannot enable accessibility before Terminal.open'); + throw new Error('Cannot enable accessibility buffer before Terminal.open'); } this._accessiblityBuffer = document.createElement('div'); @@ -56,6 +56,9 @@ export class AccessibleBuffer extends Disposable { } public registerBufferElementProvider(bufferProvider: IBufferElementProvider): IDisposable { + if (this._provider) { + throw new Error('Buffer element provider already registered'); + } this._provider = bufferProvider; return { dispose: () => { diff --git a/src/browser/Terminal.ts b/src/browser/Terminal.ts index 3e609c7bf0..fc4dce235c 100644 --- a/src/browser/Terminal.ts +++ b/src/browser/Terminal.ts @@ -195,10 +195,10 @@ export class Terminal extends CoreTerminal implements ITerminal { public registerBufferElementProvider(bufferProvider: IBufferElementProvider): IDisposable { if (!this._accessibleBuffer) { - throw new Error ('No accessible buffer'); + throw new Error ('Cannot register buffer element provider when terminal has not been opened yet'); } return this._accessibleBuffer.registerBufferElementProvider(bufferProvider); - } + } /** * Handle color event from inputhandler for OSC 4|104 | 10|110 | 11|111 | 12|112. diff --git a/src/browser/Types.d.ts b/src/browser/Types.d.ts index 8999058f0d..43af106cc9 100644 --- a/src/browser/Types.d.ts +++ b/src/browser/Types.d.ts @@ -224,4 +224,4 @@ export interface IRenderDebouncerWithCallback extends IRenderDebouncer { export interface IBufferElementProvider { provideBufferElements(): DocumentFragment; -} \ No newline at end of file +} diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 066f143c0b..1b8e05d1f3 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -1109,10 +1109,11 @@ declare module 'xterm' { */ loadAddon(addon: ITerminalAddon): void; - - /** - * Registers a buffer element provider - * @param bufferProvider + /* + * Registers a buffer element provider which will provide a custom element to + * use in the terminal's accessible buffer. Using this an xterm.js embedder + * has full control over how the buffer is represented in the DOM. + * @param bufferElementProvider The buffer element provider. */ registerBufferElementProvider(bufferProvider: IBufferElementProvider): IDisposable; }