tpl

package
v2.0.0-...-ce7e00b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 3, 2026 License: MIT Imports: 18 Imported by: 1

README

tpl Library

The tpl library provides a simple yet powerful template rendering system for string interpolation. It allows you to replace variables in a template string with values from various data structures, supporting dot notation for accessing nested fields and array indexing.

Installation

import "github.com/getevo/evo/v2/lib/tpl"

Features

  • Simple Variable Substitution: Replace $variable placeholders with actual values
  • Dot Notation: Access nested fields with $object.field syntax
  • Array Indexing: Access array elements with $array[index] syntax
  • Nested Structures: Support for complex nested objects and arrays
  • Type Conversion: Automatic conversion of values to strings
  • Multiple Data Sources: Pass multiple objects as data sources

Usage Examples

Basic Usage
package main

import (
    "fmt"
    "github.com/getevo/evo/v2/lib/tpl"
)

func main() {
    // Simple template with variables
    template := "Hello, $name! Welcome to $app."
    
    // Render the template with a map of values
    result := tpl.Render(template, map[string]interface{}{
        "name": "John",
        "app":  "EVO Framework",
    })
    
    fmt.Println(result) // Output: Hello, John! Welcome to EVO Framework.
}
Using Structs and Nested Fields
package main

import (
    "fmt"
    "github.com/getevo/evo/v2/lib/tpl"
)

type User struct {
    FirstName string
    LastName  string
    Email     string
}

type App struct {
    Name    string
    Version string
}

func main() {
    // Template with dot notation for accessing struct fields
    template := "User: $user.FirstName $user.LastName ($user.Email)\nApp: $app.Name v$app.Version"
    
    // Create data structures
    user := User{
        FirstName: "Jane",
        LastName:  "Doe",
        Email:     "jane@example.com",
    }
    
    app := App{
        Name:    "EVO Framework",
        Version: "2.0.0",
    }
    
    // Render the template with multiple data sources
    result := tpl.Render(template, user, app)
    
    fmt.Println(result)
    // Output:
    // User: Jane Doe (jane@example.com)
    // App: EVO Framework v2.0.0
}
Working with Arrays and Complex Structures
package main

import (
    "fmt"
    "github.com/getevo/evo/v2/lib/tpl"
)

type Person struct {
    Name  string
    Email string
}

func main() {
    // Template with array indexing and nested structures
    template := "Message from: $sender[0].Name <$sender[0].Email>\n" +
                "To: $recipients[0], $recipients[1]\n" +
                "Subject: $metadata.subject\n" +
                "Sent at: $metadata.time.hour:$metadata.time.minute"
    
    // Create complex data structure
    data := map[string]interface{}{
        "sender": []Person{
            {Name: "John Smith", Email: "john@example.com"},
        },
        "recipients": []string{"alice@example.com", "bob@example.com"},
        "metadata": map[string]interface{}{
            "subject": "Meeting Reminder",
            "time": map[string]int{
                "hour":   14,
                "minute": 30,
            },
        },
    }
    
    // Render the template
    result := tpl.Render(template, data)
    
    fmt.Println(result)
    // Output:
    // Message from: John Smith <john@example.com>
    // To: alice@example.com, bob@example.com
    // Subject: Meeting Reminder
    // Sent at: 14:30
}
Multiple Data Sources
package main

import (
    "fmt"
    "github.com/getevo/evo/v2/lib/tpl"
)

func main() {
    // Template with variables from different sources
    template := "Hello, $user! Your account ($account) has $balance credits."
    
    // Define multiple data sources
    userData := map[string]string{
        "user": "Alice",
    }
    
    accountData := map[string]interface{}{
        "account": "A12345",
        "balance": 150,
    }
    
    // Render the template with multiple data sources
    // The function will check each source in order until it finds a match
    result := tpl.Render(template, userData, accountData)
    
    fmt.Println(result)
    // Output: Hello, Alice! Your account (A12345) has 150 credits.
}

How It Works

The tpl library uses a regular expression to find variables in the template string and replaces them with values from the provided data sources. The variable syntax is:

  • Simple variable: $variable
  • Nested field: $object.field
  • Array element: $array[index]
  • Combination: $array[index].field or $object.array[index]

When rendering a template, the library:

  1. Searches for variables in the template using a regular expression
  2. For each variable, it looks for a matching value in the provided data sources
  3. If a match is found, it converts the value to a string and replaces the variable
  4. If no match is found, it leaves the variable unchanged

The library supports multiple data sources, checking each one in order until it finds a match for a variable. This allows you to combine data from different sources in a single template.

For more detailed information, please refer to the source code and comments within the library.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ClearCache

func ClearCache()

ClearCache clears both the file and text template caches.

func Pairs

func Pairs(args ...any) map[string]any

