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") log.Print("Compiling the templates")
// TODO: Implement per-theme template overrides here too // TODO: Implement per-theme template overrides here too
overriden := make(map[string]map[string]bool) overriden := make(map[string]map[string]bool)
for _, theme := range Themes { for _, th := range Themes {
overriden[theme.Name] = make(map[string]bool) overriden[th.Name] = make(map[string]bool)
log.Printf("theme.OverridenTemplates: %+v\n", theme.OverridenTemplates) log.Printf("th.OverridenTemplates: %+v\n", th.OverridenTemplates)
for _, override := range theme.OverridenTemplates { for _, override := range th.OverridenTemplates {
overriden[theme.Name][override] = true overriden[th.Name][override] = true
} }
} }
log.Printf("overriden: %+v\n", overriden) log.Printf("overriden: %+v\n", overriden)
@ -175,6 +175,7 @@ func CompileTemplates() error {
Minify: Config.MinifyTemplates, Minify: Config.MinifyTemplates,
Debug: Dev.DebugMode, Debug: Dev.DebugMode,
SuperDebug: Dev.TemplateDebug, SuperDebug: Dev.TemplateDebug,
DockToID: DockToID,
} }
c := tmpl.NewCTemplateSet("normal") c := tmpl.NewCTemplateSet("normal")
c.SetConfig(config) c.SetConfig(config)
@ -195,13 +196,13 @@ func CompileTemplates() error {
log.Printf("oroots: %+v\n", oroots) log.Printf("oroots: %+v\n", oroots)
log.Print("Compiling the per-theme templates") log.Print("Compiling the per-theme templates")
for theme, tmpls := range oroots { for th, tmpls := range oroots {
c.ResetLogs("normal-" + theme) c.ResetLogs("normal-" + th)
c.SetThemeName(theme) c.SetThemeName(th)
c.SetPerThemeTmpls(tmpls) c.SetPerThemeTmpls(tmpls)
log.Print("theme: ", theme) log.Print("th: ", th)
log.Printf("perThemeTmpls: %+v\n", tmpls) log.Printf("perThemeTmpls: %+v\n", tmpls)
err := compileTemplates(&wg, c, theme) err := compileTemplates(&wg, c, th)
if err != nil { if err != nil {
return err 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}) 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}} 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", "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) 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}} forumPage := ForumPage{htitle("General Forum"), topicsList, forumItem, Paginator{[]int{1}, 1, 1}}
@ -472,6 +474,7 @@ func CompileJSTemplates() error {
SkipTmplPtrMap: true, SkipTmplPtrMap: true,
SkipInitBlock: false, SkipInitBlock: false,
PackageName: "tmpl", PackageName: "tmpl",
DockToID: DockToID,
} }
c := tmpl.NewCTemplateSet("js") c := tmpl.NewCTemplateSet("js")
c.SetConfig(config) c.SetConfig(config)

View File

@ -42,6 +42,7 @@ type CTemplateConfig struct {
SkipTmplPtrMap bool SkipTmplPtrMap bool
SkipInitBlock bool SkipInitBlock bool
PackageName string PackageName string
DockToID map[string]int
} }
// nolint // nolint
@ -249,7 +250,7 @@ func Tmpl_` + fname + `(tmpl_i interface{}, w io.Writer) error {
c.fileDir = fileDir c.fileDir = fileDir
content, err := c.loadTemplate(c.fileDir, name) content, err := c.loadTemplate(c.fileDir, name)
if err != nil { if err != nil {
c.detail("bailing out: ", err) c.detail("bailing out:", err)
return "", "", "", err return "", "", "", err
} }
@ -274,7 +275,7 @@ func (c *CTemplateSet) Compile(name, fileDir, expects string, expectsInt interfa
c.fileDir = fileDir c.fileDir = fileDir
content, err := c.loadTemplate(c.fileDir, name) content, err := c.loadTemplate(c.fileDir, name)
if err != nil { if err != nil {
c.detail("bailing out: ", err) c.detail("bailing out:", err)
return "", err return "", err
} }
@ -455,7 +456,7 @@ func (c *CTemplateSet) compile(name, content, expects string, expectsInt interfa
if len(c.langIndexToName) > 0 { if len(c.langIndexToName) > 0 {
for i, name := range c.langIndexToName { for i, name := range c.langIndexToName {
//l += `"` + name + `"` + ",\n" //l += `"` + name + `"` + ",\n"
if i == 0{ if i == 0 {
l += `"` + name + `"` l += `"` + name + `"`
} else { } else {
l += `,"` + name + `"` l += `,"` + name + `"`
@ -541,7 +542,8 @@ if !ok {
for fid := 0; len(outBuf) > fid; fid++ { for fid := 0; len(outBuf) > fid; fid++ {
fr := outBuf[fid] fr := outBuf[fid]
c.detail(fr.Type + " frame") c.detail(fr.Type + " frame")
if fr.Type == "text" { switch {
case fr.Type == "text":
c.detail(fr) c.detail(fr)
oid := fid oid := fid
c.detail("oid:", oid) c.detail("oid:", oid)
@ -568,14 +570,13 @@ if !ok {
c.detail("post fid:", fid) c.detail("post fid:", fid)
} }
writeTextFrame(fr.TemplateName, fr.Extra.(int)-skip) 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" fout += "w.Write(" + fr.Body + ")\n"
} else if fr.Type == "identifier" { case fr.Type == "lang":
fout += fr.Body
} else if fr.Type == "lang" {
//fout += "w.Write(plist[" + strconv.Itoa(fr.Extra.(int)) + "])\n" //fout += "w.Write(plist[" + strconv.Itoa(fr.Extra.(int)) + "])\n"
fout += "w.Write(" + fname + "_phrase_arr[" + 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 fout += fr.Body
} }
} }
@ -587,7 +588,7 @@ if !ok {
} }
for _, frag := range c.fragBuf { for _, frag := range c.fragBuf {
c.detail("frag: ", frag) c.detail("frag:", frag)
if frag.Seen { if frag.Seen {
c.detail("invisible") c.detail("invisible")
continue continue
@ -745,7 +746,7 @@ func (c *CTemplateSet) addText(con CContext, text []byte) {
return return
} }
nodeText := string(text) nodeText := string(text)
c.detail("con.TemplateName: ", con.TemplateName) c.detail("con.TemplateName:", con.TemplateName)
fragIndex := c.fragmentCursor[con.TemplateName] fragIndex := c.fragmentCursor[con.TemplateName]
_, ok := c.fragOnce[con.TemplateName] _, ok := c.fragOnce[con.TemplateName]
c.fragBuf = append(c.fragBuf, Fragment{nodeText, con.TemplateName, fragIndex, ok}) c.fragBuf = append(c.fragBuf, Fragment{nodeText, con.TemplateName, fragIndex, ok})
@ -756,7 +757,7 @@ func (c *CTemplateSet) addText(con CContext, text []byte) {
func (c *CTemplateSet) compileRangeNode(con CContext, node *parse.RangeNode) { func (c *CTemplateSet) compileRangeNode(con CContext, node *parse.RangeNode) {
c.dumpCall("compileRangeNode", con, node) c.dumpCall("compileRangeNode", con, node)
defer c.retCall("compileRangeNode") defer c.retCall("compileRangeNode")
c.detail("node.Pipe: ", node.Pipe) c.detail("node.Pipe:", node.Pipe)
var expr string var expr string
var outVal reflect.Value var outVal reflect.Value
for _, cmd := range node.Pipe.Cmds { for _, cmd := range node.Pipe.Cmds {
@ -882,7 +883,7 @@ func (c *CTemplateSet) compileSubSwitch(con CContext, node *parse.CommandNode) {
cur = c.skipStructPointers(cur, id) cur = c.skipStructPointers(cur, id)
c.checkIfValid(cur, con.VarHolder, con.HoldReflect, varBit, multiline) c.checkIfValid(cur, con.VarHolder, con.HoldReflect, varBit, multiline)
c.detail("in-loop varBit: " + varBit) c.detail("in-loop varBit:" + varBit)
if cur.Kind() == reflect.Map { if cur.Kind() == reflect.Map {
cur = cur.MapIndex(reflect.ValueOf(id)) cur = cur.MapIndex(reflect.ValueOf(id))
varBit += "[\"" + id + "\"]" varBit += "[\"" + id + "\"]"
@ -927,7 +928,7 @@ func (c *CTemplateSet) compileSubSwitch(con CContext, node *parse.CommandNode) {
} }
varBit += cur.Type().Name() + ")" varBit += cur.Type().Name() + ")"
} }
c.detail("End Cycle: ", varBit) c.detail("End Cycle:", varBit)
} }
if multiline { if multiline {
@ -1026,19 +1027,19 @@ func (c *CTemplateSet) compileIdentSwitchN(con CContext, n *parse.CommandNode) (
} }
func (c *CTemplateSet) dumpSymbol(pos int, node *parse.CommandNode, symbol string) { func (c *CTemplateSet) dumpSymbol(pos int, node *parse.CommandNode, symbol string) {
c.detail("symbol: ", symbol) c.detail("symbol:", symbol)
c.detail("node.Args[pos+1]", node.Args[pos+1]) c.detail("node.Args[pos+1]", node.Args[pos+1])
c.detail("node.Args[pos+2]", node.Args[pos+2]) 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) { func (c *CTemplateSet) compareFunc(con CContext, pos int, n *parse.CommandNode, compare string) (out string) {
c.dumpSymbol(pos, node, compare) c.dumpSymbol(pos, n, compare)
return c.compileIfVarSubN(con, node.Args[pos+1].String()) + " " + compare + " " + c.compileIfVarSubN(con, node.Args[pos+2].String()) 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) { func (c *CTemplateSet) simpleMath(con CContext, pos int, n *parse.CommandNode, symbol string) (out string, val reflect.Value) {
leftParam, val2 := c.compileIfVarSub(con, node.Args[pos+1].String()) leftParam, val2 := c.compileIfVarSub(con, n.Args[pos+1].String())
rightParam, val3 := c.compileIfVarSub(con, node.Args[pos+2].String()) rightParam, val3 := c.compileIfVarSub(con, n.Args[pos+2].String())
if val2.IsValid() { if val2.IsValid() {
val = val2 val = val2
} else if val3.IsValid() { } else if val3.IsValid() {
@ -1048,7 +1049,7 @@ func (c *CTemplateSet) simpleMath(con CContext, pos int, node *parse.CommandNode
numSample := 1 numSample := 1
val = reflect.ValueOf(numSample) val = reflect.ValueOf(numSample)
} }
c.dumpSymbol(pos, node, symbol) c.dumpSymbol(pos, n, symbol)
return leftParam + " " + symbol + " " + rightParam, val return leftParam + " " + symbol + " " + rightParam, val
} }
@ -1097,7 +1098,7 @@ ArgLoop:
for pos := 0; pos < len(node.Args); pos++ { for pos := 0; pos < len(node.Args); pos++ {
id := node.Args[pos] id := node.Args[pos]
c.detail("pos:", pos) c.detail("pos:", pos)
c.detail("ID:", id) c.detail("id:", id)
switch id.String() { switch id.String() {
case "not": case "not":
out += "!" out += "!"
@ -1144,6 +1145,14 @@ ArgLoop:
val = val3 val = val3
// TODO: Refactor this // 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) litString("c.BuildWidget("+leftParam+","+rightParam+")", false)
break ArgLoop break ArgLoop
case "hasWidgets": case "hasWidgets":
@ -1621,8 +1630,8 @@ func (c *CTemplateSet) compileVarSub(con CContext, varname string, val reflect.V
} }
} }
c.detail("varname: ", varname) c.detail("varname:", varname)
c.detail("assLines: ", assLines) c.detail("assLines:", assLines)
var base string var base string
switch val.Kind() { switch val.Kind() {
case reflect.Int: case reflect.Int:
@ -1716,7 +1725,7 @@ func (c *CTemplateSet) compileVarSub(con CContext, varname string, val reflect.V
c.logger.Println("Unknown Type:", val.Type().Name()) c.logger.Println("Unknown Type:", val.Type().Name())
panic("-- I don't know what this variable's type is o.o\n") panic("-- I don't know what this variable's type is o.o\n")
} }
c.detail("base: ", base) c.detail("base:", base)
if assLines == "" { if assLines == "" {
con.Push("varsub", base) con.Push("varsub", base)
} else { } else {
@ -1893,12 +1902,12 @@ func (c *CTemplateSet) compileSubTemplate(pcon CContext, node *parse.TemplateNod
c.detailf("c.overridenRoots: %+v\n", c.overridenRoots) 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.dumpCall("loadTemplate", fileDir, name)
c.detail("c.themeName: ", c.themeName) c.detail("c.themeName:", c.themeName)
if c.themeName != "" { if c.themeName != "" {
t := "./themes/" + c.themeName + "/overrides/" + name t := "./themes/" + c.themeName + "/overrides/" + name
c.detail("per-theme override: ", true) c.detail("per-theme override:", true)
res, err := ioutil.ReadFile(t) res, err := ioutil.ReadFile(t)
if err == nil { if err == nil {
content = string(res) content = string(res)
@ -1907,13 +1916,13 @@ func (c *CTemplateSet) loadTemplate(fileDir string, name string) (content string
} }
return content, nil return content, nil
} }
c.detail("override err: ", err) c.detail("override err:", err)
} }
res, err := ioutil.ReadFile(c.fileDir + "overrides/" + name) res, err := ioutil.ReadFile(c.fileDir + "overrides/" + name)
if err != nil { if err != nil {
c.detail("override path: ", c.fileDir+"overrides/"+name) c.detail("override path:", c.fileDir+"overrides/"+name)
c.detail("override err: ", err) c.detail("override err:", err)
res, err = ioutil.ReadFile(c.fileDir + name) res, err = ioutil.ReadFile(c.fileDir + name)
if err != nil { if err != nil {
return "", err return "", err

View File

@ -43,6 +43,7 @@ type Theme struct {
Tag string Tag string
URL string URL string
Docks []string // Allowed Values: leftSidebar, rightSidebar, footer 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 Settings map[string]ThemeSetting
IntTmplHandle *htmpl.Template IntTmplHandle *htmpl.Template
// TODO: Do we really need both OverridenTemplates AND OverridenMap? // TODO: Do we really need both OverridenTemplates AND OverridenMap?
@ -58,6 +59,7 @@ type Theme struct {
// TODO: Implement this // TODO: Implement this
MapTmplToDock map[string]ThemeMapTmplToDock // map[dockName]data MapTmplToDock map[string]ThemeMapTmplToDock // map[dockName]data
RunOnDock func(string) string //(dock string) (sbody string) 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 // 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? // 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 "" 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 { type GzipResponseWriter struct {
io.Writer io.Writer
http.ResponseWriter http.ResponseWriter

View File

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

View File

@ -221,6 +221,61 @@ func BuildWidget(dock string, h *Header) (sbody string) {
return sbody 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) { func getDockWidgets(dock string) (widgets []*Widget, err error) {
rows, err := widgetStmts.getDockList.Query(dock) rows, err := widgetStmts.getDockList.Query(dock)
if err != nil { if err != nil {

View File

@ -35,4 +35,4 @@
</form> </form>
</div> </div>
</main> </main>
{{template "footer.html" . }} {{template "footer.html" . }}