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

Filament Rich Editor Toolkit Laravel Package

asignua/filament-rich-editor-toolkit

A Filament RichEditor toolkit adding customizable toolbar buttons, plugins, and content tools for Laravel admin forms. Extend rich text editing with reusable actions and a smoother authoring experience.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Upgrade with composer require then run php artisan filament:assets — v1.1.0 ships new and changed editor modules, and the editor-side plugins are what make the new rendering work. Run php artisan config:clear too if you cache config.
  • Look first at config/renderer.php (renderer.link_options, renderer.image_properties) and config/paste_clean.php (paste_clean.remote_image_guests, remote image allow-list). These are the only knobs that restore 1.0 behaviour.
  • First use case: render stored HTML through RichEditorToolkit::renderer($html) instead of echoing the raw value, e.g. in a Blade component or model accessor. Then diff the output against a page you already had in production — this release changes markup with no code change on your side.
  • Fast smoke test: paste a link, a <figure><img><figcaption> block, and an empty-alt image into the editor, save, and inspect the rendered HTML. You should see target/rel handling, span.asignua-rte-figure / span.asignua-rte-caption, and the empty-alt <img> retained.
  • If you must ship before auditing CSS, pin the old output globally:
    // config/renderer.php
    'link_options' => false,
    'image_properties' => false,
    
    or per call: RichEditorToolkit::renderer($html, links: false, images: false) / RichEditorToolkit::plugins(links: false, images: false).

Implementation Patterns

  • Keep editor and renderer flags in sync. The plugins are on by default because the editor needs them at render time; disabling only one side means a caption the user saved is visible while editing but vanishes on the published page (or vice versa). Treat plugins() and renderer() as a pair, ideally behind one app-level helper:
    $renderer = fn (string $html) => RichEditorToolkit::renderer($html, links: true, images: true);
    
  • Roll out per-surface, not globally. Add a feature flag (config/env) around the renderer.link_options and renderer.image_properties values so you can enable the new output on a marketing section before flipping the whole app, and flip back without a deploy.
  • Centralise rendering in one place (a Blade component, HtmlString cast, or an API resource) so every consumer gets the same link/caption/alt behaviour. Ad-hoc {!! $html !!} calls scattered across views will silently keep raw <figure> markup and unnormalised rel.
  • Link policy as configuration. Decide your link_options.rel_tokens list up front — nofollow, sponsored, ugc all need to be listed or they are filtered out of rendered anchors. Anything that must survive authoring should be a token.
  • Style the new caption markup, not the old. Target .asignua-rte-figure / .asignua-rte-caption, and during migration write comma-separated selectors that also match legacy figure / figcaption so old and new content look the same.
  • Authorize remote images deliberately. For Google Docs pastes, either require a logged-in user (default) or opt into guests via paste_clean.remote_image_guests / authorizeRemoteImages(). Prefer a Gate/policy that checks the user and rate-limits, since the fetch happens without a proxy.
  • Tighten the remote image allow-list. Replace wildcard-over-public-suffix entries (*.co.uk) with explicit hosts; the new matching no longer honours them, so remote images will fail silently rather than error.
  • Add regression tests around rendering. A small set of fixture-based assertions (anchor with rel, _blank forcing noopener noreferrer, figure→span re-render, empty alt kept) pays for itself the next time output changes by default.

Gotchas and Tips

  • This is a silent breaking change. No code change required to alter published pages. Expect snapshot tests, CSS selectors on figure/figcaption, and any JS that queried those tags to break.
  • figcaption markup is flattened. Bold, links, and line breaks inside old captions are lost on re-render. If your content relies on rich captions, back up and pre-process, or keep images: false on those surfaces.
  • rel is a whitelist, not a pass-through. Any rel value not in link_options.rel_tokens is dropped — a common cause of "SEO attributes disappeared". Adding noopener noreferrer on _blank is forced and cannot be suppressed per-link.
  • target only survives as _blank. _self, _parent, frames, and named targets are dropped; audit internal links that relied on named targets.
  • <img alt=""> is now kept. Decorative images that previously vanished from output will reappear — check a11y assertions, lazy-loading selectors, and CSS that assumed presence/absence.
  • Google Docs downloads now require a user. Public/guest editors will quietly stop importing pasted images. Fix by login, or explicitly authorizing guests and constraining the allow-list. There is no proxy and no decompression, so the server fetches user-supplied hosts directly — treat the allow-list as a security boundary.
  • Wildcard allow-list entries over public suffixes stop matching. *.co.uk, *.github.io-style patterns need explicit hostnames; verify with a real paste, because the failure mode is a missing image, not an exception.
  • Run php artisan filament:assets on every deploy. Skipping it leaves the JS modules out of sync with the renderer, producing editor/renderer drift that looks like a rendering bug.
  • Debugging: dump RichEditorToolkit::plugins() to confirm which plugins are active, then diff renderer($html) before and after the upgrade on a real record. Most "bugs" here are one of the three flags being off in one place and on in another.
  • Extension points: custom plugins can be appended to plugins(), rel_tokens is a plain config list, and the renderer accepts per-call flags — so you can scope behaviour by model, panel, or route rather than committing app-wide.
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.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel