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

Commonmark Laravel Package

league/commonmark

Extensible PHP Markdown parser supporting the full CommonMark spec and GitHub-Flavored Markdown. Works with PHP 7.4+ (mbstring) and provides simple converters to turn Markdown into HTML with configurable safety options.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

composer require league/commonmark

First Use Case: Basic Markdown Conversion

use League\CommonMark\CommonMarkConverter;

$converter = new CommonMarkConverter();
echo $converter->convert('# Hello World!');
// Output: <h1>Hello World!</h1>

Where to Look First

  1. Official Documentation: commonmark.thephpleague.com
  2. Core Classes:
    • CommonMarkConverter (strict CommonMark)
    • GithubFlavoredMarkdownConverter (GFM support)
  3. Security Section: Security Guide
  4. Release Notes: 2.8.3 Changelog

Implementation Patterns

Common Workflows

1. Basic Conversion with Configuration

$converter = new CommonMarkConverter([
    'html_input' => 'strip', // Sanitize HTML input
    'allow_unsafe_links' => false, // Security best practice
]);

2. GFM-Specific Features (Fixed Issues in 2.8.3)

$gfmConverter = new GithubFlavoredMarkdownConverter();
echo $gfmConverter->convert('```\n  code\n```'); // Fixed tab-indented code blocks
echo $gfmConverter->convert('| Tables | Are | Cool |'); // Tables work as expected

3. Custom Environment for Extensions

use League\CommonMark\Environment\Environment;
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;

$env = new Environment();
$env->addExtension(new CommonMarkCoreExtension());

$converter = new CommonMarkConverter($env);

4. Handling Fenced Code Blocks in Lists (Fixed in 2.8.3)

$gfmConverter = new GithubFlavoredMarkdownConverter();
echo $gfmConverter->convert(<<<'MD'
- List item with code:
  ```php
  echo "Fixed!";

MD );


#### 5. Parsing Without HTML Output (AST Access)
```php
$parser = new Parser();
$document = $parser->parse('# Heading');
$xmlConverter = new MarkdownToXmlConverter($env);
echo $xmlConverter->convert($document);

Integration Tips

Laravel Blade Integration

// In a service provider
app()->bind('markdown', function () {
    return new CommonMarkConverter();
});

// In a Blade view
{{ app('markdown')->convert($markdownContent) }}

Form Request Validation

use League\CommonMark\MarkdownParser;

public function rules()
{
    return [
        'content' => ['required', function ($attribute, $value, $fail) {
            $parser = new MarkdownParser();
            $parser->parse($value); // Validate syntax
        }]
    ];
}

API Response Formatting

$converter = new CommonMarkConverter();
return response()->json([
    'content' => $converter->convert($request->markdown)
]);

Safe URL Handling (Fixed in 2.8.3)

$converter = new CommonMarkConverter([
    'allow_unsafe_links' => false,
    'unsafe_link_targets' => ['example.com'] // Explicitly allow safe domains
]);

Gotchas and Tips

Pitfalls

  1. HTML Injection Risks

    • Never use html_input => 'skip' with untrusted input
    • Always sanitize or use html_input => 'strip'
  2. Encoding Issues

    • Only UTF-8/ASCII supported; convert input if needed
    • Use mb_convert_encoding() for non-UTF-8 input
  3. Extension Conflicts

    • Some extensions modify AST nodes in incompatible ways
    • Test extensions thoroughly with your content
  4. Performance with Large Documents

    • Complex markdown with many extensions can be slow
    • Consider caching parsed results for static content
  5. Fenced Code Blocks in Lists (Fixed in 2.8.3)

    • Previously lost first character of each line in tab-indented blocks
    • Now preserved correctly

Debugging Tips

  1. XML Output for Debugging

    $xmlConverter = new MarkdownToXmlConverter($env);
    echo $xmlConverter->convert($document);
    
  2. AST Inspection

    $parser = new Parser();
    $document = $parser->parse('# Test');
    $walker = new NodeWalker($document);
    $walker->walk(function (Node $node) {
        echo get_class($node) . "\n";
    });
    
  3. Common Issues

    • Tables not rendering? Ensure you're using GithubFlavoredMarkdownConverter
    • Emoji not working? Install the Emoji extension
    • Code blocks broken? Check for missing CommonMarkCoreExtension
    • Fenced code blocks mangled? Upgrade to 2.8.3 for fixes (#981, #1130)
  4. Unsafe Link Filtering (Fixed in 2.8.3)

    // Previously might incorrectly block:
    // https://example.com/vbscript:alert(1)
    // Now properly handles URLs with vbscript:, file:, or data: after domain
    

Configuration Quirks

  1. Environment Order Matters

    // Wrong: Extensions may override each other
    $env->addExtension(new ExtensionA());
    $env->addExtension(new ExtensionB());
    
    // Better: Use EnvironmentBuilder
    $env = EnvironmentBuilder::create()
        ->withExtensions([new ExtensionA(), new ExtensionB()])
        ->build();
    
  2. Renderer Priority

    // Last renderer added has highest priority
    $env->addRenderer(new CustomRenderer());
    
  3. GFM Selective Enablement

    $env = EnvironmentBuilder::create()
        ->withExtensions([
            new CommonMarkCoreExtension(),
            new TableExtension(), // Only enable tables
        ])
        ->build();
    
  4. Link Security Configuration

    // Explicitly allow specific domains
    $converter = new CommonMarkConverter([
        'allow_unsafe_links' => false,
        'unsafe_link_targets' => ['trusted.com', 'api.example.org']
    ]);
    

Extension Points

  1. Custom Node Types

    class CustomNode extends AbstractNode {
        // Implement node logic
    }
    
    $env->addNodeType(new CustomNodeType());
    
  2. Inline Parser Extensions

    $env->addInlineParser(new CustomInlineParser());
    
  3. Block Parser Extensions

    $env->addBlockParser(new CustomBlockParser());
    
  4. Renderer Overrides

    $env->addRenderer(new CustomHeadingRenderer());
    

Performance Optimization

  1. Disable Unused Extensions

    $env = EnvironmentBuilder::create()
        ->withExtensions([new CommonMarkCoreExtension()])
        ->withoutExtensions([TableExtension::class]) // Disable tables
        ->build();
    
  2. Cache Parsed Documents

    $cache = new ArrayCache();
    $parser = new Parser();
    $document = $parser->parse($markdown);
    $cache->set('markdown_'.$hash, $document, 3600);
    
  3. Use StringInput for Simple Cases

    $converter = new CommonMarkConverter();
    $html = $converter->convertToHtml($markdownString);
    
  4. Test Edge Cases After Upgrade

    // Verify fixed issues in 2.8.3
    $testCases = [
        'Tab-indented code in lists',
        'URLs with vbscript: after domain',
        'Complex nested lists with code blocks'
    ];
    
    foreach ($testCases as $case) {
        $converter->convert($case);
    }
    
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.
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
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi