]>
Commit | Line | Data |
---|---|---|
b60903a2 | 1 | (function (linkify) { |
fff56eea PK |
2 | if (typeof exports === 'object' && typeof module === 'object') { |
3 | /* | |
4 | * CommonJS environment | |
5 | */ | |
dc67c945 | 6 | module.exports = linkify(require('../../src/xterm')); |
fff56eea PK |
7 | } else if (typeof define == 'function') { |
8 | /* | |
9 | * Require.js is available | |
10 | */ | |
11 | define(['../../src/xterm'], linkify); | |
12 | } else { | |
13 | /* | |
dc67c945 PK |
14 | * Plain browser environment |
15 | */ | |
fff56eea PK |
16 | linkify(this.Xterm); |
17 | } | |
b60903a2 | 18 | })(function (Xterm) { |
fff56eea PK |
19 | 'use strict'; |
20 | ||
21 | /** | |
22 | * This module provides methods for convertings valid URL substrings | |
23 | * into HTML anchor elements (links), inside a terminal view. | |
24 | * | |
25 | * @module xterm/addons/linkify/linkify | |
26 | */ | |
27 | var exports = {}, | |
28 | protocolClause = '(https?:\\/\\/)', | |
29 | domainCharacterSet = '[\\da-z\\.-]+', | |
30 | negatedDomainCharacterSet = '[^\\da-z\\.-]+', | |
31 | domainBodyClause = '(' + domainCharacterSet + ')', | |
32 | tldClause = '([a-z\\.]{2,6})', | |
23cfa3d8 DI |
33 | ipClause = '((\\d{1,3}\\.){3}\\d{1,3})', |
34 | portClause = '(:\\d{1,5})', | |
9c3b1105 | 35 | hostClause = '((' + domainBodyClause + '\\.' + tldClause + ')|' + ipClause + ')' + portClause + '?', |
23cfa3d8 | 36 | pathClause = '(\\/[\\/\\w\\.-]*)*', |
fff56eea PK |
37 | negatedPathCharacterSet = '[^\\/\\w\\.-]+', |
38 | bodyClause = hostClause + pathClause, | |
39 | start = '(?:^|' + negatedDomainCharacterSet + ')(', | |
40 | end = ')($|' + negatedPathCharacterSet + ')', | |
41 | lenientUrlClause = start + protocolClause + '?' + bodyClause + end, | |
42 | strictUrlClause = start + protocolClause + bodyClause + end, | |
43 | lenientUrlRegex = new RegExp(lenientUrlClause), | |
44 | strictUrlRegex = new RegExp(strictUrlClause); | |
45 | ||
fff56eea PK |
46 | /** |
47 | * Converts all valid URLs found in the given terminal line into | |
48 | * hyperlinks. The terminal line can be either the HTML element itself | |
49 | * or the index of the termina line in the children of the terminal | |
50 | * rows container. | |
51 | * | |
52 | * @param {Xterm} terminal - The terminal that owns the given line. | |
53 | * @param {number|HTMLDivElement} line - The terminal line that should get | |
54 | * "linkified". | |
55 | * @param {boolean} lenient - The regex type that will be used to identify links. If lenient is | |
56 | * false, the regex requires a protocol clause. Defaults to true. | |
57 | * @emits linkify | |
58 | * @emits linkify:line | |
59 | */ | |
60 | exports.linkifyTerminalLine = function (terminal, line, lenient) { | |
61 | if (typeof line == 'number') { | |
62 | line = terminal.rowContainer.children[line]; | |
63 | } else if (! (line instanceof HTMLDivElement)) { | |
64 | var message = 'The "line" argument should be either a number'; | |
65 | message += ' or an HTMLDivElement'; | |
66 | ||
67 | throw new TypeError(message); | |
68 | } | |
b1058b9f | 69 | |
fff56eea PK |
70 | var buffer = document.createElement('span'), |
71 | nodes = line.childNodes; | |
72 | ||
73 | for (var j=0; j<nodes.length; j++) { | |
74 | var node = nodes[j], | |
75 | match; | |
76 | ||
77 | /** | |
78 | * Since we cannot access the TextNode's HTML representation | |
79 | * from the instance itself, we assign its data as textContent | |
80 | * to a dummy buffer span, in order to retrieve the TextNode's | |
81 | * HTML representation from the buffer's innerHTML. | |
82 | */ | |
83 | buffer.textContent = node.data; | |
84 | ||
85 | var nodeHTML = buffer.innerHTML; | |
86 | ||
87 | /** | |
88 | * Apply function only on TextNodes | |
89 | */ | |
90 | if (node.nodeType != node.TEXT_NODE) { | |
91 | continue; | |
92 | } | |
93 | ||
f2f0f460 | 94 | var url = exports.findLinkMatch(node.data, lenient); |
fff56eea | 95 | |
f2f0f460 | 96 | if (!url) { |
fff56eea PK |
97 | continue; |
98 | } | |
99 | ||
f2f0f460 | 100 | var startsWithProtocol = new RegExp('^' + protocolClause), |
fff56eea PK |
101 | urlHasProtocol = url.match(startsWithProtocol), |
102 | href = (urlHasProtocol) ? url : 'http://' + url, | |
103 | link = '<a href="' + href + '" >' + url + '</a>', | |
104 | newHTML = nodeHTML.replace(url, link); | |
105 | ||
106 | line.innerHTML = line.innerHTML.replace(nodeHTML, newHTML); | |
107 | } | |
c8a497eb PK |
108 | |
109 | /** | |
fff56eea PK |
110 | * This event gets emitted when conversion of all URL susbtrings |
111 | * to HTML anchor elements (links) has finished, for a specific | |
112 | * line of the current Xterm instance. | |
c8a497eb | 113 | * |
fff56eea | 114 | * @event linkify:line |
c8a497eb | 115 | */ |
fff56eea PK |
116 | terminal.emit('linkify:line', line); |
117 | }; | |
118 | ||
f2f0f460 DI |
119 | /** |
120 | * Finds a link within a block of text. | |
121 | * | |
122 | * @param {string} text - The text to search . | |
123 | * @param {boolean} lenient - Whether to use the lenient search. | |
124 | * @return {string} A URL. | |
125 | */ | |
126 | exports.findLinkMatch = function (text, lenient) { | |
127 | var match = text.match(lenient ? lenientUrlRegex : strictUrlRegex); | |
128 | if (!match || match.length === 0) { | |
129 | return null; | |
130 | } | |
131 | return match[1]; | |
132 | } | |
fff56eea PK |
133 | |
134 | /** | |
135 | * Converts all valid URLs found in the terminal view into hyperlinks. | |
136 | * | |
137 | * @param {Xterm} terminal - The terminal that should get "linkified". | |
138 | * @param {boolean} lenient - The regex type that will be used to identify links. If lenient is | |
139 | * false, the regex requires a protocol clause. Defaults to true. | |
140 | * @emits linkify | |
141 | * @emits linkify:line | |
142 | */ | |
143 | exports.linkify = function (terminal, lenient) { | |
144 | var rows = terminal.rowContainer.children; | |
145 | ||
146 | lenient = (typeof lenient == "boolean") ? lenient : true; | |
147 | for (var i=0; i<rows.length; i++) { | |
148 | var line = rows[i]; | |
149 | ||
150 | exports.linkifyTerminalLine(terminal, line, lenient); | |
151 | } | |
c8a497eb PK |
152 | |
153 | /** | |
fff56eea PK |
154 | * This event gets emitted when conversion of all URL substrings to |
155 | * HTML anchor elements (links) has finished for the current Xterm | |
156 | * instance's view. | |
c8a497eb | 157 | * |
fff56eea | 158 | * @event linkify |
c8a497eb | 159 | */ |
fff56eea PK |
160 | terminal.emit('linkify'); |
161 | }; | |
162 | ||
163 | /** | |
164 | * Extend Xterm prototype. | |
165 | */ | |
166 | ||
167 | /** | |
dc67c945 PK |
168 | * Converts all valid URLs found in the current terminal linte into |
169 | * hyperlinks. | |
fff56eea | 170 | * |
dc67c945 PK |
171 | * @memberof Xterm |
172 | * @param {number|HTMLDivElement} line - The terminal line that should get | |
173 | * "linkified". | |
174 | * @param {boolean} lenient - The regex type that will be used to identify links. If lenient is | |
175 | * false, the regex requires a protocol clause. Defaults to true. | |
fff56eea | 176 | */ |
dc67c945 PK |
177 | Xterm.prototype.linkifyTerminalLine = function (line, lenient) { |
178 | return exports.linkifyTerminalLine(this, line, lenient); | |
fff56eea PK |
179 | }; |
180 | ||
181 | /** | |
dc67c945 PK |
182 | * Converts all valid URLs found in the current terminal into hyperlinks. |
183 | * | |
184 | * @memberof Xterm | |
185 | * @param {boolean} lenient - The regex type that will be used to identify links. If lenient is | |
186 | * false, the regex requires a protocol clause. Defaults to true. | |
fff56eea | 187 | */ |
dc67c945 PK |
188 | Xterm.prototype.linkify = function (lenient) { |
189 | return exports.linkify(this, lenient); | |
190 | }; | |
c8a497eb | 191 | |
fff56eea | 192 | return exports; |
b1058b9f | 193 | }); |