diff --git a/dist/addons/attach/attach.js b/dist/addons/attach/attach.js new file mode 100644 index 00000000..8cf759ae --- /dev/null +++ b/dist/addons/attach/attach.js @@ -0,0 +1,114 @@ +/** + * Implements the attach method, that attaches the terminal to a WebSocket stream. + * @module xterm/addons/attach/attach + * @license MIT + */ +(function (attach) { + if (typeof exports === 'object' && typeof module === 'object') { + /* + * CommonJS environment + */ + module.exports = attach(require('../../xterm')); + } + else if (typeof define == 'function') { + /* + * Require.js is available + */ + define(['../../xterm'], attach); + } + else { + /* + * Plain browser environment + */ + attach(window.Terminal); + } +})(function (Xterm) { + 'use strict'; + var exports = {}; + /** + * Attaches the given terminal to the given socket. + * + * @param {Xterm} term - The terminal to be attached to the given socket. + * @param {WebSocket} socket - The socket to attach the current terminal. + * @param {boolean} bidirectional - Whether the terminal should send data + * to the socket as well. + * @param {boolean} buffered - Whether the rendering of incoming data + * should happen instantly or at a maximum + * frequency of 1 rendering per 10ms. + */ + exports.attach = function (term, socket, bidirectional, buffered) { + bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional; + term.socket = socket; + term._flushBuffer = function () { + term.write(term._attachSocketBuffer); + term._attachSocketBuffer = null; + clearTimeout(term._attachSocketBufferTimer); + term._attachSocketBufferTimer = null; + }; + term._pushToBuffer = function (data) { + if (term._attachSocketBuffer) { + term._attachSocketBuffer += data; + } + else { + term._attachSocketBuffer = data; + setTimeout(term._flushBuffer, 10); + } + }; + term._getMessage = function (ev) { + if (buffered) { + term._pushToBuffer(ev.data); + } + else { + term.write(ev.data); + } + }; + term._sendData = function (data) { + socket.send(data); + }; + socket.addEventListener('message', term._getMessage); + if (bidirectional) { + term.on('data', term._sendData); + } + socket.addEventListener('close', term.detach.bind(term, socket)); + socket.addEventListener('error', term.detach.bind(term, socket)); + }; + /** + * Detaches the given terminal from the given socket + * + * @param {Xterm} term - The terminal to be detached from the given socket. + * @param {WebSocket} socket - The socket from which to detach the current + * terminal. + */ + exports.detach = function (term, socket) { + term.off('data', term._sendData); + socket = (typeof socket == 'undefined') ? term.socket : socket; + if (socket) { + socket.removeEventListener('message', term._getMessage); + } + delete term.socket; + }; + /** + * Attaches the current terminal to the given socket + * + * @param {WebSocket} socket - The socket to attach the current terminal. + * @param {boolean} bidirectional - Whether the terminal should send data + * to the socket as well. + * @param {boolean} buffered - Whether the rendering of incoming data + * should happen instantly or at a maximum + * frequency of 1 rendering per 10ms. + */ + Xterm.prototype.attach = function (socket, bidirectional, buffered) { + return exports.attach(this, socket, bidirectional, buffered); + }; + /** + * Detaches the current terminal from the given socket. + * + * @param {WebSocket} socket - The socket from which to detach the current + * terminal. + */ + Xterm.prototype.detach = function (socket) { + return exports.detach(this, socket); + }; + return exports; +}); +//# sourceMappingURL=attach.js.map \ No newline at end of file diff --git a/dist/addons/fit/fit.js b/dist/addons/fit/fit.js new file mode 100644 index 00000000..5ba26746 --- /dev/null +++ b/dist/addons/fit/fit.js @@ -0,0 +1,59 @@ +/** + * Fit terminal columns and rows to the dimensions of its DOM element. + * + * ## Approach + * - Rows: Truncate the division of the terminal parent element height by the terminal row height. + * + * - Columns: Truncate the division of the terminal parent element width by the terminal character + * width (apply display: inline at the terminal row and truncate its width with the current + * number of columns). + * @module xterm/addons/fit/fit + * @license MIT + */ +(function (fit) { + if (typeof exports === 'object' && typeof module === 'object') { + /* + * CommonJS environment + */ + module.exports = fit(require('../../xterm')); + } + else if (typeof define == 'function') { + /* + * Require.js is available + */ + define(['../../xterm'], fit); + } + else { + /* + * Plain browser environment + */ + fit(window.Terminal); + } +})(function (Xterm) { + var exports = {}; + exports.proposeGeometry = function (term) { + var parentElementStyle = window.getComputedStyle(term.element.parentElement), parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')), parentElementWidth = parseInt(parentElementStyle.getPropertyValue('width')), elementStyle = window.getComputedStyle(term.element), elementPaddingVer = parseInt(elementStyle.getPropertyValue('padding-top')) + parseInt(elementStyle.getPropertyValue('padding-bottom')), elementPaddingHor = parseInt(elementStyle.getPropertyValue('padding-right')) + parseInt(elementStyle.getPropertyValue('padding-left')), availableHeight = parentElementHeight - elementPaddingVer, availableWidth = parentElementWidth - elementPaddingHor, container = term.rowContainer, subjectRow = term.rowContainer.firstElementChild, contentBuffer = subjectRow.innerHTML, characterHeight, rows, characterWidth, cols, geometry; + subjectRow.style.display = 'inline'; + subjectRow.innerHTML = 'W'; // Common character for measuring width, although on monospace + characterWidth = subjectRow.getBoundingClientRect().width; + subjectRow.style.display = ''; // Revert style before calculating height, since they differ. + characterHeight = parseInt(subjectRow.offsetHeight); + subjectRow.innerHTML = contentBuffer; + rows = parseInt(availableHeight / characterHeight); + cols = parseInt(availableWidth / characterWidth) - 1; + geometry = { cols: cols, rows: rows }; + return geometry; + }; + exports.fit = function (term) { + var geometry = exports.proposeGeometry(term); + term.resize(geometry.cols, geometry.rows); + }; + Xterm.prototype.proposeGeometry = function () { + return exports.proposeGeometry(this); + }; + Xterm.prototype.fit = function () { + return exports.fit(this); + }; + return exports; +}); +//# sourceMappingURL=fit.js.map \ No newline at end of file diff --git a/dist/addons/fullscreen/fullscreen.css b/dist/addons/fullscreen/fullscreen.css new file mode 100644 index 00000000..60e8c511 --- /dev/null +++ b/dist/addons/fullscreen/fullscreen.css @@ -0,0 +1,10 @@ +.xterm.fullscreen { + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + width: auto; + height: auto; + z-index: 255; +} diff --git a/dist/addons/fullscreen/fullscreen.js b/dist/addons/fullscreen/fullscreen.js new file mode 100644 index 00000000..a3227217 --- /dev/null +++ b/dist/addons/fullscreen/fullscreen.js @@ -0,0 +1,50 @@ +/** + * Fullscreen addon for xterm.js + * @module xterm/addons/fullscreen/fullscreen + * @license MIT + */ +(function (fullscreen) { + if (typeof exports === 'object' && typeof module === 'object') { + /* + * CommonJS environment + */ + module.exports = fullscreen(require('../../xterm')); + } + else if (typeof define == 'function') { + /* + * Require.js is available + */ + define(['../../xterm'], fullscreen); + } + else { + /* + * Plain browser environment + */ + fullscreen(window.Terminal); + } +})(function (Xterm) { + var exports = {}; + /** + * Toggle the given terminal's fullscreen mode. + * @param {Xterm} term - The terminal to toggle full screen mode + * @param {boolean} fullscreen - Toggle fullscreen on (true) or off (false) + */ + exports.toggleFullScreen = function (term, fullscreen) { + var fn; + if (typeof fullscreen == 'undefined') { + fn = (term.element.classList.contains('fullscreen')) ? 'remove' : 'add'; + } + else if (!fullscreen) { + fn = 'remove'; + } + else { + fn = 'add'; + } + term.element.classList[fn]('fullscreen'); + }; + Xterm.prototype.toggleFullscreen = function (fullscreen) { + exports.toggleFullScreen(this, fullscreen); + }; + return exports; +}); +//# sourceMappingURL=fullscreen.js.map \ No newline at end of file diff --git a/dist/addons/linkify/linkify.js b/dist/addons/linkify/linkify.js new file mode 100644 index 00000000..d3a6933d --- /dev/null +++ b/dist/addons/linkify/linkify.js @@ -0,0 +1,165 @@ +/** + * Methods for turning URL subscrings in the terminal's content into links (`a` DOM elements). + * @module xterm/addons/linkify/linkify + * @license MIT + */ +(function (linkify) { + if (typeof exports === 'object' && typeof module === 'object') { + /* + * CommonJS environment + */ + module.exports = linkify(require('../../xterm')); + } + else if (typeof define == 'function') { + /* + * Require.js is available + */ + define(['../../xterm'], linkify); + } + else { + /* + * Plain browser environment + */ + linkify(window.Terminal); + } +})(function (Xterm) { + 'use strict'; + var exports = {}, protocolClause = '(https?:\\/\\/)', domainCharacterSet = '[\\da-z\\.-]+', negatedDomainCharacterSet = '[^\\da-z\\.-]+', domainBodyClause = '(' + domainCharacterSet + ')', tldClause = '([a-z\\.]{2,6})', ipClause = '((\\d{1,3}\\.){3}\\d{1,3})', portClause = '(:\\d{1,5})', hostClause = '((' + domainBodyClause + '\\.' + tldClause + ')|' + ipClause + ')' + portClause + '?', pathClause = '(\\/[\\/\\w\\.-]*)*', negatedPathCharacterSet = '[^\\/\\w\\.-]+', bodyClause = hostClause + pathClause, start = '(?:^|' + negatedDomainCharacterSet + ')(', end = ')($|' + negatedPathCharacterSet + ')', lenientUrlClause = start + protocolClause + '?' + bodyClause + end, strictUrlClause = start + protocolClause + bodyClause + end, lenientUrlRegex = new RegExp(lenientUrlClause), strictUrlRegex = new RegExp(strictUrlClause); + /** + * Converts all valid URLs found in the given terminal line into + * hyperlinks. The terminal line can be either the HTML element itself + * or the index of the termina line in the children of the terminal + * rows container. + * + * @param {Xterm} terminal - The terminal that owns the given line. + * @param {number|HTMLDivElement} line - The terminal line that should get + * "linkified". + * @param {boolean} lenient - The regex type that will be used to identify links. If lenient is + * false, the regex requires a protocol clause. Defaults to true. + * @param {string} target - Sets target="" attribute with value provided to links. + * Default doesn't set target attribute + * @emits linkify + * @emits linkify:line + */ + exports.linkifyTerminalLine = function (terminal, line, lenient, target) { + if (typeof line == 'number') { + line = terminal.rowContainer.children[line]; + } + else if (!(line instanceof HTMLDivElement)) { + var message = 'The "line" argument should be either a number'; + message += ' or an HTMLDivElement'; + throw new TypeError(message); + } + if (typeof target === 'undefined') { + target = ''; + } + else { + target = 'target="' + target + '"'; + } + var buffer = document.createElement('span'), nodes = line.childNodes; + for (var j = 0; j < nodes.length; j++) { + var node = nodes[j], match; + /** + * Since we cannot access the TextNode's HTML representation + * from the instance itself, we assign its data as textContent + * to a dummy buffer span, in order to retrieve the TextNode's + * HTML representation from the buffer's innerHTML. + */ + buffer.textContent = node.data; + var nodeHTML = buffer.innerHTML; + /** + * Apply function only on TextNodes + */ + if (node.nodeType != node.TEXT_NODE) { + continue; + } + var url = exports.findLinkMatch(node.data, lenient); + if (!url) { + continue; + } + var startsWithProtocol = new RegExp('^' + protocolClause), urlHasProtocol = url.match(startsWithProtocol), href = (urlHasProtocol) ? url : 'http://' + url, link = '' + url + '', newHTML = nodeHTML.replace(url, link); + line.innerHTML = line.innerHTML.replace(nodeHTML, newHTML); + } + /** + * This event gets emitted when conversion of all URL susbtrings + * to HTML anchor elements (links) has finished, for a specific + * line of the current Xterm instance. + * + * @event linkify:line + */ + terminal.emit('linkify:line', line); + }; + /** + * Finds a link within a block of text. + * + * @param {string} text - The text to search . + * @param {boolean} lenient - Whether to use the lenient search. + * @return {string} A URL. + */ + exports.findLinkMatch = function (text, lenient) { + var match = text.match(lenient ? lenientUrlRegex : strictUrlRegex); + if (!match || match.length === 0) { + return null; + } + return match[1]; + }; + /** + * Converts all valid URLs found in the terminal view into hyperlinks. + * + * @param {Xterm} terminal - The terminal that should get "linkified". + * @param {boolean} lenient - The regex type that will be used to identify links. If lenient is + * false, the regex requires a protocol clause. Defaults to true. + * @param {string} target - Sets target="" attribute with value provided to links. + * Default doesn't set target attribute + * @emits linkify + * @emits linkify:line + */ + exports.linkify = function (terminal, lenient, target) { + var rows = terminal.rowContainer.children; + lenient = (typeof lenient == "boolean") ? lenient : true; + for (var i = 0; i < rows.length; i++) { + var line = rows[i]; + exports.linkifyTerminalLine(terminal, line, lenient, target); + } + /** + * This event gets emitted when conversion of all URL substrings to + * HTML anchor elements (links) has finished for the current Xterm + * instance's view. + * + * @event linkify + */ + terminal.emit('linkify'); + }; + /** + * Extend Xterm prototype. + */ + /** + * Converts all valid URLs found in the current terminal linte into + * hyperlinks. + * + * @memberof Xterm + * @param {number|HTMLDivElement} line - The terminal line that should get + * "linkified". + * @param {boolean} lenient - The regex type that will be used to identify links. If lenient is + * false, the regex requires a protocol clause. Defaults to true. + * @param {string} target - Sets target="" attribute with value provided to links. + * Default doesn't set target attribute + */ + Xterm.prototype.linkifyTerminalLine = function (line, lenient, target) { + return exports.linkifyTerminalLine(this, line, lenient, target); + }; + /** + * Converts all valid URLs found in the current terminal into hyperlinks. + * + * @memberof Xterm + * @param {boolean} lenient - The regex type that will be used to identify links. If lenient is + * false, the regex requires a protocol clause. Defaults to true. + * @param {string} target - Sets target="" attribute with value provided to links. + * Default doesn't set target attribute + */ + Xterm.prototype.linkify = function (lenient, target) { + return exports.linkify(this, lenient, target); + }; + return exports; +}); +//# sourceMappingURL=linkify.js.map \ No newline at end of file diff --git a/dist/addons/terminado/terminado.js b/dist/addons/terminado/terminado.js new file mode 100644 index 00000000..73183a6a --- /dev/null +++ b/dist/addons/terminado/terminado.js @@ -0,0 +1,122 @@ +/** + * This module provides methods for attaching a terminal to a terminado WebSocket stream. + * + * @module xterm/addons/terminado/terminado + * @license MIT + */ +(function (attach) { + if (typeof exports === 'object' && typeof module === 'object') { + /* + * CommonJS environment + */ + module.exports = attach(require('../../xterm')); + } + else if (typeof define == 'function') { + /* + * Require.js is available + */ + define(['../../xterm'], attach); + } + else { + /* + * Plain browser environment + */ + attach(window.Terminal); + } +})(function (Xterm) { + 'use strict'; + var exports = {}; + /** + * Attaches the given terminal to the given socket. + * + * @param {Xterm} term - The terminal to be attached to the given socket. + * @param {WebSocket} socket - The socket to attach the current terminal. + * @param {boolean} bidirectional - Whether the terminal should send data + * to the socket as well. + * @param {boolean} buffered - Whether the rendering of incoming data + * should happen instantly or at a maximum + * frequency of 1 rendering per 10ms. + */ + exports.terminadoAttach = function (term, socket, bidirectional, buffered) { + bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional; + term.socket = socket; + term._flushBuffer = function () { + term.write(term._attachSocketBuffer); + term._attachSocketBuffer = null; + clearTimeout(term._attachSocketBufferTimer); + term._attachSocketBufferTimer = null; + }; + term._pushToBuffer = function (data) { + if (term._attachSocketBuffer) { + term._attachSocketBuffer += data; + } + else { + term._attachSocketBuffer = data; + setTimeout(term._flushBuffer, 10); + } + }; + term._getMessage = function (ev) { + var data = JSON.parse(ev.data); + if (data[0] == "stdout") { + if (buffered) { + term._pushToBuffer(data[1]); + } + else { + term.write(data[1]); + } + } + }; + term._sendData = function (data) { + socket.send(JSON.stringify(['stdin', data])); + }; + term._setSize = function (size) { + socket.send(JSON.stringify(['set_size', size.rows, size.cols])); + }; + socket.addEventListener('message', term._getMessage); + if (bidirectional) { + term.on('data', term._sendData); + } + term.on('resize', term._setSize); + socket.addEventListener('close', term.terminadoDetach.bind(term, socket)); + socket.addEventListener('error', term.terminadoDetach.bind(term, socket)); + }; + /** + * Detaches the given terminal from the given socket + * + * @param {Xterm} term - The terminal to be detached from the given socket. + * @param {WebSocket} socket - The socket from which to detach the current + * terminal. + */ + exports.terminadoDetach = function (term, socket) { + term.off('data', term._sendData); + socket = (typeof socket == 'undefined') ? term.socket : socket; + if (socket) { + socket.removeEventListener('message', term._getMessage); + } + delete term.socket; + }; + /** + * Attaches the current terminal to the given socket + * + * @param {WebSocket} socket - The socket to attach the current terminal. + * @param {boolean} bidirectional - Whether the terminal should send data + * to the socket as well. + * @param {boolean} buffered - Whether the rendering of incoming data + * should happen instantly or at a maximum + * frequency of 1 rendering per 10ms. + */ + Xterm.prototype.terminadoAttach = function (socket, bidirectional, buffered) { + return exports.terminadoAttach(this, socket, bidirectional, buffered); + }; + /** + * Detaches the current terminal from the given socket. + * + * @param {WebSocket} socket - The socket from which to detach the current + * terminal. + */ + Xterm.prototype.terminadoDetach = function (socket) { + return exports.terminadoDetach(this, socket); + }; + return exports; +}); +//# sourceMappingURL=terminado.js.map \ No newline at end of file