mirror of
https://github.com/kataras/iris.git
synced 2026-03-06 16:35:57 +00:00
builtin html template functions changes
This commit is contained in:
@@ -44,7 +44,10 @@ func main() {
|
||||
// Bind: {{.message}} with "Hello world!"
|
||||
ctx.ViewData("message", "Hello world!")
|
||||
// Render template file: ./views/hello.html
|
||||
ctx.View("hello.html")
|
||||
if err := ctx.View("hello.html"); err != nil {
|
||||
ctx.HTML("<h3>%s</h3>", err.Error())
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
// Method: GET
|
||||
@@ -85,10 +88,10 @@ func main() {
|
||||
// builtin template funcs are:
|
||||
//
|
||||
// - {{ urlpath "mynamedroute" "pathParameter_ifneeded" }}
|
||||
// - {{ render "header.html" }}
|
||||
// - {{ render_r "header.html" }} // partial relative path to current page
|
||||
// - {{ yield }}
|
||||
// - {{ current }}
|
||||
// - {{ render "header.html" . }}
|
||||
// - {{ render_r "header.html" . }} // partial relative path to current page
|
||||
// - {{ yield . }}
|
||||
// - {{ current . }}
|
||||
|
||||
// register a custom template func.
|
||||
tmpl.AddFunc("greet", func(s string) string {
|
||||
@@ -106,7 +109,10 @@ func main() {
|
||||
|
||||
func hi(ctx iris.Context) {
|
||||
// render the template file "./templates/hi.html"
|
||||
ctx.View("hi.html")
|
||||
if err := ctx.View("hi.html"); err != nil {
|
||||
ctx.HTML("<h3>%s</h3>", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -150,7 +156,10 @@ type page struct {
|
||||
func hi(ctx iris.Context) {
|
||||
// {{.Page.Title}} and {{Page.Name}}
|
||||
ctx.ViewData("Page", page{Title: "Hi Page", Name: "iris"})
|
||||
ctx.View("hi.html")
|
||||
if err := ctx.View("hi.html"); err != nil {
|
||||
ctx.HTML("<h3>%s</h3>", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ func Ace(fs interface{}, extension string) *AceEngine {
|
||||
|
||||
s.middleware = func(name string, text []byte) (contents string, err error) {
|
||||
once.Do(func() { // on first template parse, all funcs are given.
|
||||
for k, v := range emptyFuncs {
|
||||
for k, v := range s.getBuiltinFuncs(name) {
|
||||
funcs[k] = v
|
||||
}
|
||||
|
||||
|
||||
@@ -103,8 +103,8 @@ func (s *HandlebarsEngine) Reload(developmentMode bool) *HandlebarsEngine {
|
||||
}
|
||||
|
||||
// Layout sets the layout template file which should use
|
||||
// the {{ yield }} func to yield the main template file
|
||||
// and optionally {{partial/partial_r/render}} to render
|
||||
// the {{ yield . }} func to yield the main template file
|
||||
// and optionally {{partial/partial_r/render . }} to render
|
||||
// other template files like headers and footers.
|
||||
func (s *HandlebarsEngine) Layout(layoutFile string) *HandlebarsEngine {
|
||||
s.layout = layoutFile
|
||||
@@ -238,7 +238,7 @@ func (s *HandlebarsEngine) ExecuteWriter(w io.Writer, filename string, layout st
|
||||
if context == nil {
|
||||
context = make(map[string]interface{}, 1)
|
||||
}
|
||||
// I'm implemented the {{ yield }} as with the rest of template engines, so this is not inneed for iris, but the user can do that manually if want
|
||||
// I'm implemented the {{ yield . }} as with the rest of template engines, so this is not inneed for iris, but the user can do that manually if want
|
||||
// there is no performance cost: raymond.RegisterPartialTemplate(name, tmpl)
|
||||
context["yield"] = raymond.SafeString(contents)
|
||||
}
|
||||
|
||||
72
view/html.go
72
view/html.go
@@ -53,27 +53,6 @@ var (
|
||||
_ EngineFuncer = (*HTMLEngine)(nil)
|
||||
)
|
||||
|
||||
var emptyFuncs = template.FuncMap{
|
||||
"yield": func(binding interface{}) (string, error) {
|
||||
return "", fmt.Errorf("yield was called, yet no layout defined")
|
||||
},
|
||||
"part": func() (string, error) {
|
||||
return "", fmt.Errorf("block was called, yet no layout defined")
|
||||
},
|
||||
"partial": func() (string, error) {
|
||||
return "", fmt.Errorf("block was called, yet no layout defined")
|
||||
},
|
||||
"partial_r": func() (string, error) {
|
||||
return "", fmt.Errorf("block was called, yet no layout defined")
|
||||
},
|
||||
"current": func() (string, error) {
|
||||
return "", nil
|
||||
},
|
||||
"render": func() (string, error) {
|
||||
return "", nil
|
||||
},
|
||||
}
|
||||
|
||||
// HTML creates and returns a new html view engine.
|
||||
// The html engine used like the "html/template" standard go package
|
||||
// but with a lot of extra features.
|
||||
@@ -175,8 +154,8 @@ func (s *HTMLEngine) Delims(left, right string) *HTMLEngine {
|
||||
}
|
||||
|
||||
// Layout sets the layout template file which inside should use
|
||||
// the {{ yield }} func to yield the main template file
|
||||
// and optionally {{partial/partial_r/render}} to render other template files like headers and footers
|
||||
// the {{ yield . }} func to yield the main template file
|
||||
// and optionally {{partial/partial_r/render . }} to render other template files like headers and footers
|
||||
//
|
||||
// The 'tmplLayoutFile' is a relative path of the templates base directory,
|
||||
// for the template file with its extension.
|
||||
@@ -334,6 +313,7 @@ func (s *HTMLEngine) parseTemplate(name string, contents []byte, funcs template.
|
||||
|
||||
name = strings.TrimPrefix(name, "/")
|
||||
tmpl := s.Templates.New(name)
|
||||
// tmpl.Option("missingkey=error")
|
||||
tmpl.Option(s.options...)
|
||||
|
||||
var text string
|
||||
@@ -347,7 +327,12 @@ func (s *HTMLEngine) parseTemplate(name string, contents []byte, funcs template.
|
||||
text = string(contents)
|
||||
}
|
||||
|
||||
tmpl.Funcs(emptyFuncs).Funcs(s.funcs)
|
||||
tmpl.Funcs(s.getBuiltinFuncs(name)).Funcs(s.funcs)
|
||||
|
||||
if strings.Contains(name, "layout") {
|
||||
tmpl.Funcs(s.layoutFuncs)
|
||||
}
|
||||
|
||||
if len(funcs) > 0 {
|
||||
tmpl.Funcs(funcs) // custom for this template.
|
||||
}
|
||||
@@ -376,27 +361,14 @@ func (s *HTMLEngine) executeTemplateBuf(name string, binding interface{}) (strin
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *HTMLEngine) layoutFuncsFor(lt *template.Template, name string, binding interface{}) {
|
||||
s.runtimeFuncsFor(lt, name, binding)
|
||||
|
||||
func (s *HTMLEngine) getBuiltinFuncs(name string) template.FuncMap {
|
||||
funcs := template.FuncMap{
|
||||
"yield": func() (template.HTML, error) {
|
||||
"yield": func(binding interface{}) (template.HTML, error) {
|
||||
result, err := s.executeTemplateBuf(name, binding)
|
||||
// Return safe HTML here since we are rendering our own template.
|
||||
return template.HTML(result), err
|
||||
},
|
||||
}
|
||||
|
||||
for k, v := range s.layoutFuncs {
|
||||
funcs[k] = v
|
||||
}
|
||||
|
||||
lt.Funcs(funcs)
|
||||
}
|
||||
|
||||
func (s *HTMLEngine) runtimeFuncsFor(t *template.Template, name string, binding interface{}) {
|
||||
funcs := template.FuncMap{
|
||||
"part": func(partName string) (template.HTML, error) {
|
||||
"part": func(partName string, binding interface{}) (template.HTML, error) {
|
||||
nameTemp := strings.ReplaceAll(name, s.extension, "")
|
||||
fullPartName := fmt.Sprintf("%s-%s", nameTemp, partName)
|
||||
result, err := s.executeTemplateBuf(fullPartName, binding)
|
||||
@@ -408,7 +380,7 @@ func (s *HTMLEngine) runtimeFuncsFor(t *template.Template, name string, binding
|
||||
"current": func() (string, error) {
|
||||
return name, nil
|
||||
},
|
||||
"partial": func(partialName string) (template.HTML, error) {
|
||||
"partial": func(partialName string, binding interface{}) (template.HTML, error) {
|
||||
fullPartialName := fmt.Sprintf("%s-%s", partialName, name)
|
||||
if s.Templates.Lookup(fullPartialName) != nil {
|
||||
result, err := s.executeTemplateBuf(fullPartialName, binding)
|
||||
@@ -420,7 +392,7 @@ func (s *HTMLEngine) runtimeFuncsFor(t *template.Template, name string, binding
|
||||
// it would be easier for adding pages' style/script inline
|
||||
// for example when using partial_r '.script' in layout.html
|
||||
// templates/users/index.html would load templates/users/index.script.html
|
||||
"partial_r": func(partialName string) (template.HTML, error) {
|
||||
"partial_r": func(partialName string, binding interface{}) (template.HTML, error) {
|
||||
ext := filepath.Ext(name)
|
||||
root := name[:len(name)-len(ext)]
|
||||
fullPartialName := fmt.Sprintf("%s%s%s", root, partialName, ext)
|
||||
@@ -430,13 +402,13 @@ func (s *HTMLEngine) runtimeFuncsFor(t *template.Template, name string, binding
|
||||
}
|
||||
return "", nil
|
||||
},
|
||||
"render": func(fullPartialName string) (template.HTML, error) {
|
||||
"render": func(fullPartialName string, binding interface{}) (template.HTML, error) {
|
||||
result, err := s.executeTemplateBuf(fullPartialName, binding)
|
||||
return template.HTML(result), err
|
||||
},
|
||||
}
|
||||
|
||||
t.Funcs(funcs)
|
||||
return funcs
|
||||
}
|
||||
|
||||
// ExecuteWriter executes a template and writes its result to the w writer.
|
||||
@@ -455,21 +427,19 @@ func (s *HTMLEngine) ExecuteWriter(w io.Writer, name string, layout string, bind
|
||||
}
|
||||
}
|
||||
|
||||
t := s.Templates.Lookup(name)
|
||||
if t == nil {
|
||||
return ErrNotExist{Name: name, IsLayout: false, Data: bindingData}
|
||||
}
|
||||
s.runtimeFuncsFor(t, name, bindingData)
|
||||
|
||||
if layout = getLayout(layout, s.layout); layout != "" {
|
||||
lt := s.Templates.Lookup(layout)
|
||||
if lt == nil {
|
||||
return ErrNotExist{Name: layout, IsLayout: true, Data: bindingData}
|
||||
}
|
||||
|
||||
s.layoutFuncsFor(lt, name, bindingData)
|
||||
return lt.Execute(w, bindingData)
|
||||
}
|
||||
|
||||
t := s.Templates.Lookup(name)
|
||||
if t == nil {
|
||||
return ErrNotExist{Name: name, IsLayout: false, Data: bindingData}
|
||||
}
|
||||
|
||||
return t.Execute(w, bindingData)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user