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 May 30, 2024
1 parent 2a7bb18 commit bceadb4
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.7.0",
"xterm-addon-search": "0.13.0",
"xterm-addon-unicode11": "0.6.0",
"xterm-addon-web-links": "0.9.0",
"xterm-addon-webgl": "0.16.0"
"xterm-addon-webgl": "0.16.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 @@ -8892,21 +8892,28 @@ [email protected]:
resolved "https://registry.npmjs.org/xterm-addon-unicode11/-/xterm-addon-unicode11-0.6.0.tgz#733fd17bdf2ae6e818493db1d41241c999de0786"
integrity sha512-5pkb8YoS/deRtNqQRw8t640mu+Ga8B2MG3RXGQu0bwgcfr8XiXIRI880TWM49ICAHhTmnOLPzIIBIjEnCq7k2A==

[email protected]:
version "0.9.0"
resolved "https://registry.npmjs.org/xterm-addon-web-links/-/xterm-addon-web-links-0.9.0.tgz#c65b18588d1f613e703eb6feb7f129e7ff1c63e7"
integrity sha512-LIzi4jBbPlrKMZF3ihoyqayWyTXAwGfu4yprz1aK2p71e9UKXN6RRzVONR0L+Zd+Ik5tPVI9bwp9e8fDTQh49Q==

[email protected]:
version "0.16.0"
resolved "https://registry.npmjs.org/xterm-addon-webgl/-/xterm-addon-webgl-0.16.0.tgz#9872d08a64136f893b27ef9a6412136d3bf563c4"
integrity sha512-E8cq1AiqNOv0M/FghPT+zPAEnvIQRDbAbkb04rRYSxUym69elPWVJ4sv22FCLBqM/3LcrmBLl/pELnBebVFKgA==

[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.3.0"
resolved "https://registry.npmjs.org/xterm/-/xterm-5.3.0.tgz#867daf9cc826f3d45b5377320aabd996cb0fce46"
integrity sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg==

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 bceadb4

Please sign in to comment.