mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Update addon-clipboard
This commit is contained in:
@@ -1,2 +1,2 @@
|
||||
lib
|
||||
node_modules
|
||||
node_modules
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"prepublishOnly": "npm run package"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"xterm": "^5.3.0"
|
||||
"@xterm/xterm": "^5.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"js-base64": "^3.7.5"
|
||||
|
||||
@@ -3,18 +3,125 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { ClipboardProvider } from './ClipboardProvider';
|
||||
import { IClipboardProvider, IDisposable, ITerminalAddon, Terminal } from '@xterm/xterm';
|
||||
import type { IDisposable, ITerminalAddon, Terminal } from '@xterm/xterm';
|
||||
import { type IClipboardProvider, ClipboardSelectionType } from '@xterm/addon-clipboard';
|
||||
import { Base64 as JSBase64 } from 'js-base64';
|
||||
|
||||
export class ClipboardAddon implements ITerminalAddon {
|
||||
private _disposable: IDisposable | undefined;
|
||||
constructor(private _provider: IClipboardProvider = new ClipboardProvider()) {}
|
||||
private readonly _provider: IClipboardProvider;
|
||||
private _terminal?: Terminal;
|
||||
private _disposable?: IDisposable;
|
||||
|
||||
constructor(provider: IClipboardProvider = new ClipboardProvider()) {
|
||||
this._provider = provider;
|
||||
}
|
||||
|
||||
public activate(terminal: Terminal): void {
|
||||
this._disposable = terminal.registerClipboardProvider(this._provider);
|
||||
this._disposable = terminal.parser.registerOscHandler(52, this._setOrReportClipboard);
|
||||
this._terminal = terminal;
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
return this._disposable?.dispose();
|
||||
}
|
||||
|
||||
private _setOrReportClipboard(data: string): boolean | Promise<boolean> {
|
||||
const args = data.split(';');
|
||||
if (args.length < 2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const pc = args[0];
|
||||
const pd = args[1];
|
||||
if (pd.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (pc) {
|
||||
case ClipboardSelectionType.SYSTEM:
|
||||
case ClipboardSelectionType.PRIMARY:
|
||||
try {
|
||||
if (pd === '?') {
|
||||
// Report clipboard
|
||||
return this._provider.readText(pc).then(data => {
|
||||
this._terminal?.input(data, false);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
return this._provider.writeText(pc, pd).then(() => true);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export class ClipboardProvider implements IClipboardProvider {
|
||||
private _base64: IBase64;
|
||||
public limit: number;
|
||||
|
||||
constructor(
|
||||
/**
|
||||
* The base64 encoder/decoder to use.
|
||||
*/
|
||||
base64: IBase64 = new Base64(),
|
||||
|
||||
/**
|
||||
* The maximum amount of data that can be copied to the clipboard.
|
||||
* Zero means no limit.
|
||||
*/
|
||||
limit: number = 0 // unlimited
|
||||
){
|
||||
this._base64 = base64;
|
||||
this.limit = limit;
|
||||
}
|
||||
|
||||
public readText(selection: ClipboardSelectionType): Promise<string> {
|
||||
if (selection !== 'c') {
|
||||
return Promise.resolve('');
|
||||
}
|
||||
return navigator.clipboard.readText().then(this._base64.encodeText);
|
||||
}
|
||||
|
||||
public writeText(selection: ClipboardSelectionType, data: string): Promise<void> {
|
||||
if (selection !== 'c' || (this.limit > 0 && data.length > this.limit)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
try {
|
||||
const text = this._base64.decodeText(data);
|
||||
return navigator.clipboard.writeText(text);
|
||||
} catch {
|
||||
// clear the clipboard if the data is not valid base64
|
||||
return navigator.clipboard.writeText('');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface IBase64 {
|
||||
/**
|
||||
* Converts a utf-8 string to a base64 string.
|
||||
* @param data The utf-8 string to convert to base64 string.
|
||||
*/
|
||||
encodeText(data: string): string;
|
||||
|
||||
/**
|
||||
* Converts a base64 string to a utf-8 string.
|
||||
* @param data The base64 string to convert to utf-8 string.
|
||||
*/
|
||||
decodeText(data: string): string;
|
||||
}
|
||||
|
||||
export class Base64 implements IBase64 {
|
||||
public encodeText(data: string): string {
|
||||
return JSBase64.encode(data);
|
||||
}
|
||||
public decodeText(data: string): string {
|
||||
const text = JSBase64.decode(data);
|
||||
if (!JSBase64.isValid(data) || JSBase64.encode(text) !== data) {
|
||||
return '';
|
||||
}
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2023 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { Base64 } from 'js-base64';
|
||||
import { ClipboardSelectionType, IClipboardProvider } from '@xterm/xterm';
|
||||
|
||||
export class ClipboardProvider implements IClipboardProvider {
|
||||
constructor(
|
||||
/**
|
||||
* The maximum amount of data that can be copied to the clipboard.
|
||||
* Zero means no limit.
|
||||
*/
|
||||
public limit = 1000000 // 1MB
|
||||
){}
|
||||
public readText(selection: ClipboardSelectionType): Promise<string> {
|
||||
if (selection !== 'c') {
|
||||
return Promise.resolve('');
|
||||
}
|
||||
return navigator.clipboard.readText().then((text) =>
|
||||
Base64.encode(text));
|
||||
}
|
||||
public writeText(selection: ClipboardSelectionType, data: string): Promise<void> {
|
||||
if (selection !== 'c' || (this.limit > 0 && data.length > this.limit)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
const text = Base64.decode(data);
|
||||
// clear the clipboard if the data is not valid base64
|
||||
if (!Base64.isValid(data) || Base64.encode(text) !== data) {
|
||||
return navigator.clipboard.writeText('');
|
||||
}
|
||||
return navigator.clipboard.writeText(text);
|
||||
}
|
||||
}
|
||||
@@ -2,22 +2,24 @@
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es2021",
|
||||
"sourceMap": true,
|
||||
"outDir": "../out",
|
||||
"lib": [
|
||||
"dom",
|
||||
"es2015"
|
||||
],
|
||||
"rootDir": ".",
|
||||
"outDir": "../out",
|
||||
"sourceMap": true,
|
||||
"removeComments": true,
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"preserveWatchOutput": true,
|
||||
"types": [
|
||||
"../../../node_modules/@types/mocha"
|
||||
],
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"browser/*": [
|
||||
"../../../src/browser/*"
|
||||
],
|
||||
"common/*": [
|
||||
"../../../src/common/*"
|
||||
"@xterm/addon-clipboard": [
|
||||
"../typings/addon-clipboard.d.ts"
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -28,9 +30,6 @@
|
||||
"references": [
|
||||
{
|
||||
"path": "../../../src/browser"
|
||||
},
|
||||
{
|
||||
"path": "../../../src/common"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ describe('ClipboardAddon', () => {
|
||||
page = await context.newPage();
|
||||
await page.setViewportSize({ width, height });
|
||||
await page.goto(APP);
|
||||
await openTerminal(page, { allowClipboardAccess: true });
|
||||
await openTerminal(page);
|
||||
await page.evaluate(`
|
||||
window.clipboardAddon = new ClipboardAddon();
|
||||
window.term.loadAddon(window.clipboardAddon);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"module": "commonjs",
|
||||
"target": "es2021",
|
||||
"lib": [
|
||||
"es2021"
|
||||
"es2015"
|
||||
],
|
||||
"rootDir": ".",
|
||||
"outDir": "../out-test",
|
||||
@@ -13,6 +13,7 @@
|
||||
"types": [
|
||||
"../../../node_modules/@types/mocha",
|
||||
"../../../node_modules/@types/node",
|
||||
"../../../out-test/api/TestUtils"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
|
||||
+72
-7
@@ -3,14 +3,9 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { Terminal, ITerminalAddon, IClipboardProvider, ClipboardSelection as ClipboardSelectionType } from 'xterm';
|
||||
import { Terminal, ITerminalAddon } from '@xterm/xterm';
|
||||
|
||||
declare module '@xterm/addon-clipboard' {
|
||||
export class ClipboardProvider implements IClipboardProvider{
|
||||
public readText(selection: ClipboardSelectionType): Promise<string>;
|
||||
public writeText(selection: ClipboardSelectionType, data: string): Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
* An xterm.js addon that enables accessing the system clipboard from
|
||||
* xterm.js.
|
||||
@@ -19,7 +14,7 @@ declare module '@xterm/addon-clipboard' {
|
||||
/**
|
||||
* Creates a new clipboard addon.
|
||||
*/
|
||||
constructor(_provider: IClipboardProvider);
|
||||
constructor(provider?: IClipboardProvider);
|
||||
|
||||
/**
|
||||
* Activates the addon
|
||||
@@ -32,4 +27,74 @@ declare module '@xterm/addon-clipboard' {
|
||||
*/
|
||||
public dispose(): void
|
||||
}
|
||||
|
||||
/**
|
||||
* The clipboard provider interface that enables xterm.js to access the system clipboard.
|
||||
*/
|
||||
export class ClipboardProvider implements IClipboardProvider{
|
||||
/**
|
||||
* Creates a new clipboard provider.
|
||||
* @param _base64 The base64 encoder/decoder to use.
|
||||
*/
|
||||
constructor(base64?: IBase64, limit?: number);
|
||||
|
||||
/**
|
||||
* Reads text from the clipboard.
|
||||
* @param selection The selection type to read from.
|
||||
* @returns A promise that resolves with the text from the clipboard.
|
||||
*/
|
||||
public readText(selection: ClipboardSelectionType): Promise<string>;
|
||||
|
||||
/**
|
||||
* Writes text to the clipboard.
|
||||
* @param selection The selection type to write to.
|
||||
* @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>;
|
||||
}
|
||||
|
||||
|
||||
export interface IBase64 {
|
||||
/**
|
||||
* Converts a utf-8 string to a base64 string.
|
||||
* @param data The utf-8 string to convert to base64 string.
|
||||
*/
|
||||
encodeText(data: string): string;
|
||||
|
||||
/**
|
||||
* Converts a base64 string to a utf-8 string.
|
||||
* @param data The base64 string to convert to utf-8 string.
|
||||
*/
|
||||
decodeText(data: string): string;
|
||||
}
|
||||
|
||||
export interface IClipboardProvider {
|
||||
/**
|
||||
* Gets the clipboard content.
|
||||
* @param selection The clipboard selection to read.
|
||||
* @returns A promise that resolves with the base64 encoded data.
|
||||
*/
|
||||
readText(selection: ClipboardSelectionType): Promise<string>;
|
||||
|
||||
/**
|
||||
* Sets the clipboard content.
|
||||
* @param selection The clipboard selection to set.
|
||||
* @param data The base64 encoded data to set. If the data is invalid
|
||||
* base64, the clipboard is cleared.
|
||||
*/
|
||||
writeText(selection: ClipboardSelectionType, data: string): Promise<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',
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
|
||||
|
||||
js-base64@^3.7.5:
|
||||
version "3.7.5"
|
||||
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.5.tgz#21e24cf6b886f76d6f5f165bfcd69cc55b9e3fca"
|
||||
integrity sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA==
|
||||
version "3.7.7"
|
||||
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.7.tgz#e51b84bf78fbf5702b9541e2cb7bfcb893b43e79"
|
||||
integrity sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==
|
||||
|
||||
Reference in New Issue
Block a user