mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Patch from Stefan Seefeld: make local toctree collapsible.
This commit is contained in:
parent
2d76170b9c
commit
394282223b
@ -164,6 +164,10 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
)
|
)
|
||||||
self.globalcontext.update(self.config.html_context)
|
self.globalcontext.update(self.config.html_context)
|
||||||
|
|
||||||
|
def _get_local_toctree(self, docname):
|
||||||
|
return self.render_partial(self.env.get_toctree_for(
|
||||||
|
docname, self, self.config.html_collapse_toctree))['fragment']
|
||||||
|
|
||||||
def get_doc_context(self, docname, body, metatags):
|
def get_doc_context(self, docname, body, metatags):
|
||||||
"""Collect items for the template context of a page."""
|
"""Collect items for the template context of a page."""
|
||||||
# find out relations
|
# find out relations
|
||||||
@ -219,8 +223,6 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
metatags = metatags,
|
metatags = metatags,
|
||||||
rellinks = rellinks,
|
rellinks = rellinks,
|
||||||
sourcename = sourcename,
|
sourcename = sourcename,
|
||||||
toctree = self.render_partial(self.env.get_toctree_for(
|
|
||||||
docname, self))['fragment'],
|
|
||||||
toc = self.render_partial(self.env.get_toc_for(docname))['fragment'],
|
toc = self.render_partial(self.env.get_toc_for(docname))['fragment'],
|
||||||
# only display a TOC if there's more than one item to show
|
# only display a TOC if there's more than one item to show
|
||||||
display_toc = (self.env.toc_num_entries[docname] > 1),
|
display_toc = (self.env.toc_num_entries[docname] > 1),
|
||||||
@ -474,6 +476,7 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
ctx['pathto'] = pathto
|
ctx['pathto'] = pathto
|
||||||
ctx['hasdoc'] = lambda name: name in self.env.all_docs
|
ctx['hasdoc'] = lambda name: name in self.env.all_docs
|
||||||
ctx['customsidebar'] = self.config.html_sidebars.get(pagename)
|
ctx['customsidebar'] = self.config.html_sidebars.get(pagename)
|
||||||
|
ctx['toctree'] = self._get_local_toctree(pagename)
|
||||||
ctx.update(addctx)
|
ctx.update(addctx)
|
||||||
|
|
||||||
self.app.emit('html-page-context', pagename, templatename, ctx, event_arg)
|
self.app.emit('html-page-context', pagename, templatename, ctx, event_arg)
|
||||||
|
@ -66,6 +66,7 @@ class Config(object):
|
|||||||
html_use_smartypants = (True, False),
|
html_use_smartypants = (True, False),
|
||||||
html_translator_class = (None, False),
|
html_translator_class = (None, False),
|
||||||
html_sidebars = ({}, False),
|
html_sidebars = ({}, False),
|
||||||
|
html_collapse_toctree = (False, False),
|
||||||
html_additional_pages = ({}, False),
|
html_additional_pages = ({}, False),
|
||||||
html_use_modindex = (True, False),
|
html_use_modindex = (True, False),
|
||||||
html_add_permalinks = (True, False),
|
html_add_permalinks = (True, False),
|
||||||
|
@ -14,7 +14,7 @@ from docutils.parsers.rst import directives
|
|||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
from sphinx.locale import pairindextypes
|
from sphinx.locale import pairindextypes
|
||||||
from sphinx.util import patfilter, ws_re, caption_ref_re, docname_join
|
from sphinx.util import patfilter, ws_re, caption_ref_re, url_re, docname_join
|
||||||
from sphinx.util.compat import make_admonition
|
from sphinx.util.compat import make_admonition
|
||||||
|
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ def toctree_directive(name, arguments, options, content, lineno,
|
|||||||
docname = docname[:-len(suffix)]
|
docname = docname[:-len(suffix)]
|
||||||
# absolutize filenames
|
# absolutize filenames
|
||||||
docname = docname_join(env.docname, docname)
|
docname = docname_join(env.docname, docname)
|
||||||
if ref.startswith('http://'): # FIXME: generalize to arbitrary xrefs
|
if url_re.match(ref):
|
||||||
entries.append((title, ref))
|
entries.append((title, ref))
|
||||||
elif docname not in env.found_docs:
|
elif docname not in env.found_docs:
|
||||||
ret.append(state.document.reporter.warning(
|
ret.append(state.document.reporter.warning(
|
||||||
|
@ -44,7 +44,7 @@ from docutils.transforms.parts import ContentsFilter
|
|||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
from sphinx.util import movefile, get_matching_docs, SEP, ustrftime, \
|
from sphinx.util import movefile, get_matching_docs, SEP, ustrftime, \
|
||||||
docname_join, FilenameUniqDict
|
docname_join, FilenameUniqDict, url_re
|
||||||
from sphinx.directives import additional_xref_types
|
from sphinx.directives import additional_xref_types
|
||||||
|
|
||||||
default_settings = {
|
default_settings = {
|
||||||
@ -830,12 +830,12 @@ class BuildEnvironment:
|
|||||||
node['refuri'] = node['anchorname']
|
node['refuri'] = node['anchorname']
|
||||||
return toc
|
return toc
|
||||||
|
|
||||||
def get_toctree_for(self, docname, builder):
|
def get_toctree_for(self, docname, builder, collapse):
|
||||||
"""Return the global TOC nodetree."""
|
"""Return the global TOC nodetree."""
|
||||||
doctree = self.get_doctree(self.config.master_doc)
|
doctree = self.get_doctree(self.config.master_doc)
|
||||||
for toctreenode in doctree.traverse(addnodes.toctree):
|
for toctreenode in doctree.traverse(addnodes.toctree):
|
||||||
result = self.resolve_toctree(docname, builder, toctreenode,
|
result = self.resolve_toctree(docname, builder, toctreenode,
|
||||||
prune=True)
|
prune=True, collapse=collapse)
|
||||||
if result is not None:
|
if result is not None:
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@ -909,7 +909,7 @@ class BuildEnvironment:
|
|||||||
return doctree
|
return doctree
|
||||||
|
|
||||||
def resolve_toctree(self, docname, builder, toctree, prune=True, maxdepth=0,
|
def resolve_toctree(self, docname, builder, toctree, prune=True, maxdepth=0,
|
||||||
titles_only=False):
|
titles_only=False, collapse=False):
|
||||||
"""
|
"""
|
||||||
Resolve a *toctree* node into individual bullet lists with titles
|
Resolve a *toctree* node into individual bullet lists with titles
|
||||||
as items, returning None (if no containing titles are found) or
|
as items, returning None (if no containing titles are found) or
|
||||||
@ -919,6 +919,8 @@ class BuildEnvironment:
|
|||||||
to the value of the *maxdepth* option on the *toctree* node.
|
to the value of the *maxdepth* option on the *toctree* node.
|
||||||
If *titles_only* is True, only toplevel document titles will be in the
|
If *titles_only* is True, only toplevel document titles will be in the
|
||||||
resulting tree.
|
resulting tree.
|
||||||
|
If *collapse* is True, all branches not containing docname will
|
||||||
|
be collapsed.
|
||||||
"""
|
"""
|
||||||
if toctree.get('hidden', False):
|
if toctree.get('hidden', False):
|
||||||
return None
|
return None
|
||||||
@ -935,13 +937,30 @@ class BuildEnvironment:
|
|||||||
else:
|
else:
|
||||||
_walk_depth(subnode, depth+1, maxdepth)
|
_walk_depth(subnode, depth+1, maxdepth)
|
||||||
|
|
||||||
|
# cull sub-entries whose parents aren't 'current'
|
||||||
|
if (collapse and
|
||||||
|
depth > 1 and
|
||||||
|
'current' not in subnode.parent['classes']):
|
||||||
|
subnode.parent.remove(subnode)
|
||||||
|
|
||||||
|
elif isinstance(subnode, nodes.reference):
|
||||||
|
# Identify the toc entry pointing to the current document.
|
||||||
|
if subnode['refuri'] == docname and not subnode['anchorname']:
|
||||||
|
# tag the whole branch as 'current'
|
||||||
|
# (We can't use traverse here as 'ascend' un-intuitively
|
||||||
|
# implies 'siblings'.)
|
||||||
|
p = subnode
|
||||||
|
while p:
|
||||||
|
p['classes'].append('current')
|
||||||
|
p = p.parent
|
||||||
|
|
||||||
def _entries_from_toctree(toctreenode, separate=False, subtree=False):
|
def _entries_from_toctree(toctreenode, separate=False, subtree=False):
|
||||||
"""Return TOC entries for a toctree node."""
|
"""Return TOC entries for a toctree node."""
|
||||||
refs = [(e[0], str(e[1])) for e in toctreenode['entries']]
|
refs = [(e[0], str(e[1])) for e in toctreenode['entries']]
|
||||||
entries = []
|
entries = []
|
||||||
for (title, ref) in refs:
|
for (title, ref) in refs:
|
||||||
try:
|
try:
|
||||||
if ref.startswith('http://'): # FIXME: (see directives/other.py)
|
if url_re.match(ref):
|
||||||
reference = nodes.reference('', '', refuri=ref, anchorname='',
|
reference = nodes.reference('', '', refuri=ref, anchorname='',
|
||||||
*[nodes.Text(title)])
|
*[nodes.Text(title)])
|
||||||
para = addnodes.compact_paragraph('', '', reference)
|
para = addnodes.compact_paragraph('', '', reference)
|
||||||
@ -1001,11 +1020,13 @@ class BuildEnvironment:
|
|||||||
|
|
||||||
newnode = addnodes.compact_paragraph('', '', *tocentries)
|
newnode = addnodes.compact_paragraph('', '', *tocentries)
|
||||||
newnode['toctree'] = True
|
newnode['toctree'] = True
|
||||||
|
|
||||||
# prune the tree to maxdepth and replace titles, also set level classes
|
# prune the tree to maxdepth and replace titles, also set level classes
|
||||||
_walk_depth(newnode, 1, prune and maxdepth or 0)
|
_walk_depth(newnode, 1, prune and maxdepth or 0)
|
||||||
|
|
||||||
# set the target paths in the toctrees (they are not known at TOC generation time)
|
# set the target paths in the toctrees (they are not known at TOC generation time)
|
||||||
for refnode in newnode.traverse(nodes.reference):
|
for refnode in newnode.traverse(nodes.reference):
|
||||||
if not refnode['refuri'].startswith('http://'): # FIXME: see above
|
if not url_re.match(refnode['refuri']):
|
||||||
refnode['refuri'] = builder.get_relative_uri(
|
refnode['refuri'] = builder.get_relative_uri(
|
||||||
docname, refnode['refuri']) + refnode['anchorname']
|
docname, refnode['refuri']) + refnode['anchorname']
|
||||||
return newnode
|
return newnode
|
||||||
|
@ -23,7 +23,7 @@ from os import path
|
|||||||
# Generally useful regular expressions.
|
# Generally useful regular expressions.
|
||||||
ws_re = re.compile(r'\s+')
|
ws_re = re.compile(r'\s+')
|
||||||
caption_ref_re = re.compile(r'^([^<]+?)\s*<(.+)>$')
|
caption_ref_re = re.compile(r'^([^<]+?)\s*<(.+)>$')
|
||||||
|
url_re = re.compile(r'(?P<schema>.+)://.*')
|
||||||
|
|
||||||
# SEP separates path elements in the canonical file names
|
# SEP separates path elements in the canonical file names
|
||||||
#
|
#
|
||||||
|
Loading…
Reference in New Issue
Block a user