mortogo321 / laravel-quill
Laravel package for Quill WYSIWYG editor with full support for Quill 2.x
Fund package maintenance!
mortogo321
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/mortogo321/laravel-quill
Requires
- php: ^8.2
- illuminate/support: ^10.0|^11.0|^12.0
Requires (Dev)
- orchestra/testbench: ^8.0|^9.0|^10.0
- phpunit/phpunit: ^10.0|^11.0
README
A Laravel package for seamless integration with Quill 2.x WYSIWYG editor.
Features
- Full support for Quill 2.x
- Blade components for easy integration
- Image upload handling with storage support
- Delta format conversion utilities
- Content sanitization
- Validation rules
- Configurable toolbar presets
- Dark mode support
- CDN or local assets
Requirements
- PHP 8.2+
- Laravel 10.x, 11.x, or 12.x
Installation
Install the package via Composer:
composer require mortogo321/laravel-quill
Publish the assets and configuration:
# Publish everything php artisan vendor:publish --tag=quill # Or publish individually php artisan vendor:publish --tag=quill-config php artisan vendor:publish --tag=quill-assets php artisan vendor:publish --tag=quill-views
Quick Start
1. Include Assets
Add the styles and scripts to your layout:
<!DOCTYPE html> <html> <head> <!-- Include Quill styles --> @quillStyles </head> <body> <!-- Your content --> <!-- Include Quill scripts (before closing body tag) --> @quillScripts </body> </html>
2. Use the Editor Component
<form method="POST" action="/posts"> @csrf <x-quill-editor name="content" :value="old('content', $post->content ?? '')" placeholder="Write your post content..." /> <button type="submit">Save</button> </form>
3. Display Content
<x-quill-viewer :content="$post->content" />
Configuration
The configuration file is located at config/quill.php. Key options include:
Theme
'theme' => 'snow', // or 'bubble'
CDN Settings
'cdn' => [ 'enabled' => true, 'version' => '2.0.2', ],
Toolbar Presets
Three built-in presets: minimal, basic, full
<x-quill-editor name="content" toolbar="minimal" /> <x-quill-editor name="content" toolbar="basic" /> <x-quill-editor name="content" toolbar="full" />
Custom Toolbar
<x-quill-editor name="content" :toolbar="['bold', 'italic', 'link']" />
Image Uploads
Configure upload settings in config/quill.php:
'uploads' => [ 'enabled' => true, 'disk' => 'public', 'path' => 'quill-uploads', 'max_size' => 2048, // KB 'allowed_types' => ['image/jpeg', 'image/png', 'image/gif', 'image/webp'], ],
Editor Component
Available Props
| Prop | Type | Default | Description |
|---|---|---|---|
name |
string | required | Form input name |
id |
string | auto | Editor element ID |
value |
string | null | Initial content (Delta JSON or HTML) |
placeholder |
string | config | Placeholder text |
theme |
string | 'snow' | Quill theme ('snow' or 'bubble') |
toolbar |
string/array | config | Toolbar preset or custom config |
read-only |
bool | false | Read-only mode |
height |
string | '300px' | Editor height |
required |
bool | false | HTML5 required attribute |
upload-url |
string | auto | Custom upload endpoint |
formats |
array | [] | Allowed formats |
modules |
array | [] | Additional Quill modules |
debug |
bool | false | Enable debug mode |
Examples
Basic Editor:
<x-quill-editor name="content" />
With Initial Content:
<x-quill-editor name="content" :value="$post->content" />
Read-Only:
<x-quill-editor name="content" :value="$content" read-only />
Custom Height:
<x-quill-editor name="content" height="500px" />
Bubble Theme:
<x-quill-editor name="content" theme="bubble" />
Viewer Component
Available Props
| Prop | Type | Default | Description |
|---|---|---|---|
content |
string | null | Content (Delta JSON or HTML) |
delta |
array | null | Delta object directly |
sanitize |
bool | true | Sanitize HTML output |
class |
string | null | Additional CSS classes |
Examples
Display Delta Content:
<x-quill-viewer :content="$post->content" />
Display with Custom Class:
<x-quill-viewer :content="$post->content" class="prose lg:prose-xl" />
Without Sanitization:
<x-quill-viewer :content="$post->content" :sanitize="false" />
Validation Rules
QuillContent
Validate Quill content with length constraints:
use Mortogo321\LaravelQuill\Rules\QuillContent; $request->validate([ 'content' => ['required', new QuillContent(minLength: 10, maxLength: 5000)], ]); // Using static methods $request->validate([ 'content' => [QuillContent::required()], 'summary' => [QuillContent::max(500)], 'bio' => [QuillContent::between(50, 1000)], ]);
QuillDelta
Validate Delta structure and allowed formats:
use Mortogo321\LaravelQuill\Rules\QuillDelta; $request->validate([ 'content' => [new QuillDelta()], ]); // Restrict formats $request->validate([ 'content' => [QuillDelta::onlyFormats(['bold', 'italic', 'link'])], ]); // Disallow media $request->validate([ 'content' => [QuillDelta::withoutImages()], 'comment' => [QuillDelta::plainTextOnly()], ]);
Facade Methods
The Quill facade provides utility methods:
use Mortogo321\LaravelQuill\Facades\Quill; // Convert Delta to HTML $html = Quill::deltaToHtml($deltaJson); // Convert HTML to Delta $delta = Quill::htmlToDelta($html); // Sanitize HTML $clean = Quill::sanitize($html); // Get configuration $config = Quill::getConfig('theme');
JavaScript API
The LaravelQuill object is available globally:
// Initialize all editors LaravelQuill.init(); // Get an editor instance const quill = LaravelQuill.getEditor('quill-content'); // Get content const delta = LaravelQuill.getContents('quill-content'); const html = LaravelQuill.getHTML('quill-content'); // Set content LaravelQuill.setContents('quill-content', delta); LaravelQuill.setContents('quill-content', '<p>HTML content</p>'); // Enable/disable LaravelQuill.setEnabled('quill-content', false); // Focus/blur LaravelQuill.focus('quill-content'); LaravelQuill.blur('quill-content');
Events
document.getElementById('quill-content').addEventListener('quill-init', (e) => { console.log('Editor initialized', e.detail.quill); }); document.getElementById('quill-content').addEventListener('quill-change', (e) => { console.log('Content changed', e.detail.delta, e.detail.html); });
Customization
Custom Upload Handler
Override the upload endpoint:
<x-quill-editor name="content" upload-url="{{ route('custom.upload') }}" />
Custom Styling
Publish the CSS and modify public/vendor/quill/css/laravel-quill.css, or use CSS variables:
.quill-editor-wrapper { --quill-editor-height: 400px; --quill-border-color: #e2e8f0; --quill-border-radius: 8px; --quill-focus-color: #3b82f6; --quill-toolbar-bg: #f8fafc; }
Environment Variables
QUILL_THEME=snow QUILL_CDN_ENABLED=true QUILL_VERSION=2.0.2 QUILL_UPLOAD_DISK=public QUILL_UPLOAD_PATH=quill-uploads QUILL_MAX_UPLOAD_SIZE=2048
Security
The package includes built-in content sanitization. Configure allowed tags and attributes in config/quill.php:
'sanitize' => [ 'enabled' => true, 'allowed_tags' => ['p', 'br', 'strong', 'em', ...], 'allowed_attributes' => [ 'a' => ['href', 'target', 'rel'], 'img' => ['src', 'alt', 'width', 'height', 'class'], // ... ], ],
License
MIT License. See LICENSE for more information.