You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 05:06:07