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>
86 lines
2.6 KiB
PHP
86 lines
2.6 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
|
||
use App\Blog\Support\ThemeManager;
|
||
|
||
if (! function_exists('theme_view')) {
|
||
/**
|
||
* 渲染主题视图:激活主题目录已前置到全局视图路径,主题缺失时自动回退默认视图。
|
||
*/
|
||
function theme_view(string $view, array $data = []): \Illuminate\Contracts\View\View
|
||
{
|
||
return view($view, $data);
|
||
}
|
||
}
|
||
|
||
if (! function_exists('theme')) {
|
||
/**
|
||
* 主题辅助函数:theme() / theme('asset', 'style.css') / theme('var', 'key', default)
|
||
*/
|
||
function theme(?string $method = null, ...$args): mixed
|
||
{
|
||
$manager = app(ThemeManager::class);
|
||
|
||
return match ($method) {
|
||
'asset' => $manager->assetUrl($args[0] ?? '', $args[1] ?? null),
|
||
'var' => $manager->variable($args[0] ?? '', $args[1] ?? null),
|
||
'vars' => $manager->variables(),
|
||
'name' => $manager->active(),
|
||
default => $manager,
|
||
};
|
||
}
|
||
}
|
||
|
||
if (! function_exists('blog_paginate')) {
|
||
/**
|
||
* Front-end pager: fewer page chips so the sidebar column does not wrap under.
|
||
*/
|
||
function blog_paginate(\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Relations\Relation $query, ?int $perPage = null): \Illuminate\Contracts\Pagination\LengthAwarePaginator
|
||
{
|
||
$perPage = max(1, (int) ($perPage ?? blog_setting('per_page', config('blog.per_page'))));
|
||
|
||
return $query->paginate($perPage)->onEachSide(1)->withQueryString();
|
||
}
|
||
}
|
||
|
||
if (! function_exists('blog_setting')) {
|
||
/**
|
||
* 读取博客设置(Setting 表,带缓存)。
|
||
*/
|
||
function blog_setting(string $key, mixed $default = null): mixed
|
||
{
|
||
return \App\Models\Setting::get($key, $default);
|
||
}
|
||
}
|
||
|
||
if (! function_exists('tracked_url')) {
|
||
/**
|
||
* 外链追踪钩子:核心视图统一调用,由插件(外链中转)改写为 /go/{hash};
|
||
* 插件停用时原样返回。站内链接等由插件自行判断。
|
||
*/
|
||
function tracked_url(string $url): string
|
||
{
|
||
return app(\App\Blog\Support\PluginManager::class)->applyFilters('link.redirect', $url);
|
||
}
|
||
}
|
||
|
||
if (! function_exists('comment_body')) {
|
||
/**
|
||
* 评论正文:转义 + 自动链接 URL(经 tracked_url 走中转,nofollow)。
|
||
*/
|
||
function comment_body(string $text): string
|
||
{
|
||
$text = e($text);
|
||
|
||
$text = preg_replace_callback(
|
||
'#(https?://[^\s<>"\'()]+)#i',
|
||
fn (array $m) => '<a href="'.e(tracked_url($m[1])).'" target="_blank" rel="nofollow noopener">'.$m[1].'</a>',
|
||
$text
|
||
);
|
||
|
||
return nl2br($text);
|
||
}
|
||
}
|