Глобальное включение в реструктурированный текст

Я использую reStructuredText для своего блога / веб-сайта и хочу добавить глобальный включаемый файл. У меня есть доступ и я рад изменить файл настроек, который я использую для генерации вывода html, я просто не могу понять синтаксис для:

  1. добавление включаемого файла по умолчанию в анализатор
  2. определение директивы / inline-ролей и т. д. в python с документами в 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

2 ответа

Решение

Я не совсем уверен, понимаю ли я вопрос. Хотите ли вы определить, например, несколько замен в каком-то файле, и они будут доступны во всех ваших других файлах reStructuredText, или вы хотите включить какой-нибудь общий HTML в ваши выходные файлы? Вы можете уточнить свой вопрос?

Если это первое, что вы хотите сделать, вы можете использовать include Директива, как я обрисую в этом ответе.

В качестве альтернативы, если вы хотите, чтобы какой-то общий HTML-код был включен в сгенерированный вывод, попробуйте скопировать и отредактировать template.txt файл, который включен в модуль path/to/docutils/writers/html4css1/, Вы можете включить в этот файл произвольные элементы HTML и изменить макет HTML, сгенерированный Docutils. Ни один из этих методов не требует от вас изменения исходного кода Docuitls, что всегда является преимуществом.

Редактировать: я не думаю, что можно установить флаг для установки включаемого файла с помощью Docuitls. Однако, если вы можете использовать Sphinx, который основан на Docuitls, но имеет множество расширений, то этот пакет имеет настройку rst_prolog который делает именно то, что вам нужно (см. этот ответ). rst_prolog является:

Строка reStructuredText, которая будет включена в начало каждого исходного файла, который читается.

Мне нужно было то же самое: способ, чтобы некоторые глобальные файлы 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)
  • Импортировать плагин (адаптировать PLUGINS в pelicanconf.py)
  • Определите список файлов RST (относительные пути к корню проекта) для включения, установив переменную RST_GLOBAL_INCLUDES в pelicanconf.py

Обратите внимание, что пеликан и документы не предназначены для этого. Не предоставляется ни один сигнал, который обеспечивает чистый доступ к необработанному содержимому исходного файла до начала обработки, а также нет возможности перехватить структуру, считывающую файл "обычным способом" (например, создание подклассов, изменение жестко заданной конфигурации и т. Д.), Этот плагин подклассов внутреннего класса FileInput из RstReader и устанавливает ссылку на класс RstReader.FileInput в подкласс. Также объекты файла Python эмулируются через SourceWrapper, Тем не менее, этот подход работает для меня и не является громоздким в повседневной работе.

Я знаю, что этот вопрос с 2012 года, но я думаю, что этот ответ все еще может быть полезным для других.

Другие вопросы по тегам