Not interested in explanations? Fast travel to the tl;dr 🚀
In Grav, we can process YAML front matter from Twig templates. This can be very useful for elegantly handling list of items:
---
title: Foo
things:
- bar
- baz
---
<ul class="things">
{% for thing in page.header.things %}
<li>{{ thing|raw }}</li>
{% endfor %}
</ul>
Result:
<ul class="things">
<li>bar</li>
<li>baz</li>
</ul>
What if we wanted to add some Markdown?
We could try using Grav’s Markdown Twig filter:
---
title: Foo
things:
- "**bar**"
- baz
---
<ul class="things">
{% for thing in page.header.things %}
<li>{{ thing|markdown }}</li>
{% endfor %}
</ul>
However, it wraps items with <p>
tags, which will probably break rendering and is definitely not what we want:
<ul class="things">
<li><p><strong>bar</strong></p></li>
<li><p>baz</p></li>
</ul>
I initially worked around it by registering a custom linemarkdown
filter to force parsing using Parsedown::line
function:
<?php
namespace Grav\Theme;
use Grav\Common\Markdown\ParsedownExtra;
class CustomQuark extends Quark
{
public function onTwigInitialized()
{
parent::onTwigInitialized();
$this->grav['twig']->twig()->addFilter(
new \Twig_SimpleFilter('linemarkdown', [$this, 'lineMarkdownFunction'])
);
}
public function lineMarkdownFunction($string)
{
$parsedown = new ParsedownExtra(null);
return $parsedown->line($string);
}
}
But after looking at how Grav was registering its markdown
filter, I noticed markdownFunction
had an optional $block
parameter, that was then used in Utils::processMarkdown
to determine whether to use Parsedown::text
(default case) or Parsedown::line
(what I wanted).
Fun fact: after digging a bit using git blame
, this was actually implemented back in 1.2.0. It just never was documented! Opened a PR for this, but in the meantime… Welp, that was a quick merge.
When processing Markdown variables in Twig using markdown
filter, pass false
to the filter to use line
mode (no wrapping) rather than the default text
mode (<p>
-wrapped):
---
title: Foo
things:
- "**bar**"
- baz
---
<ul class="things">
{% for thing in page.header.things %}
<li>{{ thing|markdown(false) }}</li>
{% endfor %}
</ul>
Result:
<ul class="things">
<li><strong>bar</strong></li>
<li>baz</li>
</ul>