| Install | |
|---|---|
composer require pjedesigns/filament-meta-lexical-editor |
|
| Latest Version: | v1.2.0 |
| PHP: | ^8.2 |
A modern, extensible rich-text editor for FilamentPHP built on Meta's Lexical framework.
Install the package via Composer:
composer require pjedesigns/filament-meta-lexical-editor
Publish the configuration file (optional):
php artisan vendor:publish --tag="filament-meta-lexical-editor-config"
Publish Filament assets (if you haven't already):
php artisan filament:assets
Note: The package automatically registers its assets with Filament. Running
filament:assetsis sufficient - no separate asset publishing is required.
Add the editor to your Filament form:
use Pjedesigns\FilamentMetaLexicalEditor\MetaLexicalEditor;
public static function form(Form $form): Form
{
return $form
->schema([
MetaLexicalEditor::make('content'),
]);
}
The simplest way to configure the toolbar:
MetaLexicalEditor::make('content')
->enabledToolbars([
'bold',
'italic',
'underline',
'divider',
'h1',
'h2',
'h3',
'divider',
'bullet',
'numbered',
'divider',
'link',
'image',
]);
For IDE autocompletion support:
use Pjedesigns\FilamentMetaLexicalEditor\Enums\ToolbarItem;
MetaLexicalEditor::make('content')
->enabledToolbars([
ToolbarItem::BOLD,
ToolbarItem::ITALIC,
ToolbarItem::UNDERLINE,
ToolbarItem::DIVIDER,
ToolbarItem::H1,
ToolbarItem::H2,
ToolbarItem::H3,
ToolbarItem::DIVIDER,
ToolbarItem::BULLET,
ToolbarItem::NUMBERED,
ToolbarItem::DIVIDER,
ToolbarItem::LINK,
ToolbarItem::IMAGE,
]);
Quick configurations for common use cases:
// Minimal: bold, italic, underline, link
MetaLexicalEditor::make('content')->preset('minimal');
// Basic: undo/redo, basic formatting, lists, link
MetaLexicalEditor::make('content')->preset('basic');
// Standard: headings, lists, quotes, formatting, alignment
MetaLexicalEditor::make('content')->preset('standard');
// Full: all available toolbar items
MetaLexicalEditor::make('content')->preset('full');
Images are disabled by default for security. Enable them with:
MetaLexicalEditor::make('content')
->hasImages();
Tables are enabled by default. To disable:
MetaLexicalEditor::make('content')
->hasTables(false);
MetaLexicalEditor::make('content')
->hasColumns();
MetaLexicalEditor::make('content')
->hasYouTube();
MetaLexicalEditor::make('content')
->hasTweets();
MetaLexicalEditor::make('content')
->hasCollapsible();
MetaLexicalEditor::make('content')
->hasDate();
Enable YouTube, Tweets, and Collapsible sections at once:
MetaLexicalEditor::make('content')
->hasEmbeds();
MetaLexicalEditor::make('content')
->hasImages()
->hasColumns()
->hasYouTube()
->hasTweets()
->hasCollapsible()
->hasDate();
Configure predefined internal pages for the link editor:
MetaLexicalEditor::make('content')
->internalLinks([
'Home' => '/',
'About Us' => 'about-us',
'Contact' => 'contact',
'Privacy Policy' => 'privacy-policy',
]);
Or with explicit format:
MetaLexicalEditor::make('content')
->internalLinks([
['title' => 'Home', 'slug' => '/'],
['title' => 'About Us', 'slug' => 'about-us'],
], 'https://example.com'); // Optional site URL
By default, the editor automatically cleans up orphaned images when content is saved (images that were uploaded but later removed from the content). To disable:
MetaLexicalEditor::make('content')
->cleanupOrphanedImages(false);
Override the default sanitizer with your own implementation:
MetaLexicalEditor::make('content')
->sanitizeHtmlUsing(function (string $html): string {
// Your custom sanitization logic
return $html;
});
Use the LexicalContentEntry component to display editor content with full support for embedded media (YouTube, Tweets):
use Pjedesigns\FilamentMetaLexicalEditor\Infolists\Components\LexicalContentEntry;
public static function infolist(Infolist $infolist): Infolist
{
return $infolist
->schema([
LexicalContentEntry::make('content')
->hiddenLabel(),
]);
}
Use the SanitizedHtmlColumn component for table views:
use Pjedesigns\FilamentMetaLexicalEditor\Tables\Columns\SanitizedHtmlColumn;
public static function table(Table $table): Table
{
return $table
->columns([
SanitizedHtmlColumn::make('content')
->limit(100),
]);
}
For frontend display, you need to include the frontend CSS and wrap your content:
php artisan vendor:publish --tag="filament-meta-lexical-editor-frontend"
This publishes frontend.css to public/vendor/filament-meta-lexical-editor/frontend.css.
Add this to your frontend layout's <head>:
<link rel="stylesheet" href="{{ asset('vendor/filament-meta-lexical-editor/frontend.css') }}">
Or import it in your Vite build (e.g., in your app.css):
@import '../../vendor/pjedesigns/filament-meta-lexical-editor/resources/css/frontend.css';
Output the content wrapped in a lexical-content div:
<div class="lexical-content">
{!! $post->content !!}
</div>
For Twitter embeds to work on the frontend, include the Twitter widget script:
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
The frontend CSS includes dark mode styles. Add the dark class to a parent element:
<body class="dark">
<div class="lexical-content">
{!! $post->content !!}
</div>
</body>
The configuration file (config/filament-meta-lexical-editor.php) allows you to customize:
// Storage disk for uploaded images
'disk' => env('FILAMENT_META_LEXICAL_EDITOR_DISK'),
// Directory for uploaded images
'directory' => env('FILAMENT_META_LEXICAL_EDITOR_DIR', 'lexical'),
// Maximum file size in KB (default: 5MB)
'max_kb' => env('FILAMENT_META_LEXICAL_EDITOR_MAX_KB', 5120),
// Allowed MIME types
'allowed_mimes' => env('FILAMENT_META_LEXICAL_EDITOR_MIMES', 'jpg,jpeg,png,gif,webp,svg'),
'middleware' => ['web', 'auth'],
'upload_route' => '/filament-meta-lexical-editor/upload-image',
'fonts' => [
'families' => [
'Arial' => 'Arial',
'Courier New' => 'Courier New',
'Georgia' => 'Georgia',
'Times New Roman' => 'Times New Roman',
'Trebuchet MS' => 'Trebuchet MS',
'Verdana' => 'Verdana',
],
'min_size' => 8,
'max_size' => 72,
'default_size' => 15,
],
| String Value | Enum Constant | Description |
|---|---|---|
undo |
UNDO |
Undo last action |
redo |
REDO |
Redo last undone action |
fontFamily |
FONT_FAMILY |
Font family selector |
fontSize |
FONT_SIZE |
Font size controls |
normal |
NORMAL |
Paragraph format |
h1 - h6 |
H1 - H6 |
Heading levels 1-6 |
bold |
BOLD |
Bold text |
italic |
ITALIC |
Italic text |
underline |
UNDERLINE |
Underlined text |
strikethrough |
STRIKETHROUGH |
Strikethrough text |
subscript |
SUBSCRIPT |
Subscript text |
superscript |
SUPERSCRIPT |
Superscript text |
lowercase |
LOWERCASE |
Convert to lowercase |
uppercase |
UPPERCASE |
Convert to uppercase |
capitalize |
CAPITALIZE |
Capitalize words |
bullet |
BULLET |
Bullet list |
numbered |
NUMBERED |
Numbered list |
quote |
QUOTE |
Block quote |
code |
CODE |
Code block |
icode |
ICODE |
Inline code |
link |
LINK |
Insert/edit hyperlink |
textColor |
TEXT_COLOR |
Text color picker |
backgroundColor |
BACKGROUND_COLOR |
Background color picker |
left |
LEFT |
Align left |
center |
CENTER |
Align center |
right |
RIGHT |
Align right |
justify |
JUSTIFY |
Justify text |
start |
START |
Align to start (RTL-aware) |
end |
END |
Align to end (RTL-aware) |
indent |
INDENT |
Increase indentation |
outdent |
OUTDENT |
Decrease indentation |
hr |
HR |
Horizontal rule |
image |
IMAGE |
Image upload |
table |
TABLE |
Insert table |
columns |
COLUMNS |
Column layout |
youtube |
YOUTUBE |
YouTube embed |
tweet |
TWEET |
Twitter/X embed |
collapsible |
COLLAPSIBLE |
Collapsible section |
date |
DATE |
Date picker |
clear |
CLEAR |
Clear formatting |
divider |
DIVIDER |
Visual toolbar separator |
| Action | Windows/Linux | macOS |
|---|---|---|
| Bold | Ctrl+B |
⌘+B |
| Italic | Ctrl+I |
⌘+I |
| Underline | Ctrl+U |
⌘+U |
| Undo | Ctrl+Z |
⌘+Z |
| Redo | Ctrl+Y |
⌘+Shift+Z |
| Insert Link | Ctrl+K |
⌘+K |
| Heading 1-6 | Ctrl+Alt+1-6 |
⌘+Opt+1-6 |
| Paragraph | Ctrl+Alt+0 |
⌘+Opt+0 |
| Bullet List | Ctrl+Alt+7 |
⌘+Opt+7 |
| Numbered List | Ctrl+Alt+8 |
⌘+Opt+8 |
| Quote | Ctrl+Alt+Q |
⌘+Opt+Q |
| Code Block | Ctrl+Alt+C |
⌘+Opt+C |
| Increase Font | Ctrl+Shift+. |
⌘+Shift+. |
| Decrease Font | Ctrl+Shift+, |
⌘+Shift+, |
The package includes robust HTML sanitization to prevent XSS attacks:
<script>, <object>, <embed>, <style>, <form>, etc.onclick, onerror, onload, etc.javascript:, data:, file: protocolshttp://, https://, and relative pathsRun the test suite:
composer test
Please see CHANGELOG for more information on what has changed recently.
Please see CONTRIBUTING for details.
Please review our security policy on how to report security vulnerabilities.
The MIT License (MIT). Please see License File for more information.