1
0
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:
Agniva De Sarker 2018-08-11 13:33:17 +05:30 committed by Brad Fitzpatrick
parent 26c26290c3
commit 3e7aa9e599
6 changed files with 124 additions and 4 deletions

View File

@ -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

View File

@ -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
}

View File

@ -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/>');

View File

@ -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

View File

@ -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 {