Skip to content

Commit

Permalink
add file url handler
Browse files Browse the repository at this point in the history
  • Loading branch information
LabhanshAgrawal committed Jul 18, 2023
1 parent af41b34 commit 7c846b3
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 14 deletions.
1 change: 0 additions & 1 deletion bin/snapshot-libs.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ if (false) {
require('xterm-addon-fit');
require('xterm-addon-image');
require('xterm-addon-search');
require('xterm-addon-web-links');
require('xterm-addon-webgl');
require('xterm-addon-canvas');
require('xterm');
Expand Down
28 changes: 23 additions & 5 deletions lib/components/term.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React from 'react';
import type {ITerminalOptions, IDisposable} from 'xterm';
import {Terminal} from 'xterm';
import {FitAddon} from 'xterm-addon-fit';
import {WebLinksAddon} from 'xterm-addon-web-links';
import type {ISearchDecorationOptions} from 'xterm-addon-search';
import {SearchAddon} from 'xterm-addon-search';
import {WebglAddon} from 'xterm-addon-webgl';
Expand All @@ -19,6 +18,8 @@ import {pickBy, isEqual} from 'lodash';
import {decorate} from '../utils/plugins';
import 'xterm/css/xterm.css';
import {ImageAddon} from 'xterm-addon-image';
import {LinkProvider} from 'xterm-link-provider';
import {FileURLMatcher, URLMatcher} from '../utils/link-matchers';

const SearchBox = decorate(_SearchBox, 'SearchBox');

Expand Down Expand Up @@ -209,10 +210,27 @@ export default class Term extends React.PureComponent<
this.term.attachCustomKeyEventHandler(this.keyboardHandler);
this.term.loadAddon(this.fitAddon);
this.term.loadAddon(this.searchAddon);
this.term.loadAddon(
new WebLinksAddon((event, uri) => {
if (shallActivateWebLink(event)) void shell.openExternal(uri);
})
this.term.registerLinkProvider(
new LinkProvider(
this.term,
URLMatcher.regex,
(event, text) => {
if (shallActivateWebLink(event)) void shell.openExternal(text);
},
{},
URLMatcher.matchIndex
)
);
this.term.registerLinkProvider(
new LinkProvider(
this.term,
FileURLMatcher.regex,
(event, text) => {
if (shallActivateWebLink(event)) void shell.openExternal(text);
},
{},
FileURLMatcher.matchIndex
)
);
this.term.open(this.termRef);

Expand Down
41 changes: 41 additions & 0 deletions lib/utils/link-matchers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
interface linkMatcher {
regex: RegExp;
matchIndex: number;
}

// Based on the regex used in xterm-addon-web-links
export const URLMatcher: linkMatcher = (() => {
const protocolClause = '(https?:\\/\\/)';
const domainCharacterSet = '[\\da-z\\.-]+';
const negatedDomainCharacterSet = '[^\\da-z\\.-]+';
const domainBodyClause = '(' + domainCharacterSet + ')';
const tldClause = '([a-z\\.]{2,6})';
const ipClause = '((\\d{1,3}\\.){3}\\d{1,3})';
const localHostClause = '(localhost)';
const portClause = '(:\\d{1,5})';
const hostClause =
'((' + domainBodyClause + '\\.' + tldClause + ')|' + ipClause + '|' + localHostClause + ')' + portClause + '?';
const pathCharacterSet = '(\\/[\\/\\w\\.\\-%~:+@]*)*([^:"\'\\s])';
const pathClause = '(' + pathCharacterSet + ')?';
const queryStringHashFragmentCharacterSet = "[0-9\\w\\[\\]\\(\\)\\/\\?\\!#@$%&'*+,:;~\\=\\.\\-]*";
const queryStringClause = '(\\?' + queryStringHashFragmentCharacterSet + ')?';
const hashFragmentClause = '(#' + queryStringHashFragmentCharacterSet + ')?';
const negatedPathCharacterSet = '[^\\/\\w\\.\\-%]+';
const bodyClause = hostClause + pathClause + queryStringClause + hashFragmentClause;
const start = '(?:^|' + negatedDomainCharacterSet + ')(';
const end = ')($|' + negatedPathCharacterSet + ')';
return {regex: new RegExp(start + protocolClause + bodyClause + end), matchIndex: 1};
})();

// Simple file url matcher
export const FileURLMatcher: linkMatcher = (() => {
const protocolClause = '(file:\\/\\/)';
const negatedDomainCharacterSet = '[^\\da-z\\.-]+';
const pathCharacterSet = '(\\/[\\/\\w\\.\\-%~:+@]*)*([^:"\'\\s])';
const pathClause = '(' + pathCharacterSet + ')';
const negatedPathCharacterSet = '[^\\/\\w\\.\\-%]+';
const bodyClause = pathClause;
const start = '(?:^|' + negatedDomainCharacterSet + ')(';
const end = ')($|' + negatedPathCharacterSet + ')';
return {regex: new RegExp(start + protocolClause + bodyClause + end), matchIndex: 1};
})();
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@
"xterm-addon-ligatures": "0.6.0",
"xterm-addon-search": "0.12.0",
"xterm-addon-unicode11": "0.5.0",
"xterm-addon-web-links": "0.8.0",
"xterm-addon-webgl": "0.15.0"
"xterm-addon-webgl": "0.15.0",
"xterm-link-provider": "1.3.1"
},
"devDependencies": {
"@ava/babel": "2.0.0",
Expand Down
1 change: 0 additions & 1 deletion webpack.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ const config: webpack.Configuration[] = [
'xterm-addon-fit': 'require("./node_modules/xterm-addon-fit/lib/xterm-addon-fit.js")',
'xterm-addon-image': 'require("./node_modules/xterm-addon-image/lib/xterm-addon-image.js")',
'xterm-addon-search': 'require("./node_modules/xterm-addon-search/lib/xterm-addon-search.js")',
'xterm-addon-web-links': 'require("./node_modules/xterm-addon-web-links/lib/xterm-addon-web-links.js")',
'xterm-addon-webgl': 'require("./node_modules/xterm-addon-webgl/lib/xterm-addon-webgl.js")',
'xterm-addon-canvas': 'require("./node_modules/xterm-addon-canvas/lib/xterm-addon-canvas.js")',
xterm: 'require("./node_modules/xterm/lib/xterm.js")'
Expand Down
17 changes: 12 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7772,21 +7772,28 @@ [email protected]:
resolved "https://registry.npmjs.org/xterm-addon-unicode11/-/xterm-addon-unicode11-0.5.0.tgz#41c0d96acc1e3bb6c6596eee64e163b6bca74be7"
integrity sha512-Jm4/g4QiTxiKiTbYICQgC791ubhIZyoIwxAIgOW8z8HWFNY+lwk+dwaKEaEeGBfM48Vk8fklsUW9u/PlenYEBg==

[email protected]:
version "0.8.0"
resolved "https://registry.npmjs.org/xterm-addon-web-links/-/xterm-addon-web-links-0.8.0.tgz#2cb1d57129271022569208578b0bf4774e7e6ea9"
integrity sha512-J4tKngmIu20ytX9SEJjAP3UGksah7iALqBtfTwT9ZnmFHVplCumYQsUJfKuS+JwMhjsjH61YXfndenLNvjRrEw==

[email protected]:
version "0.15.0"
resolved "https://registry.npmjs.org/xterm-addon-webgl/-/xterm-addon-webgl-0.15.0.tgz#c10f93ca619524f5a470eaac44258bab0ae8e3c7"
integrity sha512-ZLcqogMFHr4g/YRhcCh3xE8tTklnyut/M+O/XhVsFBRB/YCvYhPdLQ5/AQk54V0wjWAQpa8CF3W8DVR9OqyMCg==

[email protected]:
version "1.3.1"
resolved "https://registry.npmjs.org/xterm-link-provider/-/xterm-link-provider-1.3.1.tgz#69727223220dfa8758056ad6b2b5394a8454b9cb"
integrity sha512-uOlaIeUED6kJeL2nIIf5YwreO0obMhsC0RWypEUmWkz7SAQewzgwdWFjQ2He7NGcT93c4KUf8bRgAu8cV9bAYA==
dependencies:
xterm "^4.6.0"

[email protected]:
version "5.2.1"
resolved "https://registry.npmjs.org/xterm/-/xterm-5.2.1.tgz#b3fea7bdb55b9be1d4b31f4cd1091f26ac42afb8"
integrity sha512-cs5Y1fFevgcdoh2hJROMVIWwoBHD80P1fIP79gopLHJIE4kTzzblanoivxTiQ4+92YM9IxS36H1q0MxIJXQBcA==

xterm@^4.6.0:
version "4.14.1"
resolved "https://registry.npmjs.org/xterm/-/xterm-4.14.1.tgz#6884cb8fb3b83353b1a98139ea23daedf8e35796"
integrity sha512-jgzNg5BuGPwq5/M4dGnmbghZvHx2jaj+9crSEt15bV34Za49VziBmCu7zIy88zUKKiGTxeo7aVzirFSJArIMFw==

y18n@^5.0.5:
version "5.0.5"
resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz#8769ec08d03b1ea2df2500acef561743bbb9ab18"
Expand Down

0 comments on commit 7c846b3

Please sign in to comment.