<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="https://cecil.app/xsl/atom.xsl" media="all"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <id>https://cecil.app/documentation/templates/</id>
  <title>Cecil - Templates</title>
  <subtitle><![CDATA[Cecil is a command-line PHP application that merges Markdown pages, medias and Twig templates to generate a static website.]]></subtitle>
  <link href="https://cecil.app/documentation/templates/atom.xml" rel="self" type="application/atom+xml" />
  <link href="https://cecil.app/documentation/templates/" rel="alternate" type="text/html" />
  <updated>2026-10-07T21:40:48+00:00</updated>
  <author>
    <name>Cecil</name>
    <uri>https://cecil.app</uri>
  </author>
  <entry xml:lang="en">
    <id>https://cecil.app/documentation/templates/lookup-rules/</id>
    <title>Organization and lookup rules</title>
    <published>2021-05-07T00:00:00+00:00</published>
    <updated>2026-10-05T00:00:00+00:00</updated>
    <link href="https://cecil.app/documentation/templates/lookup-rules/" rel="alternate" type="text/html" />
    <content type="html">
      <![CDATA[<h1>Organization and lookup rules</h1>
<h2 id="files-organization">Files organization</h2>
<h3 id="kinds-of-templates">Kinds of templates</h3>
<p>There are three kinds of templates: <strong><em>layouts</em></strong>, <strong><em>components</em></strong>, and <strong><em>other templates</em></strong>. <em>Layouts</em> are used to render <a href="/documentation/content/pages/">pages</a>, and each layout can <a href="https://twig.symfony.com/doc/templates.html#including-other-templates" target="_blank" rel="noopener noreferrer">include templates</a> and <a href="/documentation/templates/components/">components</a>.</p>
<h3 id="naming-convention">Naming convention</h3>
<p>Template files are stored in the <code translate="no">layouts/</code> directory and must be named according to the following convention:</p>
<pre><code class="language-plaintext hljs plaintext" translate="no">layouts/(&lt;section&gt;/)&lt;type&gt;|&lt;layout&gt;.&lt;format&gt;(.&lt;language&gt;).twig</code></pre>
<dl>
<dt><code translate="no">&lt;section&gt;</code> (<em>optional</em>)</dt>
<dd>The section of the page (e.g.: <code translate="no">blog</code>).</dd>
<dt><code translate="no">&lt;type&gt;</code></dt>
<dd>The page type: <code translate="no">home</code> (or <code translate="no">index</code>) for <em>homepage</em>, <code translate="no">list</code> for <em>list</em>, <code translate="no">page</code> for <em>page</em>, etc. (See <a href="#lookup-rules"><em>Lookup rules</em></a> for details).</dd>
<dt><code translate="no">&lt;layout&gt;</code> (<em>optional</em>)</dt>
<dd>The custom layout name defined in the <a href="/documentation/content/pages/#front-matter">front matter</a> of the page (e.g.: <code translate="no">layout: my-layout</code>).</dd>
<dt><code translate="no">&lt;format&gt;</code></dt>
<dd>The <a href="/documentation/configuration/output/#output-formats">output format</a> of the rendered page (e.g.: <code translate="no">html</code>, <code translate="no">rss</code>, <code translate="no">json</code>, <code translate="no">xml</code>, etc.).</dd>
<dt><code translate="no">&lt;language&gt;</code> (<em>optional</em>)</dt>
<dd>The language of the page (e.g.: <code translate="no">fr</code>).</dd>
</dl>
<p><em>Examples:</em></p>
<pre><code class="language-plaintext hljs plaintext" translate="no">layouts/home.html.twig       # `type` is "homepage"
layouts/page.html.twig       # `type` is "page"
layouts/page.html.fr.twig    # `type` is "page" and `language` is "fr"
layouts/my-layout.html.twig  # `layout` is "my-layout"
layouts/blog/list.html.twig  # `section` is "blog"
layouts/blog/list.rss.twig   # `section` is "blog" and `format` is "rss"</code></pre>
<pre><code class="language-plaintext hljs plaintext" translate="no">&lt;my-site&gt;
├─ ...
├─ layouts
|  ├─ index.html.twig      # Used by type "homepage"
|  ├─ list.html.twig       # Used by types "homepage" and "section"
|  ├─ list.rss.twig        # Used by types "homepage" and "section", for RSS output format
|  ├─ page.html.twig       # Used by type "page"
|  ├─ taxonomy
|  |  ├─ tags.html.twig    # Used by type "vocabulary" of `tags` (list of terms)
|  |  └─ tag.html.twig     # Used by type "term" of `tags` (list of pages)
|  ├─ my-layout.html.twig  # Used by pages with `layout: my-layout` in the front matter
|  ├─ ...
|  └─ partials             # Included templates
|     ├─ footer.html.twig
|     └─ ...
└─ themes                  # Themes layouts and templates
   └─ ...</code></pre>
<h3 id="built-in-templates">Built-in templates</h3>
<p>Cecil comes with a set of <a href="https://github.com/Cecilapp/Cecil/tree/main/resources/layouts" target="_blank" rel="noopener noreferrer">built-in templates</a>.</p>
<aside class="note note-tip"><p>If you need to modify built-in templates, you can easily extract them via the following command: they will be copied in the <code translate="no">layouts</code> directory of your site.</p>
<pre><code class="language-bash hljs bash" translate="no">php cecil.phar util:templates:extract</code></pre></aside>
<h2 id="lookup-rules">Lookup rules</h2>
<p>In most of cases <strong>you don’t need to specify the layout</strong>: Cecil selects the most appropriate layout, according to the <strong>page type</strong>.</p>
<p>For example, the HTML output of <strong>home page</strong> (<code translate="no">index.md</code>) will be rendered:</p>
<ol>
<li>with <code translate="no">my-layout.html.twig</code> if the <code translate="no">layout</code> variable is set to "my-layout" (in the front matter)</li>
<li>if not, with <code translate="no">index.html.twig</code> if the file exists</li>
<li>if not, with <code translate="no">home.html.twig</code> if the file exists</li>
<li>if not, with <code translate="no">list.html.twig</code> if the file exists</li>
</ol>
<p>All rules are detailed below, for each page type, in the priority order.</p>
<h3 id="type-homepage">Type <em>homepage</em></h3>
<ol>
<li><code translate="no">&lt;layout&gt;.&lt;format&gt;.twig</code></li>
<li><code translate="no">index.&lt;format&gt;.twig</code></li>
<li><code translate="no">home.&lt;format&gt;.twig</code></li>
<li><code translate="no">list.&lt;format&gt;.twig</code></li>
<li><code translate="no">_default/&lt;layout&gt;.&lt;format&gt;.twig</code></li>
<li><code translate="no">_default/index.&lt;format&gt;.twig</code></li>
<li><code translate="no">_default/home.&lt;format&gt;.twig</code></li>
<li><code translate="no">_default/list.&lt;format&gt;.twig</code></li>
<li><code translate="no">_default/page.&lt;format&gt;.twig</code></li>
</ol>
<h3 id="type-page">Type <em>page</em></h3>
<ol>
<li><code translate="no">&lt;section&gt;/&lt;layout&gt;.&lt;format&gt;.twig</code></li>
<li><code translate="no">&lt;layout&gt;.&lt;format&gt;.twig</code></li>
<li><code translate="no">&lt;section&gt;/page.&lt;format&gt;.twig</code></li>
<li><code translate="no">_default/&lt;layout&gt;.&lt;format&gt;.twig</code></li>
<li><code translate="no">page.&lt;format&gt;.twig</code></li>
<li><code translate="no">_default/page.&lt;format&gt;.twig</code></li>
</ol>
<h3 id="type-section">Type <em>section</em></h3>
<ol>
<li><code translate="no">&lt;layout&gt;.&lt;format&gt;.twig</code></li>
<li><code translate="no">&lt;section&gt;/index.&lt;format&gt;.twig</code></li>
<li><code translate="no">&lt;section&gt;/list.&lt;format&gt;.twig</code></li>
<li><code translate="no">section/&lt;section&gt;.&lt;format&gt;.twig</code></li>
<li><code translate="no">&lt;parent&gt;/index.&lt;format&gt;.twig</code>, <code translate="no">&lt;parent&gt;/list.&lt;format&gt;.twig</code> and <code translate="no">section/&lt;parent&gt;.&lt;format&gt;.twig</code>, for each parent section of a sub-section (nearest first)</li>
<li><code translate="no">_default/section.&lt;format&gt;.twig</code></li>
<li><code translate="no">list.&lt;format&gt;.twig</code></li>
<li><code translate="no">_default/list.&lt;format&gt;.twig</code></li>
</ol>
<aside class="note note-tip"><p>The <code translate="no">&lt;section&gt;</code> of a <a href="/documentation/content/pages/#sub-section">sub-section</a> is its full path (e.g.: <code translate="no">blog/2024</code>), and a sub-section falls back to the templates of its parent sections: if <code translate="no">blog/2024/list.html.twig</code> doesn’t exist, the sub-section <code translate="no">blog/2024</code> is rendered with <code translate="no">blog/list.html.twig</code>.</p></aside>
<h3 id="type-vocabulary">Type <em>vocabulary</em></h3>
<ol>
<li><code translate="no">taxonomy/&lt;plural&gt;.&lt;format&gt;.twig</code></li>
<li><code translate="no">vocabulary.&lt;format&gt;.twig</code></li>
<li><code translate="no">_default/vocabulary.&lt;format&gt;.twig</code></li>
</ol>
<h3 id="type-term">Type <em>term</em></h3>
<ol>
<li><code translate="no">taxonomy/&lt;plural&gt;/&lt;term&gt;.&lt;format&gt;.twig</code></li>
<li><code translate="no">taxonomy/&lt;singular&gt;.&lt;format&gt;.twig</code></li>
<li><code translate="no">term.&lt;format&gt;.twig</code></li>
<li><code translate="no">_default/term.&lt;format&gt;.twig</code></li>
<li><code translate="no">_default/list.&lt;format&gt;.twig</code></li>
</ol>
<aside class="note note-important"><p>The <strong>vocabulary</strong> template is named after the <strong>plural</strong> (e.g.: <code translate="no">taxonomy/categories.html.twig</code> for <code translate="no">/categories/</code>), whereas the <strong>term</strong> template is named after the <strong>singular</strong> (e.g.: <code translate="no">taxonomy/category.html.twig</code> for <code translate="no">/categories/data-sovereignty/</code>).</p></aside>
<aside class="note note-tip"><p><code translate="no">&lt;term&gt;</code> is the slugified term name: a dedicated template for the term "Data Sovereignty" of the <code translate="no">categories</code> vocabulary is <code translate="no">taxonomy/categories/data-sovereignty.html.twig</code>.</p></aside>
<aside class="note note-info"><p>Most of those layouts are available by default, see <a href="https://github.com/Cecilapp/Cecil/tree/main/resources/layouts" target="_blank" rel="noopener noreferrer">built-in templates</a>.</p></aside>]]>
    </content>
  </entry>
  <entry xml:lang="en">
    <id>https://cecil.app/documentation/templates/reference/functions/</id>
    <title>Functions</title>
    <published>2021-05-07T00:00:00+00:00</published>
    <updated>2026-10-05T00:00:00+00:00</updated>
    <link href="https://cecil.app/documentation/templates/reference/functions/" rel="alternate" type="text/html" />
    <content type="html">
      <![CDATA[<h1>Functions</h1>
<blockquote>
<p><a href="https://twig.symfony.com/doc/functions/index.html" target="_blank" rel="noopener noreferrer">Functions</a> can be called to generate content. Functions are called by their name followed by parentheses (<code translate="no">()</code>) and may have arguments.</p>
</blockquote>
<h2 id="url">url</h2>
<p>Creates a valid URL for a page, a menu entry, an asset, a page ID or a path.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ url(value, {options}) }}</span></code></pre>
<table>
<thead>
<tr>
<th>Option</th>
<th>Description</th>
<th>Type</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td>canonical</td>
<td>Prefix URL with <a href="/configuration/site/#baseurl"><code translate="no">baseurl</code></a> or use <a href="/configuration/site/#metatags-options"><code translate="no">canonical.url</code></a> if exists.</td>
<td>boolean</td>
<td><code translate="no">false</code></td>
</tr>
<tr>
<td>format</td>
<td>Defines page <a href="/configuration/output/#output-formats">output format</a> (e.g.: <code translate="no">json</code>).</td>
<td>string</td>
<td><code translate="no">html</code></td>
</tr>
<tr>
<td>language</td>
<td>Defines page <a href="/configuration/languages/#language">language</a> (e.g.: <code translate="no">fr</code>).</td>
<td>string</td>
<td>null</td>
</tr>
</tbody>
</table>
<p><em>Examples:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-comment">{# page #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ url(page) }}</span><span class="xml">
</span><span class="hljs-template-variable">{{ url(page, {canonical: true}) }}</span><span class="xml">
</span><span class="hljs-template-variable">{{ url(page, {format: json}) }}</span><span class="xml">
</span><span class="hljs-template-variable">{{ url(page, {language: fr}) }}</span><span class="xml">
</span><span class="hljs-comment">{# menu entry #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ url(site.menus.main.about) }}</span><span class="xml">
</span><span class="hljs-comment">{# asset #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ url(asset('styles.css')) }}</span><span class="xml">
</span><span class="hljs-comment">{# page ID #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ url('page-id') }}</span><span class="xml">
</span><span class="hljs-comment">{# path #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ url('about-me/') }}</span><span class="xml">
</span><span class="hljs-template-variable">{{ url('tags/' ~ tag) }}</span></code></pre>
<aside class="note note-info"><p>For convenience the <code translate="no">url</code> function is also available as a filter:</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-comment">{# page #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ page|url }}</span><span class="xml">
</span><span class="hljs-template-variable">{{ page|url({canonical: true, format: json, language: fr}) }}</span><span class="xml">
</span><span class="hljs-comment">{# asset #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ asset('styles.css')|url }}</span></code></pre></aside>
<aside class="note note-tip"><p>When the value is a string, <code translate="no">url()</code> slugifies it to find a matching page ID (e.g.: <code translate="no">url('tags/My Tag')</code> returns the URL of the page <code translate="no">tags/my-tag</code>). If no page matches, the string is kept as a path, with invalid characters (e.g.: spaces) percent-encoded.</p></aside>
<h2 id="html">html</h2>
<p>Creates an HTML element from an asset (or an array of assets with custom attributes).</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ html(asset, {attributes}, {options}) }}</span><span class="xml">
</span><span class="hljs-comment">{# dedicated functions for each common type of asset #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ css(asset) }}</span><span class="xml">
</span><span class="hljs-template-variable">{{ js(asset) }}</span><span class="xml">
</span><span class="hljs-template-variable">{{ image(asset) }}</span><span class="xml">
</span><span class="hljs-template-variable">{{ audio(asset) }}</span><span class="xml">
</span><span class="hljs-template-variable">{{ video(asset) }}</span></code></pre>
<table>
<thead>
<tr>
<th>Option</th>
<th>Description</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>attributes</td>
<td>Adds <code translate="no">name="value"</code> couple to the HTML element.</td>
<td>array</td>
</tr>
<tr>
<td>options</td>
<td><code translate="no">{preload: boolean}</code>: preloads.<br>For images:<br><code translate="no">{formats: array}</code>: adds alternative formats.<br><code translate="no">{responsive: bool|string}</code>: adds responsive images (based on <code translate="no">width</code> or pixels <code translate="no">density</code>).<br><code translate="no">{placeholder: string}</code>: fills the image background before loading (<code translate="no">color</code> or <code translate="no">lqip</code>).</td>
<td>array</td>
</tr>
</tbody>
</table>
<aside class="note note-warning"><p>Since version <ins>8.42.0</ins>, the <code translate="no">html</code> function replace the deprecated <code translate="no">html</code> filter.</p></aside>
<aside class="note note-tip"><p>You can define a global default behavior of images options (<code translate="no">formats</code>, <code translate="no">responsive</code> and <code translate="no">placeholder</code>) through the <a href="/configuration/layouts/#layouts-images">layouts configuration</a>.</p>
<p>When <a href="/configuration/layouts/#layouts-images"><code translate="no">layouts.images.dark_suffix</code></a> is configured (e.g. <code translate="no">.dark</code>), Cecil automatically looks for a dark variant of each image (e.g. <code translate="no">photo.dark.jpg</code> alongside <code translate="no">photo.jpg</code>) and generates a <code translate="no">&lt;picture&gt;</code> element with a <code translate="no">&lt;source media="(prefers-color-scheme: dark)"&gt;</code>.</p>
<p>In the same way, when <a href="/configuration/layouts/#layouts-images"><code translate="no">layouts.images.mobile_suffix</code></a> is configured (e.g. <code translate="no">.mobile</code>), Cecil looks for a mobile variant of each image (e.g. <code translate="no">photo.mobile.jpg</code>) and adds a <code translate="no">&lt;source&gt;</code> with the <a href="/configuration/layouts/#layouts-images"><code translate="no">layouts.images.mobile_media_query</code></a> media query. If a dark variant of the mobile image exists (e.g. <code translate="no">photo.mobile.dark.jpg</code>), it is used on mobile with dark color scheme.</p></aside>
<p><em>Examples:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-comment">{# CSS with an attribute #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ html(asset('print.css'), {media: 'print'}) }}</span><span class="xml">
</span><span class="hljs-comment">{# CSS with an attribute and an option #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ html(asset('styles.css'), {title: 'Main theme'}, {preload: true}) }}</span><span class="xml">
</span><span class="hljs-comment">{# Array of assets with media query #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ html([
  {asset: asset('css/style.css')},
  {asset: asset('css/style-dark.css'), attributes: {media: '(prefers-color-scheme: dark)'}}</span><span class="xml">
]) }}
</span><span class="hljs-comment">{# JavaScript #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ html(asset('script.js')) }}</span><span class="xml">
</span><span class="hljs-comment">{# image without specific attributes nor options #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ html(asset('image.png')) }}</span><span class="xml">
</span><span class="hljs-comment">{# image with specific attributes, responsive images and alternative formats #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ html(asset('image.jpg'), {alt: 'Description', loading: 'lazy'}, {responsive: true, formats: ['avif', 'webp']}) }}</span><span class="xml">
</span><span class="hljs-comment">{# image with responsive pixels density images #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ html(asset('image.jpg'), options={responsive: 'density'}, attributes={width: 256}) }}</span><span class="xml">
</span><span class="hljs-comment">{# image with a Low-Quality Image Placeholder #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ html(asset('image.jpg'), {alt: 'Description', loading: 'lazy'}, {placeholder: 'lqip'}) }}</span><span class="xml">
</span><span class="hljs-comment">{# Audio #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ html(asset('audio.mp3')) }}</span><span class="xml">
</span><span class="hljs-comment">{# Video #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ html(asset('video.mp4')) }}</span></code></pre>
<aside class="note note-info"><p>For convenience the <code translate="no">html</code> function stay available as a filter (but is considered as deprecated):</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ asset|html({attributes}, {options}) }}</span></code></pre></aside>
<h2 id="readtime">readtime</h2>
<p>Determines read time of a text, in minutes.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ readtime(value) }}</span></code></pre>
<p><em>Example:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ readtime(page.content) }}</span><span class="xml"> min</span></code></pre>
<h2 id="hash">hash</h2>
<p>Calculates the hash of an object, an array or a string with a given algorithm.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ hash(value, algorithm) }}</span></code></pre>
<p><code translate="no">algorithm</code> can be any algorithm supported by PHP's <code translate="no">hash()</code> function (e.g.: <code translate="no">md5</code>, <code translate="no">sha256</code>, etc.). Default is <code translate="no">xxh128</code>.</p>
<p><em>Example:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ hash('my string', 'sha256') }}</span></code></pre>
<h2 id="cache-key">cache_key</h2>
<p>Calculates a cache key for <a href="/documentation/cache/#fragments-cache"><em>fragments</em> cache</a> based on a name and an optional value.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name">cache</span> cache_key(name, value) %}</span><span class="xml">
  </span><span class="hljs-comment">{# cacheable content #}</span><span class="xml">
</span><span class="hljs-template-tag">{% <span class="hljs-name">endcache</span> %}</span></code></pre>
<p>The function adds a hash of the value (could be a string, an array or an object) to the name (and the current language and build ID to be sure the generated cache key is unique) so if the value is changed the cache key is changed too and the cache is automatically cleared.</p>
<h2 id="getenv">getenv</h2>
<p>Gets the value of an environment variable from its key.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ getenv(var) }}</span></code></pre>
<p><em>Example:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ getenv('VAR') }}</span></code></pre>
<h2 id="dump">dump</h2>
<p>The <code translate="no">dump</code> function dumps information about a template variable. This is mostly useful to debug a template that does not behave as expected by introspecting its variables:</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ <span class="hljs-name">dump</span><span class="hljs-params">(user)</span> }}</span></code></pre>
<aside class="note note-important"><p>The <a href="/configuration/site/#debug"><em>debug mode</em></a> must be enabled.</p></aside>
<h2 id="d">d</h2>
<p>The <code translate="no">d()</code> function is the HTML version of <a href="#dump"><code translate="no">dump()</code></a> and use the <a href="https://symfony.com/doc/5.4/components/var_dumper.html" target="_blank" rel="noopener noreferrer">Symfony VarDumper Component</a> behind the scenes.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ d(variable, {theme: light}) }}</span></code></pre>
<ul>
<li>If <em>variable</em> is not provided then the function returns the current Twig context</li>
<li>Available themes are « light » (default) and « dark »</li>
</ul>
<aside class="note note-important"><p>The <a href="/configuration/site/#debug"><em>debug mode</em></a> must be enabled.</p></aside>]]>
    </content>
  </entry>
  <entry xml:lang="en">
    <id>https://cecil.app/documentation/templates/variables/</id>
    <title>Variables</title>
    <published>2021-05-07T00:00:00+00:00</published>
    <updated>2026-10-06T00:00:00+00:00</updated>
    <link href="https://cecil.app/documentation/templates/variables/" rel="alternate" type="text/html" />
    <content type="html">
      <![CDATA[<h1>Variables</h1>
<blockquote>
<p>The application passes variables to the templates for manipulation in the template. Variables may have attributes or elements you can access, too.<br>
Use a dot (.) to access attributes of a variable: <code translate="no">{{ foo.bar }}</code></p>
</blockquote>
<p>You can use variables from different scopes: <a href="#site"><code translate="no">site</code></a>, <a href="#page"><code translate="no">page</code></a>, <a href="#cecil"><code translate="no">cecil</code></a>.</p>
<h2 id="site">site</h2>
<p>The <code translate="no">site</code> variable contains built-in variables <strong>and</strong> those set in the <a href="/documentation/configuration/">configuration</a>.</p>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code translate="no">site.pages</code></td>
<td>Collection of all pages, in the current language.</td>
</tr>
<tr>
<td><code translate="no">site.allpages</code></td>
<td>Collection of all pages, in all languages.</td>
</tr>
<tr>
<td><code translate="no">site.page(id)</code></td>
<td>A page with the given ID.</td>
</tr>
<tr>
<td><code translate="no">site.taxonomies</code></td>
<td>Collection of vocabularies.</td>
</tr>
<tr>
<td><code translate="no">site.home</code></td>
<td>ID of the home page.</td>
</tr>
<tr>
<td><code translate="no">site.time</code></td>
<td>Current <a href="https://wikipedia.org/wiki/Unix_time" target="_blank" rel="noopener noreferrer"><em>Timestamp</em></a>.</td>
</tr>
<tr>
<td><code translate="no">site.debug</code></td>
<td>Debug mode status (<code translate="no">true</code> or <code translate="no">false</code>).</td>
</tr>
<tr>
<td><code translate="no">site.build</code></td>
<td>Current build ID.</td>
</tr>
</tbody>
</table>
<p><em>Example:</em></p>
<pre><code class="language-yaml hljs yaml" translate="no"><span class="hljs-attr">title:</span> <span class="hljs-string">"My amazing website!"</span></code></pre>
<p>Can be displayed in a template with:</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ site.title }}</span></code></pre>
<aside class="note note-important"><p>Use <code translate="no">showable</code> method on pages collection to return only published and not <em>virtual/redirect/excluded</em> pages.</p>
<p><em>Example:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">for</span></span> page in site.pages.showable %}</span><span class="xml">
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"</span></span></span><span class="hljs-template-variable">{{ url(page) }}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span>&gt;</span></span><span class="hljs-template-variable">{{ page.title }}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
</span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endfor</span></span> %}</span></code></pre></aside>
<aside class="note note-warning"><p>In some cases, you can encounter conflicts between configuration and built-in variables (e.g. <code translate="no">pages.default</code> configuration). In that case, you can use <code translate="no">config.&lt;variable&gt;</code> (where <code translate="no">&lt;variable&gt;</code> is the variable name/path) to access the raw configuration directly.</p>
<p>Example:</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ config.pages.default.sitemap.priority }}</span></code></pre></aside>
<h3 id="site-menus">site.menus</h3>
<p>Loop on <code translate="no">site.menus.&lt;menu&gt;</code> to get each entry of the <code translate="no">&lt;menu&gt;</code> collection (e.g.: <code translate="no">main</code>).</p>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code translate="no">&lt;entry&gt;.name</code></td>
<td>Entry name.</td>
</tr>
<tr>
<td><code translate="no">&lt;entry&gt;.url</code></td>
<td>Entry URL.</td>
</tr>
<tr>
<td><code translate="no">&lt;entry&gt;.weight</code></td>
<td>Entry weight (useful to sort menu entries).</td>
</tr>
</tbody>
</table>
<p><em>Example:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">nav</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">ol</span>&gt;</span>
  </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">for</span></span> entry in site.menus.main|sort_by_weight %}</span><span class="xml">
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"</span></span></span><span class="hljs-template-variable">{{ url(entry.url) }}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span> <span class="hljs-attr">data-weight</span>=<span class="hljs-string">"</span></span></span><span class="hljs-template-variable">{{ entry.weight }}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span>&gt;</span></span><span class="hljs-template-variable">{{ entry.name }}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
  </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endfor</span></span> %}</span><span class="xml">
  <span class="hljs-tag">&lt;/<span class="hljs-name">ol</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span></span></code></pre>
<h3 id="site-language">site.language</h3>
<p>Information about the current language.</p>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code translate="no">site.language</code></td>
<td>Language code (e.g.: <code translate="no">en</code>).</td>
</tr>
<tr>
<td><code translate="no">site.language.name</code></td>
<td>Language name (e.g.: <code translate="no">English</code>).</td>
</tr>
<tr>
<td><code translate="no">site.language.locale</code></td>
<td>Language <a href="/documentation/configuration/locale-codes/">locale code</a> (e.g.: <code translate="no">en_US</code>).</td>
</tr>
<tr>
<td><code translate="no">site.language.weight</code></td>
<td>Language position in the <code translate="no">languages</code> list.</td>
</tr>
</tbody>
</table>
<aside class="note note-tip"><p>You can retrieve <code translate="no">name</code>, <code translate="no">locale</code> and <code translate="no">weight</code> of a specific language by passing its code as a parameter.<br>
e.g.: <code translate="no">site.language.name('fr')</code>.</p></aside>
<h3 id="site-static">site.static</h3>
<p>The static files collection can be accessed via <code translate="no">site.static</code> if the <a href="/documentation/configuration/data-static/#static-load"><em>static load</em></a> is enabled.</p>
<p>Each file exposes the following properties:</p>
<ul>
<li><code translate="no">path</code>: relative path (e.g.: <code translate="no">/images/img-1.jpg</code>)</li>
<li><code translate="no">date</code>: creation date (<em>timestamp</em>)</li>
<li><code translate="no">updated</code>: modification date (<em>timestamp</em>)</li>
<li><code translate="no">name</code>: name (e.g.: <code translate="no">img-1.jpg</code>)</li>
<li><code translate="no">basename</code>: name without extension (e.g.: <code translate="no">img-1</code>)</li>
<li><code translate="no">ext</code>: extension (e.g.: <code translate="no">jpg</code>)</li>
<li><code translate="no">type</code>: media type (e.g.: <code translate="no">image</code>)</li>
<li><code translate="no">subtype</code>: media sub type (e.g.: <code translate="no">image/jpeg</code>)</li>
<li><code translate="no">exif</code>: image EXIF data (<em>array</em>)</li>
<li><code translate="no">audio</code>: <a href="https://github.com/wapmorgan/Mp3Info#audio-information" target="_blank" rel="noopener noreferrer">Mp3Info</a> object</li>
<li><code translate="no">video</code>: array of basic video information (duration in seconds, width and height)</li>
</ul>
<h3 id="site-data">site.data</h3>
<p>A data collection can be accessed via <code translate="no">site.data.&lt;filename&gt;</code> (without file extension).</p>
<p><em>Examples:</em></p>
<ul>
<li><code translate="no">data/authors.yml</code> : <code translate="no">site.data.authors</code></li>
<li><code translate="no">data/authors.fr.yml</code> : <code translate="no">site.data.authors</code> (if <code translate="no">site.language</code> = "fr")</li>
<li><code translate="no">data/galleries/gallery-1.json</code> : <code translate="no">site.data.galleries['gallery-1']</code></li>
</ul>
<h2 id="page">page</h2>
<p>The <code translate="no">page</code> variable contains built-in variables of a page <strong>and</strong> those set in the <a href="/documentation/content/pages/#front-matter">front matter</a>.</p>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Description</th>
<th>Example</th>
</tr>
</thead>
<tbody>
<tr>
<td><code translate="no">page.id</code></td>
<td>Unique identifier.</td>
<td><code translate="no">blog/post-1</code></td>
</tr>
<tr>
<td><code translate="no">page.title</code></td>
<td>File name (without extension).</td>
<td><code translate="no">Post 1</code></td>
</tr>
<tr>
<td><code translate="no">page.date</code></td>
<td>File creation date.</td>
<td><em>DateTime</em></td>
</tr>
<tr>
<td><code translate="no">page.body</code></td>
<td>File body.</td>
<td><em>Markdown</em></td>
</tr>
<tr>
<td><code translate="no">page.content</code></td>
<td>File body converted in HTML.</td>
<td><em>HTML</em></td>
</tr>
<tr>
<td><code translate="no">page.section</code></td>
<td>File root folder (<em>slugified</em>).</td>
<td><code translate="no">blog</code></td>
</tr>
<tr>
<td><code translate="no">page.path</code></td>
<td>File path (<em>slugified</em>).</td>
<td><code translate="no">blog/post-1</code></td>
</tr>
<tr>
<td><code translate="no">page.slug</code></td>
<td>File name (<em>slugified</em>).</td>
<td><code translate="no">post-1</code></td>
</tr>
<tr>
<td><code translate="no">page.filepath</code></td>
<td>File system path.</td>
<td><code translate="no">Blog/Post 1.md</code></td>
</tr>
<tr>
<td><code translate="no">page.type</code></td>
<td><code translate="no">homepage</code>, <code translate="no">page</code>, <code translate="no">section</code>, <code translate="no">vocabulary</code> or <code translate="no">term</code>.</td>
<td><code translate="no">page</code></td>
</tr>
<tr>
<td><code translate="no">page.pages</code></td>
<td>Collection of all sub pages.</td>
<td><em>Collection</em></td>
</tr>
<tr>
<td><code translate="no">page.translations</code></td>
<td>Collection of translated pages.</td>
<td><em>Collection</em></td>
</tr>
</tbody>
</table>
<aside class="note note-important"><p>Use <code translate="no">showable</code> method on pages collection to return only published and not <em>virtual/redirect/excluded</em> pages.</p>
<p><em>Example:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">for</span></span> page in page.pages.showable %}</span><span class="xml">
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"</span></span></span><span class="hljs-template-variable">{{ url(page) }}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span>&gt;</span></span><span class="hljs-template-variable">{{ page.title }}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
</span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endfor</span></span> %}</span></code></pre></aside>
<h3 id="nested-sections">Nested sections</h3>
<p>In a <a href="/documentation/content/pages/#sub-section">nested sections</a> context, <code translate="no">page.parent</code>, <code translate="no">page.ancestors</code>, <code translate="no">page.sections</code> and <code translate="no">page.toplevel</code> help you build navigation.</p>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Description</th>
<th>Example</th>
</tr>
</thead>
<tbody>
<tr>
<td><code translate="no">page.parent</code></td>
<td>Parent <em>section</em>'s page (<code translate="no">null</code> if none).</td>
<td><em>Page</em></td>
</tr>
<tr>
<td><code translate="no">page.ancestors</code></td>
<td>Collection of ancestor <em>sections</em> (nearest first).</td>
<td><em>Collection</em></td>
</tr>
<tr>
<td><code translate="no">page.sections</code></td>
<td>Collection of immediate descendant <em>sections</em>.</td>
<td><em>Collection</em></td>
</tr>
<tr>
<td><code translate="no">page.toplevel</code></td>
<td><code translate="no">true</code> if the page is a top level <em>section</em>.</td>
<td><em>Boolean</em></td>
</tr>
</tbody>
</table>
<p><em>Breadcrumb (from the home page to the current page):</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">nav</span> <span class="hljs-attr">aria-label</span>=<span class="hljs-string">"breadcrumb"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"</span></span></span><span class="hljs-template-variable">{{ url(site.home) }}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span>&gt;</span></span><span class="hljs-template-variable">{{ site.title }}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">for</span></span> section in page.ancestors|<span class="hljs-keyword">reverse</span> %}</span><span class="xml">
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"</span></span></span><span class="hljs-template-variable">{{ url(section) }}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span>&gt;</span></span><span class="hljs-template-variable">{{ section.title }}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endfor</span></span> %}</span><span class="xml">
    </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">if</span></span> page.id != site.home %}</span><span class="xml">
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"</span></span></span><span class="hljs-template-variable">{{ url(page) }}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span> <span class="hljs-attr">aria-current</span>=<span class="hljs-string">"page"</span>&gt;</span></span><span class="hljs-template-variable">{{ page.title }}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endif</span></span> %}</span><span class="xml">
  <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span></span></code></pre>
<aside class="note note-tip"><p>A ready-to-use <a href="https://github.com/Cecilapp/Cecil/blob/main/resources/layouts/partials/breadcrumb.html.twig" target="_blank" rel="noopener noreferrer"><code translate="no">breadcrumb.html.twig</code></a> partial is available:</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ <span class="hljs-name">include</span><span class="hljs-params">('partials/breadcrumb.html.twig')</span> }}</span></code></pre></aside>
<p><em>Sub-sections menu (immediate descendant sections of the current section):</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">if</span></span> page.sections|<span class="hljs-keyword">length</span> %}</span><span class="xml">
<span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
  </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">for</span></span> section in page.sections|sort_by_title %}</span><span class="xml">
  <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"</span></span></span><span class="hljs-template-variable">{{ url(section) }}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span>&gt;</span></span><span class="hljs-template-variable">{{ section.title }}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
  </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endfor</span></span> %}</span><span class="xml">
<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
</span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endif</span></span> %}</span></code></pre>
<p><em>Main navigation limited to top level sections (from any page):</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">nav</span>&gt;</span>
  </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">for</span></span> section in site.page(site.home).sections|sort_by_title %}</span><span class="xml">
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"</span></span></span><span class="hljs-template-variable">{{ url(section) }}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span>&gt;</span></span><span class="hljs-template-variable">{{ section.title }}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
  </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endfor</span></span> %}</span><span class="xml">
<span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span></span></code></pre>
<p><em>Link to the parent section:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">if</span></span> page.<span class="hljs-name">parent</span> %}</span><span class="xml">
<span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"</span></span></span><span class="hljs-template-variable">{{ url(page.<span class="hljs-name">parent</span>) }}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span>&gt;</span>← </span><span class="hljs-template-variable">{{ page.<span class="hljs-name">parent</span>.title }}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
</span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endif</span></span> %}</span></code></pre>
<h3 id="page-prev-next">page.&lt;prev/next&gt;</h3>
<p>Navigation between pages within the same <em>section</em>, sorted according to the section's <code translate="no">sortby</code> (chronological order for dates).</p>
<p>With <a href="/documentation/content/pages/#sub-section">sub-sections</a>, navigation follows the sections tree: the pages of a top level <em>Section</em> and of all its sub-sections are chained, each sub-section (its index page) being placed among the pages of its parent <em>Section</em> and followed by its own pages.</p>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Description</th>
<th>Example</th>
</tr>
</thead>
<tbody>
<tr>
<td><code translate="no">page.prev</code></td>
<td>Previous page.</td>
<td><em>Page</em></td>
</tr>
<tr>
<td><code translate="no">page.next</code></td>
<td>Next page.</td>
<td><em>Page</em></td>
</tr>
</tbody>
</table>
<p><em>Example:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"</span></span></span><span class="hljs-template-variable">{{ url(page.prev) }}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span>&gt;</span></span><span class="hljs-template-variable">{{ page.prev.title }}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span></code></pre>
<h3 id="page-paginator">page.paginator</h3>
<p><em>Paginator</em> helps you build navigation for list pages: homepage, sections, and taxonomies.</p>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code translate="no">page.paginator.pages</code></td>
<td>Pages Collection.</td>
</tr>
<tr>
<td><code translate="no">page.paginator.pages_total</code></td>
<td>Number total of pages.</td>
</tr>
<tr>
<td><code translate="no">page.paginator.count</code></td>
<td>Number of paginator's pages.</td>
</tr>
<tr>
<td><code translate="no">page.paginator.current</code></td>
<td>Position index of the current page.</td>
</tr>
<tr>
<td><code translate="no">page.paginator.links.first</code></td>
<td>Page ID of the first page.</td>
</tr>
<tr>
<td><code translate="no">page.paginator.links.prev</code></td>
<td>Page ID of the previous page.</td>
</tr>
<tr>
<td><code translate="no">page.paginator.links.self</code></td>
<td>Page ID of the current page.</td>
</tr>
<tr>
<td><code translate="no">page.paginator.links.next</code></td>
<td>Page ID of the next page.</td>
</tr>
<tr>
<td><code translate="no">page.paginator.links.last</code></td>
<td>Page ID of the last page.</td>
</tr>
<tr>
<td><code translate="no">page.paginator.links.path</code></td>
<td>Page ID without the position index.</td>
</tr>
</tbody>
</table>
<aside class="note note-important"><p>Because links entries are Page ID you must use the <code translate="no">url()</code> function to create working links.<br>
e.g: <code translate="no">{{ url(page.paginator.links.next) }}</code></p></aside>
<p><em>Example:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">if</span></span> page.paginator %}</span><span class="xml">
<span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
  </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">if</span></span> page.paginator.links.prev is defined %}</span><span class="xml">
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"</span></span></span><span class="hljs-template-variable">{{ url(page.paginator.links.prev) }}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span>&gt;</span>Previous<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
  </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endif</span></span> %}</span><span class="xml">
  </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">if</span></span> page.paginator.links.next is defined %}</span><span class="xml">
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"</span></span></span><span class="hljs-template-variable">{{ url(page.paginator.links.next) }}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span>&gt;</span>Next<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
  </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endif</span></span> %}</span><span class="xml">
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endif</span></span> %}</span></code></pre>
<p><em>Example:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">if</span></span> page.paginator %}</span><span class="xml">
<span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
  </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">for</span></span> paginator_index in 1..page.paginator.count %}</span><span class="xml">
    </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">if</span></span> paginator_index != page.paginator.current %}</span><span class="xml">
      </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">if</span></span> paginator_index == 1 %}</span><span class="xml">
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"</span></span></span><span class="hljs-template-variable">{{ url(page.paginator.links.first) }}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span>&gt;</span></span><span class="hljs-template-variable">{{ paginator_index }}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      </span><span class="hljs-template-tag">{% <span class="hljs-name">else</span> %}</span><span class="xml">
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"</span></span></span><span class="hljs-template-variable">{{ url(page.paginator.links.path ~ '/' ~ paginator_index) }}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span>&gt;</span></span><span class="hljs-template-variable">{{ paginator_index }}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endif</span></span> %}</span><span class="xml">
    </span><span class="hljs-template-tag">{% <span class="hljs-name">else</span> %}</span><span class="xml">
  </span><span class="hljs-template-variable">{{ paginator_index }}</span><span class="xml">
    </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endif</span></span> %}</span><span class="xml">
  </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endfor</span></span> %}</span><span class="xml">
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endif</span></span> %}</span></code></pre>
<h3 id="taxonomy">Taxonomy</h3>
<p>Variables available in <em>vocabulary</em> and <em>term</em> templates.</p>
<h4>Vocabulary</h4>
<p>Page <code translate="no">/&lt;plural&gt;/</code> (e.g.: <code translate="no">/categories/</code>).</p>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code translate="no">page.plural</code></td>
<td>Vocabulary name in plural form.</td>
</tr>
<tr>
<td><code translate="no">page.singular</code></td>
<td>Vocabulary name in singular form.</td>
</tr>
<tr>
<td><code translate="no">page.terms</code></td>
<td>List of terms (<em>Collection</em>).</td>
</tr>
</tbody>
</table>
<p>Each term of <code translate="no">page.terms</code> provides <code translate="no">term.id</code> (term ID, e.g.: <code translate="no">categories/php</code>), <code translate="no">term.name</code> (term name, e.g.: <code translate="no">PHP</code>) and the number of its pages with <code translate="no">term|length</code>.</p>
<h4>Term</h4>
<p>Page <code translate="no">/&lt;plural&gt;/&lt;term&gt;/</code> (e.g.: <code translate="no">/categories/php/</code>).</p>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code translate="no">page.title</code></td>
<td>Term name.</td>
</tr>
<tr>
<td><code translate="no">page.term</code></td>
<td>Term ID (e.g.: <code translate="no">categories/php</code>).</td>
</tr>
<tr>
<td><code translate="no">page.plural</code></td>
<td>Vocabulary name in plural form.</td>
</tr>
<tr>
<td><code translate="no">page.singular</code></td>
<td>Vocabulary name in singular form.</td>
</tr>
<tr>
<td><code translate="no">page.pages</code></td>
<td>List of pages in this term, sorted by date (<em>Collection</em>).</td>
</tr>
</tbody>
</table>
<h4>Taxonomy example</h4>
<p>Configuration:</p>
<pre><code class="language-yaml hljs yaml" translate="no"><span class="hljs-attr">taxonomies:</span>
  <span class="hljs-attr">categories:</span> <span class="hljs-string">category</span></code></pre>
<p>Page front matter:</p>
<pre><code class="language-yaml hljs yaml" translate="no"><span class="hljs-meta">---</span>
<span class="hljs-attr">categories:</span> <span class="hljs-string">["Data</span> <span class="hljs-string">Sovereignty"]</span>
<span class="hljs-meta">---</span></code></pre>
<p>List of terms (<code translate="no">/categories/</code>), in <code translate="no">layouts/taxonomy/categories.html.twig</code>:</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">extends</span></span> 'page.html.twig' %}</span><span class="xml">

</span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">block</span></span> content %}</span><span class="xml">
  <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span></span><span class="hljs-template-variable">{{ page.title }}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
  </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">for</span></span> term in page.terms %}</span><span class="xml">
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"</span></span></span><span class="hljs-template-variable">{{ url(term.id) }}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span>&gt;</span></span><span class="hljs-template-variable">{{ term.name }}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span> (</span><span class="hljs-template-variable">{{ term|<span class="hljs-keyword">length</span> }}</span><span class="xml">)<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
  </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endfor</span></span> %}</span><span class="xml">
  <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
</span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endblock</span></span> %}</span></code></pre>
<p>List of pages of a term (<code translate="no">/categories/data-sovereignty/</code>), in <code translate="no">layouts/taxonomy/category.html.twig</code>:</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">extends</span></span> 'page.html.twig' %}</span><span class="xml">

