add BuildWidget2 to avoid allocing as many strings in templates for docks

dynamic load /topics/ page where possible
reduce boilerplate
This commit is contained in:
Azareal 2020-04-12 15:00:15 +10:00
parent d1506d8567
commit 5fe0c8c95b
6 changed files with 145 additions and 50 deletions

View File

@ -162,11 +162,11 @@ func CompileTemplates() error {
log.Print("Compiling the templates")
// TODO: Implement per-theme template overrides here too
overriden := make(map[string]map[string]bool)
for _, theme := range Themes {
overriden[theme.Name] = make(map[string]bool)
log.Printf("theme.OverridenTemplates: %+v\n", theme.OverridenTemplates)
for _, override := range theme.OverridenTemplates {
overriden[theme.Name][override] = true
for _, th := range Themes {
overriden[th.Name] = make(map[string]bool)
log.Printf("th.OverridenTemplates: %+v\n", th.OverridenTemplates)
for _, override := range th.OverridenTemplates {
overriden[th.Name][override] = true
}
}
log.Printf("overriden: %+v\n", overriden)
@ -175,6 +175,7 @@ func CompileTemplates() error {
Minify: Config.MinifyTemplates,
Debug: Dev.DebugMode,
SuperDebug: Dev.TemplateDebug,
DockToID: DockToID,
}
c := tmpl.NewCTemplateSet("normal")
c.SetConfig(config)
@ -195,13 +196,13 @@ func CompileTemplates() error {
log.Printf("oroots: %+v\n", oroots)
log.Print("Compiling the per-theme templates")
for theme, tmpls := range oroots {
c.ResetLogs("normal-" + theme)
c.SetThemeName(theme)
for th, tmpls := range oroots {
c.ResetLogs("normal-" + th)
c.SetThemeName(th)
c.SetPerThemeTmpls(tmpls)
log.Print("theme: ", theme)
log.Print("th: ", th)
log.Printf("perThemeTmpls: %+v\n", tmpls)
err := compileTemplates(&wg, c, theme)
err := compileTemplates(&wg, c, th)
if err != nil {
return err
}
@ -229,6 +230,7 @@ func compileCommons(c *tmpl.CTemplateSet, head, head2 *Header, forumList []Forum
topicsList = append(topicsList, &TopicsRow{1, "topic-title", "Topic Title", "The topic content.", 1, false, false, now, now, user3.ID, 1, 1, "", "127.0.0.1", 1, 0, 1, 1, 0, "classname", 0, "", user2, "", 0, user3, "General", "/forum/general.2", nil})
topicListPage := TopicListPage{htitle("Topic List"), topicsList, forumList, Config.DefaultForum, TopicListSort{"lastupdated", false}, Paginator{[]int{1}, 1, 1}}
o.Add("topics", "c.TopicListPage", topicListPage)
o.Add("topics_mini", "c.TopicListPage", topicListPage)
forumItem := BlankForum(1, "general-forum.1", "General Forum", "Where the general stuff happens", true, "all", 0, "", 0)
forumPage := ForumPage{htitle("General Forum"), topicsList, forumItem, Paginator{[]int{1}, 1, 1}}
@ -472,6 +474,7 @@ func CompileJSTemplates() error {
SkipTmplPtrMap: true,
SkipInitBlock: false,
PackageName: "tmpl",
DockToID: DockToID,
}
c := tmpl.NewCTemplateSet("js")
c.SetConfig(config)

View File

@ -42,6 +42,7 @@ type CTemplateConfig struct {
SkipTmplPtrMap bool
SkipInitBlock bool
PackageName string
DockToID map[string]int
}
// nolint
@ -541,7 +542,8 @@ if !ok {
for fid := 0; len(outBuf) > fid; fid++ {
fr := outBuf[fid]
c.detail(fr.Type + " frame")
if fr.Type == "text" {
switch {
case fr.Type == "text":
c.detail(fr)
oid := fid
c.detail("oid:", oid)
@ -568,14 +570,13 @@ if !ok {
c.detail("post fid:", fid)
}
writeTextFrame(fr.TemplateName, fr.Extra.(int)-skip)
} else if fr.Type == "varsub" || fr.Type == "cvarsub" {
case fr.Type == "varsub" || fr.Type == "cvarsub":
fout += "w.Write(" + fr.Body + ")\n"
} else if fr.Type == "identifier" {
fout += fr.Body
} else if fr.Type == "lang" {
case fr.Type == "lang":
//fout += "w.Write(plist[" + strconv.Itoa(fr.Extra.(int)) + "])\n"
fout += "w.Write(" + fname + "_phrase_arr[" + strconv.Itoa(fr.Extra.(int)) + "])\n"
} else {
//case fr.Type == "identifier":
default:
fout += fr.Body
}
}
@ -1031,14 +1032,14 @@ func (c *CTemplateSet) dumpSymbol(pos int, node *parse.CommandNode, symbol strin
c.detail("node.Args[pos+2]", node.Args[pos+2])
}
func (c *CTemplateSet) compareFunc(con CContext, pos int, node *parse.CommandNode, compare string) (out string) {
c.dumpSymbol(pos, node, compare)
return c.compileIfVarSubN(con, node.Args[pos+1].String()) + " " + compare + " " + c.compileIfVarSubN(con, node.Args[pos+2].String())
func (c *CTemplateSet) compareFunc(con CContext, pos int, n *parse.CommandNode, compare string) (out string) {
c.dumpSymbol(pos, n, compare)
return c.compileIfVarSubN(con, n.Args[pos+1].String()) + " " + compare + " " + c.compileIfVarSubN(con, n.Args[pos+2].String())
}
func (c *CTemplateSet) simpleMath(con CContext, pos int, node *parse.CommandNode, symbol string) (out string, val reflect.Value) {
leftParam, val2 := c.compileIfVarSub(con, node.Args[pos+1].String())
rightParam, val3 := c.compileIfVarSub(con, node.Args[pos+2].String())
func (c *CTemplateSet) simpleMath(con CContext, pos int, n *parse.CommandNode, symbol string) (out string, val reflect.Value) {
leftParam, val2 := c.compileIfVarSub(con, n.Args[pos+1].String())
rightParam, val3 := c.compileIfVarSub(con, n.Args[pos+2].String())
if val2.IsValid() {
val = val2
} else if val3.IsValid() {
@ -1048,7 +1049,7 @@ func (c *CTemplateSet) simpleMath(con CContext, pos int, node *parse.CommandNode
numSample := 1
val = reflect.ValueOf(numSample)
}
c.dumpSymbol(pos, node, symbol)
c.dumpSymbol(pos, n, symbol)
return leftParam + " " + symbol + " " + rightParam, val
}
@ -1097,7 +1098,7 @@ ArgLoop:
for pos := 0; pos < len(node.Args); pos++ {
id := node.Args[pos]
c.detail("pos:", pos)
c.detail("ID:", id)
c.detail("id:", id)
switch id.String() {
case "not":
out += "!"
@ -1144,6 +1145,14 @@ ArgLoop:
val = val3
// TODO: Refactor this
if leftParam[0] == '"' {
leftParam = strings.TrimSuffix(strings.TrimPrefix(leftParam, "\""), "\"")
id, ok := c.config.DockToID[leftParam]
if ok {
litString("c.BuildWidget2("+strconv.Itoa(id)+","+rightParam+")", false)
break ArgLoop
}
}
litString("c.BuildWidget("+leftParam+","+rightParam+")", false)
break ArgLoop
case "hasWidgets":
@ -1893,7 +1902,7 @@ func (c *CTemplateSet) compileSubTemplate(pcon CContext, node *parse.TemplateNod
c.detailf("c.overridenRoots: %+v\n", c.overridenRoots)
}
func (c *CTemplateSet) loadTemplate(fileDir string, name string) (content string, err error) {
func (c *CTemplateSet) loadTemplate(fileDir, name string) (content string, err error) {
c.dumpCall("loadTemplate", fileDir, name)
c.detail("c.themeName:", c.themeName)
if c.themeName != "" {

View File

@ -43,6 +43,7 @@ type Theme struct {
Tag string
URL string
Docks []string // Allowed Values: leftSidebar, rightSidebar, footer
DocksID []int // Integer versions of Docks to try to get a speed boost in BuildWidget()
Settings map[string]ThemeSetting
IntTmplHandle *htmpl.Template
// TODO: Do we really need both OverridenTemplates AND OverridenMap?
@ -58,6 +59,7 @@ type Theme struct {
// TODO: Implement this
MapTmplToDock map[string]ThemeMapTmplToDock // map[dockName]data
RunOnDock func(string) string //(dock string) (sbody string)
RunOnDockID func(int) string //(dock int) (sbody string)
// This variable should only be set and unset by the system, not the theme meta file
// TODO: Should we phase out Active and make the default theme store the primary source of truth?
@ -381,6 +383,23 @@ func (t Theme) BuildDock(dock string) (sbody string) {
return ""
}
func (t Theme) HasDockByID(id int) bool {
for _, dock := range t.DocksID {
if dock == id {
return true
}
}
return false
}
func (t Theme) BuildDockByID(id int) (sbody string) {
runOnDock := t.RunOnDockID
if runOnDock != nil {
return runOnDock(id)
}
return ""
}
type GzipResponseWriter struct {
io.Writer
http.ResponseWriter

View File

@ -76,7 +76,7 @@ func NewThemeList() (themes ThemeList, err error) {
return themes, err
}
theme := &Theme{Name: ""}
theme := &Theme{}
err = json.Unmarshal(themeFile, theme)
if err != nil {
return themes, err
@ -97,7 +97,7 @@ func NewThemeList() (themes ThemeList, err error) {
if err != nil {
return themes, err
}
theme = &Theme{Name: "", Path: theme.Path}
theme = &Theme{Path: theme.Path}
err = json.Unmarshal(themeFile, theme)
if err != nil {
return themes, err
@ -179,21 +179,30 @@ func NewThemeList() (themes ThemeList, err error) {
for i, res := range theme.Resources {
ext := filepath.Ext(res.Name)
if ext == ".css" {
switch ext {
case ".css":
res.Type = ResTypeSheet
} else if ext == ".js" {
case ".js":
res.Type = ResTypeScript
}
if res.Location == "global" {
switch res.Location {
case "global":
res.LocID = LocGlobal
} else if res.Location == "frontend" {
case "frontend":
res.LocID = LocFront
} else if res.Location == "panel" {
case "panel":
res.LocID = LocPanel
}
theme.Resources[i] = res
}
for _, dock := range theme.Docks {
id, ok := DockToID[dock]
if ok {
theme.DocksID = append(theme.DocksID, id)
}
}
// TODO: Bind the built template, or an interpreted one for any dock overrides this theme has
themes[theme.Name] = theme

View File

@ -221,6 +221,61 @@ func BuildWidget(dock string, h *Header) (sbody string) {
return sbody
}
var DockToID = map[string]int{
"leftOfNav": 0,
"rightOfNav": 1,
"topMenu": 2,
"rightSidebar": 3,
"footer": 4,
}
func BuildWidget2(dock int, h *Header) (sbody string) {
if !h.Theme.HasDockByID(dock) {
return ""
}
// Let themes forcibly override this slot
sbody = h.Theme.BuildDockByID(dock)
if sbody != "" {
return sbody
}
var widgets []*Widget
switch dock {
case 0:
widgets = Docks.LeftOfNav
case 1:
widgets = Docks.RightOfNav
case 2:
// 1 = id for the default menu
mhold, err := Menus.Get(1)
if err == nil {
err := mhold.Build(h.Writer, h.CurrentUser, h.Path)
if err != nil {
LogError(err)
}
}
return ""
case 3:
widgets = Docks.RightSidebar.Items
case 4:
widgets = Docks.Footer.Items
}
for _, widget := range widgets {
if !widget.Enabled {
continue
}
if widget.Allowed(h.Zone, h.ZoneID) {
item, err := widget.Build(h)
if err != nil {
LogError(err)
}
sbody += item
}
}
return sbody
}
func getDockWidgets(dock string) (widgets []*Widget, err error) {
rows, err := widgetStmts.getDockList.Query(dock)
if err != nil {