diff --git a/namespace.go b/namespace.go index a26b255..4bed359 100644 --- a/namespace.go +++ b/namespace.go @@ -20,6 +20,9 @@ type Namespace struct { // WriteOnSuccess indicates whether the output should only be written if generation fully succeeds. // This option buffers the output of the template, so it will use more memory. (default: false) WriteOnSuccess bool + // NilToZero indictes whether nil pointer values should be converted to zero values of their underlying + // types. + NilToZero bool escapeHTML *bool } @@ -86,6 +89,14 @@ func (n *Namespace) WithWhitespaceMutations(b bool) *Namespace { return n } +// WithNilToZero enables or disables conversion of nil values to zero values for the namespace +func (n *Namespace) WithNilToZero(b bool) *Namespace { + n.mu.Lock() + defer n.mu.Unlock() + n.NilToZero = true + return n +} + // GetTemplate tries to get a template from the namespace's template map. // If it finds the template, it returns the template and true. If it // doesn't find it, it returns nil and false. diff --git a/salix.go b/salix.go index 9cde930..31213d3 100644 --- a/salix.go +++ b/salix.go @@ -26,6 +26,7 @@ type Template struct { // WriteOnSuccess indicates whether the output should only be written if generation fully succeeds. // This option buffers the output of the template, so it will use more memory. (default: false) WriteOnSuccess bool + NilToZero bool tags map[string]Tag vars map[string]any @@ -66,6 +67,12 @@ func (t Template) WithWriteOnSuccess(b bool) Template { return t } +// WithNilToZero enables or disables conversion of nil values to zero values. +func (t Template) WithNilToZero(b bool) Template { + t.NilToZero = true + return t +} + // Execute executes a parsed template and writes // the result to w. func (t Template) Execute(w io.Writer) error { @@ -147,6 +154,10 @@ func (t *Template) getEscapeHTML() bool { } } +func (t *Template) getNilToZero() bool { + return t.NilToZero || t.ns.NilToZero +} + func (t *Template) toString(v any) string { if h, ok := v.(HTML); ok { return string(h) @@ -334,14 +345,20 @@ func (t *Template) unwrapASTValue(node ast.Value, local map[string]any) (any, er return nil, err } + rval := reflect.ValueOf(v) + if node.Not { - rval := reflect.ValueOf(v) if rval.Kind() != reflect.Bool { return nil, ast.PosError(node, "%s: the ! operator can only be used on boolean values", valueToString(node)) } return !rval.Bool(), nil } + if rval.Kind() == reflect.Pointer && rval.IsNil() && t.getNilToZero() { + rtyp := rval.Type().Elem() + return reflect.New(rtyp).Interface(), nil + } + return v, err }