pongo2 is a Django-syntax like templating-language

Overview

pongo2

PkgGoDev Build Status

pongo2 is a Django-syntax like templating-language (official website).

Install/update using go get (no dependencies required by pongo2):

go get -u github.com/flosch/pongo2/v4

Please use the issue tracker if you're encountering any problems with pongo2 or if you need help with implementing tags or filters (create a ticket!).

First impression of a template

<html>
  <head>
    <title>Our admins and userstitle>
  head>
  {# This is a short example to give you a quick overview of pongo2's syntax. #}
  {% macro user_details(user, is_admin=false) %}
  <div class="user_item">
    
    <h2 {% if (user.karma>
      = 40) || (user.karma > calc_avg_karma(userlist)+5) %} class="karma-good"{%
      endif %}>

      
      {{ user }}
    h2>

    
    <p>This user registered {{ user.register_date|naturaltime }}.p>

    
    <p>The user's biography:p>
    <p>
      {{ user.biography|markdown|truncatewords_html:15 }}
      <a href="/user/{{ user.id }}/">read morea>
    p>

    {% if is_admin %}
    <p>This user is an admin!p>
    {% endif %}
  div>
  {% endmacro %}

  <body>
    

    <h1>Our adminsh1>
    {% for admin in adminlist %} {{ user_details(admin, true) }} {% endfor %}

    <h1>Our membersh1>
    {% for user in userlist %} {{ user_details(user) }} {% endfor %}
  body>
html>

Features

Caveats

Filters

  • date / time: The date and time filter are taking the Golang specific time- and date-format (not Django's one) currently. Take a look on the format here.
  • stringformat: stringformat does not take Python's string format syntax as a parameter, instead it takes Go's. Essentially {{ 3.14|stringformat:"pi is %.2f" }} is fmt.Sprintf("pi is %.2f", 3.14).
  • escape / force_escape: Unlike Django's behaviour, the escape-filter is applied immediately. Therefore there is no need for a force_escape-filter yet.

Tags

  • for: All the forloop fields (like forloop.counter) are written with a capital letter at the beginning. For example, the counter can be accessed by forloop.Counter and the parentloop by forloop.Parentloop.
  • now: takes Go's time format (see date and time-filter).

Misc

  • not in-operator: You can check whether a map/struct/string contains a key/field/substring by using the in-operator (or the negation of it): {% if key in map %}Key is in map{% else %}Key not in map{% endif %} or {% if !(key in map) %}Key is NOT in map{% else %}Key is in map{% endif %}.

Add-ons, libraries and helpers

Official

  • pongo2-addons - Official additional filters/tags for pongo2 (for example a markdown-filter). They are in their own repository because they're relying on 3rd-party-libraries.

3rd-party

Please add your project to this list and send me a pull request when you've developed something nice for pongo2.

Who's using pongo2

I'm compiling a list of pongo2 users. Add your project or company!

API-usage examples

Please see the documentation for a full list of provided API methods.

A tiny example (template string)

// Compile the template first (i. e. creating the AST)
tpl, err := pongo2.FromString("Hello {{ name|capfirst }}!")
if err != nil {
    panic(err)
}
// Now you can render the template with the given
// pongo2.Context how often you want to.
out, err := tpl.Execute(pongo2.Context{"name": "florian"})
if err != nil {
    panic(err)
}
fmt.Println(out) // Output: Hello Florian!

Example server-usage (template file)

package main

import (
    "github.com/flosch/pongo2/v4"
    "net/http"
)

// Pre-compiling the templates at application startup using the
// little Must()-helper function (Must() will panic if FromFile()
// or FromString() will return with an error - that's it).
// It's faster to pre-compile it anywhere at startup and only
// execute the template later.
var tplExample = pongo2.Must(pongo2.FromFile("example.html"))

func examplePage(w http.ResponseWriter, r *http.Request) {
    // Execute the template per HTTP request
    err := tplExample.ExecuteWriter(pongo2.Context{"query": r.FormValue("query")}, w)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

func main() {
    http.HandleFunc("/", examplePage)
    http.ListenAndServe(":8080", nil)
}
Issues
  • Add virtual filesystem with support for template inheritance

    Add virtual filesystem with support for template inheritance

    Maybe provide an interface that allows custom implementation of how to retrieve files.

    enhancement 
    opened by unknwon 31
  • Implement caching

    Implement caching

    Would it make sense to have a built-in template cache which is enabled in production only (non debug)?. I can see you're currently doing this in https://github.com/macaron-contrib/pongo2/blob/master/pongo2.go where you're integrating pongo2 with a web framework. I think it would make sense to have the template cache in pongo2. Otherwise this work has to be redone when integrating with multiple frameworks which is a hassle.

    Could be as simple as if the template is in cache and we're not in debug, load it from cache, otherwise reparse it.

    enhancement 
    opened by ahall 26
  • Reusable macros

    Reusable macros

    in jinja2 you can do something like this:

    {% from "helpers/macros.html" import my_reusable_macro, my_reusable_macro2 %}
    
    {{ my_reusable_macro() }}
    

    Would it make sense to implement so macros can be imported and reused instead of them having to be in the same template file as they're used in?

    enhancement 
    opened by ahall 23
  • The truncatewords tag does not support Chinese

    The truncatewords tag does not support Chinese

    case 1: {{ "中文字符"|truncatewords:1|safe }} The expected output a character (中), but in fact, if there is no space, then is unable to determine, so lead to dividing Chinese characters. Because the Chinese character do not need to rely on a space character segmentation.

    case 2: {{ "中文 字符"|truncatewords:1|safe }} Expected output a character (中), but in fact the output two characters(中文).

    bug 
    opened by insionng 12
  • Unimplemented filter usage gives not clear panic message

    Unimplemented filter usage gives not clear panic message

    I got panic message while template execution:

    2014/07/22 04:07:25 PANIC: runtime error: invalid memory address or nil pointer dereference
    /usr/local/Cellar/go/1.3/libexec/src/pkg/runtime/panic.c:552 (0x10d2d)
        panicstring: runtime·panic(err);
    /usr/local/Cellar/go/1.3/libexec/src/pkg/runtime/os_darwin.c:454 (0xf9ce)
        sigpanic: runtime·panicstring("invalid memory address or nil pointer dereference");
    /Users/vgarvardt/Sites/blogo/.godeps/src/github.com/flosch/pongo2/template.go:66 (0x126080)
        (*Template).execute: panic(string(tpl.size))
    /Users/vgarvardt/Sites/blogo/.godeps/src/github.com/flosch/pongo2/template.go:133 (0x126474)
        (*Template).Execute: buffer, err := tpl.execute(context)
    ...
    

    I found that panic occurs when I used join filter that is not implemented yet. It would be much easier to debug templates when panic can give more informative messages, e.g. "unknown filter found 'join'".

    PS: btw, thanks for the project - even without lots of filters and tags implemented it makes my life much easier =)

    invalid 
    opened by vgarvardt 11
  • Base directory

    Base directory

    I usually have my templates in a separate directory e.g. structures something like:

    templates/base.html
    templates/user/index.html
    

    In user.html I'd like to do something like:

    {% extends "base.html" %}
    

    Currently having to reference it like {% extends "../base.html" %}. I'd prefer if I could specify a template root and then reference it like a sandbox. It would also let me render "user/index" within the sandbox instead of specifying the full path. Does this make sense? Thanks for a great project, it's looking very useful.

    enhancement 
    opened by ahall 11
  • Can't use map[string]struct in template

    Can't use map[string]struct in template

    I have a data with this type:

    type Data struct{
    ...
    }
    var datas := make(map[string]Data,0)
    ...
    

    and in the template,i want to access the data through it's id:

    {{datas["somename"]}}
    

    and got an error:

    Handler crashed with error [Error (where: lexer) in views/sample.cfg | Line 36 Col 44] Unknown character: '[' (91)
    2015/01/26 12:43:13 [router.go:883] [C] /usr/src/go/src/runtime/asm_amd64.s:402
    2015/01/26 12:43:13 [router.go:883] [C] /usr/src/go/src/runtime/panic.go:387
    2015/01/26 12:43:13 [router.go:883] [C] /go/src/github.com/flosch/pongo2/pongo2.go:11
    
    opened by magicshui 10
  • Error message missing file path(#2)

    Error message missing file path(#2)

    panic: open templates\header: The system cannot find the file specified.
    

    Now I found another mistake information missing file path problem. I know this error is due to the lack of HTML suffix caused. But, I don't know who is calling this a line of code, I need to know who is calling.

    invalid 
    opened by insionng 10
  • Problem with macros calling macros

    Problem with macros calling macros

    See #40 for a detailed bug report.

    bug needs evaluation 
    opened by flosch 10
  • Is it a wrong grammar?

    Is it a wrong grammar?

                      {% for k,v in images %}
    

    V is why I get a null value?

    question 
    opened by insionng 10
  • Is pongo2 support using embed.FS ?

    Is pongo2 support using embed.FS ?

    I'm trying to embed my template using embed.FS is it supported ?

    opened by fahmifan 1
  • Update README.md

    Update README.md

    add Compatible with pongo version 4 for gin and add Compatible with pongo version 4 for echo framework

    opened by stnc 1
  • Update README.md

    Update README.md

    add Compatible with pongo version 4 for gin

    opened by stnc 1
  • Add support for numeric map keys

    Add support for numeric map keys

    I have data from an external source which contains map[string]interface{} instances with numeric keys:

    map[string]interface{}{
      "0": "foo",
      "1": "bar",
    }
    

    I'm trying to access this map via this template {{ mydict.0 }} as I would a regular map, but Pongo2 doesn't seem to allow this:

    Can't access an index on type map (variable mydict.0)
    

    This PR adds this capability.

    opened by Richtermeister 1
  • Expose some fields and methods for implementing custom tags

    Expose some fields and methods for implementing custom tags

    I am trying to make a custom tag that loads another template file like include, extends and ssi tag. I checked these built-in tags implementation. They use the code such as doc.template.set.resolveFilename(…) and doc.template.set.FromFile(…) to load a template.

    For example:

    https://github.com/flosch/pongo2/blob/af96a40c67441cd0115b536609f9d1de2f979821/tags_include.go#L45

    https://github.com/flosch/pongo2/blob/af96a40c67441cd0115b536609f9d1de2f979821/tags_include.go#L47

    But the same code can’t be used in my custom tag implementation. Because, doc.template, doc.template.set and some methods are private.

    This PR makes some field and methods public for implementing custom tags that load another templates. Could you please merge it?

    opened by kohkimakimoto 1
  • Access context from filter

    Access context from filter

    It would be a good feature if we could access the context from a filter and use some global variables here, like the selected language, using of preview mode, etc.

    For example, consider the following email template:

    <tr>
    	<td><b>{{'mail_order_id'|lang:ln}}</b></td>
    	<td>{{order.Id}}</td>
    </tr>
    <tr>
    	<td><b>{{'mail_order_name'|lang:ln}}</b></td>
    	<td>{{order.Name}}</td>
    </tr>
    

    Here we have a custom filter, which can translate the corresponding strings. But we have to pass the ln param to every filter, because the filter itself doesn't know the actual language, however it has been set in the context (context["ln"] = "en").

    Another example is an embedded image: <img src="{{'spacer.gif'|images:preview}}"/> Here the filter replaces the src to a full URL (in preview mode) or to a cid:xxxx embed mark. Another issue here is that we need to store somehow which images we should include later, when sending the actual mail, so we can embed them. Now we have to rescan the template file, looking for src attribs and css backgrounds, and get the images from here, however the images filter could do that for us and store the image list on the context itself. Later we can easily grab the info from here.

    Thanks for your great work!

    opened by globizcorp 0
  • Documentation

    Documentation

    Hey, thanks for the templating package.

    As someone coming from a Go background and not a Django background, the thing I find most missing is a concise list of features, filters, and so on. It took me about 10 minutes to search around and figure out how to check the length of an array because it seems like the user is expected to know about the length filter, or to go over to the Django docs to find it?

    I think it would be a big usability win to have your own concise listing of all features, functions, filters, etc. See for example the Jet templating docs.

    Thanks for your consideration.

    opened by tooolbox 1
  • Try to parse time

    Try to parse time

    Hi,

    As of now, date, time, and other related date/time filters only work with inputs of type time.Time.

    Often, we receive data from a JSON and therefore the value is of type string and not time.Time. This makes the date/time filters not usable.

    As an example, in the filterDate function of the file filters_builtin.go, would it be possible to:

    1. Try type assertion with time.Time which is currently the case.
    2. If the previous failed, try type assertion to string, and then make use of time.Parse given the param passed to have a valid time.Time

    What do you think?

    opened by mytototo 0
  • Adds support for negative to bound in slice filter

    Adds support for negative to bound in slice filter

    Related to issue #263, I ended up using a custom filter in my own template that just adds an extra branch in filterSlice to calculate & check the negative to bound

    opened by gbts 2
  • Slice filter ignores negative bounds

    Slice filter ignores negative bounds

    e.g. the expected output of {{ "mystring1" | slice:":-1"}} would be mystring, but instead it's just mystring1

    opened by gbts 0
Releases(v4.0.2)
  • v4.0.0(Sep 13, 2020)

    Changes in this long awaited release:

    Library

    • First semver version with Go modules compatibility
    • Several bug fixes
    • Improved error handling
    • Several refactorings to speed up execution and reduce allocations, including support for io.Writerin Execute() functions and short-circuit evaluations in expressions
    • Add TemplateSet.FromBytes
    • Add RenderTemplateBytes
    • Add Template.ExecuteWriterUnbuffered
    • Add TemplateLoader interface and according functions for virtual filesystem support (incl. support for multiple loaders)
    • Add pongo2.SetAutoescape for a global behavior change
    • Add whitespace control for tags and blocks, supporting {%- and -%} for tags and pongo2.Options for blocks
    • Add pongo2.CleanCache to remove files from the template cache
    • Add support for template functions that return an error as the second return value
    • Add Template.ExecuteBlocks to render supplied list of blocks only

    See https://github.com/flosch/pongo2/compare/v3.0...v4.0.0 for a full list of changes. Thanks to all contributors!

    Template Language

    • Add support for single quotes in variables, functions and tags
    • Add support for if_exists-flag in include-tag
    • Add support for sorted-flag in for-tag with support for maps and arrays/slices
    • Add block.Super support
    • Add split filter
    Source code(tar.gz)
    Source code(zip)
  • v2.1(Oct 27, 2014)

  • v3.0(Oct 27, 2014)

  • v2(Oct 4, 2014)

    I'm happy to release the first major update for pongo2: v2. It got a lot of new features and bug fixes. Thanks to all reporters and contributors.

    This release is backwards-incompatible to v1 which means chances are you have to adapt your codebase (slightly) in order to use v2. The pongo2 playground already uses pongo v2 (including the new features like sandboxing) and now got the official pongo2-addons package enabled for testing and playing with pongo2. pongo2-addons is already ready to use with pongo v2.

    To install v2 and get backwards-compatible changes and bugfixes for later versions of the v2 series, use this import path:

    gopkg.in/flosch/pongo2.v2 (documentation)

    Use this import path to stick with the latest development version of pongo2:

    github.com/flosch/pongo2 (documentation)

    New major features

    • Template sets: pongo2 allows to group similar kind of templates using a technique called template sets (for example web vs. email templates). Users can apply different configurations and sandbox restrictions (see below) on a specific template set. A default template set is created when pongo2 is imported (this is the one all pongo2-global API functions like From* are working on); see the DefaultSet here. Features of the template sets include:
      • Debugging: If Debug is set to true, logging of specific errors occur to stdout (you can print out errors as well using the new ExecutionContext.Logf function which will only print out your logging information when Debug is true). Debug has implications on the new template caching function as well (see below).
      • Globals: It is now possible to provide a global context (in addition to a per-template context) for a template set. It's always possible to override global variables through a per-template context.
      • Base directory: The previous behavior of a filename lookup (inside templates, for example when using the include, extends or ssi-tag, or outside templates when calling the From*()-functions) was, in case of a relative path, to lookup the filename relative to the application's directory or, in case of an absolute path, to take this absolute one. It's now possible to change the base lookup directory (for relative paths) by using the new template set functions SetBaseDirectory() and BaseDirectory().
      • Sandboxing: To provide more security, pongo2 introduces a per-template-set sandbox. It can prohibit the usage of filters and tags or restrict file accesses (within templates when using a file-sensitive tag/filter like include or outside of templates when using a function like From*()). Use the attribute SandboxDirectories to provide path patterns supported by http://golang.org/pkg/path/filepath/#Match in order to restrict the access to specifc files or directories. You can limit the tag/filter access by using the two new template set functions BanFilter and BanTag.
    • Template caching: pongo2 introduces a new API function FromCache which behaves like FromFile, but includes caching: FromCache only compiles a template once per template (even if called multiple times) and can be called from multiple Goroutines (it's thread-safe). When debugging is activated (see above), FromCache will re-compile the given template on any request (simplifies development to see live changes).
    • Macro imports/exports: pongo2 supports now importing and exporting of macros. Exporting is done by appending the export keyword to your macro declaration (like this: {% macro my_exported_macro(args1, args2="default string") export %}). You can import exported macros by using the new import tag: {% import "my_file_with_macros.html" my_exported_macro, another_exported_macro as renamed_macro %}. Macros import macros (chaining macros) is supported.
    • New pongo2-specific tag set: Sets a variable to a given expression like this: {% set my_variable = 5 + 10 / another_var_number %}

    New minor features

    • Added support for the reversed argument for the for-tag
    • elif-tag added (to support multiple cases when using the if-tag)
    • It's now possible to replace the behavior of already registered tags and filters through 2 new API-functions: ReplaceTag and ReplaceFilter.
    • It's now possible to mark a pongo2.Value as safe (so the escape filter won't get applied when outputting the value) using the new API-function AsSafeValue. This reduces the necessary to apply the safe filter manually, for example when using the markdown filter from the pongo2-addons package.
    • New Error type which returns detailed machine-readable information (including the affected raw template line) about the error occurred and is now much more specific in some cases on which error occurred

    Bugfixes and other improvements

    • Better UTF-8 handling of filters and tags
    • Performance of template execution improved
    • Bugfix in handling of the parsed argument of the ssi-tag
    • Bugfix related to the operator associativity
    • Better documentation (but still not perfect)

    Notable backward-incompatible API-changes (v1 <-> v2):

    • The interface type INodeEvavluator got replaced by IEvaluator
    • Function signature for tag and filter parsing/execution changed (error return type changed to *Error).

    See the whole changelog here: https://github.com/flosch/pongo2/compare/v1...v2

    As always, I'm happy about any feedback!

    Source code(tar.gz)
    Source code(zip)
  • v1.0(Aug 8, 2014)

    I'm happy to announce pongo2 v1.0, the first stable release.

    pongo2 aims to be compatible with Django 1.7 with regards to syntax, filters and tags. In combination with my official package pongo2-addons pongo2 offers even more filters/tags including humanization and markup features.

    All version 1.x releases will remain backwards compatible (only API improvements are possible, but no changes to any existing API functions/symbols). You can use the special import path

    gopkg.in/flosch/pongo2.v1

    to stick with version 1.x releases in your projects.

    List of TODOs which could effect users of version 1.0:

    • tag verbatim does not take a parameter yet
    • block.super not supported yet
    • Value.Iterate() over strings is not utf-8 compatible yet (probably rarely used by users)

    Please also have a look on the caveats and on the development status hints when using pongo2.

    pongo2 got a playground; feel free to play with it and to try pongo2 out.

    I'm always glad about any feedback. I hope you enjoy this release!

    Source code(tar.gz)
    Source code(zip)
  • v1.0-rc1(Jul 29, 2014)

Owner
Florian Schlachter
Computer scientist with interests in compilers/programming languages, security & privacy, hardware architectures, networking and web development.
Florian Schlachter
A strongly typed HTML templating language that compiles to Go code, and has great developer tooling.

A language, command line tool and set of IDE extensions that makes it easier to write HTML user interfaces and websites using Go.

Adrian Hesketh 80 Sep 18, 2021
An ERB-style templating language for Go.

Ego Ego is an ERb style templating language for Go. It works by transpiling templates into pure Go and including them at compile time. These templates

Ben Johnson 504 Sep 13, 2021
Templating system for HTML and other text documents - go implementation

FAQ What is Kasia.go? Kasia.go is a Go implementation of the Kasia templating system. Kasia is primarily designed for HTML, but you can use it for any

Michał Derkacz 72 May 4, 2021
"to be defined" - a really simple way to create text templates with placeholders

tbd "to be defined" A really simple way to create text templates with placeholders. This tool is deliberately simple and trivial, no advanced features

Luca Sepe 16 Aug 29, 2021
Programatic document generation as a HTTP service. Render PDFs using LaTeX templates and JSON.

LaTTe Generate PDFs using LaTeX templates and JSON. Try out the demo! Find LaTTe on Docker Hub Table of Contents About Obtaining LaTTe Running & Using

Raphael Reyna 173 Sep 18, 2021
A sweet velvety templating package

Velvet Velvet is a templating package for Go. It bears a striking resemblance to "handlebars" based templates, there are a few small changes/tweaks, t

Buffalo - The Go Web Eco-System 73 Sep 17, 2021
Razor view engine for go

gorazor gorazor is the Go port of the razor view engine originated from asp.net in 2011. In summary, gorazor is: Extremely Fast. Templates are convert

null 787 Sep 13, 2021
Fast, powerful, yet easy to use template engine for Go. Optimized for speed, zero memory allocations in hot paths. Up to 20x faster than html/template

quicktemplate A fast, powerful, yet easy to use template engine for Go. Inspired by the Mako templates philosophy. Features Extremely fast. Templates

Aliaksandr Valialkin 2.2k Sep 22, 2021
The powerful template system that Go needs

Plush Plush is the templating system that Go both needs and deserves. Powerful, flexible, and extendable, Plush is there to make writing your template

Buffalo - The Go Web Eco-System 657 Sep 22, 2021
Amber is an elegant templating engine for Go Programming Language, inspired from HAML and Jade

amber Notice While Amber is perfectly fine and stable to use, I've been working on a direct Pug.js port for Go. It is somewhat hacky at the moment but

Ekin Koc 879 Aug 23, 2021
HTML template engine for Go

Ace - HTML template engine for Go Overview Ace is an HTML template engine for Go. This is inspired by Slim and Jade. This is a refinement of Gold. Exa

Keiji Yoshida 805 Sep 22, 2021
Goview is a lightweight, minimalist and idiomatic template library based on golang html/template for building Go web application.

goview Goview is a lightweight, minimalist and idiomatic template library based on golang html/template for building Go web application. Contents Inst

foolin 246 Sep 20, 2021
A handy, fast and powerful go template engine.

Hero Hero is a handy, fast and powerful go template engine, which pre-compiles the html templates to go code. It has been used in production environme

Lime 1.5k Sep 20, 2021
A complete Liquid template engine in Go

Liquid Template Parser liquid is a pure Go implementation of Shopify Liquid templates. It was developed for use in the Gojekyll port of the Jekyll sta

Oliver Steele 134 Sep 3, 2021
Article spinning and spintax/spinning syntax engine written in Go, useful for A/B, testing pieces of text/articles and creating more natural conversations

GoSpin Article spinning and spintax/spinning syntax engine written in Go, useful for A/B, testing pieces of text/articles and creating more natural co

Miles Croxford 28 Sep 3, 2021
Package damsel provides html outlining via css-selectors and common template functionality.

Damsel Markup language featuring html outlining via css-selectors, extensible via pkg html/template and others. Library This package expects to exist

Daniel Skinner 24 Sep 12, 2020
Simple system for writing HTML/XML as Go code. Better-performing replacement for html/template and text/template

Simple system for writing HTML as Go code. Use normal Go conditionals, loops and functions. Benefit from typing and code analysis. Better performance than templating. Tiny and dependency-free.

Nelo Mitranim 3 Sep 8, 2021
A PDF document generator with high level support for text, drawing and images

GoFPDF document generator Package gofpdf implements a PDF document generator with high level support for text, drawing and images. Features UTF-8 supp

Kurt Jung 3.9k Sep 21, 2021
A template to build dynamic web apps quickly using Go, html/template and javascript

gomodest-template A modest template to build dynamic web apps in Go, HTML and sprinkles and spots of javascript. Why ? Build dynamic websites using th

Adnaan Badr 54 Sep 17, 2021