Article

tempest/highlight with Twig and Symfony

This blog did not have syntax highlighting since I rebuilt it with Symfony for my own entertainment.

So when Brendt posted about his new server-side syntax highlighter I was intrigued and after some (embarrassingly long) time I even saw it ships with a league/commonmark integration by default.

Why not integrate it into Symfony and Twig? The blog already uses the League Markdown Parser under the hood through the TwigExtraBundle, so it seemed simple.

TwigExtraBundle only supports to add new extensions to the markdown parser, but tempest/higlight only has renderers, so our own extension had to be created:

<?php
namespace App\Util;

use League\CommonMark\Environment\EnvironmentBuilderInterface;
use League\CommonMark\Extension\CommonMark\Node\Block\FencedCode;
use League\CommonMark\Extension\CommonMark\Node\Inline\Code;
use League\CommonMark\Extension\ExtensionInterface;
use Tempest\Highlight\CommonMark\CodeBlockRenderer;
use Tempest\Highlight\CommonMark\InlineCodeBlockRenderer;

class TempestLeagueExtension implements ExtensionInterface
{
    public function register(EnvironmentBuilderInterface $environment): void
    {
        $environment->addRenderer(FencedCode::class, new CodeBlockRenderer(), 10)
            ->addRenderer(Code::class, new InlineCodeBlockRenderer(), 10);
    }
}

This needs to be registered in config/services.yamlthe following way:

services:
  # other things...
  App\Util\TempestLeagueExtension:
    tags: ['twig.markdown.league_extension']

The CSS has to be integrated with Encore (or the assets build stack in general), in my case this is in assets/styles/app.sass:

@import "../../vendor/tempest/highlight/src/Themes/highlight-light-lite.css"

I pass the output of the markdown_to_htmlfilter in Twig through the HTML sanitizer just to be safe, so configuring a markdown specific sanitizer in config/packages/html_sanitizer.yaml:

framework:
  html_sanitizer:
    sanitizers:
      post.markdown:
        allow_safe_elements: true
        allowed_link_schemes: [ 'http', 'https' ]
        allow_elements:
          a: [ 'href' ]
          span: [ 'class' ]

Then using it in Twig:

{{ post.content|markdown_to_html|raw|sanitize_html('post.markdown') }}

Voila! You can see the results in this post's code snippets. I might want to adjust the font colors in the future, but the highlighting works.

Published: 2024-03-29