1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
"""Docutils transforms used by Sphinx when reading documents."""
from __future__ import annotations
from typing import TYPE_CHECKING, Any, cast
from docutils import nodes
from sphinx import addnodes
from sphinx.transforms import SphinxTransform
if TYPE_CHECKING:
from docutils.nodes import Node
from sphinx.application import Sphinx
class RefOnlyListChecker(nodes.GenericNodeVisitor):
"""Raise `nodes.NodeFound` if non-simple list item is encountered.
Here 'simple' means a list item containing only a paragraph with a
single reference in it.
"""
def default_visit(self, node: Node) -> None:
raise nodes.NodeFound
def visit_bullet_list(self, node: nodes.bullet_list) -> None:
pass
def visit_list_item(self, node: nodes.list_item) -> None:
children: list[Node] = []
for child in node.children:
if not isinstance(child, nodes.Invisible):
children.append(child)
if len(children) != 1:
raise nodes.NodeFound
if not isinstance(children[0], nodes.paragraph):
raise nodes.NodeFound
para = children[0]
if len(para) != 1:
raise nodes.NodeFound
if not isinstance(para[0], addnodes.pending_xref):
raise nodes.NodeFound
raise nodes.SkipChildren
def invisible_visit(self, node: Node) -> None:
"""Invisible nodes should be ignored."""
pass
class RefOnlyBulletListTransform(SphinxTransform):
"""Change refonly bullet lists to use compact_paragraphs.
Specifically implemented for 'Indices and Tables' section, which looks
odd when html_compact_lists is false.
"""
default_priority = 100
def apply(self, **kwargs: Any) -> None:
if self.config.html_compact_lists:
return
def check_refonly_list(node: Node) -> bool:
"""Check for list with only references in it."""
visitor = RefOnlyListChecker(self.document)
try:
node.walk(visitor)
except nodes.NodeFound:
return False
else:
return True
for node in self.document.findall(nodes.bullet_list):
if check_refonly_list(node):
for item in node.findall(nodes.list_item):
para = cast(nodes.paragraph, item[0])
ref = cast(nodes.reference, para[0])
compact_para = addnodes.compact_paragraph()
compact_para += ref
item.replace(para, compact_para)
def setup(app: Sphinx) -> dict[str, Any]:
app.add_transform(RefOnlyBulletListTransform)
return {
'version': 'builtin',
'parallel_read_safe': True,
'parallel_write_safe': True,
}
|