~sqwishy/python-syntect-meme

ref: 1c91536b python-syntect-meme/examples/furret_code_block.py -rw-r--r-- 2.3 KiB
1c91536bsqwishy 4 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
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>")