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 6 years ago commit 181e6c67800b43aaccf789f953d365da80fb13a4
Showing partial commit. Full Commit
Collapse all
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 }