</span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">block</span></span> content %}</span><span class="xml">
  <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span></span><span class="hljs-template-variable">{{ page.title }}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">for</span></span> p in page.paginator.pages ?? page.pages %}</span><span class="xml">
    <span class="hljs-tag">&lt;<span class="hljs-name">article</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"</span></span></span><span class="hljs-template-variable">{{ url(p) }}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span>&gt;</span></span><span class="hljs-template-variable">{{ p.title }}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">article</span>&gt;</span>
  </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endfor</span></span> %}</span><span class="xml">
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"</span></span></span><span class="hljs-template-variable">{{ url(page.plural) }}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span>&gt;</span>All </span><span class="hljs-template-variable">{{ page.plural }}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
</span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endblock</span></span> %}</span></code></pre>
<p>Links to the terms of the current page, in a page template:</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">for</span></span> category in page.categories ?? [] %}</span><span class="xml">
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"</span></span></span><span class="hljs-template-variable">{{ url('categories/' ~ category) }}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span>&gt;</span></span><span class="hljs-template-variable">{{ category }}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
</span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endfor</span></span> %}</span></code></pre>
<aside class="note note-tip"><p>The <a href="/documentation/templates/reference/functions/#url"><code translate="no">url()</code></a> function slugifies the given string to find the matching page: <code translate="no">url('categories/Data Sovereignty')</code> returns <code translate="no">/categories/data-sovereignty/</code>.</p>
<p>You can also use the built-in partial <code translate="no">{{ include('partials/terms-list.html.twig', {vocabulary: 'categories'}) }}</code>.</p></aside>
<h2 id="cecil">cecil</h2>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code translate="no">cecil.url</code></td>
<td>URL of the Cecil website.</td>
</tr>
<tr>
<td><code translate="no">cecil.version</code></td>
<td>Cecil current version.</td>
</tr>
<tr>
<td><code translate="no">cecil.poweredby</code></td>
<td>Print <code translate="no">Cecil v%s</code>, with <code translate="no">%s</code> is the current version.</td>
</tr>
</tbody>
</table>]]>
    </content>
  </entry>
  <entry xml:lang="en">
    <id>https://cecil.app/documentation/templates/reference/sorts/</id>
    <title>Sorts</title>
    <published>2021-05-07T00:00:00+00:00</published>
    <updated>2026-10-05T00:00:00+00:00</updated>
    <link href="https://cecil.app/documentation/templates/reference/sorts/" rel="alternate" type="text/html" />
    <content type="html">
      <![CDATA[<h1>Sorts</h1>
<p>Sorting collections (of pages, menus or taxonomies).</p>
<h2 id="sort-by-title">sort_by_title</h2>
<p>Sorts a collection by title (with <a href="https://en.wikipedia.org/wiki/Natural_sort_order" target="_blank" rel="noopener noreferrer">natural sort</a>).</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ collection|sort_by_title }}</span></code></pre>
<p><em>Example:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ site.pages|sort_by_title }}</span></code></pre>
<h2 id="sort-by-date">sort_by_date</h2>
<p>Sorts a collection by date (most recent first).</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ collection|sort_by_date(variable='<span class="hljs-name">date</span>', desc_title=false) }}</span></code></pre>
<p><em>Example:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-comment">{# sort by date #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ site.pages|sort_by_date }}</span><span class="xml">
</span><span class="hljs-comment">{# sort by updated variable instead of date #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ site.pages|sort_by_date(variable='updated') }}</span><span class="xml">
</span><span class="hljs-comment">{# sort items with the same date by desc title #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ site.pages|sort_by_date(desc_title=true) }}</span><span class="xml">
</span><span class="hljs-comment">{# reverse sort #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ site.pages|sort_by_date|<span class="hljs-keyword">reverse</span> }}</span></code></pre>
<h2 id="sort-by-weight">sort_by_weight</h2>
<p>Sorts a collection by weight (lighter first).</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ collection|sort_by_weight }}</span></code></pre>
<p><em>Example:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ site.menus.main|sort_by_weight }}</span></code></pre>
<h2 id="sort">sort</h2>
<p>For more complex cases, you should use <a href="https://twig.symfony.com/doc/filters/sort.html" target="_blank" rel="noopener noreferrer">Twig’s native <code translate="no">sort</code></a>.</p>
<p><em>Example:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">set</span></span> files = site.static|<span class="hljs-keyword">sort</span>((a, b) =&gt; a.<span class="hljs-name">date</span>|<span class="hljs-keyword">date</span>('U') &lt; b.<span class="hljs-name">date</span>|<span class="hljs-keyword">date</span>('U')) %}</span></code></pre>]]>
    </content>
  </entry>
  <entry xml:lang="en">
    <id>https://cecil.app/documentation/templates/reference/filters/</id>
    <title>Filters</title>
    <published>2021-05-07T00:00:00+00:00</published>
    <updated>2026-10-05T00:00:00+00:00</updated>
    <link href="https://cecil.app/documentation/templates/reference/filters/" rel="alternate" type="text/html" />
    <content type="html">
      <![CDATA[<h1>Filters</h1>
<p>Variables can be modified by <a href="https://twig.symfony.com/doc/filters/index.html" target="_blank" rel="noopener noreferrer">filters</a>. Filters are separated from the variable by a pipe symbol (<code translate="no">|</code>). Multiple filters can be chained. The output of one filter is applied to the next.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ page.title|truncate(25)|<span class="hljs-keyword">capitalize</span> }}</span></code></pre>
<h2 id="filter-by">filter_by</h2>
<p>Filters a pages collection by variable name/value.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ collection|filter_by(variable, value) }}</span></code></pre>
<p><em>Example:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ pages|filter_by('section', 'blog') }}</span></code></pre>
<h2 id="filter">filter</h2>
<p>For more complex cases, you should use <a href="https://twig.symfony.com/doc/filters/filter.html" target="_blank" rel="noopener noreferrer">Twig’s native <code translate="no">filter</code></a>.</p>
<p><em>Example:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name">pages</span>|<span class="hljs-keyword">filter</span>(p =&gt; p.virtual == false and p.id not in ['page-1', 'page-2']) %}</span></code></pre>
<h2 id="markdown-to-html">markdown_to_html</h2>
<p>Converts a Markdown string to HTML.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ markdown|markdown_to_html }}</span></code></pre>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">apply</span></span> markdown_to_html %}</span><span class="xml">
</span><span class="hljs-comment">{# Markdown here #}</span><span class="xml">
</span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endapply</span></span> %}</span></code></pre>
<p><em>Examples:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">set</span></span> markdown = '**This is bold text**' %}</span><span class="xml">
</span><span class="hljs-template-variable">{{ markdown|markdown_to_html }}</span></code></pre>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">apply</span></span> markdown_to_html %}</span><span class="xml">
**This is bold text**
</span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endapply</span></span> %}</span></code></pre>
<h2 id="toc">toc</h2>
<p>Extracts only headings matching the given <code translate="no">selectors</code> (h2, h3, etc.), or those defined in config <code translate="no">pages.body.toc</code> if not specified.<br>
The <code translate="no">format</code> parameter defines the output format: <code translate="no">html</code> or <code translate="no">json</code>.<br>
The <code translate="no">url</code> parameter is used to build links to headings.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ markdown|toc(format, selectors, url) }}</span></code></pre>
<p><em>Examples:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ page.body|toc }}</span><span class="xml">
</span><span class="hljs-template-variable">{{ page.body|toc('html') }}</span><span class="xml">
</span><span class="hljs-template-variable">{{ page.body|toc(selectors=['h2']) }}</span><span class="xml">
</span><span class="hljs-template-variable">{{ page.body|toc(url=url(page)) }}</span></code></pre>
<h2 id="json-decode">json_decode</h2>
<p>Converts a JSON string to an array.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ json|json_decode }}</span></code></pre>
<p><em>Example:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">set</span></span> json = '{"foo": "bar"}' %}</span><span class="xml">
</span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">set</span></span> array = json|json_decode %}</span><span class="xml">
</span><span class="hljs-template-variable">{{ array.foo }}</span></code></pre>
<h2 id="yaml-parse">yaml_parse</h2>
<p>Converts a YAML string to an array.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ yaml|yaml_parse }}</span></code></pre>
<p><em>Example:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">set</span></span> yaml = 'key: value' %}</span><span class="xml">
</span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">set</span></span> array = yaml|yaml_parse %}</span><span class="xml">
</span><span class="hljs-template-variable">{{ array.key }}</span></code></pre>
<h2 id="slugify">slugify</h2>
<p>Converts a string to a slug.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ string|slugify }}</span></code></pre>
<h2 id="u">u</h2>
<p>The <code translate="no">u</code> filter wraps a text in a Unicode object (a <a href="https://symfony.com/doc/current/components/string.html" target="_blank" rel="noopener noreferrer">Symfony UnicodeString instance</a>) that exposes methods to "manipulate" the string.</p>
<p><em>Example:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ 'cecil_string with twig'|u.camel.title }}</span></code></pre>
<blockquote>
<p>CecilStringWithTwig</p>
</blockquote>
<h2 id="singular">singular</h2>
<p>The <code translate="no">singular</code> filter transforms a given noun in its plural form into its singular version.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ string|singular(locale)}}</span></code></pre>
<p><em>Example:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-comment">{# English (en) rules are used by default #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ 'partitions'|singular }}</span></code></pre>
<blockquote>
<p>partition</p>
</blockquote>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ 'partitions'|singular('fr') }}</span></code></pre>
<blockquote>
<p>partition</p>
</blockquote>
<h2 id="plural">plural</h2>
<p>The <code translate="no">plural</code> filter transforms a given noun in its singular form into its plural version.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ string|plural(locale)}}</span></code></pre>
<p><em>Example:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-comment">{# English (en) rules are used by default #}</span><span class="xml">
</span><span class="hljs-template-variable">{{ 'animal'|plural }}</span></code></pre>
<blockquote>
<p>animals</p>
</blockquote>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ 'animal'|plural('fr') }}</span></code></pre>
<blockquote>
<p>animaux</p>
</blockquote>
<h2 id="excerpt">excerpt</h2>
<p>Truncates a string and appends suffix.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ string|excerpt(length, suffix) }}</span></code></pre>
<table>
<thead>
<tr>
<th>Option</th>
<th>Description</th>
<th>Type</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td>length</td>
<td>Truncates after this number of characters.</td>
<td>integer</td>
<td>450</td>
</tr>
<tr>
<td>suffix</td>
<td>Appends characters.</td>
<td>string</td>
<td><code translate="no">…</code></td>
</tr>
</tbody>
</table>
<p><em>Examples:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ variable|excerpt }}</span><span class="xml">
</span><span class="hljs-template-variable">{{ variable|excerpt(250, '...') }}</span></code></pre>
<h2 id="excerpt-html">excerpt_html</h2>
<p>Reads characters before or after <code translate="no">&lt;!-- excerpt --&gt;</code> or <code translate="no">&lt;!-- break --&gt;</code> tag.<br>
See <a href="/content/markdown/#excerpt">Content documentation</a> for details.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ string|excerpt_html({separator, capture}) }}</span></code></pre>
<table>
<thead>
<tr>
<th>Option</th>
<th>Description</th>
<th>Type</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td>separator</td>
<td>String to use as separator.</td>
<td>string</td>
<td><code translate="no">excerpt|break</code></td>
</tr>
<tr>
<td>capture</td>
<td>Part to capture, <code translate="no">before</code> or <code translate="no">after</code> the separator.</td>
<td>string</td>
<td><code translate="no">before</code></td>
</tr>
</tbody>
</table>
<p><em>Examples:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ variable|excerpt_html }}</span><span class="xml">
</span><span class="hljs-template-variable">{{ variable|excerpt_html({separator: 'excerpt|break', capture: 'before'}) }}</span><span class="xml">
</span><span class="hljs-template-variable">{{ variable|excerpt_html({capture: 'after'}) }}</span></code></pre>
<h2 id="highlight">highlight</h2>
<p>Highlights a code string with <a href="https://github.com/scrivo/highlight.php" target="_blank" rel="noopener noreferrer">highlight.php</a>.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ code|highlight(language) }}</span></code></pre>
<p><em>Examples:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ '&lt;?php echo $highlighted-&gt;value; ?&gt;'|highlight('php') }}</span></code></pre>
<h2 id="preg-split">preg_split</h2>
<p>Splits a string into an array using a regular expression.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ string|preg_split(pattern, limit) }}</span></code></pre>
<p><em>Example:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">set</span></span> headers = page.content|preg_split('/&lt;br[^&gt;]*&gt;/') %}</span></code></pre>
<h2 id="preg-match-all">preg_match_all</h2>
<p>Performs a regular expression match and return the group for all matches.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ string|preg_match_all(pattern, group) }}</span></code></pre>
<p><em>Example:</em></p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">set</span></span> tags = page.content|preg_match_all('/&lt;[^&gt;]+&gt;(.*)&lt;\/[^&gt;]+&gt;/') %}</span></code></pre>
<h2 id="hex-to-rgb">hex_to_rgb</h2>
<p>Converts a hexadecimal color to RGB.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ color|hex_to_rgb }}</span></code></pre>]]>
    </content>
  </entry>
  <entry xml:lang="en">
    <id>https://cecil.app/documentation/templates/components/</id>
    <title>Components</title>
    <published>2021-05-07T00:00:00+00:00</published>
    <updated>2026-10-05T00:00:00+00:00</updated>
    <link href="https://cecil.app/documentation/templates/components/" rel="alternate" type="text/html" />
    <content type="html">
      <![CDATA[<h1>Components</h1>
<p>Cecil provides a components logic to give you the power making reusable template "units".</p>
<aside class="note note-info"><p>The components feature is provided by the <a href="https://github.com/giorgiopogliani/twig-components" target="_blank" rel="noopener noreferrer"><em>Twig components extension</em></a> created by Giorgio Pogliani.</p></aside>
<h2 id="components-syntax">Components syntax</h2>
<p>Components are just Twig templates stored in the <code translate="no">components/</code> subdirectory and can be used anywhere in your templates:</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-comment">{# /components/button.twig #}</span><span class="xml">
<span class="hljs-tag">&lt;<span class="hljs-name">button</span> </span></span><span class="hljs-template-variable">{{ attributes.merge({class: 'rounded px-4'}) }}</span><span class="xml"><span class="hljs-tag">&gt;</span>
    </span><span class="hljs-template-variable">{{ slot }}</span><span class="xml">
<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span></code></pre>
<blockquote>
<p>The slot variable is any content you will add between the opening and the close tag.</p>
</blockquote>
<p>To reach a component you need to use the dedicated tag <code translate="no">x</code> followed by <code translate="no">:</code> and the filename of your component without extension:</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-comment">{# /index.twig #}</span><span class="xml">
</span><span class="hljs-template-tag">{% <span class="hljs-name">x</span>:button with {class: 'text-white'} %}</span><span class="xml">
    <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>Click me<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
</span><span class="hljs-template-tag">{% <span class="hljs-name">endx</span> %}</span></code></pre>
<p>It will render:</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-white rounded px-4"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>Click me<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span></code></pre>]]>
    </content>
  </entry>
  <entry xml:lang="en">
    <id>https://cecil.app/documentation/templates/localization/</id>
    <title>Localization</title>
    <published>2021-05-07T00:00:00+00:00</published>
    <updated>2026-10-05T00:00:00+00:00</updated>
    <link href="https://cecil.app/documentation/templates/localization/" rel="alternate" type="text/html" />
    <content type="html">
      <![CDATA[<h1>Localization</h1>
<p>Cecil support <a href="#text-translation">text translation</a> and <a href="#date-localization">date localization</a>.</p>
<h2 id="text-translation">Text translation</h2>
<p>Uses the <code translate="no">trans</code> <em>tag</em> or <em>filter</em> to translate texts in templates.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name">trans</span> with variables into locale %}</span><span class="hljs-template-tag">{% <span class="hljs-name">endtrans</span> %}</span></code></pre>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ message|trans(variables = []) }}</span></code></pre>
<h3 id="examples">Examples</h3>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name">trans</span> %}</span><span class="xml">Hello World!</span><span class="hljs-template-tag">{% <span class="hljs-name">endtrans</span> %}</span></code></pre>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ message|trans }}</span></code></pre>
<p>Include variables:</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name">trans</span> with {'%name%': 'Arnaud'} %}</span><span class="xml">Hello %name%!</span><span class="hljs-template-tag">{% <span class="hljs-name">endtrans</span> %}</span></code></pre>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ message|trans({'%name%': 'Arnaud'}) }}</span></code></pre>
<p>Force locale:</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name">trans</span> into 'fr_FR' %}</span><span class="xml">Hello World!</span><span class="hljs-template-tag">{% <span class="hljs-name">endtrans</span> %}</span></code></pre>
<p>Pluralize:</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name">trans</span> with {'%count%': 42}%}</span><span class="xml">{0}I don't have apples|{1}I have one apple|]1,Inf[I have %count% apples</span><span class="hljs-template-tag">{% <span class="hljs-name">endtrans</span> %}</span></code></pre>
<h2 id="translation-files">Translation files</h2>
<p>Translation files must be named <code translate="no">messages.&lt;locale&gt;.&lt;extension&gt;</code> and stored in the <a href="/documentation/configuration/layouts/"><code translate="no">translations</code></a> directory.<br>
Supported file extensions are defined by each translation format in <a href="/documentation/configuration/layouts/#layouts-translations"><code translate="no">layouts.translations.formats</code></a>.</p>
<p>The locale code (e.g.: <code translate="no">fr_FR</code>) of a language is defined in the <a href="/documentation/configuration/languages/#languages"><code translate="no">languages</code></a> entries of the configuration.</p>
<p><em>Example:</em></p>
<pre><code class="language-plaintext hljs plaintext" translate="no">&lt;mywebsite&gt;
└─ translations
   ├─ messages.fr_FR.mo   &lt;- Machine Object format
   └─ messages.fr_FR.yaml &lt;- Yaml format</code></pre>
<aside class="note note-info"><p>You can easily extract translations from your templates with the following command:</p>
<pre><code class="language-bash hljs bash" translate="no">php cecil.phar util:translations:extract --locale=&lt;code&gt; --show</code></pre>
<p>Use <code translate="no">--save</code> instead of (or in addition to) <code translate="no">--show</code> to save the translations to a file. The <code translate="no">--locale</code> option is required. The default output format is <code translate="no">yaml</code> (use <code translate="no">--format=po</code> for gettext PO format).</p></aside>
<aside class="note note-tip"><p><a href="https://poedit.net" target="_blank" rel="noopener noreferrer"><em>Poedit</em></a> is a simple and cross platform translation editor for gettext (PO), and <a href="https://poedit.net/pro" target="_blank" rel="noopener noreferrer"><em>Poedit Pro</em></a> supports extraction of translation strings from templates out of the box.</p></aside>
<aside class="note note-important"><p>Be careful about the <a href="/documentation/templates/cache/">cache</a> when you update translations files.</p>
<p>Cache can be cleared with with the following command:</p>
<pre><code class="language-bash hljs bash" translate="no">php cecil.phar cache:clear:translations`</code></pre></aside>
<h2 id="date-localization">Date localization</h2>
<p>Uses the Twig <a href="https://twig.symfony.com/doc/3.x/filters/format_date.html" target="_blank" rel="noopener noreferrer"><code translate="no">format_date</code></a> filter to localize a date in templates.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-variable">{{ page.<span class="hljs-name">date</span>|format_date('long') }}</span><span class="xml">
</span><span class="hljs-comment">{# September 30, 2022 #}</span></code></pre>
<p>Supported values are: <code translate="no">short</code>, <code translate="no">medium</code>, <code translate="no">long</code>, and <code translate="no">full</code>.</p>
<aside class="note note-important"><p>If you want to use the <code translate="no">format_date</code> filter <strong>with other locales than "en"</strong>, you should <a href="https://php.net/intl.setup" target="_blank" rel="noopener noreferrer">install the intl PHP extension</a>.</p></aside>]]>
    </content>
  </entry>
  <entry xml:lang="en">
    <id>https://cecil.app/documentation/templates/cache/</id>
    <title>Cache</title>
    <published>2021-05-07T00:00:00+00:00</published>
    <updated>2026-10-05T00:00:00+00:00</updated>
    <link href="https://cecil.app/documentation/templates/cache/" rel="alternate" type="text/html" />
    <content type="html">
      <![CDATA[<h1>Cache</h1>
<p>Cecil uses a cache system to speed up the generation process, it can be disabled or cleared.</p>
<p>There are three cache types involved in template rendering: templates, <a href="/documentation/assets/#asset">assets</a>, and <a href="/documentation/templates/localization/#translation-files">translations</a>.</p>
<h2 id="clear-cache">Clear cache</h2>
<p>You can clear the cache with the following commands:</p>
<pre><code class="language-bash hljs bash" translate="no">php cecil.phar cache:clear               <span class="hljs-comment"># clear all caches</span>
php cecil.phar cache:clear:assets        <span class="hljs-comment"># clear assets cache</span>
php cecil.phar cache:clear:templates     <span class="hljs-comment"># clear templates cache</span>
php cecil.phar cache:clear:translations  <span class="hljs-comment"># clear translations cache</span></code></pre>
<aside class="note note-important"><p>In practice you don't need to clear the cache manually, Cecil does it for you when needed (e.g. when files change).</p></aside>
<h2 id="fragments-cache">Fragments cache</h2>
<p>Cecil provides a way to cache parts of templates rendering to avoid re-rendering the same partial content multiple times.</p>
<p>To use <em>fragments</em> cache, you must wrap the content you want to cache with the <a href="https://twig.symfony.com/doc/tags/cache.html" target="_blank" rel="noopener noreferrer"><code translate="no">cache</code> tag</a>.</p>
<pre><code class="language-twig hljs twig" translate="no"><span class="hljs-template-tag">{% <span class="hljs-name">cache</span> 'unique-key' %}</span><span class="xml">
  </span><span class="hljs-comment">{# cacheable content #}</span><span class="xml">
</span><span class="hljs-template-tag">{% <span class="hljs-name">endcache</span> %}</span></code></pre>
<aside class="note note-tip"><p>You should use the <a href="/documentation/templates/reference/functions/#cache-key"><code translate="no">cache_key</code> function</a> to be sure to have a unique cache key for each content you want to cache.</p></aside>
<aside class="note note-warning"><p><em>Fragments</em> cache is persistent, so if the cache key is too generic, you may end up with wrong content displayed.</p></aside>
<p>To clear fragments cache only, you can use the following command:</p>
<pre><code class="language-bash hljs bash" translate="no">php cecil.phar cache:clear:templates --fragments</code></pre>
<h2 id="disable-cache">Disable cache</h2>
<p>You can disable cache with the <a href="/documentation/configuration/cache/">configuration</a>.</p>
<aside class="note note-warning"><p>Disabling cache can slow down the generation process, so it's not recommended.</p>
<p>During local development, if you need to clear cache before each generation, you can use the following option:</p>
<pre><code class="language-bash hljs bash" translate="no">php cecil.phar serve --clear-cache          <span class="hljs-comment"># clear all caches</span>
php cecil.phar serve --clear-cache=&lt;regex&gt;  <span class="hljs-comment"># clear cache for cache key matches with the regular expression &lt;regex&gt;</span></code></pre>
<p>Example:</p>
<pre><code class="language-bash hljs bash" translate="no">php cecil.phar serve --clear-cache=css  <span class="hljs-comment"># clear cache for all CSS files</span></code></pre></aside>]]>
    </content>
  </entry>
  <entry xml:lang="en">
    <id>https://cecil.app/documentation/templates/extend/</id>
    <title>Extend</title>
    <published>2021-05-07T00:00:00+00:00</published>
    <updated>2026-10-05T00:00:00+00:00</updated>
    <link href="https://cecil.app/documentation/templates/extend/" rel="alternate" type="text/html" />
    <content type="html">
      <![CDATA[<h1>Extend</h1>
<h2 id="functions-and-filters">Functions and filters</h2>
<p>You can add custom <a href="/documentation/templates/reference/functions/">functions</a> and custom <a href="/documentation/templates/reference/filters/">filters</a> with a <a href="/documentation/developers/extend/#twig-extension"><strong><em>Twig extension</em></strong></a>.</p>
<h2 id="theme">Theme</h2>
<p>It’s easy to build a theme, you just have to create a folder <code translate="no">&lt;theme&gt;</code> with the following structure (like a website but without pages):</p>
<pre><code class="language-plaintext hljs plaintext" translate="no">&lt;mywebsite&gt;
└─ themes
   └─ &lt;theme&gt;
      ├─ config.yml
      ├─ assets
      ├─ layouts
      ├─ static
      └─ translations</code></pre>]]>
    </content>
  </entry>
</feed>
