Download the PHP package degrinthorst/livewire-cms-editor without Composer
On this page you can find all versions of the php package degrinthorst/livewire-cms-editor. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download degrinthorst/livewire-cms-editor
More information about degrinthorst/livewire-cms-editor
Files in degrinthorst/livewire-cms-editor
Package livewire-cms-editor
Short Description A WordPress-classic-style rich text editor for Laravel Livewire, with first-class image insertion and properties, built on TipTap and Spatie MediaLibrary.
License MIT
Informations about the package livewire-cms-editor
Livewire CMS Editor
A WordPress-classic-style rich text editor for Laravel Livewire 4, with first-class image insertion and per-placement image properties (width/height/class/style), built on TipTap and Spatie MediaLibrary.
This is a v0 skeleton. It contains a coherent, opinionated architecture and working-shaped code, but is not yet a published, fully-tested package. See
docs/ARCHITECTURE.mdfor every design decision and the open maintenance risks.
Why
Editors like flux:editor are fine but too thin for clients coming from
WordPress. The missing feature is inserting an image into the body and setting
its display properties. Here that image is a real TipTap node backed by a
MediaLibrary record, so it's reusable across articles via a built-in picker.
Requirements
- PHP 8.2+
- Laravel 11/12, Livewire 4
- Spatie MediaLibrary 11
ueberdosis/tiptap-php(server-side rendering)
Install
The cms-editor:install command publishes the config, optionally publishes the
pre-built assets, asks which model and column(s) hold the content, writes
those choices to your .env, and scaffolds a migration for the column(s). It
never edits your model — it prints the trait/interface/cast you add yourself.
Prefer to do it by hand? The manual equivalents are:
Columns: JSON vs cached HTML (ADR-003)
The package is column-agnostic for the JSON — the editor pushes ProseMirror
JSON through wire:model and your form persists it to your own column. The only
package-managed column is the optional rendered-HTML cache:
When columns.html is set, add the SyncsEditorHtml trait to your model and the
HTML column is re-rendered from the JSON on every save (image src is re-resolved
from MediaLibrary at that moment — a renamed/replaced image refreshes on the
next save).
Front-end — either load the pre-built bundle, or import the source in your app.js.
Pre-built bundle. dist/cms-editor.js is an ES module, so it must be
loaded with type="module" (a plain <script> throws on its export and the
editor never registers). It self-registers on window.Alpine / alpine:init:
(vendor:publish --tag=cms-editor-assets copies both the JS and CSS into
public/vendor/cms-editor.)
Or import the source in your bundled app.js:
Include the base styles (optional): resources/css/cms-editor.css.
Prepare your model
AdoptsEditorMedia makes the model own the images it references on save (so they
cascade-delete with it). It's optional — without it, images stay on the shared
upload bucket (ADR-009). Skip it only if you use upload_binding=model.
Want the cached-HTML column? Also use Degrinthorst\CmsEditor\Concerns\SyncsEditorHtml;
and set CMS_EDITOR_HTML_COLUMN (the install command does both for you).
Set article_model in config/cms-editor.php (or CMS_EDITOR_ARTICLE_MODEL in
.env).
Use it
The same tag works for create and edit: pass the model when you have one,
null when you don't. Uploads on a new article attach to the package upload
bucket and are adopted onto the article on save (ADR-009) — no draft record
needed.
Render the stored document to HTML on the front-end:
How it fits together
| Concern | Where |
|---|---|
| Editor engine | TipTap (resources/js/editor.js) inside wire:ignore |
| Image node | resources/js/extensions/MediaImage.js + src/Extensions/MediaImage.php |
| Media picker | src/Livewire/MediaPicker.php (restrained to model + collection) |
| Storage | ProseMirror JSON, rendered via ContentRenderer |
| Safety | ContentSanitizer allowlist (swap for HTMLPurifier in prod) |
| Livewire sync | one-way bridge, see ADR-006 |
Hardening the sanitizer
The bundled ContentSanitizer is dependency-free and deliberately simple. For
production, bind HTMLPurifier instead:
Distribution & maintenance
The pre-built dist/cms-editor.js is committed to the repo so composer require
works without a Node toolchain (Packagist serves the git-tag archive). Keep it
fresh: run npm run build and commit the result before tagging a release — CI
rebuilds and fails if the committed bundle drifts from the source.
Supply-chain hardening:
package-lock.jsonis committed; CI usesnpm ci(verifies integrity hashes).- Dependabot (
.github/dependabot.yml) updates npm, Composer and GitHub Actions with a 7-day cooldown (cooldown.default-days: 7) — no dependency version younger than a week is adopted (the window in which most malicious releases get caught and yanked). This is native to GitHub; no app to install. - A
renovate.jsonwith the equivalentminimumReleaseAge: "7 days"is included as an alternative. Don't run both at once (duplicate PRs) — pick one; enable the Renovate GitHub app only if you disable Dependabot. .npmrcsave-exactstops caret ranges from silently floating.- CI gates on
npm auditfor production deps, pins GitHub Actions to commit SHAs, and runs with least-privilegecontents: read.
Image properties
Select an inserted image and a contextual panel appears above the editor to set
its per-placement width, height, alignment (none/left/center/right) and a
freeform style (ADR-004). Alignment uses WordPress-familiar classes
(alignleft/aligncenter/alignright) shipped in cms-editor.css; include
those styles on the front-end too. Intrinsic data (alt/caption) is edited in the
picker, not here. The style field is filtered by the render-time allowlist.
Pruning unused images
Editor images that no document references any more — un-inserted bucket uploads and de-referenced host media — are cleaned up by:
Schedule it (e.g. daily with --ttl=7 --force). It scans the configured model's
JSON column for live mediaIds; configure extra sources via prune.sources.
Roadmap
- Livewire 3 compat layer.
- JSON↔HTML render snapshot tests (Onderhoudsrisico #3).
See docs/ARCHITECTURE.md for the full reasoning.
All versions of livewire-cms-editor with dependencies
illuminate/contracts Version ^11.0 || ^12.0 || ^13.0
livewire/livewire Version ^4.0
spatie/laravel-medialibrary Version ^11.0
ueberdosis/tiptap-php Version ^2.1