├── .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 |
--------------------------------------------------------------------------------