diff options
| -rw-r--r-- | Makefile | 4 | ||||
| -rw-r--r-- | assets/iosevka-term-ss03-regular.woff | bin | 12332 -> 12136 bytes | |||
| -rw-r--r-- | assets/main.js | 2 | ||||
| -rw-r--r-- | go.mod | 2 | ||||
| -rw-r--r-- | gopherproxy.go | 63 | ||||
| -rw-r--r-- | template.go | 10 |
6 files changed, 53 insertions, 28 deletions
| @@ -7,8 +7,8 @@ dev: build | |||
| 7 | 7 | ||
| 8 | build: clean | 8 | build: clean |
| 9 | sassc -t compressed css/main.scss assets/style.css | 9 | sassc -t compressed css/main.scss assets/style.css |
| 10 | tsc --strict --module none --outFile /dev/stdout js/* | uglifyjs -c -m -o assets/main.js -- | 10 | tsc --strict --module none --outFile /dev/stdout js/* | terser --compress --mangle -o assets/main.js -- |
| 11 | pyftsubset fonts/iosevka-term-ss03-regular.ttf --name-IDs+=0,4,6 --text-file=fonts/glyphs.txt --flavor='woff' --output-file='assets/iosevka-term-ss03-regular.woff' | 11 | pyftsubset fonts/iosevka-term-ss03-regular.ttf --name-IDs+=0,4,6 --text-file=fonts/glyphs.txt --flavor='woff' --with-zopfli --output-file='assets/iosevka-term-ss03-regular.woff' |
| 12 | pyftsubset fonts/iosevka-term-ss03-regular.ttf --name-IDs+=0,4,6 --text-file=fonts/glyphs.txt --flavor='woff2' --output-file='assets/iosevka-term-ss03-regular.woff2' | 12 | pyftsubset fonts/iosevka-term-ss03-regular.ttf --name-IDs+=0,4,6 --text-file=fonts/glyphs.txt --flavor='woff2' --output-file='assets/iosevka-term-ss03-regular.woff2' |
| 13 | go build -o ./gopherproxy ./cmd/gopherproxy/main.go | 13 | go build -o ./gopherproxy ./cmd/gopherproxy/main.go |
| 14 | 14 | ||
diff --git a/assets/iosevka-term-ss03-regular.woff b/assets/iosevka-term-ss03-regular.woff index 498d93d..256e1ab 100644 --- a/assets/iosevka-term-ss03-regular.woff +++ b/assets/iosevka-term-ss03-regular.woff | |||
| Binary files differ | |||
diff --git a/assets/main.js b/assets/main.js index 33aa76d..a30a250 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"),callbacks:[function(e){localStorage.setItem("word-wrap",e?"1":"0")}],valueRange:[!1,!0]},imagePreviews:{value:"1"===ensureSetting("image-previews","1"),callbacks:[function(e){localStorage.setItem("image-previews",e?"1":"0")}],valueRange:[!1,!0]},clickablePlainLinks:{value:"1"===ensureSetting("clickable-plain-links","1"),callbacks:[function(e){localStorage.setItem("clickable-plain-links",e?"1":"0")}],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,}\b[-a-zA-Z0-9@:%_\+.~#?&//=]*/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,}\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})}(),function(){for(var e=document.getElementsByClassName("location__prefix"),t=e.length;t--;)e[t].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(),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"),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(),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 | "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"),callbacks:[function(e){localStorage.setItem("word-wrap",e?"1":"0")}],valueRange:[!1,!0]},imagePreviews:{value:"1"===ensureSetting("image-previews","1"),callbacks:[function(e){localStorage.setItem("image-previews",e?"1":"0")}],valueRange:[!1,!0]},clickablePlainLinks:{value:"1"===ensureSetting("clickable-plain-links","1"),callbacks:[function(e){localStorage.setItem("clickable-plain-links",e?"1":"0")}],valueRange:[!1,!0]}});function generateImageThumbnails(){for(var e=document.querySelectorAll(".link--IMG, .link--GIF"),t=e.length,n=function(){var n=e[t],a=n.href.replace(/^(.*?)\/I/,"$1/T"),l=document.createTextNode("\n"),i=document.createElement("span");i.classList.add("type-annotation"),i.textContent=" -> ";var r=document.createElement("img");r.src=a,r.addEventListener("load",(function(e){r.classList.remove("faded")}));var s=document.createElement("a");s.classList.add("img-preview"),s.href=n.href,s.addEventListener("click",(function(e){return e.preventDefault(),r.classList.add("faded"),r.classList.contains("expanded")?(r.classList.remove("expanded"),r.src=a):(r.classList.add("expanded"),r.src=s.href),!1})),s.append(r),n.parentNode.insertBefore(s,n.nextSibling),n.parentNode.insertBefore(i,s),n.parentNode.insertBefore(l,i)};t--;)n()}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,}\b[-a-zA-Z0-9@:%_\+.~#?&//=]*/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,}\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}))}(),function(){for(var e=document.getElementsByClassName("location__prefix"),t=e.length;t--;)e[t].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(){var e=document.getElementsByClassName("content")[0],t=document.getElementsByClassName("setting--image-previews")[0].getElementsByClassName("setting__value")[0],n=function(e,n){void 0===n&&(n=!1),e?generateImageThumbnails():n||removeImageThumbnails(),t.textContent=e?"[yes]":"[no]"};t.addEventListener("click",(function(e){return e.preventDefault(),settings.cycleValue("imagePreviews"),!1})),n(settings.getValue("imagePreviews"),!0),settings.addCallback("imagePreviews",n);var a=document.getElementsByClassName("setting--word-wrap")[0].getElementsByClassName("setting__value")[0],l=function(t){t?e.classList.add("content--wrap"):e.classList.remove("content--wrap"),a.textContent=t?"[yes]":"[no]"};a.addEventListener("click",(function(e){return e.preventDefault(),settings.cycleValue("wordWrap"),!1})),l(settings.getValue("wordWrap")),settings.addCallback("wordWrap",l);var i=document.getElementsByClassName("setting--clickable-plain-links")[0].getElementsByClassName("setting__value")[0],r=function(e){e?generateMarkupForPlainLinks():removeMarkupForPlainLinks(),i.textContent=e?"[yes]":"[no]"};i.addEventListener("click",(function(e){return e.preventDefault(),settings.cycleValue("clickablePlainLinks"),!1})),r(settings.getValue("clickablePlainLinks")),settings.addCallback("clickablePlainLinks",r)}(),function(){for(var e=document.getElementsByClassName("modal"),t=e.length,n=function(){var n=e[t],a=n.getElementsByClassName("modal__content")[0],l=n.getElementsByClassName("modal__close-btn")[0];document.addEventListener("click",(function(e){n.classList.contains("modal--visible")&&(e.target===a||a.contains(e.target)||(n.classList.remove("modal--visible"),e.preventDefault(),e.stopPropagation()))}),!0),document.addEventListener("keydown",(function(e){n.classList.contains("modal--visible")&&27===e.keyCode&&n.classList.remove("modal--visible")})),l.addEventListener("click",(function(e){return e.preventDefault(),n.classList.remove("modal--visible"),!1}))};t--;)n();var a=document.getElementsByClassName("settings-btn")[0],l=document.getElementsByClassName("modal--settings")[0];a.addEventListener("click",(function(e){return e.preventDefault(),l.classList.add("modal--visible"),!1}))}(); \ No newline at end of file | ||
| @@ -7,3 +7,5 @@ require ( | |||
| 7 | github.com/prologic/go-gopher v0.0.0-20181230133552-0c68ed5f58b0 | 7 | github.com/prologic/go-gopher v0.0.0-20181230133552-0c68ed5f58b0 |
| 8 | github.com/temoto/robotstxt v0.0.0-20180810133444-97ee4a9ee6ea | 8 | github.com/temoto/robotstxt v0.0.0-20180810133444-97ee4a9ee6ea |
| 9 | ) | 9 | ) |
| 10 | |||
| 11 | go 1.13 | ||
diff --git a/gopherproxy.go b/gopherproxy.go index 6490b28..0b3279c 100644 --- a/gopherproxy.go +++ b/gopherproxy.go | |||
| @@ -29,14 +29,14 @@ type Item struct { | |||
| 29 | Text string | 29 | Text string |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | type AssetHashList struct { | 32 | type AssetList struct { |
| 33 | Style string | 33 | Style string |
| 34 | JS string | 34 | JS string |
| 35 | FontW string | 35 | FontW string |
| 36 | FontW2 string | 36 | FontW2 string |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | func renderDirectory(w http.ResponseWriter, tpl *template.Template, assetHashList AssetHashList, uri string, hostport string, d gopher.Directory) error { | 39 | func renderDirectory(w http.ResponseWriter, tpl *template.Template, assetList AssetList, uri string, hostport string, d gopher.Directory) error { |
| 40 | var title string | 40 | var title string |
| 41 | 41 | ||
| 42 | out := make([]Item, len(d.Items)) | 42 | out := make([]Item, len(d.Items)) |
| @@ -88,10 +88,11 @@ func renderDirectory(w http.ResponseWriter, tpl *template.Template, assetHashLis | |||
| 88 | return tpl.Execute(w, struct { | 88 | return tpl.Execute(w, struct { |
| 89 | Title string | 89 | Title string |
| 90 | URI string | 90 | URI string |
| 91 | AssetHashList AssetHashList | 91 | Assets AssetList |
| 92 | Lines []Item | 92 | Lines []Item |
| 93 | RawText string | 93 | RawText string |
| 94 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetHashList, out, ""}) | 94 | Error bool |
| 95 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, out, "", false}) | ||
| 95 | } | 96 | } |
| 96 | 97 | ||
| 97 | // GopherHandler returns a Handler that proxies requests | 98 | // GopherHandler returns a Handler that proxies requests |
| @@ -99,7 +100,7 @@ func renderDirectory(w http.ResponseWriter, tpl *template.Template, assetHashLis | |||
| 99 | // to the request path and renders the content using the provided template. | 100 | // to the request path and renders the content using the provided template. |
| 100 | // The optional robots parameters points to a robotstxt.RobotsData struct | 101 | // The optional robots parameters points to a robotstxt.RobotsData struct |
| 101 | // to test user agents against a configurable robotst.txt file. | 102 | // to test user agents against a configurable robotst.txt file. |
| 102 | func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, assetHashList AssetHashList, robotsdebug bool, uri string) http.HandlerFunc { | 103 | func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, assetList AssetList, robotsdebug bool, uri string) http.HandlerFunc { |
| 103 | return func(w http.ResponseWriter, req *http.Request) { | 104 | return func(w http.ResponseWriter, req *http.Request) { |
| 104 | agent := req.UserAgent() | 105 | agent := req.UserAgent() |
| 105 | path := strings.TrimPrefix(req.URL.Path, "/") | 106 | path := strings.TrimPrefix(req.URL.Path, "/") |
| @@ -124,7 +125,14 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 124 | 125 | ||
| 125 | uri, err := url.QueryUnescape(strings.Join(parts[1:], "/")) | 126 | uri, err := url.QueryUnescape(strings.Join(parts[1:], "/")) |
| 126 | if err != nil { | 127 | if err != nil { |
| 127 | io.WriteString(w, fmt.Sprintf("<b>Error:</b><pre>%s</pre>", err)) | 128 | tpl.Execute(w, struct { |
| 129 | Title string | ||
| 130 | URI string | ||
| 131 | Assets AssetList | ||
| 132 | RawText string | ||
| 133 | Lines []Item | ||
| 134 | Error bool | ||
| 135 | }{uri, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true}) | ||
| 128 | return | 136 | return |
| 129 | } | 137 | } |
| 130 | 138 | ||
| @@ -138,7 +146,14 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 138 | ) | 146 | ) |
| 139 | 147 | ||
| 140 | if err != nil { | 148 | if err != nil { |
| 141 | io.WriteString(w, fmt.Sprintf("<b>Error:</b><pre>%s</pre>", err)) | 149 | tpl.Execute(w, struct { |
| 150 | Title string | ||
| 151 | URI string | ||
| 152 | Assets AssetList | ||
| 153 | RawText string | ||
| 154 | Lines []Item | ||
| 155 | Error bool | ||
| 156 | }{uri, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true}) | ||
| 142 | return | 157 | return |
| 143 | } | 158 | } |
| 144 | 159 | ||
| @@ -152,10 +167,11 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 152 | tpl.Execute(w, struct { | 167 | tpl.Execute(w, struct { |
| 153 | Title string | 168 | Title string |
| 154 | URI string | 169 | URI string |
| 155 | AssetHashList AssetHashList | 170 | Assets AssetList |
| 156 | RawText string | 171 | RawText string |
| 157 | Lines []Item | 172 | Lines []Item |
| 158 | }{uri, fmt.Sprintf("%s/%s", hostport, uri), assetHashList, buf.String(), nil}) | 173 | Error bool |
| 174 | }{uri, fmt.Sprintf("%s/%s", hostport, uri), assetList, buf.String(), nil, false}) | ||
| 159 | } else if parts[1] == "T" { | 175 | } else if parts[1] == "T" { |
| 160 | _, _, err = vips.NewTransform(). | 176 | _, _, err = vips.NewTransform(). |
| 161 | Load(res.Body). | 177 | Load(res.Body). |
| @@ -168,8 +184,15 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 168 | io.Copy(w, res.Body) | 184 | io.Copy(w, res.Body) |
| 169 | } | 185 | } |
| 170 | } else { | 186 | } else { |
| 171 | if err := renderDirectory(w, tpl, assetHashList, uri, hostport, res.Dir); err != nil { | 187 | if err := renderDirectory(w, tpl, assetList, uri, hostport, res.Dir); err != nil { |
| 172 | io.WriteString(w, fmt.Sprintf("<b>Error:</b><pre>%s</pre>", err)) | 188 | tpl.Execute(w, struct { |
| 189 | Title string | ||
| 190 | URI string | ||
| 191 | Assets AssetList | ||
| 192 | RawText string | ||
| 193 | Lines []Item | ||
| 194 | Error bool | ||
| 195 | }{uri, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true}) | ||
| 173 | return | 196 | return |
| 174 | } | 197 | } |
| 175 | } | 198 | } |
| @@ -268,25 +291,25 @@ func ListenAndServe(bind, robotsfile string, robotsdebug bool, vipsconcurrency i | |||
| 268 | if err != nil { | 291 | if err != nil { |
| 269 | fontdataw = []byte{} | 292 | fontdataw = []byte{} |
| 270 | } | 293 | } |
| 271 | fontwhash := fmt.Sprintf("%x", md5.Sum(fontdataw)) | 294 | fontwAsset := fmt.Sprintf("/iosevka-term-ss03-regular-%x.woff", md5.Sum(fontdataw)) |
| 272 | 295 | ||
| 273 | fontdataw2, err := box.Find("iosevka-term-ss03-regular.woff2") | 296 | fontdataw2, err := box.Find("iosevka-term-ss03-regular.woff2") |
| 274 | if err != nil { | 297 | if err != nil { |
| 275 | fontdataw2 = []byte{} | 298 | fontdataw2 = []byte{} |
| 276 | } | 299 | } |
| 277 | fontw2hash := fmt.Sprintf("%x", md5.Sum(fontdataw2)) | 300 | fontw2Asset := fmt.Sprintf("/iosevka-term-ss03-regular-%x.woff2", md5.Sum(fontdataw2)) |
| 278 | 301 | ||
| 279 | styledata, err := box.Find("style.css") | 302 | styledata, err := box.Find("style.css") |
| 280 | if err != nil { | 303 | if err != nil { |
| 281 | styledata = []byte{} | 304 | styledata = []byte{} |
| 282 | } | 305 | } |
| 283 | stylehash := fmt.Sprintf("%x", md5.Sum(styledata)) | 306 | styleAsset := fmt.Sprintf("/style-%x.css", md5.Sum(styledata)) |
| 284 | 307 | ||
| 285 | jsdata, err := box.Find("main.js") | 308 | jsdata, err := box.Find("main.js") |
| 286 | if err != nil { | 309 | if err != nil { |
| 287 | jsdata = []byte{} | 310 | jsdata = []byte{} |
| 288 | } | 311 | } |
| 289 | jshash := fmt.Sprintf("%x", md5.Sum(jsdata)) | 312 | jsAsset := fmt.Sprintf("/main-%x.js", md5.Sum(jsdata)) |
| 290 | 313 | ||
| 291 | favicondata, err := box.Find("favicon.ico") | 314 | favicondata, err := box.Find("favicon.ico") |
| 292 | if err != nil { | 315 | if err != nil { |
| @@ -334,13 +357,13 @@ func ListenAndServe(bind, robotsfile string, robotsdebug bool, vipsconcurrency i | |||
| 334 | ConcurrencyLevel: vipsconcurrency, | 357 | ConcurrencyLevel: vipsconcurrency, |
| 335 | }) | 358 | }) |
| 336 | 359 | ||
| 337 | http.HandleFunc("/", GopherHandler(tpl, robotsdata, AssetHashList{stylehash, jshash, fontwhash, fontw2hash}, robotsdebug, uri)) | 360 | http.HandleFunc("/", GopherHandler(tpl, robotsdata, AssetList{styleAsset, jsAsset, fontwAsset, fontw2Asset}, robotsdebug, uri)) |
| 338 | http.HandleFunc("/robots.txt", RobotsTxtHandler(robotstxtdata)) | 361 | http.HandleFunc("/robots.txt", RobotsTxtHandler(robotstxtdata)) |
| 339 | http.HandleFunc("/favicon.ico", FaviconHandler(favicondata)) | 362 | http.HandleFunc("/favicon.ico", FaviconHandler(favicondata)) |
| 340 | http.HandleFunc("/style-"+stylehash+".css", StyleHandler(styledata)) | 363 | http.HandleFunc(styleAsset, StyleHandler(styledata)) |
| 341 | http.HandleFunc("/main-"+jshash+".js", JavaScriptHandler(jsdata)) | 364 | http.HandleFunc(jsAsset, JavaScriptHandler(jsdata)) |
| 342 | http.HandleFunc("/iosevka-term-ss03-regular-"+fontwhash+".woff", FontHandler(false, fontdataw)) | 365 | http.HandleFunc(fontwAsset, FontHandler(false, fontdataw)) |
| 343 | http.HandleFunc("/iosevka-term-ss03-regular-"+fontw2hash+".woff2", FontHandler(true, fontdataw2)) | 366 | http.HandleFunc(fontw2Asset, FontHandler(true, fontdataw2)) |
| 344 | //http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("assets/")))) | 367 | //http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("assets/")))) |
| 345 | 368 | ||
| 346 | return http.ListenAndServe(bind, nil) | 369 | return http.ListenAndServe(bind, nil) |
diff --git a/template.go b/template.go index cb37aff..f58349e 100644 --- a/template.go +++ b/template.go | |||
| @@ -6,14 +6,14 @@ var tpltext = `<!doctype html> | |||
| 6 | <meta charset="utf-8"> | 6 | <meta charset="utf-8"> |
| 7 | <meta name="viewport" content="width=device-width, initial-scale=1" /> | 7 | <meta name="viewport" content="width=device-width, initial-scale=1" /> |
| 8 | <title>{{ .Title }}</title> | 8 | <title>{{ .Title }}</title> |
| 9 | <link rel="stylesheet" href="/style-{{ .AssetHashList.Style }}.css" /> | 9 | <link rel="stylesheet" href="{{ .Assets.Style }}" /> |
| 10 | <style> | 10 | <style> |
| 11 | @font-face { | 11 | @font-face { |
| 12 | font-family: 'Iosevka Term SS03'; | 12 | font-family: 'Iosevka Term SS03'; |
| 13 | font-style: normal; | 13 | font-style: normal; |
| 14 | font-weight: normal; | 14 | font-weight: normal; |
| 15 | src: url('/iosevka-term-ss03-regular-{{ .AssetHashList.FontW2 }}.woff2') format('woff2'), | 15 | src: url('{{ .Assets.FontW2 }}') format('woff2'), |
| 16 | url('/iosevka-term-ss03-regular-{{ .AssetHashList.FontW }}.woff') format('woff'); | 16 | url('{{ .Assets.FontW }}') format('woff'); |
| 17 | } | 17 | } |
| 18 | </style> | 18 | </style> |
| 19 | </head> | 19 | </head> |
| @@ -51,7 +51,7 @@ var tpltext = `<!doctype html> | |||
| 51 | <span class="location__uripart">{{ $uriLast -}}</span> | 51 | <span class="location__uripart">{{ $uriLast -}}</span> |
| 52 | </div> | 52 | </div> |
| 53 | <div class="actions"> | 53 | <div class="actions"> |
| 54 | {{- if not .Lines -}} | 54 | {{- if and (not .Lines) (not .Error) -}} |
| 55 | <div class="action"><a href="/{{ .URI | replace "^(.*?)/0" "$1/9" }}">View raw</a></div> | 55 | <div class="action"><a href="/{{ .URI | replace "^(.*?)/0" "$1/9" }}">View raw</a></div> |
| 56 | {{- end -}} | 56 | {{- end -}} |
| 57 | <div class="action"><button class="settings-btn">Settings</button></div> | 57 | <div class="action"><button class="settings-btn">Settings</button></div> |
| @@ -97,6 +97,6 @@ var tpltext = `<!doctype html> | |||
| 97 | </div> | 97 | </div> |
| 98 | </div> | 98 | </div> |
| 99 | </aside> | 99 | </aside> |
| 100 | <script src="/main-{{ .AssetHashList.JS }}.js"></script> | 100 | <script src="{{ .Assets.JS }}"></script> |
| 101 | </body> | 101 | </body> |
| 102 | </html>` | 102 | </html>` |
