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 26, 2023
1 parent 37289ed commit 9bb1d21
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 @@ -24,7 +24,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 @@ -13,11 +13,12 @@ import {LigaturesAddon} from 'xterm-addon-ligatures';
import {SearchAddon} from 'xterm-addon-search';
import type {ISearchDecorationOptions} from 'xterm-addon-search';
import {Unicode11Addon} from 'xterm-addon-unicode11';
import {WebLinksAddon} from 'xterm-addon-web-links';
import {WebglAddon} from 'xterm-addon-webgl';
import {LinkProvider} from 'xterm-link-provider';

import type {TermProps} from '../../typings/hyper';
import terms from '../terms';
import {FileURLMatcher, URLMatcher} from '../utils/link-matchers';
import processClipboard from '../utils/paste';
import {decorate} from '../utils/plugins';

Expand Down Expand Up @@ -214,10 +215,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 @@ -68,8 +68,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 @@ -7793,21 +7793,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 9bb1d21

Please sign in to comment.