全局包括重组文本

时间:2012-05-18 00:33:47

标签: python jekyll restructuredtext docutils hyde

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

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

    我尝试阅读源代码和文档,但发现它有点难以理解。我希望我只是错过了一些非常明显的东西,但是我想做类似下面的事情(第一部分就是已经存在的东西 - 你可以看到rest of the file in the jekyll-rst plugin source (links right to it)

    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
    

2 个答案:

答案 0 :(得分:2)

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

如果您要做的是前者,可以使用include指令,我在this answer中概述。

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

编辑:我认为无法使用Docuitls设置标记来设置包含文件。但是,如果您可以使用基于Docuitls但有大量扩展名的Sphinx,那么此软件包的设置rst_prolog可以完全满足您的需求(请参阅this answer)。 rst_prolog是:

  

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

答案 1 :(得分: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的repository
  • 导入插件(在PLUGINS中调整pelicanconf.py
  • 通过在RST_GLOBAL_INCLUDES
  • 中设置变量pelicanconf.py来定义要包含的RST文件列表(项目根目录的相对路径)

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

我知道这个问题是从2012年开始的,但我认为这个答案对其他人来说仍然有用。