mustache

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Nov 14, 2023 License: MIT Imports: 9 Imported by: 7

README

Mustache

Go Reference Go Build

This is an implementation of the mustache templating language in Go.

It is inspired by hoisie/mustache however it's not a fork, but rather a re-implementation with improved spec conformance, and a more flexible API (e.g. support for io.Writer and io.Reader).

It is built using lexing techniques described in the slides on lexical scanning in Go, and functional options as described in the blog post on self-referential functions and the design of options.

This package aims to cover 100% of the mustache specification tests, however, by the time of this writing, it is not complete.

For more information on mustache check the official documentation and the mustache spec.

Installation

Install with go get github.com/alexkappa/mustache.

Documentation

The API documentation is available at godoc.org.

Usage

The core of this package is the Template, and its Parse and Render functions.

template := mustache.New()
template.Parse(strings.NewReader("Hello, {{subject}}!"))
template.Render(os.Stdout, map[string]string{"subject": "world"})

Helpers

There are additional Parse and Render helpers to deal with different kinds of input or output, such as string, []byte or io.Writer/io.Reader.

Parse(r io.Reader) error
ParseString(s string) error
ParseBytes(b []byte) error
Render(w io.Writer, context interface{}) error
RenderString(context interface{}) (string, error)
RenderBytes(context interface{}) ([]byte, error)
Reader/Writer
f, err := os.Open("template.mustache")
if err != nil {
    fmt.Fprintf(os.Stderr, "failed to open file: %s\n", err)
}
t, err := Parse(f)
if err != nil {
    fmt.Fprintf(os.Stderr, "failed to parse template: %s\n", err)
}
t.Render(os.Stdout, nil)

Note: in the example above, we used Parse which wraps the t := New() and t.Parse() functions for conciseness.

String
t := mustache.New()
err := t.ParseString("Hello, {{subject}}!")
if err != nil {
    // handle error
}
s, _ := t.RenderString(map[string]string{"subject": "world"})
if err != nil {
    // handle error
}
fmt.Println(s)

Options

It is possible to define some options on the template, which will alter the way the template will parse, render or fail.

The options are:

  • Name(n string) Option sets the name of the template. This option is useful when using the template as a partial to another template.
  • Delimiters(start, end string) Option sets the start and end delimiters of the template.
  • Partial(p *Template) Option sets p as a partial to the template. It is important to set the name of p so that it may be looked up by the parent template.
  • SilentMiss(silent bool) Option sets missing variable lookup behavior.

Options can be defined either as arguments to New or using the Option function.

Partials

Partials are templates themselves and can be defined using the Partial option.

Note: It is important to name the partial using the Name option which should match the mustache partial tag {{>name}} in the parent template.

title := New(
    Name("header")        // instantiate and name the template
    Delimiters("|", "|")) // set the mustache delimiters to | instead of {{

title.ParseString("|title|") // parse a template string

body := New()
body.Option(Name("body"))
body.ParseString("{{content}}")

template := New(
    SilentMiss(false), // return an error if a variable lookup fails
    Partial(title),    // register a partial
    Partial(body))     // and another one...

template.ParseString("{{>header}}\n{{>body}}")

context := map[string]interface{}{
    "title":   "Mustache",
    "content": "Logic less templates with Mustache!",
}

template.Render(os.Stdout, context)

Context

When rendering, context can be either a map or a struct. Following are some examples of valid context arguments.

ctx := map[string]interface{}{
    "foo": "Hello",
    "bar": map[string]string{
        "baz": "World",
    }
}
mustache.Render("{{foo}} {{bar.baz}}", ctx) // Hello World
type Foo struct { Bar string }
ctx := &Foo{ Bar: "Hi, from a struct!" }
mustache.Render("{{Bar}}", ctx) // Hi, from a struct!
type Foo struct { bar string }
func (f *Foo) Bar() string { return f.bar }
ctx := &Foo{"Hi, from a method!"}
mustache.Render("{{Bar}}", ctx) // Hi, from a method!
type Foo struct { Bar string `tag:"bar"` }
ctx := &Foo{ Bar: "Hi, from a struct tag!" }
mustache.Render("{{bar}}", ctx) // Hi, from a struct tag!

Tests

Run go test as usual. If you want to run the spec tests against this package, make sure you've checked out the specs submodule. Otherwise, spec tests will be skipped.

Currently, certain spec tests are skipped as they fail due to an issue with how standalone tags and empty lines are being handled. Inspecting them manually, one can see that the templates render correctly but with some additional \n which should have been omitted. See issue #1.

See SPEC.md for a breakdown of which spec tests pass and fail.

Contributing

If you would like to contribute, head on to the issues page for tasks that need help.

Documentation

Overview

Package mustache is an implementation of the mustache templating language in Go. For more information on mustache check out the official documentation at http://mustache.github.io.

temlpate := mustache.New()
err := template.ParseString("Hello, {{subject}}!")
if err != nil {
    // handle error
}
s, err := template.RenderString(map[string]string{"subject": "world"})
if err != nil {
    // handle error
}
fmt.Println(s)

There are several wrappers of Parse and Render to help with different input or output types. It is quite common to need to write the output of the template to an http.ResponseWriter. In this case the Render function is the most apropriate.

import "net/http"
import "github.com/alexkappa/mustache"

func ServeHTTP(w http.ResponseWriter, r *http.Request) {
    template, err := mustache.ParseString("Hello, {{subject}}!")
    if err != nil {
        // handle error
    }
    err = template.Render(w, map[string]string{"subject": "world"})
    if err != nil {
        // handle error
    }
}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Render

func Render(r io.Reader, w io.Writer, context ...interface{}) error

Render wraps the parsing and rendering into a single function.

Types

type Option

type Option func(*Template)

The Option type describes functional options used with Templates. Check out Dave Cheney's talk on functional options http://bit.ly/1x9WWPi.

Example
title := New(Name("header"))   // instantiate and name the template
title.ParseString("{{title}}") // parse a template string

body := New()
body.Option(Name("body")) // options can be defined after we instantiate too
body.ParseString("{{content}}")

template := New(
	Delimiters("|", "|"), // set the mustache delimiters to | instead of {{
	SilentMiss(false),    // return an error if a variable lookup fails
	Partial(title),       // register a partial
	Partial(body))        // and another one...

template.ParseString("|>header|\n|>body|")

context := map[string]interface{}{
	"title":   "Mustache",
	"content": "Logic less templates with Mustache!",
}

template.Render(os.Stdout, context)
Output:

Mustache
Logic less templates with Mustache!

func Delimiters

func Delimiters(start, end string) Option

Delimiters sets the start and end delimiters of the template.

func Errors

func Errors() Option

Errors enables missing variable errors. This option is deprecated. Please use SilentMiss instead.

func Name

func Name(n string) Option

Name sets the name of the template.

func Partial

func Partial(p *Template) Option

Partial sets p as a partial to the template. It is important to set the name of p so that it may be looked up by the parent template.

func SilentMiss

func SilentMiss(silent bool) Option

SilentMiss sets the silent miss behavior of variable lookups when rendering. If true, missed lookups will not produce any errors. Otherwise a missed variable lookup will stop the rendering and return an error.

type Template

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

The Template type represents a template and its components.

Example (Basic)
template := New()
template.ParseString(`{{#foo}}{{bar}}{{/foo}}`)

context := map[string]interface{}{
	"foo": true,
	"bar": "bazinga!",
}

output, _ := template.RenderString(context)
fmt.Println(output)
Output:

bazinga!
Example (Http)
writer := httptest.NewRecorder()
request, _ := http.NewRequest("GET", "http://example.com?foo=bar&bar=one&bar=two", nil)

template := New()
template.ParseString(`
<ul>{{#foo}}<li>{{.}}</li>{{/foo}}</ul>
<ul>{{#bar}}<li>{{.}}</li>{{/bar}}</ul>`)

handler := func(w http.ResponseWriter, r *http.Request) {
	template.Render(w, r.URL.Query())
}

handler(writer, request)

fmt.Println(writer.Body.String())
Output:

<ul><li>bar</li></ul>
<ul><li>one</li><li>two</li></ul>
Example (Partials)
partial := New(Name("partial"))
partial.ParseString(`{{bar}}`)

template := New(Partial(partial))
template.ParseString(`{{#foo}}{{>partial}}{{/foo}}`)

context := map[string]interface{}{
	"foo": true,
	"bar": "bazinga!",
}

template.Render(os.Stdout, context)
Output:

bazinga!
Example (Reader)
f, err := os.Open("template.mustache")
if err != nil {
	fmt.Fprintf(os.Stderr, "failed to open file: %s\n", err)
}
t, err := Parse(f)
if err != nil {
	fmt.Fprintf(os.Stderr, "failed to parse template: %s\n", err)
}
t.Render(os.Stdout, nil)
Output:

func New

func New(options ...Option) *Template

New returns a new Template instance.

func Parse

func Parse(r io.Reader) (*Template, error)

Parse wraps the creation of a new template and parsing from r in one go.

func (*Template) Option

func (t *Template) Option(options ...Option)

Option applies options to the currrent template t.

func (*Template) Parse

func (t *Template) Parse(r io.Reader) error

Parse parses a stream of bytes read from r and creates a parse tree that represents the template.

func (*Template) ParseBytes

func (t *Template) ParseBytes(b []byte) error

ParseBytes is a helper function that uses a byte array as input.

func (*Template) ParseString

func (t *Template) ParseString(s string) error

ParseString is a helper function that uses a string as input.

func (*Template) Render

func (t *Template) Render(w io.Writer, context ...interface{}) error

Render walks through the template's parse tree and writes the output to w replacing the values found in context.

func (*Template) RenderBytes

func (t *Template) RenderBytes(context ...interface{}) ([]byte, error)

RenderBytes is a helper function that renders the template as a byte slice.

func (*Template) RenderString

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

RenderString is a helper function that renders the template as a string.

Jump to

Keyboard shortcuts

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