Fix the terminal to stop glitching out and not displaying unless window is resized.

This commit is contained in:
Dane Everitt 2017-04-14 01:21:38 -04:00
parent 6fb44f7d7b
commit a2b451b990
No known key found for this signature in database
GPG key ID: EEA66103B3D71F53
11 changed files with 478 additions and 603 deletions

View file

@ -9,6 +9,7 @@ This project follows [Semantic Versioning](http://semver.org) guidelines.
* `[pre.7]` — Fixes bug with injected JS that was causing `<!DOCTYPE html>` to be ignored in templates. * `[pre.7]` — Fixes bug with injected JS that was causing `<!DOCTYPE html>` to be ignored in templates.
* `[pre.7]` — Fixes exception thrown when trying to delete a node due to a misnamed model. * `[pre.7]` — Fixes exception thrown when trying to delete a node due to a misnamed model.
* `[pre.7]` — Fixes username vanishing on failed login attempts. * `[pre.7]` — Fixes username vanishing on failed login attempts.
* `[pre.7]` — Terminal is now fixed to actually output all lines, rather than leaving one hanging in neverland until the browser is resized.
### Added ### Added
* Login attempts and pasword reset requests are now protected by invisible ReCaptcha. This feature can be disabled with a `.env` variable. * Login attempts and pasword reset requests are now protected by invisible ReCaptcha. This feature can be disabled with a `.env` variable.
@ -24,6 +25,7 @@ This project follows [Semantic Versioning](http://semver.org) guidelines.
* Routes are now handled in the `routes/` folder, and use a significantly cleaner syntax. Controller names and methods have been updated as well to be clearer as well as avoid conflicts with PHP reserved keywords. * Routes are now handled in the `routes/` folder, and use a significantly cleaner syntax. Controller names and methods have been updated as well to be clearer as well as avoid conflicts with PHP reserved keywords.
* API has been completely overhauled to use new permissions system. **Any old API keys will immediately become invalid and fail to operate properly anymore. You will need to generate new keys.** * API has been completely overhauled to use new permissions system. **Any old API keys will immediately become invalid and fail to operate properly anymore. You will need to generate new keys.**
* Cleaned up dynamic database connection setting to use a single function call from the host model. * Cleaned up dynamic database connection setting to use a single function call from the host model.
* `[pre.7]` — Corrected a config option for spigot servers to set a boolean value as boolean, and not as a string.
## v0.6.0-pre.7 (Courageous Carniadactylus) ## v0.6.0-pre.7 (Courageous Carniadactylus)
### Fixed ### Fixed

View file

@ -17,260 +17,236 @@
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE. // SOFTWARE.
var CONSOLE_PUSH_COUNT = Pterodactyl.config.console_count || 10;
var CONSOLE_PUSH_FREQ = Pterodactyl.config.console_freq || 200;
var CONSOLE_OUTPUT_LIMIT = Pterodactyl.config.console_limit || 2000;
var InitialLogSent = false;
var Console = (function () { (function initConsole() {
var CONSOLE_PUSH_COUNT = Pterodactyl.config.console_count; window.TerminalQueue = [];
var CONSOLE_PUSH_FREQ = Pterodactyl.config.console_freq; window.Terminal = $('#terminal').terminal(function (command, term) {
Socket.emit('send command', command);
var terminalQueue; }, {
var terminal; greetings: '',
var recievedInitialLog = false; name: Pterodactyl.server.uuid,
height: 450,
var cpuChart; exit: false,
var cpuData; echoCommand: false,
var memoryChart; outputLimit: CONSOLE_OUTPUT_LIMIT,
var memoryData; prompt: Pterodactyl.server.username + ':~$ ',
var timeLabels; scrollOnEcho: false,
scrollBottomOffset: 5,
var $terminalNotify; onBlur: function (terminal) {
return false;
function initConsole() {
terminalQueue = [];
terminal = $('#terminal').terminal(function (command, term) {
Socket.emit('send command', command);
}, {
greetings: '',
name: Pterodactyl.server.uuid,
height: 450,
exit: false,
prompt: Pterodactyl.server.username + ':~$ ',
scrollOnEcho: false,
scrollBottomOffset: 5,
onBlur: function (terminal) {
return false;
}
});
$terminalNotify = $('#terminalNotify');
$terminalNotify.on('click', function () {
terminal.scroll_to_bottom();
$terminalNotify.addClass('hidden');
})
terminal.on('scroll', function () {
if (terminal.is_bottom()) {
$terminalNotify.addClass('hidden');
}
})
}
function initGraphs() {
var ctc = $('#chart_cpu');
timeLabels = [];
cpuData = [];
cpuChart = new Chart(ctc, {
type: 'line',
data: {
labels: timeLabels,
datasets: [
{
label: "Percent Use",
fill: false,
lineTension: 0.03,
backgroundColor: "#3c8dbc",
borderColor: "#3c8dbc",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "#3c8dbc",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "#3c8dbc",
pointHoverBorderColor: "rgba(220,220,220,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: cpuData,
spanGaps: false,
}
]
},
options: {
title: {
display: true,
text: 'CPU Usage (as Percent Total)'
},
legend: {
display: false,
},
animation: {
duration: 1,
}
}
});
var ctm = $('#chart_memory');
memoryData = [];
memoryChart = new Chart(ctm, {
type: 'line',
data: {
labels: timeLabels,
datasets: [
{
label: "Memory Use",
fill: false,
lineTension: 0.03,
backgroundColor: "#3c8dbc",
borderColor: "#3c8dbc",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "#3c8dbc",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "#3c8dbc",
pointHoverBorderColor: "rgba(220,220,220,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: memoryData,
spanGaps: false,
}
]
},
options: {
title: {
display: true,
text: 'Memory Usage (in Megabytes)'
},
legend: {
display: false,
},
animation: {
duration: 1,
}
}
});
}
function addSocketListeners() {
// Update Listings on Initial Status
Socket.on('initial status', function (data) {
if (! recievedInitialLog) {
updateServerPowerControls(data.status);
if (data.status === 1 || data.status === 2) {
Socket.emit('send server log');
}
}
});
// Update Listings on Status
Socket.on('status', function (data) {
updateServerPowerControls(data.status);
});
Socket.on('server log', function (data) {
if (! recievedInitialLog) {
terminal.clear();
terminalQueue.push(data);
recievedInitialLog = true;
}
});
Socket.on('console', function (data) {
terminalQueue.push(data.line);
});
Socket.on('proc', function (proc) {
if (cpuData.length > 10) {
cpuData.shift();
memoryData.shift();
timeLabels.shift();
}
var cpuUse = (Pterodactyl.server.cpu > 0) ? parseFloat(((proc.data.cpu.total / Pterodactyl.server.cpu) * 100).toFixed(3).toString()) : proc.data.cpu.total;
cpuData.push(cpuUse);
memoryData.push(parseInt(proc.data.memory.total / (1024 * 1024)));
var m = new Date();
timeLabels.push($.format.date(new Date(), 'HH:mm:ss'));
cpuChart.update();
memoryChart.update();
});
}
function pushOutputQueue() {
if (terminalQueue.length > CONSOLE_PUSH_COUNT) {
// console throttled warning show
} }
});
if (terminalQueue.length > 0) { window.TerminalNotifyElement = $('#terminalNotify');
for (var i = 0; i < CONSOLE_PUSH_COUNT && terminalQueue.length > 0; i++) { TerminalNotifyElement.on('click', function () {
terminal.echo(terminalQueue[0], {flush: false}); Terminal.scroll_to_bottom();
terminalQueue.shift(); TerminalNotifyElement.addClass('hidden');
} })
terminal.flush()
// Show Terminal.on('scroll', function () {
if (!terminal.is_bottom()) { if (Terminal.is_bottom()) {
$terminalNotify.removeClass('hidden'); TerminalNotifyElement.addClass('hidden');
}
} }
})
window.setTimeout(pushOutputQueue, CONSOLE_PUSH_FREQ); // Socket.on('initial status', function (data) {
} // Terminal.clear();
// if (data.status === 1 || data.status === 2) {
function updateServerPowerControls (data) { // Socket.emit('send server log');
// Server is On or Starting // }
if(data == 1 || data == 2) { // });
$('[data-attr="power"][data-action="start"]').addClass('disabled');
$('[data-attr="power"][data-action="stop"], [data-attr="power"][data-action="restart"]').removeClass('disabled');
} else {
if (data == 0) {
$('[data-attr="power"][data-action="start"]').removeClass('disabled');
}
$('[data-attr="power"][data-action="stop"], [data-attr="power"][data-action="restart"]').addClass('disabled');
}
if(data !== 0) {
$('[data-attr="power"][data-action="kill"]').removeClass('disabled');
} else {
$('[data-attr="power"][data-action="kill"]').addClass('disabled');
}
}
return {
init: function () {
initConsole();
pushOutputQueue();
initGraphs();
addSocketListeners();
$('[data-attr="power"]').click(function (event) {
if (! $(this).hasClass('disabled')) {
Socket.emit('set status', $(this).data('action'));
}
});
},
getTerminal: function () {
return terminal
},
getTerminalQueue: function () {
return terminalQueue
},
}
})(); })();
(function pushOutputQueue() {
if (TerminalQueue.length > CONSOLE_PUSH_COUNT) {
// console throttled warning show
}
if (TerminalQueue.length > 0) {
for (var i = 0; i < CONSOLE_PUSH_COUNT && TerminalQueue.length > 0; i++) {
Terminal.echo(TerminalQueue[0], { flush: false });
TerminalQueue.shift();
}
// Flush after looping through all.
Terminal.flush();
// Show Warning
if (! Terminal.is_bottom()) {
TerminalNotifyElement.removeClass('hidden');
}
}
window.setTimeout(pushOutputQueue, CONSOLE_PUSH_FREQ);
})();
(function setupSocketListeners() {
// Update Listings on Initial Status
Socket.on('initial status', function (data) {
console.log('initial status 2');
if (! InitialLogSent) {
updateServerPowerControls(data.status);
if (data.status === 1 || data.status === 2) {
Socket.emit('send server log');
}
}
});
// Update Listings on Status
Socket.on('status', function (data) {
updateServerPowerControls(data.status);
});
Socket.on('server log', function (data) {
if (! InitialLogSent) {
Terminal.clear();
TerminalQueue.push(data);
InitialLogSent = true;
}
});
Socket.on('console', function (data) {
TerminalQueue.push(data.line);
});
})();
function updateServerPowerControls (data) {
// Server is On or Starting
if(data == 1 || data == 2) {
$('[data-attr="power"][data-action="start"]').addClass('disabled');
$('[data-attr="power"][data-action="stop"], [data-attr="power"][data-action="restart"]').removeClass('disabled');
} else {
if (data == 0) {
$('[data-attr="power"][data-action="start"]').removeClass('disabled');
}
$('[data-attr="power"][data-action="stop"], [data-attr="power"][data-action="restart"]').addClass('disabled');
}
if(data !== 0) {
$('[data-attr="power"][data-action="kill"]').removeClass('disabled');
} else {
$('[data-attr="power"][data-action="kill"]').addClass('disabled');
}
}
$(document).ready(function () { $(document).ready(function () {
Console.init(); $('[data-attr="power"]').click(function (event) {
if (! $(this).hasClass('disabled')) {
Socket.emit('set status', $(this).data('action'));
}
});
Socket.on('proc', function (proc) {
if (CPUData.length > 10) {
CPUData.shift();
MemoryData.shift();
TimeLabels.shift();
}
var cpuUse = (Pterodactyl.server.cpu > 0) ? parseFloat(((proc.data.cpu.total / Pterodactyl.server.cpu) * 100).toFixed(3).toString()) : proc.data.cpu.total;
CPUData.push(cpuUse);
MemoryData.push(parseInt(proc.data.memory.total / (1024 * 1024)));
TimeLabels.push($.format.date(new Date(), 'HH:mm:ss'));
CPUChart.update();
MemoryChart.update();
});
var ctc = $('#chart_cpu');
var TimeLabels = [];
var CPUData = [];
var CPUChart = new Chart(ctc, {
type: 'line',
data: {
labels: TimeLabels,
datasets: [
{
label: "Percent Use",
fill: false,
lineTension: 0.03,
backgroundColor: "#3c8dbc",
borderColor: "#3c8dbc",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "#3c8dbc",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "#3c8dbc",
pointHoverBorderColor: "rgba(220,220,220,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: CPUData,
spanGaps: false,
}
]
},
options: {
title: {
display: true,
text: 'CPU Usage (as Percent Total)'
},
legend: {
display: false,
},
animation: {
duration: 1,
}
}
});
var ctm = $('#chart_memory');
MemoryData = [];
MemoryChart = new Chart(ctm, {
type: 'line',
data: {
labels: TimeLabels,
datasets: [
{
label: "Memory Use",
fill: false,
lineTension: 0.03,
backgroundColor: "#3c8dbc",
borderColor: "#3c8dbc",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "#3c8dbc",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "#3c8dbc",
pointHoverBorderColor: "rgba(220,220,220,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: MemoryData,
spanGaps: false,
}
]
},
options: {
title: {
display: true,
text: 'Memory Usage (in Megabytes)'
},
legend: {
display: false,
},
animation: {
duration: 1,
}
}
});
}); });

