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
92
93
94
|
"""
sphinx.transforms.compact_bullet_list
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Docutils transforms used by Sphinx when reading documents.
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from typing import Any, Dict, List, cast
from docutils import nodes
from docutils.nodes import Node
from sphinx import addnodes
from sphinx.application import Sphinx
from sphinx.transforms import SphinxTransform
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 = [] # type: 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.traverse(nodes.bullet_list):
if check_refonly_list(node):
for item in node.traverse(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,
}
|