Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Markdown Extra Laravel Package

twig/markdown-extra

Twig extension adding Markdown support: convert Markdown to HTML with the markdown_to_html filter, and convert HTML back to Markdown with html_to_markdown. Ideal for rendering user content and round-tripping between formats in Twig templates.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Package:

    composer require twig/markdown-extra
    

    If using Laravel with Twig (via twig/laravel), ensure your composer.json includes:

    "require": {
        "twig/laravel": "^3.0",
        "twig/markdown-extra": "^3.26.0"
    }
    
  2. Register the Extension: In your AppServiceProvider (or TwigServiceProvider if using a custom setup):

    use Twig\Extension\MarkdownExtraExtension;
    
    public function boot()
    {
        $this->app->make(\Twig\Environment::class)->addExtension(new MarkdownExtraExtension());
    }
    
  3. First Use Case: Render Markdown in a Twig template:

    {{ markdown_content|markdown_to_html }}
    

    Convert HTML back to Markdown:

    {{ html_content|html_to_markdown }}
    

Where to Look First

  • Documentation: Twig Markdown Extra README for filter details.
  • Laravel Integration: Check vendor/twig/laravel/src/TwigServiceProvider.php for Twig environment setup.
  • Security Note: Review the CVE-2026-46637 fix to understand auto-escaping behavior.

Implementation Patterns

Core Workflows

1. Rendering User-Generated Markdown (Safe)

{# Forum post rendering #}
<div class="post">
    {{ user_post.markdown|markdown_to_html }}
</div>
  • Key: The filter auto-escapes untrusted input by default (post-CVE fix). No manual |e escaping needed.

2. Bidirectional Content Pipelines

// Laravel Controller: Convert HTML to Markdown for version control
public function updateLegacyContent()
{
    $html = file_get_contents('legacy_post.html');
    $markdown = $this->twig->getTwig()->render(
        '{{ html|html_to_markdown }}',
        ['html' => $html]
    );
    file_put_contents('post.md', $markdown);
}

3. Dynamic Markdown in Blade (Laravel)

// Blade directive for Markdown (custom extension)
Blade::directive('markdown', function ($expression) {
    return "<?php echo \Twig\MarkdownExtra\MarkdownExtraExtension::renderMarkdown({$expression}); ?>";
});

Usage:

@markdown($post->content)

4. Caching Rendered Markdown

// Cache the rendered HTML for 1 hour
$cachedHtml = Cache::remember("markdown_{$post->id}", now()->addHour(), function () use ($post) {
    return $this->twig->render('{{ content|markdown_to_html }}', ['content' => $post->markdown]);
});

Integration Tips

  • Laravel Nova: Use the markdown_to_html filter in custom fields to render Markdown in the admin panel.
  • Livewire: Stream real-time Markdown updates:
    public function updatedMarkdown()
    {
        $this->renderedHtml = $this->twig->render(
            '{{ markdown|markdown_to_html }}',
            ['markdown' => $this->markdown]
        );
    }
    
  • API Responses: Serve Markdown as HTML in JSON APIs:
    return response()->json([
        'content' => $this->twig->render('{{ body|markdown_to_html }}', ['body' => $request->body]),
    ]);
    
  • Form Handling: Convert submitted HTML back to Markdown for storage:
    $markdown = $this->twig->render('{{ html_content|html_to_markdown }}', ['html_content' => $request->html]);
    

Advanced Patterns

Custom Filter for Trusted Content

// Override escaping for trusted Markdown (e.g., admin-only)
$twig->addFilter(new \Twig\TwigFilter('trusted_markdown', function ($markdown) {
    $extension = new MarkdownExtraExtension();
    return $extension->getMarkdown()->parse($markdown); // Bypasses auto-escaping
}));

Warning: Only use this for explicitly trusted sources (e.g., admin inputs).

Extending Markdown Syntax

// Add custom syntax (e.g., {{ alert }} blocks)
$markdown = new \Symfony\Markdown\MarkdownConverter([
    new \Symfony\Markdown\Extension\AlertExtension(), // Hypothetical
]);
$extension = new MarkdownExtraExtension($markdown);
$twig->addExtension($extension);

Gotchas and Tips

Pitfalls

  1. Double Escaping:

    • Issue: Applying |e (Twig’s escape filter) after markdown_to_html breaks HTML rendering.
    • Fix: Remove redundant escaping:
      {# Wrong: Double-escapes #}
      {{ user_comment|markdown_to_html|e }}
      
      {# Correct: Auto-escaping is handled #}
      {{ user_comment|markdown_to_html }}
      
  2. Legacy HTML Breakage:

    • Issue: Auto-escaping may corrupt nested HTML (e.g., <div><a href="..."> in Markdown).
    • Fix: Use html_to_markdown cautiously for complex HTML. Test with:
      {{ legacy_html|html_to_markdown|markdown_to_html }}
      
  3. Custom Filter XSS Risks:

    • Issue: Bypassing auto-escaping in custom filters re-introduces XSS risks.
    • Fix: Document and audit all custom filters. Example of a safe custom filter:
      $twig->addFilter('safe_markdown', [$extension, 'renderMarkdown'], ['is_safe' => ['html']]);
      
  4. Twig Version Conflicts:

    • Issue: Laravel 9.x may conflict with Twig 3.x dependencies.
    • Fix: Pin versions in composer.json:
      "require": {
          "twig/twig": "^3.0",
          "twig/markdown-extra": "^3.26.0"
      }
      
  5. Performance with Large Content:

    • Issue: Parsing massive Markdown blocks (e.g., 10MB docs) may time out.
    • Fix: Stream processing or chunked rendering:
      $markdown = file_get_contents('large_file.md');
      $html = $twig->render('{{ content|markdown_to_html }}', ['content' => $markdown]);
      

Debugging Tips

  • Inspect Rendered Output: Use Twig’s dump filter to debug Markdown parsing:
    {{ markdown_content|markdown_to_html|dump }}
    
  • Check for Malicious Input: Test with payloads like:
    {{ '<script>alert(1)</script>'|markdown_to_html }} {# Should render as text #}
    
  • Enable Twig Debug Mode: In config/twig.php:
    'debug' => env('APP_DEBUG', true),
    

Configuration Quirks

  1. Auto-Escaping Override: The package cannot disable auto-escaping post-v3.26.0. For trusted content, use custom filters (see above).

  2. Extension Registration:

    • If using twig/laravel, the extension is auto-registered. Manual registration may cause duplicates.
    • Fix: Check for duplicate MarkdownExtraExtension instances in your Twig environment.
  3. Markdown Flavor: The package uses Symfony’s CommonMark, which may differ from GitHub-flavored Markdown (e.g., tables, task lists). For full compatibility, extend the converter:

    $converter = new \Symfony\Markdown\MarkdownConverter([
        new \Symfony\Markdown\Extension\TableExtension(),
    ]);
    

Extension Points

  1. Custom Markdown Extensions: Extend Symfony’s Markdown converter to add syntax (e.g., Mermaid diagrams):

    $converter = new \Symfony\Markdown\MarkdownConverter([
        new \Symfony\Markdown\Extension\CustomExtension(),
    ]);
    $extension = new MarkdownExtraExtension($converter);
    
  2. Pre/Post-Processing: Hook into the parsing pipeline:

    $extension = new MarkdownExtraExtension();
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codraw/entity-migrator
codraw/doctrine-extra
codraw/aws-tool-kit
codraw/validator
codraw/workflow
codraw/open-api
codraw/cron-job
codraw/process
codraw/log
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony