文档网站

nbdev 如何为你的项目生成文档网站。

概念

源文件

在 nbdev 中,你可以通过两种媒介来撰写文档

  1. Jupyter Notebooks
  2. Quarto Markdown (.qmd)

大多数情况下,你会使用 Jupyter Notebooks。但是,如果特定页面上没有代码,你可以选择使用 Quarto Markdown 来撰写文档。如果不确定,我们建议使用 notebooks,因为它们更通用。

对于 notebooks,nbdev 会对其进行预处理,在传递给 Quarto 之前添加、删除或更改内容。在某些情况下,nbdev 甚至会执行某些单元格,以便正确渲染文档。其机制将在下面的 Notebook 处理器 部分讨论。

对于 markdown 文件,Quarto 直接渲染它们。

Notebook 处理器

Nbdev 会根据以下内容对 notebooks 进行特殊预处理

  1. 指令(Directives):指令是特殊的注释,允许你对单元格执行操作。例如,注释 #|hide 允许你隐藏单元格的输入和输出。你可以在此页面上阅读有关指令的更多信息。nbdev 特有且 Quarto 不支持的指令会在传递给 Quarto 之前从 notebook 中移除。
  2. Front Matter:Front matter 允许你指定文档级别的选项,这样就不必在每个单元格中重复设置。(类似地,_quarto.yml 允许你指定项目级别的选项。)你可以在此处阅读有关 Quarto front-matter 的更多信息。

指令和 front-matter 由一个处理管道(Processing Pipeline)用于转换 notebooks。许多预处理步骤定义在 nbdev.processors 中,然后由 nbdev.process.NBProcessor 运行。其中一些预处理步骤涉及运行代码(使用 execnb),以便动态渲染 API 文档。这个过程在下面的 show_doc 的工作原理 部分进行解释。

生成文档网站时,这些预处理后的 notebooks 和其他 quarto 项目文件的中间输出将保存在 repo 根目录下一个名为 _proc/ 的目录中。你可以检查 _proc/ 目录,以便调试或理解 notebooks 是如何预处理的。

Quarto

Quarto 是 nbdev 用于从 notebooks 生成网页的机制。访问Quarto 文档并了解其工作原理会很有帮助。nbdev 会自动为你生成 Quarto 配置文件 _quarto.ymlsidebar.yml

你可以通过定义 custom.yml 文件来覆盖 _quarto.yml 中的任何设置。这将在自定义 Quarto 部分进一步解释。我们将在自定义侧边栏 部分解释如何自定义侧边栏。

静态网站

Quarto 内置了一个静态网站生成器,它可以生成 HTML、Javascript 和 CSS 文件。这些文件将放置在你项目的 settings.ini 文件中指定的 doc_path 目录中,默认为 _docs/。此目录是静态网站文件所在的位置。

概述

下图是这些概念如何协同工作的示意图。

自定义 Quarto

你可以在与 _quarto.yml 文件相同的位置创建一个 custom.yml 文件来覆盖 _quarto.yml 中的任何值。例如,假设你的 _quarto.yml 文件包含以下内容

website:
  title: "nbdev"
  site-url: "https://nbdev.fastai.net.cn/"
  description: "Create delightful software with Jupyter Notebooks"
  twitter-card: true
  open-graph: true
  repo-branch: master
  repo-url: "https://github.com/fastai/nbdev"
  repo-actions: [issue]
  navbar:
    background: primary
    search: true
    right:
      - icon: github
        href: "https://github.com/fastai/nbdev"
  sidebar:
    style: "floating"

假设你想自定义你的侧边栏导航选项,例如将 sidebar.style 的“floating”改为“docked”,使你的导航栏“停靠”。此外,假设你想使用上面配置中没有的 sidebar.background 字段设置不同的背景颜色。

为了完成这些任务,你可以在与 _quarto.yml 相同的位置创建一个包含以下内容的 custom.yml 文件

website:
  sidebar:
      style: "docked"
      background: "dark"
注意

如果你想直接编辑 _quarto.yml 而不是在 custom.yml 中覆盖设置,你也可以在 settings.ini 中设置 custom_quarto_yml = True

自定义侧边栏

默认情况下,nbdev 会自动生成 sidebar.yml,该文件指定了侧边栏的树状结构。nbdev 通过检查包含源文件的目录结构来推断树状结构。你可以通过查看 nbdev 中的 notebooks 目录的文件夹结构以及本网站相应的左侧边栏来查看示例。文件名和目录中的前导数字在命名侧边栏元素时会被忽略(你可以在本项目的 notebooks 目录中看到示例)。

要自定义侧边栏,你必须在 settings.ini 中设置 custom_sidebar = true。这将阻止 nbdev 在每次重新构建文档时重新生成此文件。这样,你就可以直接编辑此文件,而不是使用 custom.yml 覆盖侧边栏。

使用 _brand.yml 进行多格式品牌化

Quarto 支持 _brand.yml,这是一个单独的 YAML 文件,可用于跨格式标准化文档的外观。

要使用此规范,你可以在与 _quarto.yml 相同的位置创建一个包含以下内容的 brand.yml 文件

color:
  palette:
    dark-grey: "#222222"
    blue: "#ddeaf1"
  background: blue
  foreground: dark-grey
  primary: black

logo: 
  small: favicon.png

typography:
  fonts:
    - family: Jura
      source: google
  base: Jura
  headings: Jura

然后,此文件将改变文档的外观,跨格式包含文件中指定的字体、颜色和标志。

show_doc 的工作原理

构建文档网站时,所有导出到源代码的函数和类都将使用 show_doc 自动生成文档。此函数会输出符号的摘要,显示其签名、文档字符串和参数。例如,如果你有此函数

def say_gday(
    greeting:str="G'day",  # Greeting to use
    strine:bool=True,      # Use incomprehensible Aussie accent?
    dropbears:bool=False): # Also warn about drop-bears?
    "Says g'day, the classic Aussie greeting"
    ...

这是它在文档中渲染的方式,通过自动生成一个包含以下内容的临时单元格

show_doc(say_gday)

say_gday

 say_gday (greeting:str="G'day", strine:bool=True, dropbears:bool=False)

说 g'day,经典的澳洲问候语

类型 默认值 详细信息
greeting str G’day 要使用的问候语
strine bool True 使用难以理解的澳洲口音?
dropbears bool False 还要警告关于 drop-bears 的信息吗?

因为这会在你每次构建文档时自动完成(包括持续集成自动完成),所以你的文档将始终包含有关代码的最新信息。

你还可以使用导入的代码通过 show_doc 为未在 notebook 中创建的代码生成文档。例如,如果我们想为 release_conda 生成文档,我们可以导入它并调用 show_doc(release_conda)

from nbdev.release import release_conda
show_doc(release_conda)

source

release_conda

 release_conda (path:str='conda', do_build:<function bool_arg>=True,
                build_args:str='', skip_upload:<function
                store_true>=False, mambabuild:<function store_true>=False,
                upload_user:str=None)

创建一个准备构建成软件包的 meta.yaml 文件,并可选择构建和上传它

类型 默认值 详细信息
path str conda 创建软件包的路径
do_build bool_arg True 运行 conda build 步骤
build_args str 发送给 conda build 的附加参数(字符串形式)
skip_upload store_true False 跳过 anaconda upload 步骤
mambabuild store_true False 使用 mambabuild(需要 boa
upload_user str None 可选的上传软件包的用户

自动单元格执行

构建文档时,所有手动添加的 show_doc 单元格都会自动运行。nbdev 还会执行所有包含 import 语句的单元格以及所有导出的单元格——这样我们就能确保你的 show_doc 单元格中使用的符号可用。

然而,我们不会执行任何其他单元格。这是因为你不会想为了构建文档而等待整个 notebook 运行完成;例如,你的文档可能演示了训练一个需要几个小时才能完成的模型!

这引出了编写 nbdev notebooks 时的一条重要规则

警告

不要在单个单元格中将 import 语句(或调用 show_doc)与其他代码混合。如果这样做,每次构建文档时,该单元格中的所有代码都将被执行,这可能导致错误(因为并非所有先前的单元格都会被执行)。

相反,将你的 import 放在单独的单元格中,而调用 show_doc 的单元格应只包含那一行代码——即 show_doc 调用本身。

请注意,nbdev 会自动隐藏实际的 show_doc(...) 代码行。因此你的用户只会看到输出。

强制单元格执行

有时你可能希望执行 nbdev 自动执行之外的其他单元格。例如,在我们的开始页面上,我们展示了使用 nbdev_help 自动生成的所有 nbdev 命令列表。我们希望此页面始终包含最新命令和文档列表,因此我们希望它在渲染文档时始终执行。为此,请在单元格顶部添加以下指令

#| exec_doc

另一种方法是,通过将以下内容添加到 notebook 的 frontmatter 中,让 nbdev 在渲染文档时自动执行所有单元格

---
exec_all: true
---

跳过执行

同样,你可以使用以下 front matter 指示 nbdev 在渲染文档时不执行任何单元格

---
skip_showdoc: true
---

或者使用此指令忽略特定单元格的执行

#|eval: false

为什么使用 show_doc

许多 Python 开发者使用 sphinx autodoc 一次性自动文档化整个模块。虽然这可以很好地工作,但我们认为使用 nbdev 的方法对开发者和用户都有巨大好处

nbdev 方法的前提是,你的文档非常重要,值得你花时间仔细思考想向用户展示的每一个内容、将提供的示例、也许添加一些图片来解释更复杂的想法等等。Jupyter 为创建这类文档提供了绝佳的环境。例如,使用 Jupyter 你可以

  • 直接从剪贴板粘贴图片到单元格中
  • 插入代码并执行,将结果显示给用户
  • 创建标题层级来帮助构建页面结构
  • ……还有更多。

使用 show_doc,你可以在页面的任何位置插入库的自动更新的 API 详细信息。这意味着你可以精确决定页面应该是什么样子,以及在哪里提供哪些信息。你不必局限于使用 ASCII 艺术来制作图表,并且可以包含用户将遵循的流程的完整端到端代码演练。

本地预览网站

你可以通过运行 nbdev_preview 随时预览你的文档。在预览模式下,你可以更新 notebooks,更改将在浏览器中(稍有延迟后)反映出来。

使用 GitHub Actions 部署文档

如果你的 nbdev 项目位于 GitHub,我们包含了自动化功能,可以为你将文档网站部署到 GitHub Pages

nbdev 捆绑了一个 工作流文件,用于启用此自动化。无论何时更改 repo 中的任何内容,此工作流都会自动触发。以下 GitHub Actions 工作流将运行以生成文档网站(按此顺序)

  1. Deploy to GitHub Pages:此工作流使用 nbdev 构建文档。这定义在 deploy.yaml 中,并引用了 fastai/workflows/quarto-ghp
  2. pages build and deployment:这是 GitHub 在启用 GitHub Pages 时提供的内部内置工作流。

如果页面构建出现任何问题,你可以随时查看这些工作流的日志。像其他工作流一样,这些日志可以在你的 repo 的 Actions 选项卡中找到

要了解更多关于 GitHub Actions 的信息,请参阅它们的文档

在其他平台部署文档

你可以通过运行命令 nbdev_docs 生成网站的所有静态资产(html、css 等)。运行此命令后,文档网站的所有文件将位于项目 settings.ini 文件中指定的 doc_path 目录中,默认为 _docs/。此目录不会被 Git 跟踪,并被 .gitignore 忽略,但你可以使用这些文件部署到任何你想要的托管平台。

你还可以使用 quarto publish 命令在各种其他平台上渲染你的文档,这在 Quarto 文档的此处进行了讨论。运行命令 nbdev_docs 后,quarto publish 命令必须从 _proc/ 目录的根目录运行,该目录位于你的 repo 根目录。quarto publish 的内置帮助提供了可用目标的好概述

调用 nbdev_proc_nbs 并从 _proc/ 目录发布

要在 nbdev 中使用 quarto publish,你必须运行 nbdev_proc_nbs 命令来预处理你的 notebooks,然后再发布文档。提醒一下,nbdev_proc_nbs 会在你的项目根目录创建一个 _proc/ 目录,Quarto 使用该目录来渲染你的网站。

例如,要将网站发布到 Netlify,你可以在 repo 根目录运行以下命令

nbdev_proc_nbs && cd _proc && quarto publish netlify
!quarto publish -h

  Usage:   quarto publish [provider] [path]
  Version: 1.1.75                          
                                           

  Description:

    Publish a document or project. Available providers include:
                                                               
     - Quarto Pub (quarto-pub)                                 
     - GitHub Pages (gh-pages)                                 
     - RStudio Connect (connect)                               
                                                               
     - Netlify (netlify)                                       
    Accounts are configured interactively during publishing.   
    Manage/remove accounts with: quarto publish accounts       

  Options:

    -h, --help              - Show this help.                                     
    --id          <id>      - Identifier of content to publish                    
    --server      <server>  - Server to publish to                                
    --token       <token>   - Access token for publising provider                 
    --no-render             - Do not render before publishing.                    
    --no-prompt             - Do not prompt to confirm publishing destination     
    --no-browser            - Do not open a browser to the site after publishing  
    --log         <level>   - Path to log file                                    
    --log-level   <level>   - Log level (info, warning, error, critical)          
    --log-format  <format>  - Log format (plain, json-stream)                     
    --quiet                 - Suppress console output.                            

  Commands:

    help  [command]  - Show this help or the help of a sub-command.

  Examples:

    Publish project (prompt for provider):  quarto publish                                                  
    Publish document (prompt for provider): quarto publish document.qmd                                     
    Publish project to Netlify:             quarto publish netlify                                          
    Publish with explicit target:           quarto publish netlify --id DA36416-F950-4647-815C-01A24233E294 
    Publish project to GitHub Pages:        quarto publish gh-pages                                         
    Publish project to RStudio Connect:     quarto publish connect                                          
    Publish with explicit credentials:      quarto publish connect --server example.com --token 01A24233E294
    Publish without confirmation prompt:    quarto publish --no-prompt                                      
    Publish without rendering:              quarto publish --no-render                                      
    Publish without opening browser:        quarto publish --no-browser                                     
    Manage/remove publishing accounts:      quarto publish accounts