11from urllib .parse import unquote
22
33from docutils import nodes
4+ from docutils .utils import unescape
45from docutils .parsers .rst import directives
56from sphinx import addnodes
67from sphinx .util .docutils import SphinxDirective
78
9+ from .utils import string_to_func_inputs
10+
811
912def setup_link_button (app ):
1013 app .add_directive ("link-button" , LinkButton )
14+ # TODO hide badges in non-HTML?
15+ app .add_role ("badge" , badge_role )
16+ app .add_role ("link-badge" , link_badge_role )
17+
18+
19+ def create_ref_node (link_type , uri , text , tooltip ):
20+ innernode = nodes .inline (text , text )
21+ if link_type == "ref" :
22+ ref_node = addnodes .pending_xref (
23+ reftarget = unquote (uri ),
24+ reftype = "any" ,
25+ # refdoc=self.env.docname,
26+ refdomain = "" ,
27+ refexplicit = True ,
28+ refwarn = True ,
29+ )
30+ innernode ["classes" ] = ["xref" , "any" ]
31+ # if tooltip:
32+ # ref_node["reftitle"] = tooltip
33+ # ref_node["title"] = tooltip
34+ # TODO this doesn't work
35+ else :
36+ ref_node = nodes .reference ()
37+ ref_node ["refuri" ] = uri
38+ if tooltip :
39+ ref_node ["reftitle" ] = tooltip
40+ ref_node += innernode
41+ return ref_node
1142
1243
1344class LinkButton (SphinxDirective ):
@@ -28,34 +59,56 @@ def run(self):
2859 link_type = self .options .get ("type" , "url" )
2960
3061 text = self .options .get ("text" , uri )
31- innernode = nodes .inline ("" , text )
32-
33- if link_type == "ref" :
34- ref_node = addnodes .pending_xref (
35- reftarget = unquote (uri ),
36- reftype = "any" ,
37- # refdoc=self.env.docname,
38- refdomain = "" ,
39- refexplicit = True ,
40- refwarn = True ,
41- )
42- innernode ["classes" ] = ["xref" , "any" ]
43- if "tooltip" in self .options :
44- ref_node ["title" ] = self .options ["tooltip" ]
45- else :
46- ref_node = nodes .reference ()
47- ref_node ["refuri" ] = uri
48- if "tooltip" in self .options :
49- ref_node ["reftitle" ] = self .options ["tooltip" ]
5062
63+ ref_node = create_ref_node (
64+ link_type , uri , text , self .options .get ("tooltip" , None )
65+ )
5166 self .set_source_info (ref_node )
52-
5367 ref_node ["classes" ] = ["sphinx-bs" , "btn" , "text-wrap" ] + self .options .get (
5468 "classes" , ""
5569 ).split ()
56- ref_node += innernode
70+
5771 # sphinx requires that a reference be inside a block element
5872 container = nodes .paragraph ()
5973 container += ref_node
6074
6175 return [container ]
76+
77+
78+ def get_badge_inputs (text , cls : str = "" ):
79+ return text , cls .split ()
80+
81+
82+ def badge_role (role , rawtext , text , lineno , inliner , options = {}, content = []):
83+ try :
84+ args , kwargs = string_to_func_inputs (text )
85+ text , classes = get_badge_inputs (* args , ** kwargs )
86+ except Exception as err :
87+ msg = inliner .reporter .error (f"badge input is invalid: { err } " , line = lineno )
88+ prb = inliner .problematic (rawtext , rawtext , msg )
89+ return [prb ], [msg ]
90+ node = nodes .inline (
91+ rawtext , unescape (text ), classes = ["sphinx-bs" , "badge" ] + classes
92+ )
93+ # textnodes, messages = inliner.parse(text, lineno, node, memo)
94+ # TODO this would require the memo with reporter, document and language
95+ return [node ], []
96+
97+
98+ def get_link_badge_inputs (link , text = None , type = "link" , cls : str = "" , tooltip = None ):
99+ return link , text or link , type , cls .split (), tooltip
100+
101+
102+ def link_badge_role (role , rawtext , text , lineno , inliner , options = {}, content = []):
103+ try :
104+ args , kwargs = string_to_func_inputs (text )
105+ uri , text , link_type , classes , tooltip = get_link_badge_inputs (* args , ** kwargs )
106+ except Exception as err :
107+ msg = inliner .reporter .error (f"badge input is invalid: { err } " , line = lineno )
108+ prb = inliner .problematic (rawtext , rawtext , msg )
109+ return [prb ], [msg ]
110+ ref_node = create_ref_node (link_type , uri , text , tooltip )
111+ if lineno is not None :
112+ ref_node .source , ref_node .line = inliner .reporter .get_source_and_line (lineno )
113+ ref_node ["classes" ] = ["sphinx-bs" , "badge" ] + classes
114+ return [ref_node ], []
0 commit comments