Weave 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

Highlightjs Laravel Package

components/highlightjs

A Laravel Blade component for integrating Highlight.js syntax highlighting into your views. Render highlighted code blocks with configurable languages and themes while keeping your markup clean and setup simple.

Deep Wiki
Context7

Getting Started

Understand what you are installing before you run anything: components/highlightjs is a shim repository. It contains no PHP, no service provider, no facade, no config file. It is a Composer-packaged mirror of the upstream Highlight.js browser distribution, published so that Composer-based asset workflows (the old components/* / bower-asset convention) can pull Highlight.js into vendor/ alongside other front-end dependencies. In a modern Laravel app it is a file source, nothing more.

Minimal steps:

composer require components/highlightjs

Then look at exactly two directories, in this order:

  1. vendor/components/highlightjs/styles/ — the CSS themes (github.min.css, atom-one-dark.min.css, etc.). This is the part you will actually reference.
  2. vendor/components/highlightjs/ (root) — one of highlight.min.js, highlight.js, or es/ / lib/ depending on what the shim snapshot shipped. Confirm the file names; do not assume, they vary between shim releases.

First use case — highlighting a code block on a docs or blog page:

{{-- resources/views/docs/show.blade.php --}}
<link rel="stylesheet" href="{{ asset('vendor/highlightjs/styles/github-dark.min.css') }}">

<pre><code class="language-php">{{ $snippet }}</code></pre>

<script src="{{ asset('vendor/highlightjs/highlight.min.js') }}"></script>
<script>hljs.highlightAll();</script>

...after publishing the assets, which is the step people forget:

php artisan vendor:publish --tag=public --force   # only if a publish tag exists
# otherwise, copy manually:
mkdir -p public/vendor/highlightjs
cp -r vendor/components/highlightjs/{highlight.min.js,styles} public/vendor/highlightjs/

If there is no publish tag (likely — shims rarely ship Laravel service providers), wire the copy into composer.json scripts or a small Artisan command so it is reproducible on deploy rather than a one-off manual cp.

Reality check before you commit: the repo is unlisted, the license reports NOASSERTION (upstream Highlight.js is BSD-3-Clause, but you cannot rely on that here), and the star count is low. For a new Laravel project on Vite, npm install highlight.js is the better first move. Reach for this shim only if you are maintaining a Composer-only asset pipeline, a legacy app without Node, or an environment where npm is blocked.

Implementation Patterns

1. Treat it as a vendored asset, not a dependency. The healthiest pattern is a thin build step that copies the shim into your public or Vite pipeline, so the rest of the app never references vendor/ paths directly:

// app/Console/Commands/PublishHighlightJs.php
$src = base_path('vendor/components/highlightjs');
$dst = public_path('vendor/highlightjs');
File::ensureDirectoryExists($dst);
File::copy("$src/highlight.min.js", "$dst/highlight.min.js");
File::copyDirectory("$src/styles", "$dst/styles");

Call it from post-autoload-dump in composer.json so composer install on deploy produces a working front end.

2. Serve it through a Blade component. Wrap the markup so views never repeat the <pre><code> boilerplate and the language-* class convention:

{{-- resources/views/components/code.blade.php --}}
@props(['language' => 'plaintext'])
<pre><code class="language-{{ $language }}">{{ $slot }}</code></pre>

This keeps the shim's class-name contract in one place — important, because if you ever migrate to npm highlight.js or Shiki, the call sites stay unchanged.

3. Pair it with a Markdown renderer. The common day-to-day flow is CommonMark output → highlight. Either let the client handle it (§1 above) or use the shim's Node-side file if you need server rendering. For client-side, a single delegated call is enough:

document.querySelectorAll('pre code').forEach(el => hljs.highlightElement(el));

Prefer highlightElement over highlightAll when content is injected dynamically (Livewire, Turbo, HTMX) — it is idempotent per element and won't re-scan the whole document.

4. Wire it into Vite by aliasing the vendored copy. If you want bundled output rather than a <script> tag, resolve the path explicitly:

// vite.config.js
resolve: { alias: { 'hljs': path.resolve(__dirname, 'vendor/components/highlightjs') } }

...then import hljs from 'hljs/highlight.min.js'. Verify the shim actually ships an ESM build (es/highlight.js) before doing this; many shim snapshots are UMD-only and will not tree-shake.

5. Load languages deliberately. Full builds are ~1 MB. If the shim includes languages/, register only what your content uses:

hljs.registerLanguage('php', php);
hljs.registerLanguage('sql', sql);

On the server side, if the goal is just styling, you can skip Highlight.js entirely and let the CSS class contract (.hljs-keyword, .hljs-string) do the work — useful when another tool already emits highlighted tokens.

6. Theme switching via config, not code. Store the chosen theme in config/view.php or a settings table and emit the stylesheet link from a layout component. Users switching dark/light is a CSS-variable problem; don't reload the shim.

Gotchas and Tips

  • No Laravel integration. There is no service provider, no config/highlightjs.php, no publish tag in most shim snapshots. Anything that says otherwise is your own wrapper. Assume vendor:publish will not work and plan the copy step yourself.
  • The license is the biggest risk. NOASSERTION means the package metadata did not resolve to a recognized SPDX identifier. Upstream Highlight.js is BSD-3-Clause, but you are relying on the shim author's fidelity to it. If your legal review is strict, install from npm/CDN where the license file is present and verifiable, or vendor the file yourself with a checked-in LICENSE from the official release.
  • Shim repos go stale silently. composer update may pin you to an old Highlight.js major with known regex/ReDoS issues in older language grammars. Check the version actually shipped: grep -m1 version vendor/components/highlightjs/package.json or inspect the minified header. Pin explicitly in composer.json and review on upgrade.
  • components/* naming collides with Composer's installer-plugin ecosystem. Historically these packages relied on composer/installers to place files outside vendor/. If you are on Composer 2 with a standard Laravel skeleton, files land in vendor/components/highlightjs and stay there — do not reference that path from a Blade asset() call. asset() points at public/, so a vendor/ path yields a 404 that looks like a missing file but is really a path-root mismatch. Debug by checking the rendered URL against the filesystem.
  • highlightAll on dynamically inserted content does nothing. It runs once at load. Use hljs.highlightElement(el) inside a livewire:navigated / turbo:load listener, or wrap in Alpine's x-init.
  • Escaping is your responsibility. hljs.highlightElement reads textContent and rewrites innerHTML. That is safe for code, but if you build the <pre> from user input with {!! !!} you have already lost. Always use {{ }} for the code body.
  • Theme CSS and token classes are versioned together. A styles/ file from one release against highlight.min.js from another produces unstyled or partially styled tokens. Copy both from the same directory in the same step.
  • Extension point that actually exists: none in PHP. Your extension surface is the Blade component and the copy command — build the abstraction there so a future swap to npm highlight.js, Shiki, or a server-side highlighter is a one-file change instead of a grep across views.
  • If a file is missing, check package.json in the shim root to see which build artifacts that snapshot was supposed to include. Some shims ship only styles/ + highlight.min.js; others only lib/ + es/. Do not write your asset command against filenames you have not listed.
  • Verdict for day-to-day work: fine as a zero-config asset mirror for Composer-only stacks, but it adds a supply-chain and staleness risk for no functional gain over npm i highlight.js. Use it when npm is genuinely unavailable, isolate it behind your own copy step, and pin the version.
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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle