Support FixedIndent, add tests
This commit is contained in:
parent
5b7e923bd8
commit
c9c7dd1b22
@ -16,11 +16,12 @@ type Hash map[string]interface{}
|
|||||||
type Option struct {
|
type Option struct {
|
||||||
Delimiters [2]string
|
Delimiters [2]string
|
||||||
NameLabel string // Identify the template to be used
|
NameLabel string // Identify the template to be used
|
||||||
TemplateDir string // directory where templates are located
|
TemplateDir string // Directory where templates are located
|
||||||
TemplateExtension string // appended on the label to idenfity the template
|
TemplateExtension string // Appended on the label to idenfity the template
|
||||||
DieOnBadParams bool // attempt to populate a variable that doesn't exist should result in an error
|
DieOnBadParams bool // Attempt to populate a variable that doesn't exist should result in an error
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
type TemplateNest struct {
|
type TemplateNest struct {
|
||||||
@ -118,6 +119,7 @@ func (nest *TemplateNest) index(filePath string) (TemplateFileIndex, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return TemplateFileIndex{}, fmt.Errorf("error reading file (`%s`): %w", filePath, err)
|
return TemplateFileIndex{}, fmt.Errorf("error reading file (`%s`): %w", filePath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Capture last modified time
|
// Capture last modified time
|
||||||
fileInfo, err := os.Stat(filePath)
|
fileInfo, err := os.Stat(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -134,6 +136,7 @@ func (nest *TemplateNest) index(filePath string) (TemplateFileIndex, error) {
|
|||||||
"%s\\s*(.+?)\\s*%s", regexp.QuoteMeta(delimiterStart), regexp.QuoteMeta(delimiterEnd),
|
"%s\\s*(.+?)\\s*%s", regexp.QuoteMeta(delimiterStart), regexp.QuoteMeta(delimiterEnd),
|
||||||
))
|
))
|
||||||
|
|
||||||
|
contentsStr := string(contents)
|
||||||
matches := re.FindAllStringSubmatchIndex(string(contents), -1)
|
matches := re.FindAllStringSubmatchIndex(string(contents), -1)
|
||||||
for _, match := range matches {
|
for _, match := range matches {
|
||||||
if len(match) < 4 {
|
if len(match) < 4 {
|
||||||
@ -148,15 +151,33 @@ 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 fixed indent is enabled then record the indent level for this
|
||||||
|
// variable. To get the indent level we look at each character in
|
||||||
|
// reverse from the start position of the variable until we find a
|
||||||
|
// newline character.
|
||||||
|
indentLevel := 0
|
||||||
|
if nest.option.FixedIndent {
|
||||||
|
// If we do not encounter a newline then that means this variable is
|
||||||
|
// on the first line, we take the start position as the indent
|
||||||
|
// level.
|
||||||
|
lineStartIdx := strings.LastIndex(contentsStr[:startIdx], "\n")
|
||||||
|
if lineStartIdx == -1 {
|
||||||
|
indentLevel = startIdx
|
||||||
|
} else {
|
||||||
|
indentLevel = startIdx - lineStartIdx - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
variables = append(variables, TemplateFileVariable{
|
variables = append(variables, TemplateFileVariable{
|
||||||
Name: varName,
|
Name: varName,
|
||||||
StartPosition: uint(startIdx),
|
StartPosition: uint(startIdx),
|
||||||
EndPosition: uint(endIdx),
|
EndPosition: uint(endIdx),
|
||||||
|
IndentLevel: uint(indentLevel),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fileIndex := TemplateFileIndex{
|
fileIndex := TemplateFileIndex{
|
||||||
Contents: string(contents),
|
Contents: contentsStr,
|
||||||
LastModified: fileInfo.ModTime(),
|
LastModified: fileInfo.ModTime(),
|
||||||
VariableNames: variableNames,
|
VariableNames: variableNames,
|
||||||
Variables: variables,
|
Variables: variables,
|
||||||
@ -261,15 +282,17 @@ func (nest *TemplateNest) Render(toRender interface{}) (string, error) {
|
|||||||
replacement := ""
|
replacement := ""
|
||||||
|
|
||||||
if value, exists := v[variable.Name]; exists {
|
if value, exists := v[variable.Name]; exists {
|
||||||
if text, ok := value.(string); ok {
|
subRender, err := nest.Render(value)
|
||||||
replacement = text
|
if err != nil {
|
||||||
} else {
|
return "", err
|
||||||
subRender, err := nest.Render(value)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
replacement = subRender
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if nest.option.FixedIndent && variable.IndentLevel != 0 {
|
||||||
|
indentReplacement := "\n" + strings.Repeat(" ", int(variable.IndentLevel))
|
||||||
|
subRender = strings.ReplaceAll(subRender, "\n", indentReplacement)
|
||||||
|
}
|
||||||
|
|
||||||
|
replacement = subRender
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace in rendered template
|
// Replace in rendered template
|
||||||
|
92
tests/05_fixed_indent_test.go
Normal file
92
tests/05_fixed_indent_test.go
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
package tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.virtual.blue/tomgracey/template-nest-go"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRenderSimplePageWithFixedIndent(t *testing.T) {
|
||||||
|
nest, err := templatenest.New(templatenest.Option{
|
||||||
|
TemplateDir: "templates",
|
||||||
|
FixedIndent: true,
|
||||||
|
})
|
||||||
|
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{
|
||||||
|
"TEMPLATE": "02-simple-component-multi-line",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
outputPage := templatenest.Hash{"TEMPLATE": "output/07-simple-page-fixed-indent"}
|
||||||
|
|
||||||
|
render := nest.MustRender(page)
|
||||||
|
outputRender := nest.MustRender(outputPage)
|
||||||
|
|
||||||
|
assert.Equal(t, outputRender, render, "Rendered output does not match expected output")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRenderComplexPageWithFixedIndent(t *testing.T) {
|
||||||
|
nest, err := templatenest.New(templatenest.Option{
|
||||||
|
TemplateDir: "templates",
|
||||||
|
FixedIndent: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to initialize TemplateNest: %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
page := templatenest.Hash{
|
||||||
|
"TEMPLATE": "10-complex-page",
|
||||||
|
"title": "Complex Page",
|
||||||
|
"pre_body": templatenest.Hash{
|
||||||
|
"TEMPLATE": "18-styles",
|
||||||
|
},
|
||||||
|
"navigation": templatenest.Hash{
|
||||||
|
"TEMPLATE": "11-navigation",
|
||||||
|
"banner": templatenest.Hash{
|
||||||
|
"TEMPLATE": "12-navigation-banner",
|
||||||
|
},
|
||||||
|
"items": []templatenest.Hash{
|
||||||
|
templatenest.Hash{"TEMPLATE": "13-navigation-item-00-services"},
|
||||||
|
templatenest.Hash{"TEMPLATE": "13-navigation-item-01-resources"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"hero_section": templatenest.Hash{
|
||||||
|
"TEMPLATE": "14-hero-section",
|
||||||
|
},
|
||||||
|
"main_content": []templatenest.Hash{
|
||||||
|
templatenest.Hash{"TEMPLATE": "15-isdc-card"},
|
||||||
|
templatenest.Hash{
|
||||||
|
"TEMPLATE": "16-vb-brand-cards",
|
||||||
|
"cards": []templatenest.Hash{
|
||||||
|
templatenest.Hash{
|
||||||
|
"TEMPLATE": "17-vb-brand-card-00",
|
||||||
|
"parent_classes": "p-card brand-card col-4",
|
||||||
|
},
|
||||||
|
templatenest.Hash{
|
||||||
|
"TEMPLATE": "17-vb-brand-card-01",
|
||||||
|
"parent_classes": "p-card brand-card col-4",
|
||||||
|
},
|
||||||
|
templatenest.Hash{
|
||||||
|
"TEMPLATE": "17-vb-brand-card-02",
|
||||||
|
"parent_classes": "p-card brand-card col-4",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"post_footer": templatenest.Hash{
|
||||||
|
"TEMPLATE": "19-scripts",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
outputPage := templatenest.Hash{"TEMPLATE": "output/08-complex-page-fixed-indent"}
|
||||||
|
|
||||||
|
render := nest.MustRender(page)
|
||||||
|
outputRender := nest.MustRender(outputPage)
|
||||||
|
|
||||||
|
assert.Equal(t, outputRender, render, "Rendered output does not match expected output")
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user