From 7336de45cbb5f60e934b65f823d0583b48a6c96b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 6 Jun 2017 20:34:56 +0200 Subject: [PATCH] Ability to override docutils HTML writer/translator. The RstReader class can now use user-specified writer/translator classes instead of the hardcoded ones from docutils. This allows for far easier overriding of the default HTML output -- in the past one would need to override the internal _parse_metadata() and _get_publisher() functions. With hypothetical Html5Writer and Html5FieldBodyTranslator classes, based for example on docutils.writers.html5_polyglot.Writer and docutils.writers.html5_polyglot.HTMLTranslator, a plugin that overrides the default behavior would now look just like this: # (definition of Writer / Translator classes omitted) class Html5RstReader(RstReader): writer_class = Html5Writer field_body_translator_class = Html5FieldBodyTranslator def add_reader(readers): readers.reader_classes['rst'] = Html5RstReader def register(): pelican.signals.readers_init.connect(add_reader) --- pelican/readers.py | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/pelican/readers.py b/pelican/readers.py index 46055962..61126c9c 100644 --- a/pelican/readers.py +++ b/pelican/readers.py @@ -9,7 +9,7 @@ from collections import OrderedDict import docutils import docutils.core import docutils.io -from docutils.writers.html4css1 import HTMLTranslator +from docutils.writers.html4css1 import HTMLTranslator, Writer import six from six.moves.html_parser import HTMLParser @@ -135,12 +135,19 @@ class _FieldBodyTranslator(HTMLTranslator): pass -def render_node_to_html(document, node): - visitor = _FieldBodyTranslator(document) +def render_node_to_html(document, node, field_body_translator_class): + visitor = field_body_translator_class(document) node.walkabout(visitor) return visitor.astext() +class PelicanHTMLWriter(Writer): + + def __init__(self): + Writer.__init__(self) + self.translator_class = PelicanHTMLTranslator + + class PelicanHTMLTranslator(HTMLTranslator): def visit_abbreviation(self, node): @@ -160,11 +167,26 @@ class PelicanHTMLTranslator(HTMLTranslator): class RstReader(BaseReader): - """Reader for reStructuredText files""" + """Reader for reStructuredText files + + By default the output HTML is written using + docutils.writers.html4css1.Writer and translated using a subclass of + docutils.writers.html4css1.HTMLTranslator. If you want to override it with + your own writer/translator (e.g. a HTML5-based one), pass your classes to + these two attributes. Look in the source code for details. + + writer_class Used for writing contents + field_body_translator_class Used for translating metadata such + as article summary + + """ enabled = bool(docutils) file_extensions = ['rst'] + writer_class = PelicanHTMLWriter + field_body_translator_class = _FieldBodyTranslator + class FileInput(docutils.io.FileInput): """Patch docutils.io.FileInput to remove "U" mode in py3. @@ -192,7 +214,9 @@ class RstReader(BaseReader): name_elem, body_elem = element.children name = name_elem.astext() if name in formatted_fields: - value = render_node_to_html(document, body_elem) + value = render_node_to_html( + document, body_elem, + self.field_body_translator_class) else: value = body_elem.astext() elif element.tagname == 'authors': # author list @@ -217,10 +241,10 @@ class RstReader(BaseReader): extra_params.update(user_params) pub = docutils.core.Publisher( + writer=self.writer_class(), source_class=self.FileInput, destination_class=docutils.io.StringOutput) pub.set_components('standalone', 'restructuredtext', 'html') - pub.writer.translator_class = PelicanHTMLTranslator pub.process_programmatic_settings(None, extra_params, None) pub.set_source(source_path=source_path) pub.publish(enable_exit_status=True)