spatie/commonmark-highlighter
Server-side syntax highlighting for league/commonmark code blocks using scrivo/highlight.php. Generates HTML compatible with highlight.js themes, reducing JavaScript and avoiding flashes of unstyled code. Supports 185+ languages for fast, clean markdown rendering.
Installation:
composer require spatie/commonmark-highlighter
Requires league/commonmark (≥2.0) and scrivo/highlight.php (≥v9.18).
Basic Usage:
use League\CommonMark\CommonMarkConverter;
use Spatie\CommonMarkHighlighter\CommonMarkHighlighter;
$converter = new CommonMarkConverter();
$converter->addRenderer(new CommonMarkHighlighter());
$markdown = <<<MD
```php
<?php
echo "Hello, world!";
MD;
echo $converter->convert($markdown);
Outputs HTML with syntax-highlighted PHP code.
First Use Case:
league/commonmark pipelines (e.g., in a MarkdownRenderer service).Integration with Laravel:
AppServiceProvider:
public function boot()
{
$converter = new CommonMarkConverter();
$converter->addRenderer(new CommonMarkHighlighter());
app()->singleton('markdown.converter', fn() => $converter);
}
$html = app('markdown.converter')->convert($markdownContent);
return view('post.show', compact('html'));
Dynamic Configuration:
new CommonMarkHighlighter(
theme: 'atom-one-dark',
lineNumbers: true,
tabSize: 4
)
Theming:
'monokai') to the constructor.Spatie\CommonMarkHighlighter\Highlight\Theme and pass an instance.Language Detection:
php` `code` ).scrivo/highlight.php’s language mappings).Caching:
Cache::remember()) to avoid reprocessing identical content.Custom Highlighting Rules:
Extend Spatie\CommonMarkHighlighter\Highlight\Highlighter to add language-specific rules or preprocess code blocks.
Blade Directives: Create a Blade directive for concise syntax:
Blade::directive('markdown', function ($expression) {
return "<?php echo app('markdown.converter')->convert({$expression}); ?>";
});
Usage:
@markdown($post->content)
API Responses: Use the highlighter in API responses for rich Markdown rendering:
return response()->json(['content' => app('markdown.converter')->convert($markdown)]);
Language Mismatch:
php` `code` ), auto-detection may fail for obscure languages.scrivo/highlight.php supports it.Performance:
Theme Incompatibility:
scrivo/highlight.php.Markdown Parsing Conflicts:
league/commonmark’s Environment to configure parsers.Dependency Conflicts:
scrivo/highlight.php may conflict with other packages using highlight.php (e.g., vlucas/phpdotenv).composer why-not to diagnose and pin versions.Log Highlighting Errors: Wrap the highlighter in a try-catch to log unsupported languages:
try {
$html = $highlighter->renderBlock($block);
} catch (\Exception $e) {
\Log::error("Highlighting failed for {$block->getLanguage()}: " . $e->getMessage());
$html = "<pre>{$block->getContent()}</pre>"; // Fallback
}
Inspect Raw Output:
Use dd($block->getContent()) to verify input before highlighting.
Theme Debugging: Test themes in isolation:
$highlighter = new CommonMarkHighlighter(theme: 'your-theme');
echo $highlighter->highlight('return "test";', 'php');
Custom Highlighter:
Override Spatie\CommonMarkHighlighter\Highlight\Highlighter to add:
Event Hooks:
Use league/commonmark’s EventDispatcher to hook into parsing:
$environment = Environment::create();
$environment->addEventListener(
new CodeBlockRenderedEventListener($highlighter)
);
Fallback Renderer: Implement a fallback for unsupported languages:
$converter->addRenderer(new FallbackCodeBlockRenderer());
Tab Size:
Default is 4. Adjust via constructor or environment config:
config(['commonmark-highlighter.tab_size' => 2]);
Line Numbers: Enable globally via config:
config(['commonmark-highlighter.line_numbers' => true]);
CSS Inlining:
The highlighter outputs <style> tags by default. Disable with:
new CommonMarkHighlighter(includeStyle: false);
How can I help you explore Laravel packages today?