spatie/commonmark-shiki-highlighter
League/CommonMark code block renderer that highlights fenced code using Shiki PHP. Includes extra Antlers and Blade grammars in addition to Shiki’s 100+ languages. Ideal for Laravel setups (see spatie/laravel-markdown). Requires JS shiki v1.
Installation:
composer require spatie/commonmark-shiki-highlighter
Requires league/commonmark (≥v2.0) and spatie/shiki-php (≥v1.0).
Basic Usage:
use League\CommonMark\CommonMarkConverter;
use Spatie\CommonmarkShikiHighlighter\ShikiHighlighter;
$converter = new CommonMarkConverter();
$converter->getEnvironment()->addBlockRenderer(
'code',
new ShikiHighlighter()
);
$markdown = <<<MARKDOWN
```php
echo "Hello, world!";
MARKDOWN;
echo $converter->convert($markdown);
First Use Case:
Integration with CommonMark:
ShikiHighlighter as a block renderer for code blocks in your CommonMarkConverter instance.public function boot()
{
$converter = app(CommonMarkConverter::class);
$converter->getEnvironment()->addBlockRenderer('code', new ShikiHighlighter());
}
Dynamic Configuration:
$highlighter = new ShikiHighlighter([
'theme' => 'github-dark',
'languages' => ['php', 'javascript'],
]);
Caching Highlighted Code:
$highlighter = new ShikiHighlighter(['cache' => true]);
Laravel-Specific Integration:
spatie/laravel-markdown for seamless Blade/Markdown support:
use Spatie\Markdown\MarkdownRenderer;
$renderer = new MarkdownRenderer();
$renderer->withCommonMarkConverter($converter); // Pre-configured with ShikiHighlighter
Fallback Languages:
$highlighter = new ShikiHighlighter(['fallback' => true]);
Custom Themes:
$highlighter = new ShikiHighlighter(['themePath' => storage_path('themes')]);
Async Processing:
Shiki Dependencies:
shiki-php is installed (requires Node.js for theme compilation). Run:
composer require spatie/shiki-php
vendor/bin/shiki install
Language Detection:
php vs. html). Explicitly specify languages in code blocks:
```php
// Explicit language
Performance:
Theme Compatibility:
Logs:
putenv('SHIKI_DEBUG=1');
Fallbacks:
fallback is enabled when code blocks render as plain text.Custom Renderers:
ShikiHighlighter to modify output (e.g., wrap in <pre> tags):
class CustomHighlighter extends ShikiHighlighter {
public function renderBlock(CodeBlock $block): string {
return '<pre>' . parent::renderBlock($block) . '</pre>';
}
}
Language Overrides:
ShikiHighlighter:
protected function getLanguage(string $language): ?string {
return $language === 'custom' ? 'php' : null;
}
Theme Management:
$highlighter = new ShikiHighlighter(['themeResolver' => fn() => $this->getThemeFromDb()]);
Laravel Blade:
Use @markdown directive with spatie/laravel-markdown for seamless syntax highlighting in Blade templates.
Testing:
Mock ShikiHighlighter in tests to avoid Node.js dependencies:
$highlighter = Mockery::mock(ShikiHighlighter::class)->shouldReceive('renderBlock')->andReturn('<code>mock</code>');
CI/CD: Pre-install Shiki themes in CI to avoid runtime setup:
composer require spatie/shiki-php
vendor/bin/shiki install --themes github-dark
How can I help you explore Laravel packages today?