Skip to content
Code on GitHub (opens in a new tab)

Documentation · Guides

Templates and shortcodes

How a page is wrapped in HTML with Twig, which variables you have at hand and how to create a shortcode of your own for Markdown.

Version 0.16

A template receives a page and writes its HTML. This is a complete template, plantillas/articulo.twig (“templates / article”):

{% extends 'plantillas/base.twig' %}

{% block cuerpo %}
  <article>
    <h1>{{ pagina.titulo }}</h1>
    {{ pagina.contenido }}
  </article>
{% endblock %}

A page uses it by naming it in its front matter, without folder or extension:

---
titulo: My first post
plantilla: articulo
---
Today I start a blog.

If a page says nothing, it uses plantillas/pagina.twig. With plantilla: false it comes out as it is, with no layout, which is what a robots.txt needs. And if you name a template that does not exist, the build stops: it is better not to publish than to publish a page without its frame.

Three variables

In any template you have:

  • sitio (“site”): what you wrote in sitio.yml (sitio.nombre, sitio.url).
  • datos (“data”): the files in datos/. The one in datos/menus.yml is datos.menus.
  • pagina (“page”): the page being built. It brings the fields of its front matter (pagina.titulo, pagina.fecha…), and also pagina.url, pagina.contenido (the body, already converted to HTML) and pagina.idioma (“language”).

A field that does not exist comes out empty, so {% if pagina.imagen %} works without checking first that it exists.

Custom fields and the “sí” and “no”

In the front matter you can write whatever fields you like, and the template receives them as YAML reads them. Beware of one thing: sí and no (Spanish for “yes” and “no”) only mean true and false in the fields that Ehundu reserves, such as borrador (“draft”) or listada (“listed”). In a field of your own they are the text “sí” and the text “no”:

destacado: sí

To keep the pages that carry it, compare with the text:

{% for p in coleccion('proyectos')|donde('destacado', 'sí') %}

And do not write {% if pagina.destacado %} thinking of a no: the text “no” is not empty, so a template takes it as true. If you really want a true or a false, write true or false, without quotes, which YAML does read as such: destacado: true is filtered with donde('destacado', true).

Layouts and partials

A layout is inherited with {% extends %} and filled in by blocks; a piece that repeats is brought in with {% include %}. Both are named with the path from the root of the project:

{% extends 'plantillas/base.twig' %}
{% include 'parciales/cabecera.twig' %}

An idea that brings a lot of order: in base.twig is what all the pages share (the header, the footer, the stylesheets) and an empty block; each specific layout only fills in the block.

Twig escapes what it writes

Everything a template writes comes out with the HTML escaped, so a title with < or & breaks nothing. There is one deliberate exception: what is already HTML made by the engine, such as pagina.contenido, comes out as it is. If in a template you write a field of your own that carries HTML on purpose, you have to ask for it with |raw:

{{ pagina.aviso|raw }}

Use it only with your own text, never with anything that comes from outside.

Shortcodes for Markdown

Markdown does not go through Twig: inside a text there are no variables or conditions. What there is, is a small, closed vocabulary of shortcodes (atajos, in Spanish), which you write between square brackets with named attributes:

[imagen fichero="img/escaparate.jpg" alt="The bookshop window" pie="The shop in autumn"]

Ehundu brings four:

Shortcode What it gives
imagen (“image”) A figure, with its caption and its dimensions.
video A YouTube or Vimeo video, or one from publico/.
archivo (“file”) A link with the type and the size of the file.
dato (“data”) A value from datos/, useful in legal texts that repeat the name of the company.

Create your own

A shortcode is a template in parciales/atajos/, with its name. For a notice, parciales/atajos/aviso.twig (aviso is “notice”):

<div class="aviso aviso--{{ tipo|default('nota') }}">
  {{ contenido }}
</div>

The attributes arrive as variables (tipo, “type”), and contenido is what the shortcode wraps, already converted to HTML. You use it like this, with the opening and the closing each on its own line:

[aviso tipo="importante"]
Places are **limited**.
[/aviso]

And this comes out:

<div class="aviso aviso--importante">
  <p>Places are <strong>limited</strong>.</p>
</div>

If a shortcode produces a block (a div, a figure), put it in its own paragraph. And if you need to write one as text, and not as a shortcode, put a backslash in front of it: \[aviso].

To change how one of the shortcodes the engine brings comes out, write a template with the same name in parciales/atajos/: yours wins.

The detail is in the templates (in Spanish) and in the shortcodes (in Spanish).