8. 博客侧边栏分离与 TOC 目录生成
这是最近一次重构中新增的功能。博客页面不再使用主页的侧边栏,而是加载一套独立的布局:
左侧栏:从"留言板"变为 TOC 目录——自动从正文标题生成,点击可跳转
右侧栏:保留搜索 + 最新文章,去掉更新日志和徽章,新增文章标签和功能按钮(RSS订阅、GitHub源码等)
侧边栏选择逻辑:
# Select sidebars based on page type
if ($PageName -like "blog-*") {
if ($Lang -eq "en") {
$pageLeft = $sidebarLeftBlogEn
$pageRight = $sidebarRightBlogEn
} else {
$pageLeft = $sidebarLeftBlog
$pageRight = $sidebarRightBlog
}
} else {
$pageLeft = $sidebarLeft # 主页保持原样
$pageRight = $sidebarRight
}
TOC 目录的生成是本模块最精巧的部分。它从正文中提取所有 <font size="5" color="#ff66cc"> 标题标签(这正是博客文章中的章节标题格式),然后为每个标题自动分配锚点 ID 并构建目录列表:
$headingPattern = '<font[^>]*size\s*=\s*"5"[^>]*color\s*=\s*"#ff66cc"[^>]*>\s*(.*?)\s*</font>'
$tocMatches = [regex]::Matches($content, $headingPattern)
这里有一个关键的实现技巧:从后往前处理。因为每次在标题前插入 <a name="toc-N"> 锚点时,字符串长度会发生变化,后面所有匹配的索引都会偏移。如果从前向后处理,第一个替换之后的索引就全错了。所以脚本倒序遍历匹配结果,从文档末尾向开头逐个插入锚点:
for ($ti = $tocMatches.Count - 1; $ti -ge 0; $ti--) {
$tocNum = $ti + 1 # 从后往前,编号始终正确
$tm = $tocMatches[$ti]
$anchorId = "toc-$tocNum"
$headingText = $tm.Groups[1].Value
# 在原标题前插入锚点
$replacement = '<a name="' + $anchorId + '"></a>' + $tm.Value
$content = $content.Substring(0, $tm.Index)
+ $replacement
+ $content.Substring($tm.Index + $tm.Length)
# TOC 条目往前插入(因为在倒序遍历)
$tocItem = $tmplTocItem -replace '{{anchor}}', $anchorId
$tocItem = $tocItem -replace '{{text}}', $headingText
$tocItems = $tocItem + $tocItems # 前插
}
$tocHtml = $tmplTocContainer -replace '{{items}}', $tocItems
最终 TOC 通过 <!-- TOC_ITEMS --> 注入左侧栏,渲染为带锚点链接的目录列表[5]。
文章标签注入则简单得多——从内容文件的 <!-- tags: xxx --> 元数据中提取标签列表,生成指向 /tags.html#标签名 的链接,注入到博客右侧栏的 <!-- ARTICLE_TAGS --> 占位符中。
所有的注入(最新文章、语言切换、TOC、文章标签)都同时作用于中英文博客侧边栏,确保两种语言版本的页面都获得完整的功能[6]。
|