1

我正在为我的博客/网站使用 reStructuredText,并且我想添加一个全局包含文件。我可以访问并很高兴更改用于生成 html 输出的设置文件,但我无法弄清楚其中任何一个的语法:

  1. 将默认包含文件添加到解析器
  2. 在 python 中使用 docutils 在 python 中定义指令/内联角色等

我尝试阅读源代码和文档,但发现它有点难以理解。我希望我只是错过了一些非常明显的事情,但我想做类似以下的事情(第一部分就是已经存在的——你可以在 jekyll-rst 插件中看到文件的其余部分来源(指向它的链接)

import sys
from docutils.core import publish_parts
from optparse import OptionParser
from docutils.frontend import OptionParser as DocutilsOptionParser
from docutils.parsers.rst import Parser

# sets up a writer that is then called to parse rst pages repeatedly
def transform(writer=None, part=None):
    p = OptionParser(add_help_option=False)

    # Collect all the command line options
    docutils_parser = DocutilsOptionParser(components=(writer, Parser()))
    for group in docutils_parser.option_groups:
        p.add_option_group(group.title, None).add_options(group.option_list)

    p.add_option('--part', default=part)

    opts, args = p.parse_args()


# ... more settings, etc

# then I just tell the parser/writer to process specified file X.rst every time
# (or alternately a python file defining more roles...but nicer if in rst)

有没有一种简单的方法可以做到这一点?defaults.rst定义一个文件并每次都加载它会很棒。

编辑:这里有一些我希望能够全局包含的示例(自定义指令也很好,但我可能会在代码中编写这些指令)

.. role:: raw-html(raw)
   :format: html

.. |common-substitution| replace:: apples and orange

.. |another common substitution| replace:: etc
4

2 回答 2

2

我不太确定我是否理解这个问题。例如,您想在某个文件中定义一些替换,并在所有其他 reStructuredText 文件中使用这些替换,还是想在输出文件中包含一些常见的 HTML?你能澄清你的问题吗?

如果您想要的是前者,您可以使用该include指令,正如我在此答案中概述的那样。

或者,如果您希望在生成的输出中包含一些常见的 HTML,请尝试复制和编辑template.txt包含在模块中的文件path/to/docutils/writers/html4css1/。您可以在此文件中包含任意 HTML 元素并修改 Docutils 生成的 HTML 的布局。这些方法都不需要您修改 Docuitls 源代码,这始终是一个优势。

编辑:我认为不可能设置一个标志来使用 Docuitls 设置包含文件。但是,如果您可以使用基于 Docuitls 但具有大量扩展的Sphinxrst_prolog ,那么此软件包的设置正是您需要的(请参阅此答案)。rst_prolog是:

一个 reStructuredText 字符串,将包含在每个读取的源文件的开头。

于 2012-05-18T08:02:03.440 回答
1

我需要完全相同的东西:一种将一些全局 reStructuredText 文件自动导入到每篇 reStructuredText 文章中的方法,而无需每次都手动指定它们。

解决此问题的一种方法是以下插件:

import os
from pelican import signals
from pelican.readers import RstReader


class RstReaderWrapper(RstReader):
      enabled = RstReader.enabled
      file_extensions = ['rst']

      class FileInput(RstReader.FileInput):
          def __init__(self, *args, **kwargs):
              RstReader.FileInput_.__init__(self, *args, **kwargs)
              self.source = RstReaderWrapper.SourceWrapper(self.source)

      # Hook into RstReader
      RstReader.FileInput_ = RstReader.FileInput
      RstReader.FileInput = FileInput

      class SourceWrapper():
          """
              Mimics and wraps the result of a call to `open`
          """
          content_to_prepend = None

          def __init__(self, source):
              self.source = source

          def read(self):
              content = self.source.read()
              if self.content_to_prepend is not None:
                  content = "{}\n{}".format(self.content_to_prepend, content)
              return content

          def close(self):
              self.source.close()


def process_settings(pelicanobj):
      include_files = pelicanobj.settings.get('RST_GLOBAL_INCLUDES', []) or []
      base_path = pelicanobj.settings.get('PATH', ".")

      def read(fn):
          with open(os.path.join(base_path, fn), 'r') as res:
              content = res.read()
              return ".. INLCUSION FROM {}\n{}\n".format(fn, content)

      inclusion = "".join(map(read, include_files)) if include_files else None
      RstReaderWrapper.SourceWrapper.content_to_prepend = inclusion


def register():
signals.initialized.connect(process_settings)

简而言之:

  • 从上面的代码创建一个插件(最好从 GitHub克隆存储库)
  • 导入插件(适配PLUGINSpelicanconf.py
  • 通过将变量设置RST_GLOBAL_INCLUDESpelicanconf.py

请注意,pelican 和 docutils 都不是为了允许这样做而设计的。既没有提供在处理开始之前提供对源文件原始内容的干净访问的信号,也没有可能拦截以“正常方式”读取文件的框架(如子类化、更改硬编码配置等) . 这个插件继承了内部类并设置了子类FileInput类引用。python 文件对象也通过. 不过,这种方法对我有用,在日常工作流程中并不繁琐。RstReaderRstReader.FileInputSourceWrapper

我知道这个问题来自 2012 年,但我认为这个答案仍然对其他人有帮助。

于 2016-06-28T20:15:44.410 回答