views

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

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

Go to latest
Published: Nov 12, 2026 License: BSD-3-Clause Imports: 24 Imported by: 0

README

Views

CI Go Reference

The template engines of Iris v14.

Since v14 the framework keeps only the contract, in its view middleware, and the engines live in this repository. An engine wraps one template parser. All six satisfy view.Engine, view.EngineFuncer and view.EngineExtenser, and all six are registered and rendered the same way.

Engine Constructor Parser Layout argument
HTML views.HTML html/template yes
Django views.Django flosch/pongo2 no, a template says {% extends %}
Handlebars views.Handlebars mailgun/raymond yes, with map data
Jet views.Jet CloudyKit/jet no, a template says {{ extends }}
Pug views.Pug Joker/jade yes
Ace views.Ace yosssi/ace yes

The Blocks engine of Iris v12 is not here and is not needed: kataras/blocks satisfies view.Engine by itself. Pass a blocks.New("./views") to view.Handler.

Install

go get github.com/iris-contrib/views@latest

It needs Go 1.27 or newer, as Iris v14 does.

Quick start

package main

import (
	"github.com/iris-contrib/views"

	"github.com/kataras/iris/v14"
	"github.com/kataras/iris/v14/middleware/view"
	"github.com/kataras/iris/v14/rest/errors"
)

func main() {
	app := iris.New()

	// Every .html file under ./views, parsed with html/template.
	templates := views.HTML("./views", ".html")
	app.Use(view.Handler(templates))

	app.Get("/", index)

	app.Listen(":8080")
}

func index(ctx iris.Context) {
	data := iris.Map{"Message": "Hello world!"}

	// The template, the layout ("" for none) and the data.
	if err := view.Render(ctx, "hello.html", "layouts/main.html", data); err != nil {
		// A generic 500. The error of a template names files, lines and
		// data fields, so it is logged and not sent.
		errors.Internal.LogErr(ctx, err)
	}
}
<!-- ./views/layouts/main.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Page Title</title>
</head>
<body>
    {{ yield . }}
    <footer>{{ render "partials/footer.html" . }}</footer>
</body>
</html>
<!-- ./views/hello.html -->
<h1>{{ .Message }}</h1>
<!-- ./views/partials/footer.html -->
<p>Footer partial</p>

Registering an engine

view.Handler(engine) stores the engine on the request. Register it once for the application, or give a group of routes an engine of its own:

func routes(app *iris.Application) {
	// For the application.
	app.Use(view.Handler(views.HTML("./views", ".html")))

	// For the routes under /admin, which render Django templates.
	admin := app.Router("/admin", view.Handler(views.Django("./views/admin", ".html")))
	admin.Get("/", func(ctx iris.Context) {
		view.Render(ctx, "dashboard.html", "", iris.Map{"Title": "Dashboard"})
	})
}

Any number of engines can live in one program, two of the same kind included.

Rendering

view.Render(ctx, name, layout, data) renders a template into the response. view.WithTemplate is the same thing as a handler:

func about(app *iris.Application) {
	app.Get("/about", view.WithTemplate(&view.Template{
		Name:   "about.html",
		Layout: "layouts/main.html",
		Data:   iris.Map{"Title": "About"},
	}))
}

A name is the path of the file below the template directory, with forward slashes. The extension may be left out and a leading slash is ignored, so "users/list.html", "users/list" and "/users/list.html" name the same template.

Errors:

  • A template or a layout that does not exist is a view.ErrTemplateNotFound. Its Name is the name that was asked for and IsLayout says which of the two is missing.
  • view.ErrNoEngine means that no view.Handler ran for the request.
  • Anything else comes from the parser: a template that does not parse, a function that failed.

An engine also renders into any io.Writer, with no request around it. ExecuteTemplate is the method view.Render calls:

func welcomeMail(templates *views.HTMLEngine, name string) (string, error) {
	var body strings.Builder
	err := templates.ExecuteTemplate(&body, "email/welcome.html", "layouts/email.html", map[string]any{"Name": name})
	return body.String(), err
}

Loading

The six engines load their templates by the same rule.

  1. Load() parses every template and returns the first error. Call it at startup when the program should not start with a template that does not parse.
  2. An engine that was never loaded loads itself on its first render. Requests that arrive together wait for that one load. This is why the two lines of the quick start are enough.
  3. Reload(true) parses the templates again on every render. Use it while you edit templates, not in production.
func newTemplates() *views.HTMLEngine {
	templates := views.HTML("./views", ".html")
	if err := templates.Load(); err != nil {
		log.Fatal(err)
	}
	return templates
}

When the first load happens inside a request and fails, that request gets the error and so does every request after it, until a Load() succeeds. It is not tried again on each request. Load() may be called again at any time to parse everything anew; if it fails then, the templates of the previous load keep rendering.

A load that finds nothing returns views.ErrNoTemplates. A wrong directory and a wrong extension are the usual causes, and the error of a directory that does not exist names it.

A template that includes, extends or renders itself is an error too, not a crash, with one exception that is described under Jet.

Where the templates come from

The first argument of a constructor is a directory name, an fs.FS or an http.FileSystem.

//go:embed views
var viewsFS embed.FS

func embedded() *views.HTMLEngine {
	// RootDir is the directory inside the embedded tree.
	return views.HTML(viewsFS, ".html").RootDir("views")
}

