Skip to content
This repository has been archived by the owner on Mar 15, 2018. It is now read-only.

Guide to Templates

Matt Basta edited this page Dec 7, 2013 · 6 revisions

Nunjucks is the templating engine used in Commonplace. Templates are stored in the src/templates/ directory. The Damper will automatically compile templates into templates.js, which will be loaded by require.js. The CLI tools will also compile templates when running compile includes and commonplace compile.

Documentation for Nunjucks can be found in the Nunjucks pages

Differences from "vanilla" Nunjucks

Commonplace makes some minor changes to the generated code from Nunjucks. These changes are made to improve the size and efficiency of the final product.

  • Undefined functions will throw errors when called. In vanilla Nunjucks, calling a function that's not defined will simply return "".
  • Whitespace is stripped. In Commonplace, compiled templates will strip whitespace in a number of ways.
  • Whitespace between Nunjucks code will be collapsed: {{ foo }} {{ bar }} becomes {{ foo }} {{ bar}}
  • Whitespace between Nunjucks code and markup will be stripped: {{ foo }} <div> becomes {{ foo }}<div>
  • Whitespace between Nunjucks code and non-markup will be collapsed: {{ foo }} class=" becomes {{ foo }} class="
  • Whitespace within non-Nunjucks code that begins with a line break will be collapsed or removed: </div>\n foo becomes </div>\nfoo
  • Certain features from Jinja2 are added. The features added can be found in nunjucks.compat.js. These features exist mainly to add list and dictionary methods from Python to Nunjucks.
  • Note that use of True and False will map to true and false during compilation for performance reasons; i.e.: they will not be looked up at runtime.
  • Some safe functions will not be escaped. Some functions which otherwise return SafeString instances will not be escaped if they are outputted directly. These include _(), _plural(), url(), media(), api(), and apiParams().

In virtually all cases, these changes should not impact everyday development and should remain transparent to developers. Undefined functions will throw TypeErrors which may be problematic in some circumstances, though this will ultimately lead to greater code quality and faster generated templates.

API

Filters

The filter list includes all filters provided by Nunjucks. The complete list of Nunjucks-provided filters can be found in the Nunjucks docs.

NOTE: The default Nunjucks urlencode filter has been replaced with the utils.urlencode method to avoid duplication.

|extend()

{{ object|extend(foo=bar[, key=value]) }}
{{ object|extend(kwargs) }}

The |extend() filter extends (via _.extend) an object and returns the new object. Keyword arguments may be provided, but an object of properties is also accepted.

|urlparams()

{{ url|urlparams(param=value[, key=value]) }}

This filter adds or overwrites URL parameters to a URL. A URL is accepted as the base. This uses utils.urlparams.

|urlunparam()

{{ url|urlunparam(list) }}

This filter removes parameters from a URL if they exist. list is expected to contain an array of strings where the strings describe the names of parameters to remove. A URL is accepted as the base. This uses utils.urlunparam.

|nl2br

{{ url|nl2br }}

This filter replaces all line breaks with <br>. The output of this filter is NOT escaped.

|make_data_attrs

{{ url|make_data_attrs }}

This filter converts an object to a string of data attributes. For example:

builder.start('template.html', {obj: {foo: '123'}});
{{ obj|make_data_attrs }}

will result in:

data-foo="123"

|external_href

{{ url|external_href }}

This filter returns a set of attributes to link to an external document.

{{ 'http://google.com/'|external_href }}

will result in:

href="http://google.com/" target="_blank"

The output of this filter is NOT escaped.

|translate()

{{ data|translate }}
{{ data|translate([default_language[, language]]) }}

If applied to a string, this will simply return the string.

When applied to a localization object, this will return the proper localization for the user. More information can be found in the utils section.

|numberfmt

{{ my_favorite_number|numberfmt }}

If the value passed to this filter is typeof number and the platform implements Number.prototype.toLocaleString, the toLocaleString() is called on the passed value and returned. Otherwise, the passed value is returned without changes.

|datetime

{{ my_favorite_date|datetime }}

If the value passed is falsey, an empty string is returned.

If the value passed is not a date, it is passed to the Date() function in an attempt to convert it to a date. toLocaleString() is called on the passed object. If the result is "Invalid Date", an empty string is returned. Otherwise, the result is returned.

|filter()

{{ list|filter(kwargs) }}
{{ list|filter(condition=value[, key=value]) }}

This filter will filter an array of input and return a new array that matches the criteria it is passed. Criteria can either be passed as keyword arguments or as an object containing key-value pairs of criteria.

Criteria is matched exactly. For each key in the criteria, each input object will be tested to contain the criterion key and the value will be tested to exactly match the value. If the criterion value is an array, the input object's value will instead be tested to be contained in the criterion value (criterion.indexOf(value) !== 1).

The order of the original input will be maintained.

|hex2rgba()

{{ my_favorite_hex_value|hex2rgba(opacity) }}

This filter accepts a string in standard hex format (/[a-fA-F0-9]{6}/) with an optional leading hash. Three-character hex values are not accepted. opacity is expected to be a value that would otherwise be accepted as the opacity parameter in a CSS rgba() function.

<div style="color: {{ '#ffffff'|hex2rgba(0.5) }}">

will output

<div style="color: rgba(255, 255, 255, 0.5)">

|stringify

{{ my_favorite_javascript_object|stringify }}

This will output the return of JSON.stringify on the passed value.

The output of this filter is NOT escaped.

|format()

{{ formattable_string|format(kwargs) }}
{{ formattable_string|format(key=value[, ...]) }}

This filter returns the output of format.format against the passed keyword arguments or arguments object.

The output of this filter is NOT escaped.

|sum

{{ array_of_numbers|sum }}

Returns the sum of all integers passed to it.

Helpers

  • helpers.api: Maps to urls.api.url
  • helpers.apiParams: Maps to urls.api.params
  • helpers.url: Maps to urls.reverse
  • helpers.media: Maps to urls.media
  • helpers._: Maps to l10n.gettext
  • helpers._plural: Maps to l10n.ngettext
  • helpers.format: Maps to format.format
  • helpers.settings: Maps to the settings module
  • helpers.user: Maps to a version of the user module sans any mutator methods and get_settings
  • helpers.escape: Maps to utils.escape_
  • helpers.len: Roughly maps to function(obj) {return obj.length;}
  • helpers.max: Maps to Math.max
  • helpers.min: Maps to Math.min
  • helpers.range: Maps to _.range
  • helpers.identity: Maps roughly to an identity function that filters a __keywords member
  • helpers.navigator: Maps to navigator
  • helpers.screen: Maps to window.screen
  • helpers.language: Maps to navigator.l10n.language

Best Practices

  • Keep templates as simple as possible. Assume every line of HTML compiles to three lines of JavaScript.
  • Minimize branches in template code.
  • Loops have a high performance overhead. Do not use loops when you can use static HTML.
  • Defer blocks may be nested, but you shouldn't.
  • As much logic should be uplifted to the view as possible.