Support defaults, add tests

This commit is contained in:
Andinus 2024-11-16 13:38:22 +05:30
parent decc220bfc
commit 0acc608e47
Signed by: andinus
GPG Key ID: B67D55D482A799FD
2 changed files with 101 additions and 10 deletions

@ -14,15 +14,18 @@ type Hash map[string]interface{}
// Option holds configuration for TemplateNest // Option holds configuration for TemplateNest
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 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 TokenEscapeChar string // Escapes a token delimiter, i.e. if set to '\' then variables that have '\' prefix won't be replaced
DefaultsNamespaceChar string
Defaults Hash // Provide a hash of default values that are substituted if template hash does not provide a value
defaultsFlat Hash
} }
type TemplateNest struct { type TemplateNest struct {
@ -73,6 +76,14 @@ func New(opts Option) (*TemplateNest, error) {
if opts.TemplateExtension == "" { if opts.TemplateExtension == "" {
opts.TemplateExtension = "html" opts.TemplateExtension = "html"
} }
if opts.DefaultsNamespaceChar == "" {
opts.DefaultsNamespaceChar = "."
}
if opts.Defaults == nil {
opts.Defaults = make(map[string]interface{})
}
opts.defaultsFlat = FlattenMap(opts.Defaults, "", opts.DefaultsNamespaceChar)
// Initialize TemplateNest with the final options. // Initialize TemplateNest with the final options.
nest := &TemplateNest{ nest := &TemplateNest{
@ -115,6 +126,28 @@ func New(opts Option) (*TemplateNest, error) {
return nest, nil return nest, nil
} }
// FlattenMap flattens a nested map[string]interface{} into a flat map with
// dot-separated keys.
func FlattenMap(input Hash, parentKey string, separator string) Hash {
result := make(map[string]interface{})
for key, value := range input {
fullKey := key
if parentKey != "" {
fullKey = parentKey + separator + key
}
// Check if the value is a nested map
if nestedMap, ok := value.(Hash); ok {
for k, v := range FlattenMap(nestedMap, fullKey, separator) {
result[k] = v
}
} else {
result[fullKey] = value
}
}
return result
}
func (nest *TemplateNest) index(filePath string) (TemplateFileIndex, error) { func (nest *TemplateNest) index(filePath string) (TemplateFileIndex, error) {
contents, err := ioutil.ReadFile(filePath) contents, err := ioutil.ReadFile(filePath)
if err != nil { if err != nil {
@ -303,7 +336,14 @@ func (nest *TemplateNest) Render(toRender interface{}) (string, error) {
// with an empty string. // with an empty string.
replacement := "" replacement := ""
if value, exists := v[variable.Name]; exists { value, exists := v[variable.Name]
defaultValue, defaultExists := nest.option.defaultsFlat[variable.Name]
if exists || defaultExists {
if !exists {
value = defaultValue
}
subRender, err := nest.Render(value) subRender, err := nest.Render(value)
if err != nil { if err != nil {
return "", err return "", err

51
tests/08_defaults_test.go Normal file

@ -0,0 +1,51 @@
package tests
import (
"git.virtual.blue/tomgracey/template-nest-go"
"github.com/stretchr/testify/assert"
"testing"
)
func TestRenderWithDefaults(t *testing.T) {
nest, err := templatenest.New(templatenest.Option{
TemplateDir: "templates",
Defaults: templatenest.Hash{
"variable": "Simple Variable",
"space": templatenest.Hash{
"inside": "A variable inside a space.",
},
},
})
if err != nil {
t.Fatalf("Failed to initialize TemplateNest: %+v", err)
}
page := templatenest.Hash{
"TEMPLATE": "00-simple-page",
"simple_component": []templatenest.Hash{
templatenest.Hash{
"TEMPLATE": "01-simple-component",
"variable": "Simple Variable in Simple Component",
},
},
}
outputPage := templatenest.Hash{"TEMPLATE": "output/01-simple-page"}
assert.Equal(
t,
nest.MustRender(outputPage),
nest.MustRender(page),
"Rendered output does not match expected output",
)
spacePage := templatenest.Hash{"TEMPLATE": "03-namespace-page"}
spaceOutputPage := templatenest.Hash{"TEMPLATE": "output/11-namespace-page"}
assert.Equal(
t,
nest.MustRender(spaceOutputPage),
nest.MustRender(spacePage),
"Rendered output does not match expected output",
)
}