import furret
from docutils.parsers.rst import directives, nodes
from docutils.parsers.rst.roles import set_classes
from docutils.parsers.rst.directives.body import CodeBlock
class FurretHighlighter(CodeBlock):
"""
This is incomplete as it ignores some of the CodeBlock options like line numbers.
"""
def run(self):
self.assert_has_content()
language = self.arguments[0] if self.arguments else ""
if language:
syntax = synset.find_syntax_by_token(language)
if syntax is None:
# TODO use docutils to produce a warning somehow
# logger.warning("missing syntax to highlight", language=language)
syntax = synset.find_syntax_plain_text()
else:
syntax = synset.find_syntax_plain_text()
set_classes(self.options)
classes = ["code"]
if language:
classes.append(language)
if "classes" in self.options:
classes.extend(self.options["classes"])
code = "\n".join(self.content)
html = furret.highlight_to_classed_spans(code, synset, syntax)
node = nodes.literal_block("", classes=classes)
self.add_name(node)
node += nodes.raw("", html, format="html")
return [node]
directives.register_directive("code", FurretHighlighter)
if __name__ == "__main__":
import os.path
from docutils.core import Publisher
from docutils.io import StringInput, StringOutput
synset = furret.builtin_syntax_set() # this takes some time
extra_params = {
"input_encoding": "utf-8",
"language_code": "en",
"traceback": True,
}
pub = Publisher(source_class=StringInput, destination_class=StringOutput)
pub.set_components("standalone", "restructuredtext", "html")
pub.process_programmatic_settings(None, extra_params, None)
with open(__file__, "r") as f:
source = "".join(" " + line for line in f.readlines())
rst = f"""This is a code block.
.. code:: python
{source}
That has been a code block!
"""
pub.set_source(rst)
pub.publish()
print(pub.writer.parts["body"])
theme_path = os.path.join(os.path.dirname(__file__), "gruvbox-dark.tmTheme")
theme = furret.load_theme_from_path(theme_path)
print(f"<style>body {{ margin: auto; max-width: 44em; }}\n{theme.css()}</style>")