godoc: preserve ?m=... query string

Right now, clicking around packages in the godoc web interface strips
the URL of any query strings it may have, which makes traversing
internal packages a clumsy experience (constantly have to re-add ?m=...).

This revision preserves the ?m=... flag in links between packages by examining
the current PageInfoMode and converting it to a query string.

Change-Id: I4e28279d8cbf221bcc7d5bce8de04c90cc907678
Reviewed-on: https://go-review.googlesource.com/34982
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Ted Kornish 2017-01-18 10:52:36 -08:00 committed by Brad Fitzpatrick
parent 19c96be7c4
commit 396c176f11
5 changed files with 36 additions and 8 deletions

View File

@ -252,7 +252,7 @@ func testWeb(t *testing.T, withIndex bool) {
match: []string{ match: []string{
"Standard library", "Standard library",
"Package fmt implements formatted I/O", "Package fmt implements formatted I/O",
"internal/syscall", "internal/syscall/?m=all",
}, },
dontmatch: []string{ dontmatch: []string{
"cmd/gc", "cmd/gc",

View File

@ -101,6 +101,9 @@ func (p *Presentation) initFuncMap() {
// Number operation // Number operation
"multiply": multiply, "multiply": multiply,
// formatting of PageInfoMode query string
"modeQueryString": modeQueryString,
} }
if p.URLForSrc != nil { if p.URLForSrc != nil {
p.funcMap["srcLink"] = p.URLForSrc p.funcMap["srcLink"] = p.URLForSrc
@ -442,6 +445,8 @@ type PageInfo struct {
Err error // error or nil Err error // error or nil
Share bool // show share button on examples Share bool // show share button on examples
Mode PageInfoMode // display metadata from query string
// package info // package info
FSet *token.FileSet // nil if no package documentation FSet *token.FileSet // nil if no package documentation
PDoc *doc.Package // nil if no package documentation PDoc *doc.Package // nil if no package documentation

View File

@ -55,7 +55,7 @@ func (s *handlerServer) registerWithMux(mux *http.ServeMux) {
// set to the respective error but the error is not logged. // set to the respective error but the error is not logged.
// //
func (h *handlerServer) GetPageInfo(abspath, relpath string, mode PageInfoMode, goos, goarch string) *PageInfo { func (h *handlerServer) GetPageInfo(abspath, relpath string, mode PageInfoMode, goos, goarch string) *PageInfo {
info := &PageInfo{Dirname: abspath} info := &PageInfo{Dirname: abspath, Mode: mode}
// Restrict to the package files that would be used when building // Restrict to the package files that would be used when building
// the package on this system. This makes sure that if there are // the package on this system. This makes sure that if there are
@ -203,6 +203,7 @@ func (h *handlerServer) GetPageInfo(abspath, relpath string, mode PageInfoMode,
timestamp = time.Now() timestamp = time.Now()
} }
info.Dirs = dir.listing(true, func(path string) bool { return h.includePath(path, mode) }) info.Dirs = dir.listing(true, func(path string) bool { return h.includePath(path, mode) })
info.DirTime = timestamp info.DirTime = timestamp
info.DirFlat = mode&FlatDir != 0 info.DirFlat = mode&FlatDir != 0
@ -320,6 +321,8 @@ func (h *handlerServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
type PageInfoMode uint type PageInfoMode uint
const ( const (
PageInfoModeQueryString = "m" // query string where PageInfoMode is stored
NoFiltering PageInfoMode = 1 << iota // do not filter exports NoFiltering PageInfoMode = 1 << iota // do not filter exports
AllMethods // show all embedded methods AllMethods // show all embedded methods
ShowSource // show source code, do not extract documentation ShowSource // show source code, do not extract documentation
@ -337,12 +340,32 @@ var modeNames = map[string]PageInfoMode{
"flat": FlatDir, "flat": FlatDir,
} }
// generate a query string for persisting PageInfoMode between pages.
func modeQueryString(mode PageInfoMode) string {
if modeNames := mode.names(); len(modeNames) > 0 {
return "?m=" + strings.Join(modeNames, ",")
}
return ""
}
// alphabetically sorted names of active flags for a PageInfoMode.
func (m PageInfoMode) names() []string {
var names []string
for name, mode := range modeNames {
if m&mode != 0 {
names = append(names, name)
}
}
sort.Strings(names)
return names
}
// GetPageInfoMode computes the PageInfoMode flags by analyzing the request // GetPageInfoMode computes the PageInfoMode flags by analyzing the request
// URL form value "m". It is value is a comma-separated list of mode names // URL form value "m". It is value is a comma-separated list of mode names
// as defined by modeNames (e.g.: m=src,text). // as defined by modeNames (e.g.: m=src,text).
func (p *Presentation) GetPageInfoMode(r *http.Request) PageInfoMode { func (p *Presentation) GetPageInfoMode(r *http.Request) PageInfoMode {
var mode PageInfoMode var mode PageInfoMode
for _, k := range strings.Split(r.FormValue("m"), ",") { for _, k := range strings.Split(r.FormValue(PageInfoModeQueryString), ",") {
if m, found := modeNames[strings.TrimSpace(k)]; found { if m, found := modeNames[strings.TrimSpace(k)]; found {
mode |= m mode |= m
} }
@ -519,7 +542,7 @@ func (p *Presentation) serveTextFile(w http.ResponseWriter, r *http.Request, abs
return return
} }
if r.FormValue("m") == "text" { if r.FormValue(PageInfoModeQueryString) == "text" {
p.ServeText(w, src) p.ServeText(w, src)
return return
} }

View File

@ -277,7 +277,7 @@
{{if .HasPkg}} {{if .HasPkg}}
<tr> <tr>
<td class="pkg-name"> <td class="pkg-name">
<a href="{{html .Path}}/">{{html .Path}}</a> <a href="{{html .Path}}/{{modeQueryString $.Mode | html}}">{{html .Path}}</a>
</td> </td>
<td class="pkg-synopsis"> <td class="pkg-synopsis">
{{html .Synopsis}} {{html .Synopsis}}
@ -287,7 +287,7 @@
{{else}} {{else}}
<tr> <tr>
<td class="pkg-name" style="padding-left: {{multiply .Depth 20}}px;"> <td class="pkg-name" style="padding-left: {{multiply .Depth 20}}px;">
<a href="{{html .Path}}/">{{html .Name}}</a> <a href="{{html .Path}}/{{modeQueryString $.Mode | html}}">{{html .Name}}</a>
</td> </td>
<td class="pkg-synopsis"> <td class="pkg-synopsis">
{{html .Synopsis}} {{html .Synopsis}}

View File

@ -1914,7 +1914,7 @@ function cgAddChild(tree, ul, cgn) {
{{if .HasPkg}} {{if .HasPkg}}
<tr> <tr>
<td class="pkg-name"> <td class="pkg-name">
<a href="{{html .Path}}/">{{html .Path}}</a> <a href="{{html .Path}}/{{modeQueryString $.Mode | html}}">{{html .Path}}</a>
</td> </td>
<td class="pkg-synopsis"> <td class="pkg-synopsis">
{{html .Synopsis}} {{html .Synopsis}}
@ -1924,7 +1924,7 @@ function cgAddChild(tree, ul, cgn) {
{{else}} {{else}}
<tr> <tr>
<td class="pkg-name" style="padding-left: {{multiply .Depth 20}}px;"> <td class="pkg-name" style="padding-left: {{multiply .Depth 20}}px;">
<a href="{{html .Path}}/">{{html .Name}}</a> <a href="{{html .Path}}/{{modeQueryString $.Mode | html}}">{{html .Name}}</a>
</td> </td>
<td class="pkg-synopsis"> <td class="pkg-synopsis">
{{html .Synopsis}} {{html .Synopsis}}