jigo

package module
v0.0.0-...-f75f9d0 Latest Latest
Warning

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

Go to latest
Published: Aug 13, 2014 License: MIT Imports: 12 Imported by: 0

README

jigo

Build Status Godoc license version

Jigo is a Jinja2-like template language for Go. It is in pre-alpha stages and not yet ready for use much less production. Any documentation you see here is subject to change. Jigo's name is also subject to change.

Goals

The goal of jigo is to create a template system which is powerful, flexible, and familiar. The Django template syntax has inspired Jinja2, Twig in php, Liquid in Ruby, Jinja-JS in JavaScript, and indeed Pongo2 in Go.

Although jigo is an outright attempt to implement a very functional subset of Jinja2's semantics, the fact that it is written in Go means that much of Jinja2's support for rich Python expressions and semantics are dropped.

Twig, a Jinja2-like template system implemented in PHP, allows for a limited expression syntax which more closely mimics Python's than PHP's. Jigo allows for a similarly Python-inspired expression syntax, with a clean, explicit two way mapping to Go types and stronger type matching requirements.

Unlike Go's html/template, There are no plans and currently no support for context-aware escaping. Because of html/template, this is a big deal for many in the Go community, and while I'm not against adding it to Jigo, I am more interested in getting the language in a usable state first.

  • If you want logic-less templates, try moustache (note buggy and unmaintained)
  • If you want execution safety, try liquid or mandira
  • If you want contextually aware escaping, try html/template
  • If you want something aiming to be compatible with django templates, try pongo2

Differences

There are many differences. Some infrequently used features of Jinja2 have been dropped, and the expression syntax is far less sophisticated.

Features
  • Line statements and line comments have been dropped

TODO More info here as I get through more of the implementation.

Type Safety

Template lookups are obviously not inspectable for types at compile time, but literals are, and although there are no type declarations, all types are inferred according to rules defined below. This means that the following code raises a type error at compile time:

{{ 1 + "foo" }}

Expressions

Expressions are coerced to strings at render time with fmt.Sprint, but expression syntax is strongly typed. Unlike Go, integer and floating point arithmetic can be mixed, but any introduction of floats coerces all values in the expression to float.

Function calling semantics allow for keyword arguments if the function's final argument is of type jigo.Kwargs. Varargs are allowed if a funciton is variadic or the final argument is of type jigo.Args. For a function to be both variadic and keyword, it must accept (jigo.Args, jigo.Kwargs) in that order.

Jigo follows Go's operator precedence and Go's definition of %, which is remainder, like C, and unlike Python. % is only defined in integers, and will be a compile time error on float literals and a runtime error on float variables.

Other Operators:
  • ** is power, eg 2**4 = 16
  • // is floor-div, eg. 14//3 = 4
  • ~ is a string concatenation object, which explicitly coerces both sides to the string type via fmt.Sprint
  • is will perform tests similar to Jinja2.
  • in is only valid for array, slice and map types. It is linear on arrays and slices.
  • [] is the selection operator, only valid on array, slice, and map types.
  • . is the attribute operator, only valid on struct types.
Literals
  • All integer numeric literals map to int64 (beware overflow)
  • All numeric literals with a "." in it become float64
  • Strings are standard " delimited, with \ escapes. No multi-line or `` string syntax support.
  • Lists are defined as '[' expr [, expr]... ']', and map to the Go type []interface{}
  • Hashes are defined as '{' stringExpr ':' expr [, stringExpr ':' expr]... '}', and map to map[string]interface{}. A stringExpr is an expression that is coerced to a string automatically. This means that the "1" and 1 represent the same key.
  • No advanced python expressions/literals (comprehensions, sets, generators, etc).

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewContextStack

func NewContextStack(i interface{}) contextStack

Types

type AddExpr

type AddExpr struct {
	NodeType
	Pos
	// contains filtered or unexported fields
}

func (*AddExpr) Copy

func (a *AddExpr) Copy() Node

func (*AddExpr) String

func (a *AddExpr) String() string

type BlockNode

type BlockNode struct {
	NodeType
	Pos
	Name string
	Body Node
}

func (*BlockNode) Copy

func (b *BlockNode) Copy() Node

func (*BlockNode) String

func (b *BlockNode) String() string

type BoolNode

type BoolNode struct {
	NodeType
	Pos
	Value bool
}

func (*BoolNode) Copy

func (s *BoolNode) Copy() Node

func (*BoolNode) String

func (s *BoolNode) String() string

type CallNode

type CallNode struct {
	NodeType
	Pos
}

type ConditionalNode

type ConditionalNode struct {
	NodeType
	Pos
	Guard Node
	Body  Node
}

A ConditionalNode is a node that has a guard and a body. If the guard evals as True, then the body is rendered. Otherwise, it's a Noop. If's and ElseIf's are modeled this way.

func (*ConditionalNode) Copy

func (c *ConditionalNode) Copy() Node

func (*ConditionalNode) String

func (c *ConditionalNode) String() string

type Context

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

A context represents an environment passed in by a user to a template. Certain tags can create temporary contexts (for, macro, etc), which get created at eval time.

func NewContext

func NewContext(i interface{}) (*Context, error)

Contexts can be structs or maps, or pointers to these types, but no other type.

type Environment

type Environment struct {
	// The string marking the start of a block.  Defaults to `{%`.
	BlockStartString string
	// The string marking the end of a block.  Defaults to `%}`.
	BlockEndString string
	// The string marking the start of a var statement. Defaults to `{{`.
	VariableStartString string
	// The string marking the end of a var statement. Defaults to `}}`.
	VariableEndString string
	// The string marking the start of a comment.  Defaults to `{#`.
	CommentStartString string
	// The string marking the end of a comment.  Defaults to `#}`.
	CommentEndString string
	// If true, first newline after a block is removed.  Default false.
	TrimBlocks bool
	// If true, leading whitespace is stripped from the start of a line to a block.  Default false.
	LstripBlocks bool
	// If true, html auto-escaping is enabled by default for all var output.
	AutoEscape bool
	// Should the loader attempt to auto reload.
	AutoReload bool

	// Global variables to pass to every template.  Shadowed by actual local contexts.
	Globals map[string]interface{}
}

func NewEnvironment

func NewEnvironment() *Environment

func (*Environment) Load

func (e *Environment) Load(path string) (*Template, error)

func (*Environment) Parse

func (e *Environment) Parse(r io.Reader, name, filename string) (*Template, error)

func (*Environment) ParseFragment

func (e *Environment) ParseFragment(r io.Reader) (*Template, error)

func (*Environment) ParseString

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

type ExtendsNode

type ExtendsNode struct {
	NodeType
	Pos
}

type FloatNode

type FloatNode struct {
	NodeType
	Pos
	Value float64
}

func (*FloatNode) Copy

func (f *FloatNode) Copy() Node

func (*FloatNode) String

func (f *FloatNode) String() string

type ForNode

type ForNode struct {
	NodeType
	Pos
	ForExpr Node
	InExpr  Node
	Body    Node
}

func (*ForNode) Copy

func (f *ForNode) Copy() Node

func (*ForNode) String

func (f *ForNode) String() string

FIXME: This should use the environment's begin and end tags, which we don't have down at this level...

type FromNode

type FromNode struct {
	NodeType
	Pos
	Module  string
	Imports []Import
}

type IfBlockNode

type IfBlockNode struct {
	NodeType
	Pos
	Conditionals []Node
	Else         Node
}

IfBlockNode represents a full {% if %}... block. The if and elif bodies are modeled using the ConditionalNode, and are evaluated in order to determine which body to render. `Else` will be a ListNode, but can be nil if no such clause is present.

func (*IfBlockNode) Copy

func (i *IfBlockNode) Copy() Node

func (*IfBlockNode) String

func (i *IfBlockNode) String() string

type Import

type Import struct {
	Name string
	As   string
}

type ImportNode

type ImportNode struct {
	NodeType
	Pos
	Module string
	Body   Import
}

type IncludeNode

type IncludeNode struct {
	NodeType
	Pos
}

type IndexExpr

type IndexExpr struct {
	NodeType
	Pos
	Value Node
	Index Node
}

func (*IndexExpr) Copy

func (i *IndexExpr) Copy() Node

func (*IndexExpr) String

func (i *IndexExpr) String() string

type IntegerNode

type IntegerNode struct {
	NodeType
	Pos
	Value int64
}

func (*IntegerNode) Copy

func (i *IntegerNode) Copy() Node

func (*IntegerNode) String

func (i *IntegerNode) String() string

type ListNode

type ListNode struct {
	NodeType
	Pos
	Nodes []Node // The element nodes in lexical order.
}

