mjingo

package module
v0.0.0-...-2bc3700 Latest Latest
Warning

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

Go to latest
Published: Sep 30, 2023 License: Apache-2.0 Imports: 29 Imported by: 0

README

mjingo PkgGoDev

Package mjingo provides a template engine for Go which is based on the syntax and behavior of MiniJinja template engine for Rust. MiniJinja is based on the syntax and behavior of Jinja2 template engine for Python.

See MiniJinja document https://docs.rs/minijinja/latest/minijinja/ for syntax, builtin filters, tests or functions.

NOTE: mjingo is in early development and APIs are subjective to change.

Documentation

Overview

Package mjingo provides a template engine for Go which is based on the syntax and behavior of MiniJinja template engine for Rust. MiniJinja is based on the syntax and behavior of Jinja2 template engine for Python.

See MiniJinja document https://docs.rs/minijinja/latest/minijinja/ for syntax, builtin filters, tests or functions.

Index

Examples

Constants

This section is empty.

Variables

View Source
var DefaultSyntax = Syntax{
	BlockStart:    "{%",
	BlockEnd:      "%}",
	VariableStart: "{{",
	VariableEnd:   "}}",
	CommentStart:  "{#",
	CommentEnd:    "#}",
}

DefaultSyntax is the default delimiter configuration for the environment and the parser.

Functions

func ConvertVariadicArgsToGoValue

func ConvertVariadicArgsToGoValue[S ~[]E, E ScalarTypes](args []Value) (S, error)

ConvertVariadicArgsToGoValue converts the variadic arguments to a Go value of type S.

Types

type AutoEscape

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

AutoEscape controls the autoescaping behavior.

var AutoEscapeHTML AutoEscape

AutoEscapeHTML use HTML auto escaping rules.

Any value will be converted into a string and the following characters will be escaped in ways compatible to XML and HTML: `<`, `>`, `&`, `"`, `'`, and `/`.

var AutoEscapeJSON AutoEscape

AutoEscapeJSON use escaping rules suitable for JSON/JavaScript or YAML.

Any value effectively ends up being serialized to JSON upon printing. The serialized values will be compatible with JavaScript and YAML as well.

var AutoEscapeNone AutoEscape

AutoEscapeNone do not apply auto escaping.

func DefaultAutoEscapeCallback

func DefaultAutoEscapeCallback(name string) AutoEscape

DefaultAutoEscapeCallback is the default logic for auto escaping based on file extension.

  • AutoEscapeHTML: `.html`, `.htm`, `.xml`
  • AutoEscapeJSON: `.json`, `.json5`, `.js`, `.yaml`, `.yml`
  • AutoEscapeNone: all others

type AutoEscapeFunc

type AutoEscapeFunc func(name string) AutoEscape

AutoEscapeFunc is the type of the function called by an Environment to determine the escaping behavior for the template of the specified name.

type BoxedFilter

type BoxedFilter = func(*State, []Value) (Value, error)

BoxedFilter is the type of a boxed filter.

A boxed filter can be registered as a filter to the environment via Environment.AddFilter.

A boxed filter can be created by wrapping a "unboxed" filter using one of BoxedFilterFrom* function. Or a user can define a boxed filter directly. In that case, ConvertArgToGoValue and ConvertVariadicArgsToGoValue can be used to convert a Value to Go's data type.

func BoxedFilterFromFixedArity1ArgNoErrFunc

func BoxedFilterFromFixedArity1ArgNoErrFunc[A JustOneArgTypes, R RetValTypes](f func(A) R) BoxedFilter

BoxedFilterFromFixedArity1ArgNoErrFunc creates a boxed function which wraps f.

func BoxedFilterFromFixedArity1ArgWithErrFunc

func BoxedFilterFromFixedArity1ArgWithErrFunc[A JustOneArgTypes, R RetValTypes](f func(A) (R, error)) BoxedFilter

BoxedFilterFromFixedArity1ArgWithErrFunc creates a boxed function which wraps f.

func BoxedFilterFromFixedArity2ArgNoErrFunc

func BoxedFilterFromFixedArity2ArgNoErrFunc[A FirstArgTypes, B FixedArityLastArgTypes, R RetValTypes](f func(A, B) R) BoxedFilter

BoxedFilterFromFixedArity2ArgNoErrFunc creates a boxed function which wraps f.

func BoxedFilterFromFixedArity2ArgWithErrFunc

func BoxedFilterFromFixedArity2ArgWithErrFunc[A FirstArgTypes, B FixedArityLastArgTypes, R RetValTypes](f func(A, B) (R, error)) BoxedFilter

BoxedFilterFromFixedArity2ArgWithErrFunc creates a boxed function which wraps f.

func BoxedFilterFromFixedArity3ArgNoErrFunc

func BoxedFilterFromFixedArity3ArgNoErrFunc[A FirstArgTypes, B MiddleArgTypes, C FixedArityLastArgTypes, R RetValTypes](f func(A, B, C) R) BoxedFilter

BoxedFilterFromFixedArity3ArgNoErrFunc creates a boxed function which wraps f.

func BoxedFilterFromFixedArity3ArgWithErrFunc

func BoxedFilterFromFixedArity3ArgWithErrFunc[A FirstArgTypes, B MiddleArgTypes, C FixedArityLastArgTypes, R RetValTypes](f func(A, B, C) (R, error)) BoxedFilter

BoxedFilterFromFixedArity3ArgWithErrFunc creates a boxed function which wraps f.

func BoxedFilterFromFixedArity4ArgNoErrFunc

func BoxedFilterFromFixedArity4ArgNoErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D FixedArityLastArgTypes, R RetValTypes](f func(A, B, C, D) R) BoxedFilter

BoxedFilterFromFixedArity4ArgNoErrFunc creates a boxed function which wraps f.

func BoxedFilterFromFixedArity4ArgWithErrFunc

func BoxedFilterFromFixedArity4ArgWithErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D FixedArityLastArgTypes, R RetValTypes](f func(A, B, C, D) (R, error)) BoxedFilter

BoxedFilterFromFixedArity4ArgWithErrFunc creates a boxed function which wraps f.

func BoxedFilterFromFixedArity5ArgNoErrFunc

func BoxedFilterFromFixedArity5ArgNoErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D MiddleArgTypes, E FixedArityLastArgTypes, R RetValTypes](f func(A, B, C, D, E) R) BoxedFilter

BoxedFilterFromFixedArity5ArgNoErrFunc creates a boxed function which wraps f.

func BoxedFilterFromFixedArity5ArgWithErrFunc

func BoxedFilterFromFixedArity5ArgWithErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D MiddleArgTypes, E FixedArityLastArgTypes, R RetValTypes](f func(A, B, C, D, E) (R, error)) BoxedFilter

BoxedFilterFromFixedArity5ArgWithErrFunc creates a boxed function which wraps f.

func BoxedFilterFromFuncReflect

func BoxedFilterFromFuncReflect(fn any) BoxedFilter

BoxedFilterFromFuncReflect creates a boxed filter which wraps f using Go's reflect package.

This may be slower so caller should prefer generic BoxedFilterFrom* functions.

func BoxedFilterFromVariadic1ArgNoErrFunc

func BoxedFilterFromVariadic1ArgNoErrFunc[A VariadicArgElemTypes, R RetValTypes](f func(...A) R) BoxedFilter

BoxedFilterFromVariadic1ArgNoErrFunc creates a boxed function which wraps f.

func BoxedFilterFromVariadic1ArgWithErrFunc

func BoxedFilterFromVariadic1ArgWithErrFunc[A VariadicArgElemTypes, R RetValTypes](f func(...A) (R, error)) BoxedFilter

BoxedFilterFromVariadic1ArgWithErrFunc creates a boxed function which wraps f.

func BoxedFilterFromVariadic2ArgNoErrFunc

func BoxedFilterFromVariadic2ArgNoErrFunc[A FirstArgTypes, B VariadicArgElemTypes, R RetValTypes](f func(A, ...B) R) BoxedFilter

BoxedFilterFromVariadic2ArgNoErrFunc creates a boxed function which wraps f.

func BoxedFilterFromVariadic2ArgWithErrFunc

func BoxedFilterFromVariadic2ArgWithErrFunc[A FirstArgTypes, B VariadicArgElemTypes, R RetValTypes](f func(A, ...B) (R, error)) BoxedFilter

BoxedFilterFromVariadic2ArgWithErrFunc creates a boxed function which wraps f.

func BoxedFilterFromVariadic3ArgNoErrFunc

func BoxedFilterFromVariadic3ArgNoErrFunc[A FirstArgTypes, B MiddleArgTypes, C VariadicArgElemTypes, R RetValTypes](f func(A, B, ...C) R) BoxedFilter

BoxedFilterFromVariadic3ArgNoErrFunc creates a boxed function which wraps f.

func BoxedFilterFromVariadic3ArgWithErrFunc

func BoxedFilterFromVariadic3ArgWithErrFunc[A FirstArgTypes, B MiddleArgTypes, C VariadicArgElemTypes, R RetValTypes](f func(A, B, ...C) (R, error)) BoxedFilter

BoxedFilterFromVariadic3ArgWithErrFunc creates a boxed function which wraps f.

func BoxedFilterFromVariadic4ArgNoErrFunc

func BoxedFilterFromVariadic4ArgNoErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D VariadicArgElemTypes, R RetValTypes](f func(A, B, C, ...D) R) BoxedFilter

BoxedFilterFromVariadic4ArgNoErrFunc creates a boxed function which wraps f.

func BoxedFilterFromVariadic4ArgWithErrFunc

func BoxedFilterFromVariadic4ArgWithErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D VariadicArgElemTypes, R RetValTypes](f func(A, B, C, ...D) (R, error)) BoxedFilter

BoxedFilterFromVariadic4ArgWithErrFunc creates a boxed function which wraps f.

func BoxedFilterFromVariadic5ArgNoErrFunc

func BoxedFilterFromVariadic5ArgNoErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D MiddleArgTypes, E VariadicArgElemTypes, R RetValTypes](f func(A, B, C, D, ...E) R) BoxedFilter

BoxedFilterFromVariadic5ArgNoErrFunc creates a boxed function which wraps f.

func BoxedFilterFromVariadic5ArgWithErrFunc

func BoxedFilterFromVariadic5ArgWithErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D MiddleArgTypes, E VariadicArgElemTypes, R RetValTypes](f func(A, B, C, D, ...E) (R, error)) BoxedFilter

BoxedFilterFromVariadic5ArgWithErrFunc creates a boxed function which wraps f.

type BoxedFunc

type BoxedFunc = func(*State, []Value) (Value, error)

BoxedFunc is the type of a boxed function.

A boxed function can be registered as global functions to the environment via Environment.AddFunction.

A boxed function can be created by wrapping a "unboxed" function using one of BoxedFuncFrom* function. Or a user can define a boxed function directly. In that case, ConvertArgToGoValue and ConvertVariadicArgsToGoValue can be used to convert a Value to Go's data type.

func BoxedFuncFromFixedArity1ArgNoErrFunc

func BoxedFuncFromFixedArity1ArgNoErrFunc[A JustOneArgTypes, R RetValTypes](f func(A) R) BoxedFunc

BoxedFuncFromFixedArity1ArgNoErrFunc creates a boxed function which wraps f.

func BoxedFuncFromFixedArity1ArgWithErrFunc

func BoxedFuncFromFixedArity1ArgWithErrFunc[A JustOneArgTypes, R RetValTypes](f func(A) (R, error)) BoxedFunc

BoxedFuncFromFixedArity1ArgWithErrFunc creates a boxed function which wraps f.

func BoxedFuncFromFixedArity2ArgNoErrFunc

func BoxedFuncFromFixedArity2ArgNoErrFunc[A FirstArgTypes, B FixedArityLastArgTypes, R RetValTypes](f func(A, B) R) BoxedFunc

BoxedFuncFromFixedArity2ArgNoErrFunc creates a boxed function which wraps f.

func BoxedFuncFromFixedArity2ArgWithErrFunc

func BoxedFuncFromFixedArity2ArgWithErrFunc[A FirstArgTypes, B FixedArityLastArgTypes, R RetValTypes](f func(A, B) (R, error)) BoxedFunc

BoxedFuncFromFixedArity2ArgWithErrFunc creates a boxed function which wraps f.

func BoxedFuncFromFixedArity3ArgNoErrFunc

func BoxedFuncFromFixedArity3ArgNoErrFunc[A FirstArgTypes, B MiddleArgTypes, C FixedArityLastArgTypes, R RetValTypes](f func(A, B, C) R) BoxedFunc

BoxedFuncFromFixedArity3ArgNoErrFunc creates a boxed function which wraps f.

func BoxedFuncFromFixedArity3ArgWithErrFunc

func BoxedFuncFromFixedArity3ArgWithErrFunc[A FirstArgTypes, B MiddleArgTypes, C FixedArityLastArgTypes, R RetValTypes](f func(A, B, C) (R, error)) BoxedFunc

BoxedFuncFromFixedArity3ArgWithErrFunc creates a boxed function which wraps f.

func BoxedFuncFromFixedArity4ArgNoErrFunc

func BoxedFuncFromFixedArity4ArgNoErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D FixedArityLastArgTypes, R RetValTypes](f func(A, B, C, D) R) BoxedFunc

BoxedFuncFromFixedArity4ArgNoErrFunc creates a boxed function which wraps f.

func BoxedFuncFromFixedArity4ArgWithErrFunc

func BoxedFuncFromFixedArity4ArgWithErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D FixedArityLastArgTypes, R RetValTypes](f func(A, B, C, D) (R, error)) BoxedFunc

BoxedFuncFromFixedArity4ArgWithErrFunc creates a boxed function which wraps f.

func BoxedFuncFromFixedArity5ArgNoErrFunc

func BoxedFuncFromFixedArity5ArgNoErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D MiddleArgTypes, E FixedArityLastArgTypes, R RetValTypes](f func(A, B, C, D, E) R) BoxedFunc

BoxedFuncFromFixedArity5ArgNoErrFunc creates a boxed function which wraps f.

func BoxedFuncFromFixedArity5ArgWithErrFunc

func BoxedFuncFromFixedArity5ArgWithErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D MiddleArgTypes, E FixedArityLastArgTypes, R RetValTypes](f func(A, B, C, D, E) (R, error)) BoxedFunc

BoxedFuncFromFixedArity5ArgWithErrFunc creates a boxed function which wraps f.

func BoxedFuncFromFuncReflect

func BoxedFuncFromFuncReflect(fn any) BoxedFunc

BoxedFuncFromFuncReflect creates a boxed function which wraps f using Go's reflect package.

This may be slower so caller should prefer generic BoxedFuncFrom* functions.

func BoxedFuncFromVariadic1ArgNoErrFunc

func BoxedFuncFromVariadic1ArgNoErrFunc[A VariadicArgElemTypes, R RetValTypes](f func(...A) R) BoxedFunc

BoxedFuncFromVariadic1ArgNoErrFunc creates a boxed function which wraps f.

func BoxedFuncFromVariadic1ArgWithErrFunc

func BoxedFuncFromVariadic1ArgWithErrFunc[A VariadicArgElemTypes, R RetValTypes](f func(...A) (R, error)) BoxedFunc

BoxedFuncFromVariadic1ArgWithErrFunc creates a boxed function which wraps f.

func BoxedFuncFromVariadic2ArgNoErrFunc

func BoxedFuncFromVariadic2ArgNoErrFunc[A FirstArgTypes, B VariadicArgElemTypes, R RetValTypes](f func(A, ...B) R) BoxedFunc

BoxedFuncFromVariadic2ArgNoErrFunc creates a boxed function which wraps f.

func BoxedFuncFromVariadic2ArgWithErrFunc

func BoxedFuncFromVariadic2ArgWithErrFunc[A FirstArgTypes, B VariadicArgElemTypes, R RetValTypes](f func(A, ...B) (R, error)) BoxedFunc

BoxedFuncFromVariadic2ArgWithErrFunc creates a boxed function which wraps f.

func BoxedFuncFromVariadic3ArgNoErrFunc

func BoxedFuncFromVariadic3ArgNoErrFunc[A FirstArgTypes, B MiddleArgTypes, C VariadicArgElemTypes, R RetValTypes](f func(A, B, ...C) R) BoxedFunc

BoxedFuncFromVariadic3ArgNoErrFunc creates a boxed function which wraps f.

func BoxedFuncFromVariadic3ArgWithErrFunc

func BoxedFuncFromVariadic3ArgWithErrFunc[A FirstArgTypes, B MiddleArgTypes, C VariadicArgElemTypes, R RetValTypes](f func(A, B, ...C) (R, error)) BoxedFunc

BoxedFuncFromVariadic3ArgWithErrFunc creates a boxed function which wraps f.

func BoxedFuncFromVariadic4ArgNoErrFunc

func BoxedFuncFromVariadic4ArgNoErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D VariadicArgElemTypes, R RetValTypes](f func(A, B, C, ...D) R) BoxedFunc

BoxedFuncFromVariadic4ArgNoErrFunc creates a boxed function which wraps f.

func BoxedFuncFromVariadic4ArgWithErrFunc

func BoxedFuncFromVariadic4ArgWithErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D VariadicArgElemTypes, R RetValTypes](f func(A, B, C, ...D) (R, error)) BoxedFunc

BoxedFuncFromVariadic4ArgWithErrFunc creates a boxed function which wraps f.

func BoxedFuncFromVariadic5ArgNoErrFunc

func BoxedFuncFromVariadic5ArgNoErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D MiddleArgTypes, E VariadicArgElemTypes, R RetValTypes](f func(A, B, C, D, ...E) R) BoxedFunc

BoxedFuncFromVariadic5ArgNoErrFunc creates a boxed function which wraps f.

func BoxedFuncFromVariadic5ArgWithErrFunc

func BoxedFuncFromVariadic5ArgWithErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D MiddleArgTypes, E VariadicArgElemTypes, R RetValTypes](f func(A, B, C, D, ...E) (R, error)) BoxedFunc

BoxedFuncFromVariadic5ArgWithErrFunc creates a boxed function which wraps f.

type BoxedTest

type BoxedTest = func(*State, []Value) (bool, error)

BoxedTest is the type of a boxed test.

A boxed test can be registered as test functions to the environment via Environment.AddTest.

A boxed test can be created by wrapping a "unboxed" test using one of BoxedTextFrom* function. Or a user can define a boxed test directly. In that case, ConvertArgToGoValue and ConvertVariadicArgsToGoValue can be used to convert a Value to Go's data type.

func BoxedTestFromFixedArity1ArgNoErrFunc

func BoxedTestFromFixedArity1ArgNoErrFunc[A JustOneArgTypes](f func(A) bool) BoxedTest

BoxedTestFromFixedArity1ArgNoErrFunc creates a boxed function which wraps f.

func BoxedTestFromFixedArity1ArgWithErrFunc

func BoxedTestFromFixedArity1ArgWithErrFunc[A JustOneArgTypes](f func(A) (bool, error)) BoxedTest

BoxedTestFromFixedArity1ArgWithErrFunc creates a boxed function which wraps f.

func BoxedTestFromFixedArity2ArgNoErrFunc

func BoxedTestFromFixedArity2ArgNoErrFunc[A FirstArgTypes, B FixedArityLastArgTypes](f func(A, B) bool) BoxedTest

BoxedTestFromFixedArity2ArgNoErrFunc creates a boxed function which wraps f.

func BoxedTestFromFixedArity2ArgWithErrFunc

func BoxedTestFromFixedArity2ArgWithErrFunc[A FirstArgTypes, B FixedArityLastArgTypes](f func(A, B) (bool, error)) BoxedTest

BoxedTestFromFixedArity2ArgWithErrFunc creates a boxed function which wraps f.

func BoxedTestFromFixedArity3ArgNoErrFunc

func BoxedTestFromFixedArity3ArgNoErrFunc[A FirstArgTypes, B MiddleArgTypes, C FixedArityLastArgTypes](f func(A, B, C) bool) BoxedTest

BoxedTestFromFixedArity3ArgNoErrFunc creates a boxed function which wraps f.

func BoxedTestFromFixedArity3ArgWithErrFunc

func BoxedTestFromFixedArity3ArgWithErrFunc[A FirstArgTypes, B MiddleArgTypes, C FixedArityLastArgTypes](f func(A, B, C) (bool, error)) BoxedTest

BoxedTestFromFixedArity3ArgWithErrFunc creates a boxed function which wraps f.

func BoxedTestFromFixedArity4ArgNoErrFunc

func BoxedTestFromFixedArity4ArgNoErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D FixedArityLastArgTypes](f func(A, B, C, D) bool) BoxedTest

BoxedTestFromFixedArity4ArgNoErrFunc creates a boxed function which wraps f.

func BoxedTestFromFixedArity4ArgWithErrFunc

func BoxedTestFromFixedArity4ArgWithErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D FixedArityLastArgTypes](f func(A, B, C, D) (bool, error)) BoxedTest

BoxedTestFromFixedArity4ArgWithErrFunc creates a boxed function which wraps f.

func BoxedTestFromFixedArity5ArgNoErrFunc

func BoxedTestFromFixedArity5ArgNoErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D MiddleArgTypes, E FixedArityLastArgTypes](f func(A, B, C, D, E) bool) BoxedTest

BoxedTestFromFixedArity5ArgNoErrFunc creates a boxed function which wraps f.

func BoxedTestFromFixedArity5ArgWithErrFunc

func BoxedTestFromFixedArity5ArgWithErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D MiddleArgTypes, E FixedArityLastArgTypes](f func(A, B, C, D, E) (bool, error)) BoxedTest

BoxedTestFromFixedArity5ArgWithErrFunc creates a boxed function which wraps f.

func BoxedTestFromFuncReflect

func BoxedTestFromFuncReflect(fn any) BoxedTest

BoxedTestFromFuncReflect creates a boxed test which wraps f using Go's reflect package.

This may be slower so caller should prefer generic BoxedTestFrom* functions.

func BoxedTestFromVariadic1ArgNoErrFunc

func BoxedTestFromVariadic1ArgNoErrFunc[A VariadicArgElemTypes](f func(...A) bool) BoxedTest

BoxedTestFromVariadic1ArgNoErrFunc creates a boxed function which wraps f.

func BoxedTestFromVariadic1ArgWithErrFunc

func BoxedTestFromVariadic1ArgWithErrFunc[A VariadicArgElemTypes](f func(...A) (bool, error)) BoxedTest

BoxedTestFromVariadic1ArgWithErrFunc creates a boxed function which wraps f.

func BoxedTestFromVariadic2ArgNoErrFunc

func BoxedTestFromVariadic2ArgNoErrFunc[A FirstArgTypes, B VariadicArgElemTypes](f func(A, ...B) bool) BoxedTest

BoxedTestFromVariadic2ArgNoErrFunc creates a boxed function which wraps f.

func BoxedTestFromVariadic2ArgWithErrFunc

func BoxedTestFromVariadic2ArgWithErrFunc[A FirstArgTypes, B VariadicArgElemTypes](f func(A, ...B) (bool, error)) BoxedTest

BoxedTestFromVariadic2ArgWithErrFunc creates a boxed function which wraps f.

func BoxedTestFromVariadic3ArgNoErrFunc

func BoxedTestFromVariadic3ArgNoErrFunc[A FirstArgTypes, B MiddleArgTypes, C VariadicArgElemTypes](f func(A, B, ...C) bool) BoxedTest

BoxedTestFromVariadic3ArgNoErrFunc creates a boxed function which wraps f.

func BoxedTestFromVariadic3ArgWithErrFunc

func BoxedTestFromVariadic3ArgWithErrFunc[A FirstArgTypes, B MiddleArgTypes, C VariadicArgElemTypes](f func(A, B, ...C) (bool, error)) BoxedTest

BoxedTestFromVariadic3ArgWithErrFunc creates a boxed function which wraps f.

func BoxedTestFromVariadic4ArgNoErrFunc

func BoxedTestFromVariadic4ArgNoErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D VariadicArgElemTypes](f func(A, B, C, ...D) bool) BoxedTest

BoxedTestFromVariadic4ArgNoErrFunc creates a boxed function which wraps f.

func BoxedTestFromVariadic4ArgWithErrFunc

func BoxedTestFromVariadic4ArgWithErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D VariadicArgElemTypes](f func(A, B, C, ...D) (bool, error)) BoxedTest

BoxedTestFromVariadic4ArgWithErrFunc creates a boxed function which wraps f.

func BoxedTestFromVariadic5ArgNoErrFunc

func BoxedTestFromVariadic5ArgNoErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D MiddleArgTypes, E VariadicArgElemTypes](f func(A, B, C, D, ...E) bool) BoxedTest

BoxedTestFromVariadic5ArgNoErrFunc creates a boxed function which wraps f.

func BoxedTestFromVariadic5ArgWithErrFunc

func BoxedTestFromVariadic5ArgWithErrFunc[A FirstArgTypes, B MiddleArgTypes, C MiddleArgTypes, D MiddleArgTypes, E VariadicArgElemTypes](f func(A, B, C, D, ...E) (bool, error)) BoxedTest

BoxedTestFromVariadic5ArgWithErrFunc creates a boxed function which wraps f.

type CallMethoder

type CallMethoder interface {
	// CallMethod is called when the engine tries to call a method on the object.
	//
	// It's the responsibility of the implementer to ensure that an
	// error is generated if an invalid method is invoked.
	//
	// To convert the arguments into arguments use the
	// ConvertArgToGoValue or ConvertVariadicArgsToGoValue function.
	CallMethod(state *State, name string, args []Value) (Value, error)
}

CallMethoder is implemented by any value that has CallMethod method.

type Caller

type Caller interface {
	// Call is called when the object is invoked directly.
	//
	// To convert the arguments into arguments use the
	// ConvertArgToGoValue or ConvertVariadicArgsToGoValue function.
	Call(state *State, args []Value) (Value, error)
}

Caller is implemented by any value that has Call method.

type Environment

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

Environment is an abstraction that holds the engine configuration.

This object holds the central configuration state for templates. It is also the container for all loaded templates.

The environment holds references to the source the templates were created from. This makes it very inconvenient to pass around unless the templates are static strings.

There are generally two ways to construct an environment:

  • NewEnvironment creates an environment preconfigured with sensible defaults. It will contain all built-in filters, tests and globals as well as a callback for auto escaping based on file extension.
  • NewEnvironmentEmpty creates a completely blank environment.

func NewEnvironment

func NewEnvironment() *Environment

NewEnvironment creates a new environment with sensible defaults.

This environment does not yet contain any templates but it will have all the default filters, tests and globals loaded. If you do not want any default configuration you can use the alternative NewEnvironmentEmpty method.

func NewEnvironmentEmpty

func NewEnvironmentEmpty() *Environment

NewEnvironmentEmpty creates a completely empty environment.

This environment has no filters, no templates, no globals and no default logic for auto escaping configured.

func (*Environment) AddFilter

func (e *Environment) AddFilter(name string, filter BoxedFilter, aliases ...string)

AddFilter adds a new filter function.

Example
package main

import (
	"fmt"
	"log"
	"strings"

	"github.com/hnakamur/mjingo"
)

func main() {
	slugify := func(value string) string {
		return strings.Join(strings.Split(strings.ToLower(value), " "), "-")
	}

	env := mjingo.NewEnvironment()
	env.AddFilter("slugify", mjingo.BoxedFilterFromFuncReflect(slugify))
	const templateName = "test.txt"
	err := env.AddTemplate(templateName, `{{ title|slugify }}`)
	if err != nil {
		log.Fatal(err)
	}
	tpl, err := env.GetTemplate(templateName)
	if err != nil {
		log.Fatal(err)
	}
	context := mjingo.ValueFromGoValue(map[string]string{"title": "this is my page"})
	got, err := tpl.Render(context)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(got)
}
Output:

this-is-my-page

func (*Environment) AddFunction

func (e *Environment) AddFunction(name string, fn BoxedFunc, aliases ...string)

AddFunction adds a new global function.

func (*Environment) AddGlobal

func (e *Environment) AddGlobal(name string, val Value)

AddGlobal adds a new global variable.

func (*Environment) AddTemplate

func (e *Environment) AddTemplate(name, source string) error

AddTemplate loads a template from a string into the environment.

The `name` parameter defines the name of the template which identifies it. To look up a loaded template use the Environment.GetTemplate method.

Note that there are situations where the interface of this method is too restrictive as you need to hold on to the strings for the lifetime of the environment.

func (*Environment) AddTest

func (e *Environment) AddTest(name string, test BoxedTest, aliases ...string)

AddTest adds a new test function.

Test functions are similar to filters but perform a check on a value where the return value is always true or false.

func (*Environment) ClearTemplates

func (e *Environment) ClearTemplates()

ClearTemplates removes all stored templates.

This method is mainly useful when combined with a loader as it causes the loader to "reload" templates. By calling this method one can trigger a reload.

func (*Environment) CompileExpression

func (e *Environment) CompileExpression(expr string) (*Expression, error)

CompileExpression compiles an expression.

This lets one compile an expression in the template language and receive the output. This lets one use the expressions of the language be used as a minimal scripting language. For more information and an example see Expression.

func (*Environment) Debug

func (e *Environment) Debug() bool

Debug returns the current value of the debug flag.

func (*Environment) GetTemplate

func (e *Environment) GetTemplate(name string) (*Template, error)

GetTemplate fetches a template by name.

This requires that the template has been loaded with Environment.AddTemplate beforehand. If the template was not loaded an error of kind TemplateNotFound is returned. If a loaded was added to the engine this can also dynamically load templates.

func (*Environment) KeepTrailingNewline

func (e *Environment) KeepTrailingNewline() bool

KeepTrailingNewline returns the value of the trailing newline preservation flag.

func (*Environment) RemoveFilter

func (e *Environment) RemoveFilter(name string)

RemoveFilter removes a filter by name.

func (*Environment) RemoveGlobal

func (e *Environment) RemoveGlobal(name string)

RemoveGlobal a global function or variable by name.

func (*Environment) RemoveTemplate

func (e *Environment) RemoveTemplate(name string)

RemoveTemplate removes a template by name.

func (*Environment) RemoveTest

func (e *Environment) RemoveTest(name string)

RemoveTest removes a test by name.

func (*Environment) RenderNamedStr

func (e *Environment) RenderNamedStr(name, source string, ctx Value) (string, error)

RenderNamedStr parses and renders a template from a string in one go with name.

Like Environment.RenderStr, but provide a name for the template to be used instead of the default `<string>`. This is an alias for Environment.TemplateFromNamedStr paired with [Environment.Render].

func (*Environment) RenderStr

func (e *Environment) RenderStr(source string, ctx Value) (string, error)

RenderStr parses and renders a template from a string in one go.

In some cases you really only need a template to be rendered once from a string and returned. The internal name of the template is `<string>`.

This is an alias for Environment.TemplateFromStr paired with [Environment.Render].

func (*Environment) SetAutoEscapeCallback

func (e *Environment) SetAutoEscapeCallback(fn AutoEscapeFunc)

SetAutoEscapeCallback sets a new function to select the default auto escaping.

This function is invoked when templates are loaded from the environment to determine the default auto escaping behavior. The function is invoked with the name of the template and can make an initial auto escaping decision based on that. The default implementation DefaultAutoEscapeCallback. turn on escaping depending on the file extension.

func (*Environment) SetDebug

func (e *Environment) SetDebug(enabled bool)

SetDebug enables or disables the debug mode.

When the debug mode is enabled the engine will dump out some of the execution state together with the source information of the executing template when an error is created. The cost of this is relatively high as the data including the template source is cloned.

When this is enabled templates will print debug information with source context when the error is printed.

func (*Environment) SetKeepTrailingNewline

func (e *Environment) SetKeepTrailingNewline(yes bool)

SetKeepTrailingNewline preserve the trailing newline when rendering templates.

The default is `false`, which causes a single newline, if present, to be stripped from the end of the template.

func (*Environment) SetLoader

func (e *Environment) SetLoader(f LoadFunc)

SetLoader registers a template loader as source of templates.

When a template loader is registered, the environment gains the ability to dynamically load templates. The loader is invoked with the name of the template. If this template exists the template source has to be returned, if the template does not exist an Error created with NewErrorNotFound has to be returned. Once a template has been loaded it's stored on the environment. This means the loader is only invoked once per template name.

For loading templates from the file system, you can use the PathLoader function.

func (*Environment) SetUndefinedBehavior

func (e *Environment) SetUndefinedBehavior(behavior UndefinedBehavior)

SetUndefinedBehavior changes the undefined behavior.

This changes the runtime behavior of Undefined values in the template engine. For more information see UndefinedBehavior. The default is UndefinedBehaviorLenient.

func (*Environment) TemplateFromNamedStr

func (e *Environment) TemplateFromNamedStr(name, source string) (*Template, error)

TemplateFromNamedStr loads a template from a string.

In some cases you really only need to work with (eg: render) a template to be rendered once only.

func (*Environment) TemplateFromStr

func (e *Environment) TemplateFromStr(source string) (*Template, error)

TemplateFromStr loads a template from a string, with name `<string>`.

This is a shortcut to Environment.TemplateFromNamedStr with name set to `<string>`.

func (*Environment) UndefinedBehavior

func (e *Environment) UndefinedBehavior() UndefinedBehavior

UndefinedBehavior returns the current undefined behavior.

This is particularly useful if a filter function or similar wants to change its behavior with regards to undefined values.

type Error

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

Error represents template errors.

If debug mode is enabled a template error contains additional debug information that can be displayed by formatting an error with the alternative formatting (DebugString()). That information is also shown for the [DebugString] display where the extended information is hidden when the alternative formatting is used.

Since mjingo takes advantage of chained errors it's recommended to render the entire chain to better understand the causes.

func NewError

func NewError(kind ErrorKind, detail string) *Error

NewError creates a new Error with kind and detail.

func NewErrorNotFound

func NewErrorNotFound(name string) *Error

NewErrorNotFound creates a new Error with TemplateNotFound kind.

func (*Error) Error

func (e *Error) Error() string

func (*Error) Format

func (e *Error) Format(f fmt.State, verb rune)

Format implements fmt.Formatter.

func (*Error) Kind

func (e *Error) Kind() ErrorKind

Kind returns the error kind

func (*Error) SupportsCustomVerb

func (*Error) SupportsCustomVerb(verb rune) bool

SupportRustFormat implements rustfmt.Formatter.

type ErrorKind

type ErrorKind int

ErrorKind describes the error kind.

const (
	// NonPrimitive represents a non primitive value was encountered where one was expected.
	NonPrimitive ErrorKind = 1

	// InvalidOperation is an invalid operation was attempted.
	InvalidOperation ErrorKind = 3
	// SyntaxError represents the template has a syntax error
	SyntaxError ErrorKind = 4
	// TemplateNotFound represents a template was not found.
	TemplateNotFound ErrorKind = 5
	// TooManyArguments represents too many arguments were passed to a function.
	TooManyArguments ErrorKind = 6
	// MissingArgument represents a expected argument was missing
	MissingArgument ErrorKind = 7
	// UnknownFilter represents a filter is unknown
	UnknownFilter ErrorKind = 8
	// UnknownTest represents A test is unknown
	UnknownTest ErrorKind = 9
	// UnknownFunction represents a function is unknown
	UnknownFunction ErrorKind = 10
	// UnknownMethod represents an unknown method was called
	UnknownMethod ErrorKind = 11
	// BadEscape represents a bad escape sequence in a string was encountered.
	BadEscape ErrorKind = 12
	// UndefinedError represents an operation on an undefined value was attempted.
	UndefinedError ErrorKind = 13
	// BadSerialization represents not able to serialize this
	BadSerialization ErrorKind = 14

	// BadInclude represents an error happened in an include.
	BadInclude ErrorKind = 16
	// EvalBlock represents an error happened in a super block.
	EvalBlock ErrorKind = 17
	// CannotUnpack represents unable to unpack a value.
	CannotUnpack ErrorKind = 18

	// InvalidDelimiter represents error creating aho-corasick delimiters
	InvalidDelimiter ErrorKind = 21
	// UnknownBlock represents an unknown block was called
	UnknownBlock ErrorKind = 22
)

func (ErrorKind) String

func (k ErrorKind) String() string

type Expression

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

Expression represents a compiled expression.

An expression is created via the Environment.CompileExpression method. It provides a method to evaluate the expression and return the result as value object. This for instance can be used to evaluate simple expressions from user provided input to implement features such as dynamic filtering.

func (*Expression) Eval

func (e *Expression) Eval(root Value) (Value, error)

Eval evaluates the expression with some context value.

The result of the expression is returned as Value.

type FirstArgTypes

type FirstArgTypes interface {
	ScalarTypes | OptionalTypes | SliceTypes | *State
}

FirstArgTypes is the type constraint for the first argument of an unboxed filter, test or function which has two or more arguments.

type FixedArityLastArgTypes

type FixedArityLastArgTypes interface {
	ScalarTypes | OptionalTypes | SliceTypes | Kwargs
}

FixedArityLastArgTypes is the type constraint for the last argument of a fixed-ary (non-variadic) unboxed filter, test or function which has two or more arguments.

type I128

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

I128 represents an integer in the range between -170141183460469231731687303715884105728 and 170141183460469231731687303715884105727 (both ends inclusive). The zero value for an I128 represents the value 0.

Operations always take pointer arguments (*I128) rather than I128 values, and each unique Int value requires its own unique *I128 pointer. To "copy" an I128 value, an existing (or newly allocated) I128 must be set to a new value using the I128.Set method; shallow copies of I128s are not supported and may lead to errors.

Note that methods may leak the I128's value through timing side-channels. Because of this and because of the scope and complexity of the implementation, I128 is not well-suited to implement cryptographic operations.

func I128FromInt64

func I128FromInt64(x int64) *I128

I128FromInt64 allocates and returns a new I128 set to x.

func I128FromUint64

func I128FromUint64(x uint64) *I128

I128FromUint64 allocates and returns a new I128 set to x.

func I128TryFromBigInt

func I128TryFromBigInt(x *big.Int) (*I128, error)

I128TryFromBigInt allocates and returns a new I128 set to x. If x is out of range of I128, it returns an error.

func (*I128) BigInt

func (x *I128) BigInt() big.Int

BigInt returns a new big.Int whose value is copied from x.

func (*I128) CheckedAbs

func (z *I128) CheckedAbs(x *I128) *I128

CheckedAbs sets z to |x| (the absolute value of x) and returns z. If the operation overflows, the value of z is undefined but the returned value is nil.

func (*I128) CheckedAdd

func (z *I128) CheckedAdd(x, y *I128) *I128

CheckedAdd sets z to the sum x+y and returns z if the result is in the range of I128. If the operation overflows, the value of z is undefined but the returned value is nil.

func (*I128) CheckedDiv

func (z *I128) CheckedDiv(x, y *I128) *I128

CheckedDiv sets sets z to the quotient x/y and returns z if y != 0 and the result is in the range of I128. If the operation overflows, the value of z is undefined but the returned value is nil. Div implements Euclidean division (unlike Go); see math/big.Int.DivMod for more details.

func (*I128) CheckedMod

func (z *I128) CheckedMod(x, y *I128) *I128

CheckedMod sets sets z to the modulus x%y and returns z if y != 0 and the result is in the range of I128. If the operation overflows, the value of z is undefined but the returned value is nil. Mod implements Euclidean modulus (unlike Go); see math/big.Int.DivMod for more details.

func (*I128) CheckedMul

func (z *I128) CheckedMul(x, y *I128) *I128

CheckedMul sets z to the product x*y and returns z if the result is in the range of I128. If the operation overflows, the value of z is undefined but the returned value is nil.

func (*I128) CheckedNeg

func (z *I128) CheckedNeg(x *I128) *I128

CheckedNeg sets z to -x and returns z if the result is in the range of I128. If the operation overflows, the value of z is undefined but the returned value is nil.

func (*I128) CheckedSub

func (z *I128) CheckedSub(x, y *I128) *I128

CheckedSub sets z to the difference x-y and returns z if the result is in the range of I128. If the operation overflows, the value of z is undefined but the returned value is nil.

func (*I128) Cmp

func (x *I128) Cmp(y *I128) int

Cmp compares x and y and returns:

-1 if x <  y
 0 if x == y
+1 if x >  y

func (I128) Format

func (x I128) Format(f fmt.State, _ rune)

Format implements fmt.Formatter.

func (*I128) Int64

func (x *I128) Int64() int64

Int64 returns the int64 representation of x. If x cannot be represented in an int64, the result is undefined.

func (*I128) IsInt64

func (x *I128) IsInt64() bool

IsInt64 reports whether x can be represented as an int64.

func (*I128) IsUint64

func (x *I128) IsUint64() bool

IsUint64 reports whether x can be represented as a uint64.

func (*I128) Set

func (z *I128) Set(x *I128) *I128

Set sets z to x and returns z.

func (*I128) SetInt64

func (z *I128) SetInt64(x int64) *I128

SetInt64 sets z to x and returns z.

func (*I128) SetString

func (z *I128) SetString(s string, base int) (*I128, bool)

SetString sets z to the value of s, interpreted in the given base, and returns z and a boolean indicating success. The entire string (not just a prefix) must be valid for success. If SetString fails, the value of z is undefined but the returned value is nil.

The base argument must be 0 or a value between 2 and MaxBase. For base 0, the number prefix determines the actual base: A prefix of “0b” or “0B” selects base 2, “0”, “0o” or “0O” selects base 8, and “0x” or “0X” selects base 16. Otherwise, the selected base is 10 and no prefix is accepted.

For bases <= 36, lower and upper case letters are considered the same: The letters 'a' to 'z' and 'A' to 'Z' represent digit values 10 to 35. For bases > 36, the upper case letters 'A' to 'Z' represent the digit values 36 to 61.

For base 0, an underscore character “_” may appear between a base prefix and an adjacent digit, and between successive digits; such underscores do not change the value of the number. Incorrect placement of underscores is reported as an error if there are no other errors. If base != 0, underscores are not recognized and act like any other character that is not a valid digit.

If the input is out of range of I128, SetString fails.

func (*I128) SetUint64

func (z *I128) SetUint64(x uint64) *I128

SetUint64 sets z to x and returns z.

func (*I128) String

func (x *I128) String() string

String returns the decimal representation of x in base 10.

func (*I128) Uint64

func (x *I128) Uint64() uint64

Uint64 returns the uint64 representation of x. If x cannot be represented in a uint64, the result is undefined.

type JustOneArgTypes

type JustOneArgTypes interface {
	ScalarTypes | OptionalTypes | SliceTypes | *State | Kwargs
}

JustOneArgTypes is the type constraint for the argument of an unboxed filter, test, or function which has just one argument.

type Kwargs

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

Kwargs is the utility to accept keyword arguments.

Keyword arguments are represented as regular values as the last argument in an argument list. This can be quite complex to use manually so this type is added as a utility. You can use Kwargs.GetValue to fetch a single keyword argument and then use Kwargs.AssertAllUsed to make sure extra arguments create an error.

func (*Kwargs) AssertAllUsed

func (a *Kwargs) AssertAllUsed() error

AssertAllUsed asserts that all kwargs were used.

func (*Kwargs) GetValue

func (a *Kwargs) GetValue(key string) option.Option[Value]

GetValue gets a single argument from the kwargs and marks it as used. The caller can convert a Value to a Go value with [ValueTryToGoValue].

func (*Kwargs) PeekValue

func (a *Kwargs) PeekValue(key string) option.Option[Value]

PeekValue gets a single argument from the kwargs but don't mark it as used. The caller can convert a Value to a Go value with [ValueTryToGoValue].

type LoadFunc

type LoadFunc func(name string) (string, error)

LoadFunc is the type of the function called when the engine is loading a template. A Error created with NewErrorNotFound should be returned when the template is not found.

Example
package main

import (
	"errors"
	"fmt"
	"io/fs"
	"log"
	"os"
	"path/filepath"
	"strings"

	"github.com/hnakamur/mjingo"
)

// PathLoader is a helper to load templates from a given directory.
//
// This creates a dynamic loader which looks up templates in the
// given directory.  This loader allows templates that start with a dot (`.`)
// or are contained in a folder starting with a dot.
//
// The name argument of the returned LoadFunc can contain `/` as a path separator
// (even on Windows).
// If name contains `\`, an [Error] with [TemplateNotFound] kind will be returned
// from the returned LoadFunc.
func MyPathLoader(dir string) mjingo.LoadFunc {
	return func(name string) (string, error) {
		segments := strings.Split(name, "/")
		for _, segment := range segments {
			if strings.Contains(segment, `\`) {
				return "", mjingo.NewErrorNotFound(name)
			}
		}
		if os.PathSeparator != '/' {
			name = strings.Join(segments, string(os.PathSeparator))
		}
		path := filepath.Join(dir, name)
		data, err := os.ReadFile(path)
		if err != nil {
			if errors.Is(err, fs.ErrNotExist) {
				return "", mjingo.NewErrorNotFound(name)
			}
			return "", err
		}
		return string(data), nil
	}
}

func main() {
	dir, err := os.MkdirTemp("", "mjingo-test")
	if err != nil {
		log.Fatal(err)
	}
	defer os.RemoveAll(dir)

	const templateSubdir = "subdir"
	const templateName = templateSubdir + "/hello.j2"
	if err := os.MkdirAll(filepath.Join(dir, templateSubdir), 0o700); err != nil {
		log.Fatal(err)
	}
	if err := os.WriteFile(filepath.Join(dir, templateName), []byte("Hello {{ name }}"), 0o600); err != nil {
		log.Fatal(err)
	}

	env := mjingo.NewEnvironment()
	env.SetLoader(MyPathLoader(dir))
	tpl, err := env.GetTemplate(templateName)
	if err != nil {
		log.Fatal(err)
	}
	ctx := mjingo.ValueFromGoValue(map[string]string{"name": "John"})
	got, err := tpl.Render(ctx)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(got)
}
Output:

Hello John

func PathLoader

func PathLoader(dir string) LoadFunc

PathLoader is a helper to load templates from a given directory.

This creates a dynamic loader which looks up templates in the given directory. Templates that start with a dot (`.`) or are contained in a folder starting with a dot cannot be loaded.

The name argument of the returned LoadFunc can contain `/` as a path separator (even on Windows). If name contains `\`, an Error with TemplateNotFound kind will be returned from the returned LoadFunc.

type MiddleArgTypes

type MiddleArgTypes interface {
	ScalarTypes | OptionalTypes | SliceTypes
}

MiddleArgTypes is the type constraint for the middle (which is neither the first nor the last) argument of an unboxed filter, test or function which has three or more arguments.

type Object

type Object interface {
	// Kind describes the kind of an object.
	Kind() ObjectKind
}

Object is implemented by a dynamic object.

The engine uses the Value type to represent values that the engine knows about. Most of these values are primitives such as integers, strings or maps. However it is also possible to expose custom types without undergoing a serialization step to the engine. For this to work a type needs to implement the Object interface and be wrapped in a value with ValueFromObject.

Objects need to implement String() method which is used by the engine to convert the object into a string if needed. Additionally DebugString() is required as well.

The exact runtime characteristics of the object are influenced by the [Kind] of the object. By default an object can just be stringified and methods can be called.

For examples of how to implement objects refer to SeqObject and StructObject.

Example
package main

import (
	"fmt"
	"log"
	"sync/atomic"

	"github.com/hnakamur/mjingo"
	"github.com/hnakamur/mjingo/option"
)

type Cycler struct {
	values []mjingo.Value
	idx    atomic.Uint64
}

var _ mjingo.Object = ((*Cycler)(nil))
var _ mjingo.Caller = ((*Cycler)(nil))

func (s *Cycler) Kind() mjingo.ObjectKind { return mjingo.ObjectKindPlain }

func (s *Cycler) Call(_state *mjingo.State, _args []mjingo.Value) (mjingo.Value, error) {
	idx := int(s.idx.Add(1))
	return s.values[idx%len(s.values)], nil
}

func makeCycler(_state *mjingo.State, args []mjingo.Value) (mjingo.Value, error) {
	return mjingo.ValueFromGoValue(&Cycler{
		values: args,
		idx:    atomic.Uint64{},
	}), nil
}

type Magic struct{}

var _ mjingo.Object = ((*Magic)(nil))
var _ mjingo.CallMethoder = ((*Magic)(nil))

func (s *Magic) Kind() mjingo.ObjectKind { return mjingo.ObjectKindPlain }

func (s *Magic) CallMethod(state *mjingo.State, name string, args []mjingo.Value) (mjingo.Value, error) {
	if name != "make_class" {
		return mjingo.Value{}, mjingo.NewError(mjingo.UnknownMethod,
			fmt.Sprintf("object has no method named %s!!!", name))
	}

	// single string argument
	tag, args, err := mjingo.ConvertArgToGoValue[string](state, args)
	if err != nil {
		return mjingo.Value{}, err
	}
	return mjingo.ValueFromGoValue(fmt.Sprintf("magic-%s", tag)), nil
}

type SimpleDynamicSec struct{}

var _ mjingo.Object = ((*SimpleDynamicSec)(nil))
var _ mjingo.SeqObject = ((*SimpleDynamicSec)(nil))

func (s *SimpleDynamicSec) Kind() mjingo.ObjectKind { return mjingo.ObjectKindSeq }

func (s *SimpleDynamicSec) GetItem(idx uint) option.Option[mjingo.Value] {
	if idx >= s.ItemCount() {
		return option.None[mjingo.Value]()
	}
	return option.Some(mjingo.ValueFromGoValue([]string{"a", "b", "c", "d"}[idx]))
}

func (s *SimpleDynamicSec) ItemCount() uint { return 4 }

const templateSource = `{%- with next_class = cycler(["odd", "even"]) %}
<ul class="{{ magic.make_class("ul") }}">
{%- for char in seq %}
  <li class={{ next_class() }}>{{ char }}</li>
{%- endfor %}
</ul>
{%- endwith %}`

func main() {
	env := mjingo.NewEnvironment()
	const templateName = "test.html"
	env.AddFunction("cycler", mjingo.BoxedFuncFromFuncReflect(makeCycler))
	env.AddGlobal("magic", mjingo.ValueFromGoValue(&Magic{}))
	env.AddGlobal("seq", mjingo.ValueFromGoValue(&SimpleDynamicSec{}))
	err := env.AddTemplate(templateName, templateSource)
	if err != nil {
		log.Fatal(err)
	}
	tpl, err := env.GetTemplate(templateName)
	if err != nil {
		log.Fatal(err)
	}
	context := mjingo.ValueFromGoValue(map[string]string{"title": "this is my page"})
	got, err := tpl.Render(context)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(got)
}
Output:

<ul class="magic-ul">
  <li class=even>a</li>
  <li class=odd>b</li>
  <li class=even>c</li>
  <li class=odd>d</li>
</ul>

type ObjectKind

type ObjectKind uint

ObjectKind defines the object's behavior.

When a dynamic Object is implemented, it can be of one of the kinds here. The default behavior will be a ObjectKindPlain object which doesn't do much other than that it can be printed. For an object to turn into a StructObject or SeqObject the necessary kind has to be returned with a pointer to itself.

Today object's can have the behavior of structs and sequences but this might expand in the future. It does mean that not all types of values can be represented by objects.

const (
	// ObjectKindPlain is a kind for a plain object.
	//
	// Such an object has no attributes but it might be callable and it
	// can be stringified.  When serialized it's serialized in it's
	// stringified form.
	ObjectKindPlain ObjectKind = iota + 1

	//ObjectKindSeq is a kind for a sequence.
	//
	// Requires that the object implements [SeqObject].
	ObjectKindSeq

	// ObjectKindStruct is a kind for a struct (map with string keys).
	//
	// Requires that the object implements [StructObject].
	ObjectKindStruct
)

type OptionalTypes

OptionalTypes is the type constraint for an optional argument of an unboxed filter, test, or a function.

type RetValTypes

type RetValTypes interface {
	ScalarTypes | SliceTypes
}

RetValTypes is the type constraint for the return value of an unboxed filter or function.

type ScalarTypes

type ScalarTypes interface {
	Value | bool | uint8 | uint16 | uint32 | uint64 | uint |
		int8 | int16 | int32 | int64 | int | I128 | U128 |
		float32 | float64 | string
}

ScalarTypes is the type constraint for a scalar argument of an unboxed filter, test, or a function.

type SeqObject

type SeqObject interface {
	// GetItem looks up an item by index.
	//
	// Sequences should provide a value for all items in the range of `0..ItemCount`
	// but the engine will assume that items within the range are `Undefined`
	// if `None` is returned.
	GetItem(idx uint) option.Option[Value]

	// ItemCount returns the number of items in the sequence.
	ItemCount() uint
}

SeqObject provides the behavior of an Object holding sequence of values.

An object holding a sequence of values (tuple, list etc.) can be represented by this interface.

type SliceTypes

type SliceTypes interface {
	[]Value | []bool | []uint8 | []uint16 | []uint32 | []uint64 | []uint |
		[]int8 | []int16 | []int32 | []int64 | []int | []I128 | []U128 |
		[]float32 | []float64 | []string
}

ScalarTypes is the type constraint for a slice argument of an unboxed filter, test, or a function.

type State

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

State provides access to the current execution state of the engine.

A read only reference is passed to filter functions and similar objects to allow limited interfacing with the engine. The state is useful to look up information about the engine in filter, test or global functions. It not only provides access to the template environment but also the context variables of the engine, the current auto escaping behavior as well as the auto escape flag.

In some testing scenarios or more advanced use cases you might need to get a State. The state is managed as part of the template execution but the initial state can be retrieved via [Template.NewState]. The most common way to get hold of the state however is via functions of filters.

func (*State) AutoEscape

func (s *State) AutoEscape() AutoEscape

AutoEscape returns the current value of the auto escape flag.

func (*State) Env

func (s *State) Env() *Environment

Env returns a reference to the current environment.

func (*State) Name

func (s *State) Name() string

Name returns the name of the current template.

func (*State) RenderBlock

func (s *State) RenderBlock(block string) (string, error)

RenderBlock renders a block with the given name into a string.

This method works like Template.Render but it only renders a specific block in the template. The first argument is the name of the block.

Note that rendering a block is a stateful operation. If an error is returned the module has to be re-created as the internal state can end up corrupted. This also means you can only render blocks if you have a mutable reference to the state which is not possible from within filters or similar.

func (*State) UndefinedBehavior

func (s *State) UndefinedBehavior() UndefinedBehavior

UndefinedBehavior returns the current undefined behavior.

type StructObject

type StructObject interface {
	// GetField is nvoked by the engine to get a field of a struct.
	//
	// Where possible it's a good idea for this to align with the return value
	// of [StructObject.Fields] but it's not necessary.
	//
	// If an field does not exist, `None` shall be returned.
	//
	// A note should be made here on side effects: unlike calling objects or
	// calling methods on objects, accessing fields is not supposed to
	// have side effects.  Neither does this API get access to the interpreter
	// [State] nor is there a channel to send out failures as only an option
	// can be returned.  If you do plan on doing something in field access
	// that is fallible, instead use a method call.
	GetField(name string) option.Option[Value]

	// StaticFields if possible returns a static vector of field names.
	//
	// If fields cannot be statically determined, then this must return `None`
	// and [StructObject.Fields] should be implemented instead.  If however
	// this method is implemented, then [StructObject.Fields] should be
	// implemented to return nil.
	StaticFields() option.Option[[]string]

	// Fields returns a vector of field names.
	//
	// This should be implemented if [StructObject.StaticFields] cannot
	// be implemented due to lifetime restrictions.
	Fields() []string
}

StructObject provides the behavior of an Object holding a struct.

An basic object with the shape and behavior of a struct (that means a map with string keys) can be represented by this interface.

Struct As context

Structs can also be used as template rendering context. This has a lot of benefits as it means that the serialization overhead can be largely to completely avoided. This means that even if templates take hundreds of values, MiniJinja does not spend time eagerly converting them into values.

Here is a very basic example of how a template can be rendered with a dynamic context. Note that the implementation of [StructObject.Fields] is optional for this to work. It's in fact not used by the engine during rendering but it is necessary for the DebugString() function to be able to show which values exist in the context.

type Syntax

type Syntax struct {
	BlockStart    string
	BlockEnd      string
	VariableStart string
	VariableEnd   string
	CommentStart  string
	CommentEnd    string
}

Syntax is the delimiter configuration for the environment and the parser.

mjingo allows you to override the syntax configuration for templates by setting different delimiters. The end markers can be shared, but the start markers need to be distinct. It would thus not be valid to configure `{{` to be the marker for both variables and blocks.

type Template

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

Template represents a template.

Templates are stored in the Environment as bytecode instructions. With the Environment.GetTemplate method that is looked up and returned in form of this handle. Such a template can be cheaply copied as it only holds references.

To render the Template.Render method can be used.

func (*Template) EvalToState

func (t *Template) EvalToState(context Value) (*State, error)

EvalToState evaluates the template into a [`State`].

This evaluates the template, discards the output and returns the final `State` for introspection. From there global variables or blocks can be accessed. What this does is quite similar to how the engine interally works with tempaltes that are extended or imported from.

func (*Template) Render

func (t *Template) Render(context Value) (string, error)

Render renders the template into a string.

The provided value is used as the initial context for the template. It can be any Value.

For very large contexts and to avoid the overhead of serialization of potentially unused values, you might consider using a dynamic StructObject as value.

type U128

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

U128 represents an integer in the range between 0 and 340282366920938463463374607431768211455 (both ends inclusive). The zero value for an U128 represents the value 0.

Operations always take pointer arguments (*U128) rather than U128 values, and each unique Int value requires its own unique *U128 pointer. To "copy" an U128 value, an existing (or newly allocated) U128 must be set to a new value using the U128.Set method; shallow copies of U128s are not supported and may lead to errors.

Note that methods may leak the U128's value through timing side-channels. Because of this and because of the scope and complexity of the implementation, U128 is not well-suited to implement cryptographic operations.

func U128FromUint64

func U128FromUint64(x uint64) *U128

U128FromUint64 allocates and returns a new U128 set to x.

func U128TryFromBigInt

func U128TryFromBigInt(x *big.Int) (*U128, error)

U128TryFromBigInt allocates and returns a new U128 set to x. If x is out of range of U128, it returns an error.

func U128TryFromInt64

func U128TryFromInt64(x int64) (*U128, error)

U128TryFromInt64 allocates and returns a new U128 set to x. If x is out of range of U128, it returns an error.

func (*U128) BigInt

func (x *U128) BigInt() big.Int

BigInt returns a new big.Int whose value is copied from x.

func (*U128) Cmp

func (x *U128) Cmp(y *U128) int

Cmp compares x and y and returns:

-1 if x <  y
 0 if x == y
+1 if x >  y

func (U128) Format

func (x U128) Format(f fmt.State, _ rune)

Format implements fmt.Formatter.

func (*U128) Int64

func (x *U128) Int64() int64

Int64 returns the int64 representation of x. If x cannot be represented in an int64, the result is undefined.

func (*U128) IsInt64

func (x *U128) IsInt64() bool

IsInt64 reports whether x can be represented as an int64.

func (*U128) IsUint64

func (x *U128) IsUint64() bool

IsUint64 reports whether x can be represented as a uint64.

func (*U128) Set

func (z *U128) Set(x *U128) *U128

Set sets z to x and returns z.

func (*U128) SetString

func (z *U128) SetString(s string, base int) (*U128, bool)

SetString sets z to the value of s, interpreted in the given base, and returns z and a boolean indicating success. The entire string (not just a prefix) must be valid for success. If SetString fails, the value of z is undefined but the returned value is nil.

The base argument must be 0 or a value between 2 and MaxBase. For base 0, the number prefix determines the actual base: A prefix of “0b” or “0B” selects base 2, “0”, “0o” or “0O” selects base 8, and “0x” or “0X” selects base 16. Otherwise, the selected base is 10 and no prefix is accepted.

For bases <= 36, lower and upper case letters are considered the same: The letters 'a' to 'z' and 'A' to 'Z' represent digit values 10 to 35. For bases > 36, the upper case letters 'A' to 'Z' represent the digit values 36 to 61.

For base 0, an underscore character “_” may appear between a base prefix and an adjacent digit, and between successive digits; such underscores do not change the value of the number. Incorrect placement of underscores is reported as an error if there are no other errors. If base != 0, underscores are not recognized and act like any other character that is not a valid digit.

If the input is out of range of U128, SetString fails.

func (*U128) String

func (x *U128) String() string

String returns the decimal representation of x in base 10.

func (*U128) Uint64

func (x *U128) Uint64() uint64

Uint64 returns the uint64 representation of x. If x cannot be represented in a uint64, the result is undefined.

type UndefinedBehavior

type UndefinedBehavior uint

UndefinedBehavior defines the behavior of undefined values in the engine.

At present there are three types of behaviors available which mirror the behaviors that Jinja2 provides out of the box.

const (
	// UndefinedBehaviorLenient is the default, somewhat lenient undefined behavior.
	//
	// * **printing:** allowed (returns empty string)
	// * **iteration:** allowed (returns empty array)
	// * **attribute access of undefined values:** fails
	UndefinedBehaviorLenient UndefinedBehavior = iota

	// UndefinedBehaviorChainable is like `Lenient`, but also allows chaining of undefined lookups.
	//
	// * **printing:** allowed (returns empty string)
	// * **iteration:** allowed (returns empty array)
	// * **attribute access of undefined values:** allowed (returns [`undefined`](Value::UNDEFINED))
	UndefinedBehaviorChainable

	// UndefinedBehaviorStrict complains very quickly about undefined values.
	//
	// * **printing:** fails
	// * **iteration:** fails
	// * **attribute access of undefined values:** fails
	UndefinedBehaviorStrict

	UndefinedBehaviorDefault = UndefinedBehaviorLenient
)

type Value

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

Value provides a dynamic value type abstraction.

This struct gives access to a dynamically typed value which is used by the template engine during execution.

For the most part the existence of the value type can be ignored as mjingo will perform the necessary conversions for you. For instance if you write a filter that converts a string you can directly declare the filter to take a string. However for some more advanced use cases it's useful to know that this type exists.

Basic Value Conversions

Values are typically created via ValueFromGoValue function.

The special Undefined value also exists but does not have a Go equivalent. It can be created via the Undefined variable.

var Undefined Value

Undefined is the undefined value.

This constant variable exists because the undefined type does not exist in Go and this is the only way to construct it.

func ConvertArgToGoValue

func ConvertArgToGoValue[T JustOneArgTypes](state *State, args []Value) (T, []Value, error)

ConvertArgToGoValue convert an argument in args to a Go value of type T. It returns the rest of args.

func ValueFromGoValue

func ValueFromGoValue(val any, opts ...ValueFromGoValueOption) Value

ValueFromGoValue creates a value from a Go value.

Supported scalar types are bool, uint8, uint16, uint32, uint64, uint, int8, int16, int32, int64, int, json.Number, I128, U128, float32, float64, string, nil, Value.

And struct, slice, pointer, and map of these types are supported.

func ValueFromObject

func ValueFromObject(dy Object) Value

ValueFromObject creates a value that wraps the object.

func ValueFromSafeString

func ValueFromSafeString(s string) Value

ValueFromSafeString creates a value from a safe string.

A safe string is one that will bypass auto escaping. For instance if you want to have the template engine render some HTML without the user having to supply the `|safe` filter, you can use a value of this type instead.

func (Value) DebugString

func (v Value) DebugString() string

func (Value) Equal

func (v Value) Equal(other any) bool

func (Value) Format

func (v Value) Format(f fmt.State, verb rune)

func (Value) Kind

func (v Value) Kind() ValueKind

Kind returns the Kind of the value.

This can be used to determine what's in the value before trying to perform operations on it.

func (Value) String

func (v Value) String() string

func (Value) SupportsCustomVerb

func (Value) SupportsCustomVerb(verb rune) bool

type ValueFromGoValueOption

type ValueFromGoValueOption func(*valueFromGoValueConfig)

ValueFromGoValueOption is the option type to configure the behavior of ValueFromGoValue.

func WithStructTag

func WithStructTag(tag string) ValueFromGoValueOption

WithStructTag sets the struct tag which is used to reference a struct field. If a struct tag value exists with the specified tag name, the value before comma is used as a field name instead.

type ValueKind

type ValueKind int

ValueKind describes the kind of value.

const (
	// ValueKindUndefined represents the value is undefined
	ValueKindUndefined ValueKind = iota + 1
	// ValueKindNone represents the value is the none (None).
	//
	// Note this is different from a None value of option.Option.
	ValueKindNone
	// ValueKindBool repreesnts the value is a bool
	ValueKindBool
	// ValueKindNumber represents the value is a number of a supported type.
	ValueKindNumber
	// ValueKindString represents the value is a string.
	ValueKindString
	// ValueKindBytes represents the value is a byte array.
	ValueKindBytes
	// ValueKindSeq represents the value is an array of other values.
	ValueKindSeq
	// ValueKindMap represents the value is a key/value mapping.
	ValueKindMap
)

func (ValueKind) String

func (k ValueKind) String() string

type VariadicArgElemTypes

type VariadicArgElemTypes interface {
	ScalarTypes
}

VariadicArgElemTypes is the type constraint for the element of the last argument slice of a variadic unboxed filter, test or function.

Directories

Path Synopsis
internal
datast/indexmap
Package Map defines various functions useful for Map.
Package Map defines various functions useful for Map.
datast/slicex
Package slicex defines various functions useful with slices of any type.
Package slicex defines various functions useful with slices of any type.
Package option provides the Option type which represents an optional value.
Package option provides the Option type which represents an optional value.

Jump to

Keyboard shortcuts

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