1
0
This commit is contained in:
2024-03-23 20:25:41 +09:00
parent da958c6f02
commit 15ad5fe9e7
63 changed files with 43634 additions and 0 deletions

Binary file not shown.

View File

@ -0,0 +1,249 @@
/*!
* __ _____ ________ __
* / // _ /__ __ _____ ___ __ _/__ ___/__ ___ ______ __ __ __ ___ / /
* __ / // // // // // _ // _// // / / // _ // _// // // \/ // _ \/ /
* / / // // // // // ___// / / // / / // ___// / / / / // // /\ // // / /__
* \___//____ \\___//____//_/ _\_ / /_//____//_/ /_/ /_//_//_/ /_/ \__\_\___/
* \/ /____/ version 0.10.8
* http://terminal.jcubic.pl
*
* This file is part of jQuery Terminal.
*
* Copyright (c) 2011-2016 Jakub Jankiewicz <http://jcubic.pl>
* Released under the MIT license
*
* Date: Tue, 17 May 2016 09:01:55 +0000
*/
.terminal .terminal-output .format, .cmd .format,
.cmd .prompt, .cmd .prompt div, .terminal .terminal-output div div{
display: inline-block;
}
.terminal h1, .terminal h2, .terminal h3, .terminal h4, .terminal h5, .terminal h6, .terminal pre, .cmd {
margin: 0;
}
.terminal h1, .terminal h2, .terminal h3, .terminal h4, .terminal h5, .terminal h6 {
line-height: 1.2em;
}
/*
.cmd .mask {
width: 10px;
height: 11px;
background: black;
z-index: 100;
}
*/
.cmd .clipboard {
position: absolute;
height: 16px;
left: -6px;
/* this seems to work after all on Android */
/*left: -99999px;
clip: rect(1px,1px,1px,1px);
/* on desktop textarea appear when paste */
/*
opacity: 0.01;
filter: alpha(opacity = 0.01);
filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0.01);
*/
width: 5px; /* textarea need to have width or it will not work on Android */
background: transparent;
border: none;
color: transparent;
outline: none;
padding: 0;
resize: none;
z-index: 0;
overflow: hidden;
}
.terminal .error {
color: #f00;
}
.terminal {
padding: 10px;
position: relative;
/*overflow: hidden;*/
overflow: auto;
}
.cmd {
padding: 0;
height: 1.3em;
position: relative;
/*margin-top: 3px; */
}
.terminal .inverted, .cmd .inverted, .cmd .cursor.blink {
background-color: #aaa;
color: #000;
}
.cmd .cursor.blink {
-webkit-animation: terminal-blink 1s infinite steps(1, start);
-moz-animation: terminal-blink 1s infinite steps(1, start);
-ms-animation: terminal-blink 1s infinite steps(1, start);
animation: terminal-blink 1s infinite steps(1, start);
}
@-webkit-keyframes terminal-blink {
0%, 100% {
background-color: #000;
color: #aaa;
}
50% {
background-color: #bbb;
color: #000;
}
}
@-ms-keyframes terminal-blink {
0%, 100% {
background-color: #000;
color: #aaa;
}
50% {
background-color: #bbb;
color: #000;
}
}
@-moz-keyframes terminal-blink {
0%, 100% {
background-color: #000;
color: #aaa;
}
50% {
background-color: #bbb;
color: #000;
}
}
@keyframes terminal-blink {
0%, 100% {
background-color: #000;
color: #aaa;
}
50% {
background-color: #bbb; /* not #aaa because it's seems there is Google Chrome bug */
color: #000;
}
}
.terminal .terminal-output div div, .cmd .prompt {
display: block;
line-height: 14px;
height: auto;
}
.cmd .prompt {
float: left;
}
.terminal, .cmd {
font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;
color: #aaa;
background-color: #000;
font-size: 14px;
line-height: 16px;
padding-bottom:3px;
}
.terminal-output > div {
/*padding-top: 3px;*/
min-height: 14px;
}
.terminal .terminal-output div span {
display: inline-block;
}
.cmd span {
float: left;
/*display: inline-block; */
}
/* fix double style of selecting text in terminal */
.terminal-output span, .terminal-output a, .cmd div, .cmd span, .terminal td,
.terminal pre, .terminal h1, .terminal h2, .terminal h3, .terminal h4,
.terminal h5, .terminal h6 {
-webkit-touch-callout: initial;
-webkit-user-select: initial;
-khtml-user-select: initial;
-moz-user-select: initial;
-ms-user-select: initial;
user-select: initial;
}
.terminal, .terminal-output, .terminal-output div {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
/* firefox hack */
@-moz-document url-prefix() {
.terminal, .terminal-output, .terminal-output div {
-webkit-touch-callout: initial;
-webkit-user-select: initial;
-khtml-user-select: initial;
-moz-user-select: initial;
-ms-user-select: initial;
user-select: initial;
}
}
.terminal table {
border-collapse: collapse;
}
.terminal td {
border: 1px solid #aaa;
}
.terminal h1::-moz-selection,
.terminal h2::-moz-selection,
.terminal h3::-moz-selection,
.terminal h4::-moz-selection,
.terminal h5::-moz-selection,
.terminal h6::-moz-selection,
.terminal pre::-moz-selection,
.terminal td::-moz-selection,
.terminal .terminal-output div div::-moz-selection,
.terminal .terminal-output div span::-moz-selection,
.terminal .terminal-output div div a::-moz-selection,
.cmd div::-moz-selection,
.cmd > span::-moz-selection,
.cmd .prompt span::-moz-selection {
background-color: #aaa;
color: #000;
}
/* this don't work in Chrome
.terminal tr td::-moz-selection {
border-color: #000;
}
.terminal tr td::selection {
border-color: #000;
}
*/
.terminal h1::selection,
.terminal h2::selection,
.terminal h3::selection,
.terminal h4::selection,
.terminal h5::selection,
.terminal h6::selection,
.terminal pre::selection,
.terminal td::selection,
.terminal .terminal-output div div::selection,
.terminal .terminal-output div div a::selection,
.terminal .terminal-output div span::selection,
.cmd div::selection,
.cmd > span::selection,
.cmd .prompt span::selection {
background-color: #aaa;
color: #000;
}
.terminal .terminal-output div.error, .terminal .terminal-output div.error div {
color: red;
}
.tilda {
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: 1100;
}
.clear {
clear: both;
}
.terminal a {
color: #0F60FF;
}
.terminal a:hover {
color: red;
}

View File

@ -0,0 +1 @@
.terminal .terminal-output .format,.cmd .format,.cmd .prompt,.cmd .prompt div,.terminal .terminal-output div div{display:inline-block}.terminal h1,.terminal h2,.terminal h3,.terminal h4,.terminal h5,.terminal h6,.terminal pre,.cmd{margin:0}.terminal h1,.terminal h2,.terminal h3,.terminal h4,.terminal h5,.terminal h6{line-height:1.2em}.cmd .clipboard{position:absolute;height:16px;left:-6px;width:5px;background:transparent;border:0;color:transparent;outline:0;padding:0;resize:none;z-index:0;overflow:hidden}.terminal .error{color:red}.terminal{padding:10px;position:relative;overflow:auto}.cmd{padding:0;height:1.3em;position:relative}.terminal .inverted,.cmd .inverted,.cmd .cursor.blink{background-color:#aaa;color:#000}.cmd .cursor.blink{-webkit-animation:terminal-blink 1s infinite steps(1,start);-moz-animation:terminal-blink 1s infinite steps(1,start);-ms-animation:terminal-blink 1s infinite steps(1,start);animation:terminal-blink 1s infinite steps(1,start)}@-webkit-keyframes terminal-blink{0,100%{background-color:#000;color:#aaa}50%{background-color:#bbb;color:#000}}@-ms-keyframes terminal-blink{0,100%{background-color:#000;color:#aaa}50%{background-color:#bbb;color:#000}}@-moz-keyframes terminal-blink{0,100%{background-color:#000;color:#aaa}50%{background-color:#bbb;color:#000}}@keyframes terminal-blink{0,100%{background-color:#000;color:#aaa}50%{background-color:#bbb;color:#000}}.terminal .terminal-output div div,.cmd .prompt{display:block;line-height:14px;height:auto}.cmd .prompt{float:left}.terminal,.cmd{font-family:monospace;color:#aaa;background-color:#000;font-size:12px;line-height:14px}.terminal-output>div{min-height:14px}.terminal .terminal-output div span{display:inline-block}.cmd span{float:left}.terminal-output span,.terminal-output a,.cmd div,.cmd span,.terminal td,.terminal pre,.terminal h1,.terminal h2,.terminal h3,.terminal h4,.terminal h5,.terminal h6{-webkit-touch-callout:initial;-webkit-user-select:initial;-khtml-user-select:initial;-moz-user-select:initial;-ms-user-select:initial;user-select:initial}.terminal,.terminal-output,.terminal-output div{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@-moz-document url-prefix(){.terminal,.terminal-output,.terminal-output div{-webkit-touch-callout:initial;-webkit-user-select:initial;-khtml-user-select:initial;-moz-user-select:initial;-ms-user-select:initial;user-select:initial}}.terminal table{border-collapse:collapse}.terminal td{border:1px solid #aaa}.terminal h1::-moz-selection,.terminal h2::-moz-selection,.terminal h3::-moz-selection,.terminal h4::-moz-selection,.terminal h5::-moz-selection,.terminal h6::-moz-selection,.terminal pre::-moz-selection,.terminal td::-moz-selection,.terminal .terminal-output div div::-moz-selection,.terminal .terminal-output div span::-moz-selection,.terminal .terminal-output div div a::-moz-selection,.cmd div::-moz-selection,.cmd>span::-moz-selection,.cmd .prompt span::-moz-selection{background-color:#aaa;color:#000}.terminal h1::selection,.terminal h2::selection,.terminal h3::selection,.terminal h4::selection,.terminal h5::selection,.terminal h6::selection,.terminal pre::selection,.terminal td::selection,.terminal .terminal-output div div::selection,.terminal .terminal-output div div a::selection,.terminal .terminal-output div span::selection,.cmd div::selection,.cmd>span::selection,.cmd .prompt span::selection{background-color:#aaa;color:#000}.terminal .terminal-output div.error,.terminal .terminal-output div.error div{color:red}.tilda{position:fixed;top:0;left:0;width:100%;z-index:1100}.clear{clear:both}.terminal a{color:#0f60ff}.terminal a:hover{color:red}

View File

@ -0,0 +1,113 @@
/**@license
* __ _____ ________ __
* / // _ /__ __ _____ ___ __ _/__ ___/__ ___ ______ __ __ __ ___ / /
* __ / // // // // // _ // _// // / / // _ // _// // // \/ // _ \/ /
* / / // // // // // ___// / / // / / // ___// / / / / // // /\ // // / /__
* \___//____ \\___//____//_/ _\_ / /_//____//_/ /_/ /_//_//_/ /_/ \__\_\___/
* \/ /____/
* http://terminal.jcubic.pl
*
* utility that renders simple ascii table, like the one from mysql cli tool
* it was first created for leash shell https://leash.jcubic.pl
*
* usage:
*
* var arr = [[1,2,3,4,5], ["lorem", "ipsum", "dolor", "sit", "amet"]];
* term.echo(ascii_table(arr));
* // or
* term.echo(ascii_table(arr, true)); // this will render first row as header
*
* Copyright (c) 2018-2019 Jakub Jankiewicz <https://jcubic.pl/me>
* Released under the MIT license
*
*/
/* global define, module, global, wcwidth, require */
(function(factory) {
var root = typeof window !== 'undefined' ? window : global;
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['wcwidth'], function(wcwidth) {
return (root.ascii_table = factory(wcwidth));
});
} else if (typeof module === 'object' && module.exports) {
// Node/CommonJS
module.exports = factory(require('wcwidth'));
} else {
root.ascii_table = factory(root.wcwidth);
}
})(function(wcwidth, undefined) {
var strlen = (function() {
if (typeof wcwidth === 'undefined') {
return function(string) {
return string.length;
};
} else {
return wcwidth;
}
})();
function ascii_table(array, header) {
if (!array.length) {
return '';
}
for (var i = array.length - 1; i >= 0; i--) {
var row = array[i];
var stacks = [];
for (var j = 0; j < row.length; j++) {
var new_lines = row[j].toString().replace(/\r/g).split("\n");
row[j] = new_lines.shift();
stacks.push(new_lines);
}
var stack_lengths = stacks.map(function(column) {
return column.length;
});
var new_rows_count = Math.max.apply(Math, stack_lengths);
for (var k = new_rows_count - 1; k >= 0; k--) {
array.splice(i + 1, 0, stacks.map(function(column) {
return column[k] || "";
}));
}
}
var lengths = array[0].map(function(_, i) {
var col = array.map(function(row) {
if (row[i] != undefined) {
var len = strlen(row[i]);
if (row[i].match(/\t/g)) {
// tab is 4 spaces
len += row[i].match(/\t/g).length*3;
}
return len;
} else {
return 0;
}
});
return Math.max.apply(Math, col);
});
// column padding
array = array.map(function(row) {
return '| ' + row.map(function(item, i) {
var size = strlen(item);
if (item.match(/\t/g)) {
// tab is 4 spaces
size += item.match(/\t/g).length*3;
}
if (size < lengths[i]) {
item += new Array(lengths[i] - size + 1).join(' ');
}
return item;
}).join(' | ') + ' |';
});
array = array.map(function(line) {
return line.replace(/&(?![^;]+;)/g, '&amp;');
});
var sep = '+' + lengths.map(function(length) {
return new Array(length + 3).join('-');
}).join('+') + '+';
if (header) {
return sep + '\n' + array[0] + '\n' + sep + '\n' +
array.slice(1).join('\n') + '\n' + sep;
} else {
return sep + '\n' + array.join('\n') + '\n' + sep;
}
}
return ascii_table;
});

View File

@ -0,0 +1,69 @@
/*!
* Example plugin using JQuery Terminal Emulator
* Copyright (C) 2010-2016 Jakub Jankiewicz <http://jcubic.pl>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* 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
* SOFTWARE.
*
*/
(function($) {
$.extend_if_has = function(desc, source, array) {
for (var i=array.length;i--;) {
if (typeof source[array[i]] != 'undefined') {
desc[array[i]] = source[array[i]];
}
}
return desc;
};
$.fn.dterm = function(interpreter, options) {
var op = $.extend_if_has({}, options,
['greetings', 'prompt', 'onInit',
'onExit', 'clear',
'login', 'name', 'exit']);
op.enabled = false;
var terminal = this.terminal(interpreter, op).css('overflow', 'hidden');
if (!options.title) {
options.title = 'JQuery Terminal Emulator';
}
if (options.logoutOnClose) {
options.close = function(e, ui) {
terminal.logout();
terminal.clear();
};
} else {
options.close = function(e, ui) {
terminal.disable();
};
}
var self = this;
this.dialog($.extend(options, {
resizeStop: function(e, ui) {
var content = self.find('.ui-dialog-content');
terminal.resize(content.width(), content.height());
},
open: function(e, ui) {
terminal.focus();
terminal.resize();
},
show: 'fade',
closeOnEscape: false
}));
self.terminal = terminal;
return self;
};
})(jQuery);

View File

@ -0,0 +1,2 @@
(function(c){function g(a){var b=a||window.event,i=[].slice.call(arguments,1),e=0,h=0,f=0;a=c.event.fix(b);a.type="mousewheel";if(b.wheelDelta)e=b.wheelDelta/120;if(b.detail)e=-b.detail/3;f=e;if(b.axis!==undefined&&b.axis===b.HORIZONTAL_AXIS){f=0;h=-1*e}if(b.wheelDeltaY!==undefined)f=b.wheelDeltaY/120;if(b.wheelDeltaX!==undefined)h=-1*b.wheelDeltaX/120;i.unshift(a,e,h,f);return(c.event.dispatch||c.event.handle).apply(this,i)}var d=["DOMMouseScroll","mousewheel"];if(c.event.fixHooks)for(var j=d.length;j;)c.event.fixHooks[d[--j]]=
c.event.mouseHooks;c.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=d.length;a;)this.addEventListener(d[--a],g,false);else this.onmousewheel=g},teardown:function(){if(this.removeEventListener)for(var a=d.length;a;)this.removeEventListener(d[--a],g,false);else this.onmousewheel=null}};c.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery);

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,317 @@
/**@license
* __ _____ ________ __
* / // _ /__ __ _____ ___ __ _/__ ___/__ ___ ______ __ __ __ ___ / /
* __ / // // // // // _ // _// // / / // _ // _// // // \/ // _ \/ /
* / / // // // // // ___// / / // / / // ___// / / / / // // /\ // // / /__
* \___//____ \\___//____//_/ _\_ / /_//____//_/ /_/ /_//_//_/ /_/ \__\_\___/
* \/ /____/
* http://terminal.jcubic.pl
*
* This is example of how to create custom formatter for jQuery Terminal
*
* Copyright (c) 2014-2016 Jakub Jankiewicz <http://jcubic.pl>
* Released under the MIT license
*
*/
(function($) {
if (!$.terminal) {
throw new Error('$.terminal is not defined');
}
// ---------------------------------------------------------------------
// :: Replace overtyping (from man) formatting with terminal formatting
// ---------------------------------------------------------------------
$.terminal.overtyping = function(string) {
return string.replace(/((?:_\x08.|.\x08_)+)/g, function(full, g) {
var striped = full.replace(/_x08|\x08_|_\u0008|\u0008_/g, '');
return '[[u;;]' + striped + ']';
}).replace(/((?:.\x08.)+)/g, function(full, g) {
return '[[b;#fff;]' + full.replace(/(.)(?:\x08|\u0008)(.)/g,
function(full, g1, g2) {
return g2;
}) + ']';
});
};
// ---------------------------------------------------------------------
// :: Html colors taken from ANSI formatting in Linux Terminal
// ---------------------------------------------------------------------
$.terminal.ansi_colors = {
normal: {
black: '#000',
red: '#A00',
green: '#008400',
yellow: '#A50',
blue: '#00A',
magenta: '#A0A',
cyan: '#0AA',
white: '#AAA'
},
faited: {
black: '#000',
red: '#640000',
green: '#006100',
yellow: '#737300',
blue: '#000087',
magenta: '#650065',
cyan: '#008787',
white: '#818181'
},
bold: {
black: '#000',
red: '#F55',
green: '#44D544',
yellow: '#FF5',
blue: '#55F',
magenta: '#F5F',
cyan: '#5FF',
white: '#FFF'
},
// XTerm 8-bit pallete
palette: [
'#000000', '#AA0000', '#00AA00', '#AA5500', '#0000AA', '#AA00AA',
'#00AAAA', '#AAAAAA', '#555555', '#FF5555', '#55FF55', '#FFFF55',
'#5555FF', '#FF55FF', '#55FFFF', '#FFFFFF', '#000000', '#00005F',
'#000087', '#0000AF', '#0000D7', '#0000FF', '#005F00', '#005F5F',
'#005F87', '#005FAF', '#005FD7', '#005FFF', '#008700', '#00875F',
'#008787', '#0087AF', '#0087D7', '#0087FF', '#00AF00', '#00AF5F',
'#00AF87', '#00AFAF', '#00AFD7', '#00AFFF', '#00D700', '#00D75F',
'#00D787', '#00D7AF', '#00D7D7', '#00D7FF', '#00FF00', '#00FF5F',
'#00FF87', '#00FFAF', '#00FFD7', '#00FFFF', '#5F0000', '#5F005F',
'#5F0087', '#5F00AF', '#5F00D7', '#5F00FF', '#5F5F00', '#5F5F5F',
'#5F5F87', '#5F5FAF', '#5F5FD7', '#5F5FFF', '#5F8700', '#5F875F',
'#5F8787', '#5F87AF', '#5F87D7', '#5F87FF', '#5FAF00', '#5FAF5F',
'#5FAF87', '#5FAFAF', '#5FAFD7', '#5FAFFF', '#5FD700', '#5FD75F',
'#5FD787', '#5FD7AF', '#5FD7D7', '#5FD7FF', '#5FFF00', '#5FFF5F',
'#5FFF87', '#5FFFAF', '#5FFFD7', '#5FFFFF', '#870000', '#87005F',
'#870087', '#8700AF', '#8700D7', '#8700FF', '#875F00', '#875F5F',
'#875F87', '#875FAF', '#875FD7', '#875FFF', '#878700', '#87875F',
'#878787', '#8787AF', '#8787D7', '#8787FF', '#87AF00', '#87AF5F',
'#87AF87', '#87AFAF', '#87AFD7', '#87AFFF', '#87D700', '#87D75F',
'#87D787', '#87D7AF', '#87D7D7', '#87D7FF', '#87FF00', '#87FF5F',
'#87FF87', '#87FFAF', '#87FFD7', '#87FFFF', '#AF0000', '#AF005F',
'#AF0087', '#AF00AF', '#AF00D7', '#AF00FF', '#AF5F00', '#AF5F5F',
'#AF5F87', '#AF5FAF', '#AF5FD7', '#AF5FFF', '#AF8700', '#AF875F',
'#AF8787', '#AF87AF', '#AF87D7', '#AF87FF', '#AFAF00', '#AFAF5F',
'#AFAF87', '#AFAFAF', '#AFAFD7', '#AFAFFF', '#AFD700', '#AFD75F',
'#AFD787', '#AFD7AF', '#AFD7D7', '#AFD7FF', '#AFFF00', '#AFFF5F',
'#AFFF87', '#AFFFAF', '#AFFFD7', '#AFFFFF', '#D70000', '#D7005F',
'#D70087', '#D700AF', '#D700D7', '#D700FF', '#D75F00', '#D75F5F',
'#D75F87', '#D75FAF', '#D75FD7', '#D75FFF', '#D78700', '#D7875F',
'#D78787', '#D787AF', '#D787D7', '#D787FF', '#D7AF00', '#D7AF5F',
'#D7AF87', '#D7AFAF', '#D7AFD7', '#D7AFFF', '#D7D700', '#D7D75F',
'#D7D787', '#D7D7AF', '#D7D7D7', '#D7D7FF', '#D7FF00', '#D7FF5F',
'#D7FF87', '#D7FFAF', '#D7FFD7', '#D7FFFF', '#FF0000', '#FF005F',
'#FF0087', '#FF00AF', '#FF00D7', '#FF00FF', '#FF5F00', '#FF5F5F',
'#FF5F87', '#FF5FAF', '#FF5FD7', '#FF5FFF', '#FF8700', '#FF875F',
'#FF8787', '#FF87AF', '#FF87D7', '#FF87FF', '#FFAF00', '#FFAF5F',
'#FFAF87', '#FFAFAF', '#FFAFD7', '#FFAFFF', '#FFD700', '#FFD75F',
'#FFD787', '#FFD7AF', '#FFD7D7', '#FFD7FF', '#FFFF00', '#FFFF5F',
'#FFFF87', '#FFFFAF', '#FFFFD7', '#FFFFFF', '#080808', '#121212',
'#1C1C1C', '#262626', '#303030', '#3A3A3A', '#444444', '#4E4E4E',
'#585858', '#626262', '#6C6C6C', '#767676', '#808080', '#8A8A8A',
'#949494', '#9E9E9E', '#A8A8A8', '#B2B2B2', '#BCBCBC', '#C6C6C6',
'#D0D0D0', '#DADADA', '#E4E4E4', '#EEEEEE'
]
};
// ---------------------------------------------------------------------
// :: Replace ANSI formatting with terminal formatting
// ---------------------------------------------------------------------
$.terminal.from_ansi = (function() {
var color_list = {
30: 'black',
31: 'red',
32: 'green',
33: 'yellow',
34: 'blue',
35: 'magenta',
36: 'cyan',
37: 'white',
39: 'inherit' // default color
};
var background_list = {
40: 'black',
41: 'red',
42: 'green',
43: 'yellow',
44: 'blue',
45: 'magenta',
46: 'cyan',
47: 'white',
49: 'transparent' // default background
};
function format_ansi(code) {
var controls = code.split(';');
var num;
var faited = false;
var reverse = false;
var bold = false;
var styles = [];
var output_color = '';
var output_background = '';
var _8bit_color = false;
var _8bit_background = false;
var process_8bit = false;
var palette = $.terminal.ansi_colors.palette;
for(var i in controls) {
if (controls.hasOwnProperty(i)) {
num = parseInt(controls[i], 10);
if (process_8bit && (_8bit_background || _8bit_color)) {
if (_8bit_color && palette[num]) {
output_color = palette[num];
}
if (_8bit_background && palette[num]) {
output_background = palette[num];
}
} else {
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];
}
}
}
}
}
}
if (reverse) {
if (output_color || output_background) {
var tmp = output_background;
output_background = output_color;
output_color = tmp;
} else {
output_color = 'black';
output_background = 'white';
}
}
var colors, color, background, backgrounds;
if (bold) {
colors = backgrounds = $.terminal.ansi_colors.bold;
} else if (faited) {
colors = backgrounds = $.terminal.ansi_colors.faited;
} else {
colors = backgrounds = $.terminal.ansi_colors.normal;
}
if (_8bit_color) {
color = output_color;
} else if (output_color == 'inherit') {
color = output_color;
} else {
color = colors[output_color];
}
if (_8bit_background) {
background = output_background;
} else if (output_background == 'transparent') {
background = output_background;
} else {
background = backgrounds[output_background];
}
return [styles.join(''), color, background];
}
return function(input) {
//merge multiple codes
/*input = input.replace(/((?:\x1B\[[0-9;]*[A-Za-z])*)/g, function(group) {
return group.replace(/m\x1B\[/g, ';');
});*/
var splitted = input.split(/(\x1B\[[0-9;]*[A-Za-z])/g);
if (splitted.length == 1) {
return input;
}
var output = [];
//skip closing at the begining
if (splitted.length > 3) {
var str = splitted.slice(0,3).join('');
if (str == '[0m' || str == '[m') {
splitted = splitted.slice(3);
}
}
var next, prev_color, prev_background, code, match;
var inside = false;
for (var i=0; i<splitted.length; ++i) {
match = splitted[i].match(/^\x1B\[([0-9;]*)([A-Za-z])$/);
if (match) {
switch (match[2]) {
case 'm':
if (match[1] !== '0') {
code = format_ansi(match[1]);
}
if (inside) {
output.push(']');
if (match[1] === '0' || match[1] === '') {
//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;
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];
}
}
}
break;
}
} else {
output.push(splitted[i]);
}
}
if (inside) {
output.push(']');
}
return output.join(''); //.replace(/\[\[[^\]]+\]\]/g, '');
};
})();
$.terminal.defaults.formatters.push($.terminal.overtyping);
$.terminal.defaults.formatters.push($.terminal.from_ansi);
})(jQuery);

View File

@ -0,0 +1,48 @@
/**@license
* __ _____ ________ __
* / // _ /__ __ _____ ___ __ _/__ ___/__ ___ ______ __ __ __ ___ / /
* __ / // // // // // _ // _// // / / // _ // _// // // \/ // _ \/ /
* / / // // // // // ___// / / // / / // ___// / / / / // // /\ // // / /__
* \___//____ \\___//____//_/ _\_ / /_//____//_/ /_/ /_//_//_/ /_/ \__\_\___/
* \/ /____/
* http://terminal.jcubic.pl
*
* This is example of how to create custom formatter for jQuery Terminal
*
* Copyright (c) 2014-2016 Jakub Jankiewicz <http://jcubic.pl>
* Released under the MIT license
*
*/
(function($) {
if (!$.terminal) {
throw new Error('$.terminal is not defined');
}
// this formatter allow to echo xml where tags are colors like:
// <red>hello <navy>blue</navy> world</red>
$.terminal.defaults.formatters.push(function(string) {
var stack = [];
var output = [];
var parts = string.split(/(<\/?[a-zA-Z]+>)/);
for (var i=0; i<parts.length; ++i) {
if (parts[i][0] == '<') {
if (parts[i][1] == '/') {
if (stack.length) {
stack.pop();
}
} else {
stack.push(parts[i].replace(/^<|>$/g, ''));
}
} else {
if (stack.length) {
// top of the stack
output.push('[[;' + stack[stack.length-1] + ';]');
}
output.push(parts[i]);
if (stack.length) {
output.push(']');
}
}
}
return output.join('');
});
})(jQuery);

