Download the PHP package asignua/filament-rich-editor-toolkit without Composer

On this page you can find all versions of the php package asignua/filament-rich-editor-toolkit. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package filament-rich-editor-toolkit

Filament Rich Editor Toolkit

Stand With Ukraine Latest Version on Packagist Tests Total Downloads License Plumb score

Filament Rich Editor Toolkit

Five free plugins for the Filament 5 RichEditor (TipTap) that fix the problems people keep reporting in Filament's GitHub Help:

Plugin Fixes
PasteCleanPlugin Pasting from Word / Google Docs drags in colours, fonts, mso-* junk and <span style> soup.
CustomAttributesPlugin class, id, style and data-* written in the source view are silently stripped, in the browser and on the server.
EmbedPlugin <iframe> / video embeds are removed by the schema and the sanitizer.
ImageUrlPlugin No way to insert an image that lives on another site.
StickyToolbarPlugin The toolbar scrolls away on long content (#17391, #16919, #11685).

Each plugin works alone; take only what you need.

Screenshots

Word HTML pasted and cleaned, structure kept

The Embed dialog accepting a YouTube link

The toolbar stays visible while scrolling a long document

Requirements

Installation

filament:assets publishes the compiled editor modules. They are loadedOnRequest(): no <script> is printed on a page without a rich editor, the editor imports them by URL.

Optionally publish the config and the translations:

Usage

A toolbar button is shown only when it is listed in toolbarButtons() (cleanFormat, embed, imageUrl); an unknown name makes Filament throw, so list only the plugins you installed.

PasteCleanPlugin

On Ctrl+V the structure stays (paragraphs, headings, lists, tables, links, bold/italic/underline) and colours, font sizes, backgrounds and every class/id/style they carry disappear. A pasted link keeps its href only for http(s):, mailto: and tel:; relative paths and #anchors (Word's #_Toc…, local file paths) become plain text. A paste from inside an editor is never touched (the data-pm-slice cutoff), so it composes with CustomAttributesPlugin. The marker is ProseMirror's, not the toolkit's: a paste copied from any ProseMirror/TipTap-based app (Confluence, GitLab, another CMS) skips the cleanup too and keeps its class/style.

The cleanFormat button runs the same cleanup on the selected fragment of existing content. Unlike Filament's clearFormatting it keeps headings and lists (that one runs clearNodes().unsetAllMarks()). What the editor itself put there survives untouched: custom blocks, embeds (<iframe>), images (also ones inserted by URL or stored on another host), code blocks, mentions and merge tags, grid, details and the lead paragraph. Every link stays too (relative paths, #anchors, tel:, and a link's target/rel), except the script schemes javascript:, vbscript:, data: and file:. The result goes back like a paste, so a few words picked out of a paragraph stay in it, and a table cell selection is left alone. A prefix you list is kept whatever its scheme:

Images pasted from Word and Google Docs are removed (Filament uploads only data: images from the clipboard); add them through the upload button.

CustomAttributesPlugin

Keeps class, id, style and further attributes you list, on paragraphs, headings, lists, tables, images, links, details, grid, spans and generic <div> containers. A name the node declares itself belongs to the node and wins: an <img> keeps class and style but not id (Filament's image node owns id as its media key, stored as data-id), and an extra name such as title is not kept on a node that has its own title (image, iframe). It also stops legacy markup from collapsing: <div class="row"><img> <span>…</span></div> keeps its direct children, and <li><div>…</div></li> stays a list item. A <div> that wraps an <iframe> (a responsive embed wrapper) keeps it inside. A style/class that another extension writes itself is dropped only on its own tag (text-align on paragraphs and headings, width/height on images, lead and the grid classes on div); on a <td>, <table>, <iframe> or <p class="lead"> it is yours and stays.

The list is explicit because Symfony's HTML sanitizer, which Filament runs over every rendered rich text, cannot allow data-* as a pattern. on* handlers, URL attributes (href, src, srcset, srcdoc, action, formaction, ping, poster, ...), is, any name with : and framework directives (x-*, hx-*, v-*, ng-*, wire:*) are never accepted: the panel runs Alpine over the editor, so an allowed x-init would be stored XSS against every admin. That list is a backstop, not a whitelist; allow only what you need (data-*, aria-*, role, title).

->attributes([...]) / ->types([...]) on a plugin instance replace the config for that field only. A front-end request never builds the form, so pass the same lists to the renderer, or the values are saved and dropped on the page:

EmbedPlugin

The "Embed" button takes a YouTube / Vimeo link (including youtu.be, Shorts, timecodes) or an https address from your allow-list, and inserts a bare <iframe>. A video link is rebuilt from provider and id (youtube-nocookie.com, no autoplay; an unlisted Vimeo video keeps its privacy hash), never copied. Pasted or hand-written iframes pass the same check at once in the browser and when the HTML is parsed on the server; an iframe from any other host does not exist as a node and is dropped. The check runs again when a node is rendered, so JSON content (RichEditor::json(), an array handed to the renderer) cannot smuggle one in either. The same goes for the admin editor: an iframe node whose src fails the list is drawn as an inert placeholder, and the configured sandbox, allow and referrerpolicy are forced there too. YouTube's own embed code (www.youtube.com/embed/ID) and watch?v= / youtu.be / vimeo.com iframes are rebuilt to the youtube-nocookie.com / player.vimeo.com form rather than dropped. A host/path entry matches on a segment boundary (the host is case-insensitive, the path is not), and a path with dot segments (/maps/embed/../../url), %2e, %2f or a backslash is refused.

sandbox, allow, referrerpolicy and loading="lazy" are forced onto every embed on render, whatever the stored HTML says.

ImageUrlPlugin

Inserts an <img> that is loaded from the other site, not copied. Only absolute http(s) URLs are accepted; ImageUrlPlugin::make()->hosts(['cdn.example.com']) restricts what the dialog accepts. It is not a content filter: an <img> typed in the source view or pasted is not checked against it. http:// is accepted (mixed content on an https site).

StickyToolbarPlugin

A panel plugin, CSS only:

Filament 5 has RichEditor::stickyToolbar() per field; this makes it the default for every editor and fixes the case where it silently does nothing, because a section, tab or repeater item clips with overflow: hidden (which turns it into a scroll container that position: sticky cannot escape). Those containers are switched to overflow: clip. Run php artisan filament:assets so the stylesheet is published.

Offset precedence: a field's own ->stickyOffset(), then the plugin's offset(), then Filament's own default (the topbar, or inside a modal the height of its sticky header); the plugin offset does not apply inside a modal.

Opt a single field out with RichEditor::make('body')->withoutStickyToolbar() (it sets data-toolkit-sticky="off", which the stylesheet respects, even over Filament's native ->stickyToolbar()).

Rendering on the front end

RichContentRenderer parses the stored HTML with the same tiptap-php schema and then sanitizes it, and both steps drop what they do not know. Use the helper:

or attach the plugins to a renderer you build yourself and render it through the toolkit:

This adds CustomAttributesPlugin and EmbedPlugin and sanitizes with the toolkit's own sanitizer: a copy of Filament's config plus your attribute allow-list and, when EmbedPlugin is attached, <iframe> whose src passes the embed allow-list. Filament's shared sanitizer is never changed, so TextColumn::html(), TextEntry::html(), notifications and the Markdown editor keep Filament's defaults. A renderer's own toHtml() uses that shared sanitizer, which is why RichEditorToolkit::toHtml($renderer) is needed (the same goes for HasRichContent models: RichEditorToolkit::toHtml($post->getRichContentAttribute('body')->getRenderer())). Do not add PasteCleanPlugin to the renderer: the cleanup happens once, at paste time.

Configuration

See config/rich-editor-toolkit.php: attributes, types, embed, paste_clean, sticky_toolbar.

Gotchas

Translations

English, Ukrainian, German, Spanish, French, Italian, Dutch, Polish, Brazilian Portuguese and Turkish. The namespace is rich-editor-toolkit::.

AI agents

Laravel Boost guidelines ship in resources/boost/guidelines/core.blade.php.

Testing

Changelog and license

CHANGELOG · MIT license


All versions of filament-rich-editor-toolkit with dependencies

PHP Build Version
Package Version
Requires php Version ^8.3
filament/filament Version ^5.0
illuminate/contracts Version ^12.0|^13.0
spatie/laravel-package-tools Version ^1.16
symfony/html-sanitizer Version ^7.0|^8.0
ueberdosis/tiptap-php Version ^2.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package asignua/filament-rich-editor-toolkit contains the following files

Loading the files please wait ...