Migration from Sprig
Coming from Sprig and looking to use Sprout? You're in the right place for a complete guide on making the transition. This guideline will help you navigate the differences.
This page evolves with each version based on modifications and community feedback. Having trouble following this guide?
Open an issue to get help, and contribute to improving this guide for future users. 🌱 💜
Introduction
Sprout is a modern templating engine inspired by Sprig but with enhanced features and a more modular approach. Migrating from Sprig to Sprout involves understanding these differences and adjusting your templates and code accordingly.
Key Differences
1. Registry System
Sprig: Functions are globally available.
Sprout: Functions are grouped into registries for modularity. Each registry can be added to the handler as needed.
Migration Tip
List the registries needed for your project and register them with the handler. If you're unsure, you can safely register all built-in registries.
2. Handler and Function Management
Sprig: Functions are accessed directly.
Sprout: Functions are managed by a handler, allowing for better control over function availability, error handling, and logging.
Migration Top
Nothing to do, using the new handler is enough.
3. Error Handling
Sprig: Limited and inconsistent error handling, with some functions causing panics (see Panicking Functions), and not fully adhering to Go template standards.
Sprout: Offers configurable error handling strategies, including returning default values, triggering panics, or using error channels, providing a more consistent and flexible approach.
Migration Tip
Set your preferred error handling strategy using WithErrHandling
when creating your handler.
4. Function Aliases
Sprig: Functions are accessed by a single name, deprecated functions are duplicated in code.
Sprout: Supports function aliases, allowing multiple names for the same function.
Migration Tip
Use WithAlias
or WithAliases
to set up function aliases as needed when creating your handler.
5. Following the Go Template Convention
Sprig: No error for naming convention are followed.
Sprout: Design to adhere closely to Go's native template conventions, ensuring compatibility and a consistent experience for developers familiar with Go templates. This adherence helps reduce surprises and ensures that templates behave as expected according to Go's standard practices.
Migration Tip Takes a look over renamed functions to change it in your template or use aliases.
How to Transition
Step 1: Identify and Organize Functions
Review your existing templates and identify the functions you rely on from Sprig. Determine whether these functions have direct equivalents in Sprout or if they require using the sprigin
package for backward compatibility.
Step 2: Refactor Templates
Update your templates to replace Sprig function calls with their Sprout equivalents. If a direct replacement is unavailable, consider using aliases or the sprigin
package to maintain functionality.
Step 3: Register Functions and Handlers
Set up your Sprout environment by creating a handler and registering the necessary function registries. This step ensures that your templates have access to the required functions.
Step 4: Test and Validate
Thoroughly test your migrated templates to ensure that all functions behave as expected. Pay particular attention to error handling and any deprecated functions that may require adjustments.
How to Transition for your end-users
You use sprig or sprout for end-users and want to migrate ? A complete guide will be write here soon.
You need more information now, contact maintainers or open a discussion on the repository.
Migrating Common Functions
Many functions in Sprig have direct equivalents in Sprout, but they might be organized differently or require registration in a handler.
Example: Simple Function Migration
Sprig:
Sprout:
Example: Using Aliases
Sprig:
Sprout:
You can continue to use the same function name inside your template
Panicking Functions
In Sprig, errors within certain functions cause a panic. In contrast, Sprout opts for returning nil or an empty value, improving safety and predictability.
Old Behavior (Sprig): Triggers a panic on error
New Behavior (Sprout): Returns nil or an empty value on error
Methods that previously caused a panic in Sprig :
DeepCopy
MustDeepCopy
ToRawJson
Append
Prepend
Concat
Chunk
Uniq
Compact
Slice
Without
Rest
Initial
Reverse
First
Last
Has
Dig
RandAlphaNumeric
RandAlpha
RandAscii
RandNumeric
RandBytes
Function-Specific Changes
MustDeepCopy
Sprig: Accepts
nil
input, causing an internal panic.Sprout: Returns
nil
if input isnil
, avoiding panic.
Rand Functions
Sprig: Causes an internal panic if the length parameter is zero.
Sprout: Returns an empty string if the length is zero, ensuring stability.
DateAgo
Sprig: Does not support int32 and *time.Time; returns "0s".
Sprout: Supports int32 and *time.Time and returns the correct duration.
DateRound
Sprig: Returns a corrected duration in positive form, even for negative inputs.
Sprout: Accurately returns the duration, preserving the sign of the input.
Base32Decode / Base64Decode
Sprig: Decoding functions return the error string when the input is not a valid base64 encoded string.
Sprout: Decoding functions return an empty string if the input is not a valid base64 encoded string, simplifying error handling.
Dig
Consider the example dictionary defined as follows:
Sprig: Previously, the
dig
function would return the last map in the access chain.
Sprout: Now, the
dig
function returns the final object in the chain, regardless of its type (map, array, string, etc.).
ToCamelCase / ToPascalCase
Sprig: The
toCamelCase
return value are in PascalCase. NotoPascalCase
function is available.Sprout: The
toCamelCase
function returns camelCase strings, while thetoPascalCase
function returns PascalCase strings.
Merge / MergeOverwrite
Sprig: The
merge
andmergeOverwrite
functions does dereferencing when second value are the default golang value (example:0
for int).Sprout: The
merge
andmergeOverwrite
functions does not dereference and keep the second value as is (example:0
for int).
Deprecated Features
Sprout has deprecated certain features for better security and performance. For example, direct cryptographic operations in templates are discouraged.
Migration Tip
Review your template functions and avoid using deprecated features. Move critical operations outside of templates to maintain security.
Perform cryptographic operations (listed in crypto
package) outside of templates.
All deprecated features are flagged with //! DEPRECATED
in codebase.
A complete list will be available here when the v1 of Sprout are released.
Conclusion
Migrating from Sprig to Sprout offers significant benefits, including improved error handling, modular function management, and enhanced compatibility with modern Go practices. While the sprigin
package provides a bridge for backward compatibility, fully embracing Sprout’s native capabilities will lead to a more stable and maintainable codebase. For further details on Sprout’s features and API, consult the official Sprout documentation.
Last updated