diff --git a/modules/templates/vars/vars.go b/modules/templates/vars/vars.go index a3b554e86956b..d2b12effbf74f 100644 --- a/modules/templates/vars/vars.go +++ b/modules/templates/vars/vars.go @@ -7,6 +7,8 @@ package vars import ( "fmt" "strings" + "unicode" + "unicode/utf8" ) // ErrWrongSyntax represents a wrong syntax with a tempate @@ -40,9 +42,11 @@ func IsErrNoMatchedVar(err error) bool { return ok } -// Expand replaces all variables like {var} to match, if error occurs, the error part doesn't change and is returned as it is. -// `#' is a reversed char, templates can use `{#{}` to do escape and output char '{'. +// Expand replaces all variables like {var} to match, if error occurs, +// the error part doesn't change and is returned as it is. func Expand(template string, match map[string]string) (string, error) { + // in the future, if necessary, we can introduce some escape-char, + // for example: it will use `#' as a reversed char, templates will use `{#{}` to do escape and output char '{'. var buf strings.Builder var err error @@ -84,9 +88,10 @@ func Expand(template string, match map[string]string) (string, error) { } else { // now we get a valid key "{...}" key := part[1 : len(part)-1] - if key[0] == '#' { - // escaped char - buf.WriteString(key[1:]) + keyFirst, _ := utf8.DecodeRuneInString(key) + if unicode.IsSpace(keyFirst) || unicode.IsPunct(keyFirst) || unicode.IsControl(keyFirst) { + // the if key doesn't start with a letter, then we do not treat it as a var now + buf.WriteString(part) } else { // look up in the map if val, ok := match[key]; ok { diff --git a/modules/templates/vars/vars_test.go b/modules/templates/vars/vars_test.go index 7b16e51ac43ec..78930382a8abe 100644 --- a/modules/templates/vars/vars_test.go +++ b/modules/templates/vars/vars_test.go @@ -12,61 +12,61 @@ import ( func TestExpandVars(t *testing.T) { kases := []struct { - template string - maps map[string]string - expected string - fail bool + tmpl string + data map[string]string + out string + error bool }{ { - template: "{a}", - maps: map[string]string{ + tmpl: "{a}", + data: map[string]string{ "a": "1", }, - expected: "1", + out: "1", }, { - template: "expand {a}, {b} and {c}, with escaped {#{}", - maps: map[string]string{ + tmpl: "expand {a}, {b} and {c}, with non-var { } {#}", + data: map[string]string{ "a": "1", "b": "2", "c": "3", }, - expected: "expand 1, 2 and 3, with escaped {", + out: "expand 1, 2 and 3, with non-var { } {#}", }, { - template: "中文内容 {一}, {二} 和 {三} 中文结尾", - maps: map[string]string{ + tmpl: "中文内容 {一}, {二} 和 {三} 中文结尾", + data: map[string]string{ "一": "11", "二": "22", "三": "33", }, - expected: "中文内容 11, 22 和 33 中文结尾", + out: "中文内容 11, 22 和 33 中文结尾", }, { - template: "expand {{a}, {b} and {c}", - maps: map[string]string{ + tmpl: "expand {{a}, {b} and {c}", + data: map[string]string{ "a": "foo", "b": "bar", }, - expected: "expand {{a}, bar and {c}", - fail: true, + out: "expand {{a}, bar and {c}", + error: true, }, { - template: "expand } {} and {", - expected: "expand } {} and {", - fail: true, + tmpl: "expand } {} and {", + out: "expand } {} and {", + error: true, }, } for _, kase := range kases { - t.Run(kase.template, func(t *testing.T) { - res, err := Expand(kase.template, kase.maps) - if kase.fail { + t.Run(kase.tmpl, func(t *testing.T) { + res, err := Expand(kase.tmpl, kase.data) + if kase.error { assert.Error(t, err) } else { assert.NoError(t, err) } - assert.EqualValues(t, kase.expected, res) + assert.EqualValues(t, kase.out, res) }) } }