From 0f3ee21d9d8a53622b7c640d4dfe5909fd3839bb Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 8 Feb 2017 14:13:30 -0800 Subject: [PATCH] Enable custom http link handlers --- src/Linkifier.ts | 30 +++++++++++++----------------- src/xterm.css | 6 ++++++ src/xterm.js | 10 ++++++++++ 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/Linkifier.ts b/src/Linkifier.ts index 64be3947..adb96566 100644 --- a/src/Linkifier.ts +++ b/src/Linkifier.ts @@ -28,7 +28,7 @@ export type LinkHandler = (uri: string) => void; export class Linkifier { private _rows: HTMLElement[]; private _rowTimeoutIds: number[]; - private _webLinkHandler: LinkHandler; + private _hypertextLinkHandler: LinkHandler; constructor(rows: HTMLElement[]) { this._rows = rows; @@ -48,9 +48,8 @@ export class Linkifier { } // TODO: Support local links - public attachWebLinkHandler(handler: LinkHandler): void { - this._webLinkHandler = handler; - // TODO: Refresh links if a handler is attached? + public attachHypertextLinkHandler(handler: LinkHandler): void { + this._hypertextLinkHandler = handler; } /** @@ -96,10 +95,6 @@ export class Linkifier { this._replaceNodeSubstringWithNode(node, linkElement, uri, searchIndex); } } - // Continue searching in case multiple URIs exist on a single - // const link = '' + uri + ''; - // const newHtml = rowHtml.replace(uri, link); - // this._rows[rowIndex].innerHTML = newHtml; } } @@ -124,13 +119,12 @@ export class Linkifier { private _createAnchorElement(uri: string): HTMLAnchorElement { const element = document.createElement('a'); element.textContent = uri; - // Force link on another tab so work is not lost - element.target = '_blank'; - if (this._webLinkHandler) { - element.href = '#'; - element.addEventListener('click', () => this._webLinkHandler(uri)); + if (this._hypertextLinkHandler) { + element.addEventListener('click', () => this._hypertextLinkHandler(uri)); } else { element.href = uri; + // Force link on another tab so work is not lost + element.target = '_blank'; } return element; } @@ -150,7 +144,8 @@ export class Linkifier { /** * Replace a substring within a node with a new node. - * @param {Node} targetNode The target node. + * @param {Node} targetNode The target node; either a text node or a + * containing a single text node. * @param {Node} newNode The new node to insert. * @param {string} substring The substring to replace. * @param {number} substringIndex The index of the substring within the string. @@ -160,9 +155,10 @@ export class Linkifier { if (node.nodeType !== Node.TEXT_NODE) { node = node.childNodes[0]; } - // The targetNode will be either a text node or a . The targetNode is - // assumed to have no children. In either case, the targetNode's text node - // must be split into 2 text nodes surrounding the newNode. + + // The targetNode will be either a text node or a . The text node + // (targetNode or its only-child) needs to be replaced with newNode plus new + // text nodes potentially on either side. if (node.childNodes.length === 0 && node.nodeType !== Node.TEXT_NODE) { throw new Error('targetNode must be a text node or only contain a single text node'); } diff --git a/src/xterm.css b/src/xterm.css index 3075bba4..43f2594c 100644 --- a/src/xterm.css +++ b/src/xterm.css @@ -73,6 +73,12 @@ .terminal a { color: inherit; + /* Feature underline on links even if they have no href */ + text-decoration: underline; +} + +.terminal a:hover { + cursor: pointer; } .terminal:not(.xterm-cursor-style-underline):not(.xterm-cursor-style-bar) .terminal-cursor { diff --git a/src/xterm.js b/src/xterm.js index 26ed1f70..f858af31 100644 --- a/src/xterm.js +++ b/src/xterm.js @@ -1274,6 +1274,16 @@ Terminal.prototype.attachCustomKeydownHandler = function(customKeydownHandler) { this.customKeydownHandler = customKeydownHandler; } +// TODO: Doc +Terminal.prototype.attachHypertextLinkHandler = function(handler) { + if (!this.linkifier) { + throw new Error('Cannot attach a hypertext link handler before Terminal.open is called'); + } + this.linkifier.attachHypertextLinkHandler(handler); + // Refresh to force links to refresh + this.refresh(0, this.rows - 1); +} + /** * Handle a keydown event * Key Resources: