Sphinx中的条件toctree

11
我希望能够创建多个文档版本,这些版本在包含的章节上有所不同。为了实现这一目标,我通常会使用only指令或ifconfig扩展。然而,我无法将它们与toctree指令结合使用。
基本上,我想要的是这样的东西:
.. toctree::
   :maxdepth: 2

   intro
   strings
   datatypes
   numeric
   .. only:: university
      complex

有没有一种方法可以做到这一点?


这个答案可能会有帮助:https://dev59.com/43zaa4cB1Zd3GeqPKwgv#22024580 - mzjn
4个回答

7

如果目录存在层级关系,我的先前回答可能会失败,因此我编写了一个简单的toctree-filt指令,它能够根据条目前缀过滤条目。例如,给定一个类似以下的toctree-filt指令:

.. toctree-filt::
   :maxdepth: 1

   user-manual
   :internal:supervisor-api
   :draft:new-feature
   :erik:erik-maths
   api

将排除列表设置为['draft','erik']将会得到如下有效的目录树:

.. toctree-filt::
   :maxdepth: 1

   user-manual
   supervisor-api
   api

请将以下内容添加到您的conf.py文件中:

sys.path.append(os.path.abspath('../sphinx-ext/'))
extensions = ['toctree_filter']
toc_filter_exclude = ['draft','erik']

将以下代码放置在您的/source目录旁边的/sphinx_ext中:

import re
from sphinx.directives.other import TocTree


def setup(app):
    app.add_config_value('toc_filter_exclude', [], 'html')
    app.add_directive('toctree-filt', TocTreeFilt)
    return {'version': '1.0.0'}

class TocTreeFilt(TocTree):
    """
    Directive to notify Sphinx about the hierarchical structure of the docs,
    and to include a table-of-contents like tree in the current document. This
    version filters the entries based on a list of prefixes. We simply filter
    the content of the directive and call the super's version of run. The
    list of exclusions is stored in the **toc_filter_exclusion** list. Any
    table of content entry prefixed by one of these strings will be excluded.
    If `toc_filter_exclusion=['secret','draft']` then all toc entries of the
    form `:secret:ultra-api` or `:draft:new-features` will be excuded from
    the final table of contents. Entries without a prefix are always included.
    """
    hasPat = re.compile('^\s*:(.+):(.+)$')

    # Remove any entries in the content that we dont want and strip
    # out any filter prefixes that we want but obviously don't want the
    # prefix to mess up the file name.
    def filter_entries(self, entries):
        excl = self.state.document.settings.env.config.toc_filter_exclude
        filtered = []
        for e in entries:
            m = self.hasPat.match(e)
            if m != None:
                if not m.groups()[0] in excl:
                    filtered.append(m.groups()[1])
            else:
                filtered.append(e)
        return filtered

    def run(self):
        # Remove all TOC entries that should not be on display
        self.content = self.filter_entries(self.content)
        return super().run()

现在只需将现有的toctree指令更改为toctree-filt,您就可以开始使用了。请注意,Sphinx会报错,因为它会找到未包含在文档中的文件。不确定如何修复此问题。


1
这个答案非常好,我已经点赞了。不过需要注意的是,目录被筛选掉并不意味着被筛选掉的页面不会编译进构建中。我是通过在搜索栏中搜索一些被排除内容中包含的值来偶然发现这一点的,并且我仍然能够找到那些内容。如果你真的想完全排除这些内容,你可以在你排除的文件开头也使用 .. only:: 指令来解决这个问题。 - Kdawg
哦!谢谢你注意到这个问题! - David Weber

4

一个非常简单的解决方案是维护两个不同名称的独立索引文件。您可以在conf.py中指定默认使用哪个索引文件,并通过在sphinx-build命令行上使用-D master_doc=alternate-index来覆盖特殊构建。


3
据我所知,目前没有办法实现您想要的功能。我也曾经遇到过同样的问题,详情请见https://github.com/sphinx-doc/sphinx/issues/1717
原因是Sphinx将toctree节点中的所有行都视为纯文本进行处理。
我看到有两种解决方案:
  1. you can write your own toctree directive;
  2. you can extend the toctree including an option that contains the expression to be evaluated

    .. toctree:
       :condition: expression
    
       file1
    
然后你可以自定义文档树解析事件。
  1. you can use text substitutions on the raw text defining your own tags. you can do that implementing an event handler for the source-read event. For instance $$condition$$ could contain the condition to be evaluated, while $$$ the end of the block, i.e.

    .. toctree:
    
       file1
       $$mycondition$$
       file2
       $$$
    

根据mycondition的不同,您可以删除以下代码块。

第三个选项非常简单,而对我来说第二个选项最为优雅。


3
我的解决方案是将有条件的内容放在一个名为“intern”的独立目录中,并使用标签“internal”。
在conf.py文件中,我添加了以下几行:
if tags.has('internal'):
    exclude_patters = ['_build']
else:
    exclude_patterns = ['_build', 'intern*']

现在,当我在命令行上传递“internal”标志时,我会得到所有内容,否则除了intern目录中的内容之外,其他所有内容都会被包括。
标签“internal”可以与“only”一起使用。
目录包含对intern/somedoc的引用,根据需要包括或跳过它们。我确实收到了一些有关缺少页面的警告,但可以将其消除。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接