spatie/filament-markdown-editor
Filament form field providing a Markdown editor powered by EasyMDE. Supports image uploads with configurable disk/visibility and automatically highlights code blocks. Drop it into your resource forms like any other field.
Installation:
composer require spatie/filament-markdown-editor
Publish the config file (if needed):
php artisan vendor:publish --provider="Spatie\FilamentMarkdownEditor\FilamentMarkdownEditorServiceProvider"
First Use Case: Register the field in a Filament form:
use Spatie\FilamentMarkdownEditor\FilamentMarkdownEditor;
FilamentMarkdownEditor::make('description')
->columnSpanFull()
->required()
->maxLength(5000)
Where to Look First:
config/filament-markdown-editor.php for configuration options (e.g., toolbar buttons, image uploads).Basic Markdown Field:
FilamentMarkdownEditor::make('content')
->label('Article Content')
->placeholder('Write your markdown here...')
Image Uploads:
Configure in config/filament-markdown-editor.php:
'image_upload' => [
'disk' => 'public',
'path' => 'markdown-images',
'allowed_mime_types' => ['image/jpeg', 'image/png', 'image/webp'],
],
Use the uploadImage button in the editor UI.
Code Highlighting:
Automatically enabled via Prism.js (no extra config needed). Customize themes in config/filament-markdown-editor.php:
'code_highlight' => [
'theme' => 'tomorrow-night-eighties',
],
Toolbar Customization: Override default buttons in config:
'toolbar' => [
'bold', 'italic', 'heading', '|',
'quote', 'unordered-list', 'ordered-list', '|',
'link', 'image', 'table', '|',
'preview', 'side-by-side', 'fullscreen', '|',
'guide',
],
Integration with Filament Resources:
Use in create/edit forms:
public static function form(Form $form): Form
{
return $form
->schema([
FilamentMarkdownEditor::make('body')
->rules(['required', 'max:10000']),
]);
}
Preview Mode: Enable side-by-side preview in config:
'preview' => [
'enabled' => true,
'side_by_side' => true,
],
Image Upload Permissions:
Ensure the configured disk (public, s3, etc.) has write permissions. Test uploads manually if failing silently.
Large Markdown Content:
maxLength to avoid database bloat (default: null).columnSpanFull() for better UX with long content.EasyMDE Version Mismatches: The package wraps EasyMDE v2.3.0. Avoid manually including newer versions of EasyMDE in your project to prevent conflicts.
CORS Issues with Image Uploads: If using S3 or external storage, ensure CORS headers are configured for the upload endpoint.
Markdown Parsing Quirks:
html for raw HTML rendering (e.g., <div> tags) if needed:
FilamentMarkdownEditor::make('content')->html()
purifier).Console Logs: Enable EasyMDE debug mode in config:
'debug' => env('MARKDOWN_EDITOR_DEBUG', false),
Check browser console for errors (e.g., failed image uploads).
Stored Markdown: Verify the raw markdown is stored in the database (not HTML). Use:
$model->markdown_field; // Raw markdown
$model->markdown_field->toHtml(); // Rendered HTML
Toolbar Not Showing: Clear Filament cache:
php artisan filament:cache:clear
Custom Image Upload Handler: Override the default upload logic by binding a service provider:
public function boot()
{
FilamentMarkdownEditor::macro('uploadImage', function ($imagePath) {
// Custom logic (e.g., process before saving)
return $this->handleCustomUpload($imagePath);
});
}
Add Custom Buttons: Extend EasyMDE via JavaScript:
document.addEventListener('filament-markdown-editor-initialized', (event) => {
event.detail.editor.addButton({
name: 'custom-button',
action: (editor) => {
editor.save();
alert('Custom action!');
},
className: 'custom-button',
title: 'Custom Button',
});
});
Dynamic Config: Pass config dynamically to the field:
FilamentMarkdownEditor::make('content')
->config([
'toolbar' => ['bold', 'italic'],
'preview' => ['enabled' => false],
]);
Localization: Translate toolbar labels by publishing the language files:
php artisan vendor:publish --tag=filament-markdown-editor-lang
Then override in resources/lang/{locale}/filament-markdown-editor.php.
Lazy Loading: For large forms, defer initialization:
FilamentMarkdownEditor::make('content')
->deferLoading()
Disable Preview for Large Content:
FilamentMarkdownEditor::make('content')
->preview(['enabled' => false])
Optimize Image Uploads:
spatie/laravel-medialibrary for advanced image handling.How can I help you explore Laravel packages today?