From c772716e98e11181d301deadeca52856ac18f085 Mon Sep 17 00:00:00 2001
From: Feuerfuchs <git@feuerfuchs.dev>
Date: Mon, 18 May 2020 18:51:19 +0200
Subject: Improved Gemini support

---
 internal/port/gemini.go          | 36 ++++++++++++++++++++++++++++++++++--
 internal/port/gopher.go          | 16 ++++++++++------
 internal/port/main.go            |  6 ++++++
 internal/port/tpl/gemini.html    | 11 ++++++++---
 internal/port/tpl/gopher.html    |  2 +-
 internal/port/tpl/startpage.html |  2 +-
 6 files changed, 60 insertions(+), 13 deletions(-)

(limited to 'internal/port')

diff --git a/internal/port/gemini.go b/internal/port/gemini.go
index 740fccd..f67ca05 100644
--- a/internal/port/gemini.go
+++ b/internal/port/gemini.go
@@ -29,8 +29,9 @@ type GeminiTemplateVariables struct {
 }
 
 type GeminiNavItem struct {
-	Label string
-	URL   string
+	Label   string
+	URL     string
+	Current bool
 }
 
 type GeminiSection struct {
@@ -40,6 +41,32 @@ type GeminiSection struct {
 	Items []string
 }
 
+func urlToGeminiNav(url string) (items []GeminiNavItem) {
+	partialURL := "/gemini"
+	parts := strings.Split(url, "/")
+
+	if len(parts) != 0 && parts[len(parts)-1] == "" {
+		parts = parts[:len(parts)-1]
+	}
+
+	for i, part := range parts {
+		partialURL = partialURL + "/" + part
+
+		current := false
+		if i == len(parts)-1 || (len(parts) == 2 && i == 0) {
+			current = true
+		}
+
+		items = append(items, GeminiNavItem{
+			Label:   part,
+			URL:     partialURL,
+			Current: current,
+		})
+	}
+
+	return
+}
+
 func resolveURL(uri string, baseURL *url.URL) (resolvedURL string) {
 	if strings.HasPrefix(uri, "//") {
 		resolvedURL = "/gemini/" + strings.TrimPrefix(uri, "//")
@@ -137,6 +164,7 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass
 					Type: libgemini.RAW_TEXT.String(),
 					Text: fmt.Sprintf("Error: %s", err),
 				}},
+				Nav:     urlToGeminiNav(hostport),
 				IsPlain: true,
 			}); e != nil {
 				log.Println("Template error: " + e.Error())
@@ -167,6 +195,7 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass
 					Type: libgemini.RAW_TEXT.String(),
 					Text: fmt.Sprintf("Error: %s", err),
 				}},
+				Nav:     urlToGeminiNav(fmt.Sprintf("%s/%s", hostport, uri)),
 				IsPlain: true,
 			}); e != nil {
 				log.Println("Template error: " + e.Error())
@@ -190,6 +219,7 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass
 						Type: libgemini.RAW_TEXT.String(),
 						Text: fmt.Sprintf("Error: %s", err),
 					}},
+					Nav:     urlToGeminiNav(fmt.Sprintf("%s/%s", hostport, uri)),
 					IsPlain: true,
 				}); e != nil {
 					log.Println("Template error: " + e.Error())
@@ -211,6 +241,7 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass
 					Type: libgemini.RAW_TEXT.String(),
 					Text: fmt.Sprintf("Error %d: %s", res.Header.Status, res.Header.Meta),
 				}},
