Support TokenEscapeChar, add tests
This commit is contained in:
parent
c9c7dd1b22
commit
decc220bfc
@ -22,6 +22,7 @@ type Option struct {
|
|||||||
ShowLabels bool // Prepend & Append a string to every template, helpful in debugging
|
ShowLabels bool // Prepend & Append a string to every template, helpful in debugging
|
||||||
CommentDelimiters [2]string // Used in conjunction with ShowLabels, if HTML then use '<!--', '-->'
|
CommentDelimiters [2]string // Used in conjunction with ShowLabels, if HTML then use '<!--', '-->'
|
||||||
FixedIndent bool // Intended to improve readability when inspecting nested templates
|
FixedIndent bool // Intended to improve readability when inspecting nested templates
|
||||||
|
TokenEscapeChar string // Escapes a token delimiter, i.e. if set to '\' then variables that have '\' prefix won't be replaced
|
||||||
}
|
}
|
||||||
|
|
||||||
type TemplateNest struct {
|
type TemplateNest struct {
|
||||||
@ -131,6 +132,7 @@ func (nest *TemplateNest) index(filePath string) (TemplateFileIndex, error) {
|
|||||||
|
|
||||||
delimiterStart := nest.option.Delimiters[0]
|
delimiterStart := nest.option.Delimiters[0]
|
||||||
delimiterEnd := nest.option.Delimiters[1]
|
delimiterEnd := nest.option.Delimiters[1]
|
||||||
|
escapeChar := nest.option.TokenEscapeChar
|
||||||
|
|
||||||
re := regexp.MustCompile(fmt.Sprintf(
|
re := regexp.MustCompile(fmt.Sprintf(
|
||||||
"%s\\s*(.+?)\\s*%s", regexp.QuoteMeta(delimiterStart), regexp.QuoteMeta(delimiterEnd),
|
"%s\\s*(.+?)\\s*%s", regexp.QuoteMeta(delimiterStart), regexp.QuoteMeta(delimiterEnd),
|
||||||
@ -151,6 +153,22 @@ func (nest *TemplateNest) index(filePath string) (TemplateFileIndex, error) {
|
|||||||
varName := string(contents[nameStartIdx:nameEndIdx])
|
varName := string(contents[nameStartIdx:nameEndIdx])
|
||||||
variableNames[varName] = struct{}{}
|
variableNames[varName] = struct{}{}
|
||||||
|
|
||||||
|
// If token escape char is set then look behind for it and if we
|
||||||
|
// find the escape char then we're only going to remove the escape
|
||||||
|
// char and not remove this variable.
|
||||||
|
if escapeChar != "" && startIdx >= len(escapeChar) {
|
||||||
|
escapeStartIdx := startIdx - len(escapeChar)
|
||||||
|
if contentsStr[escapeStartIdx:startIdx] == escapeChar {
|
||||||
|
variables = append(variables, TemplateFileVariable{
|
||||||
|
Name: "",
|
||||||
|
StartPosition: uint(escapeStartIdx),
|
||||||
|
EndPosition: uint(escapeStartIdx + len(escapeChar)),
|
||||||
|
EscapedToken: true,
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If fixed indent is enabled then record the indent level for this
|
// If fixed indent is enabled then record the indent level for this
|
||||||
// variable. To get the indent level we look at each character in
|
// variable. To get the indent level we look at each character in
|
||||||
// reverse from the start position of the variable until we find a
|
// reverse from the start position of the variable until we find a
|
||||||
@ -276,6 +294,10 @@ func (nest *TemplateNest) Render(toRender interface{}) (string, error) {
|
|||||||
rendered := tIndex.Contents
|
rendered := tIndex.Contents
|
||||||
for i := len(tIndex.Variables) - 1; i >= 0; i-- {
|
for i := len(tIndex.Variables) - 1; i >= 0; i-- {
|
||||||
variable := tIndex.Variables[i]
|
variable := tIndex.Variables[i]
|
||||||
|
if variable.EscapedToken {
|
||||||
|
rendered = rendered[:variable.StartPosition] + rendered[variable.EndPosition:]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// If the variable doesn't exist in template hash then replace it
|
// If the variable doesn't exist in template hash then replace it
|
||||||
// with an empty string.
|
// with an empty string.
|
||||||
|
97
tests/07_token_escape_char_test.go
Normal file
97
tests/07_token_escape_char_test.go
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
package tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.virtual.blue/tomgracey/template-nest-go"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"io/ioutil"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRenderWithEscapedVariable(t *testing.T) {
|
||||||
|
nest, err := templatenest.New(templatenest.Option{
|
||||||
|
TemplateDir: "templates",
|
||||||
|
TokenEscapeChar: "\\",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to initialize TemplateNest: %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
page := templatenest.Hash{
|
||||||
|
"TEMPLATE": "00-simple-page",
|
||||||
|
"variable": "Simple Variable",
|
||||||
|
"simple_component": []templatenest.Hash{
|
||||||
|
templatenest.Hash{
|
||||||
|
"TEMPLATE": "01-simple-component-token-escape",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
outputPath := "templates/output/09-simple-page-token-escape.html"
|
||||||
|
outputContents, err := ioutil.ReadFile(outputPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error reading file (`%s`): %+v", outputPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(
|
||||||
|
t,
|
||||||
|
strings.TrimSpace(string(outputContents)),
|
||||||
|
nest.MustRender(page),
|
||||||
|
"Rendered output does not match expected output",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRenderWithEscapedVariableAtStart(t *testing.T) {
|
||||||
|
nest, err := templatenest.New(templatenest.Option{
|
||||||
|
TemplateDir: "templates",
|
||||||
|
TokenEscapeChar: "\\",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to initialize TemplateNest: %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
page := templatenest.Hash{
|
||||||
|
"TEMPLATE": "03-var-at-begin",
|
||||||
|
"variable": "Simple Variable",
|
||||||
|
}
|
||||||
|
|
||||||
|
outputPath := "templates/output/10-var-at-begin.html"
|
||||||
|
outputContents, err := ioutil.ReadFile(outputPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error reading file (`%s`): %+v", outputPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(
|
||||||
|
t,
|
||||||
|
strings.TrimSpace(string(outputContents)),
|
||||||
|
nest.MustRender(page),
|
||||||
|
"Rendered output does not match expected output",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRenderWithEscapedVariableAtStart01(t *testing.T) {
|
||||||
|
nest, err := templatenest.New(templatenest.Option{
|
||||||
|
TemplateDir: "templates",
|
||||||
|
TokenEscapeChar: "\\",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to initialize TemplateNest: %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
page := templatenest.Hash{
|
||||||
|
"TEMPLATE": "03-var-at-begin-with-space",
|
||||||
|
}
|
||||||
|
|
||||||
|
outputPath := "templates/output/10-var-at-begin-with-space.html"
|
||||||
|
outputContents, err := ioutil.ReadFile(outputPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error reading file (`%s`): %+v", outputPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(
|
||||||
|
t,
|
||||||
|
strings.TrimSpace(string(outputContents)),
|
||||||
|
nest.MustRender(page),
|
||||||
|
"Rendered output does not match expected output",
|
||||||
|
)
|
||||||
|
}
|
1
tests/templates/03-var-at-begin-with-space.html
Normal file
1
tests/templates/03-var-at-begin-with-space.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
\<!--% variable %-->
|
1
tests/templates/output/10-var-at-begin-with-space.html
Normal file
1
tests/templates/output/10-var-at-begin-with-space.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
<!--% variable %-->
|
Loading…
Reference in New Issue
Block a user