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:
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) {