mirror of
https://github.com/golang/go
synced 2024-11-18 04:14:49 -07:00
godoc: generate TOC from server-side for search page
Currently, we generate the TOC for a page dynamically after page load through javascript. This is fine for pages with static content. But for pages with dynamic output like /search, sometimes this causes a noticeable page jump due to extensive DOM traversal. Also, the heuristics to calculate the no. of columns is very rudimentary and fills the entire above-the-fold area if the no. of results is very large. Therefore, we generate the TOC from server side itself. And improve the no. of columns heuristic further to accomodate up to 4 columns. This improves page performance and utilizes real estate appropriately according to the input. Some screenshots at laptop (1366x768) resolution. https://snag.gy/AXz2rP.jpg https://snag.gy/th3Nn8.jpg More can be found in the CL comments. Fixes golang/go#21685 Updates golang/go#21686 Change-Id: Ia9b6dd1e67231d992709e4ba10ebdbedfe38b564 Reviewed-on: https://go-review.googlesource.com/c/129135 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Bryan C. Mills <bcmills@google.com>
This commit is contained in:
parent
26c26290c3
commit
3e7aa9e599
@ -109,6 +109,9 @@ func (p *Presentation) initFuncMap() {
|
||||
|
||||
// check whether to display third party section or not
|
||||
"hasThirdParty": hasThirdParty,
|
||||
|
||||
// get the no. of columns to split the toc in search page
|
||||
"tocColCount": tocColCount,
|
||||
}
|
||||
if p.URLForSrc != nil {
|
||||
p.funcMap["srcLink"] = p.URLForSrc
|
||||
|
@ -133,3 +133,54 @@ func (p *Presentation) serveSearchDesc(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
applyTemplateToResponseWriter(w, p.SearchDescXML, &data)
|
||||
}
|
||||
|
||||
// tocColCount returns the no. of columns
|
||||
// to split the toc table to.
|
||||
func tocColCount(result SearchResult) int {
|
||||
tocLen := tocLen(result)
|
||||
colCount := 0
|
||||
// Simple heuristic based on visual aesthetic in manual testing.
|
||||
switch {
|
||||
case tocLen <= 10:
|
||||
colCount = 1
|
||||
case tocLen <= 20:
|
||||
colCount = 2
|
||||
case tocLen <= 80:
|
||||
colCount = 3
|
||||
default:
|
||||
colCount = 4
|
||||
}
|
||||
return colCount
|
||||
}
|
||||
|
||||
// tocLen calculates the no. of items in the toc table
|
||||
// by going through various fields in the SearchResult
|
||||
// that is rendered in the UI.
|
||||
func tocLen(result SearchResult) int {
|
||||
tocLen := 0
|
||||
for _, val := range result.Idents {
|
||||
if len(val) != 0 {
|
||||
tocLen++
|
||||
}
|
||||
}
|
||||
// If no identifiers, then just one item for the header text "Package <result.Query>".
|
||||
// See searchcode.html for further details.
|
||||
if len(result.Idents) == 0 {
|
||||
tocLen++
|
||||
}
|
||||
if result.Hit != nil {
|
||||
if len(result.Hit.Decls) > 0 {
|
||||
tocLen += len(result.Hit.Decls)
|
||||
// We need one extra item for the header text "Package-level declarations".
|
||||
tocLen++
|
||||
}
|
||||
if len(result.Hit.Others) > 0 {
|
||||
tocLen += len(result.Hit.Others)
|
||||
// We need one extra item for the header text "Local declarations and uses".
|
||||
tocLen++
|
||||
}
|
||||
}
|
||||
// For "textual occurrences".
|
||||
tocLen++
|
||||
return tocLen
|
||||
}
|
||||
|
@ -34,6 +34,13 @@ function generateTOC() {
|
||||
return;
|
||||
}
|
||||
|
||||
// For search, we send the toc precomputed from server-side.
|
||||
// TODO: Ideally, this should always be precomputed for all pages, but then
|
||||
// we need to do HTML parsing on the server-side.
|
||||
if (location.pathname === '/search') {
|
||||
return;
|
||||
}
|
||||
|
||||
var nav = $('#nav');
|
||||
if (nav.length === 0) {
|
||||
return;
|
||||
@ -57,7 +64,6 @@ function generateTOC() {
|
||||
if (toc_items.length <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
var dl1 = $('<dl/>');
|
||||
var dl2 = $('<dl/>');
|
||||
|
||||
|
@ -3,6 +3,54 @@
|
||||
Use of this source code is governed by a BSD-style
|
||||
license that can be found in the LICENSE file.
|
||||
-->
|
||||
|
||||
{{ $colCount := tocColCount .}}
|
||||
{{/* Generate the TOC */}}
|
||||
<nav class="search-nav" style="column-count: {{$colCount}}" role="navigation">
|
||||
{{range $key, $val := .Idents}}
|
||||
{{if $val}}
|
||||
<a href="#{{$key.Name}}">{{$key.Name}}</a>
|
||||
<br />
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if not .Idents}}
|
||||
{{with .Pak}}
|
||||
<a href="#Packages">Package {{html $.Query}}</a>
|
||||
<br />
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{with .Hit}}
|
||||
{{with .Decls}}
|
||||
<a href="#Global">Package-level declarations</a>
|
||||
<br />
|
||||
{{range .}}
|
||||
{{$pkg_html := pkgLink .Pak.Path | html}}
|
||||
<a href="#Global_{{$pkg_html}}" class="indent">package {{html .Pak.Name}}</a>
|
||||
<br />
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{with .Others}}
|
||||
<a href="#Local">Local declarations and uses</a>
|
||||
<br />
|
||||
{{range .}}
|
||||
{{$pkg_html := pkgLink .Pak.Path | html}}
|
||||
<a href="#Local_{{$pkg_html}}" class="indent">package {{html .Pak.Name}}</a>
|
||||
<br />
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{with .Textual}}
|
||||
{{if $.Complete}}
|
||||
<a href="#Textual">{{html $.Found}} textual occurrences</a>
|
||||
{{else}}
|
||||
<a href="#Textual">More than {{html $.Found}} textual occurrences</a>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</nav>
|
||||
|
||||
{{with .Alert}}
|
||||
<p>
|
||||
<span class="alert" style="font-size:120%">{{html .}}</span>
|
||||
|
File diff suppressed because one or more lines are too long
@ -47,6 +47,18 @@ pre .ln {
|
||||
width: 8ch;
|
||||
}
|
||||
|
||||
.search-nav{
|
||||
margin-left: 1.25rem;
|
||||
font-size: 0.875rem;
|
||||
column-gap: 1.25rem;
|
||||
column-fill: auto;
|
||||
column-width: 14rem;
|
||||
}
|
||||
|
||||
.search-nav .indent {
|
||||
margin-left: 1.25rem;
|
||||
}
|
||||
|
||||
a,
|
||||
.exampleHeading .text,
|
||||
.expandAll {
|
||||
|
Loading…
Reference in New Issue
Block a user