如何在Bookdown中向目录添加任意自定义内容?
实现方案
你可以通过条件渲染分别适配PDF和HTML输出,不需要修改bookdown底层逻辑,即可实现自定义内容进双端目录的需求,步骤如下:
步骤1:定义跨输出的目录注入函数
在你bookdown项目的全局setup代码块中加入以下R函数:
add_custom_toc_item <- function(toc_text, toc_level = 2, anchor_id = NULL) { # 自动生成锚点ID如果未指定 if (is.null(anchor_id)) { anchor_id <- gsub("[^a-zA-Z0-9]+", "-", tolower(toc_text)) } # PDF输出:用LaTeX原生命令加目录项 if (knitr::is_latex_output()) { tex_level <- c("chapter", "section", "subsection", "subsubsection")[toc_level] return(knitr::asis_output( sprintf("\\addcontentsline{toc}{%s}{\\protect\\hyperlink{%s}{%s}}", tex_level, anchor_id, toc_text) )) } # HTML输出:加标记锚点,后续用JS注入侧边目录 if (knitr::is_html_output()) { return(knitr::asis_output( sprintf('<span class="custom-toc-anchor" id="%s" data-toc-text="%s" data-toc-level="%s"></span>', anchor_id, toc_text, toc_level) )) } }
步骤2:添加HTML端注入逻辑
在你的HTML输出引用的JS脚本(可以单独存为toc.js放在项目根目录,然后在_output.yml的bookdown::gitbook配置下添加includes: in_header: toc.js)中加入以下代码:
document.addEventListener("DOMContentLoaded", function() { // 找到侧边目录容器 const tocContainer = document.querySelector("#TOC"); if (!tocContainer) return; // 遍历所有自定义目录锚点 document.querySelectorAll(".custom-toc-anchor").forEach(anchor => { const tocText = anchor.dataset.tocText; const tocLevel = parseInt(anchor.dataset.tocLevel); const anchorId = anchor.id; // 生成目录项元素 const tocItem = document.createElement("li"); tocItem.classList.add(`toc-level-${tocLevel}`); const tocLink = document.createElement("a"); tocLink.href = `#${anchorId}`; tocLink.textContent = tocText; tocItem.appendChild(tocLink); // 插入到目录对应层级位置 const parentLevel = tocLevel - 1; const lastParentItem = document.querySelector(`#TOC .toc-level-${parentLevel}:last-child`); if (lastParentItem) { let subList = lastParentItem.querySelector("ul"); if (!subList) { subList = document.createElement("ul"); lastParentItem.appendChild(subList); } subList.appendChild(tocItem); } else { tocContainer.appendChild(tocItem); } }); });
步骤3:在自定义块中使用
你直接在需要加目录的自定义div中调用上面的函数即可,示例如下:
::: {.colored-box #arbitrary-header} `r add_custom_toc_item("Figures and tables with captions will be placed in `figure` and `table` environments, respectively.", toc_level = 2, anchor_id = "arbitrary-header")` Figures and tables with captions will be placed in `figure` and `table` environments, respectively. 你可以在这里放任意其他内容,整个块都会应用你定义的彩色框样式。 :::
步骤4:添加自定义块样式
你可以分别给HTML和PDF输出定义彩色框样式:
- HTML端:在引用的CSS文件中添加
.colored-box的样式规则,设置背景色、边框、内边距等 - PDF端:在LaTeX前置文件(
preamble.tex)中用tcolorbox包定义对应环境,渲染自定义div为彩色框
内容的提问来源于stack exchange,提问作者duckmayr
相关产品推荐
相关产品推荐

