mirror of
https://github.com/tsl0922/ttyd.git
synced 2025-12-24 20:54:21 +01:00
html: upgrade to gts 4.0.0
This commit is contained in:
1
.github/dependabot.yml
vendored
1
.github/dependabot.yml
vendored
@@ -6,5 +6,4 @@ updates:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
ignore:
|
||||
- dependency-name: gts
|
||||
- dependency-name: webpack-dev-server
|
||||
|
||||
1
html/.eslintignore
Normal file
1
html/.eslintignore
Normal file
@@ -0,0 +1 @@
|
||||
dist/
|
||||
11
html/.eslintrc.json
Normal file
11
html/.eslintrc.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"extends": "./node_modules/gts/",
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["gulpfile.js", "webpack.config.js"],
|
||||
"rules": {
|
||||
"node/no-unpublished-require": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
6
html/.prettierrc.js
Normal file
6
html/.prettierrc.js
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
...require('gts/.prettierrc.json'),
|
||||
"bracketSpacing": true,
|
||||
"tabWidth": 4,
|
||||
"printWidth": 120,
|
||||
}
|
||||
@@ -1,31 +1,31 @@
|
||||
const { src, dest, task, series } = require("gulp");
|
||||
const { src, dest, task, series } = require('gulp');
|
||||
const clean = require('gulp-clean');
|
||||
const gzip = require('gulp-gzip');
|
||||
const inlineSource = require('gulp-inline-source');
|
||||
const rename = require("gulp-rename");
|
||||
const rename = require('gulp-rename');
|
||||
const through2 = require('through2');
|
||||
|
||||
const genHeader = (size, buf, len) => {
|
||||
let idx = 0;
|
||||
let data = "unsigned char index_html[] = {\n ";
|
||||
let data = 'unsigned char index_html[] = {\n ';
|
||||
|
||||
for (const value of buf) {
|
||||
idx++;
|
||||
|
||||
let current = value < 0 ? value + 256 : value;
|
||||
const current = value < 0 ? value + 256 : value;
|
||||
|
||||
data += "0x";
|
||||
data += '0x';
|
||||
data += (current >>> 4).toString(16);
|
||||
data += (current & 0xF).toString(16);
|
||||
data += (current & 0xf).toString(16);
|
||||
|
||||
if (idx === len) {
|
||||
data += "\n";
|
||||
data += '\n';
|
||||
} else {
|
||||
data += idx % 12 === 0 ? ",\n " : ", ";
|
||||
data += idx % 12 === 0 ? ',\n ' : ', ';
|
||||
}
|
||||
}
|
||||
|
||||
data += "};\n";
|
||||
data += '};\n';
|
||||
data += `unsigned int index_html_len = ${len};\n`;
|
||||
data += `unsigned int index_html_size = ${size};\n`;
|
||||
return data;
|
||||
@@ -33,29 +33,32 @@ const genHeader = (size, buf, len) => {
|
||||
let fileSize = 0;
|
||||
|
||||
task('clean', () => {
|
||||
return src('dist', { read: false, allowEmpty: true })
|
||||
.pipe(clean());
|
||||
return src('dist', { read: false, allowEmpty: true }).pipe(clean());
|
||||
});
|
||||
|
||||
task('inline', () => {
|
||||
return src('dist/index.html')
|
||||
.pipe(inlineSource())
|
||||
.pipe(rename("inline.html"))
|
||||
.pipe(dest('dist/'));
|
||||
return src('dist/index.html').pipe(inlineSource()).pipe(rename('inline.html')).pipe(dest('dist/'));
|
||||
});
|
||||
|
||||
task('default', series('inline', () => {
|
||||
return src('dist/inline.html')
|
||||
.pipe(through2.obj((file, enc, cb) => {
|
||||
fileSize = file.contents.length;
|
||||
return cb(null, file);
|
||||
}))
|
||||
.pipe(gzip())
|
||||
.pipe(through2.obj((file, enc, cb) => {
|
||||
const buf = file.contents;
|
||||
file.contents = Buffer.from(genHeader(fileSize, buf, buf.length));
|
||||
return cb(null, file);
|
||||
}))
|
||||
.pipe(rename("html.h"))
|
||||
.pipe(dest('../src/'));
|
||||
}));
|
||||
task(
|
||||
'default',
|
||||
series('inline', () => {
|
||||
return src('dist/inline.html')
|
||||
.pipe(
|
||||
through2.obj((file, enc, cb) => {
|
||||
fileSize = file.contents.length;
|
||||
return cb(null, file);
|
||||
})
|
||||
)
|
||||
.pipe(gzip())
|
||||
.pipe(
|
||||
through2.obj((file, enc, cb) => {
|
||||
const buf = file.contents;
|
||||
file.contents = Buffer.from(genHeader(fileSize, buf, buf.length));
|
||||
return cb(null, file);
|
||||
})
|
||||
)
|
||||
.pipe(rename('html.h'))
|
||||
.pipe(dest('../src/'));
|
||||
})
|
||||
);
|
||||
|
||||
@@ -17,11 +17,15 @@
|
||||
"check": "gts check",
|
||||
"fix": "gts fix"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"css-loader": "^6.7.1",
|
||||
"css-minimizer-webpack-plugin": "^4.2.2",
|
||||
"gts": "^1.1.2",
|
||||
"eslint-webpack-plugin": "^3.2.0",
|
||||
"gts": "^4.0.0",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-clean": "^0.4.0",
|
||||
"gulp-gzip": "^1.4.2",
|
||||
@@ -36,8 +40,6 @@
|
||||
"terser-webpack-plugin": "^5.3.6",
|
||||
"through2": "^4.0.2",
|
||||
"ts-loader": "^9.4.1",
|
||||
"tslint": "^6.1.3",
|
||||
"tslint-loader": "^3.5.4",
|
||||
"typescript": "^4.8.4",
|
||||
"util": "^0.12.5",
|
||||
"webpack": "^5.74.0",
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
module.exports = {
|
||||
trailingComma: "es5",
|
||||
tabWidth: 4,
|
||||
printWidth: 120,
|
||||
singleQuote: true,
|
||||
};
|
||||
@@ -4,12 +4,11 @@ import { ITerminalOptions, ITheme } from 'xterm';
|
||||
import { ClientOptions, FlowControl, Xterm } from './terminal';
|
||||
|
||||
if ((module as any).hot) {
|
||||
// tslint:disable-next-line:no-var-requires
|
||||
require('preact/debug');
|
||||
}
|
||||
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
const path = window.location.pathname.replace(/[\/]+$/, '');
|
||||
const path = window.location.pathname.replace(/[/]+$/, '');
|
||||
const wsUrl = [protocol, '//', window.location.host, path, '/ws', window.location.search].join('');
|
||||
const tokenUrl = [window.location.protocol, '//', window.location.host, path, '/token'].join('');
|
||||
const clientOptions = {
|
||||
@@ -17,6 +16,7 @@ const clientOptions = {
|
||||
disableLeaveAlert: false,
|
||||
disableResizeOverlay: false,
|
||||
enableZmodem: false,
|
||||
enableTrzsz: false,
|
||||
enableSixel: false,
|
||||
titleFixed: null,
|
||||
} as ClientOptions;
|
||||
|
||||
@@ -44,7 +44,7 @@ export interface ClientOptions {
|
||||
enableZmodem: boolean;
|
||||
enableTrzsz: boolean;
|
||||
enableSixel: boolean;
|
||||
titleFixed: string;
|
||||
titleFixed: string | null;
|
||||
}
|
||||
|
||||
type Options = ITerminalOptions & ClientOptions;
|
||||
@@ -70,21 +70,21 @@ interface State {
|
||||
}
|
||||
|
||||
export class Xterm extends Component<Props, State> {
|
||||
private textEncoder: TextEncoder;
|
||||
private textDecoder: TextDecoder;
|
||||
private textEncoder = new TextEncoder();
|
||||
private textDecoder = new TextDecoder();
|
||||
private container: HTMLElement;
|
||||
private terminal: Terminal;
|
||||
|
||||
private written = 0;
|
||||
private pending = 0;
|
||||
|
||||
private fitAddon: FitAddon;
|
||||
private overlayAddon: OverlayAddon;
|
||||
private webglAddon: WebglAddon;
|
||||
private canvasAddon: CanvasAddon;
|
||||
private fitAddon = new FitAddon();
|
||||
private overlayAddon = new OverlayAddon();
|
||||
private webglAddon?: WebglAddon;
|
||||
private canvasAddon?: CanvasAddon;
|
||||
|
||||
private socket: WebSocket;
|
||||
private writeFunc: (data: ArrayBuffer) => void;
|
||||
private writeFunc = (data: ArrayBuffer) => this.writeData(new Uint8Array(data));
|
||||
private token: string;
|
||||
private opened = false;
|
||||
private title: string;
|
||||
@@ -96,12 +96,6 @@ export class Xterm extends Component<Props, State> {
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.writeFunc = data => this.writeData(new Uint8Array(data));
|
||||
this.textEncoder = new TextEncoder();
|
||||
this.textDecoder = new TextDecoder();
|
||||
this.fitAddon = new FitAddon();
|
||||
this.overlayAddon = new OverlayAddon();
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
@@ -123,7 +117,7 @@ export class Xterm extends Component<Props, State> {
|
||||
|
||||
render({ id }: Props, { zmodem, trzsz }: State) {
|
||||
return (
|
||||
<div id={id} ref={c => (this.container = c)}>
|
||||
<div id={id} ref={c => (this.container = c as HTMLElement)}>
|
||||
{(zmodem || trzsz) && (
|
||||
<ZmodemAddon
|
||||
zmodem={zmodem}
|
||||
@@ -293,9 +287,9 @@ export class Xterm extends Component<Props, State> {
|
||||
disposeWebglRenderer();
|
||||
try {
|
||||
this.terminal.loadAddon(this.canvasAddon);
|
||||
console.log(`[ttyd] canvas renderer loaded`);
|
||||
console.log('[ttyd] canvas renderer loaded');
|
||||
} catch (e) {
|
||||
console.log(`[ttyd] canvas renderer could not be loaded, falling back to dom renderer`, e);
|
||||
console.log('[ttyd] canvas renderer could not be loaded, falling back to dom renderer', e);
|
||||
disposeCanvasRenderer();
|
||||
}
|
||||
};
|
||||
@@ -308,9 +302,9 @@ export class Xterm extends Component<Props, State> {
|
||||
this.webglAddon?.dispose();
|
||||
});
|
||||
terminal.loadAddon(this.webglAddon);
|
||||
console.log(`[ttyd] WebGL renderer loaded`);
|
||||
console.log('[ttyd] WebGL renderer loaded');
|
||||
} catch (e) {
|
||||
console.log(`[ttyd] WebGL renderer could not be loaded, falling back to canvas renderer`, e);
|
||||
console.log('[ttyd] WebGL renderer could not be loaded, falling back to canvas renderer', e);
|
||||
disposeWebglRenderer();
|
||||
enableCanvasRenderer();
|
||||
}
|
||||
@@ -346,13 +340,13 @@ export class Xterm extends Component<Props, State> {
|
||||
break;
|
||||
case 'disableResizeOverlay':
|
||||
if (value) {
|
||||
console.log(`[ttyd] Resize overlay disabled`);
|
||||
console.log('[ttyd] Resize overlay disabled');
|
||||
this.resizeOverlay = false;
|
||||
}
|
||||
break;
|
||||
case 'disableReconnect':
|
||||
if (value) {
|
||||
console.log(`[ttyd] Reconnect disabled`);
|
||||
console.log('[ttyd] Reconnect disabled');
|
||||
this.reconnect = false;
|
||||
this.doReconnect = false;
|
||||
}
|
||||
@@ -360,13 +354,13 @@ export class Xterm extends Component<Props, State> {
|
||||
case 'enableZmodem':
|
||||
if (value) {
|
||||
this.setState({ zmodem: true });
|
||||
console.log(`[ttyd] Zmodem enabled`);
|
||||
console.log('[ttyd] Zmodem enabled');
|
||||
}
|
||||
break;
|
||||
case 'enableTrzsz':
|
||||
if (value) {
|
||||
this.setState({ trzsz: true });
|
||||
console.log(`[ttyd] trzsz enabled`);
|
||||
console.log('[ttyd] trzsz enabled');
|
||||
}
|
||||
break;
|
||||
case 'enableSixel':
|
||||
@@ -375,7 +369,7 @@ export class Xterm extends Component<Props, State> {
|
||||
new Blob([worker], { type: 'text/javascript' })
|
||||
);
|
||||
terminal.loadAddon(new ImageAddon(imageWorkerUrl));
|
||||
console.log(`[ttyd] Sixel enabled`);
|
||||
console.log('[ttyd] Sixel enabled');
|
||||
}
|
||||
break;
|
||||
case 'titleFixed':
|
||||
@@ -401,21 +395,19 @@ export class Xterm extends Component<Props, State> {
|
||||
private onSocketOpen() {
|
||||
console.log('[ttyd] websocket connection opened');
|
||||
|
||||
const { socket, textEncoder, terminal, fitAddon, overlayAddon } = this;
|
||||
const dims = fitAddon.proposeDimensions();
|
||||
const { socket, textEncoder, terminal, overlayAddon } = this;
|
||||
socket.send(
|
||||
textEncoder.encode(
|
||||
JSON.stringify({
|
||||
AuthToken: this.token,
|
||||
columns: dims.cols,
|
||||
rows: dims.rows,
|
||||
columns: terminal.cols,
|
||||
rows: terminal.rows,
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
if (this.opened) {
|
||||
terminal.reset();
|
||||
terminal.resize(dims.cols, dims.rows);
|
||||
terminal.options.disableStdin = false;
|
||||
overlayAddon.showOverlay('Reconnected', 300);
|
||||
} else {
|
||||
@@ -432,12 +424,12 @@ export class Xterm extends Component<Props, State> {
|
||||
console.log(`[ttyd] websocket connection closed with code: ${event.code}`);
|
||||
|
||||
const { refreshToken, connect, doReconnect, overlayAddon } = this;
|
||||
overlayAddon.showOverlay('Connection Closed', null);
|
||||
overlayAddon.showOverlay('Connection Closed');
|
||||
this.setState({ zmodem: false, trzsz: false });
|
||||
|
||||
// 1000: CLOSE_NORMAL
|
||||
if (event.code !== 1000 && doReconnect) {
|
||||
overlayAddon.showOverlay('Reconnecting...', null);
|
||||
overlayAddon.showOverlay('Reconnecting...');
|
||||
refreshToken().then(connect);
|
||||
} else {
|
||||
const { terminal } = this;
|
||||
@@ -445,11 +437,11 @@ export class Xterm extends Component<Props, State> {
|
||||
const event = e.domEvent;
|
||||
if (event.key === 'Enter') {
|
||||
keyDispose.dispose();
|
||||
overlayAddon.showOverlay('Reconnecting...', null);
|
||||
overlayAddon.showOverlay('Reconnecting...');
|
||||
refreshToken().then(connect);
|
||||
}
|
||||
});
|
||||
overlayAddon.showOverlay('Press ⏎ to Reconnect', null);
|
||||
overlayAddon.showOverlay('Press ⏎ to Reconnect');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -475,8 +467,10 @@ export class Xterm extends Component<Props, State> {
|
||||
document.title = this.title;
|
||||
break;
|
||||
case Command.SET_PREFERENCES:
|
||||
const prefs = JSON.parse(textDecoder.decode(data));
|
||||
this.applyOptions({ ...this.props.clientOptions, ...prefs } as Options);
|
||||
this.applyOptions({
|
||||
...this.props.clientOptions,
|
||||
...JSON.parse(textDecoder.decode(data)),
|
||||
} as Options);
|
||||
break;
|
||||
default:
|
||||
console.warn(`[ttyd] unknown command: ${cmd}`);
|
||||
@@ -494,7 +488,7 @@ export class Xterm extends Component<Props, State> {
|
||||
|
||||
if (resizeOverlay) {
|
||||
setTimeout(() => {
|
||||
overlayAddon.showOverlay(`${size.cols}x${size.rows}`);
|
||||
overlayAddon.showOverlay(`${size.cols}x${size.rows}`, 300);
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
// 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';
|
||||
|
||||
export class OverlayAddon implements ITerminalAddon {
|
||||
private terminal: Terminal | undefined;
|
||||
private overlayNode: HTMLElement | null;
|
||||
private overlayTimeout: number | null;
|
||||
private terminal: Terminal;
|
||||
private overlayNode: HTMLElement;
|
||||
private overlayTimeout?: number;
|
||||
|
||||
constructor() {
|
||||
this.overlayNode = document.createElement('div');
|
||||
@@ -35,8 +36,10 @@ position: absolute;
|
||||
|
||||
dispose(): void {}
|
||||
|
||||
@bind
|
||||
showOverlay(msg: string, timeout?: number): void {
|
||||
const { terminal, overlayNode } = this;
|
||||
if (!terminal.element) return;
|
||||
|
||||
overlayNode.style.color = '#101010';
|
||||
overlayNode.style.backgroundColor = '#f0f0f0';
|
||||
@@ -53,21 +56,16 @@ position: absolute;
|
||||
overlayNode.style.top = (divSize.height - overlaySize.height) / 2 + 'px';
|
||||
overlayNode.style.left = (divSize.width - overlaySize.width) / 2 + 'px';
|
||||
|
||||
if (this.overlayTimeout) {
|
||||
clearTimeout(this.overlayTimeout);
|
||||
}
|
||||
if (timeout === null) {
|
||||
return;
|
||||
}
|
||||
if (this.overlayTimeout) clearTimeout(this.overlayTimeout);
|
||||
if (!timeout) return;
|
||||
|
||||
const self = this;
|
||||
self.overlayTimeout = setTimeout(() => {
|
||||
this.overlayTimeout = setTimeout(() => {
|
||||
overlayNode.style.opacity = '0';
|
||||
self.overlayTimeout = setTimeout(() => {
|
||||
this.overlayTimeout = setTimeout(() => {
|
||||
if (overlayNode.parentNode) {
|
||||
overlayNode.parentNode.removeChild(overlayNode);
|
||||
}
|
||||
self.overlayTimeout = null;
|
||||
this.overlayTimeout = undefined;
|
||||
overlayNode.style.opacity = '0.75';
|
||||
}, 200) as any;
|
||||
}, timeout || 1500) as any;
|
||||
|
||||
@@ -20,7 +20,7 @@ interface State {
|
||||
}
|
||||
|
||||
export class ZmodemAddon extends Component<Props, State> implements ITerminalAddon {
|
||||
private terminal: Terminal | undefined;
|
||||
private terminal: Terminal;
|
||||
private disposables: IDisposable[] = [];
|
||||
private sentry: Zmodem.Sentry;
|
||||
private session: Zmodem.Session;
|
||||
@@ -81,7 +81,7 @@ export class ZmodemAddon extends Component<Props, State> implements ITerminalAdd
|
||||
}
|
||||
|
||||
@bind
|
||||
private handleError(e: Error, reason: string) {
|
||||
private handleError(e: any, reason: string) {
|
||||
console.error(`[ttyd] zmodem ${reason}: `, e);
|
||||
this.reset();
|
||||
}
|
||||
@@ -115,12 +115,14 @@ export class ZmodemAddon extends Component<Props, State> implements ITerminalAdd
|
||||
on_retract: () => reset(),
|
||||
on_detect: detection => zmodemDetect(detection),
|
||||
});
|
||||
this.disposables.push(terminal.onKey(e => {
|
||||
const event = e.domEvent;
|
||||
if (event.ctrlKey && event.key === 'c') {
|
||||
if (this.denier) this.denier();
|
||||
}
|
||||
}));
|
||||
this.disposables.push(
|
||||
terminal.onKey(e => {
|
||||
const event = e.domEvent;
|
||||
if (event.ctrlKey && event.key === 'c') {
|
||||
if (this.denier) this.denier();
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@bind
|
||||
@@ -144,7 +146,7 @@ export class ZmodemAddon extends Component<Props, State> implements ITerminalAdd
|
||||
this.setState({ modal: false });
|
||||
|
||||
const { session, writeProgress, handleError } = this;
|
||||
const files: FileList = (event.target as HTMLInputElement).files;
|
||||
const files = (event.target as HTMLInputElement).files;
|
||||
|
||||
Zmodem.Browser.send_files(session, files, {
|
||||
on_progress: (_, offer) => writeProgress(offer),
|
||||
@@ -158,15 +160,11 @@ export class ZmodemAddon extends Component<Props, State> implements ITerminalAdd
|
||||
const { session, writeProgress, handleError } = this;
|
||||
|
||||
session.on('offer', offer => {
|
||||
const fileBuffer = [];
|
||||
offer.on('input', payload => {
|
||||
writeProgress(offer);
|
||||
fileBuffer.push(new Uint8Array(payload));
|
||||
});
|
||||
offer.on('input', () => writeProgress(offer));
|
||||
offer
|
||||
.accept()
|
||||
.then(() => {
|
||||
const blob = new Blob(fileBuffer, { type: 'application/octet-stream' });
|
||||
.then(payloads => {
|
||||
const blob = new Blob(payloads, { type: 'application/octet-stream' });
|
||||
saveAs(blob, offer.get_details().name);
|
||||
})
|
||||
.catch(e => handleError(e, 'receive'));
|
||||
|
||||
@@ -1,20 +1,15 @@
|
||||
{
|
||||
"extends": "./node_modules/gts/tsconfig-google.json",
|
||||
"compilerOptions": {
|
||||
"target": "es2015",
|
||||
"module": "es2015",
|
||||
"lib": [
|
||||
"es2015",
|
||||
"dom"
|
||||
],
|
||||
"allowJs": true,
|
||||
"jsx": "react",
|
||||
"jsxFactory": "h",
|
||||
"sourceMap": true,
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"jsx": "react",
|
||||
"jsxFactory": "h",
|
||||
"allowJs": true,
|
||||
"noImplicitAny": false,
|
||||
"declaration": false,
|
||||
"experimentalDecorators": true,
|
||||
"noImplicitReturns": true,
|
||||
"noUnusedParameters": true
|
||||
"strictPropertyInitialization": false,
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.tsx",
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"extends": "gts/tslint.json",
|
||||
"rules": {
|
||||
"deprecation": false,
|
||||
"no-any": false
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
const path = require('path');
|
||||
const { merge } = require('webpack-merge');
|
||||
const ESLintPlugin = require('eslint-webpack-plugin');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
|
||||
@@ -11,7 +12,7 @@ const devMode = process.env.NODE_ENV !== 'production';
|
||||
const baseConfig = {
|
||||
context: path.resolve(__dirname, 'src'),
|
||||
entry: {
|
||||
app: './index.tsx'
|
||||
app: './index.tsx',
|
||||
},
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
@@ -19,23 +20,14 @@ const baseConfig = {
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.ts$/,
|
||||
enforce: 'pre',
|
||||
use: 'tslint-loader',
|
||||
},
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
use: 'ts-loader',
|
||||
exclude: /node_modules/
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
{
|
||||
test: /\.s?[ac]ss$/,
|
||||
use: [
|
||||
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
|
||||
'css-loader',
|
||||
'sass-loader',
|
||||
],
|
||||
use: [devMode ? 'style-loader' : MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
|
||||
},
|
||||
{
|
||||
test: /xterm-addon-image-worker/,
|
||||
@@ -43,19 +35,21 @@ const baseConfig = {
|
||||
generator: {
|
||||
dataUrl: content => {
|
||||
return content.toString();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
extensions: [ '.tsx', '.ts', '.js' ]
|
||||
extensions: ['.tsx', '.ts', '.js'],
|
||||
},
|
||||
plugins: [
|
||||
new ESLintPlugin({
|
||||
context: path.resolve(__dirname, '.'),
|
||||
extensions: ['js', 'jsx', 'ts', 'tsx'],
|
||||
}),
|
||||
new CopyWebpackPlugin({
|
||||
patterns:[
|
||||
{ from: './favicon.png', to: '.' }
|
||||
],
|
||||
patterns: [{ from: './favicon.png', to: '.' }],
|
||||
}),
|
||||
new MiniCssExtractPlugin({
|
||||
filename: devMode ? '[name].css' : '[name].[contenthash].css',
|
||||
@@ -68,25 +62,27 @@ const baseConfig = {
|
||||
collapseWhitespace: true,
|
||||
},
|
||||
title: 'ttyd - Terminal',
|
||||
template: './template.html'
|
||||
})
|
||||
template: './template.html',
|
||||
}),
|
||||
],
|
||||
performance : {
|
||||
hints : false
|
||||
performance: {
|
||||
hints: false,
|
||||
},
|
||||
};
|
||||
|
||||
const devConfig = {
|
||||
const devConfig = {
|
||||
mode: 'development',
|
||||
devServer: {
|
||||
contentBase: path.join(__dirname, 'dist'),
|
||||
compress: true,
|
||||
port: 9000,
|
||||
proxy: [{
|
||||
context: ['/token', '/ws'],
|
||||
target: 'http://localhost:7681',
|
||||
ws: true
|
||||
}]
|
||||
proxy: [
|
||||
{
|
||||
context: ['/token', '/ws'],
|
||||
target: 'http://localhost:7681',
|
||||
ws: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
devtool: 'inline-source-map',
|
||||
};
|
||||
@@ -94,13 +90,9 @@ const devConfig = {
|
||||
const prodConfig = {
|
||||
mode: 'production',
|
||||
optimization: {
|
||||
minimizer: [
|
||||
new TerserPlugin(),
|
||||
new CssMinimizerPlugin(),
|
||||
]
|
||||
minimizer: [new TerserPlugin(), new CssMinimizerPlugin()],
|
||||
},
|
||||
devtool: 'source-map',
|
||||
};
|
||||
|
||||
|
||||
module.exports = merge(baseConfig, devMode ? devConfig : prodConfig);
|
||||
|
||||
1586
html/yarn.lock
1586
html/yarn.lock
File diff suppressed because it is too large
Load Diff
28283
src/html.h
generated
28283
src/html.h
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user