+				Nav:     urlToGeminiNav(fmt.Sprintf("%s/%s", hostport, uri)),
 				IsPlain: true,
 			}); err != nil {
 				log.Println("Template error: " + err.Error())
@@ -252,6 +283,7 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass
 				URL:      fmt.Sprintf("%s/%s", hostport, uri),
 				Assets:   assetList,
 				Sections: sections,
+				Nav:      urlToGeminiNav(fmt.Sprintf("%s/%s", hostport, uri)),
 				IsPlain:  isPlain,
 			}); err != nil {
 				log.Println("Template error: " + err.Error())
diff --git a/internal/port/gopher.go b/internal/port/gopher.go
index d2283c6..cb5e60c 100644
--- a/internal/port/gopher.go
+++ b/internal/port/gopher.go
@@ -49,10 +49,14 @@ func trimLeftChars(s string, n int) string {
 	return s[:0]
 }
 
-func urlToNav(url string) (items []GopherNavItem) {
+func urlToGopherNav(url string) (items []GopherNavItem) {
 	partialURL := "/gopher"
 	parts := strings.Split(url, "/")
 
+	if len(parts) != 0 && parts[len(parts)-1] == "" {
+		parts = parts[:len(parts)-1]
+	}
+
 	for i, part := range parts {
 		if i == 1 {
 			partialURL = partialURL + "/1"
@@ -151,7 +155,7 @@ func renderGopherDirectory(w http.ResponseWriter, tpl *template.Template, assetL
 		URL:    fmt.Sprintf("%s/%s", hostport, uri),
 		Assets: assetList,
 		Lines:  out,
-		Nav:    urlToNav(fmt.Sprintf("%s/%s", hostport, uri)),
+		Nav:    urlToGopherNav(fmt.Sprintf("%s/%s", hostport, uri)),
 	})
 }
 
@@ -194,7 +198,7 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass
 				Lines: []GopherItem{{
 					Text: fmt.Sprintf("Error: %s", err),
 				}},
-				Nav:     urlToNav(hostport),
+				Nav:     urlToGopherNav(hostport),
 				IsPlain: true,
 			}); e != nil {
 				log.Println("Template error: " + e.Error())
@@ -224,7 +228,7 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass
 				Lines: []GopherItem{{
 					Text: fmt.Sprintf("Error: %s", err),
 				}},
-				Nav:     urlToNav(fmt.Sprintf("%s/%s", hostport, uri)),
+				Nav:     urlToGopherNav(fmt.Sprintf("%s/%s", hostport, uri)),
 				IsPlain: true,
 			}); e != nil {
 				log.Println("Template error: " + e.Error())
@@ -246,7 +250,7 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass
 					Lines: []GopherItem{{
 						Text: buf.String(),
 					}},
-					Nav:     urlToNav(fmt.Sprintf("%s/%s", hostport, uri)),
+					Nav:     urlToGopherNav(fmt.Sprintf("%s/%s", hostport, uri)),
 					IsPlain: true,
 				}); err != nil {
 					log.Println("Template error: " + err.Error())
@@ -271,7 +275,7 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass
 					Lines: []GopherItem{{
 						Text: fmt.Sprintf("Error: %s", err),
 					}},
-					Nav:     urlToNav(fmt.Sprintf("%s/%s", hostport, uri)),
+					Nav:     urlToGopherNav(fmt.Sprintf("%s/%s", hostport, uri)),
 					IsPlain: false,
 				}); e != nil {
 					log.Println("Template error: " + e.Error())
diff --git a/internal/port/main.go b/internal/port/main.go
index 763057b..fe85ba4 100644
--- a/internal/port/main.go
+++ b/internal/port/main.go
@@ -237,9 +237,15 @@ func ListenAndServe(bind, startpagefile string, robotsfile string, robotsdebug b
 		"hasPrefix": func(s string, prefix string) bool {
 			return strings.HasPrefix(s, prefix)
 		},
+		"hasSuffix": func(s string, suffix string) bool {
+			return strings.HasSuffix(s, suffix)
+		},
 		"title": func(s string) string {
 			return strings.Title(s)
 		},
+		"string": func(s interface{}) string {
+			return fmt.Sprint(s)
+		},
 	}
 
 	//
diff --git a/internal/port/tpl/gemini.html b/internal/port/tpl/gemini.html
index df50d50..8d20da1 100644
--- a/internal/port/tpl/gemini.html
+++ b/internal/port/tpl/gemini.html
@@ -35,11 +35,16 @@
           {{- else if eq .Type "REFLOW_TEXT" -}}
             <div class="section"><p class="section__content">{{- .Text -}}</p></div>
           {{- else if eq .Type "LINK" -}}
-            <div class="section"><span class="section__type">=></span><a class="section__content" href="{{ .URL }}">{{- .Text -}}</a></div>
+            {{- $linkCls := "link" -}}
+            {{- $url := string .URL -}}
+            {{- if or (hasSuffix $url ".jpg") (hasSuffix $url ".jpeg") (hasSuffix $url ".png") (hasSuffix $url ".gif") -}}
+              {{- $linkCls = "link--IMG" -}}
+            {{- end -}}
+            <div class="section"><span class="section__type"> =></span><a class="section__content {{ $linkCls }}" href="{{ .URL }}">{{- .Text -}}</a></div>
           {{- else if eq .Type "HEADING_1" -}}
-            <div class="section"><span class="section__type">#</span><h1 class="section__content">{{- .Text -}}</h1></div>
+            <div class="section"><span class="section__type">  #</span><h1 class="section__content">{{- .Text -}}</h1></div>
           {{- else if eq .Type "HEADING_2" -}}
-            <div class="section"><span class="section__type">##</span><h2 class="section__content">{{- .Text -}}</h2></div>
+            <div class="section"><span class="section__type"> ##</span><h2 class="section__content">{{- .Text -}}</h2></div>
           {{- else if eq .Type "HEADING_3" -}}
             <div class="section"><span class="section__type">###</span><h3 class="section__content">{{- .Text -}}</h3></div>
           {{- else if eq .Type "LIST" -}}
diff --git a/internal/port/tpl/gopher.html b/internal/port/tpl/gopher.html
index 5436123..6eb607c 100644
--- a/internal/port/tpl/gopher.html
+++ b/internal/port/tpl/gopher.html
@@ -35,7 +35,7 @@
         {{- $page := . -}}
         {{- range .Lines -}}
           {{- if .Link -}}
-            <div class="section"><span class="section__type">{{- .Type -}}</span><a class="section__content" href="{{ .Link }}">{{- .Text -}}</a></div>
+            <div class="section"><span class="section__type">{{- .Type -}}</span><a class="section__content link link--{{ .Type }}" href="{{ .Link }}">{{- .Text -}}</a></div>
           {{- else -}}
             <div class="section"><span class="section__type"></span><pre class="section__content">{{- .Text -}}</pre></div>
           {{- end -}}
diff --git a/internal/port/tpl/startpage.html b/internal/port/tpl/startpage.html
index cfe519d..772ac90 100644
--- a/internal/port/tpl/startpage.html
+++ b/internal/port/tpl/startpage.html
@@ -18,7 +18,7 @@
     </header>
 
 		<main class="wrap">
-			<pre class="content content--has-monospace-font">
+			<pre class="content content--monospace">
         {{- .Content -}}
 			</pre>
 		</main>
-- 
cgit v1.2.3-70-g09d2