feat: use xpier media library for uploads and markdown embeds
Build and Deploy / verify (push) Successful in 35s
Build and Deploy / deploy (push) Successful in 33s

Store media:ID in article bodies instead of CDN URLs, and keep sablog attach tokens as a fallback.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
gouki
2026-09-16 19:03:52 +00:00
co-authored by Cursor
parent 0b0110a681
commit 64655ced1e
49 changed files with 5615 additions and 2132 deletions
@@ -5,15 +5,22 @@ declare(strict_types=1);
namespace App\Filament\Resources\Articles\Schemas;
use App\Domain\Blog\ContentFormat;
use App\Domain\Media\MarkdownMediaEmbed;
use App\Domain\Plugin\Hook;
use App\Settings\GeneralSettings;
use Filament\Actions\Action;
use Filament\Forms\Components\DateTimePicker;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Notifications\Notification;
use Filament\Schemas\Components\Actions;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Components\Utilities\Set;
use Filament\Schemas\Schema;
use Xpier\FilamentMediaLibrary\Components\MediaPicker;
use Xpier\FilamentMediaLibrary\Models\MediaLibrary;
class ArticleForm
{
@@ -57,6 +64,37 @@ class ArticleForm
->required()
->rows(18)
->columnSpanFull(),
MediaPicker::make('insert_media_id')
->label(__('admin.fields.insert_media'))
->module('articles')
->mediaType(null)
->dehydrated(false)
->helperText(__('admin.helpers.insert_media'))
->columnSpanFull(),
Actions::make([
Action::make('insertSelectedMedia')
->label(__('admin.actions.insert_media_into_content'))
->action(function (Get $get, Set $set): void {
$mediaId = $get('insert_media_id');
$media = is_numeric($mediaId)
? MediaLibrary::query()->find((int) $mediaId)
: null;
if (! $media instanceof MediaLibrary) {
Notification::make()->title(__('admin.notifications.pick_media_first'))->warning()->send();
return;
}
$snippet = app(MarkdownMediaEmbed::class)->snippet(
$media,
(string) ($get('content_format') ?: ContentFormat::MARKDOWN)
);
$set('content', rtrim((string) $get('content'))."\n\n".$snippet."\n");
$set('insert_media_id', null);
Notification::make()->title(__('admin.notifications.media_inserted'))->success()->send();
}),
])->columnSpanFull(),
TextInput::make('description')
->label(__('admin.fields.description')),
TextInput::make('keywords')
@@ -82,6 +120,12 @@ class ArticleForm
->label(__('admin.fields.cover_path'))
->helperText(__('admin.helpers.cover_path'))
->columnSpanFull(),
MediaPicker::make('cover_media_id')
->label(__('admin.fields.cover_media'))
->module('articles')
->mediaType('image')
->relationship('coverMedia')
->columnSpanFull(),
TextInput::make('cover_source')
->label(__('admin.fields.cover_source'))
->disabled()