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

Ux Prism Laravel Package

krystal-sf/ux-prism

Prism is a Laravel UX toolkit that refracts interface work into reusable Blade components and helpers, so teams can ship consistent, accessible UIs faster with less custom markup and CSS. A pragmatic design layer for modern Laravel apps.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony UX bundle that wires Prism.js into a Symfony app — it ships the Stimulus controller, the importmap/Encore wiring, and the theme CSS so you don't hand-roll them. It is not a Laravel package and has no Blade equivalent; there is no ServiceProvider, no config/ux-prism.php, and no facade. If you're coming from Laravel, think of it as the Symfony analogue of a small package that registers a Blade directive plus a <script> tag — you'll be working in config/bundles.php, assets/controllers.json, and Twig, not in app/Providers.

Practical reality check before you invest: the package has no stars, no dependents, and isn't on Packagist. Treat it as an internal Krystal artifact. Confirm the tag/branch you're pinning to and read the bundle source before adopting.

1. Add the repository (you will need this — it is not on Packagist):

{
    "repositories": [
        { "type": "vcs", "url": "https://gitlab.com/krystal-sf/ux-prism" }
    ],
    "require": {
        "krystal-sf/ux-prism": "dev-main"
    }
}

CI needs a GitLab token or SSH deploy key; anonymous clone will fail. If you can't authenticate, budget for vendoring the controller and CSS by hand instead.

2. Register the bundle:

// config/bundles.php
return [
    // ...
    Krystal\Sf\UxPrism\UxPrismBundle::class => ['all' => true],
];

Verify the FQCN from the package's composer.json autoload.psr-4 block — the namespace is the single most likely thing to be wrong in a low-traffic package.

3. Install the JS side. If the app uses AssetMapper + Symfony UX, the controller is exposed through assets/controllers.json under the package name convention. If it uses Webpack Encore, you'll import from vendor/krystal-sf/ux-prism/assets/ directly.

4. First use case — highlight a code block in Twig:

<pre data-controller="prism"><code class="language-php">{{ snippet }}</code></pre>

or, with the Stimulus Twig helpers:

<pre {{ stimulus_controller('prism') }}><code class="language-bash">php bin/console cache:clear</code></pre>

Where to look first, in this order:

  1. composer.json — namespace, autoload paths, whether Prism is a hard or peer dependency.
  2. assets/controllers.json (or the bundle's Resources/assets/) — the exact Stimulus controller name and identifier. Do not assume it's prism.
  3. The bundle's config tree (DependencyInjection/Configuration.php), if any — theme selection, language list, plugin toggles.
  4. The CSS entrypoint — which Prism theme is bundled and whether it's auto-injected.

Implementation Patterns

Auto-init via Stimulus (the intended path). The controller typically calls Prism.highlightAllUnder(this.element) on connect(). That means the controller can be scoped to a container rather than every <code> block:

<article data-controller="prism">
    <pre><code class="language-php">…</code></pre>
    <pre><code class="language-yaml">…</code></pre>
</article>

Scoping beats dropping data-controller on every <pre> — it survives partial re-renders better and keeps the DOM readable.

Registering languages and plugins explicitly. Prism's default bundle is small. Most real apps need extra grammars, and the right place is your own assets/app.js, not the vendor dir:

import Prism from 'prismjs';
import 'prismjs/components/prism-twig';
import 'prismjs/components/prism-php';
import 'prismjs/components/prism-docker';
import 'prismjs/plugins/line-numbers/prism-line-numbers';
import 'prismjs/plugins/line-numbers/prism-line-numbers.css';

Prism.manual = true; // stop the DOMContentLoaded auto-run

Order matters: import the plugin after core, and import its CSS after the theme CSS or it'll get overridden.

Content rendered server-side from Markdown. If you're storing docs as Markdown and rendering with league/commonmark (Symfony's equivalent of Laravel's Str::markdown()), you get <pre><code class="language-x"> for free — just make sure the CommonMark renderer is configured to emit the language- class prefix, which is Prism's expected format:

$config = ['html_input' => 'escape'];
$converter = new CommonMarkConverter($config);
// Fenced blocks render as <code class="language-php">

Then wrap the whole rendered body in a single data-controller="prism" container and you're done.

Handling client-side navigation. If you use Turbo (or swup), the Stimulus controller's connect() fires again on each page swap, which is usually all you need. If you're rendering fragments outside Stimulus, re-run manually:

document.addEventListener('turbo:load', () => Prism.highlightAll());

Diff and line-highlight decoration. Prism plugins read data-* attributes on the <pre> element, which compose nicely with Twig:

<pre class="line-numbers" data-line="3,7-9"
     data-controller="prism"><code class="language-diff-php">…</code></pre>

Theming. Either let the bundle inject its theme, or set a theme in your own CSS layer and disable the bundled one (check the config tree for a theme: false / theme: null option). Don't do both — you'll ship two token rulesets and spend an hour wondering why strings are the wrong green.

Gotchas and Tips

It is Symfony-only. There's no Laravel bridge, no Blade directive, no published config. In a Laravel codebase you'd be reimplementing this in ~20 lines (a Blade component plus an @push for the script). The value here is entirely in Symfony UX plumbing, so if you're not on Symfony with AssetMapper or Encore, this package adds nothing.

Pin to a commit, not a branch. dev-main on a repo with zero dependents means nobody is watching for breaking changes but you. Use an explicit SHA in composer.json and review diffs on bump:

"krystal-sf/ux-prism": "dev-main#a1b2c3d4"

Prism's auto-highlight will fight you. Prism highlights on DOMContentLoaded by default. If your content arrives after that (AJAX, Turbo frame, StreamedResponse), it silently renders unhighlighted. Set Prism.manual = true and drive highlighting from the controller, or accept double-highlighting cost.

Language grammars are lazy in AssetMapper. importmap:require prismjs gets you core only; prismjs/components/prism-twig is a bare (non-module) script that depends on a global Prism. In AssetMapper this is the most common breakage. Either add each component to importmap.php manually and verify with:

php bin/console debug:asset-map | grep prism
php bin/console importmap:validate

…or use prismjs/plugins/autoloader and accept that it fetches grammars at runtime over the network (bad for CSP, bad offline).

Stimulus identifier mismatch. Symfony UX packages are registered via assets/controllers.json under a @vendor/package key. If the bundle's key doesn't match what its package.json declares, the controller never loads and you get a console warning about an unknown data-controller. Symptoms: markup correct, no highlighting, no errors. Check the browser devtools for the Stimulus "Missing controller" log before touching anything else.

className collisions. Prism uses .token classes and a bare pre[class*="language-"] selector for its theme. If your design system also styles pre, you'll get specificity fights. Scope the theme behind a wrapper class rather than editing vendor CSS.

Escaping is on you. If you build the <code> contents from user input and don't escape, Prism will happily render your XSS. Twig's autoescaping covers this in templates; it does not cover content injected via innerHTML in JS.

Plaintext fallback. Blocks with no recognised language- class render unstyled, which can look broken next to highlighted ones. Explicitly tag language-none (Prism's built-in no-op grammar) or language-plaintext rather than leaving it bare.

Extension points are thin. Realistically you get: override the Stimulus controller in your own assets/controllers/, add grammars/plugins in app.js, and toggle the theme in config. There is no documented plugin API or event system worth building on. If you need per-block copy buttons or line anchors, write a thin wrapper controller that extends the vendor one rather than patching the package — you'll be re-patching on every update otherwise.

Bus factor. One internal repo, no public issues, no releases visible. Before adopting, ask the owning team who maintains it, whether Prism major bumps are tracked (Prism v1 → v2 is a breaking rewrite for plugins), and whether it's still the sanctioned approach or a leftover from a single project. If the answer is vague, vendoring ~100 lines of controller and CSS is the lower-risk path.

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.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums