Commit e8e4987b authored by Robert Griesemer's avatar Robert Griesemer

godoc: support for title and subtitle headers when serving .html docs

and use it to show version (date) of go spec

Fixes #68.

R=rsc
CC=golang-dev, r
https://golang.org/cl/848042
parent 7ecefdc0
<!-- The Go Programming Language Specification --> <!-- title The Go Programming Language Specification -->
<!-- subtitle Version of March 25, 2010 -->
<!-- <!--
Todo Todo
......
...@@ -198,6 +198,11 @@ span.highlight { ...@@ -198,6 +198,11 @@ span.highlight {
background-color: #ffffa0; background-color: #ffffa0;
} }
span.subtitle {
font-weight: bold;
font-size: medium;
}
/* same style as for gettingStarted */ /* same style as for gettingStarted */
#menu { #menu {
margin-top: 1.5em; margin-top: 1.5em;
......
...@@ -133,11 +133,18 @@ ...@@ -133,11 +133,18 @@
</div> </div>
{.end} {.end}
<h1 id="generatedHeader">{Title|html-esc}</h1> {.section Title}
<h1 id="generatedHeader">{@|html-esc}</h1>
{.end}
{.section Subtitle}
<span class="subtitle">{@|html-esc}</span>
{.end}
<p>
<!-- The Table of Contents is automatically inserted in this <div>. <!-- The Table of Contents is automatically inserted in this <div>.
Do not delete this <div>. --> Do not delete this <div>. -->
<div id="nav"></div> <div id="nav"></div>
</p>
<!-- Content is HTML-escaped elsewhere --> <!-- Content is HTML-escaped elsewhere -->
{Content} {Content}
......
...@@ -19,6 +19,7 @@ import ( ...@@ -19,6 +19,7 @@ import (
"log" "log"
"os" "os"
pathutil "path" pathutil "path"
"regexp"
"runtime" "runtime"
"strings" "strings"
"sync" "sync"
...@@ -874,9 +875,10 @@ func readTemplates() { ...@@ -874,9 +875,10 @@ func readTemplates() {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Generic HTML wrapper // Generic HTML wrapper
func servePage(c *http.Conn, title, query string, content []byte) { func servePage(c *http.Conn, title, subtitle, query string, content []byte) {
type Data struct { type Data struct {
Title string Title string
Subtitle string
PkgRoots []string PkgRoots []string
Timestamp uint64 // int64 to be compatible with os.Dir.Mtime_ns Timestamp uint64 // int64 to be compatible with os.Dir.Mtime_ns
Query string Query string
...@@ -888,6 +890,7 @@ func servePage(c *http.Conn, title, query string, content []byte) { ...@@ -888,6 +890,7 @@ func servePage(c *http.Conn, title, query string, content []byte) {
_, ts := fsTree.get() _, ts := fsTree.get()
d := Data{ d := Data{
Title: title, Title: title,
Subtitle: subtitle,
PkgRoots: fsMap.PrefixList(), PkgRoots: fsMap.PrefixList(),
Timestamp: uint64(ts) * 1e9, // timestamp in ns Timestamp: uint64(ts) * 1e9, // timestamp in ns
Query: query, Query: query,
...@@ -912,16 +915,16 @@ func serveText(c *http.Conn, text []byte) { ...@@ -912,16 +915,16 @@ func serveText(c *http.Conn, text []byte) {
// Files // Files
var ( var (
tagBegin = []byte("<!--") titleRx = regexp.MustCompile(`<!-- title ([^\-]*)-->`)
tagEnd = []byte("-->") subtitleRx = regexp.MustCompile(`<!-- subtitle ([^\-]*)-->`)
firstCommentRx = regexp.MustCompile(`<!--([^\-]*)-->`)
) )
// commentText returns the text of the first HTML comment in src.
func commentText(src []byte) (text string) { func extractString(src []byte, rx *regexp.Regexp) (s string) {
i := bytes.Index(src, tagBegin) m := rx.Execute(src)
j := bytes.Index(src, tagEnd) if len(m) >= 4 {
if i >= 0 && j >= i+len(tagBegin) { s = strings.TrimSpace(string(src[m[2]:m[3]]))
text = string(bytes.TrimSpace(src[i+len(tagBegin) : j]))
} }
return return
} }
...@@ -950,8 +953,15 @@ func serveHTMLDoc(c *http.Conn, r *http.Request, abspath, relpath string) { ...@@ -950,8 +953,15 @@ func serveHTMLDoc(c *http.Conn, r *http.Request, abspath, relpath string) {
src = buf.Bytes() src = buf.Bytes()
} }
title := commentText(src) // get title and subtitle, if any
servePage(c, title, "", src) title := extractString(src, titleRx)
if title == "" {
// no title found; try first comment for backward-compatibility
title = extractString(src, firstCommentRx)
}
subtitle := extractString(src, subtitleRx)
servePage(c, title, subtitle, "", src)
} }
...@@ -983,7 +993,7 @@ func serveGoSource(c *http.Conn, r *http.Request, abspath, relpath string) { ...@@ -983,7 +993,7 @@ func serveGoSource(c *http.Conn, r *http.Request, abspath, relpath string) {
info := &SourceInfo{buf.Bytes(), styler.mapping()} info := &SourceInfo{buf.Bytes(), styler.mapping()}
contents := applyTemplate(sourceHTML, "sourceHTML", info) contents := applyTemplate(sourceHTML, "sourceHTML", info)
servePage(c, "Source file "+relpath, "", contents) servePage(c, "Source file "+relpath, "", "", contents)
} }
...@@ -1056,7 +1066,7 @@ func serveTextFile(c *http.Conn, r *http.Request, abspath, relpath string) { ...@@ -1056,7 +1066,7 @@ func serveTextFile(c *http.Conn, r *http.Request, abspath, relpath string) {
template.HTMLEscape(&buf, src) template.HTMLEscape(&buf, src)
fmt.Fprintln(&buf, "</pre>") fmt.Fprintln(&buf, "</pre>")
servePage(c, "Text file "+relpath, "", buf.Bytes()) servePage(c, "Text file "+relpath, "", "", buf.Bytes())
} }
...@@ -1079,7 +1089,7 @@ func serveDirectory(c *http.Conn, r *http.Request, abspath, relpath string) { ...@@ -1079,7 +1089,7 @@ func serveDirectory(c *http.Conn, r *http.Request, abspath, relpath string) {
} }
contents := applyTemplate(dirlistHTML, "dirlistHTML", list) contents := applyTemplate(dirlistHTML, "dirlistHTML", list)
servePage(c, "Directory "+relpath, "", contents) servePage(c, "Directory "+relpath, "", "", contents)
} }
...@@ -1326,7 +1336,7 @@ func (h *httpHandler) ServeHTTP(c *http.Conn, r *http.Request) { ...@@ -1326,7 +1336,7 @@ func (h *httpHandler) ServeHTTP(c *http.Conn, r *http.Request) {
} }
contents := applyTemplate(packageHTML, "packageHTML", info) contents := applyTemplate(packageHTML, "packageHTML", info)
servePage(c, title, "", contents) servePage(c, title, "", "", contents)
} }
...@@ -1373,7 +1383,7 @@ func search(c *http.Conn, r *http.Request) { ...@@ -1373,7 +1383,7 @@ func search(c *http.Conn, r *http.Request) {
} }
contents := applyTemplate(searchHTML, "searchHTML", result) contents := applyTemplate(searchHTML, "searchHTML", result)
servePage(c, title, query, contents) servePage(c, title, "", query, contents)
} }
......
...@@ -66,7 +66,7 @@ var ( ...@@ -66,7 +66,7 @@ var (
func serveError(c *http.Conn, r *http.Request, relpath string, err os.Error) { func serveError(c *http.Conn, r *http.Request, relpath string, err os.Error) {
contents := applyTemplate(errorHTML, "errorHTML", err) // err may contain an absolute path! contents := applyTemplate(errorHTML, "errorHTML", err) // err may contain an absolute path!
servePage(c, "File "+relpath, "", contents) servePage(c, "File "+relpath, "", "", contents)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment