You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Sphinx扩展开发问题:literal_block内inline节点无法渲染为span元素

问题:Sphinx扩展中literal_block内的inline节点无法渲染为span元素

我正在开发一款用于HTML输出的Sphinx扩展,目标是生成代码块并在其中插入文本与<span>元素。但创建literal_block并添加inline节点(对应span)时,只能显示inline节点的文本内容,无法渲染出带样式的span元素。

相关代码示例

from docutils import nodes
from docutils.parsers import rst
from sphinx.addnodes import highlightlang

class MyDirective(rst.Directive):
    # 为简化和调试,暂不使用内容
    has_content = True
    
    def run(self):
        node = nodes.literal_block()
        node += nodes.inline("",
            text = "Hello World",
            classes = ["myclass"]
        )
        
        return [
            highlightlang(
                lang = "none",
                force = None,
                linenothreshold = -1
            ),
            node
        ]

def setup(app):
    app.add_directive("helloworld", MyDirective)

期望的HTML输出

<div class="highlight-none notranslate">
  <div class="highlight">
    <pre><span class="myclass">Hello World</span></pre>
  </div>
</div>

实际得到的HTML输出

<div class="highlight-none notranslate">
  <div class="highlight">
    <pre>Hello World</pre>
  </div>
</div>

解决方法

literal_block节点在Sphinx的HTML渲染流程中,默认会被当作纯代码块处理,内部的inline节点会被剥离仅保留文本内容。要实现需求,可选择以下两种方式:

方式1:自定义HTML访问器,修改literal_block渲染逻辑

注册自定义HTML转换器,让literal_block渲染时保留内部inline节点结构:

from docutils import nodes
from docutils.parsers import rst
from sphinx.addnodes import highlightlang
from sphinx.writers.html5 import HTML5Translator

class MyDirective(rst.Directive):
    has_content = True
    
    def run(self):
        node = nodes.literal_block()
        inline_node = nodes.inline("Hello World", classes=["myclass"])
        node.append(inline_node)
        
        return [
            highlightlang(lang="none", force=None, linenothreshold=-1),
            node
        ]

def setup(app):
    app.add_directive("helloworld", MyDirective)
    
    # 重写literal_block的HTML访问方法
    def visit_literal_block(self, node):
        self.body.append(self.starttag(node, 'pre', ''))
    
    def depart_literal_block(self, node):
        self.body.append('</pre>\n')
    
    app.set_translator('html', HTML5Translator, override=True)
    HTML5Translator.visit_literal_block = visit_literal_block
    HTML5Translator.depart_literal_block = depart_literal_block

方式2:直接使用raw节点嵌入HTML

如果仅需支持HTML输出,可直接在literal_block中插入raw节点:

from docutils import nodes
from docutils.parsers import rst
from sphinx.addnodes import highlightlang

class MyDirective(rst.Directive):
    has_content = True
    
    def run(self):
        raw_html = '<span class="myclass">Hello World</span>'
        raw_node = nodes.raw('', raw_html, format='html')
        node = nodes.literal_block()
        node.append(raw_node)
        
        return [
            highlightlang(lang="none", force=None, linenothreshold=-1),
            node
        ]

def setup(app):
    app.add_directive("helloworld", MyDirective)

说明:方式1保留docutils节点结构,兼容性更强;方式2实现简单,但仅适用于HTML场景。

内容的提问来源于stack exchange,提问作者Jonas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 07:55:25