1+++
2title = "Shortcodes"
3weight = 40
4+++
5
6Zola borrows the concept of [shortcodes](https://codex.wordpress.org/Shortcode_API) from WordPress.
7In our case, a shortcode corresponds to a template defined in the `templates/shortcodes` directory or
8a built-in one that can be used in a Markdown file. If you want to use something similar to shortcodes in your templates,
9try [Tera macros](https://tera.netlify.com/docs#macros).
10
11Broadly speaking, Zola's shortcodes cover two distinct use cases:
12
13* Inject more complex HTML: Markdown is good for writing, but it isn't great when you need to add inline HTML or styling.
14* Ease repetitive data based tasks: when you have [external data](@/documentation/templates/overview.md#load-data) that you
15  want to display in your page's body.
16
17The latter may also be solved by writing HTML, however Zola allows the use of Markdown based shortcodes which end in `.md`
18rather than `.html`. This may be particularly useful if you want to include headings generated by the shortcode in the
19[table of contents](@/documentation/content/table-of-contents.md).
20
21## Writing a shortcode
22Let's write a shortcode to embed YouTube videos as an example.
23In a file called `youtube.html` in the `templates/shortcodes` directory, paste the
24following:
25
26```jinja2
27<div {% if class %}class="{{class}}"{% endif %}>
28    <iframe
29        src="https://www.youtube.com/embed/{{id}}{% if autoplay %}?autoplay=1{% endif %}"
30        webkitallowfullscreen
31        mozallowfullscreen
32        allowfullscreen>
33    </iframe>
34</div>
35```
36
37This template is very straightforward: an iframe pointing to the YouTube embed URL wrapped in a `<div>`.
38In terms of input, this shortcode expects at least one variable: `id`. Because the other variables
39are in an `if` statement, they are optional.
40
41That's it. Zola will now recognise this template as a shortcode named `youtube` (the filename minus the `.html` extension).
42
43The Markdown renderer will wrap an inline HTML node such as `<a>` or `<span>` into a paragraph.
44If you want to disable this behaviour, wrap your shortcode in a `<div>`.
45
46A Markdown based shortcode in turn will be treated as if what it returned was part of the page's body. If we create
47`books.md` in `templates/shortcodes` for example:
48
49```jinja2
50{% set data = load_data(path=path) -%}
51{% for book in data.books %}
52### {{ book.title }}
53
54{{ book.description | safe }}
55{% endfor %}
56```
57
58This will create a shortcode `books` with the argument `path` pointing to a `.toml` file where it loads lists of books with
59titles and descriptions. They will flow with the rest of the document in which `books` is called.
60
61Shortcodes are rendered before the page's Markdown is parsed so they don't have access to the page's table of contents.
62Because of that, you also cannot use the [`get_page`](@/documentation/templates/overview.md#get-page)/[`get_section`](@/documentation/templates/overview.md#get-section)/[`get_taxonomy`](@/documentation/templates/overview.md#get-taxonomy) global functions. It might work while
63running `zola serve` because it has been loaded but it will fail during `zola build`.
64
65## Using shortcodes
66
67There are two kinds of shortcodes:
68
69- ones that do not take a body, such as the YouTube example above
70- ones that do, such as one that styles a quote
71
72In both cases, the arguments must be named and they will all be passed to the template.
73
74Lastly, a shortcode name (and thus the corresponding `.html` file) as well as the argument names
75can only contain numbers, letters and underscores, or in Regex terms `[0-9A-Za-z_]`.
76Although theoretically an argument name could be a number, it will not be possible to use such an argument in the template.
77
78Argument values can be of one of five types:
79
80- string: surrounded by double quotes, single quotes or backticks
81- bool: `true` or `false`
82- float: a number with a decimal point (e.g., 1.2)
83- integer: a whole number or its negative counterpart (e.g., 3)
84- array: an array of any kind of value, except arrays
85
86Malformed values will be silently ignored.
87
88Both types of shortcode will also get either a `page` or `section` variable depending on where they were used
89and a `config` variable. These values will overwrite any arguments passed to a shortcode so these variable names
90should not be used as argument names in shortcodes.
91
92### Shortcodes without body
93
94Simply call the shortcode as if it was a Tera function in a variable block. All the examples below are valid
95calls of the YouTube shortcode.
96
97```md
98Here is a YouTube video:
99
100{{/* youtube(id="dQw4w9WgXcQ") */}}
101
102{{/* youtube(id="dQw4w9WgXcQ", autoplay=true) */}}
103
104An inline {{/* youtube(id="dQw4w9WgXcQ", autoplay=true, class="youtube") */}} shortcode
105```
106
107Note that if you want to have some content that looks like a shortcode but not have Zola try to render it,
108you will need to escape it by using `{{/*` and `*/}}` instead of `{{` and `}}`.
109
110### Shortcodes with body
111Let's imagine that we have the following shortcode `quote.html` template:
112
113```jinja2
114<blockquote>
115    {{ body }} <br>
116    -- {{ author}}
117</blockquote>
118```
119
120We could use it in our Markdown file like so:
121
122```md
123As someone said:
124
125{%/* quote(author="Vincent") */%}
126A quote
127{%/* end */%}
128```
129
130The body of the shortcode will be automatically passed down to the rendering context as the `body` variable and needs
131to be on a new line.
132
133If you want to have some content that looks like a shortcode but not have Zola try to render it,
134you will need to escape it by using `{%/*` and `*/%}` instead of `{%` and `%}`. You won't need to escape
135anything else until the closing tag.
136
137## Shortcode context
138
139Every shortcode can access some variables, beyond what you explicitly passed as parameter. These variables are explained in the following subsections:
140
141- invocation count (`nth`)
142- current language (`lang`), unless called from the `markdown` template filter (in which case it will always be the same value as `default_language` in configuration, or `en` when it is unset)
143
144When one of these variables conflict with a variable passed as argument, the argument value will be used.
145
146### Invocation Count
147
148Every shortcode context is passed in a variable named `nth` that tracks how many times a particular shortcode has
149been invoked in the current Markdown file. Given a shortcode `true_statement.html` template:
150
151```jinja2
152<p id="number{{ nth }}">{{ value }} is equal to {{ nth }}.</p>
153```
154
155It could be used in our Markdown as follows:
156
157```md
158{{/* true_statement(value=1) */}}
159{{/* true_statement(value=2) */}}
160```
161
162This is useful when implementing custom markup for features such as sidenotes or end notes.
163
164### Current language
165
166**NOTE:** When calling a shortcode from within the `markdown` template filter, the `lang` variable will always be `en`. If you feel like you need that, please consider using template macros instead. If you really need that, you can rewrite your Markdown content to pass `lang` as argument to the shortcode.
167
168Every shortcode can access the current language in the `lang` variable in the context. This is useful for presenting/filtering information in a shortcode depending in a per-language manner. For example, to display a per-language book cover for the current page in a shortcode called `bookcover.md`:
169
170```jinja2
171![Book cover in {{ lang }}](cover.{{ lang }}.png)
172```
173
174You can then use it in your Markdown like so: `{{/* bookcover() */}}`
175
176## Built-in shortcodes
177
178Zola comes with a few built-in shortcodes. If you want to override a default shortcode template,
179simply place a `{shortcode_name}.html` file in the `templates/shortcodes` directory and Zola will
180use that instead.
181
182### YouTube
183Embed a responsive player for a YouTube video.
184
185The arguments are:
186
187- `id`: the video id (mandatory)
188- `playlist`: the playlist id (optional)
189- `class`: a class to add to the `<div>` surrounding the iframe
190- `autoplay`: when set to "true", the video autoplays on load
191
192Usage example:
193
194```md
195{{/* youtube(id="dQw4w9WgXcQ") */}}
196
197{{/* youtube(id="dQw4w9WgXcQ", playlist="RDdQw4w9WgXcQ") */}}
198
199{{/* youtube(id="dQw4w9WgXcQ", autoplay=true) */}}
200
201{{/* youtube(id="dQw4w9WgXcQ", autoplay=true, class="youtube") */}}
202```
203
204Result example:
205
206{{ youtube(id="dQw4w9WgXcQ") }}
207
208### Vimeo
209Embed a player for a Vimeo video.
210
211The arguments are:
212
213- `id`: the video id (mandatory)
214- `class`: a class to add to the `<div>` surrounding the iframe
215
216Usage example:
217
218```md
219{{/* vimeo(id="124313553") */}}
220
221{{/* vimeo(id="124313553", class="vimeo") */}}
222```
223
224Result example:
225
226{{ vimeo(id="124313553") }}
227
228### Streamable
229Embed a player for a Streamable video.
230
231The arguments are:
232
233- `id`: the video id (mandatory)
234- `class`: a class to add to the `<div>` surrounding the iframe
235
236Usage example:
237
238```md
239{{/* streamable(id="92ok4") */}}
240
241{{/* streamable(id="92ok4", class="streamble") */}}
242```
243
244Result example:
245
246{{ streamable(id="92ok4") }}
247
248### Gist
249Embed a [Github gist](https://gist.github.com).
250
251The arguments are:
252
253- `url`: the url to the gist (mandatory)
254- `file`: by default, the shortcode will pull every file from the URL unless a specific filename is requested
255- `class`: a class to add to the `<div>` surrounding the iframe
256
257Usage example:
258
259```md
260{{/* gist(url="https://gist.github.com/Keats/e5fb6aad409f28721c0ba14161644c57") */}}
261
262{{/* gist(url="https://gist.github.com/Keats/e5fb6aad409f28721c0ba14161644c57", class="gist") */}}
263```
264
265Result example:
266
267{{ gist(url="https://gist.github.com/Keats/e5fb6aad409f28721c0ba14161644c57") }}
268