Installation
composer require aptoma/twig-markdown
Register the service provider in config/app.php:
'providers' => [
// ...
Aptoma\TwigMarkdown\TwigMarkdownServiceProvider::class,
],
Basic Usage
In a Twig template, use the markdown() filter:
{{ 'This is **Markdown**'|markdown }}
Renders as: This is Markdown (with proper HTML conversion).
First Use Case Convert markdown in blog posts or documentation:
<article>
{{ post.content|markdown }}
</article>
Dynamic Markdown Processing Pass markdown from a database or API:
{% for doc in documents %}
<div class="doc-content">
{{ doc.body|markdown }}
</div>
{% endfor %}
Customizing Output
Use Twig’s safe filter to avoid auto-escaping (if trusted content):
{{ markdown_content|markdown|safe }}
Integration with Laravel Blade
Use @php to pre-process markdown in Blade:
@php
$rendered = e(Str::markdown($post->content));
@endphp
{{ $rendered }}
Syntax Highlighting
Combine with vlucas/phpdotenv or league/commonmark extensions:
{{ markdown_content|markdown({ 'extensions': ['highlight'] }) }}
Reusable Components Create a Twig macro for consistent markdown rendering:
{% macro renderMarkdown(content) %}
<div class="markdown-body">
{{ content|markdown }}
</div>
{% endmacro %}
Conditional Rendering Skip markdown processing for non-markdown content:
{% if content_is_markdown %}
{{ content|markdown }}
{% else %}
{{ content }}
{% endif %}
XSS Vulnerabilities
|safe on untrusted markdown. Always sanitize first:
{{ markdown_content|markdown|striptags }}
league/commonmark's HtmlRenderer with allow_unsafe_links = false.Performance
Cache::remember):
Cache::remember("markdown_{$id}", now()->addHours(1), function() use ($post) {
return Str::markdown($post->content);
});
Extension Conflicts
spatie/laravel-markdown, disable the package’s Twig integration to avoid duplication.Check Extensions If syntax fails (e.g., tables), verify extensions:
{{ markdown_content|markdown({ 'extensions': ['tables'] }) }}
Log Errors
Enable Twig’s debug mode in .env:
TWIG_DEBUG=true
Custom Extensions
Register new CommonMark extensions in config/twig-markdown.php:
'extensions' => [
new \League\CommonMark\Extension\TaskList\TaskListExtension(),
],
Override Default Renderer
Bind a custom HtmlRenderer in the service provider:
$this->app->bind(\League\CommonMark\HtmlRendererInterface::class, function () {
return new CustomHtmlRenderer();
});
Fallback for Non-Markdown Handle plain text gracefully:
{{ content|default('No content')|markdown }}
How can I help you explore Laravel packages today?