tpls

Extendable, Fast Template Engine for Go
git clone git://git.lair.cx/tpls
Log | Files | Refs | README | LICENSE

commit e2adc568d175bcbc548d79e2ae30780cb143dd02
parent 2c7dce3db9efad2b13095820575af97c99fdbe05
Author: Yongbin Kim <iam@yongbin.kim>
Date:   Thu, 21 Apr 2022 08:02:54 +0900

feat: Added attribute binding

Template tag cannot be used in attributes, so, you can binding any go code with `:attr` syntax.
For example, `<a :href="theLinkStringInGoCode"><string>theLinkStringInGoCode</string></a>` renders `<a href="https://example.com/">https://example.com/</a>`.

Signed-off-by: Yongbin Kim <iam@yongbin.kim>

Diffstat:
Mexamples/basic/templates/template.html | 5+++++
Mexamples/basic/templates/template.html.go | 9+++++++--
Mtplc/builtin_template.go | 22+++++++++++++++++++++-
Mtplc/builtin_template_test.go | 10++++++++++
4 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/examples/basic/templates/template.html b/examples/basic/templates/template.html @@ -74,4 +74,9 @@ <string>s</string><br> </for> </p> + <raw>theValue := "value"</raw> + <p> + Binding:<br> + <a :href="path.Join(`/path/to`, theValue)"><string>theValue</string></a> + </p> </template> diff --git a/examples/basic/templates/template.html.go b/examples/basic/templates/template.html.go @@ -14,8 +14,7 @@ type Page interface { } func Render(w tpls.Writer, p Page) { - w.WriteRaw(`<!doctype html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" - content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge">`) + w.WriteRaw(`<!doctype html><html lang="en"><head><meta charset="UTF-8"><meta content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" name="viewport"><meta http-equiv="X-UA-Compatible" content="ie=edge">`) w.WriteRaw(`<title>`) p.Title(w) w.WriteRaw(`</title>`) @@ -84,4 +83,10 @@ func (p *MainPage) Body(w tpls.Writer) { w.WriteRaw(`<br>`) } w.WriteRaw(`</p>`) + theValue := "value" + w.WriteRaw(`<p> Binding:<br><a href="`) + w.WriteString(path.Join(`/path/to`, theValue)) + w.WriteRaw(`">`) + w.WriteString(theValue) + w.WriteRaw(`</a></p>`) } diff --git a/tplc/builtin_template.go b/tplc/builtin_template.go @@ -3,6 +3,7 @@ package tplc import ( "bytes" "fmt" + "html" "io" "regexp" "strconv" @@ -111,7 +112,26 @@ loop: if useCustomOnly { return fmt.Errorf("unexpected tag: %s", tagName) } - buf.B = append(buf.B, t.Raw()...) + attrs := getAttrs(t) + // buf.B = append(buf.B, t.Raw()...) + buf.B = append(buf.B, '<') + buf.B = append(buf.B, tagName...) + for key, attr := range attrs { + buf.B = append(buf.B, ' ') + if len(key) > 0 && key[0] == ':' { + buf.B = append(buf.B, key[1:]...) + buf.B = append(buf.B, '=', '"') + flushBuffer() + w.WriteString(attr) + buf.B = append(buf.B, '"') + } else { + buf.B = append(buf.B, key...) + buf.B = append(buf.B, '=', '"') + buf.B = append(buf.B, html.EscapeString(attr)...) + buf.B = append(buf.B, '"') + } + } + buf.B = append(buf.B, '>') stack.Put(tagName) } else { flushBuffer() diff --git a/tplc/builtin_template_test.go b/tplc/builtin_template_test.go @@ -112,6 +112,16 @@ func Test_renderTag(t *testing.T) { "w.WriteString(\"World\")\n" + "w.WriteRaw(`!\nAnd this is second line.\n`)\n", }, + { + "attributes binding", + `<a :href="href">Link</a></test>`, + false, + "test", + nil, + false, + false, + "w.WriteRaw(`<a href=\"`)\nw.WriteString(href)\nw.WriteRaw(`\">Link</a>`)\n", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {