feat: use xpier media library for uploads and markdown embeds

Store media:ID in post 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 f6a9a8ea50
commit f81397a289
38 changed files with 5390 additions and 2059 deletions
+9
View File
@@ -50,6 +50,15 @@ class AdminPagesTest extends TestCase
$this->actingAs($this->admin)->get('/admin/media')->assertOk();
}
public function test_media_library_resource_loads(): void
{
$this->actingAs($this->admin)->get('/admin/media-library')->assertOk();
$this->actingAs($this->admin)->get('/admin/media-folders')->assertOk();
$this->actingAs($this->admin)->get('/admin/posts/create')
->assertOk()
->assertSee('media:ID', false);
}
public function test_plugin_and_payment_pages_load(): void
{
$this->actingAs($this->admin)->get('/admin/plugins')->assertOk();
+113
View File
@@ -0,0 +1,113 @@
<?php
declare(strict_types=1);
namespace Tests\Feature;
use App\Blog\Services\PostContentRenderer;
use App\Models\Post;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
use Xpier\FilamentMediaLibrary\Models\MediaLibrary;
class MarkdownMediaLibraryTest extends TestCase
{
use RefreshDatabase;
public function test_markdown_body_renders_media_protocol_to_image_without_storing_url(): void
{
$media = $this->createLibraryImage(12, 'Hero shot');
$post = Post::query()->create([
'user_id' => User::factory()->create()->id,
'title' => 'Media embed post',
'slug' => 'media-embed-post',
'content' => "Intro\n\n![Hero shot](media:{$media->id})\n",
'content_format' => 'markdown',
'status' => 'published',
'published_at' => now()->subMinute(),
]);
$html = app(PostContentRenderer::class)->render($post);
$this->assertStringContainsString((string) $media->url, $html);
$this->assertStringContainsString('<img', $html);
$this->assertStringNotContainsString('media:'.$media->id, $html);
$this->assertStringContainsString("![Hero shot](media:{$media->id})", (string) $post->fresh()->content);
}
public function test_html_body_hydrates_media_shortcode(): void
{
$media = $this->createLibraryImage(21, 'Inline');
$post = Post::query()->create([
'title' => 'HTML media post',
'content' => '<p>see [media='.$media->id.']</p>',
'content_format' => 'html',
'status' => 'published',
'published_at' => now()->subMinute(),
]);
$html = app(PostContentRenderer::class)->render($post);
$this->assertStringContainsString((string) $media->url, $html);
$this->assertStringNotContainsString('[media='.$media->id.']', $html);
}
public function test_published_post_page_shows_library_image(): void
{
$media = $this->createLibraryImage(33, 'Cover art');
$post = Post::query()->create([
'title' => 'Visible media post',
'slug' => 'visible-media-post',
'content' => "![Cover art](media:{$media->id})",
'content_format' => 'markdown',
'status' => 'published',
'published_at' => now()->subMinute(),
'cover_media_id' => $media->id,
]);
$this->get('/posts/'.$post->slug.'.shtml')
->assertOk()
->assertSee((string) $media->url, false)
->assertDontSee('media:'.$media->id, false);
$this->assertSame((string) $media->url, $post->fresh()->coverImageUrl());
}
public function test_missing_media_reference_does_not_crash_render(): void
{
$post = Post::query()->create([
'title' => 'Broken media post',
'content' => '![gone](media:99999)',
'content_format' => 'markdown',
'status' => 'published',
'published_at' => now()->subMinute(),
]);
$html = app(PostContentRenderer::class)->render($post);
$this->assertIsString($html);
$this->assertStringContainsString('media:99999', $html);
}
private function createLibraryImage(int $id, string $alt): MediaLibrary
{
$media = new MediaLibrary;
$media->forceFill([
'id' => $id,
'disk' => 'public',
'path' => 'media/library/articles/image/test-'.$id.'.jpg',
'original_name' => 'test-'.$id.'.jpg',
'extension' => 'jpg',
'mime_type' => 'image/jpeg',
'size' => 128,
'type' => MediaLibrary::TYPE_IMAGE,
'source' => MediaLibrary::SOURCE_ADMIN,
'folder' => 'articles',
'alt_text' => $alt,
]);
$media->save();
return $media->fresh();
}
}