always refer to navigator.clipboard in default provider

This commit is contained in:
Jörg Breitbart
2026-05-10 18:00:26 +02:00
parent 6f55150485
commit c5a11220c1
3 changed files with 35 additions and 33 deletions
+5 -11
View File
@@ -4,7 +4,7 @@
*/
import type { IDisposable, ITerminalAddon, Terminal } from '@xterm/xterm';
import { type IClipboardProvider, ClipboardSelectionType, type IBase64 } from '@xterm/addon-clipboard';
import { type IClipboardProvider, type IBase64 } from '@xterm/addon-clipboard';
export class ClipboardAddon implements ITerminalAddon {
private _terminal?: Terminal;
@@ -24,7 +24,7 @@ export class ClipboardAddon implements ITerminalAddon {
return this._disposable?.dispose();
}
private _readText(sel: ClipboardSelectionType, data: string): void {
private _readText(sel: string, data: string): void {
const b64 = this._base64.encodeText(data);
this._terminal?.input(`\x1b]52;${sel};${b64}\x07`, false);
}
@@ -35,7 +35,7 @@ export class ClipboardAddon implements ITerminalAddon {
return true;
}
const pc = args[0] as ClipboardSelectionType;
const pc = args[0];
const pd = args[1];
if (pd === '?') {
const text = this._provider.readText(pc);
@@ -69,17 +69,11 @@ export class ClipboardAddon implements ITerminalAddon {
}
export class BrowserClipboardProvider implements IClipboardProvider {
public async readText(selection: ClipboardSelectionType): Promise<string> {
if (selection !== 'c') {
return Promise.resolve('');
}
public readText(selection: string): Promise<string> {
return navigator.clipboard.readText();
}
public async writeText(selection: ClipboardSelectionType, text: string): Promise<void> {
if (selection !== 'c') {
return Promise.resolve();
}
public writeText(selection: string, text: string): Promise<void> {
return navigator.clipboard.writeText(text);
}
}
@@ -48,6 +48,14 @@ test.describe('ClipboardAddon', () => {
await ctx.proxy.write(`\x1b]52;c;${testDataEncoded}\x07`);
deepEqual(await ctx.page.evaluate(() => window.navigator.clipboard.readText()), testDataDecoded);
});
test('primary selection', async () => {
await ctx.proxy.write(`\x1b]52;p;${testDataEncoded}\x07`);
deepEqual(await ctx.page.evaluate(() => window.navigator.clipboard.readText()), testDataDecoded);
});
test('empty selection (default)', async () => {
await ctx.proxy.write(`\x1b]52;;${testDataEncoded}\x07`);
deepEqual(await ctx.page.evaluate(() => window.navigator.clipboard.readText()), testDataDecoded);
});
test('invalid base64 string', async () => {
await ctx.proxy.write(`\x1b]52;c;${testDataEncoded}invalid\x07`);
deepEqual(await ctx.page.evaluate(() => window.navigator.clipboard.readText()), '');
@@ -60,15 +68,24 @@ test.describe('ClipboardAddon', () => {
});
test.describe('read data', async function (): Promise<any> {
test('simple string', async () => {
test.beforeAll(async () => {
await ctx.page.evaluate(`
window.data = [];
window.term.onData(e => data.push(e));
`);
});
test('simple string', async () => {
await ctx.page.evaluate('window.data.length = 0;');
await ctx.page.evaluate(() => window.navigator.clipboard.writeText('hello world'));
await ctx.proxy.write(`\x1b]52;c;?\x07`);
deepEqual(await ctx.page.evaluate('window.data'), [`\x1b]52;c;${testDataEncoded}\x07`]);
});
test('primary selection', async () => {
await ctx.page.evaluate('window.data.length = 0;');
await ctx.page.evaluate(() => window.navigator.clipboard.writeText('hello world'));
await ctx.proxy.write(`\x1b]52;p;?\x07`);
deepEqual(await ctx.page.evaluate('window.data'), [`\x1b]52;p;${testDataEncoded}\x07`]);
});
test('clear clipboard', async () => {
await ctx.proxy.write(`\x1b]52;c;!\x07`);
await ctx.proxy.write(`\x1b]52;c;?\x07`);
+12 -21
View File
@@ -30,18 +30,6 @@ declare module '@xterm/addon-clipboard' {
public dispose(): void
}
/**
* Clipboard selection type. This is used to specify which selection buffer to
* read or write to.
* - SYSTEM `c`: The system clipboard.
* - PRIMARY `p`: The primary clipboard. This is provided for compatibility
* with Linux X11.
*/
export const enum ClipboardSelectionType {
SYSTEM = 'c',
PRIMARY = 'p',
}
export interface IBase64 {
/**
* Converts a utf-8 string to a base64 string.
@@ -78,36 +66,39 @@ declare module '@xterm/addon-clipboard' {
export interface IClipboardProvider {
/**
* Gets the clipboard content.
* @param selection The clipboard selection to read.
* @param selection The clipboard selection to read (see OSC 52 spec of xterm).
* @returns A promise that resolves with clipboard selection data.
*/
readText(selection: ClipboardSelectionType): string | Promise<string>;
readText(selection: string): string | Promise<string>;
/**
* Sets the clipboard content.
* @param selection The clipboard selection to set.
* @param selection The clipboard selection to set (see OSC 52 spec of xterm).
* @param data The clipboard text to write.
*/
writeText(selection: ClipboardSelectionType, text: string): void | Promise<void>;
writeText(selection: string, text: string): void | Promise<void>;
}
/**
* The clipboard provider interface that enables xterm.js to access the system clipboard.
* The clipboard provider interface that enables xterm.js to access the browser clipboard.
*
* Note this this clipboard provider does not implement own cut buffers as xterm does,
* but redirect the selection parameter always to navigator.clipboard.
*/
export class BrowserClipboardProvider implements IClipboardProvider{
/**
* Reads text from the clipboard.
* @param selection The selection type to read from.
* @param selection The selection type to read from (always refers to navigator.clipboard).
* @returns A promise that resolves with the text from the clipboard.
*/
public readText(selection: ClipboardSelectionType): Promise<string>;
public readText(selection: string): Promise<string>;
/**
* Writes text to the clipboard.
* @param selection The selection type to write to.
* @param selection The selection type to write to (always refers to navigator.clipboard).
* @param data The text to write to the clipboard.
* @returns A promise that resolves when the text has been written to the clipboard.
*/
public writeText(selection: ClipboardSelectionType, data: string): Promise<void>;
public writeText(selection: string, data: string): Promise<void>;
}
}