Pongo2 Tutorial
Note: in Sprouts, Pongo2 is being deprecated in favor of Scriggo!
Files ending in .tmpl or .pgo2 are interpreted as Pongo2 templates.
The basic idea is very similar to Django or Jinja templates, but not all Jinja's features are supported.
I'm not aware of a complete reference documentation for Pongo2, but if you are familiar with Django/Jinja templates, you can pick it up quite easily.
I will try to give a basic rundown of the most common/useful features.
To start, you can treat template files as regular html files with some special additional syntax.
Expressions are enclosed by {{ ... }} double curlies, while special constructs
are indicated with {% ... %}
Let's go over some useful constructs one by one.
Includes
The include directive will include the content of one file into another file
{% include "snippet.html" %}
The path specified is relative to the current template file being executed.
Filters
Like Django and Jinja, you can pass strings to filter functions with the pipe operator:
{{ "hello world"|title }}
Will produce:
Hello World
You can also use the filter tag:
{% filter title %}hello world{% endfilter %}
The following is a list of builtin filter names that ship with Pongo2:
escape
e // alias of `escape`
safe
escapejs
add
addslashes
capfirst
center
cut
date
default
default_if_none
divisibleby
first
floatformat
get_digit
iriencode
join
last
length
length_is
linebreaks
linebreaksbr
linenumbers
ljust
lower
make_list
phone2numeric
pluralize
random
removetags
rjust
slice
split
stringformat
striptags
time // time uses filterDate (same golang-format)
title
truncatechars
truncatechars_html
truncatewords
truncatewords_html
upper
urlencode
urlize
urlizetrunc
wordcount
wordwrap
yesno
float // pongo-specific
integer // pongo-specific
You can use Django's filter documentation for reference on what these filters do.
Markup languages
Sprouts adds a few more filters that can be used with the filter tag to write blocks of text in a markup language.
- markdown: write a block of markdown text
- d2: D2 diagramming language
- chroma: syntax highlighted code block
Text in these blocks can be indented and the indentation will be stripped before processing the text.
{% filter markdown %}
# Introduction
This is an example markdown block. Text here will be processed as markdown.
```go
func Hello() {
// this is a code block
}
```
{% endfilter %}
You can mix and match blocks by using multiple filters in sequence
{% filter markdown %}
Some markdown text
{% endfilter %}
{% filter d2 %}
a -> b
{% endfilter %}
Macros
When you have a repeated html pattern, you can capture it in a macro.
Let's say that you want to list out your most important essays:
<div class="essay card">
<a href="/essays/scrum">
<h2>📊 Why Scrum doesn't work, and what to do instead</h2>
</a>
<a href="/essays/scrum">
<h3>How to manage software projects</h3>
</a>
</div>
<div class="essay card">
<a href="/essays/manifesto">
<h2>📜 The Straight Forward Programming Manifesto</h2>
</a>
<a href="/essays/manifesto">
<h3>It's all about the data!</h3>
</a>
</div>
<div class="essay card">
<a href="/essays/fake-problems">
<h2>🚀 The Tyranny of the Fake Problems Equation</h2>
</a>
<a href="/essays/fake-problems">
<h3>The more solutions you have, the more solutions you need!</h3>
</a>
</div>
All essay elements have the same basic structure, so we can define a macro like this:
{% macro essay_card(url, title, subtitle) %}
<div class="essay card">
<a href="{{ url }}">
<h2>{{ title }}</h2>
</a>
<a href="{{ url }}">
<h3>{{ subtitle }}</h3>
</a>
</div>
{% endmacro %}
And use it by invoking it like this:
{{ essay_card("/essays/scrum", "📊 Why Scrum doesn't work, and what to do instead", "How to manage software projects") }}
{{ essay_card("/essays/manifesto", "📜 The Straight Forward Programming Manifesto", "It's all about the data!") }}
{{ essay_card("/essays/fake-problems", "🚀 The Tyranny of the Fake Problems Equation", "The more solutions you have, the more solutions you need!") }}
The basic structure to define a macro is:
{% macro macro_name(params) %}
body
{% endmacro %}
Inside the macro body, you can refernce passed parameters using the double curly braces.
To use a macro, you "call" it inside an expressed surrounded with curly braces:
{{ macro_name(params) }}
One limitation of the macro system in Pongo is the lack of caller() expression
found in Jinja, meaning you cannot define a macro to wrap a "body" of text; only
parameters are supported.
Shared layouts with extends and block
A template file can be used as a "skeleton" with "holes" to be filled in by other templates that "extend" it.
In the base (layout) template, you declare named blocks with some default content.
To create a template using the base template, you extend it and fill in the blocks with custom content.
Very basic example of a _base.tmpl file:
<html>
<head>
<title>{% block title %}Default Title{% endblock %}</title>
</head>
<body>
{% block content %}
{% endblock %}
</body>
</html>
In the same directory you can create, for example, 'about.tmpl':
{% extends "_base.tmpl" %}
{% block title %}About Us{% endblock %}
{% macro Content %}
<insert content here>
{% endblock %}
Note: by starting the filename with an underscore, it becomes "private": sprouts will not serve it if someone requests the url to it.