Pairs converts a flat alternating key/value list into a map[string]any. Example: Pairs("name", "Alice", "age", 30) → map[string]any{"name":"Alice","age":30}

func RegisterFunc

func RegisterFunc(name string, fn any)

RegisterFunc registers a named function for use in templates. fn must be a function value of any signature. Arguments are coerced to the declared parameter types automatically. The return value is stringified. Functions may return one or two values; when two values are returned the last must implement error — a non-nil error suppresses any output.

A registered function can be used in three ways:

$fn(arg1, arg2)   — explicit call; args may be $variables or literals ("str", 42, 3.14)
$var|fn           — modifier: receives the variable's resolved value as first argument
$fn               — standalone: called with no arguments when name is not in params

func Render

func Render(src string, params ...any) string

Render compiles src and executes it with the given params.

func RenderFile

func RenderFile(path string, params ...any) string

RenderFile loads path and executes it with the given params.

func RenderText

func RenderText(src string, params ...any) string

RenderText compiles src and executes it with the given params. This is the engine-aware version of the existing Render() function.

func RenderWriter

func RenderWriter(w io.Writer, src string, params ...any)

RenderWriter compiles src and writes the rendered output to w.

func SetCacheSize

func SetCacheSize(n int)

SetCacheSize sets the maximum number of compiled templates to cache. Pass 0 to disable caching. If n is smaller than the current cache size, the cache is cleared.

Types

type ArrayLitExpr

type ArrayLitExpr struct{ Elems []Expr }

ArrayLitExpr is a literal array constructed in a code block: [expr, expr, ...]

type AssignStmt

type AssignStmt struct {
	Name string
	X    Expr
}

AssignStmt is $var = expr

type BinExpr

type BinExpr struct {
	Op   string
	L, R Expr
}

BinExpr is L op R

type BreakStmt

type BreakStmt struct{}

BreakStmt exits the nearest enclosing for loop.

type Builder

type Builder struct {
	// contains filtered or unexported fields
}

Builder is the fluent API for loading and rendering templates.

tpl.File("path/to/file.html").Set(ctx).Render()
tpl.Text("Hello $name!").Set(ctx).Render()

func File

func File(path string) *Builder

File loads a template from a file path. The compiled Engine is cached by path, and the cache entry is invalidated automatically when the file's modification time changes. Returns a Builder whose context is empty until Set() is called.

func Text

func Text(src string) *Builder

Text compiles a template from an inline string. The compiled Engine is cached by the full source string.

func (*Builder) Render

func (b *Builder) Render() string

Render executes the template and returns the rendered string.

func (*Builder) RenderWriter

func (b *Builder) RenderWriter(w io.Writer)

RenderWriter executes the template and writes the output to w.

func (*Builder) Set

func (b *Builder) Set(ctx any) *Builder

Set adds a context value (struct, map, or any value dot.Get can traverse). Multiple Set() calls are additive; the first match wins during lookup.

type CallExpr

type CallExpr struct {
	Name string
	Args []Expr
}

CallExpr is fn(arg1, arg2, ...)

type CaseClause

type CaseClause struct {
	Vals []Expr
	Body []Node
}

CaseClause is one arm of a switch statement. A single case may match multiple values: case "a", "b":

type CompoundAssignStmt

type CompoundAssignStmt struct {
	Name string
	Op   string // "+=", "-=", "*=", "/="
	X    Expr
}

CompoundAssignStmt is $var += expr / $var -= expr / $var *= expr / $var /= expr

type Context

type Context struct {
	// contains filtered or unexported fields
}

Context holds the execution state during template rendering. Scopes form a chain: each for/if block gets a child context.

func (*Context) Get

func (c *Context) Get(name string) (any, bool)

Get looks up a bare variable name (no dots or brackets). Checks scope chain first, then the original params.

func (*Context) GetIndex

func (c *Context) GetIndex(base any, idx any) any

GetIndex resolves a path that may include a dynamic variable index at the end. E.g. GetIndex("m", VarExpr{Path:"k"}) → m[value-of-k]

func (*Context) GetPath

func (c *Context) GetPath(path string) (any, bool)

GetPath resolves a full dotted/indexed path such as "user.Name" or "arr[0]".

func (*Context) Set

func (c *Context) Set(name string, val any)

Set assigns a variable. If the name already exists in an ancestor scope, it updates there; otherwise it creates it in the current scope.

type ContinueStmt

type ContinueStmt struct{}

ContinueStmt skips to the next iteration of the nearest enclosing for loop.

type EchoStmt

type EchoStmt struct{ X Expr }

EchoStmt outputs the value of X. echo $expr / print $expr

type Engine

type Engine struct {
	// contains filtered or unexported fields
}

Engine is a compiled template ready for repeated execution.

func CompileEngine

