godoc: add links to docs in text and dir pages
Fixes golang/go#17125 Change-Id: I22dd0561cd1c8eb30524797b6c0488d08a65285b Reviewed-on: https://go-review.googlesource.com/29279 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
34f7837286
commit
5128de7288
|
@ -84,6 +84,8 @@ func (p *Presentation) initFuncMap() {
|
|||
"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 <a> tag linking to
|
||||
// the package documentation of relpath.
|
||||
func srcToPkgLinkFunc(relpath string) string {
|
||||
relpath = pkgLinkFunc(relpath)
|
||||
if relpath == "pkg/" {
|
||||
return `<a href="/pkg">Index</a>`
|
||||
}
|
||||
if i := strings.LastIndex(relpath, "/"); i != -1 {
|
||||
// Remove filename after last slash.
|
||||
relpath = relpath[:i]
|
||||
}
|
||||
return fmt.Sprintf(`<a href="/%s">%s</a>`, relpath, relpath[len("pkg/"):])
|
||||
}
|
||||
|
||||
// srcBreadcrumbFun converts each segment of relpath to a HTML <a>.
|
||||
// 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(`<a href="/%s">%s</a>/`,
|
||||
strings.Join(segments[:i+1], "/"),
|
||||
segments[i],
|
||||
))
|
||||
}
|
||||
|
||||
buf.WriteString(`<span class="text-muted">`)
|
||||
buf.WriteString(selectedSegment)
|
||||
buf.WriteString(`</span>`)
|
||||
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 {
|
||||
|
|
|
@ -290,3 +290,32 @@ func TestReplaceLeadingIndentation(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSrcBreadcrumbFunc(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
path string
|
||||
want string
|
||||
}{
|
||||
{"src/", `<span class="text-muted">src/</span>`},
|
||||
{"src/fmt/", `<a href="/src">src</a>/<span class="text-muted">fmt/</span>`},
|
||||
{"src/fmt/print.go", `<a href="/src">src</a>/<a href="/src/fmt">fmt</a>/<span class="text-muted">print.go</span>`},
|
||||
} {
|
||||
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/", `<a href="/pkg">Index</a>`},
|
||||
{"src/fmt/", `<a href="/pkg/fmt">fmt</a>`},
|
||||
} {
|
||||
if got := srcToPkgLinkFunc(tc.path); got != tc.want {
|
||||
t.Errorf("srcToPkgLinkFunc(%v) = %v; want %v", tc.path, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ type Page struct {
|
|||
Title string
|
||||
Tabtitle string
|
||||
Subtitle string
|
||||
SrcPath string
|
||||
Query string
|
||||
Body []byte
|
||||
Share bool
|
||||
|
|
|
@ -579,7 +579,8 @@ func (p *Presentation) serveTextFile(w http.ResponseWriter, r *http.Request, abs
|
|||
fmt.Fprintf(&buf, `<p><a href="/%s?m=text">View as plain text</a></p>`, 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),
|
||||
|
|
|
@ -65,13 +65,23 @@ func main() {
|
|||
<div id="page"{{if .Title}} class="wide"{{end}}>
|
||||
<div class="container">
|
||||
|
||||
{{with .Title}}
|
||||
<h1>{{html .}}</h1>
|
||||
{{if or .Title .SrcPath}}
|
||||
<h1>
|
||||
{{html .Title}}
|
||||
{{html .SrcPath | srcBreadcrumb}}
|
||||
</h1>
|
||||
{{end}}
|
||||
|
||||
{{with .Subtitle}}
|
||||
<h2>{{html .}}</h2>
|
||||
{{end}}
|
||||
|
||||
{{with .SrcPath}}
|
||||
<h2>
|
||||
Documentation: {{html . | srcToPkgLink}}
|
||||
</h2>
|
||||
{{end}}
|
||||
|
||||
{{/* The Table of Contents is automatically inserted in this <div>.
|
||||
Do not delete this <div>. */}}
|
||||
<div id="nav"></div>
|
||||
|
|
|
@ -529,13 +529,23 @@ func main() {
|
|||
<div id="page"{{if .Title}} class="wide"{{end}}>
|
||||
<div class="container">
|
||||
|
||||
{{with .Title}}
|
||||
<h1>{{html .}}</h1>
|
||||
{{if or .Title .SrcPath}}
|
||||
<h1>
|
||||
{{html .Title}}
|
||||
{{html .SrcPath | srcBreadcrumb}}
|
||||
</h1>
|
||||
{{end}}
|
||||
|
||||
{{with .Subtitle}}
|
||||
<h2>{{html .}}</h2>
|
||||
{{end}}
|
||||
|
||||
{{with .SrcPath}}
|
||||
<h2>
|
||||
Documentation: {{html . | srcToPkgLink}}
|
||||
</h2>
|
||||
{{end}}
|
||||
|
||||
{{/* The Table of Contents is automatically inserted in this <div>.
|
||||
Do not delete this <div>. */}}
|
||||
<div id="nav"></div>
|
||||
|
@ -2996,6 +3006,9 @@ h1 {
|
|||
font-size: 28px;
|
||||
line-height: 1;
|
||||
}
|
||||
h1 .text-muted {
|
||||
color:#777;
|
||||
}
|
||||
h2 {
|
||||
font-size: 20px;
|
||||
background: #E0EBF5;
|
||||
|
|
|
@ -101,6 +101,9 @@ h1 {
|
|||
font-size: 28px;
|
||||
line-height: 1;
|
||||
}
|
||||
h1 .text-muted {
|
||||
color:#777;
|
||||
}
|
||||
h2 {
|
||||
font-size: 20px;
|
||||
background: #E0EBF5;
|
||||
|
|
Loading…
Reference in New Issue