codesnippetcard.py 2.91 KB
Newer Older
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
"""
Code snippet card, used in index page.
"""

from docutils.parsers.rst import Directive, directives
from docutils.statemachine import StringList
from docutils import nodes

from sphinx.addnodes import pending_xref


CARD_TEMPLATE_HEADER = """
.. raw:: html

    <div class="codesnippet-card admonition">

    <div class="codesnippet-card-body">

    <div class="codesnippet-card-title-container">

    <div class="codesnippet-card-icon">

.. image:: {icon}

.. raw:: html

    </div>

    <h3>{title}</h3>
    </div>

"""

CARD_TEMPLATE_FOOTER = """
.. raw:: html

    </div>
"""

CARD_TEMPLATE_LINK_CONTAINER_HEADER = """
.. raw:: html

    <div class="codesnippet-card-footer">
"""

CARD_TEMPLATE_LINK = """
.. raw:: html

    <div class="codesnippet-card-link">
    For a full tutorial, please go here.
    <span class="material-icons right">arrow_forward</span>
    </div>
"""


class CodeSnippetCardDirective(Directive):
    option_spec = {
        'icon': directives.unchanged,
        'title': directives.unchanged,
        'link': directives.unchanged,
    }

    has_content = True

    def run(self):
        anchor_node = nodes.paragraph()

        try:
            title = self.options['title']
            link = directives.uri(self.options['link'])
            icon = directives.uri(self.options['icon'])
        except ValueError as e:
            print(e)
            raise

        # header, title, icon...
        card_rst = CARD_TEMPLATE_HEADER.format(title=title, icon=icon)
        card_list = StringList(card_rst.split('\n'))
        self.state.nested_parse(card_list, self.content_offset, anchor_node)

        # code snippet
        self.state.nested_parse(self.content, self.content_offset, anchor_node)

        # close body
        self.state.nested_parse(StringList(CARD_TEMPLATE_FOOTER.split('\n')), self.content_offset, anchor_node)

        # start footer
        self.state.nested_parse(StringList(CARD_TEMPLATE_LINK_CONTAINER_HEADER.split('\n')), self.content_offset, anchor_node)

        # full tutorial link
        link_node = pending_xref(CARD_TEMPLATE_LINK,
                                 reftype='doc',
                                 refdomain='std',
                                 reftarget=link,
                                 refexplicit=False,
                                 refwarn=True,
                                 refkeepformat=True)
        # refkeepformat is handled in `patch_autodoc.py`
        self.state.nested_parse(StringList(CARD_TEMPLATE_LINK.split('\n')), self.content_offset, link_node)
        anchor_node += link_node

        # close footer
        self.state.nested_parse(StringList(CARD_TEMPLATE_FOOTER.split('\n')), self.content_offset, anchor_node)

        # close whole
        self.state.nested_parse(StringList(CARD_TEMPLATE_FOOTER.split('\n')), self.content_offset, anchor_node)

        return [anchor_node]


def setup(app):
    app.add_directive('codesnippetcard', CodeSnippetCardDirective)