/usr/lib/python2.7/dist-packages/zzzeeksphinx/toc.py is in python-zzzeeksphinx 1.0.20-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | #!coding: utf-8
from docutils import nodes as docutils_nodes
class TOCMixin(object):
def get_current_subtoc(self, current_page_name, start_from=None):
"""Return a TOC for sub-files and sub-elements of the current file.
This is to provide a "contextual" navbar that shows the current page
in context of all of its siblings, not just the immediate "previous"
and "next".
This allows a very long page with many sections to be broken
into smaller pages while not losing the navigation of the overall
section, with the added bonus that only the page-level bullets for
the current subsection are expanded, thus making for a much shorter,
"drill-down" style navigation.
"""
raw_tree = self.app.env.get_toctree_for(
current_page_name, self.app.builder, True, maxdepth=-1)
local_toc_tree = self.app.env.get_toc_for(
current_page_name, self.app.builder)
if raw_tree is None:
raw_tree = local_toc_tree
# start with the bullets inside the doc's toc,
# not the top level bullet, as we get that from the other tree
if not local_toc_tree.children or \
len(local_toc_tree.children[0].children) < 2:
local_tree = None
else:
local_tree = local_toc_tree.children[0].children[1]
def _locate_nodes(nodes, level, outer=True):
# this is a lazy way of getting at all the info in a
# series of docutils nodes, with an absolute mimimal
# reliance on the actual structure of the nodes.
# we just look for refuris and the fact that a node
# is dependent on another somehow, that's it, then we
# flatten it out into a clean "tree" later.
# An official Sphinx feature/extension
# here would probably make much more use of direct
# knowledge of the structure
for elem in nodes:
if hasattr(elem, 'attributes'):
refuri = elem.attributes.get('refuri', None)
else:
refuri = None
name = None
if refuri is not None:
for index, sub_elem in enumerate(elem.children, 1):
if isinstance(
sub_elem,
(docutils_nodes.Text, docutils_nodes.literal)):
continue
else:
break
local_text = elem.children[0:index]
name = local_text[0].rawsource
remainders = elem.children[index:]
yield level, refuri, name, local_text
else:
remainders = elem.children
# try to embed the item-level get_toc_for() inside
# the file-level get_toctree_for(), otherwise if we
# just get the full get_toctree_for(), it's enormous.
if outer and refuri == '':
if local_tree is not None:
for ent in _locate_nodes(
[local_tree], level + 1, False):
yield ent
else:
for ent in _locate_nodes(
remainders, level + 1, outer):
yield ent
def _organize_nodes(nodes):
"""organize the nodes that we've grabbed with non-contiguous
'level' numbers into a clean hierarchy"""
stack = []
levels = []
for level, refuri, name, text_nodes in nodes:
if not levels or levels[-1] < level:
levels.append(level)
new_collection = []
if stack:
stack[-1].append(new_collection)
stack.append(new_collection)
elif level < levels[-1]:
while levels and level < levels[-1]:
levels.pop(-1)
if level > levels[-1]:
levels.append(level)
else:
stack.pop(-1)
stack[-1].append((refuri, name, text_nodes))
return stack
def _render_nodes(
stack, level=0, start_from=None, nested_element=False,
parent_element=None):
printing = False
if stack:
printing = nested_element or start_from is None or \
start_from in [
elem[0] for elem in stack
if isinstance(elem, tuple)
]
if printing:
if not isinstance(
parent_element, docutils_nodes.bullet_list):
new_list = docutils_nodes.bullet_list()
parent_element.append(new_list)
parent_element = new_list
while stack:
elem = stack.pop(0)
as_links = not isinstance(elem, tuple) or \
elem[0] != ''
if isinstance(elem, tuple):
refuri, name, text_nodes = elem
if not stack or isinstance(stack[0], tuple):
if printing:
list_item = docutils_nodes.list_item(
classes=['selected']
if not as_links else [])
list_item.append(
self._link_node(refuri, text_nodes)
if as_links else
self._strong_node(refuri, text_nodes)
)
parent_element.append(list_item)
elif isinstance(stack[0], list):
if printing:
list_item = docutils_nodes.list_item(
classes=['selected']
if not as_links else [])
list_item.append(
self._link_node(refuri, text_nodes)
if as_links else
self._strong_node(refuri, text_nodes)
)
parent_element.append(list_item)
else:
list_item = None
_render_nodes(
stack[0],
level=level + 1,
start_from=start_from,
nested_element=nested_element or
printing or
elem[0] == '',
parent_element=list_item or parent_element)
elif isinstance(elem, list):
_render_nodes(
elem,
level=level + 1,
start_from=start_from,
nested_element=nested_element,
parent_element=parent_element)
element = docutils_nodes.bullet_list()
nodes = _organize_nodes(_locate_nodes([raw_tree], 0))
_render_nodes(
nodes,
start_from=start_from,
parent_element=element
)
return self.app.builder.render_partial(element)['fragment']
def _link_node(self, refuri, text_nodes):
link = docutils_nodes.reference(
'', '', text_nodes[0],
refuri=refuri)
link.extend(text_nodes[1:])
cp = docutils_nodes.inline(classes=['link-container'])
cp.append(link)
return cp
def _strong_node(self, refuri, text_nodes):
cp = docutils_nodes.inline(classes=['link-container'])
n1 = docutils_nodes.strong()
n1.extend(text_nodes)
cp.append(n1)
paramlink = docutils_nodes.reference(
'', '',
docutils_nodes.Text(u"¶", u"¶"),
refid="",
# paramlink is our own CSS class, headerlink
# is theirs. Trying to get everything we can for existing
# symbols...
classes=['paramlink', 'headerlink']
)
cp.append(paramlink)
return cp
|