mirror of
https://github.com/tsl0922/ttyd.git
synced 2025-12-21 19:34:19 +01:00
html: migrate to typescript
This commit is contained in:
361
html/js/app.js
361
html/js/app.js
@@ -1,361 +0,0 @@
|
|||||||
require('../sass/app.scss');
|
|
||||||
|
|
||||||
// polyfills for ie11
|
|
||||||
require('core-js/fn/array');
|
|
||||||
require('core-js/fn/object');
|
|
||||||
require('core-js/fn/promise');
|
|
||||||
require('core-js/fn/typed');
|
|
||||||
require('core-js/fn/string/ends-with');
|
|
||||||
require('fast-text-encoding');
|
|
||||||
|
|
||||||
let Zmodem = require('zmodem.js/src/zmodem_browser');
|
|
||||||
let Terminal = require('xterm').Terminal;
|
|
||||||
|
|
||||||
Terminal.applyAddon(require('xterm/lib/addons/fit/fit'));
|
|
||||||
Terminal.applyAddon(require('./overlay'));
|
|
||||||
|
|
||||||
let modal = {
|
|
||||||
self: document.getElementById('modal'),
|
|
||||||
header: document.getElementById('header'),
|
|
||||||
status: {
|
|
||||||
self: document.getElementById('status'),
|
|
||||||
filesRemaining: document.getElementById('files-remaining'),
|
|
||||||
bytesRemaining: document.getElementById('bytes-remaining')
|
|
||||||
},
|
|
||||||
choose: {
|
|
||||||
self: document.getElementById('choose'),
|
|
||||||
files: document.getElementById('files'),
|
|
||||||
filesNames: document.getElementById('file-names')
|
|
||||||
},
|
|
||||||
progress: {
|
|
||||||
self: document.getElementById('progress'),
|
|
||||||
fileName: document.getElementById('file-name'),
|
|
||||||
progressBar: document.getElementById('progress-bar'),
|
|
||||||
bytesReceived: document.getElementById('bytes-received'),
|
|
||||||
bytesFile: document.getElementById('bytes-file'),
|
|
||||||
percentReceived: document.getElementById('percent-received'),
|
|
||||||
skip: document.getElementById('skip')
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function updateFileInfo(fileInfo) {
|
|
||||||
modal.status.self.style.display = '';
|
|
||||||
modal.choose.self.style.display = 'none';
|
|
||||||
modal.progress.self.style.display = '';
|
|
||||||
modal.status.filesRemaining.textContent = fileInfo.files_remaining;
|
|
||||||
modal.status.bytesRemaining.textContent = bytesHuman(fileInfo.bytes_remaining, 2);
|
|
||||||
modal.progress.fileName.textContent = fileInfo.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
function showReceiveModal(xfer) {
|
|
||||||
resetModal('Receiving files');
|
|
||||||
updateFileInfo(xfer.get_details());
|
|
||||||
modal.progress.skip.disabled = false;
|
|
||||||
modal.progress.skip.onclick = function () {
|
|
||||||
this.disabled = true;
|
|
||||||
xfer.skip();
|
|
||||||
};
|
|
||||||
modal.progress.skip.style.display = '';
|
|
||||||
modal.self.classList.add('is-active');
|
|
||||||
}
|
|
||||||
|
|
||||||
function showSendModal(callback) {
|
|
||||||
resetModal('Sending files');
|
|
||||||
modal.choose.self.style.display = '';
|
|
||||||
modal.choose.files.disabled = false;
|
|
||||||
modal.choose.files.value = '';
|
|
||||||
modal.choose.filesNames.textContent = '';
|
|
||||||
modal.choose.files.onchange = function () {
|
|
||||||
this.disabled = true;
|
|
||||||
let files = this.files;
|
|
||||||
let fileNames = '';
|
|
||||||
for (let i = 0; i < files.length; i++) {
|
|
||||||
if (i === 0) {
|
|
||||||
fileNames = files[i].name;
|
|
||||||
} else {
|
|
||||||
fileNames += ', ' + files[i].name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
modal.choose.filesNames.textContent = fileNames;
|
|
||||||
callback(files);
|
|
||||||
};
|
|
||||||
modal.self.classList.add('is-active');
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideModal() {
|
|
||||||
modal.self.classList.remove('is-active');
|
|
||||||
}
|
|
||||||
|
|
||||||
function resetModal(title) {
|
|
||||||
modal.header.textContent = title;
|
|
||||||
modal.status.self.style.display = 'none';
|
|
||||||
modal.choose.self.style.display = 'none';
|
|
||||||
modal.progress.self.style.display = 'none';
|
|
||||||
modal.progress.bytesReceived.textContent = '-';
|
|
||||||
modal.progress.percentReceived.textContent = '-%';
|
|
||||||
modal.progress.progressBar.textContent = '0%';
|
|
||||||
modal.progress.progressBar.value = 0;
|
|
||||||
modal.progress.skip.style.display = 'none';
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateProgress(xfer) {
|
|
||||||
let size = xfer.get_details().size;
|
|
||||||
let offset = xfer.get_offset();
|
|
||||||
modal.progress.bytesReceived.textContent = bytesHuman(offset, 2);
|
|
||||||
modal.progress.bytesFile.textContent = bytesHuman(size, 2);
|
|
||||||
|
|
||||||
let percentReceived = (100 * offset / size).toFixed(2);
|
|
||||||
modal.progress.percentReceived.textContent = percentReceived + '%';
|
|
||||||
|
|
||||||
modal.progress.progressBar.textContent = percentReceived + '%';
|
|
||||||
modal.progress.progressBar.setAttribute('value', percentReceived);
|
|
||||||
}
|
|
||||||
|
|
||||||
function bytesHuman (bytes, precision) {
|
|
||||||
if (isNaN(parseFloat(bytes)) || !isFinite(bytes)) return '-';
|
|
||||||
if (bytes === 0) return 0;
|
|
||||||
if (typeof precision === 'undefined') precision = 1;
|
|
||||||
let units = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB'],
|
|
||||||
number = Math.floor(Math.log(bytes) / Math.log(1024));
|
|
||||||
return (bytes / Math.pow(1024, Math.floor(number))).toFixed(precision) + ' ' + units[number];
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleSend(zsession) {
|
|
||||||
return new Promise((res) => {
|
|
||||||
showSendModal((files) => {
|
|
||||||
Zmodem.Browser.send_files(
|
|
||||||
zsession,
|
|
||||||
files,
|
|
||||||
{
|
|
||||||
on_progress: (obj, xfer) => {
|
|
||||||
updateFileInfo(xfer.get_details());
|
|
||||||
updateProgress(xfer);
|
|
||||||
},
|
|
||||||
on_file_complete: (obj) => {
|
|
||||||
// console.log(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
).then(
|
|
||||||
zsession.close.bind(zsession),
|
|
||||||
console.error.bind(console)
|
|
||||||
).then(() => res());
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleReceive(zsession) {
|
|
||||||
zsession.on('offer', (xfer) => {
|
|
||||||
showReceiveModal(xfer);
|
|
||||||
let fileBuffer = [];
|
|
||||||
xfer.on('input', (payload) => {
|
|
||||||
updateProgress(xfer);
|
|
||||||
fileBuffer.push(new Uint8Array(payload));
|
|
||||||
});
|
|
||||||
xfer.accept().then(() => {
|
|
||||||
Zmodem.Browser.save_to_disk(
|
|
||||||
fileBuffer,
|
|
||||||
xfer.get_details().name
|
|
||||||
);
|
|
||||||
}, console.error.bind(console));
|
|
||||||
});
|
|
||||||
let promise = new Promise((res) => {
|
|
||||||
zsession.on('session_end', () => res());
|
|
||||||
});
|
|
||||||
zsession.start();
|
|
||||||
return promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
let terminalContainer = document.getElementById('terminal-container'),
|
|
||||||
httpsEnabled = window.location.protocol === 'https:',
|
|
||||||
url = (httpsEnabled ? 'wss://' : 'ws://') + window.location.host + window.location.pathname
|
|
||||||
+ (window.location.pathname.endsWith('/') ? '' : '/') + 'ws' + window.location.search,
|
|
||||||
textDecoder = new TextDecoder(),
|
|
||||||
textEncoder = new TextEncoder(),
|
|
||||||
authToken = (typeof tty_auth_token !== 'undefined') ? tty_auth_token : null,
|
|
||||||
autoReconnect = -1,
|
|
||||||
reconnectTimer, term, title, wsError;
|
|
||||||
|
|
||||||
let openWs = function() {
|
|
||||||
let ws = new WebSocket(url, ['tty']);
|
|
||||||
let sendMessage = function (message) {
|
|
||||||
if (ws.readyState === WebSocket.OPEN) {
|
|
||||||
ws.send(textEncoder.encode(message));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let unloadCallback = function (event) {
|
|
||||||
let message = 'Close terminal? this will also terminate the command.';
|
|
||||||
event.returnValue = message;
|
|
||||||
return message;
|
|
||||||
};
|
|
||||||
let resetTerm = function() {
|
|
||||||
hideModal();
|
|
||||||
clearTimeout(reconnectTimer);
|
|
||||||
if (ws.readyState !== WebSocket.CLOSED) {
|
|
||||||
ws.close();
|
|
||||||
}
|
|
||||||
openWs();
|
|
||||||
};
|
|
||||||
|
|
||||||
let zsentry = new Zmodem.Sentry({
|
|
||||||
to_terminal: function _to_terminal(octets) {
|
|
||||||
let buffer = new Uint8Array(octets).buffer;
|
|
||||||
term.write(textDecoder.decode(buffer));
|
|
||||||
},
|
|
||||||
|
|
||||||
sender: function _ws_sender_func(octets) {
|
|
||||||
// limit max packet size to 4096
|
|
||||||
while (octets.length) {
|
|
||||||
let chunk = octets.splice(0, 4095);
|
|
||||||
let buffer = new Uint8Array(chunk.length + 1);
|
|
||||||
buffer[0]= '0'.charCodeAt(0);
|
|
||||||
buffer.set(chunk, 1);
|
|
||||||
ws.send(buffer);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
on_retract: function _on_retract() {
|
|
||||||
// console.log('on_retract');
|
|
||||||
},
|
|
||||||
|
|
||||||
on_detect: function _on_detect(detection) {
|
|
||||||
term.setOption('disableStdin', true);
|
|
||||||
let zsession = detection.confirm();
|
|
||||||
let promise = zsession.type === 'send' ? handleSend(zsession) : handleReceive(zsession);
|
|
||||||
promise.catch(console.error.bind(console)).then(() => {
|
|
||||||
hideModal();
|
|
||||||
term.setOption('disableStdin', false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ws.binaryType = 'arraybuffer';
|
|
||||||
|
|
||||||
ws.onopen = function() {
|
|
||||||
console.log('[ttyd] websocket opened');
|
|
||||||
wsError = false;
|
|
||||||
sendMessage(JSON.stringify({AuthToken: authToken}));
|
|
||||||
|
|
||||||
if (typeof term !== 'undefined') {
|
|
||||||
term.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
// expose term handle for some programatic cases
|
|
||||||
// which need to get the content of the terminal
|
|
||||||
term = window.term = new Terminal({
|
|
||||||
fontSize: 13,
|
|
||||||
fontFamily: '"Menlo for Powerline", Menlo, Consolas, "Liberation Mono", Courier, monospace',
|
|
||||||
theme: {
|
|
||||||
foreground: '#d2d2d2',
|
|
||||||
background: '#2b2b2b',
|
|
||||||
cursor: '#adadad',
|
|
||||||
black: '#000000',
|
|
||||||
red: '#d81e00',
|
|
||||||
green: '#5ea702',
|
|
||||||
yellow: '#cfae00',
|
|
||||||
blue: '#427ab3',
|
|
||||||
magenta: '#89658e',
|
|
||||||
cyan: '#00a7aa',
|
|
||||||
white: '#dbded8',
|
|
||||||
brightBlack: '#686a66',
|
|
||||||
brightRed: '#f54235',
|
|
||||||
brightGreen: '#99e343',
|
|
||||||
brightYellow: '#fdeb61',
|
|
||||||
brightBlue: '#84b0d8',
|
|
||||||
brightMagenta: '#bc94b7',
|
|
||||||
brightCyan: '#37e6e8',
|
|
||||||
brightWhite: '#f1f1f0'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let addDomListener = function(element, type, handler) {
|
|
||||||
element.addEventListener(type, handler);
|
|
||||||
term._core.register({ dispose: () => element.removeEventListener(type, handler) });
|
|
||||||
};
|
|
||||||
|
|
||||||
term.onResize((size) => {
|
|
||||||
if (ws.readyState === WebSocket.OPEN) {
|
|
||||||
sendMessage('1' + JSON.stringify({columns: size.cols, rows: size.rows}));
|
|
||||||
}
|
|
||||||
setTimeout(() => term.showOverlay(size.cols + 'x' + size.rows), 500);
|
|
||||||
});
|
|
||||||
|
|
||||||
term.onTitleChange((data) => {
|
|
||||||
if (data && data !== '') {
|
|
||||||
document.title = (data + ' | ' + title);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
term.onData((data) => sendMessage('0' + data));
|
|
||||||
|
|
||||||
while (terminalContainer.firstChild) {
|
|
||||||
terminalContainer.removeChild(terminalContainer.firstChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://stackoverflow.com/a/27923937/1727928
|
|
||||||
window.addEventListener('resize', () => {
|
|
||||||
clearTimeout(window.resizedFinished);
|
|
||||||
window.resizedFinished = setTimeout(() => term.fit(), 250);
|
|
||||||
});
|
|
||||||
window.addEventListener('beforeunload', unloadCallback);
|
|
||||||
|
|
||||||
term.open(terminalContainer);
|
|
||||||
term.fit();
|
|
||||||
term.focus();
|
|
||||||
};
|
|
||||||
|
|
||||||
ws.onmessage = function(event) {
|
|
||||||
let rawData = new Uint8Array(event.data),
|
|
||||||
cmd = String.fromCharCode(rawData[0]),
|
|
||||||
data = rawData.slice(1).buffer;
|
|
||||||
switch(cmd) {
|
|
||||||
case '0':
|
|
||||||
try {
|
|
||||||
zsentry.consume(data);
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
resetTerm();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '1':
|
|
||||||
title = textDecoder.decode(data);
|
|
||||||
document.title = title;
|
|
||||||
break;
|
|
||||||
case '2':
|
|
||||||
let preferences = JSON.parse(textDecoder.decode(data));
|
|
||||||
Object.keys(preferences).forEach((key) => {
|
|
||||||
console.log('[ttyd] xterm option: ' + key + '=' + preferences[key]);
|
|
||||||
term.setOption(key, preferences[key]);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case '3':
|
|
||||||
autoReconnect = JSON.parse(textDecoder.decode(data));
|
|
||||||
console.log('[ttyd] reconnect: ' + autoReconnect + ' seconds');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.log('[ttyd] unknown command: ' + cmd);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ws.onclose = function(event) {
|
|
||||||
console.log('[ttyd] websocket closed, code: ' + event.code);
|
|
||||||
if (term) {
|
|
||||||
term.off('data');
|
|
||||||
term.off('resize');
|
|
||||||
if (!wsError) {
|
|
||||||
term.showOverlay('Connection Closed', null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
window.removeEventListener('beforeunload', unloadCallback);
|
|
||||||
// 1000: CLOSE_NORMAL
|
|
||||||
if (event.code !== 1000 && autoReconnect > 0) {
|
|
||||||
reconnectTimer = setTimeout(openWs, autoReconnect * 1000);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
if (document.readyState === 'complete' || document.readyState !== 'loading') {
|
|
||||||
openWs();
|
|
||||||
} else {
|
|
||||||
document.addEventListener('DOMContentLoaded', openWs);
|
|
||||||
}
|
|
||||||
225
html/js/app.ts
Normal file
225
html/js/app.ts
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
import '../sass/app.scss';
|
||||||
|
|
||||||
|
// polyfills for ie11
|
||||||
|
import 'core-js/fn/array';
|
||||||
|
import 'core-js/fn/object';
|
||||||
|
import 'core-js/fn/promise';
|
||||||
|
import 'core-js/fn/typed';
|
||||||
|
import 'fast-text-encoding';
|
||||||
|
|
||||||
|
import { Terminal, ITerminalOptions, IDisposable } from 'xterm';
|
||||||
|
import * as fit from 'xterm/lib/addons/fit/fit'
|
||||||
|
import * as overlay from './overlay'
|
||||||
|
import { Modal } from './zmodem'
|
||||||
|
import * as Zmodem from 'zmodem.js/src/zmodem_browser';
|
||||||
|
import * as urljoin from 'url-join';
|
||||||
|
|
||||||
|
Terminal.applyAddon(fit);
|
||||||
|
Terminal.applyAddon(overlay);
|
||||||
|
|
||||||
|
interface ITtydTerminal extends Terminal {
|
||||||
|
resizeDisposable: IDisposable;
|
||||||
|
dataDisposable: IDisposable;
|
||||||
|
reconnectTimeout: number;
|
||||||
|
showOverlay(msg: string, timeout?: number);
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IWindowWithTerminal extends Window {
|
||||||
|
term: ITtydTerminal;
|
||||||
|
resizeTimeout?: number;
|
||||||
|
tty_auth_token?: string;
|
||||||
|
}
|
||||||
|
declare let window: IWindowWithTerminal;
|
||||||
|
|
||||||
|
const modal = new Modal();
|
||||||
|
const terminalContainer = document.getElementById('terminal-container');
|
||||||
|
const protocol = window.location.protocol === 'https:' ? 'wss://': 'ws://';
|
||||||
|
const url = urljoin(protocol, window.location.host, window.location.pathname, 'ws', window.location.search);
|
||||||
|
const textDecoder = new TextDecoder();
|
||||||
|
const textEncoder = new TextEncoder();
|
||||||
|
|
||||||
|
let authToken = (typeof window.tty_auth_token !== 'undefined') ? window.tty_auth_token : null;
|
||||||
|
let autoReconnect = -1;
|
||||||
|
let term: ITtydTerminal;
|
||||||
|
let title: string;
|
||||||
|
let wsError: boolean;
|
||||||
|
|
||||||
|
let openWs = function() {
|
||||||
|
let ws = new WebSocket(url, ['tty']);
|
||||||
|
let sendMessage = function (message) {
|
||||||
|
if (ws.readyState === WebSocket.OPEN) {
|
||||||
|
ws.send(textEncoder.encode(message));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let unloadCallback = function (event) {
|
||||||
|
let message = 'Close terminal? this will also terminate the command.';
|
||||||
|
event.returnValue = message;
|
||||||
|
return message;
|
||||||
|
};
|
||||||
|
let resetTerm = function() {
|
||||||
|
modal.hide();
|
||||||
|
clearTimeout(term.reconnectTimeout);
|
||||||
|
if (ws.readyState !== WebSocket.CLOSED) {
|
||||||
|
ws.close();
|
||||||
|
}
|
||||||
|
openWs();
|
||||||
|
};
|
||||||
|
|
||||||
|
let zsentry = new Zmodem.Sentry({
|
||||||
|
to_terminal: function _to_terminal(octets) {
|
||||||
|
let buffer = new Uint8Array(octets).buffer;
|
||||||
|
term.write(textDecoder.decode(buffer));
|
||||||
|
},
|
||||||
|
|
||||||
|
sender: function _ws_sender_func(octets) {
|
||||||
|
// limit max packet size to 4096
|
||||||
|
while (octets.length) {
|
||||||
|
let chunk = octets.splice(0, 4095);
|
||||||
|
let buffer = new Uint8Array(chunk.length + 1);
|
||||||
|
buffer[0]= '0'.charCodeAt(0);
|
||||||
|
buffer.set(chunk, 1);
|
||||||
|
ws.send(buffer);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
on_retract: function _on_retract() {
|
||||||
|
// console.log('on_retract');
|
||||||
|
},
|
||||||
|
|
||||||
|
on_detect: function _on_detect(detection) {
|
||||||
|
term.setOption('disableStdin', true);
|
||||||
|
let zsession = detection.confirm();
|
||||||
|
let promise = zsession.type === 'send' ? modal.handleSend(zsession) : modal.handleReceive(zsession);
|
||||||
|
promise.catch(console.error.bind(console)).then(() => {
|
||||||
|
modal.hide();
|
||||||
|
term.setOption('disableStdin', false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ws.binaryType = 'arraybuffer';
|
||||||
|
|
||||||
|
ws.onopen = function() {
|
||||||
|
console.log('[ttyd] websocket opened');
|
||||||
|
wsError = false;
|
||||||
|
sendMessage(JSON.stringify({AuthToken: authToken}));
|
||||||
|
|
||||||
|
if (typeof term !== 'undefined') {
|
||||||
|
term.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// expose term handle for some programatic cases
|
||||||
|
// which need to get the content of the terminal
|
||||||
|
term = window.term = <ITtydTerminal>new Terminal({
|
||||||
|
fontSize: 13,
|
||||||
|
fontFamily: '"Menlo for Powerline", Menlo, Consolas, "Liberation Mono", Courier, monospace',
|
||||||
|
theme: {
|
||||||
|
foreground: '#d2d2d2',
|
||||||
|
background: '#2b2b2b',
|
||||||
|
cursor: '#adadad',
|
||||||
|
black: '#000000',
|
||||||
|
red: '#d81e00',
|
||||||
|
green: '#5ea702',
|
||||||
|
yellow: '#cfae00',
|
||||||
|
blue: '#427ab3',
|
||||||
|
magenta: '#89658e',
|
||||||
|
cyan: '#00a7aa',
|
||||||
|
white: '#dbded8',
|
||||||
|
brightBlack: '#686a66',
|
||||||
|
brightRed: '#f54235',
|
||||||
|
brightGreen: '#99e343',
|
||||||
|
brightYellow: '#fdeb61',
|
||||||
|
brightBlue: '#84b0d8',
|
||||||
|
brightMagenta: '#bc94b7',
|
||||||
|
brightCyan: '#37e6e8',
|
||||||
|
brightWhite: '#f1f1f0'
|
||||||
|
}
|
||||||
|
} as ITerminalOptions);
|
||||||
|
|
||||||
|
term.resizeDisposable = term.onResize((size: {cols: number, rows: number}) => {
|
||||||
|
if (ws.readyState === WebSocket.OPEN) {
|
||||||
|
sendMessage('1' + JSON.stringify({columns: size.cols, rows: size.rows}));
|
||||||
|
}
|
||||||
|
setTimeout(() => (<any>term).showOverlay(size.cols + 'x' + size.rows), 500);
|
||||||
|
});
|
||||||
|
|
||||||
|
term.onTitleChange((data: string) => {
|
||||||
|
if (data && data !== '') {
|
||||||
|
document.title = (data + ' | ' + title);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
term.dataDisposable = term.onData((data: string) => sendMessage('0' + data));
|
||||||
|
|
||||||
|
while (terminalContainer.firstChild) {
|
||||||
|
terminalContainer.removeChild(terminalContainer.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://stackoverflow.com/a/27923937/1727928
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
clearTimeout(window.resizeTimeout);
|
||||||
|
window.resizeTimeout = <number><any>setTimeout(() => (<any>term).fit(), 250);
|
||||||
|
});
|
||||||
|
window.addEventListener('beforeunload', unloadCallback);
|
||||||
|
|
||||||
|
term.open(terminalContainer);
|
||||||
|
(<any>term).fit();
|
||||||
|
term.focus();
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.onmessage = function(event: MessageEvent) {
|
||||||
|
let rawData = new Uint8Array(event.data),
|
||||||
|
cmd = String.fromCharCode(rawData[0]),
|
||||||
|
data = rawData.slice(1).buffer;
|
||||||
|
switch(cmd) {
|
||||||
|
case '0':
|
||||||
|
try {
|
||||||
|
zsentry.consume(data);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
resetTerm();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
title = textDecoder.decode(data);
|
||||||
|
document.title = title;
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
let preferences = JSON.parse(textDecoder.decode(data));
|
||||||
|
Object.keys(preferences).forEach((key) => {
|
||||||
|
console.log('[ttyd] xterm option: ' + key + '=' + preferences[key]);
|
||||||
|
term.setOption(key, preferences[key]);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case '3':
|
||||||
|
autoReconnect = JSON.parse(textDecoder.decode(data));
|
||||||
|
console.log('[ttyd] reconnect: ' + autoReconnect + ' seconds');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log('[ttyd] unknown command: ' + cmd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.onclose = function(event: CloseEvent) {
|
||||||
|
console.log('[ttyd] websocket closed, code: ' + event.code);
|
||||||
|
if (term) {
|
||||||
|
term.resizeDisposable.dispose();
|
||||||
|
term.dataDisposable.dispose();
|
||||||
|
if (!wsError) {
|
||||||
|
(<any>term).showOverlay('Connection Closed', null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.removeEventListener('beforeunload', unloadCallback);
|
||||||
|
// 1000: CLOSE_NORMAL
|
||||||
|
if (event.code !== 1000 && autoReconnect > 0) {
|
||||||
|
term.reconnectTimeout = <number><any>setTimeout(openWs, autoReconnect * 1000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if (document.readyState === 'complete' || document.readyState !== 'loading') {
|
||||||
|
openWs();
|
||||||
|
} else {
|
||||||
|
document.addEventListener('DOMContentLoaded', openWs);
|
||||||
|
}
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
// ported from hterm.Terminal.prototype.showOverlay
|
|
||||||
// https://chromium.googlesource.com/apps/libapps/+/master/hterm/js/hterm_terminal.js
|
|
||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
|
|
||||||
function showOverlay(term, msg, timeout) {
|
|
||||||
if (!term.overlayNode_) {
|
|
||||||
if (!term.element)
|
|
||||||
return;
|
|
||||||
term.overlayNode_ = document.createElement('div');
|
|
||||||
term.overlayNode_.style.cssText = (
|
|
||||||
'border-radius: 15px;' +
|
|
||||||
'font-size: xx-large;' +
|
|
||||||
'opacity: 0.75;' +
|
|
||||||
'padding: 0.2em 0.5em 0.2em 0.5em;' +
|
|
||||||
'position: absolute;' +
|
|
||||||
'-webkit-user-select: none;' +
|
|
||||||
'-webkit-transition: opacity 180ms ease-in;' +
|
|
||||||
'-moz-user-select: none;' +
|
|
||||||
'-moz-transition: opacity 180ms ease-in;');
|
|
||||||
|
|
||||||
term.overlayNode_.addEventListener('mousedown', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
}, true);
|
|
||||||
}
|
|
||||||
term.overlayNode_.style.color = "#101010";
|
|
||||||
term.overlayNode_.style.backgroundColor = "#f0f0f0";
|
|
||||||
|
|
||||||
term.overlayNode_.textContent = msg;
|
|
||||||
term.overlayNode_.style.opacity = '0.75';
|
|
||||||
|
|
||||||
if (!term.overlayNode_.parentNode)
|
|
||||||
term.element.appendChild(term.overlayNode_);
|
|
||||||
|
|
||||||
var divSize = term.element.getBoundingClientRect();
|
|
||||||
var overlaySize = term.overlayNode_.getBoundingClientRect();
|
|
||||||
|
|
||||||
term.overlayNode_.style.top =
|
|
||||||
(divSize.height - overlaySize.height) / 2 + 'px';
|
|
||||||
term.overlayNode_.style.left = (divSize.width - overlaySize.width) / 2 + 'px';
|
|
||||||
|
|
||||||
if (term.overlayTimeout_)
|
|
||||||
clearTimeout(term.overlayTimeout_);
|
|
||||||
|
|
||||||
if (timeout === null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
term.overlayTimeout_ = setTimeout(function() {
|
|
||||||
term.overlayNode_.style.opacity = '0';
|
|
||||||
term.overlayTimeout_ = setTimeout(function() {
|
|
||||||
if (term.overlayNode_.parentNode)
|
|
||||||
term.overlayNode_.parentNode.removeChild(term.overlayNode_);
|
|
||||||
term.overlayTimeout_ = null;
|
|
||||||
term.overlayNode_.style.opacity = '0.75';
|
|
||||||
}, 200);
|
|
||||||
}, timeout || 1500);
|
|
||||||
}
|
|
||||||
exports.showOverlay = showOverlay;
|
|
||||||
|
|
||||||
function apply(terminalConstructor) {
|
|
||||||
terminalConstructor.prototype.showOverlay = function (msg, timeout) {
|
|
||||||
return showOverlay(this, msg, timeout);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
exports.apply = apply;
|
|
||||||
68
html/js/overlay.ts
Normal file
68
html/js/overlay.ts
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
// ported from hterm.Terminal.prototype.showOverlay
|
||||||
|
// https://chromium.googlesource.com/apps/libapps/+/master/hterm/js/hterm_terminal.js
|
||||||
|
import { Terminal } from 'xterm';
|
||||||
|
|
||||||
|
interface IOverlayAddonTerminal extends Terminal {
|
||||||
|
__overlayNode?: HTMLElement
|
||||||
|
__overlayTimeout?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export function showOverlay(term: Terminal, msg: string, timeout: number): void {
|
||||||
|
const addonTerminal = <IOverlayAddonTerminal> term;
|
||||||
|
if (!addonTerminal.__overlayNode) {
|
||||||
|
if (!term.element)
|
||||||
|
return;
|
||||||
|
addonTerminal.__overlayNode = document.createElement('div');
|
||||||
|
addonTerminal.__overlayNode.style.cssText = (
|
||||||
|
'border-radius: 15px;' +
|
||||||
|
'font-size: xx-large;' +
|
||||||
|
'opacity: 0.75;' +
|
||||||
|
'padding: 0.2em 0.5em 0.2em 0.5em;' +
|
||||||
|
'position: absolute;' +
|
||||||
|
'-webkit-user-select: none;' +
|
||||||
|
'-webkit-transition: opacity 180ms ease-in;' +
|
||||||
|
'-moz-user-select: none;' +
|
||||||
|
'-moz-transition: opacity 180ms ease-in;');
|
||||||
|
|
||||||
|
addonTerminal.__overlayNode.addEventListener('mousedown', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
addonTerminal.__overlayNode.style.color = "#101010";
|
||||||
|
addonTerminal.__overlayNode.style.backgroundColor = "#f0f0f0";
|
||||||
|
|
||||||
|
addonTerminal.__overlayNode.textContent = msg;
|
||||||
|
addonTerminal.__overlayNode.style.opacity = '0.75';
|
||||||
|
|
||||||
|
if (!addonTerminal.__overlayNode.parentNode)
|
||||||
|
term.element.appendChild(addonTerminal.__overlayNode);
|
||||||
|
|
||||||
|
const divSize = term.element.getBoundingClientRect();
|
||||||
|
const overlaySize = addonTerminal.__overlayNode.getBoundingClientRect();
|
||||||
|
|
||||||
|
addonTerminal.__overlayNode.style.top = (divSize.height - overlaySize.height) / 2 + 'px';
|
||||||
|
addonTerminal.__overlayNode.style.left = (divSize.width - overlaySize.width) / 2 + 'px';
|
||||||
|
|
||||||
|
if (addonTerminal.__overlayTimeout)
|
||||||
|
clearTimeout(addonTerminal.__overlayTimeout);
|
||||||
|
|
||||||
|
if (timeout === null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
addonTerminal.__overlayTimeout = <number><any>setTimeout(() => {
|
||||||
|
addonTerminal.__overlayNode.style.opacity = '0';
|
||||||
|
addonTerminal.__overlayTimeout = <number><any>setTimeout(() => {
|
||||||
|
if (addonTerminal.__overlayNode.parentNode)
|
||||||
|
addonTerminal.__overlayNode.parentNode.removeChild(addonTerminal.__overlayNode);
|
||||||
|
addonTerminal.__overlayTimeout = null;
|
||||||
|
addonTerminal.__overlayNode.style.opacity = '0.75';
|
||||||
|
}, 200);
|
||||||
|
}, timeout || 1500);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function apply(terminalConstructor: typeof Terminal): void {
|
||||||
|
(<any>terminalConstructor.prototype).showOverlay = function (msg: string, timeout?: number): void {
|
||||||
|
return showOverlay(this, msg, timeout);
|
||||||
|
};
|
||||||
|
}
|
||||||
191
html/js/zmodem.ts
Normal file
191
html/js/zmodem.ts
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
import * as Promise from 'core-js/fn/promise';
|
||||||
|
import * as Zmodem from 'zmodem.js/src/zmodem_browser';
|
||||||
|
|
||||||
|
class Status {
|
||||||
|
element: HTMLElement;
|
||||||
|
filesRemaining: HTMLElement;
|
||||||
|
bytesRemaining: HTMLElement;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.element = document.getElementById('status');
|
||||||
|
this.filesRemaining = document.getElementById('files-remaining');
|
||||||
|
this.bytesRemaining = document.getElementById('bytes-remaining');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Choose {
|
||||||
|
element: HTMLElement;
|
||||||
|
files: HTMLInputElement;
|
||||||
|
filesNames: HTMLElement;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.element = document.getElementById('choose');
|
||||||
|
this.files = <HTMLInputElement>document.getElementById('files');
|
||||||
|
this.filesNames = document.getElementById('file-names');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Progress {
|
||||||
|
element: HTMLElement;
|
||||||
|
fileName: HTMLElement;
|
||||||
|
progressBar: HTMLProgressElement;
|
||||||
|
bytesReceived: HTMLElement;
|
||||||
|
bytesFile: HTMLElement;
|
||||||
|
percentReceived: HTMLElement;
|
||||||
|
skip: HTMLLinkElement;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.element = document.getElementById('progress');
|
||||||
|
this.fileName = document.getElementById('file-name');
|
||||||
|
this.progressBar = <HTMLProgressElement>document.getElementById('progress-bar');
|
||||||
|
this.bytesReceived = document.getElementById('bytes-received');
|
||||||
|
this.bytesFile = document.getElementById('bytes-file');
|
||||||
|
this.percentReceived = document.getElementById('percent-received');
|
||||||
|
this.skip = <HTMLLinkElement>document.getElementById('skip');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function bytesHuman (bytes: any, precision: number): string {
|
||||||
|
if (isNaN(parseFloat(bytes)) || !isFinite(bytes)) return '-';
|
||||||
|
if (bytes === 0) return '0';
|
||||||
|
if (typeof precision === 'undefined') precision = 1;
|
||||||
|
let units = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB'],
|
||||||
|
number = Math.floor(Math.log(bytes) / Math.log(1024));
|
||||||
|
return (bytes / Math.pow(1024, Math.floor(number))).toFixed(precision) + ' ' + units[number];
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Modal {
|
||||||
|
element: HTMLElement;
|
||||||
|
header: HTMLElement;
|
||||||
|
status: Status;
|
||||||
|
choose: Choose;
|
||||||
|
progress: Progress;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.element = document.getElementById('modal');
|
||||||
|
this.header = document.getElementById('header');
|
||||||
|
this.status = new Status();
|
||||||
|
this.choose = new Choose();
|
||||||
|
this.progress = new Progress();
|
||||||
|
}
|
||||||
|
|
||||||
|
public reset(title): void {
|
||||||
|
this.header.textContent = title;
|
||||||
|
this.status.element.style.display = 'none';
|
||||||
|
this.choose.element.style.display = 'none';
|
||||||
|
this.progress.element.style.display = 'none';
|
||||||
|
this.progress.bytesReceived.textContent = '-';
|
||||||
|
this.progress.percentReceived.textContent = '-%';
|
||||||
|
this.progress.progressBar.textContent = '0%';
|
||||||
|
this.progress.progressBar.value = 0;
|
||||||
|
this.progress.skip.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
public hide(): void {
|
||||||
|
this.element.classList.remove('is-active');
|
||||||
|
}
|
||||||
|
|
||||||
|
public updateFileInfo(fileInfo): void {
|
||||||
|
this.status.element.style.display = '';
|
||||||
|
this.choose.element.style.display = 'none';
|
||||||
|
this.progress.element.style.display = '';
|
||||||
|
this.status.filesRemaining.textContent = fileInfo.files_remaining;
|
||||||
|
this.status.bytesRemaining.textContent = bytesHuman(fileInfo.bytes_remaining, 2);
|
||||||
|
this.progress.fileName.textContent = fileInfo.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public showReceive(xfer): void {
|
||||||
|
this.reset('Receiving files');
|
||||||
|
this.updateFileInfo(xfer.get_details());
|
||||||
|
this.progress.skip.disabled = false;
|
||||||
|
this.progress.skip.onclick = function () {
|
||||||
|
(<HTMLLinkElement>this).disabled = true;
|
||||||
|
xfer.skip();
|
||||||
|
};
|
||||||
|
this.progress.skip.style.display = '';
|
||||||
|
this.element.classList.add('is-active');
|
||||||
|
}
|
||||||
|
|
||||||
|
public showSend(callback): void {
|
||||||
|
this.reset('Sending files');
|
||||||
|
this.choose.element.style.display = '';
|
||||||
|
this.choose.files.disabled = false;
|
||||||
|
this.choose.files.value = '';
|
||||||
|
this.choose.filesNames.textContent = '';
|
||||||
|
let self:Modal = this;
|
||||||
|
this.choose.files.onchange = function () {
|
||||||
|
(<HTMLInputElement>this).disabled = true;
|
||||||
|
let files:FileList = (<HTMLInputElement>this).files;
|
||||||
|
let fileNames:string = '';
|
||||||
|
for (let i = 0; i < files.length; i++) {
|
||||||
|
if (i === 0) {
|
||||||
|
fileNames = files[i].name;
|
||||||
|
} else {
|
||||||
|
fileNames += ', ' + files[i].name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.choose.filesNames.textContent = fileNames;
|
||||||
|
callback(files);
|
||||||
|
};
|
||||||
|
this.element.classList.add('is-active');
|
||||||
|
}
|
||||||
|
|
||||||
|
public updateProgress(xfer): void {
|
||||||
|
let size = xfer.get_details().size;
|
||||||
|
let offset = xfer.get_offset();
|
||||||
|
this.progress.bytesReceived.textContent = bytesHuman(offset, 2);
|
||||||
|
this.progress.bytesFile.textContent = bytesHuman(size, 2);
|
||||||
|
|
||||||
|
let percentReceived = (100 * offset / size).toFixed(2);
|
||||||
|
this.progress.percentReceived.textContent = percentReceived + '%';
|
||||||
|
|
||||||
|
this.progress.progressBar.textContent = percentReceived + '%';
|
||||||
|
this.progress.progressBar.setAttribute('value', percentReceived);
|
||||||
|
}
|
||||||
|
|
||||||
|
public handleSend(zsession): Promise<any> {
|
||||||
|
return new Promise((res) => {
|
||||||
|
this.showSend((files) => {
|
||||||
|
Zmodem.Browser.send_files(
|
||||||
|
zsession,
|
||||||
|
files,
|
||||||
|
{
|
||||||
|
on_progress: (obj, xfer) => {
|
||||||
|
this.updateFileInfo(xfer.get_details());
|
||||||
|
this.updateProgress(xfer);
|
||||||
|
},
|
||||||
|
on_file_complete: (obj) => {
|
||||||
|
// console.log(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).then(
|
||||||
|
zsession.close.bind(zsession),
|
||||||
|
console.error.bind(console)
|
||||||
|
).then(() => res());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public handleReceive(zsession): Promise<any> {
|
||||||
|
zsession.on('offer', (xfer) => {
|
||||||
|
this.showReceive(xfer);
|
||||||
|
let fileBuffer = [];
|
||||||
|
xfer.on('input', (payload) => {
|
||||||
|
this.updateProgress(xfer);
|
||||||
|
fileBuffer.push(new Uint8Array(payload));
|
||||||
|
});
|
||||||
|
xfer.accept().then(() => {
|
||||||
|
Zmodem.Browser.save_to_disk(
|
||||||
|
fileBuffer,
|
||||||
|
xfer.get_details().name
|
||||||
|
);
|
||||||
|
}, console.error.bind(console));
|
||||||
|
});
|
||||||
|
let promise = new Promise((res) => {
|
||||||
|
zsession.on('session_end', () => res());
|
||||||
|
});
|
||||||
|
zsession.start();
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js": "^2.5.3",
|
"core-js": "^2.5.3",
|
||||||
"fast-text-encoding": "^1.0.0",
|
"fast-text-encoding": "^1.0.0",
|
||||||
|
"url-join": "^4.0.0",
|
||||||
"xterm": "^3.13.0",
|
"xterm": "^3.13.0",
|
||||||
"zmodem.js": "^0.1.7"
|
"zmodem.js": "^0.1.7"
|
||||||
},
|
},
|
||||||
@@ -37,6 +38,8 @@
|
|||||||
"optimize-css-assets-webpack-plugin": "^4.0.1",
|
"optimize-css-assets-webpack-plugin": "^4.0.1",
|
||||||
"sass-loader": "^6.0.6",
|
"sass-loader": "^6.0.6",
|
||||||
"style-loader": "^0.19.1",
|
"style-loader": "^0.19.1",
|
||||||
|
"ts-loader": "^6.0.0",
|
||||||
|
"typescript": "^3.4.5",
|
||||||
"uglifyjs-webpack-plugin": "^1.2.5",
|
"uglifyjs-webpack-plugin": "^1.2.5",
|
||||||
"webpack": "^4.6.0",
|
"webpack": "^4.6.0",
|
||||||
"webpack-cli": "^2.1.2",
|
"webpack-cli": "^2.1.2",
|
||||||
|
|||||||
11
html/tsconfig.json
Normal file
11
html/tsconfig.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./dist/",
|
||||||
|
"sourceMap": true,
|
||||||
|
"module": "commonjs",
|
||||||
|
"target": "es5",
|
||||||
|
"lib": [ "dom", "es5"],
|
||||||
|
"jsx": "react",
|
||||||
|
"allowJs": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
|||||||
const devMode = process.env.NODE_ENV !== 'production';
|
const devMode = process.env.NODE_ENV !== 'production';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
entry: './js/app.js',
|
entry: './js/app.ts',
|
||||||
output: {
|
output: {
|
||||||
path: __dirname + '/dist',
|
path: __dirname + '/dist',
|
||||||
filename: devMode ? '[name].js' : '[name].[hash].js',
|
filename: devMode ? '[name].js' : '[name].[hash].js',
|
||||||
@@ -12,7 +12,7 @@ module.exports = {
|
|||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.js$/,
|
test: /\.js$/,
|
||||||
exclude: /node_modules\/(?!zmodem.js\/)/,
|
include: __dirname + '/node_modules/zmodem.js',
|
||||||
use: {
|
use: {
|
||||||
loader: 'babel-loader',
|
loader: 'babel-loader',
|
||||||
options: {
|
options: {
|
||||||
@@ -20,6 +20,11 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
test: /\.tsx?$/,
|
||||||
|
use: 'ts-loader',
|
||||||
|
exclude: /node_modules/
|
||||||
|
},
|
||||||
{
|
{
|
||||||
test: /\.s?[ac]ss$/,
|
test: /\.s?[ac]ss$/,
|
||||||
use: [
|
use: [
|
||||||
@@ -30,6 +35,9 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: [ '.tsx', '.ts', '.js' ]
|
||||||
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new CopyWebpackPlugin([
|
new CopyWebpackPlugin([
|
||||||
{ from: 'favicon.png', to: '.' }
|
{ from: 'favicon.png', to: '.' }
|
||||||
@@ -42,5 +50,5 @@ module.exports = {
|
|||||||
performance : {
|
performance : {
|
||||||
hints : false
|
hints : false
|
||||||
},
|
},
|
||||||
devtool: devMode ? 'cheap-module-eval-source-map' : 'source-map',
|
devtool: 'inline-source-map',
|
||||||
}
|
};
|
||||||
|
|||||||
124
html/yarn.lock
124
html/yarn.lock
@@ -464,7 +464,7 @@ babel-core@^6.26.0:
|
|||||||
babel-core@^6.26.3:
|
babel-core@^6.26.3:
|
||||||
version "6.26.3"
|
version "6.26.3"
|
||||||
resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207"
|
resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207"
|
||||||
integrity sha1-suLwnjQtDwyI4vAuBneUEl51wgc=
|
integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==
|
||||||
dependencies:
|
dependencies:
|
||||||
babel-code-frame "^6.26.0"
|
babel-code-frame "^6.26.0"
|
||||||
babel-generator "^6.26.0"
|
babel-generator "^6.26.0"
|
||||||
@@ -633,9 +633,9 @@ babel-helpers@^6.24.1:
|
|||||||
babel-template "^6.24.1"
|
babel-template "^6.24.1"
|
||||||
|
|
||||||
babel-loader@^7.1.4:
|
babel-loader@^7.1.4:
|
||||||
version "7.1.4"
|
version "7.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.1.4.tgz#e3463938bd4e6d55d1c174c5485d406a188ed015"
|
resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.1.5.tgz#e3ee0cd7394aa557e013b02d3e492bfd07aa6d68"
|
||||||
integrity sha1-40Y5OL1ObVXRwXTFSF1AahiO0BU=
|
integrity sha512-iCHfbieL5d1LfOQeeVJEUyD9rTwBcP/fcEbRCfempxTDuqrKpu0AZjLAQHEQa3Yqyj9ORKe2iHfoj4rHLf7xpw==
|
||||||
dependencies:
|
dependencies:
|
||||||
find-cache-dir "^1.0.0"
|
find-cache-dir "^1.0.0"
|
||||||
loader-utils "^1.0.2"
|
loader-utils "^1.0.2"
|
||||||
@@ -853,7 +853,17 @@ babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015
|
|||||||
babel-runtime "^6.22.0"
|
babel-runtime "^6.22.0"
|
||||||
babel-template "^6.24.1"
|
babel-template "^6.24.1"
|
||||||
|
|
||||||
babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1:
|
babel-plugin-transform-es2015-modules-commonjs@^6.23.0:
|
||||||
|
version "6.26.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3"
|
||||||
|
integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==
|
||||||
|
dependencies:
|
||||||
|
babel-plugin-transform-strict-mode "^6.24.1"
|
||||||
|
babel-runtime "^6.26.0"
|
||||||
|
babel-template "^6.26.0"
|
||||||
|
babel-types "^6.26.0"
|
||||||
|
|
||||||
|
babel-plugin-transform-es2015-modules-commonjs@^6.24.1:
|
||||||
version "6.26.0"
|
version "6.26.0"
|
||||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a"
|
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a"
|
||||||
integrity sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=
|
integrity sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=
|
||||||
@@ -997,9 +1007,9 @@ babel-plugin-transform-strict-mode@^6.24.1:
|
|||||||
babel-types "^6.24.1"
|
babel-types "^6.24.1"
|
||||||
|
|
||||||
babel-preset-env@^1.6.1:
|
babel-preset-env@^1.6.1:
|
||||||
version "1.6.1"
|
version "1.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.1.tgz#a18b564cc9b9afdf4aae57ae3c1b0d99188e6f48"
|
resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a"
|
||||||
integrity sha1-oYtWTMm5r99KrleuPBsNmRiOb0g=
|
integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==
|
||||||
dependencies:
|
dependencies:
|
||||||
babel-plugin-check-es2015-constants "^6.22.0"
|
babel-plugin-check-es2015-constants "^6.22.0"
|
||||||
babel-plugin-syntax-trailing-function-commas "^6.22.0"
|
babel-plugin-syntax-trailing-function-commas "^6.22.0"
|
||||||
@@ -1028,7 +1038,7 @@ babel-preset-env@^1.6.1:
|
|||||||
babel-plugin-transform-es2015-unicode-regex "^6.22.0"
|
babel-plugin-transform-es2015-unicode-regex "^6.22.0"
|
||||||
babel-plugin-transform-exponentiation-operator "^6.22.0"
|
babel-plugin-transform-exponentiation-operator "^6.22.0"
|
||||||
babel-plugin-transform-regenerator "^6.22.0"
|
babel-plugin-transform-regenerator "^6.22.0"
|
||||||
browserslist "^2.1.2"
|
browserslist "^3.2.6"
|
||||||
invariant "^2.2.2"
|
invariant "^2.2.2"
|
||||||
semver "^5.3.0"
|
semver "^5.3.0"
|
||||||
|
|
||||||
@@ -1311,6 +1321,13 @@ braces@^2.3.0, braces@^2.3.1:
|
|||||||
split-string "^3.0.2"
|
split-string "^3.0.2"
|
||||||
to-regex "^3.0.1"
|
to-regex "^3.0.1"
|
||||||
|
|
||||||
|
braces@^3.0.1:
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
|
||||||
|
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
|
||||||
|
dependencies:
|
||||||
|
fill-range "^7.0.1"
|
||||||
|
|
||||||
brorand@^1.0.1:
|
brorand@^1.0.1:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
|
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
|
||||||
@@ -1382,13 +1399,13 @@ browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6:
|
|||||||
caniuse-db "^1.0.30000639"
|
caniuse-db "^1.0.30000639"
|
||||||
electron-to-chromium "^1.2.7"
|
electron-to-chromium "^1.2.7"
|
||||||
|
|
||||||
browserslist@^2.1.2:
|
browserslist@^3.2.6:
|
||||||
version "2.11.3"
|
version "3.2.8"
|
||||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.11.3.tgz#fe36167aed1bbcde4827ebfe71347a2cc70b99b2"
|
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6"
|
||||||
integrity sha1-/jYWeu0bvN5IJ+v+cTR6LMcLmbI=
|
integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
caniuse-lite "^1.0.30000792"
|
caniuse-lite "^1.0.30000844"
|
||||||
electron-to-chromium "^1.3.30"
|
electron-to-chromium "^1.3.47"
|
||||||
|
|
||||||
buffer-from@^1.0.0:
|
buffer-from@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
@@ -1526,10 +1543,10 @@ caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
|
|||||||
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000792.tgz#a7dac6dc9f5181b675fd69e5cb06fefb523157f8"
|
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000792.tgz#a7dac6dc9f5181b675fd69e5cb06fefb523157f8"
|
||||||
integrity sha1-p9rG3J9RgbZ1/Wnlywb++1IxV/g=
|
integrity sha1-p9rG3J9RgbZ1/Wnlywb++1IxV/g=
|
||||||
|
|
||||||
caniuse-lite@^1.0.30000792:
|
caniuse-lite@^1.0.30000844:
|
||||||
version "1.0.30000792"
|
version "1.0.30000967"
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000792.tgz#d0cea981f8118f3961471afbb43c9a1e5bbf0332"
|
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000967.tgz#a5039577806fccee80a04aaafb2c0890b1ee2f73"
|
||||||
integrity sha1-0M6pgfgRjzlhRxr7tDyaHlu/AzI=
|
integrity sha512-rUBIbap+VJfxTzrM4akJ00lkvVb5/n5v3EGXfWzSH5zT8aJmGzjA8HWhJ4U6kCpzxozUSnB+yvAYDRPY6mRpgQ==
|
||||||
|
|
||||||
capture-stack-trace@^1.0.0:
|
capture-stack-trace@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
@@ -1944,11 +1961,18 @@ content-type@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
|
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
|
||||||
integrity sha1-4TjMdeBAxyexlm/l5fjJruJW/js=
|
integrity sha1-4TjMdeBAxyexlm/l5fjJruJW/js=
|
||||||
|
|
||||||
convert-source-map@^1.5.0, convert-source-map@^1.5.1:
|
convert-source-map@^1.5.0:
|
||||||
version "1.5.1"
|
version "1.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5"
|
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5"
|
||||||
integrity sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=
|
integrity sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=
|
||||||
|
|
||||||
|
convert-source-map@^1.5.1:
|
||||||
|
version "1.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20"
|
||||||
|
integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==
|
||||||
|
dependencies:
|
||||||
|
safe-buffer "~5.1.1"
|
||||||
|
|
||||||
cookies@~0.7.0:
|
cookies@~0.7.0:
|
||||||
version "0.7.1"
|
version "0.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.7.1.tgz#7c8a615f5481c61ab9f16c833731bcb8f663b99b"
|
resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.7.1.tgz#7c8a615f5481c61ab9f16c833731bcb8f663b99b"
|
||||||
@@ -2589,13 +2613,18 @@ electron-releases@^2.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/electron-releases/-/electron-releases-2.1.0.tgz#c5614bf811f176ce3c836e368a0625782341fd4e"
|
resolved "https://registry.yarnpkg.com/electron-releases/-/electron-releases-2.1.0.tgz#c5614bf811f176ce3c836e368a0625782341fd4e"
|
||||||
integrity sha1-xWFL+BHxds48g242igYleCNB/U4=
|
integrity sha1-xWFL+BHxds48g242igYleCNB/U4=
|
||||||
|
|
||||||
electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.30:
|
electron-to-chromium@^1.2.7:
|
||||||
version "1.3.30"
|
version "1.3.30"
|
||||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.30.tgz#9666f532a64586651fc56a72513692e820d06a80"
|
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.30.tgz#9666f532a64586651fc56a72513692e820d06a80"
|
||||||
integrity sha1-lmb1MqZFhmUfxWpyUTaS6CDQaoA=
|
integrity sha1-lmb1MqZFhmUfxWpyUTaS6CDQaoA=
|
||||||
dependencies:
|
dependencies:
|
||||||
electron-releases "^2.1.0"
|
electron-releases "^2.1.0"
|
||||||
|
|
||||||
|
electron-to-chromium@^1.3.47:
|
||||||
|
version "1.3.134"
|
||||||
|
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.134.tgz#550222bddac43c6bd6c445c3543a0fe8a615021d"
|
||||||
|
integrity sha512-C3uK2SrtWg/gSWaluLHWSHjyebVZCe4ZC0NVgTAoTq8tCR9FareRK5T7R7AS/nPZShtlEcjVMX1kQ8wi4nU68w==
|
||||||
|
|
||||||
elegant-spinner@^1.0.1:
|
elegant-spinner@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e"
|
resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e"
|
||||||
@@ -3028,6 +3057,13 @@ fill-range@^4.0.0:
|
|||||||
repeat-string "^1.6.1"
|
repeat-string "^1.6.1"
|
||||||
to-regex-range "^2.1.0"
|
to-regex-range "^2.1.0"
|
||||||
|
|
||||||
|
fill-range@^7.0.1:
|
||||||
|
version "7.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
|
||||||
|
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
|
||||||
|
dependencies:
|
||||||
|
to-regex-range "^5.0.1"
|
||||||
|
|
||||||
find-cache-dir@^1.0.0:
|
find-cache-dir@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f"
|
resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f"
|
||||||
@@ -4427,6 +4463,11 @@ is-number@^4.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff"
|
resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff"
|
||||||
integrity sha1-ACbjf1RU1z41bf5lZGmYZ8an8P8=
|
integrity sha1-ACbjf1RU1z41bf5lZGmYZ8an8P8=
|
||||||
|
|
||||||
|
is-number@^7.0.0:
|
||||||
|
version "7.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
||||||
|
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
|
||||||
|
|
||||||
is-obj@^1.0.0:
|
is-obj@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
|
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
|
||||||
@@ -5440,6 +5481,14 @@ micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8, mic
|
|||||||
snapdragon "^0.8.1"
|
snapdragon "^0.8.1"
|
||||||
to-regex "^3.0.2"
|
to-regex "^3.0.2"
|
||||||
|
|
||||||
|
micromatch@^4.0.0:
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259"
|
||||||
|
integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==
|
||||||
|
dependencies:
|
||||||
|
braces "^3.0.1"
|
||||||
|
picomatch "^2.0.5"
|
||||||
|
|
||||||
miller-rabin@^4.0.0:
|
miller-rabin@^4.0.0:
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d"
|
resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d"
|
||||||
@@ -6409,6 +6458,11 @@ performance-now@^2.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
||||||
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
|
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
|
||||||
|
|
||||||
|
picomatch@^2.0.5:
|
||||||
|
version "2.0.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6"
|
||||||
|
integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==
|
||||||
|
|
||||||
pify@^2.0.0, pify@^2.3.0:
|
pify@^2.0.0, pify@^2.3.0:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
|
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
|
||||||
@@ -7550,6 +7604,11 @@ semver@^5.0.3, semver@^5.1.0, semver@^5.5.0:
|
|||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
|
||||||
integrity sha1-3Eu8emyp2Rbe5dQ1FvAJK1j3uKs=
|
integrity sha1-3Eu8emyp2Rbe5dQ1FvAJK1j3uKs=
|
||||||
|
|
||||||
|
semver@^6.0.0:
|
||||||
|
version "6.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/semver/-/semver-6.0.0.tgz#05e359ee571e5ad7ed641a6eec1e547ba52dea65"
|
||||||
|
integrity sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==
|
||||||
|
|
||||||
semver@~5.3.0:
|
semver@~5.3.0:
|
||||||
version "5.3.0"
|
version "5.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
|
||||||
@@ -8232,6 +8291,13 @@ to-regex-range@^2.1.0:
|
|||||||
is-number "^3.0.0"
|
is-number "^3.0.0"
|
||||||
repeat-string "^1.6.1"
|
repeat-string "^1.6.1"
|
||||||
|
|
||||||
|
to-regex-range@^5.0.1:
|
||||||
|
version "5.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
|
||||||
|
integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
|
||||||
|
dependencies:
|
||||||
|
is-number "^7.0.0"
|
||||||
|
|
||||||
to-regex@^3.0.1, to-regex@^3.0.2:
|
to-regex@^3.0.1, to-regex@^3.0.2:
|
||||||
version "3.0.2"
|
version "3.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce"
|
resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce"
|
||||||
@@ -8276,6 +8342,17 @@ trim-right@^1.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
glob "^6.0.4"
|
glob "^6.0.4"
|
||||||
|
|
||||||
|
ts-loader@^6.0.0:
|
||||||
|
version "6.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.0.0.tgz#d489f49410725a12e696ad0b67c33937a7c49147"
|
||||||
|
integrity sha512-lszy+D41R0Te2+loZxADWS+E1+Z55A+i3dFfFie1AZHL++65JRKVDBPQgeWgRrlv5tbxdU3zOtXp8b7AFR6KEg==
|
||||||
|
dependencies:
|
||||||
|
chalk "^2.3.0"
|
||||||
|
enhanced-resolve "^4.0.0"
|
||||||
|
loader-utils "^1.0.2"
|
||||||
|
micromatch "^4.0.0"
|
||||||
|
semver "^6.0.0"
|
||||||
|
|
||||||
tty-browserify@0.0.0:
|
tty-browserify@0.0.0:
|
||||||
version "0.0.0"
|
version "0.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
|
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
|
||||||
@@ -8311,6 +8388,11 @@ typedarray@^0.0.6:
|
|||||||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||||
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||||
|
|
||||||
|
typescript@^3.4.5:
|
||||||
|
version "3.4.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.5.tgz#2d2618d10bb566572b8d7aad5180d84257d70a99"
|
||||||
|
integrity sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==
|
||||||
|
|
||||||
uglify-es@^3.3.4:
|
uglify-es@^3.3.4:
|
||||||
version "3.3.9"
|
version "3.3.9"
|
||||||
resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677"
|
resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677"
|
||||||
|
|||||||
2
src/index.html
vendored
2
src/index.html
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user