This commit is contained in:
xing 2023-04-24 21:51:43 +08:00
parent 345cdcd4e0
commit 4760f65b9b
16 changed files with 104 additions and 82 deletions

View File

@ -7,7 +7,7 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
func ThemeHook(scene int) func(*gin.Context) { func ThemeHook(scene string) func(*gin.Context) {
return func(c *gin.Context) { return func(c *gin.Context) {
s := scene s := scene
if scene == constraints.Home { if scene == constraints.Home {
@ -19,6 +19,8 @@ func ThemeHook(scene int) func(*gin.Context) {
h := wp.NewHandle(c, s, t) h := wp.NewHandle(c, s, t)
h.Index = wp.NewIndexHandle(h) h.Index = wp.NewIndexHandle(h)
h.Detail = wp.NewDetailHandle(h) h.Detail = wp.NewDetailHandle(h)
templ, _ := theme.GetTemplate(t)
h.SetTemplate(templ)
theme.Hook(t, h) theme.Hook(t, h)
} }
} }

View File

@ -14,7 +14,7 @@ import (
) )
var postContextCache *cache.MapCache[uint64, dao.PostContext] var postContextCache *cache.MapCache[uint64, dao.PostContext]
var categoryAndTagsCaches *cache.MapCache[int, []models.TermsMy] var categoryAndTagsCaches *cache.MapCache[string, []models.TermsMy]
var recentPostsCaches *cache.VarCache[[]models.Posts] var recentPostsCaches *cache.VarCache[[]models.Posts]
var recentCommentsCaches *cache.VarCache[[]models.Comments] var recentCommentsCaches *cache.VarCache[[]models.Comments]
var postCommentCaches *cache.MapCache[uint64, []uint64] var postCommentCaches *cache.MapCache[uint64, []uint64]
@ -56,7 +56,7 @@ func InitActionsCommonCache() {
postMetaCache = cachemanager.MapBatchCacheBy(dao.GetPostMetaByPostIds, c.CacheTime.PostDataCacheTime) postMetaCache = cachemanager.MapBatchCacheBy(dao.GetPostMetaByPostIds, c.CacheTime.PostDataCacheTime)
categoryAndTagsCaches = cachemanager.MapCacheBy[int](dao.CategoriesAndTags, c.CacheTime.CategoryCacheTime) categoryAndTagsCaches = cachemanager.MapCacheBy[string](dao.CategoriesAndTags, c.CacheTime.CategoryCacheTime)
recentPostsCaches = cache.NewVarCache(dao.RecentPosts, c.CacheTime.RecentPostCacheTime) recentPostsCaches = cache.NewVarCache(dao.RecentPosts, c.CacheTime.RecentPostCacheTime)
@ -117,8 +117,8 @@ func Archives(ctx context.Context) []models.PostArchive {
// CategoriesTags categories or tags // CategoriesTags categories or tags
// //
// t is constraints.Tag or constraints.Category // t is constraints.Tag or constraints.Category
func CategoriesTags(ctx context.Context, t ...int) []models.TermsMy { func CategoriesTags(ctx context.Context, t ...string) []models.TermsMy {
tt := 0 tt := ""
if len(t) > 0 { if len(t) > 0 {
tt = t[0] tt = t[0]
} }
@ -126,8 +126,8 @@ func CategoriesTags(ctx context.Context, t ...int) []models.TermsMy {
logs.IfError(err, "get category fail") logs.IfError(err, "get category fail")
return r return r
} }
func AllCategoryTagsNames(ctx context.Context, t ...int) map[string]struct{} { func AllCategoryTagsNames(ctx context.Context, t ...string) map[string]struct{} {
tt := 0 tt := ""
if len(t) > 0 { if len(t) > 0 {
tt = t[0] tt = t[0]
} }

View File

@ -1,23 +1,23 @@
package constraints package constraints
const ( const (
Home = iota + 1 Home = "Home"
Archive Archive = "Archive"
Category Category = "Category"
Tag Tag = "Tag"
Search Search = "Search"
Author Author = "Author"
Detail Detail = "Detail"
Ok Ok = "Ok"
Error404 Error404 = "Error404"
ParamError ParamError = "ParamError"
InternalErr InternalErr = "InternalErr"
AllStats AllStats = "AllStats"
AllScene AllScene = "AllScene"
PipData PipeData = "PipeData"
PipRender PipeRender = "PipeRender"
Defaults = "default" Defaults = "default"

View File

@ -23,7 +23,7 @@ type PostContext struct {
func CategoriesAndTags(a ...any) (terms []models.TermsMy, err error) { func CategoriesAndTags(a ...any) (terms []models.TermsMy, err error) {
ctx := a[0].(context.Context) ctx := a[0].(context.Context)
t, ok := a[1].(int) t, ok := a[1].(string)
var in = []any{"category", "post_tag"} var in = []any{"category", "post_tag"}
if ok { if ok {
switch t { switch t {

View File

@ -22,8 +22,8 @@ var comFn = template.FuncMap{
}, },
"getLang": wpconfig.GetLang, "getLang": wpconfig.GetLang,
"postsFn": postsFn, "postsFn": postsFn,
"exec": func(fn func() string) string { "exec": func(fn func() string) template.HTML {
return fn() return template.HTML(fn())
}, },
} }

View File

@ -108,15 +108,16 @@ func calCustomHeader(h *wp.Handle) (r string, rand bool) {
return return
} }
func customHeader(h *wp.Handle) { func customHeader(h *wp.Handle) func() string {
headers := header.Load() return func() string {
if headers == constraints.Defaults { headers := header.Load()
headerss, rand := calCustomHeader(h) if headers == constraints.Defaults {
headers = headerss headerss, rand := calCustomHeader(h)
if !rand { headers = headerss
header.Store(headers) if !rand {
header.Store(headers)
}
} }
return headers
} }
h.SetData("customHeader", headers)
return
} }

View File

@ -13,7 +13,7 @@
<div id="sidebar" class="sidebar" style="position: relative; "> <div id="sidebar" class="sidebar" style="position: relative; ">
<header id="masthead" class="site-header"> <header id="masthead" class="site-header">
<div class="site-branding"> <div class="site-branding">
{{template "common/customLogo" .}} {{.customLogo|exec}}
<h1 class="site-title"> <h1 class="site-title">
<a href="/" rel="home">{{ "blogname"| getOption }}</a> <a href="/" rel="home">{{ "blogname"| getOption }}</a>
</h1> </h1>

View File

@ -62,6 +62,7 @@
<style>.recentcomments a{display:inline !important;padding:0 !important;margin:0 !important;}</style> <style>.recentcomments a{display:inline !important;padding:0 !important;margin:0 !important;}</style>
{{template "common/head" .}} {{template "common/head" .}}
{{.customHeader|exec}}
{{block "head" .}} {{block "head" .}}
{{end}} {{end}}
</head> </head>

View File

@ -42,8 +42,8 @@ func Init(fs embed.FS) {
} }
var pipe = wp.HandlePipe(wp.NothingToDo, widget.MiddleWare(ready, var pipe = wp.HandlePipe(wp.NothingToDo, widget.MiddleWare(ready,
wp.PipeHandle(constraints.PipData, wp.PipeKey, wp.PipeDataHandle), wp.PipeHandle(constraints.PipeData, wp.PipeKey, wp.PipeDataHandle),
wp.PipeHandle(constraints.PipRender, wp.PipeKey, wp.PipeRender), wp.PipeHandle(constraints.PipeRender, wp.PipeKey, wp.PipeRender),
)...) )...)
func Hook(h *wp.Handle) { func Hook(h *wp.Handle) {
@ -67,7 +67,7 @@ func configs(h *wp.Handle) {
h.CommonComponents() h.CommonComponents()
h.Index.SetListPlugin(wp.PostsPlugins(wp.PostPlugin(), wp.GetListPostPlugins(conf.ListPagePlugins, wp.ListPostPlugins())...)) h.Index.SetListPlugin(wp.PostsPlugins(wp.PostPlugin(), wp.GetListPostPlugins(conf.ListPagePlugins, wp.ListPostPlugins())...))
components.WidgetArea(h) components.WidgetArea(h)
h.PushRender(constraints.AllStats, wp.NewHandleFn(customHeader, 10, "customHeader")) h.SetData("customHeader", customHeader(h))
h.PushRender(constraints.AllStats, wp.NewHandleFn(wp.IndexRender, 50, "wp.IndexRender")) h.PushRender(constraints.AllStats, wp.NewHandleFn(wp.IndexRender, 50, "wp.IndexRender"))
h.PushRender(constraints.Detail, wp.NewHandleFn(wp.DetailRender, 50, "wp.DetailRender")) h.PushRender(constraints.Detail, wp.NewHandleFn(wp.DetailRender, 50, "wp.DetailRender"))
h.PushRender(constraints.Detail, wp.NewHandleFn(postThumb, 60, "postThumb")) h.PushRender(constraints.Detail, wp.NewHandleFn(postThumb, 60, "postThumb"))

View File

@ -20,14 +20,14 @@
<div class="site-branding" style="margin-bottom: 0px;"> <div class="site-branding" style="margin-bottom: 0px;">
<div class="wrap"> <div class="wrap">
{{template "common/customLogo" .}} {{.customLogo|exec}}
<div class="site-branding-text"> <div class="site-branding-text">
<h1 class="site-title"> <h1 class="site-title">
<a href="/" rel="home">{{ "blogname"| getOption }}</a> <a href="/" rel="home">{{ "blogname"| getOption }}</a>
</h1> </h1>
<p class="site-description">{{"blogdescription"| getOption}}</p> <p class="site-description">{{"blogdescription"| getOption}}</p>
</div><!-- .site-branding-text --> </div><!-- .site-branding-text -->
{{if eq .scene 1}} {{if eq .scene "home"}}
<a href="#content" class="menu-scroll-down"> <a href="#content" class="menu-scroll-down">
<svg class="icon icon-arrow-right" aria-hidden="true" role="img"> <svg class="icon icon-arrow-right" aria-hidden="true" role="img">
<use href="#icon-arrow-right" xlink:href="#icon-arrow-right"></use> <use href="#icon-arrow-right" xlink:href="#icon-arrow-right"></use>

View File

@ -43,8 +43,8 @@ var paginate = func() plugins.PageEle {
}() }()
var pipe = wp.HandlePipe(wp.NothingToDo, widget.MiddleWare(ready, var pipe = wp.HandlePipe(wp.NothingToDo, widget.MiddleWare(ready,
wp.PipeHandle(constraints.PipData, wp.PipeKey, wp.PipeDataHandle), wp.PipeHandle(constraints.PipeData, wp.PipeKey, wp.PipeDataHandle),
wp.PipeHandle(constraints.PipRender, wp.PipeKey, wp.PipeRender), wp.PipeHandle(constraints.PipeRender, wp.PipeKey, wp.PipeRender),
)...) )...)
func Hook(h *wp.Handle) { func Hook(h *wp.Handle) {

View File

@ -13,6 +13,12 @@ import (
"strings" "strings"
) )
func bodyClass(h *Handle) func() string {
return func() string {
return h.BodyClass()
}
}
func (h *Handle) BodyClass() string { func (h *Handle) BodyClass() string {
var class []string var class []string
if constraints.Ok != h.Stats { if constraints.Ok != h.Stats {
@ -73,6 +79,12 @@ func (h *Handle) BodyClass() string {
} }
return h.ComponentFilterFnHook("bodyClass", strings.Join(class, " ")) return h.ComponentFilterFnHook("bodyClass", strings.Join(class, " "))
} }
func postClass(h *Handle) func(posts models.Posts) string {
return func(posts models.Posts) string {
return h.PostClass(posts)
}
}
func (h *Handle) PostClass(posts models.Posts) string { func (h *Handle) PostClass(posts models.Posts) string {
var class []string var class []string
class = append(class, fmt.Sprintf("post-%d", posts.Id), posts.PostType, class = append(class, fmt.Sprintf("post-%d", posts.Id), posts.PostType,

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"github.com/fthvgb1/wp-go/helper/maps" "github.com/fthvgb1/wp-go/helper/maps"
str "github.com/fthvgb1/wp-go/helper/strings" str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/internal/cmd/reload"
"github.com/fthvgb1/wp-go/internal/pkg/cache" "github.com/fthvgb1/wp-go/internal/pkg/cache"
"github.com/fthvgb1/wp-go/internal/wpconfig" "github.com/fthvgb1/wp-go/internal/wpconfig"
) )
@ -40,3 +41,11 @@ func CalCustomLogo(h *Handle) (r string) {
r = fmt.Sprintf(`<a href="%s" class="custom-logo-link" rel="home"%s>%s</a>`, "/", ` aria-current="page"`, r) r = fmt.Sprintf(`<a href="%s" class="custom-logo-link" rel="home"%s>%s</a>`, "/", ` aria-current="page"`, r)
return return
} }
func customLogo(h *Handle) func() string {
return func() string {
return reload.GetAnyValBys("customLogo", h, func(h *Handle) string {
return CalCustomLogo(h)
})
}
}

View File

@ -18,23 +18,23 @@ func HandlePipe[T any](initial func(T), fns ...HandlePipeFn[T]) HandleFn[T] {
}, initial) }, initial)
} }
func (h *Handle) PushHandler(pipScene int, scene int, fns ...HandleCall) { func (h *Handle) PushHandler(pipScene string, scene string, fns ...HandleCall) {
if _, ok := h.handlers[pipScene]; !ok { if _, ok := h.handlers[pipScene]; !ok {
h.handlers[pipScene] = make(map[int][]HandleCall) h.handlers[pipScene] = make(map[string][]HandleCall)
} }
h.handlers[pipScene][scene] = append(h.handlers[pipScene][scene], fns...) h.handlers[pipScene][scene] = append(h.handlers[pipScene][scene], fns...)
} }
func (h *Handle) PushRender(statsOrScene int, fns ...HandleCall) { func (h *Handle) PushRender(statsOrScene string, fns ...HandleCall) {
h.PushHandler(constraints.PipRender, statsOrScene, fns...) h.PushHandler(constraints.PipeRender, statsOrScene, fns...)
} }
func (h *Handle) PushDataHandler(scene int, fns ...HandleCall) { func (h *Handle) PushDataHandler(scene string, fns ...HandleCall) {
h.PushHandler(constraints.PipData, scene, fns...) h.PushHandler(constraints.PipeData, scene, fns...)
} }
func PipeHandle(pipeScene int, keyFn func(*Handle, int) string, fn func(*Handle, map[int][]HandleCall) []HandleCall) func(HandleFn[*Handle], *Handle) { func PipeHandle(pipeScene string, keyFn func(*Handle, string) string, fn func(*Handle, map[string][]HandleCall) []HandleCall) func(HandleFn[*Handle], *Handle) {
return func(next HandleFn[*Handle], h *Handle) { return func(next HandleFn[*Handle], h *Handle) {
handlers := reload.SafetyMapBy("pipHandlers", keyFn(h, pipeScene), h, func(h *Handle) []HandleCall { handlers := reload.SafetyMapBy("pipeHandlers", keyFn(h, pipeScene), h, func(h *Handle) []HandleCall {
conf := h.handleHook[pipeScene] conf := h.handleHook[pipeScene]
calls := fn(h, h.handlers[pipeScene]) calls := fn(h, h.handlers[pipeScene])
calls = slice.FilterAndMap(calls, func(call HandleCall) (HandleCall, bool) { calls = slice.FilterAndMap(calls, func(call HandleCall) (HandleCall, bool) {
@ -64,17 +64,17 @@ func PipeHandle(pipeScene int, keyFn func(*Handle, int) string, fn func(*Handle,
} }
} }
func PipeKey(h *Handle, pipScene int) string { func PipeKey(h *Handle, pipScene string) string {
return fmt.Sprintf("pipekey-%d-%d-%d", pipScene, h.scene, h.scene) return fmt.Sprintf("pipekey-%s-%s-%s", pipScene, h.scene, h.scene)
} }
func PipeDataHandle(h *Handle, dataHandlers map[int][]HandleCall) (handlers []HandleCall) { func PipeDataHandle(h *Handle, dataHandlers map[string][]HandleCall) (handlers []HandleCall) {
handlers = append(handlers, dataHandlers[h.scene]...) handlers = append(handlers, dataHandlers[h.scene]...)
handlers = append(handlers, dataHandlers[constraints.AllScene]...) handlers = append(handlers, dataHandlers[constraints.AllScene]...)
return return
} }
func PipeRender(h *Handle, renders map[int][]HandleCall) (handlers []HandleCall) { func PipeRender(h *Handle, renders map[string][]HandleCall) (handlers []HandleCall) {
handlers = append(handlers, renders[h.Stats]...) handlers = append(handlers, renders[h.Stats]...)
handlers = append(handlers, renders[h.scene]...) handlers = append(handlers, renders[h.scene]...)
handlers = append(handlers, renders[constraints.AllStats]...) handlers = append(handlers, renders[constraints.AllStats]...)
@ -83,14 +83,14 @@ func PipeRender(h *Handle, renders map[int][]HandleCall) (handlers []HandleCall)
} }
// DeleteHandle 写插件的时候用 // DeleteHandle 写插件的时候用
func (h *Handle) DeleteHandle(pipeScene int, name string) { func (h *Handle) DeleteHandle(pipeScene string, name string) {
h.handleHook[pipeScene] = append(h.handleHook[pipeScene], func(call HandleCall) (HandleCall, bool) { h.handleHook[pipeScene] = append(h.handleHook[pipeScene], func(call HandleCall) (HandleCall, bool) {
return call, name != call.Name return call, name != call.Name
}) })
} }
// ReplaceHandle 写插件的时候用 // ReplaceHandle 写插件的时候用
func (h *Handle) ReplaceHandle(pipeScene int, name string, fn HandleFn[*Handle]) { func (h *Handle) ReplaceHandle(pipeScene, name string, fn HandleFn[*Handle]) {
h.handleHook[pipeScene] = append(h.handleHook[pipeScene], func(call HandleCall) (HandleCall, bool) { h.handleHook[pipeScene] = append(h.handleHook[pipeScene], func(call HandleCall) (HandleCall, bool) {
if name == call.Name { if name == call.Name {
call.Fn = fn call.Fn = fn
@ -100,6 +100,6 @@ func (h *Handle) ReplaceHandle(pipeScene int, name string, fn HandleFn[*Handle])
} }
// HookHandle 写插件的时候用 // HookHandle 写插件的时候用
func (h *Handle) HookHandle(pipeScene int, hook func(HandleCall) (HandleCall, bool)) { func (h *Handle) HookHandle(pipeScene string, hook func(HandleCall) (HandleCall, bool)) {
h.handleHook[pipeScene] = append(h.handleHook[pipeScene], hook) h.handleHook[pipeScene] = append(h.handleHook[pipeScene], hook)
} }

View File

@ -1,7 +1,4 @@
{{define "common/head"}} {{define "common/head"}}
{{if .customHeader}}
{{.customHeader|unescaped}}
{{end}}
{{if .headScript}} {{if .headScript}}
{{.headScript|unescaped}} {{.headScript|unescaped}}
@ -18,11 +15,6 @@
{{end}} {{end}}
{{end}} {{end}}
{{define "common/customLogo"}}
{{if .customLogo}}
{{.customLogo|unescaped}}
{{end}}
{{end}}
{{define "common/sidebarWidget"}} {{define "common/sidebarWidget"}}
{{if .sidebarsWidgets}} {{if .sidebarsWidgets}}

View File

@ -7,10 +7,10 @@ import (
"github.com/fthvgb1/wp-go/internal/cmd/reload" "github.com/fthvgb1/wp-go/internal/cmd/reload"
"github.com/fthvgb1/wp-go/internal/pkg/constraints" "github.com/fthvgb1/wp-go/internal/pkg/constraints"
"github.com/fthvgb1/wp-go/internal/pkg/logs" "github.com/fthvgb1/wp-go/internal/pkg/logs"
"github.com/fthvgb1/wp-go/internal/pkg/models"
"github.com/fthvgb1/wp-go/internal/wpconfig" "github.com/fthvgb1/wp-go/internal/wpconfig"
"github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"html/template"
"net/http" "net/http"
"strings" "strings"
) )
@ -23,19 +23,28 @@ type Handle struct {
Session sessions.Session Session sessions.Session
ginH gin.H ginH gin.H
password string password string
scene int scene string
Code int Code int
Stats int Stats string
templ string templ string
components map[string][]Components[string] components map[string][]Components[string]
themeMods wpconfig.ThemeMods themeMods wpconfig.ThemeMods
handlers map[int]map[int][]HandleCall handlers map[string]map[string][]HandleCall
handleHook map[int][]func(HandleCall) (HandleCall, bool) handleHook map[string][]func(HandleCall) (HandleCall, bool)
err error err error
abort bool abort bool
stopPipe bool stopPipe bool
componentsArgs map[string]any componentsArgs map[string]any
componentFilterFn map[string][]func(*Handle, string, ...any) string componentFilterFn map[string][]func(*Handle, string, ...any) string
template *template.Template
}
func (h *Handle) SetTemplate(template *template.Template) {
h.template = template
}
func (h *Handle) Template() *template.Template {
return h.template
} }
type HandlePlugins map[string]HandleFn[*Handle] type HandlePlugins map[string]HandleFn[*Handle]
@ -62,8 +71,8 @@ func InitThemeArgAndConfig(fn func(*Handle), h *Handle) {
h.components = make(map[string][]Components[string]) h.components = make(map[string][]Components[string])
h.componentsArgs = make(map[string]any) h.componentsArgs = make(map[string]any)
h.componentFilterFn = make(map[string][]func(*Handle, string, ...any) string) h.componentFilterFn = make(map[string][]func(*Handle, string, ...any) string)
h.handlers = make(map[int]map[int][]HandleCall) h.handlers = make(map[string]map[string][]HandleCall)
h.handleHook = make(map[int][]func(HandleCall) (HandleCall, bool)) h.handleHook = make(map[string][]func(HandleCall) (HandleCall, bool))
h.ginH = gin.H{} h.ginH = gin.H{}
fn(h) fn(h)
inited = true inited = true
@ -77,12 +86,9 @@ func InitThemeArgAndConfig(fn func(*Handle), h *Handle) {
} }
h.components = m h.components = m
h.ginH = maps.Copy(hh.ginH) h.ginH = maps.Copy(hh.ginH)
h.ginH["calPostClass"] = func(posts models.Posts) string { h.ginH["calPostClass"] = postClass(h)
return h.PostClass(posts) h.ginH["calBodyClass"] = bodyClass(h)
} h.ginH["customLogo"] = customLogo(h)
h.ginH["calBodyClass"] = func() string {
return h.BodyClass()
}
if inited { if inited {
return return
} }
@ -140,7 +146,7 @@ func (h *Handle) SetTempl(templ string) {
h.templ = templ h.templ = templ
} }
func (h *Handle) Scene() int { func (h *Handle) Scene() string {
return h.scene return h.scene
} }
@ -206,7 +212,7 @@ func (h *Handle) SetComponentsArgs(key string, value any) {
h.componentsArgs[key] = value h.componentsArgs[key] = value
} }
func NewHandle(c *gin.Context, scene int, theme string) *Handle { func NewHandle(c *gin.Context, scene string, theme string) *Handle {
mods, err := wpconfig.GetThemeMods(theme) mods, err := wpconfig.GetThemeMods(theme)
logs.IfError(err, "获取mods失败") logs.IfError(err, "获取mods失败")
return &Handle{ return &Handle{
@ -272,7 +278,7 @@ func PreTemplate(h *Handle) {
} }
} }
func PreCodeAndStats(h *Handle) { func PreCodeAndStats(h *Handle) {
if h.Stats != 0 && h.Code != 0 { if h.Stats != "" && h.Code != 0 {
return return
} }
switch h.Stats { switch h.Stats {
@ -286,7 +292,6 @@ func PreCodeAndStats(h *Handle) {
} }
func (h *Handle) CommonComponents() { func (h *Handle) CommonComponents() {
h.AddCacheComponent("customLogo", CalCustomLogo)
h.PushCacheGroupHeadScript("siteIconAndCustomCss", 0, CalSiteIcon, CalCustomCss) h.PushCacheGroupHeadScript("siteIconAndCustomCss", 0, CalSiteIcon, CalCustomCss)
h.PushRender(constraints.AllStats, NewHandleFn(CalComponents, 10, "wp.CalComponents")) h.PushRender(constraints.AllStats, NewHandleFn(CalComponents, 10, "wp.CalComponents"))
h.PushRender(constraints.AllStats, NewHandleFn(RenderTemplate, 0, "wp.RenderTemplate")) h.PushRender(constraints.AllStats, NewHandleFn(RenderTemplate, 0, "wp.RenderTemplate"))