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

Shiki Php Laravel Package

spatie/shiki-php

Use Shiki syntax highlighting from PHP. Highlight code snippets with editor-quality themes and 100+ languages, plus Antlers and Blade. Works great with Laravel via spatie/laravel-markdown and CommonMark through a companion extension.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:

    composer require spatie/shiki-php
    npm install shiki  # or yarn add shiki
    

    Ensure Node.js 20+ is installed.

  2. First usage:

    use Spatie\ShikiPhp\Shiki;
    
    echo Shiki::highlight(
        code: '<?php echo "Hello World"; ?>',
        language: 'php',
        theme: 'github-light'
    );
    

    Outputs a <pre class="shiki">...</pre> block with syntax-highlighted HTML.

  3. Key first use cases:

    • Rendering code snippets in Markdown (e.g., docs, blogs).
    • Highlighting Blade/Antlers templates (built-in support).
    • Dynamic code blocks in Laravel views or API responses.

Implementation Patterns

Core Workflows

1. Basic Highlighting

Shiki::highlight(
    code: file_get_contents('App/Service.php'),
    language: 'php',
    theme: 'dracula'
);
  • Tip: Cache the output if rendering the same code repeatedly (e.g., in a View Composer).

2. Markdown Integration

  • With spatie/laravel-markdown:
    use Spatie\Markdown\MarkdownRenderer;
    
    $renderer = new MarkdownRenderer();
    $renderer->useShiki(); // Auto-highlights code blocks
    echo $renderer->toHtml('# Hello **World**');
    
  • With league/commonmark: Use spatie/commonmark-shiki-highlighter for custom parsers.

3. Dynamic Themes

$userTheme = auth()->user()->preferred_theme ?? 'github-dark';
echo Shiki::highlight($code, 'php', $userTheme);
  • Custom themes: Pass a path to a .json theme file:
    Shiki::highlight($code, 'php', __DIR__.'/themes/custom-theme.json');
    

4. Line Annotations

// Highlight specific lines (e.g., for diffs or tutorials)
Shiki::highlight(
    code: $code,
    language: 'php',
    highlightLines: [3, '5-7'], // Lines 3, 5-7
    addLines: [10],             // Added line
    deleteLines: [2],           // Deleted line
    focusLines: [4]             // Focus line
);
  • CSS Targeting: Use classes like .shiki .line--highlighted in your stylesheet.

5. Language Detection

if (Shiki::languageIsAvailable('rust')) {
    echo Shiki::highlight($rustCode, 'rust');
} else {
    echo '<p>Unsupported language</p>';
}
  • List all available languages/themes:
    $languages = Shiki::getAvailableLanguages();
    $themes    = Shiki::getAvailableThemes();
    

Laravel-Specific Patterns

1. View Composers

// app/Http/ViewComposers/CodeBlockComposer.php
public function compose(View $view) {
    $view->with('highlight', function($code, $lang = 'text') {
        return Shiki::highlight($code, $lang, 'github-dark');
    });
}

Usage in Blade:

@highlight($codeSnippet, 'php')

2. API Responses

return response()->json([
    'code' => Shiki::highlight($code, 'javascript', 'vscode-dark-plus'),
]);

3. Caching Highlighted Output

$cacheKey = "shiki_{$lang}_{md5($code)}";
$highlighted = Cache::remember($cacheKey, now()->addHours(1), function() use ($code, $lang) {
    return Shiki::highlight($code, $lang);
});

4. Dynamic Blade Directives

// Register a custom directive
Blade::directive('highlight', function($expression) {
    return "<?php echo \\Spatie\\ShikiPhp\\Shiki::highlight($expression, 'php'); ?>";
});

Usage:

@highlight('$user->name')

Performance Considerations

  1. Large Code Blocks:

    • Use stdin for files >4KB (avoids proc_open() errors):
      Shiki::highlight(file_get_contents('large-file.php'), 'php');
      
    • Workaround: Split into chunks if needed.
  2. Batch Processing:

    $highlights = collect($codeBlocks)->map(function($block) {
        return Shiki::highlight($block['code'], $block['lang']);
    });
    
  3. Queue Jobs:

    // For async rendering (e.g., user-uploaded files)
    HighlightCodeJob::dispatch($filePath, $language);
    

Gotchas and Tips

Pitfalls

  1. Node.js Path Issues:

    • Symlink Fix: If using NVM, create a symlink:
      sudo ln -s ~/.nvm/versions/node/v20.x.x/bin/node /usr/local/bin/node
      
    • Debug: Check Node path with:
      Shiki::getNodePath(); // Returns the detected path
      
  2. Large Code Blocks:

    • Error: proc_open(): posix_spawn() failed: Argument list too long
    • Fix: Upgrade to shiki-php v2.3.3+ (uses stdin for large inputs).
  3. Theme/Language Availability:

    • Gotcha: Custom themes must be absolute paths (not relative).
    • Debug: Use Shiki::getAvailableThemes() to verify themes.
  4. Blade/Antlers Quirks:

    • Blade: Ensure @ symbols are escaped in code (e.g., @@yield).
    • Antlers: Complex nested syntax may need manual tweaks.
  5. Caching Caveats:

    • Invalidation: Clear cache when themes/languages update.
    • Key Collisions: Use unique keys (e.g., md5($code.$lang)).

Debugging Tips

  1. Log Output:

    $html = Shiki::highlight($code, 'php');
    \Log::debug($html); // Inspect raw HTML
    
  2. Validate Input:

    if (!Shiki::languageIsAvailable($lang)) {
        throw new \InvalidArgumentException("Unsupported language: {$lang}");
    }
    
  3. Test Themes:

    // Test all themes in a loop
    foreach (Shiki::getAvailableThemes() as $theme) {
        echo Shiki::highlight('test', 'text', $theme);
    }
    
  4. Node Version Conflicts:

    • Symptom: Error: Cannot find module 'shiki'
    • Fix: Ensure node_modules/shiki exists in your project root.

Extension Points

  1. Custom Renderers:

    • Override the default Node script:
      Shiki::setRendererScript(__DIR__.'/custom-renderer.js');
      
  2. Post-Processing:

    $html = Shiki::highlight($code, 'php');
    $html = str_replace('<span class="line">', '<span class="line" data-line="', $html);
    
  3. Event Listeners:

    • Hook into highlight events (e.g., log usage):
      Shiki::highlight($code, 'php')->then(function($html) {
          \Log::info('Highlighted code', ['length' => strlen($html)]);
      });
      
  4. Custom Languages:

    • Extend Shiki’s core by adding language files to your project’s node_modules/shiki/langs.

Pro Tips

  1. Dark/Light Mode Toggle:

    $theme = request()->wantsJson() ? 'github-dark' : 'github-light';
    
  2. Line Numbers:

    • Use CSS to add line numbers:
      .shiki .line {
          counter-increment: line-number;
      }
      .shiki .line::before {
          content: counter(line-number);
          margin-right: 1rem;
      }
      
  3. Copy-to-Clipboard:

    <button onclick="copyToClipboard('{{ $highlightedHtml }}')">Copy</button>
    <script>
        function copyToClipboard(html) {
            const temp = document.createElement('textarea');
            temp.value = html.replace(/<[^>]*>/g
    
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.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai