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
|
// nolint
|
||||||
var Template_topic_handle = interpretedTopicTemplate
|
var Template_topic_handle = interpretedTopicTemplate
|
||||||
var Template_topic_alt_handle = interpretedTopicTemplate
|
var Template_topic_alt_handle = interpretedTopicTemplate
|
||||||
|
var Template_topic_alt_guest_handle = interpretedTopicTemplate
|
||||||
|
var Template_topic_alt_member_handle = interpretedTopicTemplate
|
||||||
|
|
||||||
// nolint
|
// nolint
|
||||||
var Template_topics_handle = func(pi TopicListPage, w io.Writer) error {
|
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)
|
return header, buildHeader(user2), buildHeader(user3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TmplLoggedin struct {
|
||||||
|
Stub string
|
||||||
|
Guest string
|
||||||
|
Member string
|
||||||
|
}
|
||||||
|
|
||||||
// ? - Add template hooks?
|
// ? - Add template hooks?
|
||||||
func CompileTemplates() error {
|
func CompileTemplates() error {
|
||||||
var config tmpl.CTemplateConfig
|
var config tmpl.CTemplateConfig
|
||||||
|
@ -210,15 +218,24 @@ func CompileTemplates() error {
|
||||||
var compile = func(name string, expects string, expectsInt interface{}) (tmpl string, err error) {
|
var compile = func(name string, expects string, expectsInt interface{}) (tmpl string, err error) {
|
||||||
return c.Compile(name+".html", "templates/", expects, expectsInt, varList)
|
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"
|
header.Title = "Topic Name"
|
||||||
tpage := TopicPage{header, replyList, topic, &Forum{ID: 1, Name: "Hahaha"}, poll, 1, 1}
|
tpage := TopicPage{header, replyList, topic, &Forum{ID: 1, Name: "Hahaha"}, poll, 1, 1}
|
||||||
tpage.Forum.Link = BuildForumURL(NameToSlug(tpage.Forum.Name), tpage.Forum.ID)
|
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 {
|
if err != nil {
|
||||||
return err
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -309,17 +326,28 @@ func CompileTemplates() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
var writeTemplate = func(name string, content string) {
|
var writeTemplate = func(name string, content interface{}) {
|
||||||
log.Print("Writing template '" + name + "'")
|
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)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
err := writeFile("./template_"+name+".go", content)
|
switch content := content.(type) {
|
||||||
if err != nil {
|
case string:
|
||||||
log.Fatal(err)
|
writeTmpl(name, content)
|
||||||
|
case TmplLoggedin:
|
||||||
|
writeTmpl(name, content.Stub)
|
||||||
|
writeTmpl(name+"_guest", content.Guest)
|
||||||
|
writeTmpl(name+"_member", content.Member)
|
||||||
}
|
}
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
|
@ -341,8 +369,8 @@ func CompileTemplates() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Print("Writing the templates")
|
log.Print("Writing the templates")
|
||||||
writeTemplate("topic", topicIDTmpl)
|
writeTemplate("topic", topicTmpl)
|
||||||
writeTemplate("topic_alt", topicIDAltTmpl)
|
writeTemplate("topic_alt", topicAltTmpl)
|
||||||
writeTemplate("profile", profileTmpl)
|
writeTemplate("profile", profileTmpl)
|
||||||
writeTemplate("forums", forumsTmpl)
|
writeTemplate("forums", forumsTmpl)
|
||||||
writeTemplate("topics", topicListTmpl)
|
writeTemplate("topics", topicListTmpl)
|
||||||
|
@ -415,11 +443,11 @@ func CompileJSTemplates() error {
|
||||||
header.Title = "Topic Name"
|
header.Title = "Topic Name"
|
||||||
tpage := TopicPage{header, replyList, topic, &Forum{ID: 1, Name: "Hahaha"}, poll, 1, 1}
|
tpage := TopicPage{header, replyList, topic, &Forum{ID: 1, Name: "Hahaha"}, poll, 1, 1}
|
||||||
tpage.Forum.Link = BuildForumURL(NameToSlug(tpage.Forum.Name), tpage.Forum.ID)
|
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 {
|
if err != nil {
|
||||||
return err
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -443,8 +471,8 @@ func CompileJSTemplates() error {
|
||||||
}
|
}
|
||||||
writeTemplate("alert", alertTmpl)
|
writeTemplate("alert", alertTmpl)
|
||||||
writeTemplate("topics_topic", topicListItemTmpl)
|
writeTemplate("topics_topic", topicListItemTmpl)
|
||||||
writeTemplate("topic_posts", topicIDTmpl)
|
writeTemplate("topic_posts", topicPostsTmpl)
|
||||||
writeTemplate("topic_alt_posts", topicIDAltTmpl)
|
writeTemplate("topic_alt_posts", topicAltPostsTmpl)
|
||||||
writeTemplateList(c, &wg, dirPrefix)
|
writeTemplateList(c, &wg, dirPrefix)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ type OutBufferFrame struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type CContext struct {
|
type CContext struct {
|
||||||
|
RootHolder string
|
||||||
VarHolder string
|
VarHolder string
|
||||||
HoldReflect reflect.Value
|
HoldReflect reflect.Value
|
||||||
TemplateName string
|
TemplateName string
|
||||||
|
@ -34,17 +35,17 @@ type CContext struct {
|
||||||
|
|
||||||
func (con *CContext) Push(nType string, body string) (index int) {
|
func (con *CContext) Push(nType string, body string) (index int) {
|
||||||
*con.OutBuf = append(*con.OutBuf, OutBufferFrame{body, nType, con.TemplateName, nil, nil})
|
*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) {
|
func (con *CContext) PushText(body string, fragIndex int, fragOutIndex int) (index int) {
|
||||||
*con.OutBuf = append(*con.OutBuf, OutBufferFrame{body, "text", con.TemplateName, fragIndex, fragOutIndex})
|
*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) {
|
func (con *CContext) PushPhrase(body string, langIndex int) (index int) {
|
||||||
*con.OutBuf = append(*con.OutBuf, OutBufferFrame{body, "lang", con.TemplateName, langIndex, nil})
|
*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) {
|
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) {
|
func (con *CContext) StartTemplate(body string) (index int) {
|
||||||
*con.OutBuf = append(*con.OutBuf, OutBufferFrame{body, "starttemplate", con.TemplateName, nil, nil})
|
return con.addFrame(body, "starttemplate", nil, nil)
|
||||||
return len(*con.OutBuf) - 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (con *CContext) EndTemplate(body string) (index int) {
|
func (con *CContext) EndTemplate(body string) (index int) {
|
||||||
|
@ -74,3 +74,25 @@ func (con *CContext) AttachVars(vars string, index int) {
|
||||||
node.Body += vars
|
node.Body += vars
|
||||||
outBuf[index] = node
|
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
|
hasDispInt bool
|
||||||
localDispStructIndex int
|
localDispStructIndex int
|
||||||
langIndexToName []string
|
langIndexToName []string
|
||||||
|
guestOnly bool
|
||||||
|
memberOnly bool
|
||||||
stats map[string]int
|
stats map[string]int
|
||||||
previousNode parse.NodeType
|
|
||||||
currentNode parse.NodeType
|
|
||||||
nextNode parse.NodeType
|
|
||||||
//tempVars map[string]string
|
//tempVars map[string]string
|
||||||
config CTemplateConfig
|
config CTemplateConfig
|
||||||
baseImportMap map[string]string
|
baseImportMap map[string]string
|
||||||
buildTags string
|
buildTags string
|
||||||
expectsInt interface{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCTemplateSet() *CTemplateSet {
|
func NewCTemplateSet() *CTemplateSet {
|
||||||
|
@ -126,10 +124,86 @@ type Skipper struct {
|
||||||
Index int
|
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) {
|
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 {
|
if c.config.Debug {
|
||||||
fmt.Println("Compiling template '" + name + "'")
|
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{}
|
c.importMap = map[string]string{}
|
||||||
for index, item := range c.baseImportMap {
|
for index, item := range c.baseImportMap {
|
||||||
c.importMap[index] = item
|
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.varList = varList
|
||||||
c.hasDispInt = false
|
c.hasDispInt = false
|
||||||
c.localDispStructIndex = 0
|
c.localDispStructIndex = 0
|
||||||
c.stats = make(map[string]int)
|
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)
|
tree := parse.New(name, c.funcMap)
|
||||||
var treeSet = make(map[string]*parse.Tree)
|
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)
|
c.detail(name)
|
||||||
|
|
||||||
fname := strings.TrimSuffix(name, filepath.Ext(name))
|
fname := strings.TrimSuffix(name, filepath.Ext(name))
|
||||||
|
if c.guestOnly {
|
||||||
|
fname += "_guest"
|
||||||
|
} else if c.memberOnly {
|
||||||
|
fname += "_member"
|
||||||
|
}
|
||||||
|
|
||||||
var outBuf []OutBufferFrame
|
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.templateList = map[string]*parse.Tree{fname: tree}
|
||||||
c.detail(c.templateList)
|
c.detail(c.templateList)
|
||||||
c.localVars = make(map[string]map[string]VarItemReflect)
|
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("text frame:")
|
||||||
c.detail(frame)
|
c.detail(frame)
|
||||||
oid := fid
|
oid := fid
|
||||||
|
c.detail("oid:", oid)
|
||||||
skipBlock, ok := skipped[frame.TemplateName]
|
skipBlock, ok := skipped[frame.TemplateName]
|
||||||
if !ok {
|
if !ok {
|
||||||
skipBlock = &SkipBlock{make(map[int]int), 0, 0}
|
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
|
skip := skipBlock.LastCount
|
||||||
c.detailf("skipblock %+v\n", skipBlock)
|
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 {
|
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]
|
next := outBuf[fid+1]
|
||||||
c.detail("next frame:", next)
|
c.detail("next frame:", next)
|
||||||
c.detail("frame frag:", c.fragBuf[frame.Extra2.(int)])
|
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[frame.Extra2.(int)].Body += c.fragBuf[next.Extra2.(int)].Body
|
||||||
c.fragBuf[next.Extra2.(int)].Seen = true
|
c.fragBuf[next.Extra2.(int)].Seen = true
|
||||||
fid++
|
fid++
|
||||||
skipBlock.LastCount += (fid - oid)
|
skipBlock.LastCount++
|
||||||
skipBlock.Frags[frame.Extra.(int)] = skipBlock.LastCount
|
skipBlock.Frags[frame.Extra.(int)] = skipBlock.LastCount
|
||||||
|
c.detail("post fid:", fid)
|
||||||
}
|
}
|
||||||
writeTextFrame(frame.TemplateName, frame.Extra.(int)-skip)
|
writeTextFrame(frame.TemplateName, frame.Extra.(int)-skip)
|
||||||
} else if frame.Type == "varsub" || frame.Type == "cvarsub" {
|
} else if frame.Type == "varsub" || frame.Type == "cvarsub" {
|
||||||
c.detail(frame.Type + " frame")
|
c.detail(frame.Type + " frame")
|
||||||
fout += "w.Write(" + frame.Body + ")\n"
|
fout += "w.Write(" + frame.Body + ")\n"
|
||||||
|
} else if frame.Type == "identifier" {
|
||||||
|
c.detailf(frame.Type+" frame:%+v\n", frame)
|
||||||
|
fout += frame.Body
|
||||||
} else {
|
} else {
|
||||||
c.detail(frame.Type + " frame")
|
c.detail(frame.Type + " frame")
|
||||||
fout += frame.Body
|
fout += frame.Body
|
||||||
|
@ -334,14 +407,8 @@ w.Write([]byte(`, " + ", -1)
|
||||||
func (c *CTemplateSet) rootIterate(tree *parse.Tree, con CContext) {
|
func (c *CTemplateSet) rootIterate(tree *parse.Tree, con CContext) {
|
||||||
c.dumpCall("rootIterate", tree, con)
|
c.dumpCall("rootIterate", tree, con)
|
||||||
c.detail(tree.Root)
|
c.detail(tree.Root)
|
||||||
treeLength := len(tree.Root.Nodes)
|
for _, node := range tree.Root.Nodes {
|
||||||
for index, node := range tree.Root.Nodes {
|
|
||||||
c.detail("Node:", node.String())
|
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.compileSwitch(con, node)
|
||||||
}
|
}
|
||||||
c.retCall("rootIterate")
|
c.retCall("rootIterate")
|
||||||
|
@ -371,9 +438,54 @@ func (c *CTemplateSet) compileSwitch(con CContext, node parse.Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
c.detail("Expression:", expr)
|
c.detail("Expression:", expr)
|
||||||
c.previousNode = c.currentNode
|
// Simple member / guest optimisation for now
|
||||||
c.currentNode = parse.NodeList
|
// TODO: Expand upon this
|
||||||
c.nextNode = -1
|
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")
|
con.Push("startif", "if "+expr+" {\n")
|
||||||
c.compileSwitch(con, node.List)
|
c.compileSwitch(con, node.List)
|
||||||
if node.ElseList == nil {
|
if node.ElseList == nil {
|
||||||
|
@ -387,7 +499,7 @@ func (c *CTemplateSet) compileSwitch(con CContext, node parse.Node) {
|
||||||
con.Push("endelse", "}\n")
|
con.Push("endelse", "}\n")
|
||||||
}
|
}
|
||||||
case *parse.ListNode:
|
case *parse.ListNode:
|
||||||
c.detail("List Node")
|
c.detailf("List Node: %+v\n", node)
|
||||||
for _, subnode := range node.Nodes {
|
for _, subnode := range node.Nodes {
|
||||||
c.compileSwitch(con, subnode)
|
c.compileSwitch(con, subnode)
|
||||||
}
|
}
|
||||||
|
@ -396,14 +508,10 @@ func (c *CTemplateSet) compileSwitch(con CContext, node parse.Node) {
|
||||||
case *parse.TemplateNode:
|
case *parse.TemplateNode:
|
||||||
c.compileSubTemplate(con, node)
|
c.compileSubTemplate(con, node)
|
||||||
case *parse.TextNode:
|
case *parse.TextNode:
|
||||||
c.previousNode = c.currentNode
|
|
||||||
c.currentNode = node.Type()
|
|
||||||
c.nextNode = 0
|
|
||||||
tmpText := bytes.TrimSpace(node.Text)
|
tmpText := bytes.TrimSpace(node.Text)
|
||||||
if len(tmpText) == 0 {
|
if len(tmpText) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeText := string(node.Text)
|
nodeText := string(node.Text)
|
||||||
fragIndex := c.fragmentCursor[con.TemplateName]
|
fragIndex := c.fragmentCursor[con.TemplateName]
|
||||||
_, ok := c.FragOnce[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.VarHolder = "item" + depth
|
||||||
ccon.HoldReflect = item
|
ccon.HoldReflect = item
|
||||||
c.compileSwitch(ccon, node.List)
|
c.compileSwitch(ccon, node.List)
|
||||||
|
if con.LastBufIndex() == startIndex {
|
||||||
|
con.DiscardAndAfter(startIndex - 1)
|
||||||
|
return
|
||||||
|
}
|
||||||
con.EndLoop("}\n")
|
con.EndLoop("}\n")
|
||||||
c.afterTemplate(con, startIndex)
|
c.afterTemplate(con, startIndex)
|
||||||
if node.ElseList != nil {
|
if node.ElseList != nil {
|
||||||
|
@ -1115,6 +1227,7 @@ func (c *CTemplateSet) compileVarSub(con CContext, varname string, val reflect.V
|
||||||
c.importMap["strconv"] = "strconv"
|
c.importMap["strconv"] = "strconv"
|
||||||
base = "[]byte(strconv.Itoa(" + varname + "))"
|
base = "[]byte(strconv.Itoa(" + varname + "))"
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
|
// TODO: Take c.guestOnly / c.memberOnly into account
|
||||||
con.Push("startif", "if "+varname+" {\n")
|
con.Push("startif", "if "+varname+" {\n")
|
||||||
con.Push("varsub", "[]byte(\"true\")")
|
con.Push("varsub", "[]byte(\"true\")")
|
||||||
con.Push("endif", "} ")
|
con.Push("endif", "} ")
|
||||||
|
@ -1127,6 +1240,11 @@ func (c *CTemplateSet) compileVarSub(con CContext, varname string, val reflect.V
|
||||||
varname = "string(" + varname + ")"
|
varname = "string(" + varname + ")"
|
||||||
}
|
}
|
||||||
base = "[]byte(" + 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:
|
case reflect.Int64:
|
||||||
c.importMap["strconv"] = "strconv"
|
c.importMap["strconv"] = "strconv"
|
||||||
base = "[]byte(strconv.FormatInt(" + varname + ", 10))"
|
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.dumpCall("compileSubTemplate", pcon, node)
|
||||||
c.detail("Template Node: ", node.Name)
|
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))
|
fname := strings.TrimSuffix(node.Name, filepath.Ext(node.Name))
|
||||||
|
if c.guestOnly {
|
||||||
|
fname += "_guest"
|
||||||
|
} else if c.memberOnly {
|
||||||
|
fname += "_member"
|
||||||
|
}
|
||||||
|
|
||||||
con := pcon
|
con := pcon
|
||||||
con.VarHolder = "tmpl_" + fname + "_vars"
|
con.VarHolder = "tmpl_" + fname + "_vars"
|
||||||
con.TemplateName = fname
|
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
|
c.templateList[fname] = tree
|
||||||
subtree := c.templateList[fname]
|
subtree := c.templateList[fname]
|
||||||
c.detail("subtree.Root", subtree.Root)
|
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) {
|
func (c *CTemplateSet) afterTemplate(con CContext, startIndex int) {
|
||||||
c.dumpCall("afterTemplate", con, startIndex)
|
c.dumpCall("afterTemplate", con, startIndex)
|
||||||
defer c.retCall("afterTemplate")
|
defer c.retCall("afterTemplate")
|
||||||
|
|
|
@ -62,6 +62,7 @@ func userRoutes() *RouteGroup {
|
||||||
Action("routes.AccountEditEmailTokenSubmit", "/user/edit/token/", "extraData"),
|
Action("routes.AccountEditEmailTokenSubmit", "/user/edit/token/", "extraData"),
|
||||||
|
|
||||||
MemberView("routes.LevelList", "/user/levels/"),
|
MemberView("routes.LevelList", "/user/levels/"),
|
||||||
|
//MemberView("routes.LevelRankings", "/user/rankings/"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div style="clear: both;"></div>
|
<div style="clear: both;"></div>
|
||||||
</nav>
|
</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 **/}}
|
{{/** 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"}}
|
{{if eq .Header.Theme.Name "nox"}}
|
||||||
<div class="user_box">
|
<div class="user_box">
|
||||||
|
|
|
@ -15,12 +15,14 @@
|
||||||
<span class="topic_name_forum_sep hide_on_edit"> / </span>
|
<span class="topic_name_forum_sep hide_on_edit"> / </span>
|
||||||
<a href="{{.Forum.Link}}" class="topic_forum hide_on_edit">{{.Forum.Name}}</a>
|
<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 **/}}
|
{{/** 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 not .Topic.IsClosed or .CurrentUser.Perms.CloseTopic}}
|
||||||
{{if .CurrentUser.Perms.EditTopic}}
|
{{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"}}" />
|
<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>
|
<button name="topic-button" class="formbutton show_on_edit submit_edit">{{lang "topic.update_button"}}</button>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
{{end}}
|
||||||
<span class="topic_view_count hide_on_edit">{{.Topic.ViewCount}}</span>
|
<span class="topic_view_count hide_on_edit">{{.Topic.ViewCount}}</span>
|
||||||
{{/** TODO: Inline this CSS **/}}
|
{{/** 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}}
|
{{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" . }}
|
{{template "topic_alt_posts.html" . }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{if .CurrentUser.Loggedin}}
|
||||||
{{if .CurrentUser.Perms.CreateReply}}
|
{{if .CurrentUser.Perms.CreateReply}}
|
||||||
{{if not .Topic.IsClosed or .CurrentUser.Perms.CloseTopic}}
|
{{if not .Topic.IsClosed or .CurrentUser.Perms.CloseTopic}}
|
||||||
<div class="rowblock topic_reply_container">
|
<div class="rowblock topic_reply_container">
|
||||||
|
@ -144,6 +147,7 @@
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
<div class="action_button_right">
|
<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 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>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
Loading…
Reference in New Issue