зеркало из https://github.com/golang/gddo.git
gddo-server: consolidate template initialization
This is in preparation for passing around the template map explicitly instead of using it as a global. It also moves the manifest of template sets into templates.go and out of main.go. Change-Id: Ic7db8d5ab0186c1f4eb2446871e2c18ae1554d82 Reviewed-on: https://go-review.googlesource.com/67051 Reviewed-by: Tuo Shan <shantuo@google.com>
This commit is contained in:
Родитель
ddb3324051
Коммит
d0b0199669
|
@ -310,10 +310,10 @@ func servePackage(resp http.ResponseWriter, req *http.Request) error {
|
|||
}
|
||||
template += templateExt(req)
|
||||
|
||||
return executeTemplate(resp, template, status, http.Header{"Etag": {etag}}, map[string]interface{}{
|
||||
return templates.execute(resp, template, status, http.Header{"Etag": {etag}}, map[string]interface{}{
|
||||
"flashMessages": flashMessages,
|
||||
"pkgs": pkgs,
|
||||
"pdoc": newTDoc(pdoc),
|
||||
"pdoc": newTDoc(viper.GetViper(), pdoc),
|
||||
"importerCount": importerCount,
|
||||
})
|
||||
case isView(req, "imports"):
|
||||
|
@ -324,20 +324,20 @@ func servePackage(resp http.ResponseWriter, req *http.Request) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return executeTemplate(resp, "imports.html", http.StatusOK, nil, map[string]interface{}{
|
||||
return templates.execute(resp, "imports.html", http.StatusOK, nil, map[string]interface{}{
|
||||
"flashMessages": flashMessages,
|
||||
"pkgs": pkgs,
|
||||
"pdoc": newTDoc(pdoc),
|
||||
"pdoc": newTDoc(viper.GetViper(), pdoc),
|
||||
})
|
||||
case isView(req, "tools"):
|
||||
proto := "http"
|
||||
if req.Host == "godoc.org" {
|
||||
proto = "https"
|
||||
}
|
||||
return executeTemplate(resp, "tools.html", http.StatusOK, nil, map[string]interface{}{
|
||||
return templates.execute(resp, "tools.html", http.StatusOK, nil, map[string]interface{}{
|
||||
"flashMessages": flashMessages,
|
||||
"uri": fmt.Sprintf("%s://%s/%s", proto, req.Host, importPath),
|
||||
"pdoc": newTDoc(pdoc),
|
||||
"pdoc": newTDoc(viper.GetViper(), pdoc),
|
||||
})
|
||||
case isView(req, "importers"):
|
||||
if pdoc.Name == "" {
|
||||
|
@ -352,10 +352,10 @@ func servePackage(resp http.ResponseWriter, req *http.Request) error {
|
|||
// Hide back links from robots.
|
||||
template = "importers_robot.html"
|
||||
}
|
||||
return executeTemplate(resp, template, http.StatusOK, nil, map[string]interface{}{
|
||||
return templates.execute(resp, template, http.StatusOK, nil, map[string]interface{}{
|
||||
"flashMessages": flashMessages,
|
||||
"pkgs": pkgs,
|
||||
"pdoc": newTDoc(pdoc),
|
||||
"pdoc": newTDoc(viper.GetViper(), pdoc),
|
||||
})
|
||||
case isView(req, "import-graph"):
|
||||
if requestType == robotRequest {
|
||||
|
@ -379,10 +379,10 @@ func servePackage(resp http.ResponseWriter, req *http.Request) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return executeTemplate(resp, "graph.html", http.StatusOK, nil, map[string]interface{}{
|
||||
return templates.execute(resp, "graph.html", http.StatusOK, nil, map[string]interface{}{
|
||||
"flashMessages": flashMessages,
|
||||
"svg": template.HTML(b),
|
||||
"pdoc": newTDoc(pdoc),
|
||||
"pdoc": newTDoc(viper.GetViper(), pdoc),
|
||||
"hide": hide,
|
||||
})
|
||||
case isView(req, "play"):
|
||||
|
@ -447,7 +447,7 @@ func serveGoIndex(resp http.ResponseWriter, req *http.Request) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return executeTemplate(resp, "std.html", http.StatusOK, nil, map[string]interface{}{
|
||||
return templates.execute(resp, "std.html", http.StatusOK, nil, map[string]interface{}{
|
||||
"pkgs": pkgs,
|
||||
})
|
||||
}
|
||||
|
@ -457,7 +457,7 @@ func serveGoSubrepoIndex(resp http.ResponseWriter, req *http.Request) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return executeTemplate(resp, "subrepo.html", http.StatusOK, nil, map[string]interface{}{
|
||||
return templates.execute(resp, "subrepo.html", http.StatusOK, nil, map[string]interface{}{
|
||||
"pkgs": pkgs,
|
||||
})
|
||||
}
|
||||
|
@ -540,7 +540,7 @@ func serveHome(resp http.ResponseWriter, req *http.Request) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return executeTemplate(resp, "home"+templateExt(req), http.StatusOK, nil,
|
||||
return templates.execute(resp, "home"+templateExt(req), http.StatusOK, nil,
|
||||
map[string]interface{}{"Popular": pkgs})
|
||||
}
|
||||
|
||||
|
@ -573,17 +573,17 @@ func serveHome(resp http.ResponseWriter, req *http.Request) error {
|
|||
gceLogger.LogEvent(resp, req, logPkgs)
|
||||
}
|
||||
|
||||
return executeTemplate(resp, "results"+templateExt(req), http.StatusOK, nil,
|
||||
return templates.execute(resp, "results"+templateExt(req), http.StatusOK, nil,
|
||||
map[string]interface{}{"q": q, "pkgs": pkgs})
|
||||
}
|
||||
|
||||
func serveAbout(resp http.ResponseWriter, req *http.Request) error {
|
||||
return executeTemplate(resp, "about.html", http.StatusOK, nil,
|
||||
return templates.execute(resp, "about.html", http.StatusOK, nil,
|
||||
map[string]interface{}{"Host": req.Host})
|
||||
}
|
||||
|
||||
func serveBot(resp http.ResponseWriter, req *http.Request) error {
|
||||
return executeTemplate(resp, "bot.html", http.StatusOK, nil, nil)
|
||||
return templates.execute(resp, "bot.html", http.StatusOK, nil, nil)
|
||||
}
|
||||
|
||||
func serveHealthCheck(resp http.ResponseWriter, req *http.Request) {
|
||||
|
@ -757,7 +757,7 @@ func errorText(err error) string {
|
|||
func handleError(resp http.ResponseWriter, req *http.Request, status int, err error) {
|
||||
switch status {
|
||||
case http.StatusNotFound:
|
||||
executeTemplate(resp, "notfound"+templateExt(req), status, nil, map[string]interface{}{
|
||||
templates.execute(resp, "notfound"+templateExt(req), status, nil, map[string]interface{}{
|
||||
"flashMessages": getFlashMessages(resp, req),
|
||||
})
|
||||
default:
|
||||
|
@ -846,38 +846,12 @@ func main() {
|
|||
doc.SetDefaultGOOS(viper.GetString(ConfigDefaultGOOS))
|
||||
httpClient = newHTTPClient(viper.GetViper())
|
||||
|
||||
if err := parseHTMLTemplates([][]string{
|
||||
{"about.html", "common.html", "layout.html"},
|
||||
{"bot.html", "common.html", "layout.html"},
|
||||
{"cmd.html", "common.html", "layout.html"},
|
||||
{"dir.html", "common.html", "layout.html"},
|
||||
{"home.html", "common.html", "layout.html"},
|
||||
{"importers.html", "common.html", "layout.html"},
|
||||
{"importers_robot.html", "common.html", "layout.html"},
|
||||
{"imports.html", "common.html", "layout.html"},
|
||||
{"notfound.html", "common.html", "layout.html"},
|
||||
{"pkg.html", "common.html", "layout.html"},
|
||||
{"results.html", "common.html", "layout.html"},
|
||||
{"tools.html", "common.html", "layout.html"},
|
||||
{"std.html", "common.html", "layout.html"},
|
||||
{"subrepo.html", "common.html", "layout.html"},
|
||||
{"graph.html", "common.html"},
|
||||
}); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if err := parseTextTemplates([][]string{
|
||||
{"cmd.txt", "common.txt"},
|
||||
{"dir.txt", "common.txt"},
|
||||
{"home.txt", "common.txt"},
|
||||
{"notfound.txt", "common.txt"},
|
||||
{"pkg.txt", "common.txt"},
|
||||
{"results.txt", "common.txt"},
|
||||
}); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var err error
|
||||
templates, err = parseTemplates(viper.GetString(ConfigAssetsDir), viper.GetViper())
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
db, err = database.New(
|
||||
viper.GetString(ConfigDBServer),
|
||||
viper.GetDuration(ConfigDBIdleTimeout),
|
||||
|
|
|
@ -80,7 +80,8 @@ func setFlashMessages(resp http.ResponseWriter, messages []flashMessage) {
|
|||
|
||||
type tdoc struct {
|
||||
*doc.Package
|
||||
allExamples []*texample
|
||||
allExamples []*texample
|
||||
sourcegraphURL string
|
||||
}
|
||||
|
||||
type texample struct {
|
||||
|
@ -91,8 +92,11 @@ type texample struct {
|
|||
obj interface{}
|
||||
}
|
||||
|
||||
func newTDoc(pdoc *doc.Package) *tdoc {
|
||||
return &tdoc{Package: pdoc}
|
||||
func newTDoc(v *viper.Viper, pdoc *doc.Package) *tdoc {
|
||||
return &tdoc{
|
||||
Package: pdoc,
|
||||
sourcegraphURL: v.GetString(ConfigSourcegraphURL),
|
||||
}
|
||||
}
|
||||
|
||||
func (pdoc *tdoc) SourceLink(pos doc.Pos, text string, textOnlyOK bool) htemp.HTML {
|
||||
|
@ -110,7 +114,7 @@ func (pdoc *tdoc) SourceLink(pos doc.Pos, text string, textOnlyOK bool) htemp.HT
|
|||
// UsesLink generates a link to uses of a symbol definition.
|
||||
// title is used as the tooltip. defParts are parts of the symbol definition name.
|
||||
func (pdoc *tdoc) UsesLink(title string, defParts ...string) htemp.HTML {
|
||||
if viper.GetString(ConfigSourcegraphURL) == "" {
|
||||
if pdoc.sourcegraphURL == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
|
@ -146,7 +150,7 @@ func (pdoc *tdoc) UsesLink(title string, defParts ...string) htemp.HTML {
|
|||
"pkg": {pdoc.ImportPath},
|
||||
"def": {def},
|
||||
}
|
||||
u := viper.GetString(ConfigSourcegraphURL) + "/-/godoc/refs?" + q.Encode()
|
||||
u := pdoc.sourcegraphURL + "/-/godoc/refs?" + q.Encode()
|
||||
return htemp.HTML(fmt.Sprintf(`<a class="uses" title="%s" href="%s">Uses</a>`, htemp.HTMLEscapeString(title), htemp.HTMLEscapeString(u)))
|
||||
}
|
||||
|
||||
|
@ -485,7 +489,15 @@ var mimeTypes = map[string]string{
|
|||
".txt": textMIMEType,
|
||||
}
|
||||
|
||||
func executeTemplate(resp http.ResponseWriter, name string, status int, header http.Header, data interface{}) error {
|
||||
// TODO(light): pass templates explicitly, not as a global.
|
||||
|
||||
var templates templateMap
|
||||
|
||||
type templateMap map[string]interface {
|
||||
Execute(io.Writer, interface{}) error
|
||||
}
|
||||
|
||||
func (m templateMap) execute(resp http.ResponseWriter, name string, status int, header http.Header, data interface{}) error {
|
||||
for k, v := range header {
|
||||
resp.Header()[k] = v
|
||||
}
|
||||
|
@ -494,7 +506,7 @@ func executeTemplate(resp http.ResponseWriter, name string, status int, header h
|
|||
mimeType = textMIMEType
|
||||
}
|
||||
resp.Header().Set("Content-Type", mimeType)
|
||||
t := templates[name]
|
||||
t := m[name]
|
||||
if t == nil {
|
||||
return fmt.Errorf("template %s not found", name)
|
||||
}
|
||||
|
@ -505,10 +517,6 @@ func executeTemplate(resp http.ResponseWriter, name string, status int, header h
|
|||
return t.Execute(resp, data)
|
||||
}
|
||||
|
||||
var templates = map[string]interface {
|
||||
Execute(io.Writer, interface{}) error
|
||||
}{}
|
||||
|
||||
func joinTemplateDir(base string, files []string) []string {
|
||||
result := make([]string, len(files))
|
||||
for i := range files {
|
||||
|
@ -517,53 +525,76 @@ func joinTemplateDir(base string, files []string) []string {
|
|||
return result
|
||||
}
|
||||
|
||||
func parseHTMLTemplates(sets [][]string) error {
|
||||
for _, set := range sets {
|
||||
func parseTemplates(dir string, v *viper.Viper) (templateMap, error) {
|
||||
m := make(templateMap)
|
||||
htmlSets := [][]string{
|
||||
{"about.html", "common.html", "layout.html"},
|
||||
{"bot.html", "common.html", "layout.html"},
|
||||
{"cmd.html", "common.html", "layout.html"},
|
||||
{"dir.html", "common.html", "layout.html"},
|
||||
{"home.html", "common.html", "layout.html"},
|
||||
{"importers.html", "common.html", "layout.html"},
|
||||
{"importers_robot.html", "common.html", "layout.html"},
|
||||
{"imports.html", "common.html", "layout.html"},
|
||||
{"notfound.html", "common.html", "layout.html"},
|
||||
{"pkg.html", "common.html", "layout.html"},
|
||||
{"results.html", "common.html", "layout.html"},
|
||||
{"tools.html", "common.html", "layout.html"},
|
||||
{"std.html", "common.html", "layout.html"},
|
||||
{"subrepo.html", "common.html", "layout.html"},
|
||||
{"graph.html", "common.html"},
|
||||
}
|
||||
hfuncs := htemp.FuncMap{
|
||||
"code": codeFn,
|
||||
"comment": commentFn,
|
||||
"equal": reflect.DeepEqual,
|
||||
"gaAccount": func() string { return v.GetString(ConfigGAAccount) },
|
||||
"host": hostFn,
|
||||
"htmlComment": htmlCommentFn,
|
||||
"importPath": importPathFn,
|
||||
"isInterface": isInterfaceFn,
|
||||
"isValidImportPath": gosrc.IsValidPath,
|
||||
"map": mapFn,
|
||||
"noteTitle": noteTitleFn,
|
||||
"relativePath": relativePathFn,
|
||||
"sidebarEnabled": func() bool { return v.GetBool(ConfigSidebar) },
|
||||
"staticPath": func(p string) string { return cacheBusters.AppendQueryParam(p, "v") },
|
||||
}
|
||||
for _, set := range htmlSets {
|
||||
templateName := set[0]
|
||||
t := htemp.New("")
|
||||
t.Funcs(htemp.FuncMap{
|
||||
"code": codeFn,
|
||||
"comment": commentFn,
|
||||
"equal": reflect.DeepEqual,
|
||||
"gaAccount": func() string { return viper.GetString(ConfigGAAccount) },
|
||||
"host": hostFn,
|
||||
"htmlComment": htmlCommentFn,
|
||||
"importPath": importPathFn,
|
||||
"isInterface": isInterfaceFn,
|
||||
"isValidImportPath": gosrc.IsValidPath,
|
||||
"map": mapFn,
|
||||
"noteTitle": noteTitleFn,
|
||||
"relativePath": relativePathFn,
|
||||
"sidebarEnabled": func() bool { return viper.GetBool(ConfigSidebar) },
|
||||
"staticPath": func(p string) string { return cacheBusters.AppendQueryParam(p, "v") },
|
||||
"templateName": func() string { return templateName },
|
||||
t := htemp.New("").Funcs(hfuncs).Funcs(htemp.FuncMap{
|
||||
"templateName": func() string { return templateName },
|
||||
})
|
||||
if _, err := t.ParseFiles(joinTemplateDir(viper.GetString(ConfigAssetsDir), set)...); err != nil {
|
||||
return err
|
||||
if _, err := t.ParseFiles(joinTemplateDir(dir, set)...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t = t.Lookup("ROOT")
|
||||
if t == nil {
|
||||
return fmt.Errorf("ROOT template not found in %v", set)
|
||||
return nil, fmt.Errorf("ROOT template not found in %v", set)
|
||||
}
|
||||
templates[set[0]] = t
|
||||
m[set[0]] = t
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseTextTemplates(sets [][]string) error {
|
||||
for _, set := range sets {
|
||||
t := ttemp.New("")
|
||||
t.Funcs(ttemp.FuncMap{
|
||||
"comment": commentTextFn,
|
||||
})
|
||||
if _, err := t.ParseFiles(joinTemplateDir(viper.GetString(ConfigAssetsDir), set)...); err != nil {
|
||||
return err
|
||||
textSets := [][]string{
|
||||
{"cmd.txt", "common.txt"},
|
||||
{"dir.txt", "common.txt"},
|
||||
{"home.txt", "common.txt"},
|
||||
{"notfound.txt", "common.txt"},
|
||||
{"pkg.txt", "common.txt"},
|
||||
{"results.txt", "common.txt"},
|
||||
}
|
||||
tfuncs := ttemp.FuncMap{
|
||||
"comment": commentTextFn,
|
||||
}
|
||||
for _, set := range textSets {
|
||||
t := ttemp.New("").Funcs(tfuncs)
|
||||
if _, err := t.ParseFiles(joinTemplateDir(dir, set)...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t = t.Lookup("ROOT")
|
||||
if t == nil {
|
||||
return fmt.Errorf("ROOT template not found in %v", set)
|
||||
return nil, fmt.Errorf("ROOT template not found in %v", set)
|
||||
}
|
||||
templates[set[0]] = t
|
||||
m[set[0]] = t
|
||||
}
|
||||
return nil
|
||||
return m, nil
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче