A console for the Web written in completely in JavaScript. The console supports Web versions of some Linux commands. This work is based, in part, on earlier work by Eric Bidelman.
A Pen by Andrew Mitchell Barfield on CodePen.
A console for the Web written in completely in JavaScript. The console supports Web versions of some Linux commands. This work is based, in part, on earlier work by Eric Bidelman.
A Pen by Andrew Mitchell Barfield on CodePen.
| This is the main script for the<br/>"HTML5 Web Terminal" pen. | |
| <!-- See: http://codepen.io/AndrewBarfield/pen/qEqWMq --> |
| var util = util || {}; | |
| util.toArray = function(list) { | |
| return Array.prototype.slice.call(list || [], 0); | |
| }; | |
| var Terminal = Terminal || function(cmdLineContainer, outputContainer) { | |
| window.URL = window.URL || window.webkitURL; | |
| window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; | |
| var cmdLine_ = document.querySelector(cmdLineContainer); | |
| var output_ = document.querySelector(outputContainer); | |
| const CMDS_ = [ | |
| 'cat', 'clear', 'date', 'echo', 'help', 'uname', 'whoami' | |
| ]; | |
| var fs_ = null; | |
| var cwd_ = null; | |
| var history_ = []; | |
| var histpos_ = 0; | |
| var histtemp_ = 0; | |
| window.addEventListener('click', function(e) { | |
| cmdLine_.focus(); | |
| }, false); | |
| cmdLine_.addEventListener('click', inputTextClick_, false); | |
| cmdLine_.addEventListener('keydown', historyHandler_, false); | |
| cmdLine_.addEventListener('keydown', processNewCommand_, false); | |
| // | |
| function inputTextClick_(e) { | |
| this.value = this.value; | |
| } | |
| // | |
| function historyHandler_(e) { | |
| if (history_.length) { | |
| if (e.keyCode == 38 || e.keyCode == 40) { | |
| if (history_[histpos_]) { | |
| history_[histpos_] = this.value; | |
| } else { | |
| histtemp_ = this.value; | |
| } | |
| } | |
| if (e.keyCode == 38) { // up | |
| histpos_--; | |
| if (histpos_ < 0) { | |
| histpos_ = 0; | |
| } | |
| } else if (e.keyCode == 40) { // down | |
| histpos_++; | |
| if (histpos_ > history_.length) { | |
| histpos_ = history_.length; | |
| } | |
| } | |
| if (e.keyCode == 38 || e.keyCode == 40) { | |
| this.value = history_[histpos_] ? history_[histpos_] : histtemp_; | |
| this.value = this.value; // Sets cursor to end of input. | |
| } | |
| } | |
| } | |
| // | |
| function processNewCommand_(e) { | |
| if (e.keyCode == 9) { // tab | |
| e.preventDefault(); | |
| // TODO(ericbidelman): Implement tab suggest. | |
| } else if (e.keyCode == 13) { // enter | |
| // Save shell history. | |
| if (this.value) { | |
| history_[history_.length] = this.value; | |
| histpos_ = history_.length; | |
| } | |
| // Duplicate current input and append to output section. | |
| var line = this.parentNode.parentNode.cloneNode(true); | |
| line.removeAttribute('id') | |
| line.classList.add('line'); | |
| var input = line.querySelector('input.cmdline'); | |
| input.autofocus = false; | |
| input.readOnly = true; | |
| output_.appendChild(line); | |
| // Parse out command, args, and trim off whitespace. | |
| // TODO(ericbidelman): Support multiple comma separated commands. | |
| if (this.value && this.value.trim()) { | |
| var args = this.value.split(' ').filter(function(val, i) { | |
| return val; | |
| }); | |
| var cmd = args[0].toLowerCase(); | |
| args = args.splice(1); // Remove cmd from arg list. | |
| } | |
| switch (cmd) { | |
| case 'cat': | |
| var url = args.join(' '); | |
| if (!url) { | |
| output('Usage: ' + cmd + ' http://s.codepen.io/...'); | |
| output('Example: ' + cmd + ' http://s.codepen.io/AndrewBarfield/pen/LEbPJx.js'); | |
| break; | |
| } | |
| $.get( url, function(data) { | |
| var encodedStr = data.replace(/[\u00A0-\u9999<>\&]/gim, function(i) { | |
| return '&#'+i.charCodeAt(0)+';'; | |
| }); | |
| output('<pre>' + encodedStr + '</pre>'); | |
| }); | |
| break; | |
| case 'clear': | |
| output_.innerHTML = ''; | |
| this.value = ''; | |
| return; | |
| case 'date': | |
| output( new Date() ); | |
| break; | |
| case 'echo': | |
| output( args.join(' ') ); | |
| break; | |
| case 'help': | |
| output('<div class="ls-files">' + CMDS_.join('<br>') + '</div>'); | |
| break; | |
| case 'uname': | |
| output(navigator.appVersion); | |
| break; | |
| case 'whoami': | |
| var result = "<img src=\"" + codehelper_ip["Flag"]+ "\"><br><br>"; | |
| for (var prop in codehelper_ip) | |
| result += prop + ": " + codehelper_ip[prop] + "<br>"; | |
| output(result); | |
| break; | |
| default: | |
| if (cmd) { | |
| output(cmd + ': command not found'); | |
| } | |
| }; | |
| window.scrollTo(0, getDocHeight_()); | |
| this.value = ''; // Clear/setup line for next input. | |
| } | |
| } | |
| // | |
| function formatColumns_(entries) { | |
| var maxName = entries[0].name; | |
| util.toArray(entries).forEach(function(entry, i) { | |
| if (entry.name.length > maxName.length) { | |
| maxName = entry.name; | |
| } | |
| }); | |
| var height = entries.length <= 3 ? | |
| 'height: ' + (entries.length * 15) + 'px;' : ''; | |
| // 12px monospace font yields ~7px screen width. | |
| var colWidth = maxName.length * 7; | |
| return ['<div class="ls-files" style="-webkit-column-width:', | |
| colWidth, 'px;', height, '">']; | |
| } | |
| // | |
| function output(html) { | |
| output_.insertAdjacentHTML('beforeEnd', '<p>' + html + '</p>'); | |
| } | |
| // Cross-browser impl to get document's height. | |
| function getDocHeight_() { | |
| var d = document; | |
| return Math.max( | |
| Math.max(d.body.scrollHeight, d.documentElement.scrollHeight), | |
| Math.max(d.body.offsetHeight, d.documentElement.offsetHeight), | |
| Math.max(d.body.clientHeight, d.documentElement.clientHeight) | |
| ); | |
| } | |
| // | |
| return { | |
| initFS: function() { | |
| output('<img align="left" src="http://www.w3.org/html/logo/downloads/HTML5_Badge_128.png" style="padding: 0px 10px 30px 0px"><h2>HTML5 Web Terminal</h2><p>' + new Date() + '</p><p>Enter "help" for more information.</p>'); | |
| }, | |
| output: output | |
| } | |
| }; |
| /* latin */ | |
| @font-face { | |
| font-family: 'Roboto'; | |
| font-style: normal; | |
| font-weight: 400; | |
| src: local('Roboto Regular'), local('Roboto-Regular'), url(http://fonts.gstatic.com/s/roboto/v14/fg2nPs59wPnJ0blURyMU3PesZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); | |
| unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; | |
| } | |
| body { | |
| margin: 20px; | |
| font: 40px/40px 'Roboto', sans-serif; | |
| color:#fff; | |
| background-color: #593f6b; | |
| } |