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 Aug 16, 2021
1 parent e30969a commit 5ee2f8f
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 21 deletions.
34 changes: 21 additions & 13 deletions lib/components/term.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React from 'react';
import {Terminal, ITerminalOptions, IDisposable} from 'xterm';
import {FitAddon} from 'xterm-addon-fit';
import {WebLinksAddon} from 'xterm-addon-web-links';
import {SearchAddon} from 'xterm-addon-search';
import {WebglAddon} from 'xterm-addon-webgl';
import {LigaturesAddon} from 'xterm-addon-ligatures';
Expand All @@ -13,6 +12,8 @@ import processClipboard from '../utils/paste';
import SearchBox from './searchBox';
import {TermProps} from '../hyper';
import {ObjectTypedKeys} from '../utils/object';
import {LinkProvider} from 'xterm-link-provider';
import {FileURLMatcher, URLMatcher} from '../utils/link-matchers';

const isWindows = ['Windows', 'Win16', 'Win32', 'WinCE'].includes(navigator.platform);

Expand Down Expand Up @@ -157,19 +158,26 @@ export default class Term extends React.PureComponent<TermProps> {
this.term.attachCustomKeyEventHandler(this.keyboardHandler);
this.term.loadAddon(this.fitAddon);
this.term.loadAddon(this.searchAddon);
this.term.loadAddon(
new WebLinksAddon(
(event: MouseEvent | undefined, uri: string) => {
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);
},
{
// prevent default electron link handling to allow selection, e.g. via double-click
willLinkActivate: (event: MouseEvent | undefined) => {
event?.preventDefault();
return shallActivateWebLink(event);
},
priority: Date.now()
}
{},
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 @@ -56,8 +56,8 @@
"xterm-addon-ligatures": "^0.5.1",
"xterm-addon-search": "^0.8.0",
"xterm-addon-unicode11": "^0.2.0",
"xterm-addon-web-links": "^0.4.0",
"xterm-addon-webgl": "^0.11.1"
"xterm-addon-webgl": "^0.11.1",
"xterm-link-provider": "1.3.1"
},
"devDependencies": {
"@ava/babel": "2.0.0",
Expand Down
14 changes: 8 additions & 6 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8432,17 +8432,19 @@ xterm-addon-unicode11@^0.2.0:
resolved "https://registry.npmjs.org/xterm-addon-unicode11/-/xterm-addon-unicode11-0.2.0.tgz#9ed0c482b353908bba27778893ca80823382737c"
integrity sha512-rjFDItPc/IDoSiEnoDFwKroNwLD/7t9vYKENjrcKVZg5tgJuuUj8D4rZtP6iVCjSB1LTLYmUs4L/EmCqIyLR/Q==

xterm-addon-web-links@^0.4.0:
version "0.4.0"
resolved "https://registry.npmjs.org/xterm-addon-web-links/-/xterm-addon-web-links-0.4.0.tgz#265cbf8221b9b315d0a748e1323bee331cd5da03"
integrity sha512-xv8GeiINmx0zENO9hf5k+5bnkaE8mRzF+OBAr9WeFq2eLaQSudioQSiT34M1ofKbzcdjSsKiZm19Rw3i4eXamg==

xterm-addon-webgl@^0.11.1:
version "0.11.1"
resolved "https://registry.npmjs.org/xterm-addon-webgl/-/xterm-addon-webgl-0.11.1.tgz#33dd250ab52e9f51d2ff52396447962e6f53e24c"
integrity sha512-xF6DnEoV+rPtzetMBXBZVe1kLKtus7AKdEcyfq2eMHQzhaRvC+pfnU+XiCXC85kueguqu2UkBHXZs5mihK9jOQ==

xterm@^4.13.0:
[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"

xterm@^4.13.0, xterm@^4.6.0:
version "4.13.0"
resolved "https://registry.npmjs.org/xterm/-/xterm-4.13.0.tgz#7998de1e2ad92c4796fe45807be4f31061f3d9d1"
integrity sha512-HVW1gdoLOTnkMaqQCr2r3mQy4fX9iSa5gWxKZ2UTYdLa4iqavv7QxJ8n1Ypse32shPVkhTYPLS6vHEFZp5ghzw==
Expand Down

0 comments on commit 5ee2f8f

Please sign in to comment.