cardlinkitem.py 3.42 KB
Newer Older
1
2
3
4
5
6
7
8
9
"""
Directive "cardlinkitem" used in tutorials navigation page.
"""

import os

from docutils.parsers.rst import Directive, directives
from docutils.statemachine import StringList
from docutils import nodes
10
from sphinx.addnodes import pending_xref
11
12
13
14
15
16
17

TAG_TEMPLATE = """<span class="card-link-tag">{tag}</span>"""

TAGS_TEMPLATE = """
    <p class="card-link-summary">{tags}</p>
"""

18
CARD_HEADER = """
19
20
21
22
.. raw:: html

    <div class="card-link admonition">

23
    <a class="card-link-clickable" href="#">
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

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

    <div class="card-link-text">

    <div class="card-link-title-container">
        <h4>{header}</h4>
    </div>

    <p class="card-link-summary">{description}</p>

    {tags}

    </div>

    <div class="card-link-icon circle {image_background}">

.. image:: {image}

.. raw:: html

    </div>

    </div>

    </a>
50
51
52
53
"""

CARD_FOOTER = """
.. raw:: html
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

    </div>
"""


class CustomCardItemDirective(Directive):
    option_spec = {
        'header': directives.unchanged,
        'image': directives.unchanged,
        'background': directives.unchanged,
        'link': directives.unchanged,
        'description': directives.unchanged,
        'tags': directives.unchanged
    }

    def run(self):
        env = self.state.document.settings.env

        try:
            if 'header' in self.options:
                header = self.options['header']
            else:
                raise ValueError('header not found')

            if 'link' in self.options:
                link = directives.uri(self.options['link'])
            else:
                raise ValueError('link not found')

            if 'image' in self.options:
                image = directives.uri(self.options['image'])
            else:
                image = os.path.join(os.path.relpath(env.app.srcdir, env.app.confdir), '../img/thumbnails/nni_icon_white.png')

            image_background = self.options.get('background', 'indigo')
            description = self.options.get('description', '')

            tags = self.options.get('tags', '').strip().split('/')
            tags = [t.strip() for t in tags if t.strip()]

        except ValueError as e:
            print(e)
            raise

        if tags:
            tags_rst = TAGS_TEMPLATE.format(tags=''.join([TAG_TEMPLATE.format(tag=tag) for tag in tags]))
        else:
            tags_rst = ''

103
104
105
106
107
108
109
        card_rst = CARD_HEADER.format(
            header=header,
            image=image,
            image_background=image_background,
            link=link,
            description=description,
            tags=tags_rst)
110
        card = nodes.paragraph()
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
        self.state.nested_parse(StringList(card_rst.split('\n')), self.content_offset, card)

        # This needs to corporate with javascript: propagate_card_link.
        # because sphinx can't correctly handle image in a `pending_xref` after `keepformat`.
        link_node = pending_xref('<a/>',
                                 reftype='doc',
                                 refdomain='std',
                                 reftarget=link,
                                 refexplicit=False,
                                 refwarn=True)
        link_node += nodes.paragraph(header)
        link_node['classes'] = ['card-link-anchor']
        card += link_node

        self.state.nested_parse(StringList(CARD_FOOTER.split('\n')), self.content_offset, card)

127
128
129
130
131
        return [card]


def setup(app):
    app.add_directive('cardlinkitem', CustomCardItemDirective)