func CompileEngine(src string) *Engine

CompileEngine compiles src into an Engine.

func (*Engine) Execute

func (e *Engine) Execute(ctx *Context) string

Execute renders the Engine with the given context and returns the output.

func (*Engine) ExecuteWriter

func (e *Engine) ExecuteWriter(ctx *Context, w io.Writer)

ExecuteWriter renders into w.

type Expr

type Expr interface {
	// contains filtered or unexported methods
}

type ExprStmt

type ExprStmt struct{ X Expr }

ExprStmt evaluates X and outputs a non-nil result. Used for bare <? $name ?> and <? fn(args) ?>

type ForCNode

type ForCNode struct {
	Init Stmt // may be nil
	Cond Expr // nil → infinite loop
	Post Stmt // may be nil
	Body []Node
}

ForCNode is <? for($i=0; $i<10; $i++){ ?> body <? } ?> Also serves as a while loop when Init and Post are nil: for($cond){

type ForRangeNode

type ForRangeNode struct {
	Key  string // "" when only one variable
	Val  string
	Iter Expr
	Body []Node
}

ForRangeNode is <? for($key, $val := range $iter){ ?> body <? } ?>

type IfNode

type IfNode struct {
	Cond Expr
	Then []Node
	Else []Node // nil if no else
}

IfNode is <? if(cond){ ?> then <? }else{ ?> else <? } ?>

type IncDecExpr

type IncDecExpr struct {
	Name string
	Op   string // "++" or "--"
}

IncDecExpr is $var++ or $var-- used inside a larger expression.

type IncDecStmt

type IncDecStmt struct {
	Name string
	Op   string // "++" or "--"
}

IncDecStmt is $var++ or $var--

type IncludeNode

type IncludeNode struct {
	Path Expr
}

IncludeNode is <? require("path") ?> or <? include("path") ?>

type IsSetExpr

type IsSetExpr struct {
	Path string
}

IsSetExpr reports whether a variable path is defined in the context. Produced by isset($path) in code blocks.

type LitExpr

type LitExpr struct{ Val any }

LitExpr is a literal value: string, int64, float64, bool, or nil.

type MapLitExpr

type MapLitExpr struct {
	Keys []string
	Vals []Expr
}

MapLitExpr is a literal map constructed in a code block: {"key": val, "key2": val2}

type Node

type Node interface {
	// contains filtered or unexported methods
}

type Stmt

type Stmt interface {
	// contains filtered or unexported methods
}

type StmtsNode

type StmtsNode struct {
	// contains filtered or unexported fields
}

StmtsNode is a list of statements from one <? ... ?> code block.

type SwitchNode

type SwitchNode struct {
	Val     Expr
	Cases   []CaseClause
	Default []Node
}

SwitchNode is <? switch($val){ ?> cases <? } ?>

type TKind

type TKind uint8

TKind is a code-block token kind.

const (
	TkEOF       TKind = iota
	TkIdent           // bare identifier: echo, for, range, translate, …
	TkVar             // $name  (val holds the name without '$')
	TkString          // "…" or '…'  (lit holds the parsed string value)
	TkInt             // integer literal (lit holds int64)
	TkFloat           // float literal   (lit holds float64)
	TkOp              // any operator or punctuation stored as a string
	TkLParen          // (
	TkRParen          // )
	TkLBrace          // {
	TkRBrace          // }
	TkLBracket        // [
	TkRBracket        // ]
	TkComma           // ,
	TkSemicolon       // ;  (or newline acting as statement separator)
)

type Template

type Template struct {
	// contains filtered or unexported fields
}

Template is a pre-compiled template ready for repeated execution.

func Parse

func Parse(src string) *Template

Parse compiles src into a Template and caches the result up to the configured cache size.

func (*Template) Execute

func (t *Template) Execute(params ...any) string

Execute renders t with the given params and returns the result as a string.

func (*Template) WriteTo

func (t *Template) WriteTo(w io.Writer, params ...any)

WriteTo renders t into w.

type TernaryExpr

type TernaryExpr struct {
	Cond Expr
	Then Expr
	Else Expr
}

TernaryExpr is cond ? then : else

type TextNode

type TextNode struct {
	// contains filtered or unexported fields
}

TextNode is literal template text with $var placeholders pre-scanned.

type Token

type Token struct {
	Kind TKind
	Val  string // raw text
	Lit  any    // parsed value for TkString, TkInt, TkFloat
}

Token is one lexed unit from a code block.

type UnExpr

type UnExpr struct {
	Op string
	X  Expr
}

UnExpr is op X (e.g. !$flag, -$n)

type VarExpr

type VarExpr struct{ Path string }

VarExpr is a variable path: plain name, dotted, or indexed. Examples: "name", "user.Name", "arr[0]", "m[key]"

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL