├── .github ├── PULL_REQUEST_TEMPLATE ├── ISSUE_TEMPLATE │ ├── feature.md │ ├── question.md │ └── bug.md └── FUNDING.yml ├── files ├── tsconfig.json ├── .gitignore ├── templates ├── npmrc.tmpl ├── bower.in ├── import.in ├── package.git ├── Makefile.in ├── package.in └── README.in ├── scripts ├── options ├── update-contributors-readme ├── version ├── cssnano.js ├── mkemoji ├── update-contributors-package.js ├── methods.js └── contributors.js ├── .gitattributes ├── .travis.yml ├── .npmignore ├── bower.json ├── import.html ├── manifest ├── terminal.jquery.json ├── js ├── jquery.mousewheel-min.js ├── terminal.widget.js ├── terminal.widget.in ├── xml_formatting.js ├── dterm.js ├── ascii_table.js ├── emoji.js ├── echo_newline.js ├── autocomplete_menu.js ├── prism.js └── pipe.js ├── examples ├── dialog.html ├── mysql-rpc-demo.php ├── rpc-demo.html ├── json-rpc-service-demo.php ├── dialog.css ├── tilda-demo.html ├── multiple-interpreters-demo.html ├── json-rpc.php └── dialog.js ├── LICENSE ├── CONTRIBUTING.md ├── Makefile ├── package.json └── css ├── jquery.terminal-2.0.0.min.css ├── jquery.terminal.min.css └── jquery.terminal-2.8.0.min.css /.github/PULL_REQUEST_TEMPLATE: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature 3 | about: Feature request or proposal 4 | --- 5 | 6 | ### I have idea for a new feature for jQuery Terminal 7 | 8 | 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: Question about the library 4 | --- 5 | 6 | ### I have question related to jQuery Terminal 7 | 8 | 9 | -------------------------------------------------------------------------------- /files: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | find . -type f -not -path './node_modules*' -a -not -path '*.git*' -a -not -path './coverage*' -a -not -path './bower_components*' | while read file; do 4 | git check-ignore -q "$file" || echo "$file" 5 | done -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "commonjs", 5 | "strict": true, 6 | "lib": ["es2015", "ES2018.Promise", "dom"] 7 | }, 8 | "exclude": ["npm"] 9 | } 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .[0-9/]* 3 | components 4 | \#*\# 5 | .\#* 6 | www 7 | test 8 | bower_components 9 | node_modules 10 | coverage 11 | reports 12 | .github.token 13 | .npmrc 14 | tmp 15 | npm 16 | contributors.json 17 | contributors-www.json -------------------------------------------------------------------------------- /templates/npmrc.tmpl: -------------------------------------------------------------------------------- 1 | //npm.pkg.github.com/:_authToken={{TOKEN}} 2 | 3 | @jcubic:registry=https://npm.pkg.github.com/ 4 | 5 | init.author.name=Jakub T. Jankiewicz 6 | init.author.email=jcubic@onet.pl 7 | init.author.url=https://jcubic.pl/jakub-jankiewicz/ -------------------------------------------------------------------------------- /scripts/options: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # print missing options in documentation 3 | grep -oE 'settings\.[^;, ().?:]+' js/jquery.terminal-src.js | sort | uniq | while read setting; do grep `echo $setting | sed -e 's/settings.//'` ../www/api_reference.php.in > /dev/null || echo $setting; done 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | .* text eol=lf 3 | js/jquery.terminal-[0-9.]* binary 4 | js/jquery.terminal.min.js binary 5 | js/jquery.terminal.js binary 6 | css/jquery.terminal-[0-9.]* binary 7 | css/jquery.terminal.min.css binary 8 | css/jquery.terminal.css binary 9 | css/*map binary 10 | js/*map binary 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 10.15.0 4 | install: 5 | - npm ci 6 | script: 7 | - make 8 | - make lint 9 | - make tscheck || travis_terminate 1 10 | - make skipped_tests || travis_terminate 1 11 | - make test || travis_terminate 1 12 | after_script: 13 | - make coveralls 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Found bug in the library 4 | --- 5 | 6 | ### Expected behavior 7 | 8 | ### Actual behavior 9 | 10 | ### Steps to reproduce 11 | 12 | ### Browser and OS 13 | 14 | 20 | -------------------------------------------------------------------------------- /scripts/update-contributors-readme: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | input=$1 4 | marker=$2 5 | file=$3 6 | 7 | CONTRIBUTORS=`./scripts/contributors.js -f $input -m | tr '\n' '☺'` 8 | if echo "$CONTRIBUTORS" | grep ERROR > /dev/null; then 9 | echo "$CONTRIBUTORS" | tr '☺' '\n' 10 | else 11 | cat $file | sed -n "/${marker}-START/{p;:a;N;/${marker}-END/!ba;s%.*\n%${CONTRIBUTORS}%};p" | tr '☺' '\n' > README.tmp 12 | cp README.tmp $file 13 | rm README.tmp 14 | fi -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | custom: https://www.paypal.me/jcubic 10 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .* 2 | *~ 3 | \#* 4 | .\#* 5 | tmp 6 | scripts 7 | tsconfig.json 8 | www 9 | bower.* 10 | package.in 11 | test.ts 12 | Makefile* 13 | manifest 14 | README.in 15 | terminal.jquery.json 16 | SpecRunner.html 17 | __tests__ 18 | reports 19 | node_modules 20 | bower_components 21 | coverage 22 | examples 23 | bin 24 | css/jquery.terminal-*.css 25 | js/jquery.terminal-*.js 26 | js/jquery-1.7.1.min.js 27 | js/terminal.widget.in 28 | version 29 | CONTRIBUTING.md 30 | methods 31 | options 32 | files 33 | templates 34 | mkemoji 35 | -------------------------------------------------------------------------------- /scripts/version: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Display current version or update version if used with version as argument 4 | 5 | cd `git rev-parse --show-toplevel` 6 | 7 | VERSION=`grep VERSION= Makefile | sed -e 's/VERSION=\(.*\)/\1/'` 8 | if [ -z "$1" ]; then 9 | echo $VERSION 10 | elif [ "$1" != "$VERSION" ]; then 11 | sed -e "s/{{VERSION}}/"$1"/" templates/Makefile.in > Makefile 12 | git mv css/jquery.terminal-${VERSION}.css css/jquery.terminal-${1}.css 13 | git mv css/jquery.terminal-${VERSION}.min.css css/jquery.terminal-${1}.min.css 14 | git mv js/jquery.terminal-${VERSION}.js js/jquery.terminal-${1}.js 15 | git mv js/jquery.terminal-${VERSION}.min.js js/jquery.terminal-${1}.min.js 16 | rm .${VERSION} 17 | fi 18 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery.terminal", 3 | "version": "2.8.0", 4 | "main": [ 5 | "js/jquery.terminal.min.js", 6 | "js/jquery.mousewheel-min.js", 7 | "css/jquery.terminal.min.css" 8 | ], 9 | "description": "jQuery Terminal Emulator is a plugin for creating command line interpreters in your applications.", 10 | "license": "MIT", 11 | "ignore": [ 12 | "examples", 13 | "README.in", 14 | "bower.in", 15 | "Makefile", 16 | "manifest", 17 | ".gitignore", 18 | ".npmignore", 19 | "package.in", 20 | "package.json", 21 | "bin", 22 | "version" 23 | ], 24 | "dependencies": { 25 | "jquery": "~3" 26 | }, 27 | "devDependencies": { 28 | "keyboardevent-key-polyfill": "^1.0.2" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /templates/bower.in: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery.terminal", 3 | "version": "{{VER}}", 4 | "main": [ 5 | "js/jquery.terminal.min.js", 6 | "js/jquery.mousewheel-min.js", 7 | "css/jquery.terminal.min.css" 8 | ], 9 | "description": "jQuery Terminal Emulator is a plugin for creating command line interpreters in your applications.", 10 | "license": "MIT", 11 | "ignore": [ 12 | "examples", 13 | "README.in", 14 | "bower.in", 15 | "Makefile", 16 | "manifest", 17 | ".gitignore", 18 | ".npmignore", 19 | "package.in", 20 | "package.json", 21 | "bin", 22 | "version" 23 | ], 24 | "dependencies": { 25 | "jquery": "~3" 26 | }, 27 | "devDependencies": { 28 | "keyboardevent-key-polyfill": "^1.0.2" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /import.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | 26 | 27 | -------------------------------------------------------------------------------- /templates/import.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | 26 | 27 | -------------------------------------------------------------------------------- /manifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "terminal", 3 | "title": "jQuery Terminal Emulator", 4 | "description": "jQuery Terminal Emulator is a plugin for creating command line interpreters in your applications.", 5 | "version": "{{VER}}", 6 | "keywords": [ 7 | "terminal", "emulator", "prompt", "console", "keyboard", "type", "rpc", "input", "ui" 8 | ], 9 | "author": { 10 | "name": "Jakub Jankiewicz", 11 | "email": "jcubic@onet.pl", 12 | "url": "http://jcubic.pl/me" 13 | }, 14 | "licenses": [{ 15 | "type": "MIT", 16 | "url": "http://opensource.org/licenses/MIT" 17 | }], 18 | "homepage": "http://terminal.jcubic.pl/", 19 | "bugs": "https://github.com/jcubic/jquery.terminal/issues", 20 | "demo": "http://terminal.jcubic.pl/#demo", 21 | "docs": "http://terminal.jcubic.pl/api_reference.php", 22 | "download": "https://github.com/jcubic/jquery.terminal/releases", 23 | "dependencies": { 24 | "jquery": ">=1.5" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /scripts/cssnano.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var nano = require('cssnano'); 3 | 4 | var input = process.argv[2]; 5 | var output = process.argv[3]; 6 | 7 | var options = { 8 | preset: "default", 9 | map: { 10 | inline: false 11 | }, 12 | discardUnused: false, 13 | from: input, 14 | to: output 15 | }; 16 | 17 | function error(err) { 18 | if (err) { 19 | if (err.message && typeof err.showSourceCode === 'function') { 20 | console.error(err.message); 21 | console.error(err.showSourceCode()); 22 | } else { 23 | console.error(err); 24 | } 25 | process.exit(1); 26 | } 27 | } 28 | 29 | fs.readFile(input, function(err, buffer) { 30 | nano.process(String(buffer), options).then(function(result) { 31 | fs.writeFile(output, result.css, function(err) { 32 | error(err); 33 | fs.writeFile(output + '.map', result.map.toString(), error); 34 | }); 35 | }).catch(error); 36 | }); 37 | -------------------------------------------------------------------------------- /terminal.jquery.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "terminal", 3 | "title": "jQuery Terminal Emulator", 4 | "description": "jQuery Terminal Emulator is a plugin for creating command line interpreters in your applications.", 5 | "version": "2.8.0", 6 | "keywords": [ 7 | "terminal", "emulator", "prompt", "console", "keyboard", "type", "rpc", "input", "ui" 8 | ], 9 | "author": { 10 | "name": "Jakub Jankiewicz", 11 | "email": "jcubic@onet.pl", 12 | "url": "http://jcubic.pl/me" 13 | }, 14 | "licenses": [{ 15 | "type": "MIT", 16 | "url": "http://opensource.org/licenses/MIT" 17 | }], 18 | "homepage": "http://terminal.jcubic.pl/", 19 | "bugs": "https://github.com/jcubic/jquery.terminal/issues", 20 | "demo": "http://terminal.jcubic.pl/#demo", 21 | "docs": "http://terminal.jcubic.pl/api_reference.php", 22 | "download": "https://github.com/jcubic/jquery.terminal/releases", 23 | "dependencies": { 24 | "jquery": ">=1.5" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /js/jquery.mousewheel-min.js: -------------------------------------------------------------------------------- 1 | (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]]= 2 | 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); 3 | -------------------------------------------------------------------------------- /examples/dialog.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Text based input box using jQuery Terminal 6 | 7 | 8 | 9 | 10 | 11 | 12 | 17 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /scripts/mkemoji: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const http = require('https'); 4 | const url = require('url'); 5 | const emoji = require('emoji-datasource-twitter'); 6 | 7 | if (process.argv.length === 3) { 8 | console.log([ 9 | '/*', 10 | ' * Autogenerated by mkemoji script from jQuery Terminal', 11 | ' * Copyright (C) Jakub T. Jankiewicz ', 12 | ' * ship with version: ' + process.argv[2], 13 | ' * build: ' + new Date().toUTCString(), 14 | ' */'].join('\n')); 15 | emoji.map(function(emoji) { 16 | var url = 'https://unpkg.com/emoji-datasource-twitter/img/' + 17 | 'twitter/64/' + emoji.image; 18 | // escape special characters in class name 19 | // https://mathiasbynens.be/notes/css-escapes 20 | var class_name = emoji.short_name.replace(/\+/g, '\\+') 21 | .replace(/^(\d)/i, '\\3$1 '); 22 | var selector = [ 23 | '.terminal-output>:not(.raw) .emoji.' + class_name, 24 | '.cmd .emoji.' + class_name].join(','); 25 | console.log(`${selector}{background-image:url(${url});}`); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2019 Jakub Jankiewicz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /scripts/update-contributors-package.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var fs = require('fs'); 4 | var path = require('path'); 5 | var argv = require('optimist').argv; 6 | 7 | function usage(error) { 8 | if (error) { 9 | console.error(error); 10 | } 11 | console.log('usage: \n' + path.basename(process.argv[1]) + 12 | ' -f ' + 13 | ' -j '); 14 | } 15 | 16 | if (argv.f && argv.j) { 17 | fs.readFile(argv.j, function(err, data) { 18 | if (err) { 19 | return usage(err); 20 | } 21 | var contributors = JSON.parse(data.toString()); 22 | fs.readFile(argv.f, function(err, data) { 23 | if (err) { 24 | return usage(err); 25 | } 26 | var _package = JSON.parse(data.toString()); 27 | _package.contributors = contributors.map(function(user) { 28 | const { name, url } = user; 29 | return { name, url }; 30 | }); 31 | fs.writeFile(argv.f, JSON.stringify(_package, null, 2) + '\n', 'utf8', function(err) { 32 | if (err) { 33 | return usage(err); 34 | } 35 | }); 36 | }); 37 | }); 38 | } else { 39 | usage(); 40 | } -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | All contribution are welcome even not tech one. To contribute you need to fork, then clone the repo: 4 | 5 | ``` 6 | git clone git@github.com:your-name/jquery.terminal.git 7 | ``` 8 | 9 | Please only modify `js/jquery.terminal-src.js`/`css/jquery.terminal-src.css` files. You can run `make`, but you may have conflicts others push commits with their build (you may have conflict because there is build date/time in build file) make sure you're on devel branch and create PR to devel brach as well, fixes to examples and README can be made directly to master but they could also be made to devel. 10 | 11 | Non tech contribution are also welcome, if you find a bug in documentation on the website you can file an issue to [jcubic/jquery.terminal-www](https://github.com/jcubic/jquery.terminal-www). 12 | 13 | 14 | ## Test 15 | 16 | You should run test to make sure you don't break anything, to run tests from browser you need to run 17 | 18 | ``` 19 | npm install 20 | make test 21 | ``` 22 | 23 | and run ESlint and JSONLint using: 24 | 25 | ``` 26 | make lint 27 | ``` 28 | you can also run test coverage using 29 | 30 | ``` 31 | make coverage 32 | ``` 33 | 34 | ## README 35 | 36 | if you want to modify readme please modify the one in templates directory because that one is source file with {{VER}} 37 | markers that get filled with current version when running `make`. 38 | -------------------------------------------------------------------------------- /examples/mysql-rpc-demo.php: -------------------------------------------------------------------------------- 1 | query($query)) { 27 | if ($res === true) { 28 | return true; 29 | } 30 | if ($res->num_rows > 0) { 31 | while ($row = $res->fetch_array(MYSQLI_NUM)) { 32 | $result[] = $row; 33 | } 34 | return $result; 35 | } else { 36 | return array(); 37 | } 38 | } else { 39 | throw new Exception("MySQL Error: " . mysqli_error($link)); 40 | } 41 | } 42 | } 43 | 44 | handle_json_rpc(new MysqlDemo()); 45 | 46 | ?> 47 | -------------------------------------------------------------------------------- /js/terminal.widget.js: -------------------------------------------------------------------------------- 1 | /* global jQuery */ 2 | 3 | (function() { 4 | function get(url) { 5 | var element; 6 | if (url.match(/css$/)) { 7 | element = document.createElement('link'); 8 | element.setAttribute('href', url); 9 | element.setAttribute('rel', 'stylesheet'); 10 | } else if (url.match(/js$/)) { 11 | element = document.createElement('script'); 12 | element.setAttribute('src', url); 13 | } 14 | console.log(element); 15 | return new Promise(function(resolve, reject) { 16 | console.log(element); 17 | if (element) { 18 | element.onload = resolve; 19 | var head = document.querySelector('head'); 20 | head.appendChild(element); 21 | } else { 22 | reject(); 23 | } 24 | }); 25 | } 26 | var terminals = window.terminals || []; 27 | if (typeof jQuery === 'undefined') { 28 | get('http://code.jquery.com/jquery-3.2.1.min.js').then(function() { 29 | jQuery.noConflict(); 30 | get('https://cdnjs.cloudflare.com/ajax/libs/jquery.terminal/1.7.2/css/jquery.terminal.min.css'); 31 | return get('https://cdnjs.cloudflare.com/ajax/libs/jquery.terminal/1.7.2/js/jquery.terminal.min.js'); 32 | }).then(function() { 33 | terminals.forEach(function(spec) { 34 | jQuery.fn.terminal.apply(jQuery(spec[0]), spec.slice(1)); 35 | }); 36 | }); 37 | } 38 | })(); 39 | -------------------------------------------------------------------------------- /js/terminal.widget.in: -------------------------------------------------------------------------------- 1 | /* global jQuery */ 2 | 3 | (function() { 4 | function get(url) { 5 | var element; 6 | if (url.match(/css$/)) { 7 | element = document.createElement('link'); 8 | element.setAttribute('href', url); 9 | element.setAttribute('rel', 'stylesheet'); 10 | } else if (url.match(/js$/)) { 11 | element = document.createElement('script'); 12 | element.setAttribute('src', url); 13 | } 14 | console.log(element); 15 | return new Promise(function(resolve, reject) { 16 | console.log(element); 17 | if (element) { 18 | element.onload = resolve; 19 | var head = document.querySelector('head'); 20 | head.appendChild(element); 21 | } else { 22 | reject(); 23 | } 24 | }); 25 | } 26 | var terminals = window.terminals || []; 27 | if (typeof jQuery === 'undefined') { 28 | get('http://code.jquery.com/jquery-3.2.1.min.js').then(function() { 29 | jQuery.noConflict(); 30 | get('https://cdnjs.cloudflare.com/ajax/libs/jquery.terminal/{{VER}}/css/jquery.terminal.min.css'); 31 | return get('https://cdnjs.cloudflare.com/ajax/libs/jquery.terminal/{{VER}}/js/jquery.terminal.min.js'); 32 | }).then(function() { 33 | terminals.forEach(function(spec) { 34 | jQuery.fn.terminal.apply(jQuery(spec[0]), spec.slice(1)); 35 | }); 36 | }); 37 | } 38 | })(); 39 | -------------------------------------------------------------------------------- /scripts/methods.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/node 2 | 3 | /* 4 | * script print terminal methods. it require esprima. 5 | * 6 | * To get list of functions, not covered by tests, use: 7 | * 8 | * methods | while read method; do 9 | * grep $method spec/terminalSpec.js > /dev/null || echo $method; 10 | * done 11 | * 12 | * if you want to find methods not in documentation use www/api_reference.php 13 | * instead of spec/terminalSpec.js 14 | */ 15 | 16 | var fs = require('fs'); 17 | var esprima = require('esprima'); 18 | 19 | fs.readFile('js/jquery.terminal-src.js', function(err, file) { 20 | var syntax = esprima.parse(file.toString()); 21 | traverse(syntax, function(obj) { 22 | if (obj.callee && obj.callee.property && obj.callee.property.name == 'omap' && 23 | obj.callee.type == 'MemberExpression') { 24 | var methods = []; 25 | if (obj.arguments[0].properties) { 26 | obj.arguments[0].properties.map(function(prop) { 27 | console.log(prop.key.name); 28 | }); 29 | return false; 30 | } 31 | } 32 | }); 33 | function traverse(obj, fn) { 34 | for (var key in obj) { 35 | if (obj[key] !== null && fn(obj[key]) === false) { 36 | return false; 37 | } 38 | if (typeof obj[key] == 'object' && obj[key] !== null) { 39 | if (traverse(obj[key], fn) === false) { 40 | return false; 41 | } 42 | } 43 | } 44 | } 45 | 46 | }); 47 | -------------------------------------------------------------------------------- /examples/rpc-demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JSON-RPC Demo for JQuery Terminal Emulator 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /examples/json-rpc-service-demo.php: -------------------------------------------------------------------------------- 1 | $_SERVER["HTTP_USER_AGENT"], 47 | "your IP" => $_SERVER['REMOTE_ADDR'], 48 | "you acces this from" => $_SERVER["HTTP_REFERER"]); 49 | } 50 | } 51 | 52 | handle_json_rpc(new Demo()); 53 | 54 | ?> 55 | -------------------------------------------------------------------------------- /js/xml_formatting.js: -------------------------------------------------------------------------------- 1 | /**@license 2 | * __ _____ ________ __ 3 | * / // _ /__ __ _____ ___ __ _/__ ___/__ ___ ______ __ __ __ ___ / / 4 | * __ / // // // // // _ // _// // / / // _ // _// // // \/ // _ \/ / 5 | * / / // // // // // ___// / / // / / // ___// / / / / // // /\ // // / /__ 6 | * \___//____ \\___//____//_/ _\_ / /_//____//_/ /_/ /_//_//_/ /_/ \__\_\___/ 7 | * \/ /____/ 8 | * http://terminal.jcubic.pl 9 | * 10 | * This is example of how to create custom formatter for jQuery Terminal 11 | * 12 | * Copyright (c) 2014-2019 Jakub Jankiewicz 13 | * Released under the MIT license 14 | * 15 | */ 16 | /* global define, global, require, module */ 17 | (function(factory) { 18 | var root = typeof window !== 'undefined' ? window : global; 19 | if (typeof define === 'function' && define.amd) { 20 | // AMD. Register as an anonymous module. 21 | // istanbul ignore next 22 | define(['jquery', 'jquery.terminal'], factory); 23 | } else if (typeof module === 'object' && module.exports) { 24 | // Node/CommonJS 25 | module.exports = function(root, jQuery) { 26 | if (jQuery === undefined) { 27 | // require('jQuery') returns a factory that requires window to 28 | // build a jQuery instance, we normalize how we use modules 29 | // that require this pattern but the window provided is a noop 30 | // if it's defined (how jquery works) 31 | if (typeof window !== 'undefined') { 32 | jQuery = require('jquery'); 33 | } else { 34 | jQuery = require('jquery')(root); 35 | } 36 | } 37 | if (!jQuery.fn.terminal) { 38 | if (typeof window !== 'undefined') { 39 | require('jquery.terminal'); 40 | } else { 41 | require('jquery.terminal')(jQuery); 42 | } 43 | } 44 | factory(jQuery); 45 | return jQuery; 46 | }; 47 | } else { 48 | // Browser 49 | // istanbul ignore next 50 | factory(root.jQuery); 51 | } 52 | })(function($) { 53 | if (!$.terminal) { 54 | throw new Error('$.terminal is not defined'); 55 | } 56 | // this formatter allow to echo xml where tags are colors like: 57 | // hello blue world 58 | function xml_formatter(string) { 59 | var stack = []; 60 | var output = []; 61 | var parts = string.split(/(<\/?[a-zA-Z]+>)/); 62 | for (var i = 0; i < parts.length; ++i) { 63 | if (parts[i][0] === '<') { 64 | if (parts[i][1] === '/') { 65 | if (stack.length) { 66 | stack.pop(); 67 | } 68 | } else { 69 | stack.push(parts[i].replace(/^<|>$/g, '')); 70 | } 71 | } else { 72 | if (stack.length) { 73 | // top of the stack 74 | output.push('[[;' + stack[stack.length - 1] + ';]'); 75 | } 76 | output.push(parts[i]); 77 | if (stack.length) { 78 | output.push(']'); 79 | } 80 | } 81 | } 82 | return output.join(''); 83 | } 84 | $.terminal.new_formatter(xml_formatter); 85 | }); 86 | -------------------------------------------------------------------------------- /examples/dialog.css: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery Plugin for text based dialogs that look 3 | * like dialog linux command it use cmd plugin from 4 | * jQuery Terminal 5 | * 6 | * Copyright (c) 2017 Jakub Jankiewicz 7 | * 8 | * Linceses under MIT license 9 | */ 10 | .dialog { 11 | background-color: #00a; 12 | position: relatieve; 13 | font-size: 12px; 14 | line-height: 14px; 15 | margin: 0; 16 | } 17 | .dialog, .dialog button { 18 | font-family: monospace; 19 | } 20 | .dialog > :not(.box) { 21 | display: none; 22 | } 23 | .dialog .box > .input .cmd { 24 | float: none; 25 | margin-bottom: -4px; 26 | --color: #000; 27 | --background: #aaa; 28 | padding: 0; 29 | } 30 | .dialog .cmd > span:not(.prompt) { 31 | float: none; 32 | } 33 | @supports (--css: variables) { 34 | .dialog, .dialog button { 35 | font-size: calc(var(--size, 1) * 12px); 36 | line-height: calc(var(--size, 1) * 14px); 37 | } 38 | } 39 | .dialog > .box { 40 | background-color: #aaa; 41 | float: left; 42 | position: absolute; 43 | top: 50%; 44 | left: 50%; 45 | transform: translate(-50%, -50%); 46 | -webkit-box-shadow: calc(var(--char-width) * 2px) calc(var(--char-width) * 2px) black; 47 | box-shadow: calc(var(--char-width) * 2px) calc(var(--char-width) * 2px) black; 48 | } 49 | .dialog .box .light { 50 | color: #fff; 51 | } 52 | .dialog .box .dark { 53 | color: #000; 54 | } 55 | .dialog .line { 56 | float: left; 57 | clear: both; 58 | white-space: nowrap; 59 | } 60 | .dialog .box > .input .left, 61 | .dialog .box > .input .top, 62 | .dialog .box > .input .bottom, 63 | .dialog .box > .input .cmd, 64 | .dialog .box > .input .right { 65 | display: inline-block; 66 | } 67 | .dialog .box > .buttons-line .left, 68 | .dialog .box > .buttons-line .buttons, 69 | .dialog .box > .buttons-line .right { 70 | float: left; 71 | } 72 | .dialog .box .title { 73 | position: absolute; 74 | top: 0; 75 | left: 0; 76 | right: 0; 77 | text-align: center; 78 | overflow: hidden; 79 | } 80 | .dialog .box .title span { 81 | background-color: #aaa; 82 | } 83 | .dialog .box .header span { 84 | display: inline-block; 85 | } 86 | .dialog .box .buttons { 87 | display: flex; 88 | justify-content: space-around; 89 | } 90 | .dialog .box button { 91 | margin: 0; 92 | padding: 0; 93 | border: none; 94 | color: #555; 95 | min-width: 87px; 96 | } 97 | .dialog .box button:active, 98 | .dialog .box button { 99 | outline: none; 100 | } 101 | 102 | .dialog .box button:before { 103 | content: '<'; 104 | float: left; 105 | } 106 | .dialog .box button:after { 107 | content: '>'; 108 | float: right; 109 | } 110 | .dialog .box button:before, 111 | .dialog .box button:after { 112 | display: inline-block; 113 | color: #000; 114 | } 115 | .dialog .box button, 116 | .dialog .box button:before, 117 | .dialog .box button:after { 118 | background-color: transparent; 119 | } 120 | .dialog .box button:not(.active) .mark { 121 | color: #a00; 122 | } 123 | .dialog .box button.active, 124 | .dialog .box button.active:before, 125 | .dialog .box button.active:after { 126 | background-color: #00a; 127 | } 128 | .dialog .box button.active { 129 | color: #ff5; 130 | } 131 | .dialog .box button.active:before, 132 | .dialog .box button.active:after { 133 | color: #fff; 134 | } 135 | .dialog .box button.active.selected .mark { 136 | color: #00a; 137 | background: #fff; 138 | } 139 | -------------------------------------------------------------------------------- /examples/tilda-demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Quake like teminal - JQuery Terminal Emulator Demo 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 34 | 106 | 107 | 108 |
109 |

This is demo of JQuery Terminal Emulator, type tilda to open terminal

110 | 111 | 112 | -------------------------------------------------------------------------------- /templates/package.git: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jcubic/jquery.terminal", 3 | "version": "{{VER}}", 4 | "description": "jQuery Terminal Emulator is a plugin for creating command line interpreters in your applications.", 5 | "main": "js/jquery.terminal.js", 6 | "typings": "js/jquery.terminal.d.ts", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/jcubic/jquery.terminal.git" 10 | }, 11 | "keywords": [ 12 | "terminal", 13 | "emulator", 14 | "prompt", 15 | "console", 16 | "keyboard", 17 | "type", 18 | "rpc", 19 | "input", 20 | "ui" 21 | ], 22 | "scripts": { 23 | "test": "make test" 24 | }, 25 | "author": { 26 | "name": "Jakub Jankiewicz", 27 | "email": "jcubic@onet.pl", 28 | "url": "https://jcubic.pl/me" 29 | }, 30 | "contributors": [ 31 | { 32 | "name": "Jakub T. Jankiewicz", 33 | "url": "https://jcubic.pl/me" 34 | }, 35 | { 36 | "name": "Zuo Qiyang", 37 | "url": "http://zuoqy.com" 38 | }, 39 | { 40 | "name": "Marcel Link", 41 | "url": "https://github.com/ml1nk" 42 | }, 43 | { 44 | "name": "Sébastien Warin", 45 | "url": "http://sebastien.warin.fr" 46 | }, 47 | { 48 | "name": "Christopher John Ryan", 49 | "url": "https://github.com/ChrisJohnRyan" 50 | }, 51 | { 52 | "name": "Johan", 53 | "url": "https://github.com/johanjordaan" 54 | }, 55 | { 56 | "name": "Florian Schäfer", 57 | "url": "https://github.com/fschaefer" 58 | }, 59 | { 60 | "name": "David Refoua", 61 | "url": "http://www.Refoua.me" 62 | }, 63 | { 64 | "name": "Ishan Ratnapala", 65 | "url": "https://github.com/IshanRatnapala" 66 | }, 67 | { 68 | "name": "Tomasz Ducin", 69 | "url": "http://ducin.it" 70 | }, 71 | { 72 | "name": "Abdelrahman Omran", 73 | "url": "https://omranic.com" 74 | }, 75 | { 76 | "name": "Anton Vasil'ev", 77 | "url": "https://github.com/avdes" 78 | }, 79 | { 80 | "name": "finlob", 81 | "url": "https://github.com/finlob" 82 | }, 83 | { 84 | "name": "Hraban Luyat", 85 | "url": "https://luyat.com" 86 | }, 87 | { 88 | "name": "Jon Steinich", 89 | "url": "https://github.com/jsteinich" 90 | }, 91 | { 92 | "name": "Martin v. Löwis", 93 | "url": "https://github.com/loewis" 94 | }, 95 | { 96 | "name": "Mateusz Paprocki", 97 | "url": "https://github.com/mattpap" 98 | }, 99 | { 100 | "name": "exit1", 101 | "url": "https://github.com/exit1" 102 | }, 103 | { 104 | "name": "Robert Wikman", 105 | "url": "https://github.com/rbw" 106 | }, 107 | { 108 | "name": "Steve Phillips", 109 | "url": "https://tryingtobeawesome.com/" 110 | }, 111 | { 112 | "name": "Yutong Luo", 113 | "url": "https://yutongluo.com" 114 | }, 115 | { 116 | "name": "coderaiser", 117 | "url": "http://coderaiser.github.io" 118 | }, 119 | { 120 | "name": "mrkaiser", 121 | "url": "https://github.com/mrkaiser" 122 | }, 123 | { 124 | "name": "stereobooster", 125 | "url": "https://stereobooster.com" 126 | }, 127 | { 128 | "name": "Steve Kirkegard", 129 | "url": "https://www.linkedin.com/in/steve-kirkegard" 130 | }, 131 | { 132 | "name": "Juraj Vitko", 133 | "url": "https://github.com/youurayy" 134 | } 135 | ], 136 | "license": "MIT", 137 | "bugs": { 138 | "url": "https://github.com/jcubic/jquery.terminal/issues" 139 | }, 140 | "homepage": "https://terminal.jcubic.pl", 141 | "dependencies": { 142 | "@types/jquery": "3.3.29", 143 | "jquery": "~3", 144 | "prismjs": "^1.16.0", 145 | "wcwidth": "^1.0.1" 146 | }, 147 | "devDependencies": { 148 | "coveralls": "^3.0.3", 149 | "cssnano": "^4.1.10", 150 | "emoji-datasource-twitter": "^4.1.0", 151 | "eslint": "^5.16.0", 152 | "jest": "^24.8.0", 153 | "jsonlint": "^1.6.3", 154 | "typescript": "~3.1.6", 155 | "uglify-js": "^3.5.12" 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /examples/multiple-interpreters-demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JSON-RPC Demo for JQuery Terminal Emulator 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /js/dterm.js: -------------------------------------------------------------------------------- 1 | /**@license 2 | * __ _____ ________ __ 3 | * / // _ /__ __ _____ ___ __ _/__ ___/__ ___ ______ __ __ __ ___ / / 4 | * __ / // // // // // _ // _// // / / // _ // _// // // \/ // _ \/ / 5 | * / / // // // // // ___// / / // / / // ___// / / / / // // /\ // // / /__ 6 | * \___//____ \\___//____//_/ _\_ / /_//____//_/ /_/ /_//_//_/ /_/ \__\_\___/ 7 | * \/ /____/ 8 | * Example plugin using JQuery Terminal Emulator 9 | * Copyright (c) 2014-2019 Jakub Jankiewicz 10 | * Released under the MIT license 11 | * 12 | */ 13 | /* global setTimeout, IntersectionObserver, define, global, require, module */ 14 | (function(factory, undefined) { 15 | var root = typeof window !== 'undefined' ? window : global; 16 | if (typeof define === 'function' && define.amd) { 17 | // AMD. Register as an anonymous module. 18 | // istanbul ignore next 19 | define(['jquery', 'jquery.terminal'], factory); 20 | } else if (typeof module === 'object' && module.exports) { 21 | // Node/CommonJS 22 | module.exports = function(root, jQuery) { 23 | if (jQuery === undefined) { 24 | // require('jQuery') returns a factory that requires window to 25 | // build a jQuery instance, we normalize how we use modules 26 | // that require this pattern but the window provided is a noop 27 | // if it's defined (how jquery works) 28 | if (window !== undefined) { 29 | jQuery = require('jquery'); 30 | } else { 31 | jQuery = require('jquery')(root); 32 | } 33 | } 34 | if (!jQuery.fn.terminal) { 35 | if (window !== undefined) { 36 | require('jquery.terminal'); 37 | } else { 38 | require('jquery.terminal')(jQuery); 39 | } 40 | } 41 | factory(jQuery); 42 | return jQuery; 43 | }; 44 | } else { 45 | // Browser 46 | // istanbul ignore next 47 | factory(root.jQuery); 48 | } 49 | })(function($) { 50 | $.extend_if_has = function(desc, source, array) { 51 | for (var i = array.length; i--;) { 52 | if (typeof source[array[i]] !== 'undefined') { 53 | desc[array[i]] = source[array[i]]; 54 | } 55 | } 56 | return desc; 57 | }; 58 | var defaults = Object.keys($.terminal.defaults).concat(['greetings']); 59 | $.fn.dterm = function(interpreter, options) { 60 | var op = $.extend_if_has({}, options, defaults); 61 | op.enabled = false; 62 | this.addClass('dterm'); 63 | var terminal = $('
').appendTo(this).terminal(interpreter, op); 64 | if (!options.title) { 65 | options.title = 'JQuery Terminal Emulator'; 66 | } 67 | var close = options.close || $.noop; 68 | if (options.logoutOnClose) { 69 | options.close = function() { 70 | terminal.logout(); 71 | terminal.clear(); 72 | close(); 73 | }; 74 | } else { 75 | options.close = function() { 76 | terminal.disable(); 77 | close(); 78 | }; 79 | } 80 | var self = this; 81 | if (window.IntersectionObserver) { 82 | var visibility_observer = new IntersectionObserver(function() { 83 | if (self.is(':visible')) { 84 | terminal.focus().resize(); 85 | } else { 86 | terminal.disable(); 87 | } 88 | }, { 89 | root: null 90 | }); 91 | visibility_observer.observe(terminal[0]); 92 | } 93 | this.dialog($.extend({}, options, { 94 | open: function(event, ui) { 95 | if (!window.IntersectionObserver) { 96 | setTimeout(function() { 97 | terminal.enable().resize(); 98 | }, 100); 99 | } 100 | if (typeof options.open === 'function') { 101 | options.open(event, ui); 102 | } 103 | }, 104 | show: 'fade', 105 | closeOnEscape: false 106 | })); 107 | self.terminal = terminal; 108 | return self; 109 | }; 110 | }); 111 | -------------------------------------------------------------------------------- /scripts/contributors.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var https = require('https'); 4 | var path = require('path'); 5 | var fs = require('fs'); 6 | var argv = require('optimist').argv; 7 | var request = require('request'); 8 | 9 | 10 | function split_equal(array, length) { 11 | var result = []; 12 | var len = array.length; 13 | if (len < length) { 14 | return [array]; 15 | } else if (length < 0) { 16 | throw new Error("split_equal: length can't be negative"); 17 | } 18 | for (var i = 0; i < len; i += length) { 19 | result.push(array.slice(i, i + length)); 20 | } 21 | return result; 22 | } 23 | 24 | function get(url, query) { 25 | var options = { 26 | url: url, 27 | qs: query, 28 | headers: { 29 | 'User-Agent': 'Node.js' 30 | } 31 | }; 32 | if (argv.auth) { 33 | options.auth = argv.auth; 34 | } 35 | //return; 36 | return new Promise(function(resolve, reject) { 37 | request(options, function(error, res, body) { 38 | if (res.statusCode == 200) { 39 | resolve(JSON.parse(body)); 40 | } else if (+res.headers['x-ratelimit-remaining'] == 0) { 41 | var date = new Date(+res.headers['x-ratelimit-reset']*1000); 42 | reject('Rate limit util ' + date); 43 | } else { 44 | reject('Error code ' + res.statusCode); 45 | } 46 | }); 47 | }); 48 | } 49 | 50 | function get_file(filename) { 51 | return new Promise(function(resolve, reject) { 52 | fs.readFile(filename, function(err, data) { 53 | if (err) { 54 | reject(err); 55 | } else { 56 | resolve(JSON.parse(data.toString())); 57 | } 58 | }); 59 | }); 60 | } 61 | 62 | function get_api(argv) { 63 | var user = argv.u; 64 | var repo = argv.r; 65 | var path = '/repos/' + user + '/' + repo + '/contributors'; 66 | var query = { 67 | "per_page": 100 68 | }; 69 | if (argv.t) { 70 | query['access_token'] = argv.t; 71 | } 72 | return get('https://api.github.com' + path, query).then(function(contributors) { 73 | return Promise.all(contributors.map(function(contributor) { 74 | var path = contributor.url.replace(/https:\/\/[^\/]+/, ''); 75 | return get('https://api.github.com' + path, query).then(function(user) { 76 | if (user.name || user.login) { 77 | var object = { 78 | name: user.name || user.login 79 | }; 80 | if (user.email) { 81 | object.email = user.email; 82 | } 83 | if (user.blog) { 84 | object.url = user.blog; 85 | } else { 86 | object.url = "https://github.com/" + user.login 87 | } 88 | object.avatar = contributor.avatar_url; 89 | object.login = user.login; 90 | return object; 91 | } 92 | }); 93 | }).filter(Boolean)); 94 | }); 95 | } 96 | 97 | 98 | if ((argv.f && argv.m) || (argv.u && argv.r)) { 99 | (argv.f ? get_file(argv.f) : get_api(argv)).then(function(contributors) { 100 | if (argv.m) { 101 | var split = split_equal(contributors, 7); 102 | var align = new Array(split[0].length + 1).join('| :---: ') + ' |'; 103 | var rows = split.map(function(list) { 104 | return '| ' + list.map(function(contributor) { 105 | return '[' + 106 | '
' + contributor.name + '](' + 107 | contributor.url + ')
[commits](https://github.com/jcubic' + 108 | '/jquery.terminal/commits?author=' + contributor.login + ')'; 109 | }).join(' | ') + ' |'; 110 | }); 111 | rows.splice(1, 0, align); 112 | console.log(rows.join('\n')); 113 | } else { 114 | console.log(JSON.stringify(contributors, null, 2)); 115 | } 116 | }).catch(function(error) { 117 | console.log('ERROR: ' + error); 118 | }); 119 | } else { 120 | var script = path.basename(process.argv[1]); 121 | console.log('usage: \n' + script + '-u -r ' + 122 | '[--auth githubUsername:githubPassword] [-m]\n' + 123 | script + ' -f -m'); 124 | } 125 | -------------------------------------------------------------------------------- /js/ascii_table.js: -------------------------------------------------------------------------------- 1 | /**@license 2 | * __ _____ ________ __ 3 | * / // _ /__ __ _____ ___ __ _/__ ___/__ ___ ______ __ __ __ ___ / / 4 | * __ / // // // // // _ // _// // / / // _ // _// // // \/ // _ \/ / 5 | * / / // // // // // ___// / / // / / // ___// / / / / // // /\ // // / /__ 6 | * \___//____ \\___//____//_/ _\_ / /_//____//_/ /_/ /_//_//_/ /_/ \__\_\___/ 7 | * \/ /____/ 8 | * http://terminal.jcubic.pl 9 | * 10 | * utility that renders simple ascii table, like the one from mysql cli tool 11 | * it was first created for leash shell https://leash.jcubic.pl 12 | * 13 | * usage: 14 | * 15 | * var arr = [[1,2,3,4,5], ["lorem", "ipsum", "dolor", "sit", "amet"]]; 16 | * term.echo(ascii_table(arr)); 17 | * // or 18 | * term.echo(ascii_table(arr, true)); // this will render first row as header 19 | * 20 | * Copyright (c) 2018-2019 Jakub Jankiewicz 21 | * Released under the MIT license 22 | * 23 | */ 24 | /* global define, module, global, wcwidth, require */ 25 | (function(factory) { 26 | var root = typeof window !== 'undefined' ? window : global; 27 | if (typeof define === 'function' && define.amd) { 28 | // AMD. Register as an anonymous module. 29 | define(['wcwidth'], function(wcwidth) { 30 | return (root.ascii_table = factory(wcwidth)); 31 | }); 32 | } else if (typeof module === 'object' && module.exports) { 33 | // Node/CommonJS 34 | module.exports = factory(require('wcwidth')); 35 | } else { 36 | root.ascii_table = factory(root.wcwidth); 37 | } 38 | })(function(wcwidth, undefined) { 39 | var strlen = (function() { 40 | if (typeof wcwidth === 'undefined') { 41 | return function(string) { 42 | return string.length; 43 | }; 44 | } else { 45 | return wcwidth; 46 | } 47 | })(); 48 | function ascii_table(array, header) { 49 | if (!array.length) { 50 | return ''; 51 | } 52 | for (var i = array.length - 1; i >= 0; i--) { 53 | var row = array[i]; 54 | var stacks = []; 55 | for (var j = 0; j < row.length; j++) { 56 | var new_lines = row[j].toString().replace(/\r/g).split("\n"); 57 | row[j] = new_lines.shift(); 58 | stacks.push(new_lines); 59 | } 60 | var stack_lengths = stacks.map(function(column) { 61 | return column.length; 62 | }); 63 | var new_rows_count = Math.max.apply(Math, stack_lengths); 64 | for (var k = new_rows_count - 1; k >= 0; k--) { 65 | array.splice(i + 1, 0, stacks.map(function(column) { 66 | return column[k] || ""; 67 | })); 68 | } 69 | } 70 | var lengths = array[0].map(function(_, i) { 71 | var col = array.map(function(row) { 72 | if (row[i] != undefined) { 73 | var len = strlen(row[i]); 74 | if (row[i].match(/\t/g)) { 75 | // tab is 4 spaces 76 | len += row[i].match(/\t/g).length*3; 77 | } 78 | return len; 79 | } else { 80 | return 0; 81 | } 82 | }); 83 | return Math.max.apply(Math, col); 84 | }); 85 | // column padding 86 | array = array.map(function(row) { 87 | return '| ' + row.map(function(item, i) { 88 | var size = strlen(item); 89 | if (item.match(/\t/g)) { 90 | // tab is 4 spaces 91 | size += item.match(/\t/g).length*3; 92 | } 93 | if (size < lengths[i]) { 94 | item += new Array(lengths[i] - size + 1).join(' '); 95 | } 96 | return item; 97 | }).join(' | ') + ' |'; 98 | }); 99 | array = array.map(function(line) { 100 | return line.replace(/&(?![^;]+;)/g, '&'); 101 | }); 102 | var sep = '+' + lengths.map(function(length) { 103 | return new Array(length + 3).join('-'); 104 | }).join('+') + '+'; 105 | if (header) { 106 | return sep + '\n' + array[0] + '\n' + sep + '\n' + 107 | array.slice(1).join('\n') + '\n' + sep; 108 | } else { 109 | return sep + '\n' + array.join('\n') + '\n' + sep; 110 | } 111 | } 112 | return ascii_table; 113 | }); 114 | -------------------------------------------------------------------------------- /js/emoji.js: -------------------------------------------------------------------------------- 1 | /**@license 2 | * __ _____ ________ __ 3 | * / // _ /__ __ _____ ___ __ _/__ ___/__ ___ ______ __ __ __ ___ / / 4 | * __ / // // // // // _ // _// // / / // _ // _// // // \/ // _ \/ / 5 | * / / // // // // // ___// / / // / / // ___// / / / / // // /\ // // / /__ 6 | * \___//____ \\___//____//_/ _\_ / /_//____//_/ /_/ /_//_//_/ /_/ \__\_\___/ 7 | * \/ /____/ 8 | * http://terminal.jcubic.pl 9 | * 10 | * this is formatter for jQuery Terminal that add support for emoji 11 | * 12 | * Copyright (c) 2019 Jakub Jankiewicz 13 | * Released under the MIT license 14 | * 15 | */ 16 | /* global define, global, require, module */ 17 | (function(factory, undefined) { 18 | var root = typeof window !== 'undefined' ? window : global; 19 | if (typeof define === 'function' && define.amd) { 20 | // AMD. Register as an anonymous module. 21 | // istanbul ignore next 22 | define(['jquery', 'jquery.terminal'], factory); 23 | } else if (typeof module === 'object' && module.exports) { 24 | // Node/CommonJS 25 | module.exports = function(root, jQuery) { 26 | if (jQuery === undefined) { 27 | // require('jQuery') returns a factory that requires window to 28 | // build a jQuery instance, we normalize how we use modules 29 | // that require this pattern but the window provided is a noop 30 | // if it's defined (how jquery works) 31 | if (window !== undefined) { 32 | jQuery = require('jquery'); 33 | } else { 34 | jQuery = require('jquery')(root); 35 | } 36 | } 37 | if (!jQuery.fn.terminal) { 38 | if (window !== undefined) { 39 | require('jquery.terminal'); 40 | } else { 41 | require('jquery.terminal')(jQuery); 42 | } 43 | } 44 | factory(jQuery); 45 | return jQuery; 46 | }; 47 | } else { 48 | // Browser 49 | // istanbul ignore next 50 | factory(root.jQuery, root.Prism); 51 | } 52 | })(function($) { 53 | // https://2ality.com/2013/09/javascript-unicode.html 54 | function toUTF16(codePoint) { 55 | var TEN_BITS = parseInt('1111111111', 2); 56 | function u(codeUnit) { 57 | return '\\u' + codeUnit.toString(16).toUpperCase(); 58 | } 59 | 60 | if (codePoint <= 0xFFFF) { 61 | return u(codePoint); 62 | } 63 | codePoint -= 0x10000; 64 | 65 | // Shift right to get to most significant 10 bits 66 | var leadSurrogate = 0xD800 + (codePoint >> 10); 67 | 68 | // Mask to get least significant 10 bits 69 | var tailSurrogate = 0xDC00 + (codePoint & TEN_BITS); 70 | 71 | return u(leadSurrogate) + u(tailSurrogate); 72 | } 73 | // emoji_data param need to be JavaScript object from 74 | // https://unpkg.com/emoji-datasource-twitter/emoji.json 75 | $.terminal.emoji = function(emoji_data) { 76 | var text = {}; 77 | var names = []; 78 | emoji_data.forEach(function(emoji) { 79 | if (emoji.text && !text[emoji.text]) { 80 | text[emoji.text] = emoji.short_name; 81 | } 82 | names.push(emoji.short_name); 83 | }); 84 | // new API from version 1.10.0, old one with function will still work but 85 | // if you need to use replacement that change length of the input text 86 | // you need to use [regex, str] or function formatter where you use 87 | // $.terminal.tracking_replace that returns [string, position] the same 88 | // should be returned by formatter, optionally you can check if options 89 | // have position 90 | $.terminal.defaults.formatters.push([ 91 | new RegExp(':(' + names.map(function(name) { 92 | return $.terminal.escape_regex(name); 93 | }).join('|') + '):', 'g'), 94 | '[[;;;emoji $1]⻇]' 95 | ]); 96 | Object.keys(text).forEach(function(name) { 97 | $.terminal.defaults.formatters.push([ 98 | new RegExp($.terminal.escape_regex(name), 'g'), 99 | '[[;;;emoji ' + text[name] + ']⻇]' 100 | ]); 101 | }); 102 | // this is unicode emoji handling 103 | $.terminal.defaults.formatters.push(function(string, options) { 104 | var result = [string, options.position]; 105 | emoji_data.forEach(function(emoji) { 106 | if (emoji.unified) { 107 | var unicode = emoji.unified.split('-').map(function(u) { 108 | var x = parseInt(u, 16); 109 | if (x > 0xFFFF) { 110 | return toUTF16(x); 111 | } 112 | return '\\u' + u; 113 | }).join(''); 114 | var re = new RegExp('(' + unicode + ')', 'g'); 115 | if (re.test(result[0])) { 116 | result = $.terminal.tracking_replace( 117 | result[0], 118 | re, 119 | '[[;;;emoji ' + emoji.short_name + ']$1]', 120 | result[1] 121 | ); 122 | } 123 | } 124 | }); 125 | return result; 126 | }); 127 | }; 128 | }); 129 | -------------------------------------------------------------------------------- /js/echo_newline.js: -------------------------------------------------------------------------------- 1 | /**@license 2 | * __ _____ ________ __ 3 | * / // _ /__ __ _____ ___ __ _/__ ___/__ ___ ______ __ __ __ ___ / / 4 | * __ / // // // // // _ // _// // / / // _ // _// // // \/ // _ \/ / 5 | * / / // // // // // ___// / / // / / // ___// / / / / // // /\ // // / /__ 6 | * \___//____ \\___//____//_/ _\_ / /_//____//_/ /_/ /_//_//_/ /_/ \__\_\___/ 7 | * \/ /____/ 8 | * http://terminal.jcubic.pl 9 | * 10 | * Monkey patch to add newlinew option for echo method inside jQuery Terminal 11 | * 12 | * Copyright (c) 2014-2019 Jakub Jankiewicz 13 | * Released under the MIT license 14 | * 15 | */ 16 | /* global define, global, require, module */ 17 | (function(factory) { 18 | var root = typeof window !== 'undefined' ? window : global; 19 | if (typeof define === 'function' && define.amd) { 20 | // AMD. Register as an anonymous module. 21 | // istanbul ignore next 22 | define(['jquery', 'jquery.terminal'], factory); 23 | } else if (typeof module === 'object' && module.exports) { 24 | // Node/CommonJS 25 | module.exports = function(root, jQuery) { 26 | if (jQuery === undefined) { 27 | // require('jQuery') returns a factory that requires window to 28 | // build a jQuery instance, we normalize how we use modules 29 | // that require this pattern but the window provided is a noop 30 | // if it's defined (how jquery works) 31 | if (typeof window !== 'undefined') { 32 | jQuery = require('jquery'); 33 | } else { 34 | jQuery = require('jquery')(root); 35 | } 36 | } 37 | if (!jQuery.fn.terminal) { 38 | if (typeof window !== 'undefined') { 39 | require('jquery.terminal'); 40 | } else { 41 | require('jquery.terminal')(jQuery); 42 | } 43 | } 44 | factory(jQuery); 45 | return jQuery; 46 | }; 47 | } else { 48 | // Browser 49 | // istanbul ignore next 50 | factory(root.jQuery); 51 | } 52 | })(function($) { 53 | var init = $.fn.terminal; 54 | $.fn.terminal = function(interpreter, options) { 55 | return init.call(this, interpreter, patch_options(options)).each(function() { 56 | patch_term($(this).data('terminal'), should_echo_command(options)); 57 | }); 58 | }; 59 | var last; 60 | var prompt; 61 | function should_echo_command(options) { 62 | return options && options.echoCommand !== false || !options; 63 | } 64 | function patch_options(options) { 65 | var keymap = { 66 | 'ENTER': function(e, original) { 67 | var term = this; 68 | if (!last) { 69 | if (should_echo_command(options)) { 70 | term.echo_command(); 71 | } 72 | } else { 73 | this.__echo(last + prompt + this.get_command()); 74 | this.set_prompt(prompt); 75 | last = ''; 76 | } 77 | if (options && options.keymap && options.keymap.ENTER) { 78 | options.keymap.ENTER.call(this, e, original); 79 | } else { 80 | original.call(this, e); 81 | } 82 | } 83 | }; 84 | var settings = { 85 | echoCommand: false, 86 | keymap: $.extend({}, options && options.keymap || {}, keymap) 87 | }; 88 | return $.extend({}, options || {}, settings); 89 | } 90 | function patch_term(term, echo_command) { 91 | term.__echo = term.echo; 92 | term.__exec = term.exec; 93 | term.exec = function() { 94 | last = ''; 95 | if (echo_command) { 96 | this.settings().echoCommand = true; 97 | } 98 | var ret = term.__exec.apply(this, arguments); 99 | if (echo_command) { 100 | this.settings().echoCommand = false; 101 | } 102 | return ret; 103 | }; 104 | term.echo = function(arg, options) { 105 | var settings = $.extend({ 106 | newline: true 107 | }, options); 108 | function process(prompt) { 109 | // this probably can be simplify because terminal handle 110 | // newlines in prompt 111 | var last_line; 112 | last += arg; 113 | arg = last + prompt; 114 | var arr = arg.split('\n'); 115 | if (arr.length === 1) { 116 | last_line = arg; 117 | } else { 118 | term.__echo(arr.slice(0, -1).join('\n'), options); 119 | last_line = arr[arr.length - 1]; 120 | } 121 | term.set_prompt(last_line); 122 | } 123 | if (settings.newline === false) { 124 | if (!prompt) { 125 | prompt = term.get_prompt(); 126 | } 127 | if (typeof prompt === 'string') { 128 | process(prompt); 129 | } else { 130 | prompt(process); 131 | } 132 | } else { 133 | if (prompt) { 134 | term.set_prompt(prompt); 135 | } 136 | if (last) { 137 | term.__echo(last + arg, options); 138 | } else if (!arguments.length) { 139 | // original echo check length to test if someone call echo 140 | // with value that is undefined 141 | term.__echo(); 142 | } else { 143 | term.__echo(arg, options); 144 | } 145 | last = ''; 146 | prompt = ''; 147 | } 148 | return term; 149 | }; 150 | } 151 | }); 152 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | VERSION=2.8.0 2 | SED=sed 3 | CD=cd 4 | NPM=npm 5 | CP=cp 6 | RM=rm 7 | CAT=cat 8 | DATE=`date -uR` 9 | GIT=git 10 | BRANCH=`git branch | grep '^*' | sed 's/* //'` 11 | UGLIFY=../node_modules/.bin/uglifyjs 12 | JSONLINT=./node_modules/.bin/jsonlint 13 | JEST=./node_modules/.bin/jest 14 | CSSNANO=node ./scripts/cssnano.js 15 | ESLINT=./node_modules/.bin/eslint 16 | TSC=./node_modules/.bin/tsc 17 | SPEC_CHECKSUM=`md5sum __tests__/terminal.spec.js | cut -d' ' -f 1` 18 | COMMIT=`git log -n 1 | grep '^commit' | sed 's/commit //'` 19 | TOKEN=cat .github.token | tr -d '\n' 20 | URL=`git config --get remote.origin.url` 21 | skip_re="[xfi]it\\(|[fdx]describe\\(" 22 | UPDATE_CONTRIBUTORS=0 23 | 24 | .PHONY: coverage test coveralls lint.src eslint skipped_tests jsonlint publish lint tscheck publish-guthub emoji 25 | 26 | ALL: Makefile .$(VERSION) terminal.jquery.json bower.json package.json js/jquery.terminal-$(VERSION).js js/jquery.terminal.js js/jquery.terminal-$(VERSION).min.js js/jquery.terminal.min.js js/jquery.terminal.min.js.map css/jquery.terminal-$(VERSION).css css/jquery.terminal-$(VERSION).min.css css/jquery.terminal.min.css css/jquery.terminal.min.css.map css/jquery.terminal.css README.md import.html js/terminal.widget.js css/emoji.css update-contributors 27 | 28 | bower.json: templates/bower.in .$(VERSION) 29 | $(SED) -e "s/{{VER}}/$(VERSION)/g" templates/bower.in > bower.json 30 | 31 | package.json: templates/package.in .$(VERSION) 32 | $(SED) -e "s/{{VER}}/$(VERSION)/g" templates/package.in > package.json 33 | 34 | js/jquery.terminal-$(VERSION).js: js/jquery.terminal-src.js .$(VERSION) 35 | $(GIT) branch | grep '* devel' > /dev/null && $(SED) -e "s/{{VER}}/DEV/g" -e "s/{{DATE}}/$(DATE)/g" js/jquery.terminal-src.js > js/jquery.terminal-$(VERSION).js || $(SED) -e "s/{{VER}}/$(VERSION)/g" -e "s/{{DATE}}/$(DATE)/g" js/jquery.terminal-src.js > js/jquery.terminal-$(VERSION).js 36 | 37 | js/jquery.terminal.js: js/jquery.terminal-$(VERSION).js 38 | $(CP) js/jquery.terminal-$(VERSION).js js/jquery.terminal.js 39 | 40 | js/jquery.terminal-$(VERSION).min.js: js/jquery.terminal.min.js 41 | $(CP) js/jquery.terminal.min.js js/jquery.terminal-$(VERSION).min.js 42 | 43 | js/jquery.terminal.min.js js/jquery.terminal.min.js.map: js/jquery.terminal-$(VERSION).js 44 | $(CD) js && $(UGLIFY) -o jquery.terminal.min.js --comments --mangle --source-map "includeSources,url='jquery.terminal.min.js.map'" -- jquery.terminal.js 45 | 46 | css/jquery.terminal-$(VERSION).css: css/jquery.terminal-src.css .$(VERSION) 47 | $(GIT) branch | grep '* devel' > /dev/null && $(SED) -e "s/{{VER}}/DEV/g" -e "s/{{DATE}}/$(DATE)/g" css/jquery.terminal-src.css > css/jquery.terminal-$(VERSION).css || $(SED) -e "s/{{VER}}/$(VERSION)/g" -e "s/{{DATE}}/$(DATE)/g" css/jquery.terminal-src.css > css/jquery.terminal-$(VERSION).css 48 | 49 | css/jquery.terminal.css: css/jquery.terminal-$(VERSION).css .$(VERSION) 50 | $(CP) css/jquery.terminal-$(VERSION).css css/jquery.terminal.css 51 | 52 | css/jquery.terminal.min.css css/jquery.terminal.min.css.map: css/jquery.terminal.css 53 | $(CSSNANO) css/jquery.terminal.css css/jquery.terminal.min.css 54 | 55 | css/jquery.terminal-$(VERSION).min.css: css/jquery.terminal.min.css 56 | $(CP) css/jquery.terminal.min.css css/jquery.terminal-$(VERSION).min.css 57 | 58 | README.md: templates/README.in .$(VERSION) __tests__/terminal.spec.js 59 | $(GIT) branch | grep '* devel' > /dev/null && $(SED) -e "s/{{VER}}/DEV/g" -e \ 60 | "s/{{BRANCH}}/$(BRANCH)/g" -e "s/{{CHECKSUM}}/$(SPEC_CHECKSUM)/" \ 61 | -e "s/{{COMMIT}}/$(COMMIT)/g" < templates/README.in > README.md || $(SED) -e \ 62 | "s/{{VER}}/$(VERSION)/g" -e "s/{{BRANCH}}/$(BRANCH)/g" -e \ 63 | "s/{{CHECKSUM}}/$(SPEC_CHECKSUM)/" -e "s/{{COMMIT}}/$(COMMIT)/g" < templates/README.in > README.md 64 | 65 | .$(VERSION): Makefile 66 | touch .$(VERSION) 67 | 68 | Makefile: templates/Makefile.in 69 | $(SED) -e "s/{{VER""SION}}/"$(VERSION)"/" templates/Makefile.in > Makefile 70 | 71 | import.html: templates/import.in 72 | $(SED) -e "s/{{BRANCH}}/$(BRANCH)/g" templates/import.in > import.html 73 | 74 | js/terminal.widget.js: js/terminal.widget.in 75 | $(GIT) branch | grep '* devel' > /dev/null || $(SED) -e "s/{{VER}}/$(VERSION)/g" js/terminal.widget.in > js/terminal.widget.js 76 | 77 | terminal.jquery.json: manifest .$(VERSION) 78 | $(SED) -e "s/{{VER}}/$(VERSION)/g" manifest > terminal.jquery.json 79 | 80 | css/emoji.css: ./scripts/mkemoji .$(VERSION) 81 | ./scripts/mkemoji $(VERSION) > css/emoji.css 82 | 83 | emoji: 84 | ./scripts/mkemoji $(VERSION) > css/emoji.css 85 | 86 | test: 87 | $(JEST) --coverage --testMatch '**/__tests__/*.spec.js' 88 | 89 | coveralls: 90 | $(CAT) ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js 91 | 92 | lint.src: 93 | $(ESLINT) js/jquery.terminal-src.js 94 | 95 | eslint: 96 | $(ESLINT) js/jquery.terminal-src.js 97 | $(ESLINT) js/dterm.js 98 | $(ESLINT) js/xml_formatting.js 99 | $(ESLINT) js/unix_formatting.js 100 | $(ESLINT) js/prism.js 101 | $(ESLINT) js/less.js 102 | $(ESLINT) js/emoji.js 103 | $(ESLINT) js/pipe.js 104 | $(ESLINT) js/autocomplete_menu.js 105 | $(ESLINT) js/echo_newline.js 106 | 107 | skipped_tests: 108 | @! grep -E $(skip_re) __tests__/terminal.spec.js 109 | 110 | tscheck: 111 | $(TSC) --noEmit --project tsconfig.json 112 | 113 | jsonlint: package.json bower.json 114 | $(JSONLINT) -cq package.json 115 | $(JSONLINT) -cq bower.json 116 | 117 | npm: 118 | test -e npm && ( $(CD) npm && $(GIT) pull ) || true 119 | test -e npm || $(GIT) clone $(URL) --depth 1 npm 120 | 121 | publish: npm 122 | $(CD) npm && $(NPM) publish 123 | 124 | publish-guthub: .github.token 125 | $(SED) "s/{{TOKEN}}/`$(TOKEN)`/" templates/npmrc.tmpl > .npmrc 126 | $(SED) -e "s/{{VER}}/$(VERSION)/g" templates/package.git > package.json 127 | 128 | contributors.json: 129 | ./scripts/contributors.js -u jcubic -r jquery.terminal > contributors.json 130 | 131 | contributors-www.json: 132 | ./scripts/contributors.js -u jcubic -r jquery.terminal-www > contributors-www.json 133 | 134 | contributors: contributors-www.json contributors.json 135 | ./scripts/update-contributors-readme contributors.json "CONTRIBUTORS" templates/README.in 136 | ./scripts/update-contributors-readme contributors-www.json "CONTRIBUTORS-WWW" templates/README.in 137 | ./scripts/update-contributors-readme contributors-www.json "CONTRIBUTORS" www/README.md 138 | ./scripts/update-contributors-package.js -j contributors.json -f templates/package.in 139 | ./scripts/update-contributors-package.js -j contributors.json -f templates/package.git 140 | 141 | lint: eslint jsonlint 142 | 143 | checkout: 144 | @git status | sed "1,/not staged/d" | grep modified | sed "s/.*modified:\s*\(.*\)/\1/" | tr '\n' ' ' | sed -e "s/.*/git checkout &; touch &/" | bash 145 | 146 | 147 | update-contributors: 148 | @if [ $(UPDATE_CONTRIBUTORS) = 1 ]; then\ 149 | echo -e "\x1b[31mUpdate Contributors\x1b[m";\ 150 | if [ $(BRANCH) = 'master' ]; then \ 151 | false;\ 152 | fi;\ 153 | fi 154 | -------------------------------------------------------------------------------- /templates/Makefile.in: -------------------------------------------------------------------------------- 1 | VERSION={{VERSION}} 2 | SED=sed 3 | CD=cd 4 | NPM=npm 5 | CP=cp 6 | RM=rm 7 | CAT=cat 8 | DATE=`date -uR` 9 | GIT=git 10 | BRANCH=`git branch | grep '^*' | sed 's/* //'` 11 | UGLIFY=../node_modules/.bin/uglifyjs 12 | JSONLINT=./node_modules/.bin/jsonlint 13 | JEST=./node_modules/.bin/jest 14 | CSSNANO=node ./scripts/cssnano.js 15 | ESLINT=./node_modules/.bin/eslint 16 | TSC=./node_modules/.bin/tsc 17 | SPEC_CHECKSUM=`md5sum __tests__/terminal.spec.js | cut -d' ' -f 1` 18 | COMMIT=`git log -n 1 | grep '^commit' | sed 's/commit //'` 19 | TOKEN=cat .github.token | tr -d '\n' 20 | URL=`git config --get remote.origin.url` 21 | skip_re="[xfi]it\\(|[fdx]describe\\(" 22 | UPDATE_CONTRIBUTORS=0 23 | 24 | .PHONY: coverage test coveralls lint.src eslint skipped_tests jsonlint publish lint tscheck publish-guthub emoji 25 | 26 | ALL: Makefile .$(VERSION) terminal.jquery.json bower.json package.json js/jquery.terminal-$(VERSION).js js/jquery.terminal.js js/jquery.terminal-$(VERSION).min.js js/jquery.terminal.min.js js/jquery.terminal.min.js.map css/jquery.terminal-$(VERSION).css css/jquery.terminal-$(VERSION).min.css css/jquery.terminal.min.css css/jquery.terminal.min.css.map css/jquery.terminal.css README.md import.html js/terminal.widget.js css/emoji.css update-contributors 27 | 28 | bower.json: templates/bower.in .$(VERSION) 29 | $(SED) -e "s/{{VER}}/$(VERSION)/g" templates/bower.in > bower.json 30 | 31 | package.json: templates/package.in .$(VERSION) 32 | $(SED) -e "s/{{VER}}/$(VERSION)/g" templates/package.in > package.json 33 | 34 | js/jquery.terminal-$(VERSION).js: js/jquery.terminal-src.js .$(VERSION) 35 | $(GIT) branch | grep '* devel' > /dev/null && $(SED) -e "s/{{VER}}/DEV/g" -e "s/{{DATE}}/$(DATE)/g" js/jquery.terminal-src.js > js/jquery.terminal-$(VERSION).js || $(SED) -e "s/{{VER}}/$(VERSION)/g" -e "s/{{DATE}}/$(DATE)/g" js/jquery.terminal-src.js > js/jquery.terminal-$(VERSION).js 36 | 37 | js/jquery.terminal.js: js/jquery.terminal-$(VERSION).js 38 | $(CP) js/jquery.terminal-$(VERSION).js js/jquery.terminal.js 39 | 40 | js/jquery.terminal-$(VERSION).min.js: js/jquery.terminal.min.js 41 | $(CP) js/jquery.terminal.min.js js/jquery.terminal-$(VERSION).min.js 42 | 43 | js/jquery.terminal.min.js js/jquery.terminal.min.js.map: js/jquery.terminal-$(VERSION).js 44 | $(CD) js && $(UGLIFY) -o jquery.terminal.min.js --comments --mangle --source-map "includeSources,url='jquery.terminal.min.js.map'" -- jquery.terminal.js 45 | 46 | css/jquery.terminal-$(VERSION).css: css/jquery.terminal-src.css .$(VERSION) 47 | $(GIT) branch | grep '* devel' > /dev/null && $(SED) -e "s/{{VER}}/DEV/g" -e "s/{{DATE}}/$(DATE)/g" css/jquery.terminal-src.css > css/jquery.terminal-$(VERSION).css || $(SED) -e "s/{{VER}}/$(VERSION)/g" -e "s/{{DATE}}/$(DATE)/g" css/jquery.terminal-src.css > css/jquery.terminal-$(VERSION).css 48 | 49 | css/jquery.terminal.css: css/jquery.terminal-$(VERSION).css .$(VERSION) 50 | $(CP) css/jquery.terminal-$(VERSION).css css/jquery.terminal.css 51 | 52 | css/jquery.terminal.min.css css/jquery.terminal.min.css.map: css/jquery.terminal.css 53 | $(CSSNANO) css/jquery.terminal.css css/jquery.terminal.min.css 54 | 55 | css/jquery.terminal-$(VERSION).min.css: css/jquery.terminal.min.css 56 | $(CP) css/jquery.terminal.min.css css/jquery.terminal-$(VERSION).min.css 57 | 58 | README.md: templates/README.in .$(VERSION) __tests__/terminal.spec.js 59 | $(GIT) branch | grep '* devel' > /dev/null && $(SED) -e "s/{{VER}}/DEV/g" -e \ 60 | "s/{{BRANCH}}/$(BRANCH)/g" -e "s/{{CHECKSUM}}/$(SPEC_CHECKSUM)/" \ 61 | -e "s/{{COMMIT}}/$(COMMIT)/g" < templates/README.in > README.md || $(SED) -e \ 62 | "s/{{VER}}/$(VERSION)/g" -e "s/{{BRANCH}}/$(BRANCH)/g" -e \ 63 | "s/{{CHECKSUM}}/$(SPEC_CHECKSUM)/" -e "s/{{COMMIT}}/$(COMMIT)/g" < templates/README.in > README.md 64 | 65 | .$(VERSION): Makefile 66 | touch .$(VERSION) 67 | 68 | Makefile: templates/Makefile.in 69 | $(SED) -e "s/{{VER""SION}}/"$(VERSION)"/" templates/Makefile.in > Makefile 70 | 71 | import.html: templates/import.in 72 | $(SED) -e "s/{{BRANCH}}/$(BRANCH)/g" templates/import.in > import.html 73 | 74 | js/terminal.widget.js: js/terminal.widget.in 75 | $(GIT) branch | grep '* devel' > /dev/null || $(SED) -e "s/{{VER}}/$(VERSION)/g" js/terminal.widget.in > js/terminal.widget.js 76 | 77 | terminal.jquery.json: manifest .$(VERSION) 78 | $(SED) -e "s/{{VER}}/$(VERSION)/g" manifest > terminal.jquery.json 79 | 80 | css/emoji.css: ./scripts/mkemoji .$(VERSION) 81 | ./scripts/mkemoji $(VERSION) > css/emoji.css 82 | 83 | emoji: 84 | ./scripts/mkemoji $(VERSION) > css/emoji.css 85 | 86 | test: 87 | $(JEST) --coverage --testMatch '**/__tests__/*.spec.js' 88 | 89 | coveralls: 90 | $(CAT) ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js 91 | 92 | lint.src: 93 | $(ESLINT) js/jquery.terminal-src.js 94 | 95 | eslint: 96 | $(ESLINT) js/jquery.terminal-src.js 97 | $(ESLINT) js/dterm.js 98 | $(ESLINT) js/xml_formatting.js 99 | $(ESLINT) js/unix_formatting.js 100 | $(ESLINT) js/prism.js 101 | $(ESLINT) js/less.js 102 | $(ESLINT) js/emoji.js 103 | $(ESLINT) js/pipe.js 104 | $(ESLINT) js/autocomplete_menu.js 105 | $(ESLINT) js/echo_newline.js 106 | 107 | skipped_tests: 108 | @! grep -E $(skip_re) __tests__/terminal.spec.js 109 | 110 | tscheck: 111 | $(TSC) --noEmit --project tsconfig.json 112 | 113 | jsonlint: package.json bower.json 114 | $(JSONLINT) -cq package.json 115 | $(JSONLINT) -cq bower.json 116 | 117 | npm: 118 | test -e npm && ( $(CD) npm && $(GIT) pull ) || true 119 | test -e npm || $(GIT) clone $(URL) --depth 1 npm 120 | 121 | publish: npm 122 | $(CD) npm && $(NPM) publish 123 | 124 | publish-guthub: .github.token 125 | $(SED) "s/{{TOKEN}}/`$(TOKEN)`/" templates/npmrc.tmpl > .npmrc 126 | $(SED) -e "s/{{VER}}/$(VERSION)/g" templates/package.git > package.json 127 | 128 | contributors.json: 129 | ./scripts/contributors.js -u jcubic -r jquery.terminal > contributors.json 130 | 131 | contributors-www.json: 132 | ./scripts/contributors.js -u jcubic -r jquery.terminal-www > contributors-www.json 133 | 134 | contributors: contributors-www.json contributors.json 135 | ./scripts/update-contributors-readme contributors.json "CONTRIBUTORS" templates/README.in 136 | ./scripts/update-contributors-readme contributors-www.json "CONTRIBUTORS-WWW" templates/README.in 137 | ./scripts/update-contributors-readme contributors-www.json "CONTRIBUTORS" www/README.md 138 | ./scripts/update-contributors-package.js -j contributors.json -f templates/package.in 139 | ./scripts/update-contributors-package.js -j contributors.json -f templates/package.git 140 | 141 | lint: eslint jsonlint 142 | 143 | checkout: 144 | @git status | sed "1,/not staged/d" | grep modified | sed "s/.*modified:\s*\(.*\)/\1/" | tr '\n' ' ' | sed -e "s/.*/git checkout &; touch &/" | bash 145 | 146 | 147 | update-contributors: 148 | @if [ $(UPDATE_CONTRIBUTORS) = 1 ]; then\ 149 | echo -e "\x1b[31mUpdate Contributors\x1b[m";\ 150 | if [ $(BRANCH) = 'master' ]; then \ 151 | false;\ 152 | fi;\ 153 | fi 154 | -------------------------------------------------------------------------------- /js/autocomplete_menu.js: -------------------------------------------------------------------------------- 1 | /**@license 2 | * __ _____ ________ __ 3 | * / // _ /__ __ _____ ___ __ _/__ ___/__ ___ ______ __ __ __ ___ / / 4 | * __ / // // // // // _ // _// // / / // _ // _// // // \/ // _ \/ / 5 | * / / // // // // // ___// / / // / / // ___// / / / / // // /\ // // / /__ 6 | * \___//____ \\___//____//_/ _\_ / /_//____//_/ /_/ /_//_//_/ /_/ \__\_\___/ 7 | * \/ /____/ 8 | * http://terminal.jcubic.pl 9 | * 10 | * Wrapper for options that will create autocomplete menu for jQuery Terminal 11 | * 12 | * Copyright (c) 2014-2019 Jakub Jankiewicz 13 | * Released under the MIT license 14 | * 15 | */ 16 | /* global define, global, require, module, setTimeout, clearTimeout */ 17 | (function(factory) { 18 | var root = typeof window !== 'undefined' ? window : global; 19 | if (typeof define === 'function' && define.amd) { 20 | // AMD. Register as an anonymous module. 21 | // istanbul ignore next 22 | define(['jquery', 'jquery.terminal'], factory); 23 | } else if (typeof module === 'object' && module.exports) { 24 | // Node/CommonJS 25 | module.exports = function(root, jQuery) { 26 | if (jQuery === undefined) { 27 | // require('jQuery') returns a factory that requires window to 28 | // build a jQuery instance, we normalize how we use modules 29 | // that require this pattern but the window provided is a noop 30 | // if it's defined (how jquery works) 31 | if (typeof window !== 'undefined') { 32 | jQuery = require('jquery'); 33 | } else { 34 | jQuery = require('jquery')(root); 35 | } 36 | } 37 | if (!jQuery.fn.terminal) { 38 | if (typeof window !== 'undefined') { 39 | require('jquery.terminal'); 40 | } else { 41 | require('jquery.terminal')(jQuery); 42 | } 43 | } 44 | factory(jQuery); 45 | return jQuery; 46 | }; 47 | } else { 48 | // Browser 49 | // istanbul ignore next 50 | factory(root.jQuery); 51 | } 52 | })(function($) { 53 | var jquery_terminal = $.fn.terminal; 54 | $.fn.terminal = function(interpreter, options) { 55 | function init(node) { 56 | return jquery_terminal.call(node, interpreter, autocomplete_menu(options)); 57 | } 58 | if (this.length > 1) { 59 | return this.each(init.bind(null, this)); 60 | } else { 61 | return init(this); 62 | } 63 | }; 64 | // ----------------------------------------------------------------------------------- 65 | // :: cancableble task for usage in comletion menu to ignore previous async completion 66 | // ----------------------------------------------------------------------------------- 67 | function Task(fn) { 68 | this._fn = fn; 69 | } 70 | Task.prototype.invoke = function() { 71 | if (!this._cancel) { 72 | this._fn.apply(null, arguments); 73 | } 74 | }; 75 | Task.prototype.cancel = function() { 76 | this._cancel = true; 77 | }; 78 | // ----------------------------------------------------------------------------------- 79 | // :: function return patched terminal settings 80 | // ----------------------------------------------------------------------------------- 81 | function autocomplete_menu(options) { 82 | if (options && !options.autocompleteMenu) { 83 | return options; 84 | } 85 | var settings = options || {}; 86 | var last_task; 87 | // ------------------------------------------------------------------------------- 88 | // :: function that do actuall matching and displaying of completion menu 89 | // ------------------------------------------------------------------------------- 90 | function complete_menu(term, e, word, list) { 91 | var matched = []; 92 | var regex = new RegExp('^' + $.terminal.escape_regex(word)); 93 | for (var i = list.length; i--;) { 94 | if (regex.test(list[i])) { 95 | matched.unshift(list[i]); 96 | } 97 | } 98 | if (e.which === 9) { 99 | if (term.complete(matched)) { 100 | word = term.before_cursor(true); 101 | regex = new RegExp('^' + $.terminal.escape_regex(word)); 102 | } 103 | } 104 | if (word && matched.length) { 105 | ul.hide(); 106 | for (i = 0; i < matched.length; ++i) { 107 | var text = matched[i].replace(regex, ''); 108 | if (text) { 109 | $('
  • ' + text + '
  • ').appendTo(ul); 110 | } 111 | } 112 | ul.show(); 113 | } 114 | } 115 | var ul; 116 | if (typeof settings.completion !== 'undefined') { 117 | var onInit = settings.onInit || $.noop; 118 | var keydown = settings.keydown || $.noop; 119 | var completion = settings.completion; 120 | delete settings.completion; 121 | settings.onInit = function(term) { 122 | onInit.call(this, term); 123 | // init html menu element 124 | var wrapper = this.cmd().find('.cmd-cursor'). 125 | wrap('').parent().addClass('cursor-wrapper'); 126 | ul = $('
      ').appendTo(wrapper); 127 | ul.on('click', 'li', function() { 128 | term.insert($(this).text()); 129 | ul.empty(); 130 | }); 131 | }; 132 | var timer; 133 | settings.keydown = function(e, term) { 134 | // setTimeout because terminal is adding characters in keypress 135 | // we use keydown because we need to prevent default action 136 | // for tab and still execute custom code 137 | clearTimeout(timer); 138 | timer = setTimeout(function() { 139 | ul.empty(); 140 | var word = term.before_cursor(true); 141 | if (last_task) { 142 | last_task.cancel(); // ignore previous completion task 143 | } 144 | // we save task in closure for callbacks and promise::then 145 | var task = last_task = new Task(complete_menu); 146 | if (typeof completion === 'function') { 147 | var ret = completion.call(term, word, function(list) { 148 | task.invoke(term, e, word, list); 149 | }); 150 | if (ret && typeof ret.then === 'function') { 151 | ret.then(function(completion) { 152 | task.invoke(term, e, word, completion); 153 | }); 154 | } else if (ret instanceof Array) { 155 | task.invoke(term, e, word, ret); 156 | } 157 | } else if (completion instanceof Array) { 158 | task.invoke(term, e, word, completion); 159 | } 160 | }, 0); 161 | var ret = keydown.call(this, e, term); 162 | if (typeof ret !== 'undefined') { 163 | return false; 164 | } 165 | if (e.which === 9) { 166 | return false; 167 | } 168 | }; 169 | } 170 | return settings; 171 | } 172 | }); 173 | -------------------------------------------------------------------------------- /js/prism.js: -------------------------------------------------------------------------------- 1 | /**@license 2 | * __ _____ ________ __ 3 | * / // _ /__ __ _____ ___ __ _/__ ___/__ ___ ______ __ __ __ ___ / / 4 | * __ / // // // // // _ // _// // / / // _ // _// // // \/ // _ \/ / 5 | * / / // // // // // ___// / / // / / // ___// / / / / // // /\ // // / /__ 6 | * \___//____ \\___//____//_/ _\_ / /_//____//_/ /_/ /_//_//_/ /_/ \__\_\___/ 7 | * \/ /____/ 8 | * http://terminal.jcubic.pl 9 | * 10 | * this is utility that monkey patch Prism functions to output 11 | * terminal formatting (it was first created here https://codepen.io/jcubic/pen/zEyxjJ) 12 | * 13 | * usage: 14 | * 15 | * you need to include both css and js (it need to be before this file) 16 | * 17 | * js code: 18 | * 19 | * code = $.terminal.escape_brackets(code); 20 | * code = $.terminal.prism(language, code); 21 | * 22 | * term.echo(code); // or term.less(code) if you include less.js 23 | * 24 | * you can also use helper that will create formatter 25 | * 26 | * $.terminal.syntax(language); 27 | * 28 | * there is one extra language 'website' that format html with script and style tags 29 | * 30 | * by default only javascript markup and css languages are defined (also file extension 31 | * for them. To have more languages you need to include appropriate js files. 32 | * 33 | * Copyright (c) 2018-2019 Jakub Jankiewicz 34 | * Released under the MIT license 35 | * 36 | */ 37 | /* global define, global, require, module */ 38 | (function(factory, undefined) { 39 | var root = typeof window !== 'undefined' ? window : global; 40 | if (typeof define === 'function' && define.amd) { 41 | // AMD. Register as an anonymous module. 42 | // istanbul ignore next 43 | define(['jquery', 'prismjs', 'jquery.terminal'], factory); 44 | } else if (typeof module === 'object' && module.exports) { 45 | // Node/CommonJS 46 | module.exports = function(root, jQuery, Prism) { 47 | if (Prism === undefined) { 48 | Prism = require('prismjs'); 49 | } 50 | if (jQuery === undefined) { 51 | // require('jQuery') returns a factory that requires window to 52 | // build a jQuery instance, we normalize how we use modules 53 | // that require this pattern but the window provided is a noop 54 | // if it's defined (how jquery works) 55 | if (window !== undefined) { 56 | jQuery = require('jquery'); 57 | } else { 58 | jQuery = require('jquery')(root); 59 | } 60 | } 61 | if (!jQuery.fn.terminal) { 62 | if (window !== undefined) { 63 | require('jquery.terminal'); 64 | } else { 65 | require('jquery.terminal')(jQuery); 66 | } 67 | } 68 | factory(jQuery, Prism); 69 | return jQuery; 70 | }; 71 | } else { 72 | // Browser 73 | // istanbul ignore next 74 | factory(root.jQuery, root.Prism); 75 | } 76 | })(function($, Prism) { 77 | var Token = Prism.Token; 78 | if (typeof Prism === 'undefined') { 79 | throw new Error('PrismJS not defined'); 80 | } 81 | var _ = $.extend({}, Prism); 82 | 83 | _.Token = function() { 84 | Token.apply(this, [].slice.call(arguments)); 85 | }; 86 | _.Token.stringify = function(o, language, parent) { 87 | if (typeof o === 'string') { 88 | return o; 89 | } 90 | 91 | if (_.util.type(o) === 'Array') { 92 | return o.map(function(element) { 93 | return _.Token.stringify(element, language, o); 94 | }).join(''); 95 | } 96 | 97 | var env = { 98 | content: _.Token.stringify(o.content, language, parent), 99 | tag: 'span', 100 | classes: ['token', o.type], 101 | attributes: {}, 102 | language: language, 103 | parent: parent 104 | }; 105 | 106 | if (env.type === 'comment') { 107 | env.attributes['spellcheck'] = 'true'; 108 | } 109 | 110 | if (o.alias) { 111 | var aliases = _.util.type(o.alias) === 'Array' ? o.alias : [o.alias]; 112 | Array.prototype.push.apply(env.classes, aliases); 113 | } 114 | 115 | _.hooks.run('wrap', env); 116 | 117 | return env.content.split(/\n/).map(function(content) { 118 | if (content) { 119 | return '\x00\x00\x00\x00[[b;;;' + env.classes.join(' ') + ']' + 120 | $.terminal.escape_brackets(content).replace(/\\/g, '\') 121 | + '\x00\x00\x00\x00]'; 122 | } 123 | return ''; 124 | }).join('\n'); 125 | }; 126 | if (!$) { 127 | throw new Error('jQuery Not defined'); 128 | } 129 | if (!$.terminal) { 130 | throw new Error('$.terminal is not defined'); 131 | } 132 | // we use 0x00 character so we know which one of the formatting came from prism 133 | // so we can escape the reset because we unescape original values, the values 134 | // need to be escape in cmd plugin so you can't type in formatting 135 | /* eslint-disable */ 136 | var format_split_re = /(\x00\x00\x00\x00(?:\[\[[!gbiuso]*;[^;]*;[^\]]*\](?:[^\]\\]*(\\\\)*\\\][^\]]*|[^\]]*|[^[]*\[[^\]]*)\]?|\]))/i; 137 | /* eslint-enable */ 138 | $.terminal.prism = function prism(language, string) { 139 | if (language === 'website') { 140 | var re = /(<\/?\s*(?:script|style)[^>]*>)/g; 141 | var style; 142 | var script; 143 | return string.split(re).filter(Boolean).map(function(string) { 144 | if (script) { 145 | script = false; 146 | return $.terminal.prism('javascript', string); 147 | } else if (style) { 148 | style = false; 149 | return $.terminal.prism('css', string); 150 | } 151 | if (string.match(/^ 74 | 75 | ``` 76 | 77 | 78 | Then include js/jquery.terminal-{{VER}}.min.js and css/jquery.terminal-{{VER}}.min.css 79 | 80 | You can grab the files from CDN: 81 | 82 | ```html 83 | 84 | 85 | ``` 86 | 87 | or 88 | 89 | ```html 90 | 91 | 92 | ``` 93 | 94 | If you always want latest version, you can get it from [unpkg](https://unpkg.com/) without specifying version, 95 | it will redirect to the latest ones: 96 | 97 | 98 | ```html 99 | 100 | 101 | ``` 102 | 103 | #### Bleeding Edge Version 104 | 105 | If you want to test bleeding edge, development version of jQuery Terminal. You can use those files: 106 | 107 | ```html 108 | 109 | 110 | ``` 111 | 112 | but the service will be [shutdown in October 2019](https://rawgit.com/), and it don't accept new files. Great things 113 | about rawgit that (at least when you don't put cdn subdomain) you can get lastest version very fast after the commit 114 | is pushed on GitHub (sometimes you need to add no cache query string, anything unique, for faster refresh). 115 | 116 | there is also alternative from jsdelivr: 117 | 118 | ```html 119 | 120 | 121 | ``` 122 | 123 | but it's not refreshed as fast as rawgit does, because it's CDN and need to be propagated to different servers. 124 | 125 | #### Keyboard key polyfill 126 | 127 | **NOTE:** From version 1.0.0 if you want to support old browsers then you'll need to use [key event property polyfill](https://rawgit.com/inexorabletash/polyfill/master/keyboard.js). You can check the support for it on [can I use](https://caniuse.com/#feat=keyboardevent-key) (as you can see in chart it's required by Android so it's good to add). 128 | 129 | ```html 130 | 131 | ``` 132 | 133 | or 134 | 135 | ```html 136 | 137 | ``` 138 | 139 | #### Command Line 140 | 141 | 142 | You can also install jQuery Terminal using command line, from [bower repository](https://bower.io/): 143 | 144 | ``` 145 | bower install jquery.terminal 146 | ``` 147 | 148 | or [npm registry](https://www.npmjs.com/): 149 | 150 | ``` 151 | npm install jquery.terminal 152 | ``` 153 | 154 | 155 | ### Example of usage 156 | 157 | This is code that uses low level function, that gives you full control of the commands, 158 | just pass anything that the user types into a function. 159 | 160 | ```javascript 161 | jQuery(function($, undefined) { 162 | $('#term_demo').terminal(function(command) { 163 | if (command !== '') { 164 | var result = window.eval(command); 165 | if (result != undefined) { 166 | this.echo(String(result)); 167 | } 168 | } 169 | }, { 170 | greetings: 'Javascript Interpreter', 171 | name: 'js_demo', 172 | height: 200, 173 | width: 450, 174 | prompt: 'js> ' 175 | }); 176 | }); 177 | ``` 178 | 179 | Here is a higher level call, using an object as an interpreter, By default the terminal will 180 | parse commands that a user types and replace number like strings with real numbers 181 | regex with regexes and process escape characters in double quoted strings. 182 | 183 | ```javascript 184 | jQuery(function($, undefined) { 185 | $('#term_demo').terminal({ 186 | add: function(a, b) { 187 | this.echo(a + b); 188 | }, 189 | foo: 'foo.php', 190 | bar: { 191 | sub: function(a, b) { 192 | this.echo(a - b); 193 | } 194 | } 195 | }, { 196 | height: 200, 197 | width: 450, 198 | prompt: 'demo> ' 199 | }); 200 | }); 201 | ``` 202 | 203 | Command foo will execute json-rpc from foo.php file. 204 | 205 | You can create JSON-RPC interpreter with authentication in just one line: 206 | 207 | ```javascript 208 | $('#term_demo').terminal('service.php', {login: true}); 209 | ``` 210 | 211 | More examples [here](http://terminal.jcubic.pl/examples.php). You can also check 212 | [Full Documentation](http://terminal.jcubic.pl/api_reference.php) or 213 | [Getting Started Guide in Wiki](https://github.com/jcubic/jquery.terminal/wiki/Getting-Started). 214 | 215 | ### Security 216 | 217 | Because of security in version 1.20.0 links with protocols different then ftp or http(s) (it was 218 | possible to enter javascript protocol, that could lead to XSS if author of hte app echo user input 219 | and save it in DB) was turn off by default. To enable it, you need to use `anyLinks: true` option. 220 | 221 | In version 1.21.0 executing terminal methods using extendend commands `[[ terminal::clear() ]]` was 222 | also disabled by default because attacker (depending on your application) could execute 223 | `terminal::echo` with raw option to enter any html and execute any javascript. To enable this 224 | feature from this version you need to use `invokeMethods: true` option. 225 | 226 | The features are safe to enable, if you don't save user input in DB and don't echo it back to 227 | different users (like with chat application). It's also safe if you escape formatting before you 228 | echo stuff. 229 | 230 | If you don't save user input in DB but allow to echo back what user types and have enabled 231 | `execHash` options, you may have reflected XSS vulnerability if you enable this features. If you 232 | escape formatting this options are also safe. 233 | 234 | **NOTE**: To disable exec if you have `execHash` (or echo stuff from users with `invokeMethods: true`), 235 | you can also set option `{exec: false}` to your `echo` call and use it only when you get 236 | values from server (not from DB indireclty from users). If you do this you will be able to echo stuff 237 | from users and execute terminal methods from server (this feature is mostly done just for that). 238 | 239 | ### Contributors 240 | 241 | If you want to contrubite read [CONTRIBUTING.md](CONTRIBUTING.md) first. Here are project contributors: 242 | 243 | 244 | | [
      Jakub T. Jankiewicz](https://jcubic.pl/me)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=jcubic) | [
      Zuo Qiyang](http://zuoqy.com)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=kid1412z) | [
      Marcel Link](https://github.com/ml1nk)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=ml1nk) | [
      Sébastien Warin](http://sebastien.warin.fr)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=sebastienwarin) | [
      Christopher John Ryan](https://github.com/ChrisJohnRyan)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=ChrisJohnRyan) | [
      Johan](https://github.com/johanjordaan)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=johanjordaan) | [
      Florian Schäfer](https://github.com/fschaefer)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=fschaefer) | 245 | | :---: | :---: | :---: | :---: | :---: | :---: | :---: | 246 | | [
      David Refoua](http://www.Refoua.me)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=DRSDavidSoft) | [
      Ishan Ratnapala](https://github.com/IshanRatnapala)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=IshanRatnapala) | [
      Tomasz Ducin](http://ducin.it)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=ducin) | [
      Abdelrahman Omran](https://omranic.com)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=Omranic) | [
      Anton Vasil'ev](https://github.com/avdes)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=avdes) | [
      finlob](https://github.com/finlob)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=finlob) | [
      Hraban Luyat](https://luyat.com)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=hraban) | 247 | | [
      Jon Steinich](https://github.com/jsteinich)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=jsteinich) | [
      Martin v. Löwis](https://github.com/loewis)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=loewis) | [
      Mateusz Paprocki](https://github.com/mattpap)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=mattpap) | [
      exit1](https://github.com/exit1)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=exit1) | [
      Robert Wikman](https://github.com/rbw)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=rbw) | [
      Steve Phillips](https://tryingtobeawesome.com/)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=elimisteve) | [
      Yutong Luo](https://yutongluo.com)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=yutongluo) | 248 | | [
      coderaiser](http://coderaiser.github.io)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=coderaiser) | [
      mrkaiser](https://github.com/mrkaiser)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=mrkaiser) | [
      stereobooster](https://stereobooster.com)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=stereobooster) | [
      Steve Kirkegard](https://www.linkedin.com/in/steve-kirkegard)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=stevekirks) | [
      Juraj Vitko](https://github.com/youurayy)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=youurayy) | 249 | 250 | 251 | [jQuery Terminal Website](https://github.com/jcubic/jquery.terminal-www) contributors: 252 | 253 | 254 | | [
      Jakub T. Jankiewicz](https://jcubic.pl/me)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=jcubic) | [
      Rich Morin](http://www.cfcl.com/rdm)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=RichMorin) | [
      DInesh51297](https://github.com/DInesh51297)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=DInesh51297) | [
      Logan Rosen](https://www.loganrosen.com/)
      [commits](https://github.com/jcubic/jquery.terminal/commits?author=loganrosen) | 255 | | :---: | :---: | :---: | :---: | 256 | 257 | 258 | 259 | ### License 260 | 261 | Licensed under [MIT](http://opensource.org/licenses/MIT) license 262 | 263 | Copyright (c) 2011-2019 [Jakub Jankiewicz](https://jcubic.pl/jakub-jankiewicz) 264 | --------------------------------------------------------------------------------