View file

@ -50,11 +50,13 @@ var Server = (function () {
var notifySocketError = false; var notifySocketError = false;
console.log('Starting connection');
window.Socket = io(Pterodactyl.node.scheme + '://' + Pterodactyl.node.fqdn + ':' + Pterodactyl.node.daemonListen + '/ws/' + Pterodactyl.server.uuid, { window.Socket = io(Pterodactyl.node.scheme + '://' + Pterodactyl.node.fqdn + ':' + Pterodactyl.node.daemonListen + '/ws/' + Pterodactyl.server.uuid, {
'query': 'token=' + Pterodactyl.server.daemonSecret, 'query': 'token=' + Pterodactyl.server.daemonSecret,
}); });
Socket.io.on('connect_error', function (err) { Socket.io.on('connect_error', function (err) {
console.log('connect_error');
if(typeof notifySocketError !== 'object') { if(typeof notifySocketError !== 'object') {
notifySocketError = $.notify({ notifySocketError = $.notify({
message: 'There was an error attempting to establish a WebSocket connection to the Daemon. This panel will not work as expected.<br /><br />' + err, message: 'There was an error attempting to establish a WebSocket connection to the Daemon. This panel will not work as expected.<br /><br />' + err,
@ -67,6 +69,7 @@ var Server = (function () {
// Connected to Socket Successfully // Connected to Socket Successfully
Socket.on('connect', function () { Socket.on('connect', function () {
console.log('connect');
if (notifySocketError !== false) { if (notifySocketError !== false) {
notifySocketError.close(); notifySocketError.close();
notifySocketError = false; notifySocketError = false;
@ -74,6 +77,7 @@ var Server = (function () {
}); });
Socket.on('initial status', function (data) { Socket.on('initial status', function (data) {
console.log('initial status');
setStatusIcon(data.status); setStatusIcon(data.status);
}); });

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,121 @@
/* global define, KeyboardEvent, module */
// https://github.com/cvan/keyboardevent-key-polyfill/blob/master/LICENSE.md
(function () {
var keyboardeventKeyPolyfill = {
polyfill: polyfill,
keys: {
3: 'Cancel',
6: 'Help',
8: 'Backspace',
9: 'Tab',
12: 'Clear',
13: 'Enter',
16: 'Shift',
17: 'Control',
18: 'Alt',
19: 'Pause',
20: 'CapsLock',
27: 'Escape',
28: 'Convert',
29: 'NonConvert',
30: 'Accept',
31: 'ModeChange',
32: ' ',
33: 'PageUp',
34: 'PageDown',
35: 'End',
36: 'Home',
37: 'ArrowLeft',
38: 'ArrowUp',
39: 'ArrowRight',
40: 'ArrowDown',
41: 'Select',
42: 'Print',
43: 'Execute',
44: 'PrintScreen',
45: 'Insert',
46: 'Delete',
48: ['0', ')'],
49: ['1', '!'],
50: ['2', '@'],
51: ['3', '#'],
52: ['4', '$'],
53: ['5', '%'],
54: ['6', '^'],
55: ['7', '&'],
56: ['8', '*'],
57: ['9', '('],
91: 'OS',
93: 'ContextMenu',
144: 'NumLock',
145: 'ScrollLock',
181: 'VolumeMute',
182: 'VolumeDown',
183: 'VolumeUp',
186: [';', ':'],
187: ['=', '+'],
188: [',', '<'],
189: ['-', '_'],
190: ['.', '>'],
191: ['/', '?'],
192: ['`', '~'],
219: ['[', '{'],
220: ['\\', '|'],
221: [']', '}'],
222: ["'", '"'],
224: 'Meta',
225: 'AltGraph',
246: 'Attn',
247: 'CrSel',
248: 'ExSel',
249: 'EraseEof',
250: 'Play',
251: 'ZoomOut'
}
};
// Function keys (F1-24).
var i;
for (i = 1; i < 25; i++) {
keyboardeventKeyPolyfill.keys[111 + i] = 'F' + i;
}
// Printable ASCII characters.
var letter = '';
for (i = 65; i < 91; i++) {
letter = String.fromCharCode(i);
keyboardeventKeyPolyfill.keys[i] = [letter.toLowerCase(), letter.toUpperCase()];
}
function polyfill () {
if (!('KeyboardEvent' in window) ||
'key' in KeyboardEvent.prototype) {
return false;
}
// Polyfill `key` on `KeyboardEvent`.
var proto = {
get: function (x) {
var key = keyboardeventKeyPolyfill.keys[this.which || this.keyCode];
if (Array.isArray(key)) {
key = key[+this.shiftKey];
}
return key;
}
};
Object.defineProperty(KeyboardEvent.prototype, 'key', proto);
return proto;
}
if (typeof define === 'function' && define.amd) {
define('keyboardevent-key-polyfill', keyboardeventKeyPolyfill);
} else if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
module.exports = keyboardeventKeyPolyfill;
} else if (window) {
window.keyboardeventKeyPolyfill = keyboardeventKeyPolyfill;
}
})();

View file

@ -9,7 +9,7 @@
* *
* This is example of how to create custom formatter for jQuery Terminal * This is example of how to create custom formatter for jQuery Terminal
* *
* Copyright (c) 2014-2016 Jakub Jankiewicz <http://jcubic.pl> * Copyright (c) 2014-2016 Jakub Jankiewicz <http://jcubic.pl/me>
* Released under the MIT license * Released under the MIT license
* *
*/ */
@ -21,10 +21,10 @@
// :: Replace overtyping (from man) formatting with terminal formatting // :: Replace overtyping (from man) formatting with terminal formatting
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
$.terminal.overtyping = function(string) { $.terminal.overtyping = function(string) {
return string.replace(/((?:_\x08.|.\x08_)+)/g, function(full, g) { return string.replace(/((?:_\x08.|.\x08_)+)/g, function(full) {
var striped = full.replace(/_x08|\x08_|_\u0008|\u0008_/g, ''); var striped = full.replace(/_x08|\x08_|_\u0008|\u0008_/g, '');
return '[[u;;]' + striped + ']'; return '[[u;;]' + striped + ']';
}).replace(/((?:.\x08.)+)/g, function(full, g) { }).replace(/((?:.\x08.)+)/g, function(full) {
return '[[b;#fff;]' + full.replace(/(.)(?:\x08|\u0008)\1/g, return '[[b;#fff;]' + full.replace(/(.)(?:\x08|\u0008)\1/g,
function(full, g) { function(full, g) {
return g; return g;
@ -153,7 +153,47 @@
var _8bit_background = false; var _8bit_background = false;
var process_8bit = false; var process_8bit = false;
var palette = $.terminal.ansi_colors.palette; var palette = $.terminal.ansi_colors.palette;
for(var i in controls) { function set_styles(num) {
switch (num) {
case 1:
styles.push('b');
bold = true;
faited = false;
break;
case 4:
styles.push('u');
break;
case 3:
styles.push('i');
break;
case 5:
process_8bit = true;
break;
case 38:
_8bit_color = true;
break;
case 48:
_8bit_background = true;
break;
case 2:
faited = true;
bold = false;
break;
case 7:
reverse = true;
break;
default:
if (controls.indexOf('5') === -1) {
if (color_list[num]) {
output_color = color_list[num];
}
if (background_list[num]) {
output_background = background_list[num];
}
}
}
}
for (var i in controls) {
if (controls.hasOwnProperty(i)) { if (controls.hasOwnProperty(i)) {
num = parseInt(controls[i], 10); num = parseInt(controls[i], 10);
if (process_8bit && (_8bit_background || _8bit_color)) { if (process_8bit && (_8bit_background || _8bit_color)) {
@ -164,44 +204,7 @@
output_background = palette[num]; output_background = palette[num];
} }
} else { } else {
switch(num) { set_styles(num);
case 1:
styles.push('b');
bold = true;
faited = false;
break;
case 4:
styles.push('u');
break;
case 3:
styles.push('i');
break;
case 5:
process_8bit = true;
break;
case 38:
_8bit_color = true;
break;
case 48:
_8bit_background = true;
break;
case 2:
faited = true;
bold = false;
break;
case 7:
reverse = true;
break;
default:
if (controls.indexOf('5') == -1) {
if (color_list[num]) {
output_color = color_list[num];
}
if (background_list[num]) {
output_background = background_list[num];
}
}
}
} }
} }
} }
@ -225,14 +228,14 @@
} }
if (_8bit_color) { if (_8bit_color) {
color = output_color; color = output_color;
} else if (output_color == 'inherit') { } else if (output_color === 'inherit') {
color = output_color; color = output_color;
} else { } else {
color = colors[output_color]; color = colors[output_color];
} }
if (_8bit_background) { if (_8bit_background) {
background = output_background; background = output_background;
} else if (output_background == 'transparent') { } else if (output_background === 'transparent') {
background = output_background; background = output_background;
} else { } else {
background = backgrounds[output_background]; background = backgrounds[output_background];
@ -242,51 +245,50 @@
return function(input) { return function(input) {
//merge multiple codes //merge multiple codes
/*input = input.replace(/((?:\x1B\[[0-9;]*[A-Za-z])*)/g, function(group) { /*input = input.replace(/((?:\x1B\[[0-9;]*[A-Za-z])*)/g, function(group) {
return group.replace(/m\x1B\[/g, ';'); return group.replace(/m\x1B\[/g, ';');
});*/ });*/
var splitted = input.split(/(\x1B\[[0-9;]*[A-Za-z])/g); var splitted = input.split(/(\x1B\[[0-9;]*[A-Za-z])/g);
if (splitted.length == 1) { if (splitted.length === 1) {
return input; return input;
} }
var output = []; var output = [];
//skip closing at the begining //skip closing at the begining
if (splitted.length > 3) { if (splitted.length > 3) {
var str = splitted.slice(0,3).join(''); var str = splitted.slice(0, 3).join('');
if (str.match(/^\[0*m$/)) { if (str.match(/^\[0*m$/)) {
splitted = splitted.slice(3); splitted = splitted.slice(3);
} }
} }
var next, prev_color, prev_background, code, match; var prev_color, prev_background, code, match;
var inside = false; var inside = false;
for (var i=0; i<splitted.length; ++i) { for (var i = 0; i < splitted.length; ++i) {
match = splitted[i].match(/^\x1B\[([0-9;]*)([A-Za-z])$/); match = splitted[i].match(/^\x1B\[([0-9;]*)([A-Za-z])$/);
if (match) { if (match) {
switch (match[2]) { switch (match[2]) {
case 'm': case 'm':
if (+match[1] !== 0) {
code = format_ansi(match[1]);
}
if (inside) {
output.push(']');
if (+match[1] === 0) {
//just closing
inside = false;
prev_color = prev_background = '';
} else {
// someone forget to close - move to next
code[1] = code[1] || prev_color;
code[2] = code[2] || prev_background;
output.push('[[' + code.join(';') + ']');
// store colors to next use
if (code[1]) {
prev_color = code[1];
}
if (code[2]) {
prev_background = code[2];
}
}
} else {
if (+match[1] !== 0) { if (+match[1] !== 0) {
code = format_ansi(match[1]);
}
if (inside) {
output.push(']');
if (+match[1] === 0) {
//just closing
inside = false;
prev_color = prev_background = '';
} else {
// someone forget to close - move to next
code[1] = code[1] || prev_color;
code[2] = code[2] || prev_background;
output.push('[[' + code.join(';') + ']');
// store colors to next use
if (code[1]) {
prev_color = code[1];
}
if (code[2]) {
prev_background = code[2];
}
}
} else if (+match[1] !== 0) {
inside = true; inside = true;
code[1] = code[1] || prev_color; code[1] = code[1] || prev_color;
code[2] = code[2] || prev_background; code[2] = code[2] || prev_background;
@ -299,8 +301,7 @@
prev_background = code[2]; prev_background = code[2];
} }
} }
} break;
break;
} }
} else { } else {
output.push(splitted[i]); output.push(splitted[i]);

View file

@ -222,6 +222,9 @@
<div class="control-sidebar-bg"></div> <div class="control-sidebar-bg"></div>
</div> </div>
@section('footer-scripts') @section('footer-scripts')
{!! Theme::js('vendor/terminal/keyboard.polyfill.js') !!}
<script>keyboardeventKeyPolyfill.polyfill();</script>
{!! Theme::js('js/laroute.js') !!} {!! Theme::js('js/laroute.js') !!}
{!! Theme::js('vendor/jquery/jquery.min.js') !!} {!! Theme::js('vendor/jquery/jquery.min.js') !!}
{!! Theme::js('vendor/sweetalert/sweetalert.min.js') !!} {!! Theme::js('vendor/sweetalert/sweetalert.min.js') !!}

View file

@ -262,6 +262,9 @@
<div class="control-sidebar-bg"></div> <div class="control-sidebar-bg"></div>
</div> </div>
@section('footer-scripts') @section('footer-scripts')
{!! Theme::js('vendor/terminal/keyboard.polyfill.js') !!}
<script>keyboardeventKeyPolyfill.polyfill();</script>
{!! Theme::js('js/laroute.js') !!} {!! Theme::js('js/laroute.js') !!}
{!! Theme::js('vendor/jquery/jquery.min.js') !!} {!! Theme::js('vendor/jquery/jquery.min.js') !!}
{!! Theme::js('vendor/sweetalert/sweetalert.min.js') !!} {!! Theme::js('vendor/sweetalert/sweetalert.min.js') !!}

View file

@ -83,7 +83,7 @@
@parent @parent
{!! Theme::js('js/frontend/server.socket.js') !!} {!! Theme::js('js/frontend/server.socket.js') !!}
{!! Theme::js('vendor/mousewheel/jquery.mousewheel-min.js') !!} {!! Theme::js('vendor/mousewheel/jquery.mousewheel-min.js') !!}
{!! Theme::js('vendor/terminal/jquery.terminal-0.11.23.min.js') !!} {!! Theme::js('vendor/terminal/jquery.terminal.min.js') !!}
{!! Theme::js('vendor/terminal/unix_formatting.js') !!} {!! Theme::js('vendor/terminal/unix_formatting.js') !!}
{!! Theme::js('js/frontend/console.js') !!} {!! Theme::js('js/frontend/console.js') !!}
{!! Theme::js('vendor/chartjs/chart.min.js') !!} {!! Theme::js('vendor/chartjs/chart.min.js') !!}