dmitri.shuralyov.com/website/gido/...

Add more detailed page titles.

This makes it easier to tell pages apart when multiple tabs are open,
or when viewing browsing history.

Use a little html/template to make this change easier.

Fixes issue 2.
dmitshur committed 1 year ago commit 181e6c67800b43aaccf789f953d365da80fb13a4
main.go
@@ -4,10 +4,11 @@ package main
 import (
 	"context"
 	"encoding/json"
 	"flag"
 	"fmt"
+	"html/template"
 	"io"
 	"io/ioutil"
 	"log"
 	"mime"
 	"net/http"
@@ -135,13 +136,13 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, req *http.Request) error {
 	}
 	pkg := req.URL.Path[1:]
 	return h.ServeIssues(w, req, pkg)
 }
 
-const htmlPart1, htmlPart2, htmlPart3 = `<html>
+var pageHTML = template.Must(template.New("").Parse(`{{define "Header"}}<html>
 	<head>
-`, `		<title>Go Issues</title>
+{{.AnalyticsHTML}}		<title>{{with .PageName}}{{.}} - {{end}}Go Issues</title>
 		<meta name="viewport" content="width=device-width">
 		<link href="/assets/fonts/fonts.css" rel="stylesheet" type="text/css">
 		<link href="/assets/style.css" rel="stylesheet" type="text/css">
 	</head>
 	<body style="margin: 0; position: relative;">
@@ -150,37 +151,35 @@ const htmlPart1, htmlPart2, htmlPart3 = `<html>
 				<a class="black" href="/"                                      ><strong style="padding: 15px 0 15px 0; display: inline-block;">Go Issues</strong></a>
 				<a class="black" href="/-/packages" style="padding-left: 30px;"><span   style="padding: 15px 0 15px 0; display: inline-block;">Packages</span></a>
 			</div>
 		</header>
 
-		<main style="max-width: 800px; margin: 0 auto 0 auto; padding: 0 15px 120px 15px;">`, `</main>
+		<main style="max-width: 800px; margin: 0 auto 0 auto; padding: 0 15px 120px 15px;">
+			{{end}}
+
+			{{define "Trailer"}}
+		</main>
 
 		<footer style="background-color: hsl(209, 51%, 92%); position: absolute; bottom: 0; left: 0; right: 0;">
 			<div style="max-width: 800px; margin: 0 auto 0 auto; padding: 0 15px 0 15px; text-align: right;">
 				<span style="padding: 15px 0 15px 0; display: inline-block;"><a href="https://dmitri.shuralyov.com/website/gido/...$issues">Website Issues</a></span>
 			</div>
 		</footer>
 	</body>
 </html>
-`
+{{end}}`))
 
 // ServeIndex serves the index page.
 func (h *handler) ServeIndex(w http.ResponseWriter, req *http.Request) error {
 	if req.Method != http.MethodGet {
 		return httperror.Method{Allowed: []string{http.MethodGet}}
 	}
 
 	w.Header().Set("Content-Type", "text/html; charset=utf-8")
-	_, err := io.WriteString(w, htmlPart1)
-	if err != nil {
-		return err
-	}
-	_, err = w.Write(h.analyticsHTML)
-	if err != nil {
-		return err
-	}
-	_, err = io.WriteString(w, htmlPart2)
+	err := pageHTML.ExecuteTemplate(w, "Header", map[string]interface{}{
+		"AnalyticsHTML": template.HTML(h.analyticsHTML),
+	})
 	if err != nil {
 		return err
 	}
 
 	// Write the About section.
@@ -230,11 +229,11 @@ func (h *handler) ServeIndex(w http.ResponseWriter, req *http.Request) error {
 	err = renderTable(w, popular)
 	if err != nil {
 		return err
 	}
 
-	_, err = io.WriteString(w, htmlPart3)
+	err = pageHTML.ExecuteTemplate(w, "Trailer", nil)
 	return err
 }
 
 // ServePackages serves a list of all known packages.
 func (h *handler) ServePackages(w http.ResponseWriter, req *http.Request) error {
@@ -269,19 +268,14 @@ func (h *handler) ServePackages(w http.ResponseWriter, req *http.Request) error
 		err := e.Encode(append(stdlib, subrepo...)) // TODO: Measure if slow, optimize if needed.
 		return err
 	}
 
 	w.Header().Set("Content-Type", "text/html; charset=utf-8")
-	_, err := io.WriteString(w, htmlPart1)
-	if err != nil {
-		return err
-	}
-	_, err = w.Write(h.analyticsHTML)
-	if err != nil {
-		return err
-	}
-	_, err = io.WriteString(w, htmlPart2)
+	err := pageHTML.ExecuteTemplate(w, "Header", map[string]interface{}{
+		"PageName":      "Packages",
+		"AnalyticsHTML": template.HTML(h.analyticsHTML),
+	})
 	if err != nil {
 		return err
 	}
 
 	// Render the stdlib section.
@@ -314,11 +308,11 @@ func (h *handler) ServePackages(w http.ResponseWriter, req *http.Request) error
 			</p>`)
 	if err != nil {
 		return err
 	}
 
-	_, err = io.WriteString(w, htmlPart3)
+	err = pageHTML.ExecuteTemplate(w, "Trailer", nil)
 	return err
 }
 
 type pkg struct {
 	Path string `json:"ImportPath"`
@@ -380,19 +374,14 @@ func (h *handler) ServeIssues(w http.ResponseWriter, req *http.Request, pkg stri
 	}
 	openCount := uint64(len(pi.Open))
 	closedCount := uint64(len(pi.Closed))
 
 	w.Header().Set("Content-Type", "text/html; charset=utf-8")
-	_, err = io.WriteString(w, htmlPart1)
-	if err != nil {
-		return err
-	}
-	_, err = w.Write(h.analyticsHTML)
-	if err != nil {
-		return err
-	}
-	_, err = io.WriteString(w, htmlPart2)
+	err = pageHTML.ExecuteTemplate(w, "Header", map[string]interface{}{
+		"PageName":      pkg,
+		"AnalyticsHTML": template.HTML(h.analyticsHTML),
+	})
 	if err != nil {
 		return err
 	}
 	heading := htmlg.NodeComponent{
 		Type: html.ElementNode, Data: atom.H2.String(),
@@ -425,11 +414,11 @@ func (h *handler) ServeIssues(w http.ResponseWriter, req *http.Request, pkg stri
 	}
 	err = htmlg.RenderComponents(w, heading, subheading{pkg}, newIssue, issues)
 	if err != nil {
 		return err
 	}
-	_, err = io.WriteString(w, htmlPart3)
+	err = pageHTML.ExecuteTemplate(w, "Trailer", nil)
 	return err
 }
 
 type subheading struct{ Pkg string }