如何创建适用于 Latex 的自定义 sphinx 扩展

How to create an custom sphinx extention that works in latex

我创建了一个超小的扩展来在我的文档中添加角色“图标”。这个想法是写下以下内容:

I'm a folder :icon:`fa fa-folder`

我改编了一些网上找到的代码,得出了以下结论:

from docutils import nodes

def icon_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
    """add inline icons

    Returns 2 part tuple containing list of nodes to insert into the
    document and a list of system messages.  Both are allowed to be
    empty.

    :param name: The role name used in the document.
    :param rawtext: The entire markup snippet, with role.
    :param text: The text marked with the role.
    :param lineno: The line number where rawtext appears in the input.
    :param inliner: The inliner instance that called us.
    :param options: Directive options for customization.
    :param content: The directive content for customization.
    """
    node =nodes.reference()
    html = f"<i class=\"{text}\"></i>"
    node = nodes.raw('', html, format='html')
    return [node], []

def setup(app):
    """Install the plugin.

    :param app: Sphinx application context.
    """
    app.add_role('icon', icon_role)
    return

问题是我的 pdf 输出中没有考虑角色,它仍然是空白的。是否有额外的代码我应该添加以使其在乳胶中也能工作?

根据我在 sphinx-contrib organization and in particular in the clever youtube sphinx extension 中找到的内容,我编写了一个自定义 node 代码,它将为 HTML 输出创建 <i> 标记,并为乳胶的。在乳胶中显示图标当然需要更多工作,但这与此处无关。

我把代码留给感兴趣的人。

# -*- coding: utf-8 -*-

from docutils import nodes

class icon(nodes.General, nodes.Element):
    """A general node class that will be used in setup"""

    pass

def depart_icon_node(self, node):
    """Empty depart function, everything is handled in visit functions"""

    pass

def visit_icon_node_html(self, node):
    """entry point of the html node. we simply create a <i> tag"""

    icon = node["icon"]
    self.body.append(f"<i class=\"{icon}\"></i>")
    
    return
    
def visit_icon_node_latex(self, node):
    """ 
    entry point of the html node. we simply write down the text in bold. 
    See the linked repository for more complex macros and how to set them up in 'preamble'
    """
    
    icon = node["icon"]
        
    self.body.append("\textbf{%s}" %(icon))
    
    return
        
def visit_icon_node_unsuported(self, node):
    """raise error when the requested output is not supported"""
    
    self.builder.warn(f'unsupported output format (node skipped)')
    raise nodes.SkipNode
    
_NODE_VISITORS = {
    'html': (visit_icon_node_html, depart_icon_node),
    'latex': (visit_icon_node_latex, depart_icon_node),
    'man': (visit_icon_node_unsuported, None), # don't need depart function because I raise an error 
    'texinfo': (visit_icon_node_unsuported, None), # same 
    'text': (visit_icon_node_unsuported, None) #same
}
    

def icon_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
    """add inline icons"""
    
    node = icon(icon=text)

    return [node], []

def setup(app):
    """Install the plugin.

    :param app: Sphinx application context.
    """

    app.add_node(icon, **_NODE_VISITORS)
    app.add_role('icon', icon_role)

    return