Add desc_sig_element and inherited nodes

This commit is contained in:
Takeshi KOMIYA 2020-02-24 01:23:07 +09:00
parent f85b870ad5
commit 89c446eaf7
2 changed files with 63 additions and 2 deletions

View File

@ -12,7 +12,7 @@ import warnings
from typing import Any, Dict, List, Sequence
from docutils import nodes
from docutils.nodes import Node
from docutils.nodes import Element, Node
from sphinx.deprecation import RemovedInSphinx40Warning
@ -174,6 +174,31 @@ class desc_content(nodes.General, nodes.Element):
"""
class desc_sig_element(nodes.inline):
"""Common parent class of nodes for inline text of a signature."""
classes = [] # type: List[str]
def __init__(self, rawsource: str = '', text: str = '',
*children: Element, **attributes: Any) -> None:
super().__init__(rawsource, text, *children, **attributes)
self['classes'].extend(self.classes)
class desc_sig_name(desc_sig_element):
"""Node for a name in a signature."""
classes = ["n"]
class desc_sig_operator(desc_sig_element):
"""Node for an operator in a signature."""
classes = ["o"]
class desc_sig_punctuation(desc_sig_element):
"""Node for a punctuation in a signature."""
classes = ["p"]
# new admonition-like constructs
class versionmodified(nodes.Admonition, nodes.TextElement):
@ -332,6 +357,9 @@ def setup(app: "Sphinx") -> Dict[str, Any]:
app.add_node(desc_optional)
app.add_node(desc_annotation)
app.add_node(desc_content)
app.add_node(desc_sig_name)
app.add_node(desc_sig_operator)
app.add_node(desc_sig_punctuation)
app.add_node(versionmodified)
app.add_node(seealso)
app.add_node(productionlist)

View File

@ -8,7 +8,7 @@
:license: BSD, see LICENSE for details.
"""
from typing import Any, Dict, List, Tuple
from typing import Any, Dict, List, Tuple, Type
from typing import cast
from docutils import nodes
@ -22,6 +22,7 @@ from sphinx.errors import NoUri
from sphinx.locale import __
from sphinx.transforms import SphinxTransform
from sphinx.util import logging
from sphinx.util.docutils import SphinxTranslator
from sphinx.util.nodes import process_only_nodes
@ -186,9 +187,41 @@ class OnlyNodeTransform(SphinxPostTransform):
process_only_nodes(self.document, self.app.builder.tags)
class SigElementFallbackTransform(SphinxPostTransform):
"""Fallback desc_sig_element nodes to inline if translator does not supported them."""
default_priority = 200
SIG_ELEMENTS = [addnodes.desc_sig_name,
addnodes.desc_sig_operator,
addnodes.desc_sig_punctuation]
def run(self, **kwargs: Any) -> None:
def has_visitor(translator: Type[nodes.NodeVisitor], node: Type[Element]) -> bool:
return hasattr(translator, "visit_%s" % node.__name__)
translator = self.app.builder.get_translator_class()
if isinstance(translator, SphinxTranslator):
# subclass of SphinxTranslator supports desc_sig_element nodes automatically.
return
if all(has_visitor(translator, node) for node in self.SIG_ELEMENTS):
# the translator supports all desc_sig_element nodes
return
else:
self.fallback()
def fallback(self):
for node in self.document.traverse(addnodes.desc_sig_element):
newnode = nodes.inline()
newnode.update_all_atts(node)
newnode.extend(node)
node.replace_self(newnode)
def setup(app: Sphinx) -> Dict[str, Any]:
app.add_post_transform(ReferencesResolver)
app.add_post_transform(OnlyNodeTransform)
app.add_post_transform(SigElementFallbackTransform)
return {
'version': 'builtin',