diff --git a/addons/attach/attach.js b/addons/attach/attach.js index 2788f8e7..775535cf 100644 --- a/addons/attach/attach.js +++ b/addons/attach/attach.js @@ -7,105 +7,111 @@ */ (function (attach) { - if (typeof exports === 'object' && typeof module === 'object') { - /* - * CommonJS environment - */ - module.exports = attach.call(this); - } else if (typeof define == 'function') { - /* - * Require.js is available - */ - define(['../../src/xterm'], attach); - } else { - /* - * Plain browser environment - */ - attach(this.Xterm); - } + if (typeof exports === 'object' && typeof module === 'object') { + /* + * CommonJS environment + */ + module.exports = attach.call(this); + } else if (typeof define == 'function') { + /* + * Require.js is available + */ + define(['../../src/xterm'], attach); + } else { + /* + * Plain browser environment + */ + attach(this.Xterm); + } })(function (Xterm) { - 'use strict'; + 'use strict'; - /** - * This module provides methods for attaching a terminal to a WebSocket - * stream. - * - * @module xterm/addons/attach/attach - */ - var exports = {}; + /** + * This module provides methods for attaching a terminal to a WebSocket + * stream. + * + * @module xterm/addons/attach/attach + */ + 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; + /** + * 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)); + term._flushBuffer = function () { + term.write(term._attachSocketBuffer); + term._attachSocketBuffer = null; + clearTimeout(term._attachSocketBufferTimer); + term._attachSocketBufferTimer = null; }; - /** - * 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; + 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; + }; + + /** + * Extends the given terminal prototype with the public methods of this add-on. + * + * @param {function} Xterm - The prototype to be extended. + */ + exports.extendXtermPrototype = function (Xterm) { /** * Attaches the current terminal to the given socket * @@ -117,7 +123,7 @@ * frequency of 1 rendering per 10ms. */ Xterm.prototype.attach = function (socket, bidirectional, buffered) { - return exports.attach(this, socket, bidirectional, buffered); + return exports.attach(this, socket, bidirectional, buffered); }; /** @@ -127,8 +133,17 @@ * terminal. */ Xterm.prototype.detach = function (socket) { - return exports.detach(this, socket); + return exports.detach(this, socket); }; + }; - return exports; + /** + * If the Xterm parameter is a function, then extend it with the methods declared in this + * add-on. + */ + if (typeof Xterm == 'function') { + exports.extendXtermPrototype(Xterm); + } + + return exports; }); diff --git a/addons/attach/package.json b/addons/attach/package.json new file mode 100644 index 00000000..9e45068b --- /dev/null +++ b/addons/attach/package.json @@ -0,0 +1,5 @@ +{ + "name": "xterm.attach", + "main": "attach.js", + "private": true +} diff --git a/addons/fit/fit.js b/addons/fit/fit.js index c39b9cf1..3bcf0907 100644 --- a/addons/fit/fit.js +++ b/addons/fit/fit.js @@ -12,58 +12,90 @@ * of columns) */ (function (fit) { - if (typeof exports === 'object' && typeof module === 'object') { - /* - * CommonJS environment - */ - module.exports = fit.call(this); - } else if (typeof define == 'function') { - /* - * Require.js is available - */ - define(['../../src/xterm'], fit); - } else { - /* - * Plain browser environment - */ - fit(this.Xterm); - } + if (typeof exports === 'object' && typeof module === 'object') { + /* + * CommonJS environment + */ + module.exports = fit.call(this); + } else if (typeof define == 'function') { + /* + * Require.js is available + */ + define(['../../src/xterm'], fit); + } else { + /* + * Plain browser environment + */ + fit(this.Xterm); + } })(function (Xterm) { + /** + * This module provides methods for fitting a terminal's size to a parent container. + * + * @module xterm/addons/fit/fit + */ + 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); + }; + + /** + * Extends the given terminal prototype with the public methods of this add-on. + * + * @param {function} Xterm - The prototype to be extended. + */ + exports.extendXtermPrototype = function (Xterm) { Xterm.prototype.proposeGeometry = function () { - var parentElementStyle = window.getComputedStyle(this.element.parentElement), - parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')), - parentElementWidth = parseInt(parentElementStyle.getPropertyValue('width')), - elementStyle = window.getComputedStyle(this.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 = this.rowContainer, - subjectRow = this.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; + return exports.proposeGeometry(this); }; Xterm.prototype.fit = function () { - var geometry = this.proposeGeometry(); - - this.resize(geometry.cols, geometry.rows); + return exports.fit(this); }; + }; + + /** + * If the Xterm parameter is a function, then extend it with the methods declared in this + * add-on. + */ + if (typeof Xterm == 'function') { + exports.extendXtermPrototype(Xterm); + } + + return exports; }); diff --git a/addons/fit/package.json b/addons/fit/package.json new file mode 100644 index 00000000..f7cb5bc8 --- /dev/null +++ b/addons/fit/package.json @@ -0,0 +1,5 @@ +{ + "name": "xterm.fit", + "main": "fit.js", + "private": true +} diff --git a/addons/fullscreen/fullscreen.js b/addons/fullscreen/fullscreen.js index 4e3d0028..1d5a568b 100644 --- a/addons/fullscreen/fullscreen.js +++ b/addons/fullscreen/fullscreen.js @@ -11,34 +11,57 @@ * fullscreen mode is being toggled. */ (function (fullscreen) { - if (typeof exports === 'object' && typeof module === 'object') { - /* - * CommonJS environment - */ - module.exports = fullscreen.call(this); - } else if (typeof define == 'function') { - /* - * Require.js is available - */ - define(['../../src/xterm'], fullscreen); - } else { - /* - * Plain browser environment - */ - fullscreen(this.Xterm); - } + if (typeof exports === 'object' && typeof module === 'object') { + /* + * CommonJS environment + */ + module.exports = fullscreen.call(this); + } else if (typeof define == 'function') { + /* + * Require.js is available + */ + define(['../../src/xterm'], fullscreen); + } else { + /* + * Plain browser environment + */ + fullscreen(this.Xterm); + } })(function (Xterm) { + var exports = {}; + + 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'); + }; + + /** + * Extends the given terminal prototype with the public methods of this add-on. + * + * @param {function} Xterm - The prototype to be extended. + */ + exports.extendXtermPrototype = function (Xterm) { Xterm.prototype.toggleFullscreen = function (fullscreen) { - var fn; - - if (typeof fullscreen == 'undefined') { - fn = (this.element.classList.contains('fullscreen')) ? 'remove' : 'add'; - } else if (!fullscreen) { - fn = 'remove'; - } else { - fn = 'add'; - } - - this.element.classList[fn]('fullscreen'); + exports.toggleFullScreen(this, fullscreen); }; + }; + + /** + * If the Xterm parameter is a function, then extend it with the methods declared in this + * add-on. + */ + if (typeof Xterm == 'function') { + exports.extendXtermPrototype(Xterm); + } + + return exports; }); diff --git a/addons/fullscreen/package.json b/addons/fullscreen/package.json new file mode 100644 index 00000000..fdaf6880 --- /dev/null +++ b/addons/fullscreen/package.json @@ -0,0 +1,5 @@ +{ + "name": "xterm.fullscreen", + "main": "fullscreen.js", + "private": true +} diff --git a/addons/linkify/linkify.js b/addons/linkify/linkify.js index ab3c041a..86849409 100644 --- a/addons/linkify/linkify.js +++ b/addons/linkify/linkify.js @@ -1,164 +1,170 @@ (function (linkify) { - if (typeof exports === 'object' && typeof module === 'object') { - /* - * CommonJS environment - */ - module.exports = linkify.call(this); - } else if (typeof define == 'function') { - /* - * Require.js is available - */ - define(['../../src/xterm'], linkify); - } else { - /* + if (typeof exports === 'object' && typeof module === 'object') { + /* + * CommonJS environment + */ + module.exports = linkify.call(this); + } else if (typeof define == 'function') { + /* + * Require.js is available + */ + define(['../../src/xterm'], linkify); + } else { + /* * Plain browser environment */ - linkify(this.Xterm); - } + linkify(this.Xterm); + } })(function (Xterm) { - 'use strict'; + 'use strict'; + + /** + * This module provides methods for convertings valid URL substrings + * into HTML anchor elements (links), inside a terminal view. + * + * @module xterm/addons/linkify/linkify + */ + var exports = {}, + protocolClause = '(https?:\\/\\/)', + domainCharacterSet = '[\\da-z\\.-]+', + negatedDomainCharacterSet = '[^\\da-z\\.-]+', + domainBodyClause = '(' + domainCharacterSet + ')', + tldClause = '([a-z\\.]{2,6})', + hostClause = domainBodyClause + '\\.' + tldClause, + 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. + * @emits linkify + * @emits linkify:line + */ + exports.linkifyTerminalLine = function (terminal, line, lenient) { + 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); + } + + var buffer = document.createElement('span'), + nodes = line.childNodes; + + for (var j=0; j' + url + '', + newHTML = nodeHTML.replace(url, link); + + line.innerHTML = line.innerHTML.replace(nodeHTML, newHTML); + } /** - * This module provides methods for convertings valid URL substrings - * into HTML anchor elements (links), inside a terminal view. + * 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. * - * @module xterm/addons/linkify/linkify + * @event linkify:line */ - var exports = {}, - protocolClause = '(https?:\\/\\/)', - domainCharacterSet = '[\\da-z\\.-]+', - negatedDomainCharacterSet = '[^\\da-z\\.-]+', - domainBodyClause = '(' + domainCharacterSet + ')', - tldClause = '([a-z\\.]{2,6})', - hostClause = domainBodyClause + '\\.' + tldClause, - 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); + terminal.emit('linkify:line', line); + }; + /** + * 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. + * @emits linkify + * @emits linkify:line + */ + exports.linkify = function (terminal, lenient) { + var rows = terminal.rowContainer.children; + + lenient = (typeof lenient == "boolean") ? lenient : true; + for (var i=0; i' + 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); - }; + terminal.emit('linkify'); + }; + /** + * Extend Xterm prototype. + */ + /** + * Extends the given terminal prototype with the public methods of this add-on. + * + * @param {function} Xterm - The prototype to be extended. + */ + exports.extendXtermPrototype = function (Xterm) { /** - * 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. - * @emits linkify - * @emits linkify:line - */ - exports.linkify = function (terminal, lenient) { - var rows = terminal.rowContainer.children; - - lenient = (typeof lenient == "boolean") ? lenient : true; - for (var i=0; i