go-sprout/sprout

View on GitHub
sprigin/sprig_backward_compatibility.go

Summary

Maintainability
A
0 mins
Test Coverage
package sprigin

import (
    htemplate "html/template"
    "log/slog"
    gostrings "strings"
    ttemplate "text/template"

    "github.com/go-sprout/sprout"
    "github.com/go-sprout/sprout/internal/runtime"
    "github.com/go-sprout/sprout/registry/backward"
    "github.com/go-sprout/sprout/registry/checksum"
    "github.com/go-sprout/sprout/registry/conversion"
    "github.com/go-sprout/sprout/registry/crypto"
    "github.com/go-sprout/sprout/registry/encoding"
    "github.com/go-sprout/sprout/registry/env"
    "github.com/go-sprout/sprout/registry/filesystem"
    "github.com/go-sprout/sprout/registry/maps"
    "github.com/go-sprout/sprout/registry/numeric"
    "github.com/go-sprout/sprout/registry/random"
    "github.com/go-sprout/sprout/registry/reflect"
    "github.com/go-sprout/sprout/registry/regexp"
    "github.com/go-sprout/sprout/registry/semver"
    "github.com/go-sprout/sprout/registry/slices"
    "github.com/go-sprout/sprout/registry/std"
    "github.com/go-sprout/sprout/registry/strings"
    "github.com/go-sprout/sprout/registry/time"
    "github.com/go-sprout/sprout/registry/uniqueid"
)

// BACKWARDS COMPATIBILITY
// The following functions are provided for backwards compatibility with the
// original sprig methods. They are not recommended for use in new code.
var bc_registerSprigFuncs = sprout.FunctionAliasMap{
    "dateModify":     []string{"date_modify"},                   // ! Deprecated: Should use dateModify instead
    "dateInZone":     []string{"date_in_zone"},                  // ! Deprecated: Should use dateInZone instead
    "mustDateModify": []string{"must_date_modify"},              // ! Deprecated: Should use mustDateModify instead
    "ellipsis":       []string{"abbrev"},                        // ! Deprecated: Should use ellipsis instead
    "ellipsisBoth":   []string{"abbrevboth"},                    // ! Deprecated: Should use ellipsisBoth instead
    "trimAll":        []string{"trimall"},                       // ! Deprecated: Should use trimAll instead
    "append":         []string{"push"},                          // ! Deprecated: Should use append instead
    "mustAppend":     []string{"mustPush"},                      // ! Deprecated: Should use mustAppend instead
    "list":           []string{"tuple"},                         // FIXME: with the addition of append/prepend these are no longer immutable.
    "max":            []string{"biggest"},                       // ! Deprecated: Should use max instead
    "toUpper":        []string{"upper", "toupper", "uppercase"}, // ! Deprecated: Should use toUpper instead
    "toLower":        []string{"lower", "tolower", "lowercase"}, // ! Deprecated: Should use toLower instead
    "add":            []string{"addf"},                          // ! Deprecated: Should use add instead
    "add1":           []string{"add1f"},                         // ! Deprecated: Should use add1 instead
    "sub":            []string{"subf"},                          // ! Deprecated: Should use sub instead
    "toTitleCase":    []string{"title", "titlecase"},            // ! Deprecated: Should use toTitleCase instead
    "toPascalCase":   []string{"camelcase"},                     // ! Deprecated: Should use toPascalCase instead
    "toSnakeCase":    []string{"snake", "snakecase"},            // ! Deprecated: Should use toSnakeCase instead
    "toKebabCase":    []string{"kebab", "kebabcase"},            // ! Deprecated: Should use toKebabCase instead
    "swapCase":       []string{"swapcase"},                      // ! Deprecated: Should use swapCase instead
    "base64Encode":   []string{"b64enc"},                        // ! Deprecated: Should use base64Encode instead
    "base64Decode":   []string{"b64dec"},                        // ! Deprecated: Should use base64Decode instead
    "base32Encode":   []string{"b32enc"},                        // ! Deprecated: Should use base32Encode instead
    "base32Decode":   []string{"b32dec"},                        // ! Deprecated: Should use base32Decode instead
    "pathBase":       []string{"base"},                          // ! Deprecated: Should use pathBase instead
    "pathDir":        []string{"dir"},                           // ! Deprecated: Should use pathDir instead
    "pathExt":        []string{"ext"},                           // ! Deprecated: Should use pathExt instead
    "pathClean":      []string{"clean"},                         // ! Deprecated: Should use pathClean instead
    "pathIsAbs":      []string{"isAbs"},                         // ! Deprecated: Should use pathIsAbs instead
    "expandEnv":      []string{"expandenv"},                     // ! Deprecated: Should use expandEnv instead
    "dateAgo":        []string{"ago"},                           // ! Deprecated: Should use dateAgo instead
    "strSlice":       []string{"toStrings"},                     // ! Deprecated: Should use strSlice instead
    "toInt":          []string{"int", "atoi"},                   // ! Deprecated: Should use toInt instead
    "toInt64":        []string{"int64"},                         // ! Deprecated: Should use toInt64 instead
    "toFloat64":      []string{"float64"},                       // ! Deprecated: Should use toFloat64 instead
    "toOctal":        []string{"toDecimal"},                     // ! Deprecated: Should use toOctal instead
}

// \ BACKWARDS COMPATIBILITY

// These functions are not guaranteed to evaluate to the same result for given input, because they
// refer to the environment or global state.
// FOR BACKWARDS COMPATIBILITY ONLY
var nonhermeticFunctions = []string{
    // Date functions
    "date",
    "dateInZone",
    "dateModify",
    "now",
    "htmlDate",
    "htmlDateInZone",

    // Strings
    "randAlphaNum",
    "randAlpha",
    "randAscii",
    "randNumeric",
    "randBytes",
    "uuidv4",

    // OS
    "env",
    "expandenv",

    // Network
    "getHostByName",
}

type SprigHandler struct {
    registries []sprout.Registry
    notices    []sprout.FunctionNotice

    funcsMap   sprout.FunctionMap
    funcsAlias sprout.FunctionAliasMap
}

func NewSprigHandler() *SprigHandler {
    return &SprigHandler{
        registries: make([]sprout.Registry, 0),
        funcsMap:   make(sprout.FunctionMap),
        funcsAlias: make(sprout.FunctionAliasMap),
    }
}

func (sh *SprigHandler) AddRegistry(registry sprout.Registry) error {
    sh.registries = append(sh.registries, registry)

    _ = registry.LinkHandler(sh)
    _ = registry.RegisterFunctions(sh.funcsMap)

    if regAlias, ok := registry.(sprout.RegistryWithAlias); ok {
        _ = regAlias.RegisterAliases(sh.funcsAlias)
    }

    if regNotice, ok := registry.(sprout.RegistryWithNotice); ok {
        _ = regNotice.RegisterNotices(&sh.notices)
    }

    return nil
}

func (sh *SprigHandler) AddRegistries(registries ...sprout.Registry) error {
    for _, registry := range registries {
        _ = sh.AddRegistry(registry)
    }
    return nil
}

func (sh *SprigHandler) Logger() *slog.Logger {
    return slog.New(slog.Default().Handler())
}

func (sh *SprigHandler) RawFunctions() sprout.FunctionMap {
    return sh.funcsMap
}

func (sh *SprigHandler) RawAliases() sprout.FunctionAliasMap {
    return sh.funcsAlias
}

func (sh *SprigHandler) Notices() []sprout.FunctionNotice {
    return sh.notices
}

func (sh *SprigHandler) Build() sprout.FunctionMap {
    _ = sh.AddRegistries(
        std.NewRegistry(),
        uniqueid.NewRegistry(),
        semver.NewRegistry(),
        backward.NewRegistry(),
        reflect.NewRegistry(),
        time.NewRegistry(),
        strings.NewRegistry(),
        random.NewRegistry(),
        checksum.NewRegistry(),
        conversion.NewRegistry(),
        numeric.NewRegistry(),
        encoding.NewRegistry(),
        regexp.NewRegistry(),
        slices.NewRegistry(),
        maps.NewRegistry(),
        crypto.NewRegistry(),
        filesystem.NewRegistry(),
        env.NewRegistry(),
    )

    // Register aliases for functions
    // BACKWARDS COMPATIBILITY
    // Register the sprig function aliases
    for originalFunction, aliases := range bc_registerSprigFuncs {
        for _, alias := range aliases {
            if fn, ok := sh.funcsMap[originalFunction]; ok {
                sh.funcsMap[alias] = fn
                sh.notices = append(sh.notices, *sprout.NewDeprecatedNotice(alias, "please use `"+originalFunction+"` instead"))
            }
        }
    }
    // \ BACKWARDS COMPATIBILITY

    sprout.AssignAliases(sh)
    sprout.AssignNotices(sh)

    // BACKWARDS COMPATIBILITY
    // Ensure error handling is consistent with sprig functions
    for funcName, fn := range sh.funcsMap {
        if !gostrings.HasPrefix(funcName, "must") {
            sh.funcsMap[funcName] = func(args ...any) (any, error) {
                out, _ := runtime.SafeCall(fn, args...)
                return out, nil
            }
        }
    }
    // \ BACKWARDS COMPATIBILITY

    return sh.funcsMap
}

// HermeticTxtFuncMap returns a 'text/template'.FuncMap with only repeatable functions.
// It provides backward compatibility with sprig.FuncMap and integrates
// additional configured functions.
// FOR BACKWARDS COMPATIBILITY ONLY
func HermeticTxtFuncMap() ttemplate.FuncMap {
    r := TxtFuncMap()
    for _, name := range nonhermeticFunctions {
        delete(r, name)
    }
    return r
}

// HermeticHtmlFuncMap returns an 'html/template'.Funcmap with only repeatable functions.
// It provides backward compatibility with sprig.FuncMap and integrates
// additional configured functions.
// FOR BACKWARDS COMPATIBILITY ONLY
func HermeticHtmlFuncMap() htemplate.FuncMap {
    r := HtmlFuncMap()
    for _, name := range nonhermeticFunctions {
        delete(r, name)
    }
    return r
}

// TxtFuncMap returns a 'text/template'.FuncMap
// It provides backward compatibility with sprig.FuncMap and integrates
// additional configured functions.
// FOR BACKWARDS COMPATIBILITY ONLY
func TxtFuncMap() ttemplate.FuncMap {
    return ttemplate.FuncMap(FuncMap())
}

// HtmlFuncMap returns an 'html/template'.Funcmap
// It provides backward compatibility with sprig.FuncMap and integrates
// additional configured functions.
// FOR BACKWARDS COMPATIBILITY ONLY
func HtmlFuncMap() htemplate.FuncMap {
    return htemplate.FuncMap(FuncMap())
}

// GenericFuncMap returns a copy of the basic function map as a map[string]any.
// It provides backward compatibility with sprig.FuncMap and integrates
// additional configured functions.
// FOR BACKWARDS COMPATIBILITY ONLY
func GenericFuncMap() map[string]any {
    return FuncMap()
}

// FuncMap returns a template.FuncMap for use with text/template or html/template.
// It provides backward compatibility with sprig.FuncMap and integrates
// additional configured functions.
// FOR BACKWARD COMPATIBILITY ONLY
func FuncMap() ttemplate.FuncMap {
    sprigHandler := NewSprigHandler()

    return sprigHandler.Build()
}