github.com/powerman/golang-tools@v0.1.11-0.20220410185822-5ad214d8d803/godoc/pres.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package godoc 6 7 import ( 8 "net/http" 9 "regexp" 10 "sync" 11 "text/template" 12 13 "github.com/powerman/golang-tools/godoc/vfs/httpfs" 14 ) 15 16 // SearchResultFunc functions return an HTML body for displaying search results. 17 type SearchResultFunc func(p *Presentation, result SearchResult) []byte 18 19 // Presentation generates output from a corpus. 20 type Presentation struct { 21 Corpus *Corpus 22 23 mux *http.ServeMux 24 fileServer http.Handler 25 cmdHandler handlerServer 26 pkgHandler handlerServer 27 28 CallGraphHTML, 29 DirlistHTML, 30 ErrorHTML, 31 ExampleHTML, 32 GodocHTML, 33 ImplementsHTML, 34 MethodSetHTML, 35 PackageHTML, 36 PackageRootHTML, 37 SearchHTML, 38 SearchDocHTML, 39 SearchCodeHTML, 40 SearchTxtHTML, 41 SearchDescXML *template.Template // If not nil, register a /opensearch.xml handler with this template. 42 43 // TabWidth optionally specifies the tab width. 44 TabWidth int 45 46 ShowTimestamps bool 47 ShowPlayground bool 48 DeclLinks bool 49 50 // NotesRx optionally specifies a regexp to match 51 // notes to render in the output. 52 NotesRx *regexp.Regexp 53 54 // AdjustPageInfoMode optionally specifies a function to 55 // modify the PageInfoMode of a request. The default chosen 56 // value is provided. 57 AdjustPageInfoMode func(req *http.Request, mode PageInfoMode) PageInfoMode 58 59 // URLForSrc optionally specifies a function that takes a source file and 60 // returns a URL for it. 61 // The source file argument has the form /src/<path>/<filename>. 62 URLForSrc func(src string) string 63 64 // URLForSrcPos optionally specifies a function to create a URL given a 65 // source file, a line from the source file (1-based), and low & high offset 66 // positions (0-based, bytes from beginning of file). Ideally, the returned 67 // URL will be for the specified line of the file, while the high & low 68 // positions will be used to highlight a section of the file. 69 // The source file argument has the form /src/<path>/<filename>. 70 URLForSrcPos func(src string, line, low, high int) string 71 72 // URLForSrcQuery optionally specifies a function to create a URL given a 73 // source file, a query string, and a line from the source file (1-based). 74 // The source file argument has the form /src/<path>/<filename>. 75 // The query argument will be escaped for the purposes of embedding in a URL 76 // query parameter. 77 // Ideally, the returned URL will be for the specified line of the file with 78 // the query string highlighted. 79 URLForSrcQuery func(src, query string, line int) string 80 81 // SearchResults optionally specifies a list of functions returning an HTML 82 // body for displaying search results. 83 SearchResults []SearchResultFunc 84 85 // GoogleAnalytics optionally adds Google Analytics via the provided 86 // tracking ID to each page. 87 GoogleAnalytics string 88 89 initFuncMapOnce sync.Once 90 funcMap template.FuncMap 91 templateFuncs template.FuncMap 92 } 93 94 // NewPresentation returns a new Presentation from a corpus. 95 // It sets SearchResults to: 96 // [SearchResultDoc SearchResultCode SearchResultTxt]. 97 func NewPresentation(c *Corpus) *Presentation { 98 if c == nil { 99 panic("nil Corpus") 100 } 101 p := &Presentation{ 102 Corpus: c, 103 mux: http.NewServeMux(), 104 fileServer: http.FileServer(httpfs.New(c.fs)), 105 106 TabWidth: 4, 107 DeclLinks: true, 108 SearchResults: []SearchResultFunc{ 109 (*Presentation).SearchResultDoc, 110 (*Presentation).SearchResultCode, 111 (*Presentation).SearchResultTxt, 112 }, 113 } 114 p.cmdHandler = handlerServer{ 115 p: p, 116 c: c, 117 pattern: "/cmd/", 118 fsRoot: "/src", 119 } 120 p.pkgHandler = handlerServer{ 121 p: p, 122 c: c, 123 pattern: "/pkg/", 124 stripPrefix: "pkg/", 125 fsRoot: "/src", 126 exclude: []string{"/src/cmd"}, 127 } 128 p.cmdHandler.registerWithMux(p.mux) 129 p.pkgHandler.registerWithMux(p.mux) 130 p.mux.HandleFunc("/", p.ServeFile) 131 p.mux.HandleFunc("/search", p.HandleSearch) 132 if p.SearchDescXML != nil { 133 p.mux.HandleFunc("/opensearch.xml", p.serveSearchDesc) 134 } 135 return p 136 } 137 138 func (p *Presentation) FileServer() http.Handler { 139 return p.fileServer 140 } 141 142 func (p *Presentation) ServeHTTP(w http.ResponseWriter, r *http.Request) { 143 p.mux.ServeHTTP(w, r) 144 } 145 146 func (p *Presentation) PkgFSRoot() string { 147 return p.pkgHandler.fsRoot 148 } 149 150 func (p *Presentation) CmdFSRoot() string { 151 return p.cmdHandler.fsRoot 152 } 153 154 // TODO(bradfitz): move this to be a method on Corpus. Just moving code around for now, 155 // but this doesn't feel right. 156 func (p *Presentation) GetPkgPageInfo(abspath, relpath string, mode PageInfoMode) *PageInfo { 157 return p.pkgHandler.GetPageInfo(abspath, relpath, mode, "", "") 158 } 159 160 // TODO(bradfitz): move this to be a method on Corpus. Just moving code around for now, 161 // but this doesn't feel right. 162 func (p *Presentation) GetCmdPageInfo(abspath, relpath string, mode PageInfoMode) *PageInfo { 163 return p.cmdHandler.GetPageInfo(abspath, relpath, mode, "", "") 164 }