The `html_sidebars` config value can now contain patterns as keys, and the values can be lists that explicitly select which sidebar templates should be rendered.

That means that the builtin sidebar contents can be included only selectively.
This commit is contained in:
Georg Brandl
2010-01-07 17:56:09 +01:00
parent 5cb64a7228
commit 2f09d24472
15 changed files with 209 additions and 62 deletions

View File

@@ -1,6 +1,11 @@
Release 1.0 (in development)
============================
* The ``html_sidebars`` config value can now contain patterns as
keys, and the values can be lists that explicitly select which
sidebar templates should be rendered. That means that the builtin
sidebar contents can be included only selectively.
* ``html_static_path`` can now contain single file entries.
* The new universal config value ``exclude_patterns`` makes the

View File

@@ -52,7 +52,7 @@ html_last_updated_fmt = '%b %d, %Y'
html_index = 'index.html'
# Custom sidebar templates, maps page names to templates.
html_sidebars = {'index': 'indexsidebar.html'}
html_sidebars = {'index': ['indexsidebar.html', 'searchbox.html']}
# Additional templates that should be rendered to pages, maps page names to
# templates.

View File

@@ -90,7 +90,7 @@ General configuration
.. confval:: exclude_patterns
A list of glob-style patterns that should be excluded when looking for source
files. [#]_ They are matched against the source file names relative to the
files. [1]_ They are matched against the source file names relative to the
source directory, using slashes as directory separators on all platforms.
Example patterns:
@@ -445,14 +445,53 @@ that use Sphinx' HTMLWriter class.
.. confval:: html_sidebars
Custom sidebar templates, must be a dictionary that maps document names to
template names. Example::
template names.
The keys can contain glob-style patterns [1]_, in which case all matching
documents will get the specified sidebars. (A warning is emitted when a
more than one glob-style pattern matches for any document.)
The values can be either lists or single strings.
* If a value is a list, it specifies the complete list of sidebar templates
to include. If all or some of the default sidebars are to be included,
they must be put into this list as well.
The default sidebars (for documents that don't match any pattern) are:
``['localtoc.html', 'relations.html', 'sourcelink.html',
'searchbox.html']``.
* If a value is a single string, it specifies a custom sidebar to be added
between the ``'sourcelink.html'`` and ``'searchbox.html'`` entries. This
is for compatibility with Sphinx versions before 1.0.
Builtin sidebar templates that can be rendered are:
* **localtoc.html** -- a fine-grained table of contents of the current document
* **globaltoc.html** -- a coarse-grained table of contents for the whole
documentation set, collapsed
* **relations.html** -- two links to the previous and next documents
* **sourcelink.html** -- a link to the source of the current document, if
enabled in :confval:`html_show_sourcelink`
* **searchbox.html** -- the "quick search" box
Example::
html_sidebars = {
'using/windows': 'windowssidebar.html'
'**': ['globaltoc.html', 'sourcelink.html', 'searchbox.html'],
'using/windows': ['windowssidebar.html', 'searchbox.html'],
}
This will render the template ``windowssidebar.html`` within the sidebar of
the given document.
This will render the custom template ``windowssidebar.html`` and the quick
search box within the sidebar of the given document, and render the default
sidebars for all other pages (except that the local TOC is replaced by the
global TOC).
.. versionadded:: 1.0
The ability to use globbing keys and to specify multiple sidebars.
Note that this value only has no effect if the chosen theme does not possess
a sidebar, like the builtin **scrolls** and **haiku** themes.
.. confval:: html_additional_pages
@@ -835,7 +874,7 @@ These options influence LaTeX output.
.. rubric:: Footnotes
.. [#] A note on available globbing syntax: you can use the standard shell
.. [1] A note on available globbing syntax: you can use the standard shell
constructs ``*``, ``?``, ``[...]`` and ``[!...]`` with the feature that
these all don't match slashes. A double star ``**`` can be used to match
any sequence of characters *including* slashes.

View File

@@ -28,8 +28,8 @@ from docutils.frontend import OptionParser
from docutils.readers.doctree import Reader as DoctreeReader
from sphinx import package_dir, __version__
from sphinx.util import SEP, os_path, relative_uri, ensuredir, \
movefile, ustrftime, copy_static_entry, copyfile, compile_matchers
from sphinx.util import SEP, os_path, relative_uri, ensuredir, patmatch, \
movefile, ustrftime, copy_static_entry, copyfile, compile_matchers, any
from sphinx.errors import SphinxError
from sphinx.search import js_index
from sphinx.theming import Theme
@@ -74,6 +74,9 @@ class StandaloneHTMLBuilder(Builder):
# Dito for this one.
css_files = []
default_sidebars = ['localtoc.html', 'relations.html',
'sourcelink.html', 'searchbox.html']
# cached publisher object for snippets
_publisher = None
@@ -654,6 +657,33 @@ class StandaloneHTMLBuilder(Builder):
def get_outfilename(self, pagename):
return path.join(self.outdir, os_path(pagename) + self.out_suffix)
def get_sidebars(self, pagename):
def has_wildcard(pattern):
return any(char in pattern for char in '*?[')
sidebars = None
matched = None
for pattern, patsidebars in self.config.html_sidebars.iteritems():
if patmatch(pagename, pattern):
if matched:
if has_wildcard(pattern):
# warn if both patterns contain wildcards
if has_wildcard(matched):
self.warn('page %s matches two patterns in '
'html_sidebars: %r and %r' %
(pagename, matched, pattern))
# else the already matched pattern is more specific
# than the present one, because it contains no wildcard
continue
matched = pattern
sidebars = patsidebars
if sidebars is None:
sidebars = self.default_sidebars
elif isinstance(sidebars, basestring):
# 0.x compatible mode: insert custom sidebar before searchbox
sidebars = self.default_sidebars[:-1] + [sidebars] + \
self.default_sidebars[-1:]
return sidebars
# --------- these are overwritten by the serialization builder
def get_target_uri(self, docname, typ=None):
@@ -673,9 +703,9 @@ class StandaloneHTMLBuilder(Builder):
return uri
ctx['pathto'] = pathto
ctx['hasdoc'] = lambda name: name in self.env.all_docs
ctx['customsidebar'] = self.config.html_sidebars.get(pagename)
ctx['encoding'] = encoding = self.config.html_output_encoding
ctx['toctree'] = lambda **kw: self._get_local_toctree(pagename, **kw)
ctx['sidebars'] = self.get_sidebars(pagename)
ctx.update(addctx)
self.app.emit('html-page-context', pagename, templatename,
@@ -790,9 +820,7 @@ class SerializingHTMLBuilder(StandaloneHTMLBuilder):
def handle_page(self, pagename, ctx, templatename='page.html',
outfilename=None, event_arg=None):
ctx['current_page_name'] = pagename
sidebarfile = self.config.html_sidebars.get(pagename)
if sidebarfile:
ctx['customsidebar'] = sidebarfile
ctx['sidebars'] = self.get_sidebars(pagename)
if not outfilename:
outfilename = path.join(self.outdir,

View File

@@ -0,0 +1,15 @@
{#
basic/globaltoc.html
~~~~~~~~~~~~~~~~~~~~
Sphinx sidebar template: global table of contents.
:copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
#}
{%- block sidebartoc %}
{%- if display_toc %}
<h3><a href="{{ pathto(master_doc) }}">{{ _('Table Of Contents') }}</a></h3>
{{ toctree() }}
{%- endif %}
{%- endblock %}

View File

@@ -46,53 +46,9 @@
</a></p>
{%- endif %}
{%- endblock %}
{%- block sidebartoc %}
{%- if display_toc %}
<h3><a href="{{ pathto(master_doc) }}">{{ _('Table Of Contents') }}</a></h3>
{{ toc }}
{%- endif %}
{%- endblock %}
{%- block sidebarrel %}
{%- if prev %}
<h4>{{ _('Previous topic') }}</h4>
<p class="topless"><a href="{{ prev.link|e }}"
title="{{ _('previous chapter') }}">{{ prev.title }}</a></p>
{%- endif %}
{%- if next %}
<h4>{{ _('Next topic') }}</h4>
<p class="topless"><a href="{{ next.link|e }}"
title="{{ _('next chapter') }}">{{ next.title }}</a></p>
{%- endif %}
{%- endblock %}
{%- block sidebarsourcelink %}
{%- if show_source and has_source and sourcename %}
<h3>{{ _('This Page') }}</h3>
<ul class="this-page-menu">
<li><a href="{{ pathto('_sources/' + sourcename, true)|e }}"
rel="nofollow">{{ _('Show Source') }}</a></li>
</ul>
{%- endif %}
{%- endblock %}
{%- if customsidebar %}
{% include customsidebar %}
{%- endif %}
{%- block sidebarsearch %}
{%- if pagename != "search" %}
<div id="searchbox" style="display: none">
<h3>{{ _('Quick search') }}</h3>
<form class="search" action="{{ pathto('search') }}" method="get">
<input type="text" name="q" size="18" />
<input type="submit" value="{{ _('Go') }}" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
{{ _('Enter search terms or a module, class or function name.') }}
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
{%- endif %}
{%- endblock %}
{%- for sidebar in sidebars %}
{%- include sidebar %}
{%- endfor %}
</div>
</div>
{%- endif %}{% endif %}

View File

@@ -0,0 +1,15 @@
{#
basic/localtoc.html
~~~~~~~~~~~~~~~~~~~
Sphinx sidebar template: local table of contents.
:copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
#}
{%- block sidebartoc %}
{%- if display_toc %}
<h3><a href="{{ pathto(master_doc) }}">{{ _('Table Of Contents') }}</a></h3>
{{ toc }}
{%- endif %}
{%- endblock %}

View File

@@ -0,0 +1,21 @@
{#
basic/relations.html
~~~~~~~~~~~~~~~~~~~~
Sphinx sidebar template: relation links.
:copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
#}
{%- block sidebarrel %}
{%- if prev %}
<h4>{{ _('Previous topic') }}</h4>
<p class="topless"><a href="{{ prev.link|e }}"
title="{{ _('previous chapter') }}">{{ prev.title }}</a></p>
{%- endif %}
{%- if next %}
<h4>{{ _('Next topic') }}</h4>
<p class="topless"><a href="{{ next.link|e }}"
title="{{ _('next chapter') }}">{{ next.title }}</a></p>
{%- endif %}
{%- endblock %}

View File

@@ -0,0 +1,26 @@
{#
basic/searchbox.html
~~~~~~~~~~~~~~~~~~~~
Sphinx sidebar template: quick search box.
:copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
#}
{%- block sidebarsearch %}
{%- if pagename != "search" %}
<div id="searchbox" style="display: none">
<h3>{{ _('Quick search') }}</h3>
<form class="search" action="{{ pathto('search') }}" method="get">
<input type="text" name="q" size="18" />
<input type="submit" value="{{ _('Go') }}" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
{{ _('Enter search terms or a module, class or function name.') }}
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
{%- endif %}
{%- endblock %}

View File

@@ -0,0 +1,18 @@
{#
basic/sourcelink.html
~~~~~~~~~~~~~~~~~~~~~
Sphinx sidebar template: "show source" link.
:copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
#}
{%- block sidebarsourcelink %}
{%- if show_source and has_source and sourcename %}
<h3>{{ _('This Page') }}</h3>
<ul class="this-page-menu">
<li><a href="{{ pathto('_sources/' + sourcename, true)|e }}"
rel="nofollow">{{ _('Show Source') }}</a></li>
</ul>
{%- endif %}
{%- endblock %}

View File

@@ -12,7 +12,6 @@
import os
import re
import sys
import stat
import time
import errno
import types
@@ -285,6 +284,14 @@ def compile_matchers(patterns):
_pat_cache = {}
def patmatch(name, pat):
"""
Return if name matches pat. Adapted from fnmatch module.
"""
if pat not in _pat_cache:
_pat_cache[pat] = re.compile(_translate_pattern(pat))
return _pat_cache[pat].match(name)
def patfilter(names, pat):
"""
Return the subset of the list NAMES that match PAT.
@@ -483,6 +490,15 @@ def split_explicit_title(text):
return False, text, text
try:
any = any
except NameError:
def any(gen):
for i in gen:
if i:
return True
return False
# monkey-patch Node.traverse to get more speed
# traverse() is called so many times during a build that it saves
# on average 20-25% overall build time!

View File

@@ -0,0 +1,2 @@
{# sidebar only for contents document #}
<h4>Contents sidebar</h4>

View File

@@ -0,0 +1,2 @@
{# custom sidebar template #}
<h4>Custom sidebar</h4>

View File

@@ -31,7 +31,7 @@ rst_epilog = '.. |subst| replace:: global substitution'
html_theme = 'testtheme'
html_theme_path = ['.']
html_theme_options = {'testopt': 'testoverride'}
html_sidebars = {'**': 'customsb.html', 'contents': 'contentssb.html'}
html_style = 'default.css'
html_static_path = ['_static', 'templated.css_t']
html_last_updated_fmt = '%b %d, %Y'

View File

@@ -86,6 +86,8 @@ HTML_XPATH = {
".//dl[@class='userdesc']": '',
".//dt[@id='userdescrole-myobj']": '',
".//a[@href='#userdescrole-myobj']": '',
# custom sidebar
".//h4": 'Custom sidebar',
},
'contents.html': {
".//meta[@name='hc'][@content='hcval']": '',
@@ -98,6 +100,8 @@ HTML_XPATH = {
".//title": 'Sphinx <Tests>',
".//div[@class='footer']": 'Georg Brandl & Team',
".//a[@href='http://python.org/']": '',
# custom sidebar only for contents
".//h4": 'Contents sidebar',
},
'bom.html': {
".//title": " File with UTF-8 BOM",