feat: Markdown 正文自动 TOC(锚点+折叠目录)+ 社交账号扩充国内平台(B站/小红书/抖音/视频号/公众号/其他)+ 侧边栏社交展示 + JSON-LD sameAs 全平台聚合 + 首页 h1(SEO 语义)
This commit is contained in:
@@ -46,6 +46,43 @@ class PostContentRenderer
|
||||
return app(\App\Blog\Support\PluginManager::class)->applyFilters('post.rendered', $html, $post);
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染并提取目录(TOC)。
|
||||
*
|
||||
* @return array{html: string, toc: array<int, array{id: string, text: string, level: int}>}
|
||||
*/
|
||||
public function renderWithToc(Post $post): array
|
||||
{
|
||||
$html = $this->render($post);
|
||||
|
||||
$toc = [];
|
||||
$index = 0;
|
||||
|
||||
$html = preg_replace_callback(
|
||||
'/<h([2-6])([^>]*)>(.*?)<\/h\1>/is',
|
||||
function (array $m) use (&$toc, &$index): string {
|
||||
$level = (int) $m[1];
|
||||
$attrs = $m[2];
|
||||
$text = trim(strip_tags($m[3]));
|
||||
$id = 'toc-'.(++$index);
|
||||
|
||||
$toc[] = ['id' => $id, 'text' => $text, 'level' => $level];
|
||||
|
||||
// 已存在 id 则保留原 id,否则注入锚点
|
||||
if (preg_match('/id="([^"]+)"/', $attrs, $idMatch)) {
|
||||
$toc[array_key_last($toc)]['id'] = $idMatch[1];
|
||||
|
||||
return $m[0];
|
||||
}
|
||||
|
||||
return '<h'.$level.$attrs.' id="'.$id.'">'.$m[3].'</h'.$level.'>';
|
||||
},
|
||||
$html
|
||||
);
|
||||
|
||||
return ['html' => $html, 'toc' => $toc];
|
||||
}
|
||||
|
||||
public function toHtml(string $markdown): string
|
||||
{
|
||||
return $this->converter->convert($markdown)->getContent();
|
||||
|
||||
Reference in New Issue
Block a user