summaryrefslogtreecommitdiff
path: root/source/features/linkify-urls-in-code.tsx
diff options
context:
space:
mode:
authorGravatar Federico Brigante <github@bfred.it> 2019-01-17 19:57:53 +0700
committerGravatar GitHub <noreply@github.com> 2019-01-17 19:57:53 +0700
commit11b927189bab258a226e251c1bd87504feee51f4 (patch)
tree89b3cf4ba9e6b49afd65b8f9a59a7ca33e46efe3 /source/features/linkify-urls-in-code.tsx
parentf25483fa128d9dcc8e1e74fcf2d2751d604fe11f (diff)
downloadrefined-github-11b927189bab258a226e251c1bd87504feee51f4.tar.gz
refined-github-11b927189bab258a226e251c1bd87504feee51f4.tar.zst
refined-github-11b927189bab258a226e251c1bd87504feee51f4.zip
Drop Babel in favor of esm and TypeScript (#1726)
To get some meaningful errors during feature development, I thought it'd be useful to use TypeScript on `features.js` only, hoping to keep it contained to that file. @sindresorhus suggested we just extend it the whole extension and maybe that can be done incrementally, without having to necessarily use types on everything.
Diffstat (limited to 'source/features/linkify-urls-in-code.tsx')
-rw-r--r--source/features/linkify-urls-in-code.tsx82
1 files changed, 82 insertions, 0 deletions
diff --git a/source/features/linkify-urls-in-code.tsx b/source/features/linkify-urls-in-code.tsx
new file mode 100644
index 00000000..d41178ae
--- /dev/null
+++ b/source/features/linkify-urls-in-code.tsx
@@ -0,0 +1,82 @@
+import select from 'select-dom';
+import linkifyUrls from 'linkify-urls';
+import linkifyIssues from 'linkify-issues';
+import features from '../libs/features';
+import getTextNodes from '../libs/get-text-nodes';
+import {getOwnerAndRepo} from '../libs/page-detect';
+
+// Shared class necessary to avoid also shortening the links
+export const linkifiedURLClass = 'rgh-linkified-code';
+
+// If we are not in a repo, relative issue references won't make sense
+// but `user`/`repo` need to be set to avoid breaking errors in `linkify-issues`
+// https://github.com/sindresorhus/refined-github/issues/1305
+const currentRepo = getOwnerAndRepo();
+const options = {
+ user: currentRepo.ownerName || '/',
+ repo: currentRepo.repoName || '/',
+ type: 'dom',
+ baseUrl: '',
+ attributes: {
+ rel: 'noreferrer noopener',
+ class: linkifiedURLClass // Necessary to avoid also shortening the links
+ }
+};
+
+export const editTextNodes = (fn, el) => {
+ for (const textNode of getTextNodes(el)) {
+ if (fn === linkifyUrls && textNode.textContent.length < 11) { // Shortest url: http://j.mp
+ continue;
+ }
+ const linkified = fn(textNode.textContent, options);
+ if (linkified.children.length > 0) { // Children are <a>
+ if (fn === linkifyIssues) {
+ // Enable native issue title fetch
+ for (const link of linkified.children) {
+ const issue = link.href.split('/').pop();
+ link.setAttribute('class', 'issue-link js-issue-link tooltipped tooltipped-ne');
+ link.setAttribute('data-error-text', 'Failed to load issue title');
+ link.setAttribute('data-permission-text', 'Issue title is private');
+ link.setAttribute('data-url', link.href);
+ link.setAttribute('data-id', `rgh-issue-${issue}`);
+ }
+ }
+ textNode.replaceWith(linkified);
+ }
+ }
+};
+
+function init() {
+ const wrappers = select.all(`
+ .blob-wrapper:not(.${linkifiedURLClass}),
+ .comment-body:not(.${linkifiedURLClass})
+ `);
+
+ // Don't linkify any already linkified code
+ if (wrappers.length === 0) {
+ return false;
+ }
+
+ // Linkify full URLs
+ // `.blob-code-inner` in diffs
+ // `pre` in GitHub comments
+ for (const el of select.all('.blob-code-inner, pre', wrappers)) {
+ editTextNodes(linkifyUrls, el);
+ }
+
+ // Linkify issue refs in comments
+ for (const el of select.all('span.pl-c', wrappers)) {
+ editTextNodes(linkifyIssues, el);
+ }
+
+ // Mark code block as touched
+ for (const el of wrappers) {
+ el.classList.add(linkifiedURLClass);
+ }
+}
+
+features.add({
+ id: 'linkify-urls-in-code',
+ load: features.onAjaxedPages,
+ init
+});