Split the transpiled topic alt route into a guest part and a member part for extra speed.
Fixed a bug in the template fragment coalescer. Added the loadTemplate function to help reduce the amount of duplicated code in the template generator. Added a couple of helper methods to CContext to reduce the amount of possibly error prone boilerplate.
This commit is contained in:
parent
826330035f
commit
50fef78078
|
@ -43,6 +43,8 @@ func interpretedTopicTemplate(pi TopicPage, w io.Writer) error {
|
|||
// nolint
|
||||
var Template_topic_handle = interpretedTopicTemplate
|
||||
var Template_topic_alt_handle = interpretedTopicTemplate
|
||||
var Template_topic_alt_guest_handle = interpretedTopicTemplate
|
||||
var Template_topic_alt_member_handle = interpretedTopicTemplate
|
||||
|
||||
// nolint
|
||||
var Template_topics_handle = func(pi TopicListPage, w io.Writer) error {
|
||||
|
@ -172,6 +174,12 @@ func tmplInitHeaders(user User, user2 User, user3 User) (*Header, *Header, *Head
|
|||
return header, buildHeader(user2), buildHeader(user3)
|
||||
}
|
||||
|
||||
type TmplLoggedin struct {
|
||||
Stub string
|
||||
Guest string
|
||||
Member string
|
||||
}
|
||||
|
||||
// ? - Add template hooks?
|
||||
func CompileTemplates() error {
|
||||
var config tmpl.CTemplateConfig
|
||||
|
@ -210,15 +218,24 @@ func CompileTemplates() error {
|
|||
var compile = func(name string, expects string, expectsInt interface{}) (tmpl string, err error) {
|
||||
return c.Compile(name+".html", "templates/", expects, expectsInt, varList)
|
||||
}
|
||||
var compileByLoggedin = func(name string, expects string, expectsInt interface{}) (tmpl TmplLoggedin, err error) {
|
||||
stub, guest, member, err := c.CompileByLoggedin(name+".html", "templates/", expects, expectsInt, varList)
|
||||
return TmplLoggedin{stub, guest, member}, err
|
||||
}
|
||||
|
||||
header.Title = "Topic Name"
|
||||
tpage := TopicPage{header, replyList, topic, &Forum{ID: 1, Name: "Hahaha"}, poll, 1, 1}
|
||||
tpage.Forum.Link = BuildForumURL(NameToSlug(tpage.Forum.Name), tpage.Forum.ID)
|
||||
topicIDTmpl, err := compile("topic", "common.TopicPage", tpage)
|
||||
topicTmpl, err := compile("topic", "common.TopicPage", tpage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
topicIDAltTmpl, err := compile("topic_alt", "common.TopicPage", tpage)
|
||||
/*topicAltTmpl, err := compile("topic_alt", "common.TopicPage", tpage)
|
||||
if err != nil {
|
||||
return err
|
||||
}*/
|
||||
|
||||
topicAltTmpl, err := compileByLoggedin("topic_alt", "common.TopicPage", tpage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -309,17 +326,28 @@ func CompileTemplates() error {
|
|||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
var writeTemplate = func(name string, content string) {
|
||||
var writeTemplate = func(name string, content interface{}) {
|
||||
log.Print("Writing template '" + name + "'")
|
||||
if content == "" {
|
||||
log.Fatal("No content body")
|
||||
|
||||
var writeTmpl = func(name string, content string) {
|
||||
if content == "" {
|
||||
log.Fatal("No content body for " + name)
|
||||
}
|
||||
err := writeFile("./template_"+name+".go", content)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
err := writeFile("./template_"+name+".go", content)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
switch content := content.(type) {
|
||||
case string:
|
||||
writeTmpl(name, content)
|
||||
case TmplLoggedin:
|
||||
writeTmpl(name, content.Stub)
|
||||
writeTmpl(name+"_guest", content.Guest)
|
||||
writeTmpl(name+"_member", content.Member)
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
|
@ -341,8 +369,8 @@ func CompileTemplates() error {
|
|||
}
|
||||
|
||||
log.Print("Writing the templates")
|
||||
writeTemplate("topic", topicIDTmpl)
|
||||
writeTemplate("topic_alt", topicIDAltTmpl)
|
||||
writeTemplate("topic", topicTmpl)
|
||||
writeTemplate("topic_alt", topicAltTmpl)
|
||||
writeTemplate("profile", profileTmpl)
|
||||
writeTemplate("forums", forumsTmpl)
|
||||
writeTemplate("topics", topicListTmpl)
|
||||
|
@ -415,11 +443,11 @@ func CompileJSTemplates() error {
|
|||
header.Title = "Topic Name"
|
||||
tpage := TopicPage{header, replyList, topic, &Forum{ID: 1, Name: "Hahaha"}, poll, 1, 1}
|
||||
tpage.Forum.Link = BuildForumURL(NameToSlug(tpage.Forum.Name), tpage.Forum.ID)
|
||||
topicIDTmpl, err := c.Compile("topic_posts.html", "templates/", "common.TopicPage", tpage, varList)
|
||||
topicPostsTmpl, err := c.Compile("topic_posts.html", "templates/", "common.TopicPage", tpage, varList)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
topicIDAltTmpl, err := c.Compile("topic_alt_posts.html", "templates/", "common.TopicPage", tpage, varList)
|
||||
topicAltPostsTmpl, err := c.Compile("topic_alt_posts.html", "templates/", "common.TopicPage", tpage, varList)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -443,8 +471,8 @@ func CompileJSTemplates() error {
|
|||
}
|
||||
writeTemplate("alert", alertTmpl)
|
||||
writeTemplate("topics_topic", topicListItemTmpl)
|
||||
writeTemplate("topic_posts", topicIDTmpl)
|
||||
writeTemplate("topic_alt_posts", topicIDAltTmpl)
|
||||
writeTemplate("topic_posts", topicPostsTmpl)
|
||||
writeTemplate("topic_alt_posts", topicAltPostsTmpl)
|
||||
writeTemplateList(c, &wg, dirPrefix)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ type OutBufferFrame struct {
|
|||
}
|
||||
|
||||
type CContext struct {
|
||||
RootHolder string
|
||||
VarHolder string
|
||||
HoldReflect reflect.Value
|
||||
TemplateName string
|
||||
|
@ -34,17 +35,17 @@ type CContext struct {
|
|||
|
||||
func (con *CContext) Push(nType string, body string) (index int) {
|
||||
*con.OutBuf = append(*con.OutBuf, OutBufferFrame{body, nType, con.TemplateName, nil, nil})
|
||||
return len(*con.OutBuf) - 1
|
||||
return con.LastBufIndex()
|
||||
}
|
||||
|
||||
func (con *CContext) PushText(body string, fragIndex int, fragOutIndex int) (index int) {
|
||||
*con.OutBuf = append(*con.OutBuf, OutBufferFrame{body, "text", con.TemplateName, fragIndex, fragOutIndex})
|
||||
return len(*con.OutBuf) - 1
|
||||
return con.LastBufIndex()
|
||||
}
|
||||
|
||||
func (con *CContext) PushPhrase(body string, langIndex int) (index int) {
|
||||
*con.OutBuf = append(*con.OutBuf, OutBufferFrame{body, "lang", con.TemplateName, langIndex, nil})
|
||||
return len(*con.OutBuf) - 1
|
||||
return con.LastBufIndex()
|
||||
}
|
||||
|
||||
func (con *CContext) StartLoop(body string) (index int) {
|
||||
|
@ -57,8 +58,7 @@ func (con *CContext) EndLoop(body string) (index int) {
|
|||
}
|
||||
|
||||
func (con *CContext) StartTemplate(body string) (index int) {
|
||||
*con.OutBuf = append(*con.OutBuf, OutBufferFrame{body, "starttemplate", con.TemplateName, nil, nil})
|
||||
return len(*con.OutBuf) - 1
|
||||
return con.addFrame(body, "starttemplate", nil, nil)
|
||||
}
|
||||
|
||||
func (con *CContext) EndTemplate(body string) (index int) {
|
||||
|
@ -74,3 +74,25 @@ func (con *CContext) AttachVars(vars string, index int) {
|
|||
node.Body += vars
|
||||
outBuf[index] = node
|
||||
}
|
||||
|
||||
func (con *CContext) addFrame(body string, ftype string, extra1 interface{}, extra2 interface{}) (index int) {
|
||||
*con.OutBuf = append(*con.OutBuf, OutBufferFrame{body, ftype, con.TemplateName, extra1, extra2})
|
||||
return con.LastBufIndex()
|
||||
}
|
||||
|
||||
func (con *CContext) LastBufIndex() int {
|
||||
return len(*con.OutBuf) - 1
|
||||
}
|
||||
|
||||
func (con *CContext) DiscardAndAfter(index int) {
|
||||
outBuf := *con.OutBuf
|
||||
if len(outBuf) <= index {
|
||||
return
|
||||
}
|
||||
if index == 0 {
|
||||
outBuf = nil
|
||||
} else {
|
||||
outBuf = outBuf[:index]
|
||||
}
|
||||
*con.OutBuf = outBuf
|
||||
}
|
||||
|
|
|
@ -56,15 +56,13 @@ type CTemplateSet struct {
|
|||
hasDispInt bool
|
||||
localDispStructIndex int
|
||||
langIndexToName []string
|
||||
guestOnly bool
|
||||
memberOnly bool
|
||||
stats map[string]int
|
||||
previousNode parse.NodeType
|
||||
currentNode parse.NodeType
|
||||
nextNode parse.NodeType
|
||||
//tempVars map[string]string
|
||||
config CTemplateConfig
|
||||
baseImportMap map[string]string
|
||||
buildTags string
|
||||
expectsInt interface{}
|
||||
}
|
||||
|
||||
func NewCTemplateSet() *CTemplateSet {
|
||||
|
@ -126,10 +124,86 @@ type Skipper struct {
|
|||
Index int
|
||||
}
|
||||
|
||||
func (c *CTemplateSet) CompileByLoggedin(name string, fileDir string, expects string, expectsInt interface{}, varList map[string]VarItem, imports ...string) (stub string, gout string, mout string, err error) {
|
||||
c.importMap = map[string]string{}
|
||||
for index, item := range c.baseImportMap {
|
||||
c.importMap[index] = item
|
||||
}
|
||||
if len(imports) > 0 {
|
||||
for _, importItem := range imports {
|
||||
c.importMap[importItem] = importItem
|
||||
}
|
||||
}
|
||||
var importList string
|
||||
for _, item := range c.importMap {
|
||||
importList += "import \"" + item + "\"\n"
|
||||
}
|
||||
|
||||
fname := strings.TrimSuffix(name, filepath.Ext(name))
|
||||
c.importMap["github.com/Azareal/Gosora/common"] = "github.com/Azareal/Gosora/common"
|
||||
|
||||
stub = `package ` + c.config.PackageName + `
|
||||
` + importList + `
|
||||
`
|
||||
|
||||
if !c.config.SkipInitBlock {
|
||||
stub += "// nolint\nfunc init() {\n"
|
||||
|
||||
if !c.config.SkipHandles {
|
||||
stub += "\tcommon.Template_" + fname + "_handle = Template_" + fname + "\n"
|
||||
stub += "\tcommon.Ctemplates = append(common.Ctemplates,\"" + fname + "\")\n\tcommon.TmplPtrMap[\"" + fname + "\"] = &common.Template_" + fname + "_handle\n"
|
||||
}
|
||||
|
||||
if !c.config.SkipTmplPtrMap {
|
||||
stub += "\tcommon.TmplPtrMap[\"o_" + fname + "\"] = Template_" + fname + "\n"
|
||||
}
|
||||
|
||||
stub += "}\n\n"
|
||||
}
|
||||
|
||||
stub += `
|
||||
// nolint
|
||||
func Template_` + fname + `(tmpl_` + fname + `_vars ` + expects + `, w io.Writer) error {
|
||||
if tmpl_` + fname + `_vars.CurrentUser.Loggedin {
|
||||
return Template_` + fname + `_member(tmpl_` + fname + `_vars, w)
|
||||
}
|
||||
return Template_` + fname + `_guest(tmpl_` + fname + `_vars, w)
|
||||
}`
|
||||
|
||||
c.fileDir = fileDir
|
||||
content, err := c.loadTemplate(c.fileDir, name)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
|
||||
c.guestOnly = true
|
||||
gout, err = c.compile(name, content, expects, expectsInt, varList, imports...)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
c.guestOnly = false
|
||||
|
||||
c.memberOnly = true
|
||||
mout, err = c.compile(name, content, expects, expectsInt, varList, imports...)
|
||||
c.memberOnly = false
|
||||
|
||||
return stub, gout, mout, err
|
||||
}
|
||||
|
||||
func (c *CTemplateSet) Compile(name string, fileDir string, expects string, expectsInt interface{}, varList map[string]VarItem, imports ...string) (out string, err error) {
|
||||
if c.config.Debug {
|
||||
fmt.Println("Compiling template '" + name + "'")
|
||||
}
|
||||
c.fileDir = fileDir
|
||||
content, err := c.loadTemplate(c.fileDir, name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return c.compile(name, content, expects, expectsInt, varList, imports...)
|
||||
}
|
||||
|
||||
func (c *CTemplateSet) compile(name string, content, expects string, expectsInt interface{}, varList map[string]VarItem, imports ...string) (out string, err error) {
|
||||
c.importMap = map[string]string{}
|
||||
for index, item := range c.baseImportMap {
|
||||
c.importMap[index] = item
|
||||
|
@ -140,26 +214,10 @@ func (c *CTemplateSet) Compile(name string, fileDir string, expects string, expe
|
|||
}
|
||||
}
|
||||
|
||||
c.fileDir = fileDir
|
||||
c.varList = varList
|
||||
c.hasDispInt = false
|
||||
c.localDispStructIndex = 0
|
||||
c.stats = make(map[string]int)
|
||||
c.expectsInt = expectsInt
|
||||
|
||||
res, err := ioutil.ReadFile(fileDir + "overrides/" + name)
|
||||
if err != nil {
|
||||
c.detail("override path: ", fileDir+"overrides/"+name)
|
||||
c.detail("override err: ", err)
|
||||
res, err = ioutil.ReadFile(fileDir + name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
content := string(res)
|
||||
if c.config.Minify {
|
||||
content = minify(content)
|
||||
}
|
||||
|
||||
tree := parse.New(name, c.funcMap)
|
||||
var treeSet = make(map[string]*parse.Tree)
|
||||
|
@ -170,8 +228,15 @@ func (c *CTemplateSet) Compile(name string, fileDir string, expects string, expe
|
|||
c.detail(name)
|
||||
|
||||
fname := strings.TrimSuffix(name, filepath.Ext(name))
|
||||
if c.guestOnly {
|
||||
fname += "_guest"
|
||||
} else if c.memberOnly {
|
||||
fname += "_member"
|
||||
}
|
||||
|
||||
var outBuf []OutBufferFrame
|
||||
con := CContext{VarHolder: "tmpl_" + fname + "_vars", HoldReflect: reflect.ValueOf(expectsInt), TemplateName: fname, OutBuf: &outBuf}
|
||||
var rootHold = "tmpl_" + fname + "_vars"
|
||||
con := CContext{RootHolder: rootHold, VarHolder: rootHold, HoldReflect: reflect.ValueOf(expectsInt), TemplateName: fname, OutBuf: &outBuf}
|
||||
c.templateList = map[string]*parse.Tree{fname: tree}
|
||||
c.detail(c.templateList)
|
||||
c.localVars = make(map[string]map[string]VarItemReflect)
|
||||
|
@ -264,6 +329,7 @@ func (c *CTemplateSet) Compile(name string, fileDir string, expects string, expe
|
|||
c.detail("text frame:")
|
||||
c.detail(frame)
|
||||
oid := fid
|
||||
c.detail("oid:", oid)
|
||||
skipBlock, ok := skipped[frame.TemplateName]
|
||||
if !ok {
|
||||
skipBlock = &SkipBlock{make(map[int]int), 0, 0}
|
||||
|
@ -271,7 +337,10 @@ func (c *CTemplateSet) Compile(name string, fileDir string, expects string, expe
|
|||
}
|
||||
skip := skipBlock.LastCount
|
||||
c.detailf("skipblock %+v\n", skipBlock)
|
||||
//var count int
|
||||
for len(outBuf) > fid+1 && outBuf[fid+1].Type == "text" && outBuf[fid+1].TemplateName == frame.TemplateName {
|
||||
c.detail("pre fid:", fid)
|
||||
//count++
|
||||
next := outBuf[fid+1]
|
||||
c.detail("next frame:", next)
|
||||
c.detail("frame frag:", c.fragBuf[frame.Extra2.(int)])
|
||||
|
@ -279,13 +348,17 @@ func (c *CTemplateSet) Compile(name string, fileDir string, expects string, expe
|
|||
c.fragBuf[frame.Extra2.(int)].Body += c.fragBuf[next.Extra2.(int)].Body
|
||||
c.fragBuf[next.Extra2.(int)].Seen = true
|
||||
fid++
|
||||
skipBlock.LastCount += (fid - oid)
|
||||
skipBlock.LastCount++
|
||||
skipBlock.Frags[frame.Extra.(int)] = skipBlock.LastCount
|
||||
c.detail("post fid:", fid)
|
||||
}
|
||||
writeTextFrame(frame.TemplateName, frame.Extra.(int)-skip)
|
||||
} else if frame.Type == "varsub" || frame.Type == "cvarsub" {
|
||||
c.detail(frame.Type + " frame")
|
||||
fout += "w.Write(" + frame.Body + ")\n"
|
||||
} else if frame.Type == "identifier" {
|
||||
c.detailf(frame.Type+" frame:%+v\n", frame)
|
||||
fout += frame.Body
|
||||
} else {
|
||||
c.detail(frame.Type + " frame")
|
||||
fout += frame.Body
|
||||
|
@ -334,14 +407,8 @@ w.Write([]byte(`, " + ", -1)
|
|||
func (c *CTemplateSet) rootIterate(tree *parse.Tree, con CContext) {
|
||||
c.dumpCall("rootIterate", tree, con)
|
||||
c.detail(tree.Root)
|
||||
treeLength := len(tree.Root.Nodes)
|
||||
for index, node := range tree.Root.Nodes {
|
||||
for _, node := range tree.Root.Nodes {
|
||||
c.detail("Node:", node.String())
|
||||
c.previousNode = c.currentNode
|
||||
c.currentNode = node.Type()
|
||||
if treeLength != (index + 1) {
|
||||
c.nextNode = tree.Root.Nodes[index+1].Type()
|
||||
}
|
||||
c.compileSwitch(con, node)
|
||||
}
|
||||
c.retCall("rootIterate")
|
||||
|
@ -371,9 +438,54 @@ func (c *CTemplateSet) compileSwitch(con CContext, node parse.Node) {
|
|||
}
|
||||
|
||||
c.detail("Expression:", expr)
|
||||
c.previousNode = c.currentNode
|
||||
c.currentNode = parse.NodeList
|
||||
c.nextNode = -1
|
||||
// Simple member / guest optimisation for now
|
||||
// TODO: Expand upon this
|
||||
var inSlice = func(haystack []string, expr string) bool {
|
||||
for _, needle := range haystack {
|
||||
if needle == expr {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
var userExprs = []string{
|
||||
con.RootHolder + ".CurrentUser.Loggedin",
|
||||
con.RootHolder + ".CurrentUser.IsSuperMod",
|
||||
con.RootHolder + ".CurrentUser.IsAdmin",
|
||||
}
|
||||
var negUserExprs = []string{
|
||||
"!" + con.RootHolder + ".CurrentUser.Loggedin",
|
||||
"!" + con.RootHolder + ".CurrentUser.IsSuperMod",
|
||||
"!" + con.RootHolder + ".CurrentUser.IsAdmin",
|
||||
}
|
||||
if c.guestOnly {
|
||||
c.detail("optimising away member branch")
|
||||
if inSlice(userExprs, expr) {
|
||||
c.detail("positive conditional:", expr)
|
||||
if node.ElseList != nil {
|
||||
c.compileSwitch(con, node.ElseList)
|
||||
}
|
||||
return
|
||||
} else if inSlice(negUserExprs, expr) {
|
||||
c.detail("negative conditional:", expr)
|
||||
c.compileSwitch(con, node.List)
|
||||
return
|
||||
}
|
||||
} else if c.memberOnly {
|
||||
c.detail("optimising away guest branch")
|
||||
if (con.RootHolder + ".CurrentUser.Loggedin") == expr {
|
||||
c.detail("positive conditional:", expr)
|
||||
c.compileSwitch(con, node.List)
|
||||
return
|
||||
} else if ("!" + con.RootHolder + ".CurrentUser.Loggedin") == expr {
|
||||
c.detail("negative conditional:", expr)
|
||||
if node.ElseList != nil {
|
||||
c.compileSwitch(con, node.ElseList)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
con.Push("startif", "if "+expr+" {\n")
|
||||
c.compileSwitch(con, node.List)
|
||||
if node.ElseList == nil {
|
||||
|
@ -387,7 +499,7 @@ func (c *CTemplateSet) compileSwitch(con CContext, node parse.Node) {
|
|||
con.Push("endelse", "}\n")
|
||||
}
|
||||
case *parse.ListNode:
|
||||
c.detail("List Node")
|
||||
c.detailf("List Node: %+v\n", node)
|
||||
for _, subnode := range node.Nodes {
|
||||
c.compileSwitch(con, subnode)
|
||||
}
|
||||
|
@ -396,14 +508,10 @@ func (c *CTemplateSet) compileSwitch(con CContext, node parse.Node) {
|
|||
case *parse.TemplateNode:
|
||||
c.compileSubTemplate(con, node)
|
||||
case *parse.TextNode:
|
||||
c.previousNode = c.currentNode
|
||||
c.currentNode = node.Type()
|
||||
c.nextNode = 0
|
||||
tmpText := bytes.TrimSpace(node.Text)
|
||||
if len(tmpText) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
nodeText := string(node.Text)
|
||||
fragIndex := c.fragmentCursor[con.TemplateName]
|
||||
_, ok := c.FragOnce[con.TemplateName]
|
||||
|
@ -447,6 +555,10 @@ func (c *CTemplateSet) compileRangeNode(con CContext, node *parse.RangeNode) {
|
|||
ccon.VarHolder = "item" + depth
|
||||
ccon.HoldReflect = item
|
||||
c.compileSwitch(ccon, node.List)
|
||||
if con.LastBufIndex() == startIndex {
|
||||
con.DiscardAndAfter(startIndex - 1)
|
||||
return
|
||||
}
|
||||
con.EndLoop("}\n")
|
||||
c.afterTemplate(con, startIndex)
|
||||
if node.ElseList != nil {
|
||||
|
@ -1115,6 +1227,7 @@ func (c *CTemplateSet) compileVarSub(con CContext, varname string, val reflect.V
|
|||
c.importMap["strconv"] = "strconv"
|
||||
base = "[]byte(strconv.Itoa(" + varname + "))"
|
||||
case reflect.Bool:
|
||||
// TODO: Take c.guestOnly / c.memberOnly into account
|
||||
con.Push("startif", "if "+varname+" {\n")
|
||||
con.Push("varsub", "[]byte(\"true\")")
|
||||
con.Push("endif", "} ")
|
||||
|
@ -1127,6 +1240,11 @@ func (c *CTemplateSet) compileVarSub(con CContext, varname string, val reflect.V
|
|||
varname = "string(" + varname + ")"
|
||||
}
|
||||
base = "[]byte(" + varname + ")"
|
||||
// We don't to waste time on this conversion / w.Write call when guests don't have sessions
|
||||
// TODO: Implement this properly
|
||||
if c.guestOnly && base == "[]byte("+con.RootHolder+".CurrentUser.Session))" {
|
||||
return
|
||||
}
|
||||
case reflect.Int64:
|
||||
c.importMap["strconv"] = "strconv"
|
||||
base = "[]byte(strconv.FormatInt(" + varname + ", 10))"
|
||||
|
@ -1151,7 +1269,26 @@ func (c *CTemplateSet) compileSubTemplate(pcon CContext, node *parse.TemplateNod
|
|||
c.dumpCall("compileSubTemplate", pcon, node)
|
||||
c.detail("Template Node: ", node.Name)
|
||||
|
||||
// TODO: Cascade errors back up the tree to the caller?
|
||||
content, err := c.loadTemplate(c.fileDir, node.Name)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
tree := parse.New(node.Name, c.funcMap)
|
||||
var treeSet = make(map[string]*parse.Tree)
|
||||
tree, err = tree.Parse(content, "{{", "}}", treeSet, c.funcMap)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fname := strings.TrimSuffix(node.Name, filepath.Ext(node.Name))
|
||||
if c.guestOnly {
|
||||
fname += "_guest"
|
||||
} else if c.memberOnly {
|
||||
fname += "_member"
|
||||
}
|
||||
|
||||
con := pcon
|
||||
con.VarHolder = "tmpl_" + fname + "_vars"
|
||||
con.TemplateName = fname
|
||||
|
@ -1171,28 +1308,6 @@ func (c *CTemplateSet) compileSubTemplate(pcon CContext, node *parse.TemplateNod
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Cascade errors back up the tree to the caller?
|
||||
res, err := ioutil.ReadFile(c.fileDir + "overrides/" + node.Name)
|
||||
if err != nil {
|
||||
c.detail("override path: ", c.fileDir+"overrides/"+node.Name)
|
||||
c.detail("override err: ", err)
|
||||
res, err = ioutil.ReadFile(c.fileDir + node.Name)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
content := string(res)
|
||||
if c.config.Minify {
|
||||
content = minify(content)
|
||||
}
|
||||
|
||||
tree := parse.New(node.Name, c.funcMap)
|
||||
var treeSet = make(map[string]*parse.Tree)
|
||||
tree, err = tree.Parse(content, "{{", "}}", treeSet, c.funcMap)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
c.templateList[fname] = tree
|
||||
subtree := c.templateList[fname]
|
||||
c.detail("subtree.Root", subtree.Root)
|
||||
|
@ -1216,6 +1331,23 @@ func (c *CTemplateSet) compileSubTemplate(pcon CContext, node *parse.TemplateNod
|
|||
}
|
||||
}
|
||||
|
||||
func (c *CTemplateSet) loadTemplate(fileDir string, name string) (content string, err error) {
|
||||
res, err := ioutil.ReadFile(c.fileDir + "overrides/" + name)
|
||||
if err != nil {
|
||||
c.detail("override path: ", c.fileDir+"overrides/"+name)
|
||||
c.detail("override err: ", err)
|
||||
res, err = ioutil.ReadFile(c.fileDir + name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
content = string(res)
|
||||
if c.config.Minify {
|
||||
content = minify(content)
|
||||
}
|
||||
return content, nil
|
||||
}
|
||||
|
||||
func (c *CTemplateSet) afterTemplate(con CContext, startIndex int) {
|
||||
c.dumpCall("afterTemplate", con, startIndex)
|
||||
defer c.retCall("afterTemplate")
|
||||
|
|
|
@ -62,6 +62,7 @@ func userRoutes() *RouteGroup {
|
|||
Action("routes.AccountEditEmailTokenSubmit", "/user/edit/token/", "extraData"),
|
||||
|
||||
MemberView("routes.LevelList", "/user/levels/"),
|
||||
//MemberView("routes.LevelRankings", "/user/rankings/"),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
</div>
|
||||
<div style="clear: both;"></div>
|
||||
</nav>
|
||||
<div class="right_of_nav"><!--{{dock "rightOfNav" .Header }}-->
|
||||
<div class="right_of_nav">{{/**<!--{{dock "rightOfNav" .Header }}-->**/}}
|
||||
{{/** TODO: Make this a separate template and load it via the theme docks, here for now so we can rapidly prototype the Nox theme **/}}
|
||||
{{if eq .Header.Theme.Name "nox"}}
|
||||
<div class="user_box">
|
||||
|
|
|
@ -15,12 +15,14 @@
|
|||
<span class="topic_name_forum_sep hide_on_edit"> / </span>
|
||||
<a href="{{.Forum.Link}}" class="topic_forum hide_on_edit">{{.Forum.Name}}</a>
|
||||
{{/** TODO: Does this need to be guarded by a permission? It's only visible in edit mode anyway, which can't be triggered, if they don't have the permission **/}}
|
||||
{{if .CurrentUser.Loggedin}}
|
||||
{{if not .Topic.IsClosed or .CurrentUser.Perms.CloseTopic}}
|
||||
{{if .CurrentUser.Perms.EditTopic}}
|
||||
<input class='show_on_edit topic_name_input' name="topic_name" value='{{.Topic.Title}}' type="text" aria-label="{{lang "topic.title_input_aria"}}" />
|
||||
<button name="topic-button" class="formbutton show_on_edit submit_edit">{{lang "topic.update_button"}}</button>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
<span class="topic_view_count hide_on_edit">{{.Topic.ViewCount}}</span>
|
||||
{{/** TODO: Inline this CSS **/}}
|
||||
{{if .Topic.IsClosed}}<span class='username hide_on_micro topic_status_e topic_status_closed hide_on_edit' title='{{lang "status.closed_tooltip"}}' aria-label='{{lang "topic.status_closed_aria"}}' style="font-weight:normal;float: right;position:relative;top:-5px;">🔒︎</span>{{end}}
|
||||
|
@ -102,6 +104,7 @@
|
|||
{{template "topic_alt_posts.html" . }}
|
||||
</div>
|
||||
|
||||
{{if .CurrentUser.Loggedin}}
|
||||
{{if .CurrentUser.Perms.CreateReply}}
|
||||
{{if not .Topic.IsClosed or .CurrentUser.Perms.CloseTopic}}
|
||||
<div class="rowblock topic_reply_container">
|
||||
|
@ -144,6 +147,7 @@
|
|||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
</main>
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
<div class="action_button_right">
|
||||
<a class="action_button like_count hide_on_micro" aria-label="{{lang "topic.post_like_count_tooltip"}}">{{.LikeCount}}</a>
|
||||
<a class="action_button created_at hide_on_mobile">{{.RelativeCreatedAt}}</a>
|
||||
{{if $.CurrentUser.Perms.ViewIPs}}<a href="/users/ips/?ip={{.IPAddress}}" title="IP Address" class="action_button ip_item hide_on_mobile" aria-hidden="true">{{.IPAddress}}</a>{{end}}
|
||||
{{if $.CurrentUser.Loggedin}}{{if $.CurrentUser.Perms.ViewIPs}}<a href="/users/ips/?ip={{.IPAddress}}" title="IP Address" class="action_button ip_item hide_on_mobile" aria-hidden="true">{{.IPAddress}}</a>{{end}}{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
|
Loading…
Reference in New Issue