summaryrefslogtreecommitdiffstats
path: root/html/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'html/src/components')
-rw-r--r--html/src/components/app.tsx6
-rw-r--r--html/src/components/terminal/index.tsx2
-rw-r--r--html/src/components/terminal/xterm/addons/overlay.ts2
-rw-r--r--html/src/components/terminal/xterm/addons/zmodem.ts4
-rw-r--r--html/src/components/terminal/xterm/index.ts80
5 files changed, 78 insertions, 16 deletions
diff --git a/html/src/components/app.tsx b/html/src/components/app.tsx
index 1ad5fd3..9057727 100644
--- a/html/src/components/app.tsx
+++ b/html/src/components/app.tsx
@@ -1,9 +1,10 @@
import { h, Component } from 'preact';
-import { ITerminalOptions, ITheme } from 'xterm';
-import { ClientOptions, FlowControl } from './terminal/xterm';
import { Terminal } from './terminal';
+import type { ITerminalOptions, ITheme } from '@xterm/xterm';
+import type { ClientOptions, FlowControl } from './terminal/xterm';
+
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const path = window.location.pathname.replace(/[/]+$/, '');
const wsUrl = [protocol, '//', window.location.host, path, '/ws', window.location.search].join('');
@@ -16,6 +17,7 @@ const clientOptions = {
enableTrzsz: false,
enableSixel: false,
isWindows: false,
+ unicodeVersion: '11',
} as ClientOptions;
const termOptions = {
fontSize: 13,
diff --git a/html/src/components/terminal/index.tsx b/html/src/components/terminal/index.tsx
index a7349fd..b42bf15 100644
--- a/html/src/components/terminal/index.tsx
+++ b/html/src/components/terminal/index.tsx
@@ -2,7 +2,7 @@ import { bind } from 'decko';
import { Component, h } from 'preact';
import { Xterm, XtermOptions } from './xterm';
-import 'xterm/css/xterm.css';
+import '@xterm/xterm/css/xterm.css';
import { Modal } from '../modal';
interface Props extends XtermOptions {
diff --git a/html/src/components/terminal/xterm/addons/overlay.ts b/html/src/components/terminal/xterm/addons/overlay.ts
index 6fa5a92..74da079 100644
--- a/html/src/components/terminal/xterm/addons/overlay.ts
+++ b/html/src/components/terminal/xterm/addons/overlay.ts
@@ -1,7 +1,7 @@
// ported from hterm.Terminal.prototype.showOverlay
// https://chromium.googlesource.com/apps/libapps/+/master/hterm/js/hterm_terminal.js
import { bind } from 'decko';
-import { ITerminalAddon, Terminal } from 'xterm';
+import { ITerminalAddon, Terminal } from '@xterm/xterm';
export class OverlayAddon implements ITerminalAddon {
private terminal: Terminal;
diff --git a/html/src/components/terminal/xterm/addons/zmodem.ts b/html/src/components/terminal/xterm/addons/zmodem.ts
index 8571f68..52627ef 100644
--- a/html/src/components/terminal/xterm/addons/zmodem.ts
+++ b/html/src/components/terminal/xterm/addons/zmodem.ts
@@ -1,6 +1,6 @@
import { bind } from 'decko';
import { saveAs } from 'file-saver';
-import { IDisposable, ITerminalAddon, Terminal } from 'xterm';
+import { IDisposable, ITerminalAddon, Terminal } from '@xterm/xterm';
import * as Zmodem from 'zmodem.js/src/zmodem_browser';
import { TrzszFilter } from 'trzsz';
@@ -8,6 +8,7 @@ export interface ZmodeOptions {
zmodem: boolean;
trzsz: boolean;
windows: boolean;
+ trzszDragInitTimeout: number;
onSend: () => void;
sender: (data: string | Uint8Array) => void;
writer: (data: string | Uint8Array) => void;
@@ -75,6 +76,7 @@ export class ZmodemAddon implements ITerminalAddon {
sendToServer: data => sender(data),
terminalColumns: terminal.cols,
isWindowsShell: this.options.windows,
+ dragInitTimeout: this.options.trzszDragInitTimeout,
});
const element = terminal.element as EventTarget;
this.addDisposableListener(element, 'dragover', event => event.preventDefault());
diff --git a/html/src/components/terminal/xterm/index.ts b/html/src/components/terminal/xterm/index.ts
index 06d97ee..b643f92 100644
--- a/html/src/components/terminal/xterm/index.ts
+++ b/html/src/components/terminal/xterm/index.ts
@@ -1,14 +1,16 @@
import { bind } from 'decko';
-import { IDisposable, ITerminalOptions, Terminal } from 'xterm';
-import { CanvasAddon } from 'xterm-addon-canvas';
-import { WebglAddon } from 'xterm-addon-webgl';
-import { FitAddon } from 'xterm-addon-fit';
-import { WebLinksAddon } from 'xterm-addon-web-links';
-import { ImageAddon } from 'xterm-addon-image';
+import type { IDisposable, ITerminalOptions } from '@xterm/xterm';
+import { Terminal } from '@xterm/xterm';
+import { CanvasAddon } from '@xterm/addon-canvas';
+import { WebglAddon } from '@xterm/addon-webgl';
+import { FitAddon } from '@xterm/addon-fit';
+import { WebLinksAddon } from '@xterm/addon-web-links';
+import { ImageAddon } from '@xterm/addon-image';
+import { Unicode11Addon } from '@xterm/addon-unicode11';
import { OverlayAddon } from './addons/overlay';
import { ZmodemAddon } from './addons/zmodem';
-import 'xterm/css/xterm.css';
+import '@xterm/xterm/css/xterm.css';
interface TtydTerminal extends Terminal {
fit(): void;
@@ -20,7 +22,7 @@ declare global {
}
}
-const enum Command {
+enum Command {
// server side
OUTPUT = '0',
SET_WINDOW_TITLE = '1',
@@ -45,6 +47,8 @@ export interface ClientOptions {
enableSixel: boolean;
titleFixed?: string;
isWindows: boolean;
+ trzszDragInitTimeout: number;
+ unicodeVersion: string;
}
export interface FlowControl {
@@ -294,6 +298,40 @@ export class Xterm {
}
@bind
+ private parseOptsFromUrlQuery(query: string): Preferences {
+ const { terminal } = this;
+ const { clientOptions } = this.options;
+ const prefs = {} as Preferences;
+ const queryObj = Array.from(new URLSearchParams(query) as unknown as Iterable<[string, string]>);
+
+ for (const [k, queryVal] of queryObj) {
+ let v = clientOptions[k];
+ if (v === undefined) v = terminal.options[k];
+ switch (typeof v) {
+ case 'boolean':
+ prefs[k] = queryVal === 'true' || queryVal === '1';
+ break;
+ case 'number':
+ case 'bigint':
+ prefs[k] = Number.parseInt(queryVal, 10);
+ break;
+ case 'string':
+ prefs[k] = queryVal;
+ break;
+ case 'object':
+ prefs[k] = JSON.parse(queryVal);
+ break;
+ default:
+ console.warn(`[ttyd] maybe unknown option: ${k}=${queryVal}, treating as string`);
+ prefs[k] = queryVal;
+ break;
+ }
+ }
+
+ return prefs;
+ }
+
+ @bind
private onSocketData(event: MessageEvent) {
const { textDecoder } = this;
const rawData = event.data as ArrayBuffer;
@@ -312,6 +350,7 @@ export class Xterm {
this.applyPreferences({
...this.options.clientOptions,
...JSON.parse(textDecoder.decode(data)),
+ ...this.parseOptsFromUrlQuery(window.location.search),
} as Preferences);
break;
default:
@@ -328,6 +367,7 @@ export class Xterm {
zmodem: prefs.enableZmodem,
trzsz: prefs.enableTrzsz,
windows: prefs.isWindows,
+ trzszDragInitTimeout: prefs.trzszDragInitTimeout,
onSend: this.sendCb,
sender: this.sendData,
writer: this.writeData,
@@ -335,8 +375,8 @@ export class Xterm {
this.writeFunc = data => this.zmodemAddon?.consume(data);
terminal.loadAddon(register(this.zmodemAddon));
}
- Object.keys(prefs).forEach(key => {
- const value = prefs[key];
+
+ for (const [key, value] of Object.entries(prefs)) {
switch (key) {
case 'rendererType':
this.setRendererType(value);
@@ -366,6 +406,9 @@ export class Xterm {
case 'enableTrzsz':
if (value) console.log('[ttyd] trzsz enabled');
break;
+ case 'trzszDragInitTimeout':
+ if (value) console.log(`[ttyd] trzsz drag init timeout: ${value}`);
+ break;
case 'enableSixel':
if (value) {
terminal.loadAddon(register(new ImageAddon()));
@@ -381,6 +424,21 @@ export class Xterm {
case 'isWindows':
if (value) console.log('[ttyd] is windows');
break;
+ case 'unicodeVersion':
+ switch (value) {
+ case 6:
+ case '6':
+ console.log('[ttyd] setting Unicode version: 6');
+ break;
+ case 11:
+ case '11':
+ default:
+ console.log('[ttyd] setting Unicode version: 11');
+ terminal.loadAddon(new Unicode11Addon());
+ terminal.unicode.activeVersion = '11';
+ break;
+ }
+ break;
default:
console.log(`[ttyd] option: ${key}=${JSON.stringify(value)}`);
if (terminal.options[key] instanceof Object) {
@@ -391,7 +449,7 @@ export class Xterm {
if (key.indexOf('font') === 0) fitAddon.fit();
break;
}
- });
+ }
}
@bind