A directory name is relative to the working directory of the process, so embedded templates are the safer choice for a program that is deployed as one binary.

Templates can also be given as text, alone (pass nil as the first argument) or next to the files:

func fromText() (*views.HTMLEngine, error) {
	templates := views.HTML(nil, ".html")
	err := templates.ParseTemplate("hello.html", []byte(`<h1>Hello {{ .Name }}</h1>`), nil)
	return templates, err
}

ParseTemplate returns the error of a template that does not parse, and adds nothing then. On an engine that is loaded already it loads again, so the new template renders at once. Every engine has it; the arguments differ a little, see each engine's documentation.

Layouts

HTML, Pug, Ace and Handlebars render a page inside a layout. The layout of a render is the first of these that is set:

  1. the layout argument of view.Render, or the Layout field of a view.Template,
  2. the layout of the request, set by view.WithLayout for a group of routes or by view.Layout inside a handler,
  3. the default of the engine, set by its Layout method.

views.NoLayout, in the first or the second place, renders the page alone.

func layouts(app *iris.Application) {
	templates := views.HTML("./views", ".html").Layout("layouts/main.html")
	app.Use(view.Handler(templates))

	// layouts/main.html, the default of the engine.
	app.Get("/", func(ctx iris.Context) {
		view.Render(ctx, "index.html", "", nil)
	})

	// layouts/admin.html for every route of the group.
	admin := app.Router("/admin", view.WithLayout("layouts/admin.html"))
	admin.Get("/", func(ctx iris.Context) {
		view.Render(ctx, "admin/index.html", "", nil)
	})

	// No layout for this render.
	app.Get("/print", func(ctx iris.Context) {
		view.Render(ctx, "index.html", views.NoLayout, nil)
	})
}

Django and Jet ignore the layout, wherever it comes from. Their templates name their own parent, which is how those two languages work.

Data

The data of a template is the last argument of view.Render. When it is nil, the template gets the data of the request, which view.WithData, view.Data and view.KeyValue set:

func data(app *iris.Application) {
	app.Get("/profile", func(ctx iris.Context) {
		view.KeyValue(ctx, "User", "maria")
		view.KeyValue(ctx, "Role", "editor")

		// nil: the template reads User and Role.
		view.Render(ctx, "profile.html", "", nil)
	})
}

A map and a struct both work as data in every engine, with two limits. Django accepts nothing else. Handlebars needs a map[string]any or nil when it renders through a layout, because the page reaches the layout as one more entry of that map.

view.WithData(m) gives the same map m to every request. view.KeyValue does not write into it: the first call of a request copies the map, so a key added for one request is not seen by another. The engines do not write into the data either.

Functions

Give a template function to the engine with its AddFunc method:

func withFuncs() *views.HTMLEngine {
	templates := views.HTML("./views", ".html")
	templates.AddFunc("greet", func(name string) string {
		return "Greetings " + name + "!"
	})
	return templates
}
<b>{{ greet "kataras" }}</b> <!-- <b>Greetings kataras!</b> -->

view.AddFunc(ctx, name, fn) and view.WithFuncMap(funcs) reach the same method through the request. The function still belongs to the engine and not to the request, so it must not depend on the request it was added from. A function that does depend on the request goes into the data of the render. In HTML, Pug and Ace a template calls it with {{ call .Greet .Name }}.

When the function takes effect depends on the engine:

  • Django and Jet look a function up when a template runs. It works at once.
  • HTML, Pug, Ace and Handlebars bind functions when they parse, so the function takes effect at the next load. Add it before Load(). With an engine that loads itself, a view.WithFuncMap registered ahead of the handlers is in time, because the first render is what loads the engine.

A value that the parser does not accept as a function fails the load with an error.

The engines

HTML

views.HTML(dirOrFS, ".html") parses with the standard html/template package, so everything in its documentation applies, contextual escaping included.

func html() *views.HTMLEngine {
	return views.HTML("./views", ".html").
		Layout("layouts/main.html").
		Option("missingkey=error").
		Funcs(template.FuncMap{"upper": strings.ToUpper})
}

The engine adds these actions to the ones of html/template:

Action Renders
{{ yield . }} the page, inside its layout. Nothing anywhere else.
{{ render "partials/footer.html" . }} any template, by name
{{ partial_r ".script" . }} for the page users/index.html, the template users/index.script.html, if it exists
{{ part "head" . }} for the page users/index.html, the template users/index-head, if a {{ define }} made one
{{ partial "sidebar" . }} for the page users/index.html, the template sidebar-users/index.html, if it exists
{{ current }} the name of the page

Delims changes the {{ and }} delimiters, Option passes options such as missingkey=error to the parser, and Funcs, SetFuncs, AddFunc and AddLayoutFunc add functions.

Two things to know:

  • html/template keeps one function map for a whole set of templates, and yield has to know which page it is rendering. The engine therefore renders in copies of the set, one render per copy at a time, and makes a new copy only when all of them are busy. It keeps one per CPU at most. Renders that overlap beyond that, because a template function waits for a query for example, get a copy that the garbage collector takes back afterwards. A copy costs roughly three times the size of the template sources in memory.
  • A page is rendered into a buffer and sent when it is complete. When a template fails halfway, nothing has been written and the handler can still answer with an error page.
Django

views.Django(dirOrFS, ".html") parses with pongo2, a Go implementation of the Django template language.

func django() *views.DjangoEngine {
	templates := views.Django("./views", ".html")

	// A global: a function or a plain value.
	templates.AddFunc("site", "example.com")

	// A filter: {{ title|shout }}.
	templates.AddFilter("shout", func(in *views.Value, param *views.Value) (*views.Value, *views.Error) {
		return views.AsValue(strings.ToUpper(in.String()) + "!"), nil
	})

	return templates
}
{# ./views/page.html #}
{% extends "layouts/main.html" %}

{% block content %}
<h1>{{ title|shout }}</h1>
{% include "partials/footer.html" %}
{% endblock %}
  • The layout argument is ignored. A template names its parent with {% extends %}.
  • The names in {% extends %} and {% include %} are relative to the template directory, whichever file they are written in.
  • The data is a map[string]any or a struct. Anything else is an error.
  • Filters and tags are kept by pongo2 for the whole process. All Django engines of a program share them, and a filter that is registered again under the same name replaces the earlier one. Register them at startup.
Handlebars

views.Handlebars(dirOrFS, ".html") parses with raymond.

func handlebars() *views.HandlebarsEngine {
	templates := views.Handlebars("./views", ".html").Layout("layouts/main.html")

	// A helper: {{ fullName author }}.
	templates.AddFunc("fullName", func(person map[string]string) string {
		return person["firstName"] + " " + person["lastName"]
	})

	return templates
}
{{! ./views/layouts/main.html }}
<html>
<body>
    {{ yield }}
    <footer>{{ render "partials/footer.html" . }}</footer>
</body>
</html>
  • A layout prints the page with {{ yield }}. The page is one more entry of the data, which is why a render through a layout needs a map[string]any or nil.
  • {{ render "name" . }} renders another template. A name that does not exist fails the render.
  • A helper added with AddFunc belongs to the engine. AddGlobalFunc registers one for every Handlebars engine of the process, replaces a helper of the same name, and panics for a value raymond would not take.
  • A helper returns one value. raymond does not accept a function with a second, error result.
Jet

views.Jet(dirOrFS, ".jet") parses with jet. The extension must be .jet, .html.jet or .jet.html, and the constructor panics for any other.

func jet() *views.JetEngine {
	templates := views.Jet("./views", ".jet")

	// Any Go function: {{ upper(.Title) }}.
	templates.AddFunc("upper", strings.ToUpper)
	// A global variable: {{ site }}.
	templates.AddVar("site", "example.com")

	return templates
}
{* ./views/page.jet *}
{{ extends "layouts/main.jet" }}

{{ block main() }}
<h1>{{ upper(.Title) }} on {{ site }}</h1>
{{ include "partials/footer.jet" }}
{{ end }}
  • The layout argument is ignored. A template names its parent with {{ extends }}.
  • jet reads a template from the file system when it is first rendered and keeps it. Load() parses every file to report the ones that do not parse, and empties that cache.
  • Reload(true) parses all templates on every render, as in the other engines, and turns on jet's development mode, in which the template that is rendered is read again. Call it before the engine loads.
  • jet runs {{ include }} when a template executes, which allows a template to include itself for every child of a tree. A template that does so without an end overflows the stack inside jet and takes the process with it. The engine cannot stop that one.
  • views.AddJetRuntimeVars(ctx, vars) sets variables for one request. The entries of the request's data map are variables too, so {{ title }} and {{ .title }} both read a title that view.KeyValue set.
  • SetLoader replaces the file system with a jet loader of your own.
Pug

views.Pug(dirOrFS, ".pug") turns a Pug template into html/template text with jade and hands it to the HTML engine. It returns a *views.HTMLEngine, so layouts, the actions of the table above and the functions all work as they do there.

//- ./views/layouts/main.pug
doctype html
html
  body
    include ../partials/header.pug
    | {{ yield . }}
  • include and extends read from the template directory of the engine. Write the file extension: include partials/header.pug. The path is relative to the file that includes.
  • Data and functions are written in the html/template syntax: p Hello {{ .Name }}.
Ace

views.Ace(dirOrFS, ".ace") compiles each Ace file into html/template text and hands it to the HTML engine. It returns a *views.AceEngine, which is an HTML engine with one more method, so layouts, the actions of the table above and the functions all work as they do there.

/ ./views/layouts/main.ace
= doctype html
html
  body
    = include partials/header.ace .
    {{ yield . }}
  • = include becomes a {{ template }} action. Give it the name of the file with its extension, relative to the template directory.
  • The base and inner templates of Ace, = yield and = content, are not available. Use a layout.
  • The output is minified. SetIndent(" ") indents it.

Other template engines

An engine that compiles its templates to Go code needs nothing from this package, because the Iris Context is an io.Writer. The examples for hero, quicktemplate and templ show how.

Any type with this method is an engine for view.Handler:

type Engine interface {
	ExecuteTemplate(w io.Writer, templateName string, layoutName string, data any) error
}

Examples

Example Shows
overview The HTML engine from a directory: maps, structs and functions
embedding-templates-into-app embed.FS, Load at startup, layouts per engine, per group and per render
write-to Rendering into an io.Writer outside a request, for an e-mail body
herotemplate hero, compiled templates
quicktemplate quicktemplate, compiled templates, with a test
templ templ components

The last three are modules of their own, so that their template libraries are not dependencies of this package.

Coming from Iris v12

The engines kept their names and their methods. Three things changed around them:

  • An engine is registered with view.Handler and rendered with view.Render. The application and the context no longer have view methods of their own. MIGRATION.md in the framework shows both sides.
  • ExecuteWriter is now ExecuteTemplate.
  • The framework no longer calls Load for you, and it does not have to: see Loading.

License

BSD 3-Clause, see LICENSE.

Documentation

Overview

Package views holds the template engines of the Iris web framework: HTML, Django, Handlebars, Jet, Pug and Ace.

Every engine satisfies the three interfaces of github.com/kataras/iris/v14/middleware/view (Engine, EngineFuncer and EngineExtenser), so it is registered with view.Handler and rendered with view.Render:

templates := views.HTML("./views", ".html")
app.Use(view.Handler(templates))

app.Get("/", func(ctx iris.Context) {
	view.Render(ctx, "index.html", "layouts/main.html", iris.Map{"Title": "Home"})
})

Loading

The six engines load their templates the same way:

  • Load parses every template and returns the first error. Call it at startup to refuse to start with a template that does not parse.
  • An engine that was never loaded loads itself on its first ExecuteTemplate. Requests that arrive together wait for that one load. If it fails, every render returns its error until a Load succeeds.
  • Reload(true) parses the templates again on every render, for development.

A template or a layout that does not exist is a view.ErrTemplateNotFound. A name may leave the engine's extension out and may start with a slash.

Index

Constants

View Source
const JetRuntimeVarsContextKey = "iris.jetvarmap"

JetRuntimeVarsContextKey is the Iris Context key to keep any custom jet runtime variables. See `AddJetRuntimeVars` package-level function and `JetEngine.AddRuntimeVars` method.

View Source
const NoLayout = "iris.nolayout"

NoLayout disables the configuration's layout for a specific execution.

Variables

View Source
var AsSafeValue = pongo2.AsSafeValue

AsSafeValue works like AsValue, but does not apply the 'escape' filter. Shortcut for `pongo2.AsSafeValue`.

View Source
var AsValue = pongo2.AsValue

AsValue converts any given value to a pongo2.Value Usually being used within own functions passed to a template through a Context or within filter functions.

Example:

AsValue("my string")

Shortcut for `pongo2.AsValue`.

View Source
var ErrNoTemplates = errors.New("views: no templates found")

ErrNoTemplates is returned by Load, and by the first render of an engine that was never loaded, when there is nothing to load: no file with the engine's extension and no template added with ParseTemplate. The usual causes are a wrong directory and a wrong extension.

Functions

func AddJetRuntimeVars

func AddJetRuntimeVars(ctx *context.Context, jetVarMap JetRuntimeVars)

AddJetRuntimeVars sets or inserts runtime jet variables through the Iris Context. This gives the ability to add runtime variables from different handlers in the request chain, something that the jet template parser does not offer at all.

Usage: views.AddJetRuntimeVars(ctx, views.JetRuntimeVars{...}). See `JetEngine.AddRuntimeVars` too.

Types

type AceEngine

type AceEngine struct {
	*HTMLEngine
	// contains filtered or unexported fields
}

AceEngine represents the Ace view engine. See the `Ace` package-level function for more.

func Ace

func Ace(fs any, extension string) *AceEngine

Ace returns a new Ace view engine. It shares the same exactly logic with the html view engine, it uses the same exactly configuration. The given "extension" MUST begin with a dot. Ace minifies the response automatically unless SetIndent() method is set.

Every file is compiled on its own into html/template text, so the actions of the html engine ({{ yield . }}, {{ render "name" . }} and the rest) and its layouts work the same. The "= include" helper of Ace becomes a {{ template }} action: give it the name of the file with its extension, as in "= include partials/footer.ace .". The base and inner templates of Ace ("= yield" and "= content") are not available, use a layout instead.

Read more about the Ace Go Parser: https://github.com/yosssi/ace

Usage: Ace("./views", ".ace") or Ace(embed.FS, ".ace").RootDir("views") for embedded templates.

func (*AceEngine) SetIndent

func (s *AceEngine) SetIndent(indent string) *AceEngine

SetIndent string used for indentation. Do NOT use tabs, only spaces characters. Defaults to minified response, no indentation.

type DjangoEngine

type DjangoEngine struct {

	// Set is the pongo2 template set of the engine.
	// It is nil until the first Load, ParseTemplate or render, unless the
	// application assigns one of its own before that.
	Set *pongo2.TemplateSet
	// contains filtered or unexported fields
}

DjangoEngine contains the django view engine structure.

func Django

func Django(fs any, extension string) *DjangoEngine

Django creates and returns a new django view engine. The given "extension" MUST begin with a dot.

A Django template names its own parent with {% extends %}, so the layout argument of ExecuteTemplate is ignored by this engine.

Usage: Django("./views", ".html") or Django(embed.FS, ".html").RootDir("views") for embedded templates.

func (*DjangoEngine) AddFilter

func (s *DjangoEngine) AddFilter(filterName string, filterBody FilterFunction) *DjangoEngine

AddFilter registers a new filter.

Same as `RegisterFilter`.

func (*DjangoEngine) AddFunc

func (s *DjangoEngine) AddFunc(funcName string, funcBody any)

AddFunc adds the function to the template's Globals. A template calls it as {{ name(argument) }}. Unlike the other engines, it takes effect at once, loaded or not.

func (*DjangoEngine) ExecuteTemplate

func (s *DjangoEngine) ExecuteTemplate(w io.Writer, filename string, _ string, bindingData any) error

ExecuteTemplate executes a template and writes its result to the w writer. The layout is ignored: a Django template names its own parent with {% extends %}.

The engine loads itself first if it was never loaded. It returns a view.ErrTemplateNotFound for a template that does not exist. Nothing is written to w when the execution fails.

func (*DjangoEngine) Ext

func (s *DjangoEngine) Ext() string

Ext returns the file extension which this view engine is responsible to render. If the filename extension on ExecuteTemplate is empty then this is appended.

func (*DjangoEngine) IsLoaded

func (s *DjangoEngine) IsLoaded() bool

IsLoaded reports whether the templates are loaded at least once or not.

func (*DjangoEngine) Load

func (s *DjangoEngine) Load() error

Load parses the templates to the engine.

Calling it is optional: an engine that was never loaded loads itself on its first ExecuteTemplate. Call it at startup to find a template that does not parse before the first request does.

It may be called again to parse everything anew. If it fails then, the templates of the previous load keep rendering.

Returns an error if something bad happens, user is responsible to catch it.

func (*DjangoEngine) Name

func (s *DjangoEngine) Name() string

Name returns the django engine's name.

func (*DjangoEngine) ParseTemplate

func (s *DjangoEngine) ParseTemplate(name string, contents []byte) error

ParseTemplate adds a custom template from text. This parser does not support funcs per template. Use the `AddFunc` instead.

A template given here is kept, and parsed again on every load. When it returns an error, nothing was added.

func (*DjangoEngine) RegisterFilter

func (s *DjangoEngine) RegisterFilter(filterName string, filterBody FilterFunction) *DjangoEngine

RegisterFilter registers a new filter.

pongo2 keeps its filters in one registry for the whole process. A filter is therefore shared by every Django engine of the program, and a name that is registered again replaces the filter for all of them. Register filters at startup, before anything renders: the registry is not safe to change while templates execute.

See http://www.florian-schlachter.de/post/pongo2/ for more about writing filters and tags.

func (*DjangoEngine) RegisterTag

func (s *DjangoEngine) RegisterTag(tagName string, fn TagParser) error

RegisterTag registers a new tag. You usually want to call this function in the tag's init() function: http://golang.org/doc/effective_go.html#init

Tags live in the process-wide registry of pongo2, like filters, and it returns an error for a name that is already registered.

See http://www.florian-schlachter.de/post/pongo2/ for more about writing filters and tags.

func (*DjangoEngine) Reload

func (s *DjangoEngine) Reload(developmentMode bool) *DjangoEngine

Reload if set to true the templates are reloading on each render, use it when you're in development and you don't want to restart the whole app when you edit a template file.

Every render then parses all templates first, one render at a time. Do not use it in production.

func (*DjangoEngine) RootDir

func (s *DjangoEngine) RootDir(root string) *DjangoEngine

RootDir sets the directory to be used as a starting point to load templates from the provided file system. It is what points the engine at a directory of an embed.FS.

It panics if root is not a valid path inside the file system.

type Engine

type Engine = view.Engine

Engine is the interface for a compatible Iris view engine. It's an alias of view.Engine.

type ErrTemplateNotFound

type ErrTemplateNotFound = view.ErrTemplateNotFound

ErrTemplateNotFound reports whether a template was not found in the parsed templates tree.

type Error

type Error = pongo2.Error

Error type alias for pongo2.Error

type FilterFunction

type FilterFunction = pongo2.FilterFunction

FilterFunction type alias for pongo2.FilterFunction

type HTMLEngine

type HTMLEngine struct {

	// Templates is a copy of the template set of the last successful load,
	// nil before it. Use it to look templates up, for example with
	// DefinedTemplates. The engine does not render with it, so parsing into
	// it or changing its functions has no effect on what the engine renders.
	//
	// Every load replaces it, with no lock: read it when no load can run.
	// With Reload(true) every render is a load.
	Templates *template.Template
	// contains filtered or unexported fields
}

HTMLEngine contains the html view engine structure. Read more at: https://pkg.go.dev/text/template#hdr-Functions.

It is also the engine behind Pug and Ace, which turn their own syntax into html/template text before it is parsed.

func HTML

func HTML(dirOrFS any, extension string) *HTMLEngine

HTML creates and returns a new html view engine. The html engine used like the "html/template" standard go package but with a lot of extra features. The given "extension" MUST begin with a dot.

Usage: HTML("./views", ".html") or HTML(embed.FS, ".html").RootDir("views") for embedded templates or HTML(nil, ".html") and ParseTemplate("hello.html", []byte("hello {{.Name}}"), nil) for templates given as text.

func Pug

func Pug(fs any, extension string) *HTMLEngine

Pug (or Jade) returns a new pug view engine. It shares the same exactly logic with the html view engine, it uses the same exactly configuration. The given "extension" MUST begin with a dot.

A template is turned into html/template text first, so the actions of the html engine ({{ yield . }}, {{ render "name" . }} and the rest) and its layouts work the same. The "include" and "extends" keywords of Pug read from the engine's own file system. Give them the file extension, as in "include partials/footer.pug".

Read more about the Jade Go Parser: https://github.com/Joker/jade

Usage: Pug("./views", ".pug") or Pug(embed.FS, ".pug").RootDir("views") for embedded templates.

func (*HTMLEngine) AddFunc

func (s *HTMLEngine) AddFunc(funcName string, funcBody any)

AddFunc adds the function to the template's function map. It is legal to overwrite elements of the default actions: - render func(fullPartialName string, binding any) (template.HTML, error).

html/template resolves function names when it parses, so the function takes effect at the next load: add it before Load, or before the first render of an engine that loads itself.

func (*HTMLEngine) AddLayoutFunc

func (s *HTMLEngine) AddLayoutFunc(funcName string, funcBody any) *HTMLEngine

AddLayoutFunc adds the function to the template's function map. It is legal to overwrite elements of the default layout actions: - current func() string - partial func(partialName string, binding any) (template.HTML, error) - partial_r func(partialName string, binding any) (template.HTML, error) - part func(partName string, binding any) (template.HTML, error) - render func(fullPartialName string, binding any) (template.HTML, error).

The function takes effect at the next load. Functions belong to the whole template set in html/template, so pages can call it too, and a function of the same name added with AddFunc is replaced by it. The yield action always renders the current page and cannot be replaced.

func (*HTMLEngine) Delims

func (s *HTMLEngine) Delims(left, right string) *HTMLEngine

Delims sets the action delimiters to the specified strings, to be used in templates. An empty delimiter stands for the corresponding default: {{ or }}.

func (*HTMLEngine) ExecuteTemplate

func (s *HTMLEngine) ExecuteTemplate(w io.Writer, name string, layout string, bindingData any) error

ExecuteTemplate executes a template and writes its result to the w writer. The layout is the layout argument or, when that is empty, the one set by Layout. NoLayout renders the template without any.

The engine loads itself first if it was never loaded. It returns a view.ErrTemplateNotFound for a template or a layout that does not exist. Nothing is written to w when the execution fails.

func (*HTMLEngine) Ext

func (s *HTMLEngine) Ext() string

Ext returns the file extension which this view engine is responsible to render. If the filename extension on ExecuteTemplate is empty then this is appended.

func (*HTMLEngine) FS

func (s *HTMLEngine) FS(dirOrFS any) *HTMLEngine

FS sets the directory or the file system the templates are loaded from, replacing the one given to the constructor.

func (*HTMLEngine) Funcs

func (s *HTMLEngine) Funcs(funcMap template.FuncMap) *HTMLEngine

Funcs adds the elements of the argument map to the template's function map. It is legal to overwrite elements of the map. The return value is the template, so calls can be chained.

func (*HTMLEngine) IsLoaded

func (s *HTMLEngine) IsLoaded() bool

IsLoaded reports whether the templates are loaded at least once or not.

func (*HTMLEngine) Layout

func (s *HTMLEngine) Layout(layoutFile string) *HTMLEngine

Layout sets the layout template file which inside should use the {{ yield . }} func to yield the main template file and optionally {{partial/partial_r/render . }} to render other template files like headers and footers

The 'tmplLayoutFile' is a relative path of the templates base directory, for the template file with its extension.

Example: HTML("./templates", ".html").Layout("layouts/mainLayout.html")

// mainLayout.html is inside: "./templates/layouts/".

Note: Layout can be changed for a specific call with the layout argument of view.Render, or with view.Layout and view.WithLayout. Pass NoLayout there to render a template without this layout.

func (*HTMLEngine) Load

func (s *HTMLEngine) Load() error

Load parses the templates to the engine. It's also responsible to add the necessary global functions.

Calling it is optional: an engine that was never loaded loads itself on its first ExecuteTemplate. Call it at startup to find a template that does not parse before the first request does.

It may be called again to parse everything anew. If it fails then, the templates of the previous load keep rendering.

Returns an error if something bad happens, caller is responsible to handle that.

func (*HTMLEngine) Name

func (s *HTMLEngine) Name() string

Name returns the engine's name.

func (*HTMLEngine) Option

func (s *HTMLEngine) Option(opt ...string) *HTMLEngine

Option sets options for the template. Options are described by strings, either a simple string or "key=value". There can be at most one equals sign in an option string. An option string that is unrecognized or otherwise invalid makes Load return an error.

Known options:

missingkey: Control the behavior during execution if a map is indexed with a key that is not present in the map.

"missingkey=default" or "missingkey=invalid"
	The default behavior: Do nothing and continue execution.
	If printed, the result of the index operation is the string
	"<no value>".
"missingkey=zero"
	The operation returns the zero value for the map type's element.
"missingkey=error"
	Execution stops immediately with an error.

func (*HTMLEngine) ParseTemplate

func (s *HTMLEngine) ParseTemplate(name string, contents []byte, funcs template.FuncMap) (err error)

ParseTemplate adds a custom template to the root template. The funcs are for this template only as far as parsing goes: html/template keeps one function map for the whole set.

A template given here is kept, and parsed again on every load. When it returns an error, nothing was added.

func (*HTMLEngine) Reload

func (s *HTMLEngine) Reload(developmentMode bool) *HTMLEngine

Reload if set to true the templates are reloading on each render, use it when you're in development and you don't want to restart the whole app when you edit a template file.

Every render then parses all templates first, one render at a time. Do not use it in production.

func (*HTMLEngine) RootDir

func (s *HTMLEngine) RootDir(root string) *HTMLEngine

RootDir sets the directory to be used as a starting point to load templates from the provided file system. It is what points the engine at a directory of an embed.FS.

It panics if root is not a valid path inside the file system.

func (*HTMLEngine) SetFuncs

func (s *HTMLEngine) SetFuncs(funcMap template.FuncMap) *HTMLEngine

SetFuncs overrides the template funcs with the given "funcMap".

type HandlebarsEngine

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

HandlebarsEngine contains the handlebars view engine structure.

func Handlebars

func Handlebars(fs any, extension string) *HandlebarsEngine

Handlebars creates and returns a new handlebars view engine. The given "extension" MUST begin with a dot.

Usage: Handlebars("./views", ".html") or Handlebars(embed.FS, ".html").RootDir("views") for embedded templates.

func (*HandlebarsEngine) AddFunc

func (s *HandlebarsEngine) AddFunc(funcName string, funcBody any)

AddFunc adds a helper to the templates of this engine. It is legal to overwrite elements of the default actions: - render func(fullPartialName string, binding any) raymond.SafeString.

A helper is given to a template when it is parsed, so it takes effect at the next load: add it before Load, or before the first render of an engine that loads itself.

func (*HandlebarsEngine) AddGlobalFunc

func (s *HandlebarsEngine) AddGlobalFunc(funcName string, funcBody any)

AddGlobalFunc registers a global template function for all Handlebars view engines. A name that is registered already is replaced.

It panics, as raymond does, if funcBody is not a function with one result.

func (*HandlebarsEngine) ExecuteTemplate

func (s *HandlebarsEngine) ExecuteTemplate(w io.Writer, filename string, layout string, bindingData any) error

ExecuteTemplate executes a template and writes its result to the w writer. The layout is the layout argument or, when that is empty, the one set by Layout. NoLayout renders the template without any. A render through a layout needs the data to be a map[string]any or nil.

The engine loads itself first if it was never loaded. It returns a view.ErrTemplateNotFound for a template or a layout that does not exist. Nothing is written to w when the execution fails.

func (*HandlebarsEngine) Ext

func (s *HandlebarsEngine) Ext() string

Ext returns the file extension which this view engine is responsible to render. If the filename extension on ExecuteTemplate is empty then this is appended.

func (*HandlebarsEngine) IsLoaded

func (s *HandlebarsEngine) IsLoaded() bool

IsLoaded reports whether the templates are loaded at least once or not.

func (*HandlebarsEngine) Layout

func (s *HandlebarsEngine) Layout(layoutFile string) *HandlebarsEngine

Layout sets the layout template file, which prints the page where it says {{ yield }} and may use {{ render "name" . }} to render other template files like headers and footers.

The page reaches the layout as a "yield" entry of the template data, so a render through a layout needs the data to be a map[string]any or nil.

func (*HandlebarsEngine) Load

func (s *HandlebarsEngine) Load() error

Load parses the templates to the engine.

Calling it is optional: an engine that was never loaded loads itself on its first ExecuteTemplate. Call it at startup to find a template that does not parse before the first request does.

It may be called again to parse everything anew. If it fails then, the templates of the previous load keep rendering.

Returns an error if something bad happens, user is responsible to catch it.

func (*HandlebarsEngine) Name

func (s *HandlebarsEngine) Name() string

Name returns the handlebars engine's name.

func (*HandlebarsEngine) ParseTemplate

func (s *HandlebarsEngine) ParseTemplate(name string, contents string, funcs template.FuncMap) error

ParseTemplate adds a custom template from text. The funcs are helpers for this template alone.

A template given here is kept, and parsed again on every load. When it returns an error, nothing was added.

func (*HandlebarsEngine) Reload

func (s *HandlebarsEngine) Reload(developmentMode bool) *HandlebarsEngine

Reload if set to true the templates are reloading on each render, use it when you're in development and you don't want to restart the whole app when you edit a template file.

Every render then parses all templates first, one render at a time. Do not use it in production.

func (*HandlebarsEngine) RootDir

func (s *HandlebarsEngine) RootDir(root string) *HandlebarsEngine

RootDir sets the directory to be used as a starting point to load templates from the provided file system. It is what points the engine at a directory of an embed.FS.

It panics if root is not a valid path inside the file system.

type INodeTag

type INodeTag = pongo2.INodeTag

INodeTag type alias for pongo2.InodeTag

type JetArguments

type JetArguments = jet.Arguments

JetArguments is a type alias of `jet.Arguments`, can be used on `AddFunc$funcBody`.

type JetEngine

type JetEngine struct {

	// The Set is the `*jet.Set`, exported to offer any custom capabilities that jet users may want.
	// It is nil until the first Load, ParseTemplate or render.
	Set *jet.Set
	// contains filtered or unexported fields
}

JetEngine is the jet template parser's view engine.

func Jet

func Jet(dirOrFS any, extension string) *JetEngine

Jet creates and returns a new jet view engine. The given "extension" MUST begin with a dot. It panics for an extension other than ".jet", ".html.jet" and ".jet.html".

A Jet template names its own parent with {{ extends }}, so the layout argument of ExecuteTemplate is ignored by this engine.

Usage: Jet("./views", ".jet") or Jet(embed.FS, ".jet").RootDir("views") for embedded templates.

func (*JetEngine) AddFunc

func (s *JetEngine) AddFunc(funcName string, funcBody any)

AddFunc should adds a global function to the jet template set. It takes effect at once, loaded or not.

The function can be a jet.Func, a func(JetArguments) reflect.Value, or any other Go function, which jet calls with the arguments of the template.

func (*JetEngine) AddRuntimeVars

func (s *JetEngine) AddRuntimeVars(ctx *context.Context, vars JetRuntimeVars)

AddRuntimeVars sets or inserts runtime jet variables through the Iris Context. This gives the ability to add runtime variables from different handlers in the request chain, something that the jet template parser does not offer at all.

Usage: engine.AddRuntimeVars(ctx, views.JetRuntimeVars{...}). See `views.AddJetRuntimeVars` if package-level access is more meanful to the code flow.

func (*JetEngine) AddVar

func (s *JetEngine) AddVar(key string, value any)

AddVar adds a global variable to the jet template set. It takes effect at once, loaded or not.

func (*JetEngine) Delims

func (s *JetEngine) Delims(left, right string) *JetEngine

Delims sets the action delimiters to the specified strings, to be used in templates. An empty delimiter stands for the corresponding default: {{ or }}. Should act before `Load` or `view.Handler`.

func (*JetEngine) ExecuteTemplate

func (s *JetEngine) ExecuteTemplate(w io.Writer, filename string, layout string, bindingData any) error

ExecuteTemplate should execute a template by its filename with an optional layout and bindingData. The layout is ignored: a Jet template names its own parent with {{ extends }}.

The engine loads itself first if it was never loaded. It returns a view.ErrTemplateNotFound for a template that does not exist.

func (*JetEngine) Ext

func (s *JetEngine) Ext() string

Ext should return the final file extension which this view engine is responsible to render. If the filename extension on ExecuteTemplate is empty then this is appended.

func (*JetEngine) IsLoaded

func (s *JetEngine) IsLoaded() bool

IsLoaded reports whether the templates are loaded at least once or not.

func (*JetEngine) Load

func (s *JetEngine) Load() error

Load parses every template, to find the ones that do not parse, and empties the cache, so that each template is read again when it is next rendered.

Calling it is optional: an engine that was never loaded loads itself on its first ExecuteTemplate. Call it at startup to find a template that does not parse before the first request does.

func (*JetEngine) Name

func (s *JetEngine) Name() string

Name returns the jet engine's name.

func (*JetEngine) ParseTemplate

func (s *JetEngine) ParseTemplate(name string, contents string) error

ParseTemplate accepts a name and contnets to parse and cache a template. This parser does not support funcs per template. Use the `AddFunc` instead.

When it returns an error, nothing was added.

func (*JetEngine) Reload

func (s *JetEngine) Reload(developmentMode bool) *JetEngine

Reload if setted to true the templates are reloading on each render, use it when you're in development and you don't want to restart the whole app when you edit a template file.

Every render then parses all templates first, as in the other engines, and jet is put in its development mode, in which it reads the template it renders again. Call it before the engine loads. Do not use it in production.

func (*JetEngine) RootDir

func (s *JetEngine) RootDir(root string) *JetEngine

RootDir sets the directory to be used as a starting point to load templates from the provided file system. It is what points the engine at a directory of an embed.FS.

It panics if root is not a valid path inside the file system.

func (*JetEngine) SetLoader

func (s *JetEngine) SetLoader(loader jet.Loader) *JetEngine

SetLoader can be used when the caller wants to use something like multi.Loader or httpfs.Loader. The templates are then read from that loader and not from the file system given to Jet.

func (*JetEngine) String

func (s *JetEngine) String() string

String returns the name of this view engine, the "jet".

type JetRuntime

type JetRuntime = jet.Runtime

JetRuntime is a type alias of `jet.Runtime`, can be used on RuntimeVariable input function.

type JetRuntimeVars

type JetRuntimeVars = jet.VarMap

JetRuntimeVars is a type alias for `jet.VarMap`. Can be used at `AddJetRuntimeVars/JetEngine.AddRuntimeVars` to set a runtime variable ${name} to the executing template.

type Parser

type Parser = pongo2.Parser

Parser type alias for pongo2.Parser

type TagParser

type TagParser = pongo2.TagParser

TagParser the function signature of the tag's parser you will have to implement in order to create a new tag.

'doc' is providing access to the whole document while 'arguments' is providing access to the user's arguments to the tag:

{% your_tag_name some "arguments" 123 %}

start_token will be the *Token with the tag's name in it (here: your_tag_name).

Please see the Parser documentation on how to use the parser. See `RegisterTag` for more information about writing a tag as well.

type Token

type Token = pongo2.Token

Token type alias for pongo2.Token

type Value

type Value = pongo2.Value

Value type alias for pongo2.Value

Directories

Path Synopsis
_examples
embedding-templates-into-app command
Templates compiled into the binary, with layouts and a partial.
Templates compiled into the binary, with layouts and a partial.
overview command
The HTML engine: a directory of templates, rendered through the view middleware.
The HTML engine: a directory of templates, rendered through the view middleware.
write-to command
An engine renders into any io.Writer, with no request and no server.
An engine renders into any io.Writer, with no request and no server.

Jump to

Keyboard shortcuts

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