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