View File

@ -0,0 +1,688 @@
if (typeof window === 'undefined') {
var node = true;
var jsdom = require("jsdom");
global.document = jsdom.jsdom();
global.window = global.document.parentWindow;
var navigator = {userAgent: "node-js", platform: "Linux i686"};
global.window.navigator = global.navigator = navigator;
global.jQuery = global.$ = require("jquery");
require('../js/jquery.terminal-src');
require('../js/unix_formatting');
}
describe('Terminal utils', function() {
var command = 'test "foo bar" baz /^asd [x]/ str\\ str 10 1e10';
var args = '"foo bar" baz /^asd [x]/ str\\ str 10 1e10';
describe('$.terminal.split_arguments', function() {
it('should create array of arguments', function() {
expect($.terminal.split_arguments(args)).toEqual([
'foo bar',
'baz',
'/^asd [x]/',
'str str',
'10',
'1e10'
]);
});
});
describe('$.terminal.parse_arguments', function() {
it('should create array of arguments and convert types', function() {
expect($.terminal.parse_arguments(args)).toEqual([
'foo bar',
'baz',
/^asd [x]/,
'str str',
10,
1e10
]);
});
});
describe('$.terminal.split_command', function() {
it('Should split command', function() {
var cmd = jQuery.terminal.split_command(command);
expect(cmd).toEqual({
command: command,
name: 'test',
args: [
'foo bar',
'baz',
'/^asd [x]/',
'str str',
'10',
'1e10'
],
rest: '"foo bar" baz /^asd [x]/ str\\ str 10 1e10'
});
});
});
describe('$.terminal.parse_command', function() {
it('should split and parse command', function() {
var cmd = jQuery.terminal.parse_command(command);
expect(cmd).toEqual({
command: command,
name: 'test',
args: [
'foo bar',
'baz',
/^asd [x]/,
'str str',
10,
1e10
],
rest: '"foo bar" baz /^asd [x]/ str\\ str 10 1e10'
});
});
});
var ansi_string = '\x1b[2;31;46mFoo\x1b[1;3;4;32;45mBar\x1b[0m\x1b[7mBaz';
describe('$.terminal.from_ansi', function() {
it('should convert ansi to terminal formatting', function() {
var string = $.terminal.from_ansi(ansi_string);
expect(string).toEqual('[[;#640000;#008787]Foo][[biu;#44D544;#F5F]'+
'Bar][[;#000;#AAA]Baz]');
});
});
describe('$.terminal.overtyping', function() {
var string = 'HELLO TERMINAL'.replace(/./g, function(chr) {
return chr == ' ' ? chr : chr + '\x08' + chr;
});
var result = '[[b;#fff;]HELLO] [[b;#fff;]TERMINAL]';
it('should convert to terminal formatting', function() {
expect($.terminal.overtyping(string)).toEqual(result);
});
});
describe('$.terminal.escape_brackets', function() {
var string = '[[jQuery]] [[Terminal]]';
var result = '&#91;&#91;jQuery&#93;&#93; &#91;&#91;Terminal&#93;&#93;';
it('should replace [ and ] with html entities', function() {
expect($.terminal.escape_brackets(string)).toEqual(result);
});
});
describe('$.terminal.encode', function() {
var tags = '<hello> </hello>\t<world> </world>';
var tags_result = '&lt;hello&gt;&nbsp;&lt;/hello&gt;&nbsp;&nbsp;&nbsp;'+
'&nbsp;&lt;world&gt;&nbsp;&lt;/world&gt;';
it('should convert < > space and tabs', function() {
expect($.terminal.encode(tags)).toEqual(tags_result);
});
var entites = '& & &amp; &64; &#61; &#91';
//'&amp;&nbsp;&amp;&nbsp;&amp;&nbsp;&amp;64;&nbsp;&#61;&nbsp;&#91'
var ent_result = '&amp;&nbsp;&amp;&nbsp;&amp;&nbsp;&amp;64;&nbsp;&#61;'+
'&nbsp;&amp;#91';
it('it should convert & but not when used with entities', function() {
expect($.terminal.encode(entites)).toEqual(ent_result);
});
});
describe('$.terminal.format_split', function() {
});
describe('$.terminal.is_formatting', function() {
it('should detect terminal formatting', function() {
var formattings = [
'[[;;]Te[xt]',
'[[;;]Te\\]xt]',
'[[;;]]',
'[[gui;;;class]Text]',
'[[b;#fff;]Text]',
'[[b;red;blue]Text]'];
var not_formattings = [
'[[;;]Text[',
'[[Text]]',
'[[Text[[',
'[[;]Text]',
'Text]',
'[[Text',
'[;;]Text]'];
formattings.forEach(function(formatting) {
expect($.terminal.is_formatting(formatting)).toEqual(true);
});
not_formattings.forEach(function(formatting) {
expect($.terminal.is_formatting(formatting)).toEqual(false);
});
});
});
describe('$.terminal.escape_regex', function() {
it('should escape regex special characters', function() {
var safe = "\\\\\\^\\*\\+\\?\\.\\$\\[\\]\\{\\}\\(\\)";
expect($.terminal.escape_regex('\\^*+?.$[]{}()')).toEqual(safe);
});
});
describe('$.terminal.have_formatting', function() {
var formattings = [
'some text [[;;]Te[xt] and formatting',
'some text [[;;]Te\\]xt] and formatting',
'some text [[;;]] and formatting',
'some text [[gui;;;class]Text] and formatting',
'some text [[b;#fff;]Text] and formatting',
'some text [[b;red;blue]Text] and formatting'];
var not_formattings = [
'some text [[;;]Text[ and formatting',
'some text [[Text]] and formatting',
'some text [[Text[[ and formatting',
'some text [[;]Text] and formatting',
'some text Text] and formatting',
'some text [[Text and formatting',
'some text [;;]Text] and formatting'];
it('should detect terminal formatting', function() {
formattings.forEach(function(formatting) {
expect($.terminal.have_formatting(formatting)).toEqual(true);
});
not_formattings.forEach(function(formatting) {
expect($.terminal.have_formatting(formatting)).toEqual(false);
});
});
});
describe('$.terminal.valid_color', function() {
it('should mark hex color as valid', function() {
var valid_colors = ['#fff', '#fab', '#ffaacc', 'red', 'blue'];
valid_colors.forEach(function(color) {
expect($.terminal.valid_color(color)).toBe(true);
});
});
});
describe('$.terminal.format', function() {
var format = '[[biugs;#fff;#000]Foo][[i;;;foo]Bar][[ous;;]Baz]';
it('should create html span tags with style and classes', function() {
var string = $.terminal.format(format);
expect(string).toEqual('<span style="font-weight:bold;text-decorat'+
'ion:underline line-through;font-style:ital'+
'ic;color:#fff;text-shadow:0 0 5px #fff;bac'+
'kground-color:#000" data-text="Foo">Foo</s'+
'pan><span style="font-style:italic;" class'+
'="foo" data-text="Bar">Bar</span><span sty'+
'le="text-decoration:underline line-through'+
' overline;" data-text="Baz">Baz</span>');
});
});
describe('$.terminal.strip', function() {
var formatting = '-_-[[biugs;#fff;#000]Foo]-_-[[i;;;foo]Bar]-_-[[ous;;'+
']Baz]-_-';
var result = '-_-Foo-_-Bar-_-Baz-_-';
it('should remove formatting', function() {
expect($.terminal.strip(formatting)).toEqual(result);
});
});
describe('$.terminal.split_equal', function() {
var text = ['[[bui;#fff;]Lorem ipsum dolor sit amet, consectetur adipi',
'scing elit. Nulla sed dolor nisl, in suscipit justo. Donec a enim',
' et est porttitor semper at vitae augue. Proin at nulla at dui ma',
'ttis mattis. Nam a volutpat ante. Aliquam consequat dui eu sem co',
'nvallis ullamcorper. Nulla suscipit, massa vitae suscipit ornare,',
' tellus] est [[b;;#f00]consequat nunc, quis blandit elit odio eu ',
'arcu. Nam a urna nec nisl varius sodales. Mauris iaculis tincidun',
't orci id commodo. Aliquam] non magna quis [[i;;]tortor malesuada',
' aliquam] eget ut lacus. Nam ut vestibulum est. Praesent volutpat',
' tellus in eros dapibus elementum. Nam laoreet risus non nulla mo',
'llis ac luctus [[ub;#fff;]felis dapibus. Pellentesque mattis elem',
'entum augue non sollicitudin. Nullam lobortis fermentum elit ac m',
'ollis. Nam ac varius risus. Cras faucibus euismod nulla, ac aucto',
'r diam rutrum sit amet. Nulla vel odio erat], ac mattis enim.'
].join('');
it('should split text that into equal length chunks', function() {
var cols = [10, 40, 60, 400];
for (var i=cols.length; i--;) {
var lines = $.terminal.split_equal(text, cols[i]);
var success = true;
for (var j=0; j<lines.length; ++j) {
if ($.terminal.strip(lines[j]).length > cols[i]) {
success = false;
break;
}
}
expect(success).toEqual(true);
}
});
});
});
function support_animations() {
var animation = false,
animationstring = 'animation',
keyframeprefix = '',
domPrefixes = 'Webkit Moz O ms Khtml'.split(' '),
pfx = '',
elm = document.createElement('div');
if (elm.style.animationName) { animation = true; }
if (animation === false) {
for (var i = 0; i < domPrefixes.length; i++) {
var name = domPrefixes[i] + 'AnimationName';
if (elm.style[ name ] !== undefined) {
pfx = domPrefixes[i];
animationstring = pfx + 'Animation';
keyframeprefix = '-' + pfx.toLowerCase() + '-';
animation = true;
break;
}
}
}
return animation;
}
function enter_text(text) {
var e;
var $root = $(document.documentElement || window);
for (var i=0; i<text.length; ++i) {
e = $.Event("keypress");
e.which = e.keyCode = text.charCodeAt(i);
e.ctrlKey = false;
e.altKey = false;
$root.trigger(e);
}
}
function shortcut(ctrl, alt, shift, which) {
var e = $.Event("keydown");
e.ctrlKey = ctrl;
e.altKey = alt;
e.shiftKey = shift;
e.which = e.keyCode = which;
$(document.documentElement || window).trigger(e);
}
function enter_key() {
shortcut(false, false, false, 13);
}
function tests_on_ready() {
describe('Terminal plugin', function() {
describe('terminal create / terminal destroy', function() {
var term = $('<div></div>').appendTo('body').terminal();
it('should create terminal', function() {
expect(term.length).toBe(1);
});
it('should have proper elements', function() {
expect(term.hasClass('terminal')).toBe(true);
expect(term.find('.terminal-output').length).toBe(1);
expect(term.find('.cmd').length).toBe(1);
var prompt = term.find('.prompt');
expect(prompt.length).toBe(1);
expect(prompt.is('span')).toBe(true);
expect(prompt.children().length).toBe(1);
var cursor = term.find('.cursor');
expect(cursor.length).toBe(1);
expect(cursor.is('span')).toBe(true);
expect(cursor.prev().is('span')).toBe(true);
expect(cursor.next().is('span')).toBe(true);
term.focus(true);
if (support_animations()) {
expect(cursor.hasClass('blink')).toBe(true);
}
expect(term.find('.clipboard').length).toBe(1);
});
it('should have signature', function() {
var sig = term.find('.terminal-output div div').map(function() { return $(this).text(); }).get().join('\n');
expect(term.signature().replace(/ /g, '\xA0')).toEqual(sig);
});
it('should have default prompt', function() {
var prompt = term.find('.prompt');
expect(prompt.html()).toEqual("<span>&gt;&nbsp;</span>");
expect(prompt.text()).toEqual('>\xA0');
});
it('should destroy terminal', function() {
term.destroy();
expect(term.children().length).toBe(0);
term.remove();
});
});
describe('exec', function() {
var interpreter = {
foo: function() {
}
};
var term = $('<div></div>').appendTo('body').terminal(interpreter);
it('should execute function', function() {
var spy = spyOn(interpreter, 'foo');
if (spy.andCallThrough) {
spy.andCallThrough();
} else {
spy.and.callThrough();
}
term.exec('foo').then(function() {
expect(interpreter.foo).toHaveBeenCalled();
term.destroy().remove();
});
});
});
describe('enter text', function() {
var interpreter = {
foo: function() {
}
};
var term = $('<div></div>').appendTo('body').terminal(interpreter);
it('text should appear and interpreter function should be called', function() {
term.focus(true);
var spy = spyOn(interpreter, 'foo');
if (spy.andCallThrough) {
spy.andCallThrough();
} else {
spy.and.callThrough();
}
enter_text('foo');
enter_key();
expect(interpreter.foo).toHaveBeenCalled();
var last_div = term.find('.terminal-output > div:last-child');
expect(last_div.hasClass('command')).toBe(true);
expect(last_div.children().html()).toEqual('<span>&gt;&nbsp;foo</span>');
term.destroy().remove();
});
});
describe('prompt', function() {
var term = $('<div></div>').appendTo('body').terminal($.noop, {
prompt: '>>> '
});
it('should return prompt', function() {
expect(term.get_prompt()).toEqual('>>> ');
expect(term.find('.prompt').html()).toEqual('<span>&gt;&gt;&gt;&nbsp;</span>');
});
it('should set prompt', function() {
term.set_prompt('||| ');
expect(term.get_prompt()).toEqual('||| ');
expect(term.find('.prompt').html()).toEqual('<span>|||&nbsp;</span>');
function prompt(callback) {
callback('>>> ');
}
term.set_prompt(prompt);
expect(term.get_prompt()).toEqual(prompt);
expect(term.find('.prompt').html()).toEqual('<span>&gt;&gt;&gt;&nbsp;</span>');
});
it('should format prompt', function() {
var prompt = '<span style="font-weight:bold;text-decoration:underline;color:#fff;" data-text=">>>">&gt;&gt;&gt;</span><span>&nbsp;</span>';
term.set_prompt('[[ub;#fff;]>>>] ');
expect(term.find('.prompt').html()).toEqual(prompt);
term.set_prompt(function(callback) {
callback('[[ub;#fff;]>>>] ');
});
expect(term.find('.prompt').html()).toEqual(prompt);
term.destroy().remove();
});
});
describe('cmd plugin', function() {
var term = $('<div></div>').appendTo('body').css('overflow-y', 'scroll').terminal($.noop, {
name: 'cmd',
numChars: 150,
numRows: 20
});
var string = '';
for (var i=term.cols(); i--;) {
term.insert('M');
}
var cmd = term.cmd();
var line = cmd.find('.prompt').next();
it('text should have 2 lines', function() {
expect(line.is('div')).toBe(true);
expect(line.text().length).toBe(term.cols()-2);
});
it('cmd plugin moving cursor', function() {
cmd.position(-8, true);
var before = cmd.find('.prompt').next();
var cursor = cmd.find('.cursor');
var after = cursor.next();
expect(before.is('span')).toBe(true);
expect(before.text().length).toBe(term.cols()-8);
expect(after.next().text().length).toBe(2);
expect(after.text().length).toBe(5);
expect(cursor.text()).toBe('M');
});
it('should remove characters', function() {
cmd['delete'](-10);
var before = cmd.find('.prompt').next();
var cursor = cmd.find('.cursor');
var after = cursor.next();
expect(before.text().length).toEqual(term.cols()-8-10);
cmd['delete'](8);
expect(cursor.text()).toEqual('\xA0');
expect(after.text().length).toEqual(0);
});
var history = cmd.history()
it('should have one entry in history', function() {
cmd.purge();
term.set_command('something').focus(true);
enter_key();
expect(history.data()).toEqual(['something']);
});
it('should not add item to history if history is disabled', function() {
history.disable();
term.set_command('something else');
enter_key();
expect(history.data()).toEqual(['something']);
});
it('should remove commands from history', function() {
var spy = spyOn(history, 'purge');
if (spy.andCallThrough) {
spy.andCallThrough();
} else {
spy.and.callThrough();
}
cmd.purge();
expect(history.purge).toHaveBeenCalled();
expect(history.data()).toEqual([]);
});
it('should have name', function() {
expect(cmd.name()).toEqual('cmd_4');
});
it('should return command', function() {
cmd.set('foo');
expect(cmd.get()).toEqual('foo');
});
it('should not move position', function() {
var pos = cmd.position();
cmd.insert('bar', true);
expect(cmd.position()).toEqual(pos);
});
it('should return $.noop for commands', function() {
expect($.terminal.active().commands()).toEqual($.noop);
});
it('should set position', function() {
cmd.position(0);
expect(cmd.position()).toEqual(0);
});
it('should set and remove mask', function() {
cmd.mask('•');
cmd.position(6);
var before = cmd.find('.prompt').next();
expect(before.text()).toEqual('••••••');
expect(cmd.get()).toEqual('foobar');
cmd.mask(false);
expect(before.text()).toEqual('foobar');
});
it('should execute functions on shortcuts', function() {
var spy;
spy = spyOn(cmd, 'position');
if (spy.andCallThrough) {
spy.andCallThrough();
} else {
spy.and.callThrough();
}
shortcut(true, false, false, 65); // CTRL+A
expect(cmd.position).toHaveBeenCalled();
spy = spyOn(cmd, 'delete');
if (spy.andCallThrough) {
spy.andCallThrough();
} else {
spy.and.callThrough();
}
shortcut(true, false, false, 75); // CTRL+K
expect(cmd['delete']).toHaveBeenCalled();
spy = spyOn(cmd, 'insert');
if (spy.andCallThrough) {
spy.andCallThrough();
} else {
spy.and.callThrough();
}
shortcut(true, false, false, 89); // CTRL+Y
expect(cmd.insert).toHaveBeenCalled();
shortcut(true, false, false, 85); // CTRL+U
expect(cmd.kill_text()).toEqual('foobar');
shortcut(true, false, true, 13);
expect(cmd.find('.prompt').next().text()).toEqual('\xA0');
expect(cmd.get()).toEqual('\n');
cmd.set('');
shortcut(false, false, false, 9); // TAB
expect(cmd.get()).toEqual('\t');
history.enable();
cmd.set('foo bar');
enter_key();
shortcut(false, false, false, 38); // UP ARROW
expect(cmd.get()).toEqual('foo bar');
shortcut(false, false, false, 40); // DOWN ARROW
expect(cmd.get()).toEqual('');
cmd.insert('hello');
shortcut(false, false, false, 38);
shortcut(false, false, false, 40);
expect(cmd.get()).toEqual('hello');
shortcut(true, false, false, 80); // CTRL+P
expect(cmd.get()).toEqual('foo bar');
shortcut(true, false, false, 78); // CTRL+N
expect(cmd.get()).toEqual('hello');
cmd.set('foo bar baz');
shortcut(false, false, false, 37); // LEFT ARROW
expect(cmd.position()).toEqual(10);
shortcut(true, false, false, 37); // moving by words
expect(cmd.position()).toEqual(8);
shortcut(true, false, false, 37);
expect(cmd.position()).toEqual(4);
shortcut(true, false, false, 37);
expect(cmd.position()).toEqual(0);
shortcut(false, false, false, 39); // RIGHT ARROW
expect(cmd.position()).toEqual(1);
shortcut(true, false, false, 39);
expect(cmd.position()).toEqual(3);
shortcut(true, false, false, 39);
expect(cmd.position()).toEqual(7);
shortcut(true, false, false, 39);
expect(cmd.position()).toEqual(11);
shortcut(false, false, false, 36); // HOME
expect(cmd.position()).toEqual(0);
shortcut(false, false, false, 35); // END
expect(cmd.position()).toEqual(cmd.get().length);
shortcut(true, false, false, 82); // CTRL+R
expect(cmd.prompt()).toEqual("(reverse-i-search)`': ");
enter_text('foo');
expect(cmd.get()).toEqual('foo bar');
shortcut(true, false, false, 71); // CTRL+G
expect(cmd.get()).toEqual('foo bar baz');
cmd.purge();
term.destroy();
});
});
function JSONRPCMock(url, object) {
var ajax = $.ajax;
var system = {
'sdversion': '1.0',
'name': 'DemoService',
'address': url,
// md5('JSONRPCMock')
'id': 'urn:md5:e1a975ac782ce4ed0a504ceb909abf44',
'procs': []
};
for (var key in object) {
var proc = {
name: key
};
if ($.isFunction(object[key])) {
var re = /function[^\(]+\(([^\)]+)\)/;
var m = object[key].toString().match(re);
if (m) {
proc.params = m[1].split(/\s*,\s*/);
}
}
system.procs.push(proc);
}
$.ajax = function(obj) {
if (obj.url == url) {
var defer = $.Deferred();
try {
var req = JSON.parse(obj.data);
var resp;
if (req.method == 'system.describe') {
resp = system;
} else {
var error = null;
var ret = null
try {
ret = object[req.method].apply(null, req.params);
} catch (e) {
error = {message: e.message};
}
resp = {
id: req.id,
jsonrpc: '1.1',
result: ret,
error: error
};
}
resp = JSON.stringify(resp);
if ($.isFunction(obj.success)) {
obj.success(resp, 'OK', {
getResponseHeader: function(header) {
if (header == 'Content-Type') {
return 'application/json';
}
}
});
}
defer.resolve(resp);
} catch (e) {
throw new Error(e.message);
}
return defer.promise();
} else {
return ajax.apply($, arguments);
}
}
}
var object = {
echo: function(token, str) {
return str;
},
login: function(user, password) {
if (user == 'demo' && password == 'demo') {
return 'TOKEN';
} else {
return null;
}
}
};
JSONRPCMock('/test', object);
describe('JSON-RPC', function() {
var term = $('<div></div>').appendTo('body').terminal('/test', {
login: true
});
it('should call login', function() {
term.focus();
var spy = spyOn(object, 'login');
if (spy.andCallThrough) {
spy.andCallThrough();
} else {
spy.and.callThrough();
}
term.insert('test');
enter_key();
term.insert('test');
enter_key();
var last_div = term.find('.terminal-output > div:last-child');
expect(last_div.text()).toEqual('Wrong password try again!');
expect(object.login).toHaveBeenCalledWith('test', 'test');
term.insert('demo');
enter_key();
term.insert('demo');
enter_key();
expect(object.login).toHaveBeenCalledWith('demo', 'demo');
});
it('should call a function', function() {
term.focus();
var spy = spyOn(object, 'echo');
if (spy.andCallThrough) {
spy.andCallThrough();
} else {
spy.and.callThrough();
}
term.insert('echo hello');
enter_key();
expect(object.echo).toHaveBeenCalledWith('TOKEN', 'hello');
});
});
});
}
if (node) {
tests_on_ready();
} else {
$(tests_on_ready);
}