feat: restore sablog browse modes and clean imported HTML
Build and Deploy / verify (push) Successful in 40s
Build and Deploy / deploy (push) Successful in 36s

Keep the public site readable after import (nbsp, highlighter, wrapping code, compact pager) and finish the admin extras already in this tree: sticky levels, preview, page cache, and live llms.txt.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
gouki
2026-09-18 21:33:02 +00:00
co-authored by Cursor
parent 469160dc3f
commit ae47447062
98 changed files with 8618 additions and 901 deletions
+15 -6
View File
@@ -2,17 +2,15 @@
declare(strict_types=1);
namespace App\Blog\Controllers;
use App\Blog\Services\PostContentRenderer;
use App\Models\Post;
use Illuminate\Pagination\Paginator;
class PostController extends Controller
{
public function __construct(private PostContentRenderer $renderer)
{
}
public function __construct(private PostContentRenderer $renderer) {}
public function show(string $id, ?string $page = null)
{
@@ -21,13 +19,16 @@ class PostController extends Controller
->orWhere('slug', $id)
->first();
abort_unless($post && $post->status === 'published', 404);
abort_unless($post, 404);
$canPreview = $this->canPreviewUnpublished();
abort_unless($post->status === 'published' || $canPreview, 404);
$this->ensureReadable($post);
// sablog 式 /show-{id}-{page}.shtml 的评论分页
if ($page !== null) {
\Illuminate\Pagination\Paginator::currentPageResolver(fn () => max(1, (int) $page));
Paginator::currentPageResolver(fn () => max(1, (int) $page));
}
// 浏览量由 /track-view 端点统计(页面整页缓存下控制器不执行,避免双计)
@@ -44,9 +45,17 @@ class PostController extends Controller
'comments' => $comments,
'contentHtml' => $rendered['html'],
'toc' => $rendered['toc'],
'isPreview' => $post->status !== 'published' && $canPreview,
]);
}
private function canPreviewUnpublished(): bool
{
$user = auth()->user();
return $user && ($user->isAdmin() || $user->hasRole('editor'));
}
private function ensureReadable(Post $post): void
{
if (! $post->read_password) {