]> git.proxmox.com Git - mirror_xterm.js.git/blame - src/Linkifier.ts
Initial linkify implementation
[mirror_xterm.js.git] / src / Linkifier.ts
CommitLineData
2207d356
DI
1/**
2 * The time to wait after a row is changed before it is linkified. This prevents
3 * the costly operation of searching every row multiple times, pntentially a
4 * huge aount of times.
5 */
6const TIME_BEFORE_LINKIFY = 200;
7
8const badUrlRegex = /https?:\/\/(\/[\/\\w\.-]*)*/;
9
10const protocolClause = '(https?:\\/\\/)';
11const domainCharacterSet = '[\\da-z\\.-]+';
12const negatedDomainCharacterSet = '[^\\da-z\\.-]+';
13const domainBodyClause = '(' + domainCharacterSet + ')';
14const tldClause = '([a-z\\.]{2,6})';
15const ipClause = '((\\d{1,3}\\.){3}\\d{1,3})';
16const portClause = '(:\\d{1,5})';
17const hostClause = '((' + domainBodyClause + '\\.' + tldClause + ')|' + ipClause + ')' + portClause + '?';
18const pathClause = '(\\/[\\/\\w\\.-]*)*';
19const negatedPathCharacterSet = '[^\\/\\w\\.-]+';
20const bodyClause = hostClause + pathClause;
21const start = '(?:^|' + negatedDomainCharacterSet + ')(';
22const end = ')($|' + negatedPathCharacterSet + ')';
23const lenientUrlClause = start + protocolClause + '?' + bodyClause + end;
24const strictUrlClause = start + protocolClause + bodyClause + end;
25const lenientUrlRegex = new RegExp(lenientUrlClause);
26const strictUrlRegex = new RegExp(strictUrlClause);
27
28export type LinkHandler = (uri: string) => void;
29
30export class Linkifier {
31 private _rows: HTMLElement[];
32 private _rowTimeoutIds: number[];
33 private _webLinkHandler: LinkHandler;
34
35 constructor(rows: HTMLElement[]) {
36 this._rows = rows;
37 this._rowTimeoutIds = [];
38 }
39
40 /**
41 * Queues a row for linkification.
42 * @param {number} rowIndex The index of the row to linkify.
43 */
44 public linkifyRow(rowIndex: number): void {
45 const timeoutId = this._rowTimeoutIds[rowIndex];
46 if (timeoutId) {
47 clearTimeout(timeoutId);
48 }
49 this._rowTimeoutIds[rowIndex] = setTimeout(this._linkifyRow.bind(this, rowIndex), TIME_BEFORE_LINKIFY);
50 }
51
52 public attachWebLinkHandler(handler: LinkHandler): void {
53 this._webLinkHandler = handler;
54 }
55
56 /**
57 * Linkifies a row.
58 * @param {number} rowIndex The index of the row to linkify.
59 */
60 private _linkifyRow(rowIndex: number): void {
61 const rowHtml = this._rows[rowIndex].innerHTML;
62 const uri = this._findLinkMatch(rowHtml);
63 if (uri) {
64 const link = '<a href="' + uri + '">' + uri + '</a>';
65 const newHtml = rowHtml.replace(uri, link);
66 this._rows[rowIndex].innerHTML = newHtml;
67 console.log(this._rows[rowIndex].innerHTML);
68 }
69 }
70
71 /**
72 * Finds a link match in a piece of HTML.
73 * @param {string} html The HTML to search.
74 * @return The matching URI or null if not found.
75 */
76 private _findLinkMatch(html): string {
77 const match = html.match(strictUrlRegex);
78 if (!match || match.length === 0) {
79 return null;
80 }
81 return match[1];
82 }
83}