diff --git a/godoc/godoc.go b/godoc/godoc.go index e7868ee5..a9e8b3bb 100644 --- a/godoc/godoc.go +++ b/godoc/godoc.go @@ -79,11 +79,13 @@ func (p *Presentation) initFuncMap() { "sanitize": sanitizeFunc, // support for URL attributes - "pkgLink": pkgLinkFunc, - "srcLink": srcLinkFunc, - "posLink_url": newPosLink_urlFunc(srcPosLinkFunc), - "docLink": docLinkFunc, - "queryLink": queryLinkFunc, + "pkgLink": pkgLinkFunc, + "srcLink": srcLinkFunc, + "posLink_url": newPosLink_urlFunc(srcPosLinkFunc), + "docLink": docLinkFunc, + "queryLink": queryLinkFunc, + "srcBreadcrumb": srcBreadcrumbFunc, + "srcToPkgLink": srcToPkgLinkFunc, // formatting of Examples "example_html": p.example_htmlFunc, @@ -459,6 +461,51 @@ func pkgLinkFunc(path string) string { return "pkg/" + path } +// srcToPkgLinkFunc builds an tag linking to +// the package documentation of relpath. +func srcToPkgLinkFunc(relpath string) string { + relpath = pkgLinkFunc(relpath) + if relpath == "pkg/" { + return `Index` + } + if i := strings.LastIndex(relpath, "/"); i != -1 { + // Remove filename after last slash. + relpath = relpath[:i] + } + return fmt.Sprintf(`%s`, relpath, relpath[len("pkg/"):]) +} + +// srcBreadcrumbFun converts each segment of relpath to a HTML . +// Each segment links to its corresponding src directories. +func srcBreadcrumbFunc(relpath string) string { + segments := strings.Split(relpath, "/") + var buf bytes.Buffer + var selectedSegment string + var selectedIndex int + + if strings.HasSuffix(relpath, "/") { + // relpath is a directory ending with a "/". + // Selected segment is the segment before the last slash. + selectedIndex = len(segments) - 2 + selectedSegment = segments[selectedIndex] + "/" + } else { + selectedIndex = len(segments) - 1 + selectedSegment = segments[selectedIndex] + } + + for i := range segments[:selectedIndex] { + buf.WriteString(fmt.Sprintf(`%s/`, + strings.Join(segments[:i+1], "/"), + segments[i], + )) + } + + buf.WriteString(``) + buf.WriteString(selectedSegment) + buf.WriteString(``) + return buf.String() +} + func newPosLink_urlFunc(srcPosLinkFunc func(s string, line, low, high int) string) func(info *PageInfo, n interface{}) string { // n must be an ast.Node or a *doc.Note return func(info *PageInfo, n interface{}) string { diff --git a/godoc/godoc_test.go b/godoc/godoc_test.go index ef5790ed..dca1c951 100644 --- a/godoc/godoc_test.go +++ b/godoc/godoc_test.go @@ -290,3 +290,32 @@ func TestReplaceLeadingIndentation(t *testing.T) { } } } + +func TestSrcBreadcrumbFunc(t *testing.T) { + for _, tc := range []struct { + path string + want string + }{ + {"src/", `src/`}, + {"src/fmt/", `src/fmt/`}, + {"src/fmt/print.go", `src/fmt/print.go`}, + } { + if got := srcBreadcrumbFunc(tc.path); got != tc.want { + t.Errorf("srcBreadcrumbFunc(%v) = %v; want %v", tc.path, got, tc.want) + } + } +} + +func TestSrcToPkgLinkFunc(t *testing.T) { + for _, tc := range []struct { + path string + want string + }{ + {"src/", `Index`}, + {"src/fmt/", `fmt`}, + } { + if got := srcToPkgLinkFunc(tc.path); got != tc.want { + t.Errorf("srcToPkgLinkFunc(%v) = %v; want %v", tc.path, got, tc.want) + } + } +} diff --git a/godoc/page.go b/godoc/page.go index 35d6cfba..0c7bf00a 100644 --- a/godoc/page.go +++ b/godoc/page.go @@ -16,6 +16,7 @@ type Page struct { Title string Tabtitle string Subtitle string + SrcPath string Query string Body []byte Share bool diff --git a/godoc/server.go b/godoc/server.go index ffe59972..c9b40566 100644 --- a/godoc/server.go +++ b/godoc/server.go @@ -579,7 +579,8 @@ func (p *Presentation) serveTextFile(w http.ResponseWriter, r *http.Request, abs fmt.Fprintf(&buf, `

View as plain text

`, htmlpkg.EscapeString(relpath)) p.ServePage(w, Page{ - Title: title + " " + relpath, + Title: title, + SrcPath: relpath, Tabtitle: relpath, Body: buf.Bytes(), Share: allowShare(r), @@ -649,7 +650,8 @@ func (p *Presentation) serveDirectory(w http.ResponseWriter, r *http.Request, ab } p.ServePage(w, Page{ - Title: "Directory " + relpath, + Title: "Directory", + SrcPath: relpath, Tabtitle: relpath, Body: applyTemplate(p.DirlistHTML, "dirlistHTML", list), Share: allowShare(r), diff --git a/godoc/static/godoc.html b/godoc/static/godoc.html index a7009827..92b10aa7 100644 --- a/godoc/static/godoc.html +++ b/godoc/static/godoc.html @@ -65,13 +65,23 @@ func main() {
-{{with .Title}} -

{{html .}}

+{{if or .Title .SrcPath}} +

+ {{html .Title}} + {{html .SrcPath | srcBreadcrumb}} +

{{end}} + {{with .Subtitle}}

{{html .}}

{{end}} +{{with .SrcPath}} +

+ Documentation: {{html . | srcToPkgLink}} +

+{{end}} + {{/* The Table of Contents is automatically inserted in this
. Do not delete this
. */}} diff --git a/godoc/static/static.go b/godoc/static/static.go index c8915765..862ea104 100644 --- a/godoc/static/static.go +++ b/godoc/static/static.go @@ -529,13 +529,23 @@ func main() {
-{{with .Title}} -

{{html .}}

+{{if or .Title .SrcPath}} +

+ {{html .Title}} + {{html .SrcPath | srcBreadcrumb}} +

{{end}} + {{with .Subtitle}}

{{html .}}

{{end}} +{{with .SrcPath}} +

+ Documentation: {{html . | srcToPkgLink}} +

+{{end}} + {{/* The Table of Contents is automatically inserted in this
. Do not delete this
. */}} @@ -2996,6 +3006,9 @@ h1 { font-size: 28px; line-height: 1; } +h1 .text-muted { + color:#777; +} h2 { font-size: 20px; background: #E0EBF5; diff --git a/godoc/static/style.css b/godoc/static/style.css index e89ac290..25933a3d 100644 --- a/godoc/static/style.css +++ b/godoc/static/style.css @@ -101,6 +101,9 @@ h1 { font-size: 28px; line-height: 1; } +h1 .text-muted { + color:#777; +} h2 { font-size: 20px; background: #E0EBF5;