diff options
Diffstat (limited to 'html/src/components')
-rw-r--r-- | html/src/components/app.tsx | 6 | ||||
-rw-r--r-- | html/src/components/terminal/index.tsx | 2 | ||||
-rw-r--r-- | html/src/components/terminal/xterm/addons/overlay.ts | 2 | ||||
-rw-r--r-- | html/src/components/terminal/xterm/addons/zmodem.ts | 4 | ||||
-rw-r--r-- | html/src/components/terminal/xterm/index.ts | 80 |
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 |