twig/markdown-extra
Twig extension adding Markdown conversion filters: markdown_to_html to render Markdown as HTML, and html_to_markdown to convert HTML back to Markdown. Useful for templating content workflows where Markdown and HTML need to interoperate.
Install the package (Symfony/Twig projects only):
composer require twig/markdown-extra league/html-to-markdown
Note: Laravel users should skip this and use cebe/markdown or league/commonmark instead.
Register the extension (Symfony):
Add to config/packages/twig.yaml:
twig:
extra:
markdown: true
First use case: Render Markdown in a Twig template:
{{ user_comment|markdown_to_html }}
Pass a Markdown string (e.g., **Hello**) to render as HTML.
Markdown to HTML (Rendering)
markdown_to_html filter for user-generated content (e.g., blog posts, comments):
<div class="content">
{{ article_body|markdown_to_html }}
</div>
html-sanitizer for untrusted input:
{{ user_input|markdown_to_html|sanitize_html }}
HTML to Markdown (Conversion)
{{ legacy_html|html_to_markdown }}
Bidirectional Editing
{# Display rendered preview #}
<div class="preview">{{ markdown_editor|markdown_to_html }}</div>
{# Sync back to Markdown #}
{{ form_hidden('content', markdown_editor|html_to_markdown) }}
Symfony Forms: Use with Symfony\Component\Form\Extension\Core\Type\TextareaType:
$builder->add('description', TextareaType::class, [
'attr' => ['class' => 'markdown-editor'],
]);
Render with:
{{ form_row(form.description) }}
<div class="preview">{{ form.description.data|markdown_to_html }}</div>
Caching: Cache rendered HTML for performance:
{% cache 'markdown_'.article.id %}
{{ article.content|markdown_to_html }}
{% endcache %}
Custom Extensions: Extend Twig’s Markdown parser via league/commonmark:
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
use League\CommonMark\Environment;
$env = new Environment();
$env->addExtension(new CommonMarkCoreExtension());
Laravel Incompatibility
Class 'Twig\Extension\MarkdownExtraExtension' not found in Laravel.cebe/markdown or league/commonmark instead. Avoid Twig bridges unless necessary.HTML-to-Markdown Lossiness
<table>, <script>, or inline styles may not round-trip cleanly.{{ legacy_html|replace({'<table>': '', '</table>': ''})|html_to_markdown }}
XSS Risks
{{ user_input|markdown_to_html|sanitize_html }}
Install html-sanitizer:
composer require html-sanitizer
Dependency Conflicts
league/html-to-markdown may conflict with Laravel’s Twig.composer.json:
"require": {
"league/html-to-markdown": "^5.0"
}
Performance Overhead
// In a controller
$article->setAttribute('rendered_content', $article->content|markdown_to_html);
Filter Availability: Verify the extension is registered:
{% if 'markdown_to_html' in twig.filters %}
{# Filter is available #}
{% endif %}
Markdown Parsing Errors: Check for invalid syntax:
{% if markdown_content is not null %}
{{ markdown_content|markdown_to_html }}
{% else %}
<p>Invalid Markdown</p>
{% endif %}
HTML-to-Markdown Debugging: Log the output to inspect lossiness:
{% set markdown = html_content|html_to_markdown %}
{{ dump(markdown) }}
Custom Markdown Parser Override the default parser in a Twig extension:
use League\CommonMark\MarkdownConverter;
class CustomMarkdownExtension extends \Twig\Extension\AbstractExtension
{
public function getFilters()
{
return [
new \Twig\TwigFilter('markdown_to_html', [$this, 'customMarkdownToHtml']),
];
}
public function customMarkdownToHtml($markdown)
{
$converter = new MarkdownConverter();
return $converter->convert($markdown);
}
}
Post-Processing Filters Chain filters for custom transformations:
{{ content
| markdown_to_html
| replace({'<p>': '<div class="prose">'})
| sanitize_html
}}
Environment Configuration
Configure league/html-to-markdown globally in a service provider:
use League\HTMLToMarkdown\HtmlConverter;
$converter = new HtmlConverter();
$converter->getConfig()->setExtra('tables', true); // Enable table support
How can I help you explore Laravel packages today?