Merge remote-tracking branch 'upstream/master' into 455_linkify

This commit is contained in:
Daniel Imms
2017-02-17 10:05:22 -08:00
22 changed files with 4518 additions and 5526 deletions
+8
View File
@@ -1,5 +1,6 @@
List of xterm.js contributors. Updated before every release. List of xterm.js contributors. Updated before every release.
Aleksandr Andrienko <aandrienko@codenvy.com>
Alessandro Nadalin <alessandro.nadalin@gmail.com> Alessandro Nadalin <alessandro.nadalin@gmail.com>
Alexander Olsson <noseglid@gmail.com> Alexander Olsson <noseglid@gmail.com>
Antonis Kalipetis <akalipetis@sourcelair.com> Antonis Kalipetis <akalipetis@sourcelair.com>
@@ -7,7 +8,10 @@ Anton Skshidlevsky <meefik@gmail.com>
Anton Yurovskykh <anton.yurovskykh@gmail.com> Anton Yurovskykh <anton.yurovskykh@gmail.com>
Austin Robertson <austinrobertson@gmail.com> Austin Robertson <austinrobertson@gmail.com>
ayapi <colors.aya@gmail.com> ayapi <colors.aya@gmail.com>
Ben Hall <ben@benhall.me.uk>
Benjamin Fischer <benjamin.fischer@rwth-aachen.de> Benjamin Fischer <benjamin.fischer@rwth-aachen.de>
Bill Church <billchurch@users.noreply.github.com>
Bob Reid <bobreid@Bobs-MacBook-Pro.local>
bottleofwater <nison.mael+bottleofwater@gmail.com> bottleofwater <nison.mael+bottleofwater@gmail.com>
Carson Anderson <carson@betterservers.com> Carson Anderson <carson@betterservers.com>
Christian Budde Christensen <budde377@gmail.com> Christian Budde Christensen <budde377@gmail.com>
@@ -22,13 +26,17 @@ Ian Lewis <ianlewis@google.com>
imoses <ido@twiggle.com> imoses <ido@twiggle.com>
Jean Bruenn <himself@jeanbruenn.info> Jean Bruenn <himself@jeanbruenn.info>
Jörg Breitbart <jerch@rockborn.de> Jörg Breitbart <jerch@rockborn.de>
Lucian Buzzo <lucian.buzzo@gmail.com>
Maël Nison <nison.mael@gmail.com> Maël Nison <nison.mael@gmail.com>
Mikko Karvonen <mikko.karvonen@arm.com> Mikko Karvonen <mikko.karvonen@arm.com>
Paris Kasidiaris <pariskasidiaris@gmail.com> Paris Kasidiaris <pariskasidiaris@gmail.com>
Paris Kasidiaris <paris@sourcelair.com> Paris Kasidiaris <paris@sourcelair.com>
runarberg <runar@greenqloud.com> runarberg <runar@greenqloud.com>
Saswat Das <saswatds@users.noreply.github.com>
Shuanglei Tao <tsl0922@gmail.com> Shuanglei Tao <tsl0922@gmail.com>
Steven Silvester <steven.silvester@ieee.org> Steven Silvester <steven.silvester@ieee.org>
Thanasis Daglis <thanasis@sourcelair.com> Thanasis Daglis <thanasis@sourcelair.com>
Tine Jozelj <tine.jozelj@outlook.com> Tine Jozelj <tine.jozelj@outlook.com>
Tyler Jewell <tjewell@codenvy.com>
Vincent Woo <me@vincentwoo.com>
YuviPanda <yuvipanda@gmail.com> YuviPanda <yuvipanda@gmail.com>
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "xterm.js", "name": "xterm.js",
"version": "2.2.3", "version": "2.3.2",
"ignore": ["demo", "test", ".gitignore"], "ignore": ["demo", "test", ".gitignore"],
"main": [ "main": [
"dist/xterm.js", "dist/xterm.js",
+114 -102
View File
@@ -3,112 +3,124 @@
* @module xterm/addons/attach/attach * @module xterm/addons/attach/attach
* @license MIT * @license MIT
*/ */
(function (attach) { (function (attach) {
if (typeof exports === 'object' && typeof module === 'object') { if (typeof exports === 'object' && typeof module === 'object') {
/* /*
* CommonJS environment * CommonJS environment
*/ */
module.exports = attach(require('../../xterm')); module.exports = attach(require('../../xterm'));
} } else if (typeof define == 'function') {
else if (typeof define == 'function') { /*
/* * Require.js is available
* Require.js is available */
*/ define(['../../xterm'], attach);
define(['../../xterm'], attach); } else {
} /*
else { * Plain browser environment
/* */
* Plain browser environment attach(window.Terminal);
*/ }
attach(window.Terminal);
}
})(function (Xterm) { })(function (Xterm) {
'use strict'; 'use strict';
var exports = {};
/** var exports = {};
* Attaches the given terminal to the given socket.
* /**
* @param {Xterm} term - The terminal to be attached to the given socket. * Attaches the given terminal to the given socket.
* @param {WebSocket} socket - The socket to attach the current terminal. *
* @param {boolean} bidirectional - Whether the terminal should send data * @param {Xterm} term - The terminal to be attached to the given socket.
* to the socket as well. * @param {WebSocket} socket - The socket to attach the current terminal.
* @param {boolean} buffered - Whether the rendering of incoming data * @param {boolean} bidirectional - Whether the terminal should send data
* should happen instantly or at a maximum * to the socket as well.
* frequency of 1 rendering per 10ms. * @param {boolean} buffered - Whether the rendering of incoming data
*/ * should happen instantly or at a maximum
exports.attach = function (term, socket, bidirectional, buffered) { * frequency of 1 rendering per 10ms.
bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional; */
term.socket = socket; exports.attach = function (term, socket, bidirectional, buffered) {
term._flushBuffer = function () { bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional;
term.write(term._attachSocketBuffer); term.socket = socket;
term._attachSocketBuffer = null;
clearTimeout(term._attachSocketBufferTimer); term._flushBuffer = function () {
term._attachSocketBufferTimer = null; term.write(term._attachSocketBuffer);
}; term._attachSocketBuffer = null;
term._pushToBuffer = function (data) { clearTimeout(term._attachSocketBufferTimer);
if (term._attachSocketBuffer) { term._attachSocketBufferTimer = null;
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 term._pushToBuffer = function (data) {
* if (term._attachSocketBuffer) {
* @param {Xterm} term - The terminal to be detached from the given socket. term._attachSocketBuffer += data;
* @param {WebSocket} socket - The socket from which to detach the current } else {
* terminal. term._attachSocketBuffer = data;
*/ setTimeout(term._flushBuffer, 10);
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 term._getMessage = function (ev) {
* if (buffered) {
* @param {WebSocket} socket - The socket to attach the current terminal. term._pushToBuffer(ev.data);
* @param {boolean} bidirectional - Whether the terminal should send data } else {
* to the socket as well. term.write(ev.data);
* @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. term._sendData = function (data) {
* socket.send(data);
* @param {WebSocket} socket - The socket from which to detach the current
* terminal.
*/
Xterm.prototype.detach = function (socket) {
return exports.detach(this, socket);
}; };
return exports;
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
+66 -44
View File
@@ -10,50 +10,72 @@
* @module xterm/addons/fit/fit * @module xterm/addons/fit/fit
* @license MIT * @license MIT
*/ */
(function (fit) { (function (fit) {
if (typeof exports === 'object' && typeof module === 'object') { if (typeof exports === 'object' && typeof module === 'object') {
/* /*
* CommonJS environment * CommonJS environment
*/ */
module.exports = fit(require('../../xterm')); module.exports = fit(require('../../xterm'));
} } else if (typeof define == 'function') {
else if (typeof define == 'function') { /*
/* * Require.js is available
* Require.js is available */
*/ define(['../../xterm'], fit);
define(['../../xterm'], fit); } else {
} /*
else { * Plain browser environment
/* */
* Plain browser environment fit(window.Terminal);
*/ }
fit(window.Terminal);
}
})(function (Xterm) { })(function (Xterm) {
var exports = {}; var exports = {};
exports.proposeGeometry = function (term) {
var parentElementStyle = window.getComputedStyle(term.element.parentElement), parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')), parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')) - 17), 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; exports.proposeGeometry = function (term) {
subjectRow.style.display = 'inline'; var parentElementStyle = window.getComputedStyle(term.element.parentElement),
subjectRow.innerHTML = 'W'; // Common character for measuring width, although on monospace parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')),
characterWidth = subjectRow.getBoundingClientRect().width; parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')) - 17),
subjectRow.style.display = ''; // Revert style before calculating height, since they differ. elementStyle = window.getComputedStyle(term.element),
characterHeight = parseInt(subjectRow.offsetHeight); elementPaddingVer = parseInt(elementStyle.getPropertyValue('padding-top')) + parseInt(elementStyle.getPropertyValue('padding-bottom')),
subjectRow.innerHTML = contentBuffer; elementPaddingHor = parseInt(elementStyle.getPropertyValue('padding-right')) + parseInt(elementStyle.getPropertyValue('padding-left')),
rows = parseInt(availableHeight / characterHeight); availableHeight = parentElementHeight - elementPaddingVer,
cols = parseInt(availableWidth / characterWidth); availableWidth = parentElementWidth - elementPaddingHor,
geometry = { cols: cols, rows: rows }; container = term.rowContainer,
return geometry; subjectRow = term.rowContainer.firstElementChild,
}; contentBuffer = subjectRow.innerHTML,
exports.fit = function (term) { characterHeight,
var geometry = exports.proposeGeometry(term); rows,
term.resize(geometry.cols, geometry.rows); characterWidth,
}; cols,
Xterm.prototype.proposeGeometry = function () { geometry;
return exports.proposeGeometry(this);
}; subjectRow.style.display = 'inline';
Xterm.prototype.fit = function () { subjectRow.innerHTML = 'W'; // Common character for measuring width, although on monospace
return exports.fit(this); characterWidth = subjectRow.getBoundingClientRect().width;
}; subjectRow.style.display = ''; // Revert style before calculating height, since they differ.
return exports; characterHeight = parseInt(subjectRow.offsetHeight);
subjectRow.innerHTML = contentBuffer;
rows = parseInt(availableHeight / characterHeight);
cols = parseInt(availableWidth / characterWidth);
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
+42 -42
View File
@@ -4,47 +4,47 @@
* @license MIT * @license MIT
*/ */
(function (fullscreen) { (function (fullscreen) {
if (typeof exports === 'object' && typeof module === 'object') { if (typeof exports === 'object' && typeof module === 'object') {
/* /*
* CommonJS environment * 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) { module.exports = fullscreen(require('../../xterm'));
var fn; } else if (typeof define == 'function') {
if (typeof fullscreen == 'undefined') { /*
fn = (term.element.classList.contains('fullscreen')) ? 'remove' : 'add'; * Require.js is available
} */
else if (!fullscreen) { define(['../../xterm'], fullscreen);
fn = 'remove'; } else {
} /*
else { * Plain browser environment
fn = 'add'; */
} fullscreen(window.Terminal);
term.element.classList[fn]('fullscreen'); }
}; })(function (Xterm) {
Xterm.prototype.toggleFullscreen = function (fullscreen) { var exports = {};
exports.toggleFullScreen(this, fullscreen);
}; /**
return 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
+193 -151
View File
@@ -3,163 +3,205 @@
* @module xterm/addons/linkify/linkify * @module xterm/addons/linkify/linkify
* @license MIT * @license MIT
*/ */
(function (linkify) { (function (linkify) {
if (typeof exports === 'object' && typeof module === 'object') { if (typeof exports === 'object' && typeof module === 'object') {
/* /*
* CommonJS environment * CommonJS environment
*/ */
module.exports = linkify(require('../../xterm')); module.exports = linkify(require('../../xterm'));
} } else if (typeof define == 'function') {
else if (typeof define == 'function') { /*
/* * Require.js is available
* Require.js is available */
*/ define(['../../xterm'], linkify);
define(['../../xterm'], linkify); } else {
} /*
else { * Plain browser environment
/* */
* Plain browser environment linkify(window.Terminal);
*/ }
linkify(window.Terminal);
}
})(function (Xterm) { })(function (Xterm) {
'use strict'; '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);
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 = '<a href="' + href + '" ' + target + '>' + url + '</a>',
newHTML = nodeHTML.replace(url, link);
line.innerHTML = line.innerHTML.replace(nodeHTML, newHTML);
}
/** /**
* Converts all valid URLs found in the given terminal line into * This event gets emitted when conversion of all URL susbtrings
* hyperlinks. The terminal line can be either the HTML element itself * to HTML anchor elements (links) has finished, for a specific
* or the index of the termina line in the children of the terminal * line of the current Xterm instance.
* rows container.
* *
* @param {Xterm} terminal - The terminal that owns the given line. * @event linkify: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) { terminal.emit('linkify:line', line);
if (typeof line == 'number') { };
line = terminal.rowContainer.children[line];
} /**
else if (!(line instanceof HTMLDivElement)) { * Finds a link within a block of text.
var message = 'The "line" argument should be either a number'; *
message += ' or an HTMLDivElement'; * @param {string} text - The text to search .
throw new TypeError(message); * @param {boolean} lenient - Whether to use the lenient search.
} * @return {string} A URL.
if (typeof target === 'undefined') { */
target = ''; exports.findLinkMatch = function (text, lenient) {
} var match = text.match(lenient ? lenientUrlRegex : strictUrlRegex);
else { if (!match || match.length === 0) {
target = 'target="' + target + '"'; return null;
} }
var buffer = document.createElement('span'), nodes = line.childNodes; return match[1];
for (var j = 0; j < nodes.length; j++) { }
var node = nodes[j], match;
/** /**
* Since we cannot access the TextNode's HTML representation * Converts all valid URLs found in the terminal view into hyperlinks.
* from the instance itself, we assign its data as textContent *
* to a dummy buffer span, in order to retrieve the TextNode's * @param {Xterm} terminal - The terminal that should get "linkified".
* HTML representation from the buffer's innerHTML. * @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.
buffer.textContent = node.data; * @param {string} target - Sets target="" attribute with value provided to links.
var nodeHTML = buffer.innerHTML; * Default doesn't set target attribute
/** * @emits linkify
* Apply function only on TextNodes * @emits linkify:line
*/ */
if (node.nodeType != node.TEXT_NODE) { exports.linkify = function (terminal, lenient, target) {
continue; var rows = terminal.rowContainer.children;
}
var url = exports.findLinkMatch(node.data, lenient); lenient = (typeof lenient == "boolean") ? lenient : true;
if (!url) { for (var i=0; i<rows.length; i++) {
continue; var line = rows[i];
}
var startsWithProtocol = new RegExp('^' + protocolClause), urlHasProtocol = url.match(startsWithProtocol), href = (urlHasProtocol) ? url : 'http://' + url, link = '<a href="' + href + '" ' + target + '>' + url + '</a>', newHTML = nodeHTML.replace(url, link); exports.linkifyTerminalLine(terminal, line, lenient, target);
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. * This event gets emitted when conversion of all URL substrings to
* HTML anchor elements (links) has finished for the current Xterm
* instance's view.
* *
* @param {string} text - The text to search . * @event linkify
* @param {boolean} lenient - Whether to use the lenient search.
* @return {string} A URL.
*/ */
exports.findLinkMatch = function (text, lenient) { terminal.emit('linkify');
var match = text.match(lenient ? lenientUrlRegex : strictUrlRegex); };
if (!match || match.length === 0) {
return null; /**
} * Extend Xterm prototype.
return match[1]; */
};
/** /**
* Converts all valid URLs found in the terminal view into hyperlinks. * Converts all valid URLs found in the current terminal linte 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 * @memberof Xterm
* false, the regex requires a protocol clause. Defaults to true. * @param {number|HTMLDivElement} line - The terminal line that should get
* @param {string} target - Sets target="" attribute with value provided to links. * "linkified".
* Default doesn't set target attribute * @param {boolean} lenient - The regex type that will be used to identify links. If lenient is
* @emits linkify * false, the regex requires a protocol clause. Defaults to true.
* @emits linkify:line * @param {string} target - Sets target="" attribute with value provided to links.
*/ * Default doesn't set target attribute
exports.linkify = function (terminal, lenient, target) { */
var rows = terminal.rowContainer.children; Xterm.prototype.linkifyTerminalLine = function (line, lenient, target) {
lenient = (typeof lenient == "boolean") ? lenient : true; return exports.linkifyTerminalLine(this, line, lenient, target);
for (var i = 0; i < rows.length; i++) { };
var line = rows[i];
exports.linkifyTerminalLine(terminal, line, lenient, target); /**
} * Converts all valid URLs found in the current terminal into hyperlinks.
/** *
* This event gets emitted when conversion of all URL substrings to * @memberof Xterm
* HTML anchor elements (links) has finished for the current Xterm * @param {boolean} lenient - The regex type that will be used to identify links. If lenient is
* instance's view. * false, the regex requires a protocol clause. Defaults to true.
* * @param {string} target - Sets target="" attribute with value provided to links.
* @event linkify * Default doesn't set target attribute
*/ */
terminal.emit('linkify'); Xterm.prototype.linkify = function (lenient, target) {
}; return exports.linkify(this, lenient, target);
/** };
* Extend Xterm prototype.
*/ return exports;
/**
* 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
+122 -109
View File
@@ -4,119 +4,132 @@
* @module xterm/addons/terminado/terminado * @module xterm/addons/terminado/terminado
* @license MIT * @license MIT
*/ */
(function (attach) { (function (attach) {
if (typeof exports === 'object' && typeof module === 'object') { if (typeof exports === 'object' && typeof module === 'object') {
/* /*
* CommonJS environment * CommonJS environment
*/ */
module.exports = attach(require('../../xterm')); module.exports = attach(require('../../xterm'));
} } else if (typeof define == 'function') {
else if (typeof define == 'function') { /*
/* * Require.js is available
* Require.js is available */
*/ define(['../../xterm'], attach);
define(['../../xterm'], attach); } else {
} /*
else { * Plain browser environment
/* */
* Plain browser environment attach(window.Terminal);
*/ }
attach(window.Terminal);
}
})(function (Xterm) { })(function (Xterm) {
'use strict'; 'use strict';
var exports = {};
/** var exports = {};
* Attaches the given terminal to the given socket.
* /**
* @param {Xterm} term - The terminal to be attached to the given socket. * Attaches the given terminal to the given socket.
* @param {WebSocket} socket - The socket to attach the current terminal. *
* @param {boolean} bidirectional - Whether the terminal should send data * @param {Xterm} term - The terminal to be attached to the given socket.
* to the socket as well. * @param {WebSocket} socket - The socket to attach the current terminal.
* @param {boolean} buffered - Whether the rendering of incoming data * @param {boolean} bidirectional - Whether the terminal should send data
* should happen instantly or at a maximum * to the socket as well.
* frequency of 1 rendering per 10ms. * @param {boolean} buffered - Whether the rendering of incoming data
*/ * should happen instantly or at a maximum
exports.terminadoAttach = function (term, socket, bidirectional, buffered) { * frequency of 1 rendering per 10ms.
bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional; */
term.socket = socket; exports.terminadoAttach = function (term, socket, bidirectional, buffered) {
term._flushBuffer = function () { bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional;
term.write(term._attachSocketBuffer); term.socket = socket;
term._attachSocketBuffer = null;
clearTimeout(term._attachSocketBufferTimer); term._flushBuffer = function () {
term._attachSocketBufferTimer = null; term.write(term._attachSocketBuffer);
}; term._attachSocketBuffer = null;
term._pushToBuffer = function (data) { clearTimeout(term._attachSocketBufferTimer);
if (term._attachSocketBuffer) { term._attachSocketBufferTimer = null;
term._attachSocketBuffer += data; };
}
else { term._pushToBuffer = function (data) {
term._attachSocketBuffer = data; if (term._attachSocketBuffer) {
setTimeout(term._flushBuffer, 10); term._attachSocketBuffer += data;
} } else {
}; term._attachSocketBuffer = data;
term._getMessage = function (ev) { setTimeout(term._flushBuffer, 10);
var data = JSON.parse(ev.data); }
if (data[0] == "stdout") { };
if (buffered) {
term._pushToBuffer(data[1]); term._getMessage = function (ev) {
} var data = JSON.parse(ev.data)
else { if( data[0] == "stdout" ) {
term.write(data[1]); 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 term._sendData = function (data) {
* socket.send(JSON.stringify(['stdin', data]));
* @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 term._setSize = function (size) {
* socket.send(JSON.stringify(['set_size', size.rows, size.cols]));
* @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. socket.addEventListener('message', term._getMessage);
*
* @param {WebSocket} socket - The socket from which to detach the current if (bidirectional) {
* terminal. term.on('data', term._sendData);
*/ }
Xterm.prototype.terminadoDetach = function (socket) { term.on('resize', term._setSize);
return exports.terminadoDetach(this, socket);
}; socket.addEventListener('close', term.terminadoDetach.bind(term, socket));
return exports; 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
+40 -4
View File
@@ -71,7 +71,7 @@
resize: none; resize: none;
} }
.terminal .terminal-cursor { .terminal:not(.xterm-cursor-style-underline):not(.xterm-cursor-style-bar) .terminal-cursor {
background-color: #fff; background-color: #fff;
color: #000; color: #000;
} }
@@ -82,11 +82,11 @@
background-color: transparent; background-color: transparent;
} }
.terminal.focus .terminal-cursor.blinking { .terminal:not(.xterm-cursor-style-underline):not(.xterm-cursor-style-bar).focus.xterm-cursor-blink .terminal-cursor {
animation: blink-cursor 1.2s infinite step-end; animation: xterm-cursor-blink 1.2s infinite step-end;
} }
@keyframes blink-cursor { @keyframes xterm-cursor-blink {
0% { 0% {
background-color: #fff; background-color: #fff;
color: #000; color: #000;
@@ -97,6 +97,38 @@
} }
} }
.terminal.xterm-cursor-style-bar .terminal-cursor,
.terminal.xterm-cursor-style-underline .terminal-cursor {
position: relative;
}
.terminal.xterm-cursor-style-bar .terminal-cursor::before,
.terminal.xterm-cursor-style-underline .terminal-cursor::before {
content: "";
display: block;
position: absolute;
background-color: #fff;
}
.terminal.xterm-cursor-style-bar .terminal-cursor::before {
top: 0;
bottom: 0;
left: 0;
width: 1px;
}
.terminal.xterm-cursor-style-underline .terminal-cursor::before {
bottom: 0;
left: 0;
right: 0;
height: 1px;
}
.terminal.xterm-cursor-style-bar.focus.xterm-cursor-blink .terminal-cursor::before,
.terminal.xterm-cursor-style-underline.focus.xterm-cursor-blink .terminal-cursor::before {
animation: xterm-cursor-non-bar-blink 1.2s infinite step-end;
}
@keyframes xterm-cursor-non-bar-blink {
0% { background-color: #fff; }
50% { background-color: transparent; }
}
.terminal .composition-view { .terminal .composition-view {
background: #000; background: #000;
color: #FFF; color: #FFF;
@@ -116,6 +148,10 @@
overflow-y: scroll; overflow-y: scroll;
} }
.terminal .xterm-wide-char {
display: inline-block;
}
.terminal .xterm-rows { .terminal .xterm-rows {
position: absolute; position: absolute;
left: 0; left: 0;
+3775 -5038
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
File diff suppressed because one or more lines are too long
+12 -3
View File
@@ -3,11 +3,12 @@ const buffer = require('vinyl-buffer');
const fs = require('fs-extra'); const fs = require('fs-extra');
const gulp = require('gulp'); const gulp = require('gulp');
const merge = require('merge-stream'); const merge = require('merge-stream');
const mocha = require('gulp-mocha');
const mochaPhantomJs = require('gulp-mocha-phantomjs');
const sorcery = require('sorcery'); const sorcery = require('sorcery');
const source = require('vinyl-source-stream'); const source = require('vinyl-source-stream');
const sourcemaps = require('gulp-sourcemaps'); const sourcemaps = require('gulp-sourcemaps');
const ts = require('gulp-typescript'); const ts = require('gulp-typescript');
const tsify = require('tsify');
let buildDir = process.env.BUILD_DIR || 'build'; let buildDir = process.env.BUILD_DIR || 'build';
@@ -53,7 +54,6 @@ gulp.task('browserify', ['tsc'], function() {
packageCache: {} packageCache: {}
}; };
let bundleStream = browserify(browserifyOptions) let bundleStream = browserify(browserifyOptions)
.plugin(tsify)
.bundle() .bundle()
.pipe(source('xterm.js')) .pipe(source('xterm.js'))
.pipe(buffer()) .pipe(buffer())
@@ -70,6 +70,15 @@ gulp.task('browserify', ['tsc'], function() {
return merge(bundleStream, copyAddons, copyStylesheets); return merge(bundleStream, copyAddons, copyStylesheets);
}); });
gulp.task('test-mocha', function () {
return gulp.src(['lib/*test.js', 'lib/**/*test.js'], {read: false})
.pipe(mocha())
});
gulp.task('test-mocha-phantomjs', function () {
return gulp.src('test-harness.html')
.pipe(mochaPhantomJs());
});
/** /**
* Use `sorcery` to resolve the source map chain and point back to the TypeScript files. * Use `sorcery` to resolve the source map chain and point back to the TypeScript files.
@@ -83,5 +92,5 @@ gulp.task('sorcery', ['browserify'], function () {
}); });
gulp.task('build', ['sorcery']); gulp.task('build', ['sorcery']);
gulp.task('test', ['test-mocha', 'test-mocha-phantomjs']);
gulp.task('default', ['build']); gulp.task('default', ['build']);
+4 -4
View File
@@ -1,7 +1,7 @@
{ {
"name": "xterm", "name": "xterm",
"description": "Full xterm terminal, in your browser", "description": "Full xterm terminal, in your browser",
"version": "2.2.3", "version": "2.3.2",
"ignore": [ "ignore": [
"demo", "demo",
"test", "test",
@@ -47,16 +47,16 @@
"glob": "^7.0.5", "glob": "^7.0.5",
"gulp": "^3.9.1", "gulp": "^3.9.1",
"gulp-cli": "^1.2.2", "gulp-cli": "^1.2.2",
"gulp-mocha": "^3.0.1",
"gulp-mocha-phantomjs": "^0.12.0",
"gulp-sourcemaps": "1.9.1", "gulp-sourcemaps": "1.9.1",
"gulp-typescript": "^3.1.3", "gulp-typescript": "^3.1.3",
"jsdoc": "3.4.3", "jsdoc": "3.4.3",
"merge-stream": "^1.0.1", "merge-stream": "^1.0.1",
"mocha": "2.5.3",
"node-pty": "^0.4.1", "node-pty": "^0.4.1",
"nodemon": "1.10.2", "nodemon": "1.10.2",
"sleep": "^3.0.1", "sleep": "^3.0.1",
"sorcery": "^0.10.0", "sorcery": "^0.10.0",
"tsify": "^3.0.0",
"tslint": "^4.0.2", "tslint": "^4.0.2",
"typescript": "^2.0.3", "typescript": "^2.0.3",
"vinyl-buffer": "^1.0.0", "vinyl-buffer": "^1.0.0",
@@ -67,7 +67,7 @@
"start": "node demo/app", "start": "node demo/app",
"dev": "nodemon -e js,ts --watch src --watch demo --exec npm start", "dev": "nodemon -e js,ts --watch src --watch demo --exec npm start",
"lint": "tslint src/*.ts src/**/*.ts", "lint": "tslint src/*.ts src/**/*.ts",
"test": "mocha --recursive ./lib", "test": "gulp test",
"build:docs": "jsdoc -c jsdoc.json", "build:docs": "jsdoc -c jsdoc.json",
"build": "gulp build", "build": "gulp build",
"prepublish": "npm run build" "prepublish": "npm run build"
+1 -1
View File
@@ -1394,7 +1394,7 @@ export class InputHandler implements IInputHandler {
this._terminal.cursorHidden = false; this._terminal.cursorHidden = false;
this._terminal.insertMode = false; this._terminal.insertMode = false;
this._terminal.originMode = false; this._terminal.originMode = false;
this._terminal.wraparoundMode = false; // autowrap this._terminal.wraparoundMode = true; // defaults: xterm - true, vt100 - false
this._terminal.applicationKeypad = false; // ? this._terminal.applicationKeypad = false; // ?
this._terminal.viewport.syncScrollArea(); this._terminal.viewport.syncScrollArea();
this._terminal.applicationCursor = false; this._terminal.applicationCursor = false;
+6
View File
@@ -44,6 +44,12 @@ export interface ITerminal {
emit(event: string, data: any); emit(event: string, data: any);
} }
export interface ICharMeasure {
width: number;
height: number;
measure(): void;
}
interface ICircularList<T> { interface ICircularList<T> {
length: number; length: number;
maxLength: number; maxLength: number;
+26 -18
View File
@@ -41,13 +41,17 @@ describe('Viewport', () => {
}); });
describe('refresh', () => { describe('refresh', () => {
it('should set the line-height of the terminal', () => { it('should set the line-height of the terminal', done => {
assert.equal(viewportElement.style.lineHeight, CHARACTER_HEIGHT + 'px'); // Allow CharMeasure to be initialized
assert.equal(terminal.rowContainer.style.lineHeight, CHARACTER_HEIGHT + 'px'); setTimeout(() => {
charMeasure.height = 1; assert.equal(viewportElement.style.lineHeight, CHARACTER_HEIGHT + 'px');
viewport.refresh(); assert.equal(terminal.rowContainer.style.lineHeight, CHARACTER_HEIGHT + 'px');
assert.equal(viewportElement.style.lineHeight, '1px'); charMeasure.height = 1;
assert.equal(terminal.rowContainer.style.lineHeight, '1px'); viewport.refresh();
assert.equal(viewportElement.style.lineHeight, '1px');
assert.equal(terminal.rowContainer.style.lineHeight, '1px');
done();
}, 0);
}); });
it('should set the height of the viewport when the line-height changed', () => { it('should set the height of the viewport when the line-height changed', () => {
terminal.lines.push(''); terminal.lines.push('');
@@ -62,17 +66,21 @@ describe('Viewport', () => {
}); });
describe('syncScrollArea', () => { describe('syncScrollArea', () => {
it('should sync the scroll area', () => { it('should sync the scroll area', done => {
terminal.lines.push(''); // Allow CharMeasure to be initialized
terminal.rows = 1; setTimeout(() => {
assert.equal(scrollAreaElement.style.height, 0 * CHARACTER_HEIGHT + 'px'); terminal.lines.push('');
viewport.syncScrollArea(); terminal.rows = 1;
assert.equal(viewportElement.style.height, 1 * CHARACTER_HEIGHT + 'px'); assert.equal(scrollAreaElement.style.height, 0 * CHARACTER_HEIGHT + 'px');
assert.equal(scrollAreaElement.style.height, 1 * CHARACTER_HEIGHT + 'px'); viewport.syncScrollArea();
terminal.lines.push(''); assert.equal(viewportElement.style.height, 1 * CHARACTER_HEIGHT + 'px');
viewport.syncScrollArea(); assert.equal(scrollAreaElement.style.height, 1 * CHARACTER_HEIGHT + 'px');
assert.equal(viewportElement.style.height, 1 * CHARACTER_HEIGHT + 'px'); terminal.lines.push('');
assert.equal(scrollAreaElement.style.height, 2 * CHARACTER_HEIGHT + 'px'); viewport.syncScrollArea();
assert.equal(viewportElement.style.height, 1 * CHARACTER_HEIGHT + 'px');
assert.equal(scrollAreaElement.style.height, 2 * CHARACTER_HEIGHT + 'px');
done();
}, 0);
}); });
}); });
}); });
+2 -1
View File
@@ -35,7 +35,8 @@ export class Viewport {
this.terminal.on('resize', this.syncScrollArea.bind(this)); this.terminal.on('resize', this.syncScrollArea.bind(this));
this.viewportElement.addEventListener('scroll', this.onScroll.bind(this)); this.viewportElement.addEventListener('scroll', this.onScroll.bind(this));
this.syncScrollArea(); // Perform this async to ensure the CharMeasure is ready.
setTimeout(() => this.syncScrollArea(), 0);
} }
/** /**
+6 -1
View File
@@ -32,6 +32,9 @@
var exports = {}; var exports = {};
exports.proposeGeometry = function (term) { exports.proposeGeometry = function (term) {
if (!term.element.parentElement) {
return null;
}
var parentElementStyle = window.getComputedStyle(term.element.parentElement), var parentElementStyle = window.getComputedStyle(term.element.parentElement),
parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')), parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')),
parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')) - 17), parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')) - 17),
@@ -66,7 +69,9 @@
exports.fit = function (term) { exports.fit = function (term) {
var geometry = exports.proposeGeometry(term); var geometry = exports.proposeGeometry(term);
term.resize(geometry.cols, geometry.rows); if (geometry) {
term.resize(geometry.cols, geometry.rows);
}
}; };
Xterm.prototype.proposeGeometry = function () { Xterm.prototype.proposeGeometry = function () {
+6
View File
@@ -1,9 +1,15 @@
var glob = require('glob'); var glob = require('glob');
var fs = require('fs'); var fs = require('fs');
var os = require('os');
var pty = require('node-pty'); var pty = require('node-pty');
var sleep = require('sleep'); var sleep = require('sleep');
var Terminal = require('../xterm'); var Terminal = require('../xterm');
if (os.platform() === 'win32') {
// Skip tests on Windows since pty.open isn't supported
return;
}
var CONSOLE_LOG = console.log; var CONSOLE_LOG = console.log;
// expect files need terminal at 80x25! // expect files need terminal at 80x25!
+65
View File
@@ -0,0 +1,65 @@
/**
* @license MIT
*/
import { ICharMeasure, ITerminal } from '../Interfaces';
declare var assert: Chai.Assert;
declare var Terminal: ITerminal;
// Do not describe tests unless in PhantomJS environment
if (typeof Terminal !== 'undefined') {
const CharMeasure = (<any>Terminal).CharMeasure;
describe('CharMeasure', () => {
const parentElement = document.createElement('div');
let charMeasure: ICharMeasure;
beforeEach(() => {
charMeasure = new CharMeasure(parentElement);
document.querySelector('#xterm').appendChild(parentElement);
});
afterEach(() => {
if (parentElement && parentElement.parentElement) {
parentElement.parentElement.removeChild(parentElement);
}
});
describe('measure', () => {
it('should be performed async on first call', done => {
assert.equal(charMeasure.width, null);
charMeasure.measure();
assert.equal(charMeasure.width, null);
setTimeout(() => {
assert.isTrue(charMeasure.width > 0);
done();
}, 0);
});
it('should be performed sync on successive calls', done => {
charMeasure.measure();
setTimeout(() => {
const firstWidth = charMeasure.width;
parentElement.style.fontSize = '2em';
charMeasure.measure();
assert.equal(charMeasure.width, firstWidth * 2);
done();
}, 0);
});
it('should NOT do a measure when the parent is hidden', done => {
charMeasure.measure();
setTimeout(() => {
const firstWidth = charMeasure.width;
parentElement.style.display = 'none';
parentElement.style.fontSize = '2em';
charMeasure.measure();
assert.equal(charMeasure.width, firstWidth);
done();
}, 0);
});
});
});
}
+2 -5
View File
@@ -97,13 +97,10 @@
} }
@keyframes xterm-cursor-blink { @keyframes xterm-cursor-blink {
0% { 0% { }
background-color: #fff;
color: #000;
}
50% { 50% {
background-color: transparent; background-color: transparent;
color: #FFF; color: inherit;
} }
} }
+4 -1
View File
@@ -1781,7 +1781,7 @@ Terminal.prototype.error = function() {
* @param {number} y The number of rows to resize to. * @param {number} y The number of rows to resize to.
*/ */
Terminal.prototype.resize = function(x, y) { Terminal.prototype.resize = function(x, y) {
if (Number.isNaN(x) || Number.isNaN(y)) { if (isNaN(x) || isNaN(y)) {
return; return;
} }
@@ -2303,6 +2303,9 @@ function keys(obj) {
Terminal.EventEmitter = EventEmitter; Terminal.EventEmitter = EventEmitter;
Terminal.inherits = inherits; Terminal.inherits = inherits;
// Expose for Phantom.JS tests
Terminal.CharMeasure = CharMeasure;
/** /**
* Adds an event listener to the terminal. * Adds an event listener to the terminal.
* *
+22
View File
@@ -0,0 +1,22 @@
<html>
<head>
<meta charset="utf-8">
<!-- encoding must be set for mocha's special characters to render properly -->
<link rel="stylesheet" href="node_modules/mocha/mocha.css" />
</head>
<body>
<div id="mocha"></div>
<div id="xterm"></div>
<script src="node_modules/mocha/mocha.js"></script>
<script src="node_modules/chai/chai.js"></script>
<script>
mocha.ui('bdd')
assert = chai.assert
</script>
<script src="build/xterm.js"></script>
<script src="lib/utils/CharMeasure.phantom.js"></script>
<script>
mocha.run()
</script>
</body>
</html>