使CSS按钮成为Sphinx中的链接

使CSS按钮成为Sphinx中的链接,css,jinja2,python-sphinx,restructuredtext,Css,Jinja2,Python Sphinx,Restructuredtext,我使用来自的建议将css按钮从添加到Sphinx。我有 我可以用它 :button:`button text` 我现在想让这个按钮成为一个链接,以交叉引用到不同的页面,基本上,是“文本”的 :ref:`text` 是一个简单的Sphinx扩展,可以实现这一功能。获取所需按钮的CSS,并将其添加为source/\u static/button.CSS(调用标记按钮) 然后在源代码旁边添加button.py,然后添加 sys.path.insert(0, os.path.abspath('..')

我使用来自的建议将css按钮从添加到Sphinx。我有

我可以用它

:button:`button text`
我现在想让这个按钮成为一个链接,以交叉引用到不同的页面,基本上,是“文本”的

:ref:`text`
是一个简单的Sphinx扩展,可以实现这一功能。获取所需按钮的CSS,并将其添加为
source/\u static/button.CSS
(调用标记
按钮

然后在
源代码旁边添加button.py,然后添加

sys.path.insert(0, os.path.abspath('..'))
添加到您的
conf.py
(如果它还没有)以便它可以找到它,并将
'button'
添加到
conf.py
中的扩展列表中

然后像这样使用它

.. button::
   :text: Button Text
   :link: link/to/stuff.html
非常感谢您编写此扩展的大部分内容

这太棒了

但是我想使用,所以我做了一些修改:

...

def button_role(role, rawtext, text, line_no, in_liner: Inliner, options: Dict = None, content: List = None):
    text, link = text.split('|')
    node = ButtonNode()
    node['text'] = text.rstrip()
    node['link'] = link.rstrip()
    return [node], []


def setup(app: Sphinx):

    ...

    """
    :btn:`text | link`
    """
    roles.register_canonical_role('btn', button_role)
用法:

Hello :btn:`Click me to SO | https://stackoverflow.com/` !!!
完整代码(v2) 第2版

  • 添加样式
  • 现在您不需要在
    指令
    中添加
    :text:
    (使用
    包含内容
其中类
btn hollow
是从

参考文献
  • 您可以转到
    docutils.parsers.rst.directives
    ::

    admonitions.py
    body.py
    html.py
    images.py
    misc.py
    parts.py
    references.py
    tables.py
    
    ↑ 选择一个您感兴趣的类,看看如何实现一个指令类

    • 查看详细信息:
      docutils.parsers.rst.roles.py
  • 斯芬克斯应用


您指向button.py Sphinx扩展的链接不再起作用,因为该特定存储库经过重构并被删除。可在此处找到button.py的最新版本:
Hello :btn:`Click me to SO | https://stackoverflow.com/` !!!
from docutils import nodes
import jinja2
from docutils.parsers.rst.directives import unchanged
from docutils.parsers.rst import Directive
from sphinx.application import Sphinx
from docutils.parsers.rst import roles
from docutils.parsers.rst.states import Inliner
from typing import List, Dict
import re

BUTTON_TEMPLATE = jinja2.Template("""
{% if link  %} 
    <a href="{{ link }}">    
        <button class="{{ class }}" {{ style |default('') }}>{{ text }}</button>
    </a>
{% else %}
    <button class="{{ class }}" {{ style |default('') }}>{{ text }}</button>
{% endif %}
""")


# placeholder node for document graph
class ButtonNode(nodes.Element):
    ...


class ButtonDirective(Directive):
    has_content = True
    required_arguments = 0

    """
    You have to set `option_spec` before you do the following
    .. xxx::
        :link:
        :class:
    """
    option_spec = {
        'link': unchanged,
        'class': unchanged,
        'style': unchanged,
    }

    # this will execute when your directive is encountered
    # it will insert a ButtonNode into the document that will
    # get visisted during the build phase
    def run(self):
        # env = self.state.document.settings.env
        # app: Sphinx = env.app
        # app.add_css_file('css/button/solid-blue-btn.css')  # or you can set it on the conf.py

        node = ButtonNode()
        node['text'] = ''.join(self.content.data)
        """
        .. button::
            :class: solid-blue-btn

            content.data[0]
            content.data[1]

        .. button:: content.data[0]
            :class: solid-blue-btn                
        """
        # style = "background-color:green; font-size: 30px;"

        node['class'] = self.options['class'].strip()
        node['link'] = self.options.get('link')
        if self.options.get('style'):
            style = 'style=' + self.options['style']  # style = "background-color:green; font-size: 30px;"
            node['style'] = style
        return [node]


# build phase visitor emits HTML to append to output
def html_visit_button_node(self, node: ButtonNode):
    # html = BUTTON_TEMPLATE.render(text=node['text'], link=node['link'])
    html = BUTTON_TEMPLATE.render({k: v for k, v in node.attributes.items()})
    self.body.append(''.join([_.strip() for _ in html.split('\n') if _.strip()]))
    raise nodes.SkipNode


def button_role(role, rawtext, text, line_no, in_liner: Inliner, options: Dict = None, content: List = None):
    # 'link="https://www.google.com/" style="background-color:green; font-size: 30px;"'
    regex = re.compile(f"(?:.*"
                       fr"(?P<link>link=\S*)|"
                       fr"(?P<style>style=\S*)"
                       f")",
                       )

    text, cls, *options = text.split('|')
    node = ButtonNode()  # nodes.paragraph
    node['class'] = cls.strip()
    node['text'] = text.rstrip()

    if options:
        options: str = options[0].strip()
        for attr in options.split(' '):
            m = regex.match(attr)
            if m:
                dict_option = m.groupdict()
                if dict_option.get('link'):
                    dict_option['link'] = dict_option['link'][5:]  # remove link=
                for key, value in dict_option.items():
                    if value:
                        node[key] = value.strip()
    return [node], []


def setup(app: Sphinx):

    """
    .. button::
        option1:
        option2:
    """
    app.add_node(ButtonNode,
                 # ↓ kwargs
                 html=(html_visit_button_node, lambda: None)
                 # other_2: Tuple[Callable, Callable],
                 # other_3: Tuple[visit_xxx, depart_xxx],
                 )
    app.add_directive('button', ButtonDirective)

    """
    :btn:``
    """
    roles.register_canonical_role('btn', button_role)

.. button:: Google
    :class: btn-solid-blue
    :style: "background-color:green; font-size:30px;"
    :link: https://www.google.com/

.. button:: FB (no link)
    :class: btn-solid-blue


- .. button:: Google
    :class: btn-solid-blue
    :link: https://www.google.com/

- .. button:: FB (no link)
    :class: btn-solid-blue

----

Hello :btn:`link | btn-solid-blue | link=https://stackoverflow.com/` !!!

Hello :btn:`bg f-size | btn-solid-blue | style="font-size:30px;"` !!!

Hello :btn:`bg font-size | btn-hollow-red | style="background-color:yellow; font-size:30px;"` !!!

Hello :btn:`font-size | btn-hollow-red | style="font-size:50px;"` !!!

Hello :btn:`link | btn-hollow-red | link=https://stackoverflow.com/` !!!

Hello\ :btn:`none | btn-hollow-black`\!!!
admonitions.py
body.py
html.py
images.py
misc.py
parts.py
references.py
tables.py