diff options
author | Feuerfuchs <git@feuerfuchs.dev> | 2019-06-26 20:16:19 +0200 |
---|---|---|
committer | Feuerfuchs <git@feuerfuchs.dev> | 2019-06-26 20:16:19 +0200 |
commit | 3bcc0b99e2d221243c3bcc2a5cc2a7f46c6a6d59 (patch) | |
tree | 94dec3e5d1203992e23e8c59c38acc63502f5aa7 | |
parent | Better ellipsis for location overflow (diff) | |
download | gopherproxy-3bcc0b99e2d221243c3bcc2a5cc2a7f46c6a6d59.tar.gz gopherproxy-3bcc0b99e2d221243c3bcc2a5cc2a7f46c6a6d59.tar.bz2 gopherproxy-3bcc0b99e2d221243c3bcc2a5cc2a7f46c6a6d59.zip |
New feature: Clickable links in plain text (opt)
-rw-r--r-- | assets/main.js | 2 | ||||
-rw-r--r-- | js/main.ts | 77 | ||||
-rw-r--r-- | template.go | 6 |
3 files changed, 80 insertions, 5 deletions
diff --git a/assets/main.js b/assets/main.js index 577a56e..4875dbf 100644 --- a/assets/main.js +++ b/assets/main.js | |||
@@ -1 +1 @@ | |||
"use strict";var KeyValueStore=function(){function e(e){this.data=e;for(var t=0,n=Object.keys(e);t<n.length;t++){var a=n[t],l=e[a];if(l.valueRange&&-1===l.valueRange.indexOf(l.value))throw new Error('Invalid value "'+l.value+'" for ID "'+a+'"')}}return e.prototype.getValue=function(e){return this.data[e].value},e.prototype.setValue=function(e,t){var n=this.data[e];if(n.valueRange&&-1===n.valueRange.indexOf(t))throw new Error('Invalid value "'+t+'" for ID "'+e+'"');n.value=t,n.callbacks&&n.callbacks.forEach(function(e){e(t)})},e.prototype.cycleValue=function(e,t){void 0===t&&(t=1);var n=this.data[e];if(!n)throw new Error('Invalid ID "'+e+'"');var a=n.value;if(n.valueRange){var l=n.valueRange.indexOf(a)+t;l>=n.valueRange.length?l=0:l<0&&(l=n.valueRange.length-1),a=n.value=n.valueRange[l]}else{if("number"!=typeof a)throw new Error("Can't cycle \""+e+'"');a+=t,n.value=a}return n.callbacks&&n.callbacks.forEach(function(e){e(a)}),a},e.prototype.addCallback=function(e,t){var n=this.data[e];n.callbacks||(n.callbacks=[]),n.callbacks.push(t)},e}();function ensureSetting(e,t){var n=localStorage.getItem(e);return null===n&&(n=t,localStorage.setItem(e,n)),n}var settings=new KeyValueStore({wordWrap:{value:"1"===ensureSetting("word-wrap","1"),valueRange:[!1,!0]},imagePreviews:{value:"1"===ensureSetting("image-previews","1"),valueRange:[!1,!0]}});function generateImageThumbnails(){for(var s=document.querySelectorAll(".link--IMG, .link--GIF"),i=s.length,e=function(){var e=s[i],t=e.href.replace(/^(.*?)\/I/,"$1/T"),n=document.createTextNode("\n"),a=document.createElement("span");a.classList.add("type-annotation"),a.textContent=" -> ";var l=document.createElement("img");l.src=t,l.addEventListener("load",function(e){l.classList.remove("faded")});var r=document.createElement("a");r.classList.add("img-preview"),r.href=e.href,r.addEventListener("click",function(e){return e.preventDefault(),l.classList.add("faded"),l.classList.contains("expanded")?(l.classList.remove("expanded"),l.src=t):(l.classList.add("expanded"),l.src=r.href),!1}),r.append(l),e.parentNode.insertBefore(r,e.nextSibling),e.parentNode.insertBefore(a,r),e.parentNode.insertBefore(n,a)};i--;)e()}function removeImageThumbnails(){for(var e=document.querySelectorAll(".link--IMG, .link--GIF"),t=e.length;t--;)for(var n=e[t],a=3;a--&&n.nextSibling;)n.nextSibling.remove()}!function(){for(var e=document.getElementsByClassName("link--QRY"),t=e.length;t--;)e[t].addEventListener("click",function(e){e.preventDefault();var t=prompt("Please enter required input: ","");return null!==t&&""!==t&&(window.location.href=e.target.href+"?"+t),!1})}(),document.getElementsByClassName("location__prefix")[0].addEventListener("click",function(e){e.preventDefault();var t=prompt("Please enter new location: ","");return null!==t&&""!==t&&(window.location.href=window.location.origin+"/"+t),!1}),function(){function e(e,t){void 0===t&&(t=!1),e?generateImageThumbnails():t||removeImageThumbnails(),localStorage.setItem("image-previews",e?"1":"0"),n.textContent=e?"[yes]":"[no]"}var t=document.getElementsByClassName("content")[0],n=document.getElementsByClassName("setting--image-previews")[0].getElementsByClassName("setting__value")[0];n.addEventListener("click",function(e){return e.preventDefault(),settings.cycleValue("imagePreviews"),!1}),e(settings.getValue("imagePreviews"),!0),settings.addCallback("imagePreviews",e);function a(e){e?t.classList.add("content--wrap"):t.classList.remove("content--wrap"),localStorage.setItem("image-previews",e?"1":"0"),l.textContent=e?"[yes]":"[no]"}var l=document.getElementsByClassName("setting--word-wrap")[0].getElementsByClassName("setting__value")[0];l.addEventListener("click",function(e){return e.preventDefault(),settings.cycleValue("wordWrap"),!1}),a(settings.getValue("wordWrap")),settings.addCallback("wordWrap",a)}(),function(){for(var a=document.getElementsByClassName("modal"),l=a.length,e=function(){var t=a[l],n=t.getElementsByClassName("modal__content")[0],e=t.getElementsByClassName("modal__close-btn")[0];document.addEventListener("click",function(e){t.classList.contains("modal--visible")&&(e.target===n||n.contains(e.target)||(t.classList.remove("modal--visible"),e.preventDefault(),e.stopPropagation()))},!0),document.addEventListener("keydown",function(e){t.classList.contains("modal--visible")&&27===e.keyCode&&t.classList.remove("modal--visible")}),e.addEventListener("click",function(e){return e.preventDefault(),t.classList.remove("modal--visible"),!1})};l--;)e();var t=document.getElementsByClassName("settings-btn")[0],n=document.getElementsByClassName("modal--settings")[0];t.addEventListener("click",function(e){return e.preventDefault(),n.classList.add("modal--visible"),!1})}(); \ No newline at end of file | "use strict";var KeyValueStore=function(){function e(e){this.data=e;for(var t=0,n=Object.keys(e);t<n.length;t++){var a=n[t],l=e[a];if(l.valueRange&&-1===l.valueRange.indexOf(l.value))throw new Error('Invalid value "'+l.value+'" for ID "'+a+'"')}}return e.prototype.getValue=function(e){return this.data[e].value},e.prototype.setValue=function(e,t){var n=this.data[e];if(n.valueRange&&-1===n.valueRange.indexOf(t))throw new Error('Invalid value "'+t+'" for ID "'+e+'"');n.value=t,n.callbacks&&n.callbacks.forEach(function(e){e(t)})},e.prototype.cycleValue=function(e,t){void 0===t&&(t=1);var n=this.data[e];if(!n)throw new Error('Invalid ID "'+e+'"');var a=n.value;if(n.valueRange){var l=n.valueRange.indexOf(a)+t;l>=n.valueRange.length?l=0:l<0&&(l=n.valueRange.length-1),a=n.value=n.valueRange[l]}else{if("number"!=typeof a)throw new Error("Can't cycle \""+e+'"');a+=t,n.value=a}return n.callbacks&&n.callbacks.forEach(function(e){e(a)}),a},e.prototype.addCallback=function(e,t){var n=this.data[e];n.callbacks||(n.callbacks=[]),n.callbacks.push(t)},e}();function ensureSetting(e,t){var n=localStorage.getItem(e);return null===n&&(n=t,localStorage.setItem(e,n)),n}var settings=new KeyValueStore({wordWrap:{value:"1"===ensureSetting("word-wrap","1"),valueRange:[!1,!0]},imagePreviews:{value:"1"===ensureSetting("image-previews","1"),valueRange:[!1,!0]},clickablePlainLinks:{value:"1"===ensureSetting("clickable-plain-links","1"),valueRange:[!1,!0]}});function generateImageThumbnails(){for(var r=document.querySelectorAll(".link--IMG, .link--GIF"),s=r.length,e=function(){var e=r[s],t=e.href.replace(/^(.*?)\/I/,"$1/T"),n=document.createTextNode("\n"),a=document.createElement("span");a.classList.add("type-annotation"),a.textContent=" -> ";var l=document.createElement("img");l.src=t,l.addEventListener("load",function(e){l.classList.remove("faded")});var i=document.createElement("a");i.classList.add("img-preview"),i.href=e.href,i.addEventListener("click",function(e){return e.preventDefault(),l.classList.add("faded"),l.classList.contains("expanded")?(l.classList.remove("expanded"),l.src=t):(l.classList.add("expanded"),l.src=i.href),!1}),i.append(l),e.parentNode.insertBefore(i,e.nextSibling),e.parentNode.insertBefore(a,i),e.parentNode.insertBefore(n,a)};s--;)e()}function removeImageThumbnails(){for(var e=document.querySelectorAll(".link--IMG, .link--GIF"),t=e.length;t--;)for(var n=e[t],a=3;a--&&n.nextSibling;)n.nextSibling.remove()}function generateMarkupForPlainLinks(){if(document.body.classList.contains("is-plain")){var e=document.getElementsByClassName("content")[0];e.innerHTML=e.innerHTML.replace(/\b([a-z]*:\/\/[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b[-a-zA-Z0-9@:%_\+.~#?&//=]*)\b/g,function(e){var t=e;return 0===t.indexOf("gopher://")&&(t=t.replace(/^gopher:\/\/(.*)$/,location.origin+"/$1")),'<a href="'+t+'">'+e+"</a>"}),e.innerHTML=e.innerHTML.replace(/\bmailto:[-a-zA-Z0-9@:%._\+~#=]+@(?:[-a-zA-Z0-9@:%._\+~#=]+\.)+[a-z]{2,4}\b/g,function(e){return'<a href="'+e+'">'+e+"</a>"})}}function removeMarkupForPlainLinks(){if(document.body.classList.contains("is-plain"))for(var e=document.getElementsByClassName("content")[0],t=e.getElementsByTagName("a"),n=t.length;n--;){var a=t[n],l=document.createTextNode(a.textContent);e.replaceChild(l,a)}}!function(){for(var e=document.getElementsByClassName("link--QRY"),t=e.length;t--;)e[t].addEventListener("click",function(e){e.preventDefault();var t=prompt("Please enter required input: ","");return null!==t&&""!==t&&(window.location.href=e.target.href+"?"+t),!1})}(),document.getElementsByClassName("location__prefix")[0].addEventListener("click",function(e){e.preventDefault();var t=prompt("Please enter new location: ","");return null!==t&&""!==t.trim()&&(0===(t=t.trim()).indexOf("gopher://")&&(t=t.substring(9)),window.location.href=window.location.origin+"/"+t),!1}),function(){function e(e,t){void 0===t&&(t=!1),e?generateImageThumbnails():t||removeImageThumbnails(),localStorage.setItem("image-previews",e?"1":"0"),n.textContent=e?"[yes]":"[no]"}var t=document.getElementsByClassName("content")[0],n=document.getElementsByClassName("setting--image-previews")[0].getElementsByClassName("setting__value")[0];n.addEventListener("click",function(e){return e.preventDefault(),settings.cycleValue("imagePreviews"),!1}),e(settings.getValue("imagePreviews"),!0),settings.addCallback("imagePreviews",e);function a(e){e?t.classList.add("content--wrap"):t.classList.remove("content--wrap"),localStorage.setItem("word-wrap",e?"1":"0"),l.textContent=e?"[yes]":"[no]"}var l=document.getElementsByClassName("setting--word-wrap")[0].getElementsByClassName("setting__value")[0];l.addEventListener("click",function(e){return e.preventDefault(),settings.cycleValue("wordWrap"),!1}),a(settings.getValue("wordWrap")),settings.addCallback("wordWrap",a);function i(e){e?generateMarkupForPlainLinks():removeMarkupForPlainLinks(),localStorage.setItem("clickable-plain-links",e?"1":"0"),r.textContent=e?"[yes]":"[no]"}var r=document.getElementsByClassName("setting--clickable-plain-links")[0].getElementsByClassName("setting__value")[0];r.addEventListener("click",function(e){return e.preventDefault(),settings.cycleValue("clickablePlainLinks"),!1}),i(settings.getValue("clickablePlainLinks")),settings.addCallback("clickablePlainLinks",i)}(),function(){for(var a=document.getElementsByClassName("modal"),l=a.length,e=function(){var t=a[l],n=t.getElementsByClassName("modal__content")[0],e=t.getElementsByClassName("modal__close-btn")[0];document.addEventListener("click",function(e){t.classList.contains("modal--visible")&&(e.target===n||n.contains(e.target)||(t.classList.remove("modal--visible"),e.preventDefault(),e.stopPropagation()))},!0),document.addEventListener("keydown",function(e){t.classList.contains("modal--visible")&&27===e.keyCode&&t.classList.remove("modal--visible")}),e.addEventListener("click",function(e){return e.preventDefault(),t.classList.remove("modal--visible"),!1})};l--;)e();var t=document.getElementsByClassName("settings-btn")[0],n=document.getElementsByClassName("modal--settings")[0];t.addEventListener("click",function(e){return e.preventDefault(),n.classList.add("modal--visible"),!1})}(); \ No newline at end of file | ||
@@ -20,6 +20,10 @@ const settings = new KeyValueStore({ | |||
20 | value: ensureSetting('image-previews', '1') === '1', | 20 | value: ensureSetting('image-previews', '1') === '1', |
21 | valueRange: [false, true] | 21 | valueRange: [false, true] |
22 | }, | 22 | }, |
23 | clickablePlainLinks: { | ||
24 | value: ensureSetting('clickable-plain-links', '1') === '1', | ||
25 | valueRange: [false, true] | ||
26 | }, | ||
23 | }); | 27 | }); |
24 | 28 | ||
25 | // | 29 | // |
@@ -46,8 +50,13 @@ const settings = new KeyValueStore({ | |||
46 | locationPrefixEl.addEventListener('click', e => { | 50 | locationPrefixEl.addEventListener('click', e => { |
47 | e.preventDefault(); | 51 | e.preventDefault(); |
48 | 52 | ||
49 | const resp = prompt('Please enter new location: ', ''); | 53 | let resp = prompt('Please enter new location: ', ''); |
50 | if ((resp !== null) && (resp !== "")) { | 54 | if ((resp !== null) && (resp.trim() !== "")) { |
55 | resp = resp.trim(); | ||
56 | if (resp.indexOf('gopher://') === 0) { | ||
57 | resp = resp.substring(9); | ||
58 | } | ||
59 | |||
51 | window.location.href = window.location.origin + '/' + resp; | 60 | window.location.href = window.location.origin + '/' + resp; |
52 | } | 61 | } |
53 | 62 | ||
@@ -93,7 +102,7 @@ const settings = new KeyValueStore({ | |||
93 | contentEl.classList.remove("content--wrap"); | 102 | contentEl.classList.remove("content--wrap"); |
94 | } | 103 | } |
95 | 104 | ||
96 | localStorage.setItem('image-previews', value ? '1' : '0'); | 105 | localStorage.setItem('word-wrap', value ? '1' : '0'); |
97 | settingWordWrapValueEl.textContent = value ? '[yes]' : '[no]'; | 106 | settingWordWrapValueEl.textContent = value ? '[yes]' : '[no]'; |
98 | } | 107 | } |
99 | 108 | ||
@@ -105,6 +114,30 @@ const settings = new KeyValueStore({ | |||
105 | 114 | ||
106 | settingWordWrapCallback(settings.getValue('wordWrap')); | 115 | settingWordWrapCallback(settings.getValue('wordWrap')); |
107 | settings.addCallback('wordWrap', settingWordWrapCallback); | 116 | settings.addCallback('wordWrap', settingWordWrapCallback); |
117 | |||
118 | // | ||
119 | |||
120 | const clickablePlainLinksEl = document.getElementsByClassName('setting--clickable-plain-links')[0]; | ||
121 | const clickablePlainLinksValueEl = clickablePlainLinksEl.getElementsByClassName('setting__value')[0]; | ||
122 | const clickablePlainLinksCallback = (value: boolean) => { | ||
123 | if (value) { | ||
124 | generateMarkupForPlainLinks(); | ||
125 | } else { | ||
126 | removeMarkupForPlainLinks(); | ||
127 | } | ||
128 | |||
129 | localStorage.setItem('clickable-plain-links', value ? '1' : '0'); | ||
130 | clickablePlainLinksValueEl.textContent = value ? '[yes]' : '[no]'; | ||
131 | } | ||
132 | |||
133 | clickablePlainLinksValueEl.addEventListener('click', e => { | ||
134 | e.preventDefault(); | ||
135 | settings.cycleValue('clickablePlainLinks'); | ||
136 | return false; | ||
137 | }); | ||
138 | |||
139 | clickablePlainLinksCallback(settings.getValue('clickablePlainLinks')); | ||
140 | settings.addCallback('clickablePlainLinks', clickablePlainLinksCallback); | ||
108 | })(); | 141 | })(); |
109 | 142 | ||
110 | (() => { | 143 | (() => { |
@@ -211,3 +244,41 @@ function removeImageThumbnails() { | |||
211 | } | 244 | } |
212 | } | 245 | } |
213 | } | 246 | } |
247 | |||
248 | function generateMarkupForPlainLinks() { | ||
249 | if (!document.body.classList.contains('is-plain')) { | ||
250 | return; | ||
251 | } | ||
252 | |||
253 | const contentEl = document.getElementsByClassName('content')[0]; | ||
254 | const urlRegex = /\b([a-z]*:\/\/[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b[-a-zA-Z0-9@:%_\+.~#?&//=]*)\b/g; | ||
255 | const mailRegex = /\bmailto:[-a-zA-Z0-9@:%._\+~#=]+@(?:[-a-zA-Z0-9@:%._\+~#=]+\.)+[a-z]{2,4}\b/g; | ||
256 | |||
257 | contentEl.innerHTML = contentEl.innerHTML.replace(urlRegex, match => { | ||
258 | let href: string = match; | ||
259 | if (href.indexOf('gopher://') === 0) { | ||
260 | href = href.replace(/^gopher:\/\/(.*)$/, location.origin + '/$1'); | ||
261 | } | ||
262 | return `<a href="${href}">${match}</a>`; | ||
263 | }); | ||
264 | |||
265 | contentEl.innerHTML = contentEl.innerHTML.replace(mailRegex, match => { | ||
266 | return `<a href="${match}">${match}</a>`; | ||
267 | }); | ||
268 | } | ||
269 | |||
270 | function removeMarkupForPlainLinks() { | ||
271 | if (!document.body.classList.contains('is-plain')) { | ||
272 | return; | ||
273 | } | ||
274 | |||
275 | const contentEl = document.getElementsByClassName('content')[0]; | ||
276 | const anchorEls = contentEl.getElementsByTagName('a'); | ||
277 | let i = anchorEls.length; | ||
278 | while (i--) { | ||
279 | const anchorEl = anchorEls[i]; | ||
280 | const textNodeEl = document.createTextNode(anchorEl.textContent!); | ||
281 | |||
282 | contentEl.replaceChild(textNodeEl, anchorEl); | ||
283 | } | ||
284 | } | ||
diff --git a/template.go b/template.go index 3d95838..583a50b 100644 --- a/template.go +++ b/template.go | |||
@@ -11,7 +11,7 @@ var tpltext = `<!doctype html> | |||
11 | {{ .Style | safeCss }} | 11 | {{ .Style | safeCss }} |
12 | </style> | 12 | </style> |
13 | </head> | 13 | </head> |
14 | <body> | 14 | <body class="{{ if not .Lines }}is-plain{{ end }}"> |
15 | <header class="header header-base"> | 15 | <header class="header header-base"> |
16 | <div class="location"> | 16 | <div class="location"> |
17 | {{- $href := "" -}} | 17 | {{- $href := "" -}} |
@@ -85,6 +85,10 @@ var tpltext = `<!doctype html> | |||
85 | <strong class="setting__label">Image thumbnails</strong> | 85 | <strong class="setting__label">Image thumbnails</strong> |
86 | <button class="setting__value">[N/A]</button> | 86 | <button class="setting__value">[N/A]</button> |
87 | </div> | 87 | </div> |
88 | <div class="setting setting--clickable-plain-links"> | ||
89 | <strong class="setting__label">Clickable links in text files</strong> | ||
90 | <button class="setting__value">[N/A]</button> | ||
91 | </div> | ||
88 | </div> | 92 | </div> |
89 | </aside> | 93 | </aside> |
90 | <script type="text/javascript"> | 94 | <script type="text/javascript"> |