ListNode holds a sequence of nodes.

func (*ListNode) Copy

func (l *ListNode) Copy() Node

func (*ListNode) CopyList

func (l *ListNode) CopyList() *ListNode

func (*ListNode) String

func (l *ListNode) String() string

type LookupNode

type LookupNode struct {
	NodeType
	Pos
	Name string
}

A LookupNode is a variable lookup.

func (*LookupNode) Copy

func (l *LookupNode) Copy() Node

func (*LookupNode) String

func (l *LookupNode) String() string

type MacroNode

type MacroNode struct {
	NodeType
	Pos
}

type MapElem

type MapElem struct {
	NodeType
	Pos
	Key   Node
	Value Node
}

func (*MapElem) Copy

func (m *MapElem) Copy() Node

func (*MapElem) String

func (m *MapElem) String() string

type MapExpr

type MapExpr struct {
	NodeType
	Pos
	Elems []*MapElem
}

func (*MapExpr) Copy

func (m *MapExpr) Copy() Node

func (*MapExpr) String

func (m *MapExpr) String() string

type MulExpr

type MulExpr struct {
	NodeType
	Pos
	// contains filtered or unexported fields
}

func (*MulExpr) Copy

func (m *MulExpr) Copy() Node

func (*MulExpr) String

func (m *MulExpr) String() string

type Node

type Node interface {
	Type() NodeType
	String() string
	// Copy does a deep copy of the Node and all its components.
	Copy() Node
	Position() Pos // byte position of start of node in full original input string
}

type NodeType

type NodeType int
const (
	NodeList NodeType = iota
	NodeText
	NodeVar
	NodeLookup
	NodeUnary
	NodeFloat
	NodeInteger
	NodeString
	NodeBool
	NodeAdd
	NodeMul
	NodeMapExpr
	NodeMapElem
	NodeIndexExpr
	NodeSet
	NodeIf
	NodeElseIf
	NodeFor
)

func (NodeType) Type

func (t NodeType) Type() NodeType

type Pos

type Pos int

func (Pos) Position

func (p Pos) Position() Pos

type PrintNode

type PrintNode struct {
	NodeType
	Pos
}

type SetNode

type SetNode struct {
	NodeType
	Pos
	// contains filtered or unexported fields
}

block types

func (*SetNode) Copy

func (s *SetNode) Copy() Node

func (*SetNode) String

func (s *SetNode) String() string

FIXME: environment needed to really recreate this as it requires block begin and end tags, which we don't technically know

type StringNode

type StringNode struct {
	NodeType
	Pos
	Value string
}

func (*StringNode) Copy

func (s *StringNode) Copy() Node

func (*StringNode) String

func (s *StringNode) String() string

type Template

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

func (*Template) Render

func (t *Template) Render(context interface{}) (string, error)

Render this template with the given context.

type TextNode

type TextNode struct {
	NodeType
	Pos
	Text []byte // The text; may span newlines.
}

TextNode holds plain text.

func (*TextNode) Copy

func (t *TextNode) Copy() Node

func (*TextNode) String

func (t *TextNode) String() string

type Tree

type Tree struct {
	Name      string    // name of the template represented by the tree.
	ParseName string    // name of the top-level template during parsing, for error messages.
	Root      *ListNode // top-level root of the tree.
	// contains filtered or unexported fields
}

Tree is the representation of a single parsed template.

func (*Tree) Copy

func (t *Tree) Copy() *Tree

Copy returns a copy of the Tree. Any parsing state is discarded.

func (*Tree) ErrorContext

func (t *Tree) ErrorContext(n Node) (location, context string)

ErrorContext returns a textual representation of the location of the node in the input text.

func (*Tree) Parse

func (t *Tree) Parse(lex *lexer) (tree *Tree, err error)

Parse parses the template given the lexer.

type UnaryNode

type UnaryNode struct {
	NodeType
	Pos
	Value Node
	Unary item
}

func (*UnaryNode) Copy

func (u *UnaryNode) Copy() Node

func (*UnaryNode) String

func (u *UnaryNode) String() string

type VarNode

type VarNode struct {
	NodeType
	Pos
	Node Node
}

VarNode represents a var print expr, ie {{ ... }}. It is represented as a sequence of expressions.

func (*VarNode) Copy

func (v *VarNode) Copy() Node

func (*VarNode) String

func (v *VarNode) String() string

Jump to

Keyboard shortcuts

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