File: button.py

package info (click to toggle)
sphinx-panels 0.6.0-7
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 944 kB
  • sloc: python: 1,054; xml: 60; makefile: 23; sh: 16
file content (115 lines) | stat: -rw-r--r-- 3,766 bytes parent folder | download | duplicates (3)
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
113
114
115
from urllib.parse import unquote

from docutils import nodes
from docutils.utils import unescape
from docutils.parsers.rst import directives
from sphinx import addnodes
from sphinx.util.docutils import SphinxDirective

from .utils import string_to_func_inputs


def setup_link_button(app):
    app.add_directive("link-button", LinkButton)
    # TODO hide badges in non-HTML?
    app.add_role("badge", badge_role)
    app.add_role("link-badge", link_badge_role)


def create_ref_node(link_type, uri, text, tooltip):
    innernode = nodes.inline(text, text)
    if link_type == "ref":
        ref_node = addnodes.pending_xref(
            reftarget=unquote(uri),
            reftype="any",
            # refdoc=self.env.docname,
            refdomain="",
            refexplicit=True,
            refwarn=True,
        )
        innernode["classes"] = ["xref", "any"]
        # if tooltip:
        #     ref_node["reftitle"] = tooltip
        #     ref_node["title"] = tooltip
        # TODO this doesn't work
    else:
        ref_node = nodes.reference()
        ref_node["refuri"] = uri
        if tooltip:
            ref_node["reftitle"] = tooltip
    ref_node += innernode
    return ref_node


class LinkButton(SphinxDirective):
    """A directive to turn a link into a button."""

    has_content = False
    required_arguments = 1
    final_argument_whitespace = True
    option_spec = {
        "type": lambda arg: directives.choice(arg, ("url", "ref")),
        "text": directives.unchanged,
        "tooltip": directives.unchanged,
        "classes": directives.unchanged,
    }

    def run(self):

        uri = self.arguments[0]
        link_type = self.options.get("type", "url")

        text = self.options.get("text", uri)

        ref_node = create_ref_node(
            link_type, uri, text, self.options.get("tooltip", None)
        )
        self.set_source_info(ref_node)
        ref_node["classes"] = ["sphinx-bs", "btn", "text-wrap"] + self.options.get(
            "classes", ""
        ).split()

        # sphinx requires that a reference be inside a block element
        container = nodes.paragraph()
        container += ref_node

        return [container]


def get_badge_inputs(text, cls: str = ""):
    return text, cls.split()


def badge_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
    try:
        args, kwargs = string_to_func_inputs(text)
        text, classes = get_badge_inputs(*args, **kwargs)
    except Exception as err:
        msg = inliner.reporter.error(f"badge input is invalid: {err}", line=lineno)
        prb = inliner.problematic(rawtext, rawtext, msg)
        return [prb], [msg]
    node = nodes.inline(
        rawtext, unescape(text), classes=["sphinx-bs", "badge"] + classes
    )
    # textnodes, messages = inliner.parse(text, lineno, node, memo)
    # TODO this would require the memo with reporter, document and language
    return [node], []


def get_link_badge_inputs(link, text=None, type="link", cls: str = "", tooltip=None):
    return link, text or link, type, cls.split(), tooltip


def link_badge_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
    try:
        args, kwargs = string_to_func_inputs(text)
        uri, text, link_type, classes, tooltip = get_link_badge_inputs(*args, **kwargs)
    except Exception as err:
        msg = inliner.reporter.error(f"badge input is invalid: {err}", line=lineno)
        prb = inliner.problematic(rawtext, rawtext, msg)
        return [prb], [msg]
    ref_node = create_ref_node(link_type, uri, text, tooltip)
    if lineno is not None:
        ref_node.source, ref_node.line = inliner.reporter.get_source_and_line(lineno)
    ref_node["classes"] = ["sphinx-bs", "badge"] + classes
    return [ref_node], []