nicodmf/highlight-bundle
Symfony bundle that integrates highlight.php to add syntax highlighting for code snippets. It provides Twig helpers and configurable themes, making it easy to render readable, colorized source code in templates with minimal setup.
This is a Symfony2 bundle, not a Laravel package. composer require nicodmf/highlight-bundle will not produce a working feature in a Laravel app — no service provider, no Blade extension, no config publish, and the code targets Symfony2-era container wiring. Do not install it. Instead, read it as a reference spec and build a ~1–2 day Laravel-native equivalent.
Read these three things first, in this order:
Pygment, Geshi, Highlight). This is the whole reusable idea: a highlight(string $code, string $lang): string seam over swappable engines.Then pick your engine before writing any code:
scrivo/highlight.php (highlight.js port) — pure PHP, no shell exec, installs with Composer. Start here for Laravel.pygmentize) — best quality, but requires Python in every container and a Process call per snippet.highlight — needs --out-format=xhtml; default output is ANSI and useless in HTML.easybook/geshi) — pure PHP, dated output, viable if scrivo has a coverage gap.First use case: a docs, blog, or changelog page rendering fenced code blocks from stored Markdown. The realistic Laravel shape is a highlight() helper + a <x-code-block :code="$snippet" language="php" /> component, backed by a cached service.
Bind an interface, not a backend. That's the one durable lesson from the bundle:
interface Highlighter { public function highlight(string $code, string $language): string; }
Bind ScrivoHighlighter::class in a HighlighterServiceProvider. Swap engines later without touching Blade.
Blade component over directive. A directive that returns HTML bypasses escaping mental models. Use an anonymous component that returns a HtmlString explicitly, so reviewers can see the unescaped boundary.
<x-code-block language="php" :code="$snippet" />
// resources/views/components/code-block.blade.php
<pre class="hljs"><code class="language-{{ $language }}">{!! app(Highlighter::class)->highlight($code, $language) !!}</code></pre>
Cache at the edge, keyed on content. Highlighting is CPU-bound (and process-bound if shelling out). Wrap the engine in a CachedHighlighter decorator:
$key = 'hl:'.hash('xxh128', $theme.'|'.$language.'|'.$code);
return Cache::remember($key, now()->addDay(), fn () => $engine->highlight($code, $language));
If snippets come out of a model, prefer precomputing into a highlighted_html column on save and rendering that — you remove highlighting from the request path entirely. This is what the Symfony bundle never solved, and it's the difference between a snappy page and a p95 blowout.
Use class-based themes, not inline styles. Emit hljs classes and ship the theme via Vite, so output is CSP-friendly and swappable per page. Pygments-based engines tend toward inline stylesheets — strip or override them.
Normalize unknown languages to a safe fallback. Map lang ?: 'text' to a registered language; render raw-but-escaped htmlspecialchars() inside <code> when unknown. Never fall through to "just output the string" — that's how you get XSS.
Guard untrusted input. Cap input length (e.g. 20 KB), strip CRLF edge cases, and treat output as untrusted if the source is user-submitted. Even a pure-PHP port can emit markup you don't want in a <script> context.
--ignore-platform-reqs your way into the bundle. Modern Laravel on PHP 8.x will at best autoload dead classes; at worst you get container or autoloader conflicts. The Symfony Bundle concept has no analogue in Laravel.mews/purifier or a DOM-whitelist pass) or pre-render and store sanitized HTML.Symfony\Component\Process\Process with a hard timeout (setTimeout(2)) and an input cap. A multi-megabyte pasted snippet will happily fork-bomb your workers at peak traffic.scrivo and highlight.js guess from content; don't rely on it for user-facing labels or links. Always require an explicit language argument from the template, defaulting to text.<, >, & before emitting spans. Verify by highlighting a snippet that literally contains <script>alert(1)</script>.config('highlight.theme') changes.scrivo can't handle (some LaTeX dialects, niche DSLs), add a PygmentsHighlighter behind the same interface — don't rewire Blade.How can I help you explore Laravel packages today?