Skip to content
Daniel Lohse edited this page Aug 10, 2016 · 23 revisions

Jet v2

This is the documentation for Jet v2. You can find the documentation for v1 here.

v2's syntax is slightly different in a few places – read the upgrade to v2 guide.

What's new in v2?

  • much more powerful {{block}} and {{yield}} constructs, allowing local variables, default variables as well as wrapping
  • fast functions that are up to 50% faster than normal functions; the built-in len and isset functions are implemented as fast functions (read more in the new Advanced section)
  • simple string concatenation in templates obviate the need for sprintf-like functions: {{ "build."+someString+".your-string" }}
  • isset can now be used to check for the existence of a key in a map (works both with the var map as well as the context)

What does Jet have to offer?

Jet is a template engine that was designed to be easy to use and fast.

  • simple and familiar syntax
  • easy to use
  • dynamic
  • fast and light
  • useful error messages
  • template inheritance
  • powerful

Simple and familiar syntax

The syntax has many similarities with Go's text/template templating language. The main differences are:

  • support for template inheritance
  • simple C-like expressions
  • pipelines can only be used in actions (i.e. {{ expression|pipe|pipe }})
  • all templates are file based – there are no "define", "template" or "with" actions

Dynamic

Templates can extend a template (known as a layout) and import blocks from another and everything just works, that way you can create a template library, layout templates and the application templates.

Fast and light

The engine was designed to be fast and light by avoiding unnecessary allocations and a fast runtime.

Useful error messages

All error messages are tied to the file and line of the node executing the action or expression, and all message are descriptive so you know exactly what's wrong.

Template inheritance

In Jet you can extend, import and include templates:

  • when extending, all blocks from the template that you extend will be available for your template even the ones that it imports or extends, also the root of the extended template is used as the entry point when executing
  • when importing a template, all blocks of the imported template will be available in your template
  • When including a template, the template will be invoked and all blocks available in your template will be available in the included template

Getting started

Getting started is easy and consists of getting the package, initializing a Set with a path to the templates and then rendering your first template.

  1. Get the package
  $ go get -u github.com/CloudyKit/jet

You may also use your favorite tool to vendor the library (git-freeze, git submodule).

  1. Create a Set and specify the lookup directories
  import (
      "os"
      "path/filepath"

      "github.com/CloudyKit/jet"
  )

  var View = jet.NewHTMLSet("./views")) // relative path to the Go file where this code is located

  // may also use an absolute path:
  var root, _ = os.Getwd()
  var View = jet.NewHTMLSet(filepath.Join(root, "views"))
  1. Create a layout and your first template
  <!-- file: "views/layouts/application.jet" -->
  <!DOCTYPE html>
  <html>
    <head></head>
    <body>
      {{yield body}}
    </body>
  </html>

  <!-- file: "views/home.jet" -->
  {{extends "layouts/application.jet"}}
  {{block body}}
    <main>
      This content will be yielded in the layout above.
    </main>
  {{end}}
  1. Execute the template. You'll be providing the template with variables (map[string]interface{}), data (interface{}) and most importantly, an io.Writer for the template to be rendered into. Anything that conforms to that interface can be passed; examples include a simple bytes.Buffer, Gin's context.Writer, or http.ResponseWriter in the case of Goji or if you're using the standard library's http package.
  templateName := "home.jet"
  t, err := View.GetTemplate(templateName)
  if err != nil {
      // template could not be loaded
  }
  var w bytes.Buffer // needs to conform to io.Writer interface (like gin's context.Writer for example)
  vars := map[string]interface{}
  if err = t.Execute(&w, vars, nil); err != nil {
      // error when executing template
  }

Template execution is synchronous and w will contain the rendered template's content. We didn't have any variables or data in this simple example so the vars map was empty (can also just pass nil here), as was the data (last parameter). Learn more about loading and executing templates in rendering templates.

Now that you know the basics, go on to the syntax documentation, learn how to add global variables and functions and take a look at the built-in functions available to you in every template.

Clone this wiki locally