Sphinx中的条件toctree

时间:2013-02-21 12:07:07

标签: documentation python-sphinx restructuredtext docutils

我想要做多个版本的文档,这些版本在所包含的部分中有所不同。要实现这一点,我通常会使用only指令或ifconfig扩展名。但是,我不能将任何这些与toctree指令结合使用。

我基本上想要的是这样的:

.. toctree::
   :maxdepth: 2

   intro
   strings
   datatypes
   numeric
   .. only:: university
      complex

有办法吗?

4 个答案:

答案 0 :(得分:3)

据我所知,没有办法做你想做的事。我一直在努力解决同样的问题,请参阅https://github.com/sphinx-doc/sphinx/issues/1717

原因是Sphinx将toctree节点中包含的所有行都处理为纯文本。

我看到两种选择:

  1. 你可以编写自己的toctree指令;
  2. 您可以扩展toctree,包括一个包含要评估的表达式的选项

    .. toctree:
       :condition: expression
    
       file1
    
  3. 然后您自定义doctree resolve事件。

    1. 您可以在定义自己的标签的原始文本上使用文本替换。你可以为source-read事件实现一个事件处理程序。例如$$condition$$可以包含要评估的条件,而$$$可以包含块的结尾,即

      .. toctree:
      
         file1
         $$mycondition$$
         file2
         $$$
      
    2. 根据mycondition,您可以删除以下块行。

      3号很简单,而对我来说2号是最优雅的。

答案 1 :(得分:2)

我的解决方案是将条件内容放在一个单独的目录“实习生”中。并使用标签'内部'

在conf.py中我添加了行

if tags.has('internal'):
    exclude_patters = ['_build']
else:
    exclude_patterns = ['_build', 'intern*']

现在当我通过内部'在命令行上标记我得到所有,否则除了实习生目录中的内容之外的所有内容。

标签内部只能与。

结合使用

ToC包含对intern / somedoc的引用,并根据需要包含或跳过它们。 我确实收到了许多关于遗失页面的警告,但这些警告可以保持沉默。

答案 2 :(得分:2)

如果您有目录的层次结构,我的上一个答案将失败,因此我编写了一个简单的toctree-filt指令,该指令能够根据条目的前缀过滤条目。例如,给出toctree-filt指令,如

.. toctree-filt::
   :maxdepth: 1

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

并将排除列表设置为['draft','erik']将导致 有效的toctree看起来像

.. 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']

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

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会发布错误,因为它会找到文档中未包含的文件。不知道如何解决这个问题。

答案 3 :(得分:1)

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