From 3bcc0b99e2d221243c3bcc2a5cc2a7f46c6a6d59 Mon Sep 17 00:00:00 2001 From: Feuerfuchs Date: Wed, 26 Jun 2019 20:16:19 +0200 Subject: New feature: Clickable links in plain text (opt) --- js/main.ts | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 3 deletions(-) (limited to 'js') diff --git a/js/main.ts b/js/main.ts index 3b2a081..5bbcd97 100644 --- a/js/main.ts +++ b/js/main.ts @@ -20,6 +20,10 @@ const settings = new KeyValueStore({ value: ensureSetting('image-previews', '1') === '1', valueRange: [false, true] }, + clickablePlainLinks: { + value: ensureSetting('clickable-plain-links', '1') === '1', + valueRange: [false, true] + }, }); // @@ -46,8 +50,13 @@ const settings = new KeyValueStore({ locationPrefixEl.addEventListener('click', e => { e.preventDefault(); - const resp = prompt('Please enter new location: ', ''); - if ((resp !== null) && (resp !== "")) { + let resp = prompt('Please enter new location: ', ''); + if ((resp !== null) && (resp.trim() !== "")) { + resp = resp.trim(); + if (resp.indexOf('gopher://') === 0) { + resp = resp.substring(9); + } + window.location.href = window.location.origin + '/' + resp; } @@ -93,7 +102,7 @@ const settings = new KeyValueStore({ contentEl.classList.remove("content--wrap"); } - localStorage.setItem('image-previews', value ? '1' : '0'); + localStorage.setItem('word-wrap', value ? '1' : '0'); settingWordWrapValueEl.textContent = value ? '[yes]' : '[no]'; } @@ -105,6 +114,30 @@ const settings = new KeyValueStore({ settingWordWrapCallback(settings.getValue('wordWrap')); settings.addCallback('wordWrap', settingWordWrapCallback); + + // + + const clickablePlainLinksEl = document.getElementsByClassName('setting--clickable-plain-links')[0]; + const clickablePlainLinksValueEl = clickablePlainLinksEl.getElementsByClassName('setting__value')[0]; + const clickablePlainLinksCallback = (value: boolean) => { + if (value) { + generateMarkupForPlainLinks(); + } else { + removeMarkupForPlainLinks(); + } + + localStorage.setItem('clickable-plain-links', value ? '1' : '0'); + clickablePlainLinksValueEl.textContent = value ? '[yes]' : '[no]'; + } + + clickablePlainLinksValueEl.addEventListener('click', e => { + e.preventDefault(); + settings.cycleValue('clickablePlainLinks'); + return false; + }); + + clickablePlainLinksCallback(settings.getValue('clickablePlainLinks')); + settings.addCallback('clickablePlainLinks', clickablePlainLinksCallback); })(); (() => { @@ -211,3 +244,41 @@ function removeImageThumbnails() { } } } + +function generateMarkupForPlainLinks() { + if (!document.body.classList.contains('is-plain')) { + return; + } + + const contentEl = document.getElementsByClassName('content')[0]; + const urlRegex = /\b([a-z]*:\/\/[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b[-a-zA-Z0-9@:%_\+.~#?&//=]*)\b/g; + const mailRegex = /\bmailto:[-a-zA-Z0-9@:%._\+~#=]+@(?:[-a-zA-Z0-9@:%._\+~#=]+\.)+[a-z]{2,4}\b/g; + + contentEl.innerHTML = contentEl.innerHTML.replace(urlRegex, match => { + let href: string = match; + if (href.indexOf('gopher://') === 0) { + href = href.replace(/^gopher:\/\/(.*)$/, location.origin + '/$1'); + } + return `${match}`; + }); + + contentEl.innerHTML = contentEl.innerHTML.replace(mailRegex, match => { + return `${match}`; + }); +} + +function removeMarkupForPlainLinks() { + if (!document.body.classList.contains('is-plain')) { + return; + } + + const contentEl = document.getElementsByClassName('content')[0]; + const anchorEls = contentEl.getElementsByTagName('a'); + let i = anchorEls.length; + while (i--) { + const anchorEl = anchorEls[i]; + const textNodeEl = document.createTextNode(anchorEl.textContent!); + + contentEl.replaceChild(textNodeEl, anchorEl); + } +} -- cgit v1.2.3-70-g09d2