--- /dev/null
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package godoc
+
+import (
+ "net/http"
+ "regexp"
+ "sync"
+ "text/template"
+
+ "golang.org/x/tools/godoc/vfs/httpfs"
+)
+
+// SearchResultFunc functions return an HTML body for displaying search results.
+type SearchResultFunc func(p *Presentation, result SearchResult) []byte
+
+// Presentation generates output from a corpus.
+type Presentation struct {
+ Corpus *Corpus
+
+ mux *http.ServeMux
+ fileServer http.Handler
+ cmdHandler handlerServer
+ pkgHandler handlerServer
+
+ CallGraphHTML,
+ DirlistHTML,
+ ErrorHTML,
+ ExampleHTML,
+ GodocHTML,
+ ImplementsHTML,
+ MethodSetHTML,
+ PackageHTML,
+ PackageRootHTML,
+ SearchHTML,
+ SearchDocHTML,
+ SearchCodeHTML,
+ SearchTxtHTML,
+ SearchDescXML *template.Template // If not nil, register a /opensearch.xml handler with this template.
+
+ // TabWidth optionally specifies the tab width.
+ TabWidth int
+
+ ShowTimestamps bool
+ ShowPlayground bool
+ DeclLinks bool
+
+ // NotesRx optionally specifies a regexp to match
+ // notes to render in the output.
+ NotesRx *regexp.Regexp
+
+ // AdjustPageInfoMode optionally specifies a function to
+ // modify the PageInfoMode of a request. The default chosen
+ // value is provided.
+ AdjustPageInfoMode func(req *http.Request, mode PageInfoMode) PageInfoMode
+
+ // URLForSrc optionally specifies a function that takes a source file and
+ // returns a URL for it.
+ // The source file argument has the form /src/<path>/<filename>.
+ URLForSrc func(src string) string
+
+ // URLForSrcPos optionally specifies a function to create a URL given a
+ // source file, a line from the source file (1-based), and low & high offset
+ // positions (0-based, bytes from beginning of file). Ideally, the returned
+ // URL will be for the specified line of the file, while the high & low
+ // positions will be used to highlight a section of the file.
+ // The source file argument has the form /src/<path>/<filename>.
+ URLForSrcPos func(src string, line, low, high int) string
+
+ // URLForSrcQuery optionally specifies a function to create a URL given a
+ // source file, a query string, and a line from the source file (1-based).
+ // The source file argument has the form /src/<path>/<filename>.
+ // The query argument will be escaped for the purposes of embedding in a URL
+ // query parameter.
+ // Ideally, the returned URL will be for the specified line of the file with
+ // the query string highlighted.
+ URLForSrcQuery func(src, query string, line int) string
+
+ // SearchResults optionally specifies a list of functions returning an HTML
+ // body for displaying search results.
+ SearchResults []SearchResultFunc
+
+ // GoogleAnalytics optionally adds Google Analytics via the provided
+ // tracking ID to each page.
+ GoogleAnalytics string
+
+ initFuncMapOnce sync.Once
+ funcMap template.FuncMap
+ templateFuncs template.FuncMap
+}
+
+// NewPresentation returns a new Presentation from a corpus.
+// It sets SearchResults to:
+// [SearchResultDoc SearchResultCode SearchResultTxt].
+func NewPresentation(c *Corpus) *Presentation {
+ if c == nil {
+ panic("nil Corpus")
+ }
+ p := &Presentation{
+ Corpus: c,
+ mux: http.NewServeMux(),
+ fileServer: http.FileServer(httpfs.New(c.fs)),
+
+ TabWidth: 4,
+ DeclLinks: true,
+ SearchResults: []SearchResultFunc{
+ (*Presentation).SearchResultDoc,
+ (*Presentation).SearchResultCode,
+ (*Presentation).SearchResultTxt,
+ },
+ }
+ p.cmdHandler = handlerServer{
+ p: p,
+ c: c,
+ pattern: "/cmd/",
+ fsRoot: "/src",
+ }
+ p.pkgHandler = handlerServer{
+ p: p,
+ c: c,
+ pattern: "/pkg/",
+ stripPrefix: "pkg/",
+ fsRoot: "/src",
+ exclude: []string{"/src/cmd"},
+ }
+ p.cmdHandler.registerWithMux(p.mux)
+ p.pkgHandler.registerWithMux(p.mux)
+ p.mux.HandleFunc("/", p.ServeFile)
+ p.mux.HandleFunc("/search", p.HandleSearch)
+ if p.SearchDescXML != nil {
+ p.mux.HandleFunc("/opensearch.xml", p.serveSearchDesc)
+ }
+ return p
+}
+
+func (p *Presentation) FileServer() http.Handler {
+ return p.fileServer
+}
+
+func (p *Presentation) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ p.mux.ServeHTTP(w, r)
+}
+
+func (p *Presentation) PkgFSRoot() string {
+ return p.pkgHandler.fsRoot
+}
+
+func (p *Presentation) CmdFSRoot() string {
+ return p.cmdHandler.fsRoot
+}
+
+// TODO(bradfitz): move this to be a method on Corpus. Just moving code around for now,
+// but this doesn't feel right.
+func (p *Presentation) GetPkgPageInfo(abspath, relpath string, mode PageInfoMode) *PageInfo {
+ return p.pkgHandler.GetPageInfo(abspath, relpath, mode, "", "")
+}
+
+// TODO(bradfitz): move this to be a method on Corpus. Just moving code around for now,
+// but this doesn't feel right.
+func (p *Presentation) GetCmdPageInfo(abspath, relpath string, mode PageInfoMode) *PageInfo {
+ return p.cmdHandler.GetPageInfo(abspath, relpath, mode, "", "")
+}