diff --git a/.vscode/settings.json b/.vscode/settings.json
index 7fef8b16..2c1653d3 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -2,6 +2,7 @@
"chat.tools.terminal.autoApprove": {
"npm run build": true,
"npm run esbuild": true,
+ "npm run dev": true,
"npm run lint": true,
"npm run lint-fix": true,
"npm run lint-api": true,
diff --git a/bin/esbuild.mjs b/bin/esbuild.mjs
index 1727defe..b1e9e88f 100644
--- a/bin/esbuild.mjs
+++ b/bin/esbuild.mjs
@@ -12,6 +12,7 @@ const config = {
isProd: argv.includes('--prod'),
isWatch: argv.includes('--watch'),
isDemoClient: argv.includes('--demo-client'),
+ isDemoServer: argv.includes('--demo-server'),
isHeadless: argv.includes('--headless'),
addon: argv.find(e => e.startsWith('--addon='))?.replace(/^--addon=/, ''),
};
@@ -126,7 +127,7 @@ if (config.addon) {
} else if (config.isDemoClient) {
bundleConfig = {
...bundleConfig,
- entryPoints: [`demo/client.ts`],
+ entryPoints: [`demo/client/client.ts`],
outfile: 'demo/dist/client-bundle.js',
external: ['util', 'os', 'fs', 'path', 'stream', 'Terminal'],
alias: {
@@ -152,6 +153,19 @@ if (config.addon) {
"@xterm/addon-ligatures": "./addons/addon-ligatures/out-esbuild/LigaturesAddon",
}
}
+ skipOut = true;
+ skipOutTest = true;
+} else if (config.isDemoServer) {
+ bundleConfig = {
+ ...bundleConfig,
+ entryPoints: [`demo/server/server.ts`],
+ outfile: 'demo/dist/server-bundle.js',
+ format: 'cjs',
+ platform: 'node',
+ external: ['node-pty'],
+ }
+ skipOut = true;
+ skipOutTest = true;
} else if (config.isHeadless) {
bundleConfig = {
...bundleConfig,
diff --git a/demo/client.ts b/demo/client/client.ts
similarity index 100%
rename from demo/client.ts
rename to demo/client/client.ts
diff --git a/demo/components/controlBar.ts b/demo/client/components/controlBar.ts
similarity index 100%
rename from demo/components/controlBar.ts
rename to demo/client/components/controlBar.ts
diff --git a/demo/components/window/addonsWindow.ts b/demo/client/components/window/addonsWindow.ts
similarity index 100%
rename from demo/components/window/addonsWindow.ts
rename to demo/client/components/window/addonsWindow.ts
diff --git a/demo/components/window/baseWindow.ts b/demo/client/components/window/baseWindow.ts
similarity index 100%
rename from demo/components/window/baseWindow.ts
rename to demo/client/components/window/baseWindow.ts
diff --git a/demo/components/window/gpuWindow.ts b/demo/client/components/window/gpuWindow.ts
similarity index 100%
rename from demo/components/window/gpuWindow.ts
rename to demo/client/components/window/gpuWindow.ts
diff --git a/demo/components/window/optionsWindow.ts b/demo/client/components/window/optionsWindow.ts
similarity index 100%
rename from demo/components/window/optionsWindow.ts
rename to demo/client/components/window/optionsWindow.ts
diff --git a/demo/components/window/styleWindow.ts b/demo/client/components/window/styleWindow.ts
similarity index 100%
rename from demo/components/window/styleWindow.ts
rename to demo/client/components/window/styleWindow.ts
diff --git a/demo/components/window/testWindow.ts b/demo/client/components/window/testWindow.ts
similarity index 99%
rename from demo/components/window/testWindow.ts
rename to demo/client/components/window/testWindow.ts
index 99efbad4..bb542595 100644
--- a/demo/components/window/testWindow.ts
+++ b/demo/client/components/window/testWindow.ts
@@ -3,9 +3,9 @@
* @license MIT
*/
-///
+///
-import { writeUnicodeTable } from 'unicodeTable';
+import { writeUnicodeTable } from '../../unicodeTable';
import type { IControlWindow } from '../controlBar';
import { BaseWindow } from './baseWindow';
import type { IDisposable, Terminal } from '@xterm/xterm';
diff --git a/demo/components/window/vtWindow.ts b/demo/client/components/window/vtWindow.ts
similarity index 100%
rename from demo/components/window/vtWindow.ts
rename to demo/client/components/window/vtWindow.ts
diff --git a/demo/client/tsconfig.json b/demo/client/tsconfig.json
new file mode 100644
index 00000000..7676cd37
--- /dev/null
+++ b/demo/client/tsconfig.json
@@ -0,0 +1,27 @@
+{
+ "compilerOptions": {
+ "module": "commonjs",
+ "target": "es2021",
+ "rootDir": ".",
+ "sourceMap": true,
+ "baseUrl": ".",
+ "paths": {
+ "@xterm/addon-attach": ["../../addons/addon-attach"],
+ "@xterm/addon-clipboard": ["../../addons/addon-clipboard"],
+ "@xterm/addon-fit": ["../../addons/addon-fit"],
+ "@xterm/addon-image": ["../../addons/addon-image"],
+ "@xterm/addon-progress": ["../../addons/addon-progress"],
+ "@xterm/addon-search": ["../../addons/addon-search"],
+ "@xterm/addon-serialize": ["../../addons/addon-serialize"],
+ "@xterm/addon-web-links": ["../../addons/addon-web-links"],
+ "@xterm/addon-webgl": ["../../addons/addon-webgl"],
+ "@xterm/addon-unicode11": ["../../addons/addon-unicode11"],
+ "@xterm/addon-unicode-graphemes": ["../../addons/addon-unicode-graphemes"],
+ "@xterm/addon-ligatures": ["../../addons/addon-ligatures"]
+ }
+ },
+ "include": [
+ "client.ts",
+ "../../typings/xterm.d.ts"
+ ]
+}
diff --git a/demo/unicodeTable.ts b/demo/client/unicodeTable.ts
similarity index 100%
rename from demo/unicodeTable.ts
rename to demo/client/unicodeTable.ts
diff --git a/demo/server.js b/demo/server/server.ts
similarity index 78%
rename from demo/server.js
rename to demo/server/server.ts
index 4537d501..cefb343e 100644
--- a/demo/server.js
+++ b/demo/server/server.ts
@@ -4,54 +4,58 @@
* demo to the public as is would introduce security risks for the host.
**/
-// @ts-check
+import * as express from 'express';
+import * as expressWs from 'express-ws';
+import * as os from 'os';
+import * as pty from 'node-pty';
+import * as path from 'path';
+import type { IPty } from 'node-pty';
-const express = require('express');
-const expressWs = require('express-ws');
-const os = require('os');
-const pty = require('node-pty');
+interface IDisposable {
+ dispose(): void;
+}
/** Whether to use binary transport. */
const USE_BINARY = os.platform() !== "win32";
-function startServer() {
+const demoRoot = path.join(__dirname, '..');
+
+function startServer(): void {
const app = express();
const appWs = expressWs(app).app;
- const terminals = {};
- const unsentOutput = {};
- const temporaryDisposable = {};
+ const terminals: { [pid: number]: IPty } = {};
+ const unsentOutput: { [pid: number]: string } = {};
+ const temporaryDisposable: { [pid: number]: IDisposable } = {};
- app.use('/xterm.css', express.static(__dirname + '/../css/xterm.css'));
+ app.use('/xterm.css', express.static(demoRoot + '/../css/xterm.css'));
app.get('/logo.png', (req, res) => {
- res.sendFile(__dirname + '/logo.png');
+ res.sendFile(demoRoot + '/logo.png');
});
app.get('/', (req, res) => {
- res.sendFile(__dirname + '/index.html');
+ res.sendFile(demoRoot + '/index.html');
});
app.get('/test', (req, res) => {
- res.sendFile(__dirname + '/test.html');
+ res.sendFile(demoRoot + '/test.html');
});
app.get('/index.css', (req, res) => {
- res.sendFile(__dirname + '/index.css');
+ res.sendFile(demoRoot + '/index.css');
});
- app.use('/dist', express.static(__dirname + '/dist'));
- app.use('/src', express.static(__dirname + '/src'));
+ app.use('/dist', express.static(demoRoot + '/dist'));
+ app.use('/src', express.static(demoRoot + '/src'));
app.post('/terminals', (req, res) => {
- /** @type {{ [key: string]: string }} */
- const env = {};
+ const env: { [key: string]: string } = {};
for (const k of Object.keys(process.env)) {
const v = process.env[k];
if (v) {
env[k] = v;
}
}
- // const env = Object.assign({}, process.env);
env['COLORTERM'] = 'truecolor';
if (typeof req.query.cols !== 'string' || typeof req.query.rows !== 'string') {
console.error({ req });
@@ -108,10 +112,10 @@ function startServer() {
let userInput = false;
// string message buffering
- function buffer(socket, timeout, maxSize) {
+ function buffer(socket: typeof ws, timeout: number, maxSize: number) {
let s = '';
- let sender = null;
- return (data) => {
+ let sender: ReturnType | null = null;
+ return (data: string) => {
s += data;
if (s.length > maxSize || userInput) {
userInput = false;
@@ -131,11 +135,11 @@ function startServer() {
};
}
// binary message buffering
- function bufferUtf8(socket, timeout, maxSize) {
- const chunks = [];
+ function bufferUtf8(socket: typeof ws, timeout: number, maxSize: number) {
+ const chunks: Buffer[] = [];
let length = 0;
- let sender = null;
- return (data) => {
+ let sender: ReturnType | null = null;
+ return (data: Buffer) => {
chunks.push(data);
length += data.length;
if (length > maxSize || userInput) {
@@ -164,13 +168,13 @@ function startServer() {
// the problem and how to implement flow control at https://xtermjs.org/docs/guides/flowcontrol/
term.onData(function(data) {
try {
- send(data);
+ send(data as string & Buffer);
} catch (ex) {
// The WebSocket is not open, ignore
}
});
ws.on('message', function(msg) {
- term.write(msg);
+ term.write(msg.toString());
userInput = true;
});
ws.on('close', function () {
@@ -196,4 +200,4 @@ process.on('uncaughtException', (error) => {
}
});
-module.exports = startServer;
+export default startServer;
diff --git a/demo/server/tsconfig.json b/demo/server/tsconfig.json
new file mode 100644
index 00000000..ed5c6a90
--- /dev/null
+++ b/demo/server/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "compilerOptions": {
+ "module": "commonjs",
+ "target": "es2021",
+ "rootDir": ".",
+ "sourceMap": true
+ },
+ "include": [
+ "server.ts"
+ ]
+}
diff --git a/demo/start.js b/demo/start.js
index b240966f..08f9c059 100644
--- a/demo/start.js
+++ b/demo/start.js
@@ -5,6 +5,6 @@
// @ts-check
-const startServer = require('./server.js');
+const startServer = require('./dist/server-bundle.js').default;
startServer();
diff --git a/demo/tsconfig.json b/demo/tsconfig.json
index 405dbf0f..e9e26053 100644
--- a/demo/tsconfig.json
+++ b/demo/tsconfig.json
@@ -1,27 +1,7 @@
{
- "compilerOptions": {
- "module": "commonjs",
- "target": "es2021",
- "rootDir": ".",
- "sourceMap": true,
- "baseUrl": ".",
- "paths": {
- "@xterm/addon-attach": ["../addons/addon-attach"],
- "@xterm/addon-clipboard": ["../addons/addon-clipboard"],
- "@xterm/addon-fit": ["../addons/addon-fit"],
- "@xterm/addon-image": ["../addons/addon-image"],
- "@xterm/addon-progress": ["../addons/addon-progress"],
- "@xterm/addon-search": ["../addons/addon-search"],
- "@xterm/addon-serialize": ["../addons/addon-serialize"],
- "@xterm/addon-web-links": ["../addons/addon-web-links"],
- "@xterm/addon-webgl": ["../addons/addon-webgl"],
- "@xterm/addon-unicode11": ["../addons/addon-unicode11"],
- "@xterm/addon-unicode-graphemes": ["../addons/addon-unicode-graphemes"],
- "@xterm/addon-ligatures": ["../addons/addon-ligatures"]
- }
- },
- "include": [
- "client.ts",
- "../typings/xterm.d.ts"
- ]
+ "references": [
+ { "path": "./client" },
+ { "path": "./server" }
+ ],
+ "files": []
}