diff --git a/doc/_templates/layout.html b/doc/_templates/layout.html index e8970899d..2c370dbda 100644 --- a/doc/_templates/layout.html +++ b/doc/_templates/layout.html @@ -1,8 +1,8 @@ {% extends "!layout.html" %} {% block rootrellink %} -
  • Sphinx home
  • -
  • Documentation »
  • +
  • Sphinx home  | 
  • +
  • Documentation »
  • {% endblock %} {% block header %} diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index 57105d169..a24141641 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -179,6 +179,9 @@ class StandaloneHTMLBuilder(Builder): logo = logo, favicon = favicon, ) + self.globalcontext.update( + ('theme_' + key, val) for (key, val) in + self.theme.get_options(self.config.html_theme_options).iteritems()) self.globalcontext.update(self.config.html_context) def _get_local_toctree(self, docname): diff --git a/sphinx/config.py b/sphinx/config.py index 2cba96a34..79f3ce8a3 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -58,6 +58,7 @@ class Config(object): # HTML options html_theme = ('default', False), html_theme_path = ([], False), + html_theme_options = ({}, False), html_title = (lambda self: '%s v%s documentation' % (self.project, self.release), False), diff --git a/sphinx/jinja2glue.py b/sphinx/jinja2glue.py index c7c163aa8..9fc9ba3aa 100644 --- a/sphinx/jinja2glue.py +++ b/sphinx/jinja2glue.py @@ -18,6 +18,12 @@ from sphinx.util import mtimes_of_files from sphinx.application import TemplateBridge +def _tobool(val): + if isinstance(val, basestring): + return val.lower() in ('true', '1', 'yes', 'on') + return bool(val) + + class BuiltinTemplateLoader(TemplateBridge, jinja2.BaseLoader): """ Interfaces the rendering environment of jinja2 for use in Sphinx. @@ -38,6 +44,8 @@ class BuiltinTemplateLoader(TemplateBridge, jinja2.BaseLoader): chain[0:0] = [path.join(builder.confdir, tp) for tp in builder.config.templates_path] + self.pathchain = chain + # make the paths into loaders self.loaders = map(jinja2.FileSystemLoader, chain) @@ -45,6 +53,7 @@ class BuiltinTemplateLoader(TemplateBridge, jinja2.BaseLoader): extensions = use_i18n and ['jinja2.ext.i18n'] or [] self.environment = jinja2.Environment(loader=self, extensions=extensions) + self.environment.filters['tobool'] = _tobool if use_i18n: self.environment.install_gettext_translations(builder.translator) @@ -52,7 +61,7 @@ class BuiltinTemplateLoader(TemplateBridge, jinja2.BaseLoader): return self.environment.get_template(template).render(context) def newest_template_mtime(self): - return max(mtimes_of_files(self.theme.get_dirchain(), '.html')) + return max(mtimes_of_files(self.pathchain, '.html')) # Loader interface diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py index c7bf92f64..d2a1c62db 100644 --- a/sphinx/quickstart.py +++ b/sphinx/quickstart.py @@ -114,10 +114,17 @@ pygments_style = 'sphinx' # -- Options for HTML output --------------------------------------------------- -# The style sheet to use for HTML and HTML Help pages. A file of that name -# must exist either in Sphinx' static/ path, or in one of the custom paths -# given in html_static_path. -html_style = 'default.css' +# The theme to use for HTML and HTML Help pages. Major themes that come with +# Sphinx are currently 'default' and 'sphinxdoc'. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". diff --git a/sphinx/themes/basic/layout.html b/sphinx/themes/basic/layout.html index b4b1e7c57..dda18343f 100644 --- a/sphinx/themes/basic/layout.html +++ b/sphinx/themes/basic/layout.html @@ -27,7 +27,7 @@ {%- endmacro %} {%- macro sidebar() %} - {%- if not embedded %} + {%- if not embedded %}{% if not theme_nosidebar|tobool %}
    {%- block sidebarlogo %} @@ -86,7 +86,7 @@ {%- endblock %}
    - {%- endif %} + {%- endif %}{% endif %} {%- endmacro %} @@ -155,15 +155,15 @@ {%- block document %}
    - {%- if not embedded %} + {%- if not embedded %}{% if not theme_nosidebar|tobool %}
    - {%- endif %} + {%- endif %}{% endif %}
    {% block body %} {% endblock %}
    - {%- if not embedded %} + {%- if not embedded %}{% if not theme_nosidebar|tobool %}
    - {%- endif %} + {%- endif %}{% endif %}
    {%- endblock %} diff --git a/sphinx/themes/basic/theme.conf b/sphinx/themes/basic/theme.conf index 3157eac59..d1fe6d1f9 100644 --- a/sphinx/themes/basic/theme.conf +++ b/sphinx/themes/basic/theme.conf @@ -2,3 +2,6 @@ inherit = none stylesheet = basic.css pygments_style = none + +[options] +nosidebar = false diff --git a/sphinx/themes/default/layout.html b/sphinx/themes/default/layout.html new file mode 100644 index 000000000..9a909b0b9 --- /dev/null +++ b/sphinx/themes/default/layout.html @@ -0,0 +1,12 @@ +{% extends "basic/layout.html" %} +{% block extrahead %} +{%- if theme_rightsidebar|tobool %} + +{%- endif %} +{%- if theme_stickysidebar|tobool %} + +{%- endif %} +{{ super() }} +{% endblock %} diff --git a/sphinx/themes/default/static/rightsidebar.css b/sphinx/themes/default/static/rightsidebar.css index bc604a893..d21eb0969 100644 --- a/sphinx/themes/default/static/rightsidebar.css +++ b/sphinx/themes/default/static/rightsidebar.css @@ -1,10 +1,8 @@ -/** - * Sphinx Doc Design -- Right Side Bar Overrides - */ - +/* rightsidebar overrides for default design */ div.sphinxsidebar { float: right; + right: 0; /* for sticky sidebar */ } div.bodywrapper { diff --git a/sphinx/themes/default/static/stickysidebar.css b/sphinx/themes/default/static/stickysidebar.css index dfc99c77a..01450853c 100644 --- a/sphinx/themes/default/static/stickysidebar.css +++ b/sphinx/themes/default/static/stickysidebar.css @@ -1,15 +1,17 @@ -/** - * Sphinx Doc Design -- Sticky sidebar Overrides - */ +/* stickysidebar overrides for default design */ div.sphinxsidebar { top: 30px; - left: 0px; + height: 100%; + overflow: auto; position: fixed; margin: 0; - float: none; + background-color: #1c4e63; } +/* this is nice, but it it leads to hidden headings when jumping + to an anchor */ +/* div.related { position: fixed; } @@ -17,3 +19,4 @@ div.related { div.documentwrapper { margin-top: 30px; } +*/ diff --git a/sphinx/themes/default/theme.conf b/sphinx/themes/default/theme.conf index 1f5132065..f3d4d5ea6 100644 --- a/sphinx/themes/default/theme.conf +++ b/sphinx/themes/default/theme.conf @@ -2,3 +2,7 @@ inherit = basic stylesheet = default.css pygments_style = sphinx + +[options] +rightsidebar = false +stickysidebar = false diff --git a/sphinx/theming.py b/sphinx/theming.py index cdfe314a8..c6e4f4ce4 100644 --- a/sphinx/theming.py +++ b/sphinx/theming.py @@ -108,7 +108,7 @@ class Theme(object): """ try: return self.themeconf.get(section, name) - except ConfigParser.NoOptionError: + except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): if self.base is not None: return self.base.get_confstr(section, name) if default is NODEFAULT: @@ -117,6 +117,27 @@ class Theme(object): else: return default + def get_options(self, overrides): + """ + Return a dictionary of theme options and their values. + """ + chain = [self.themeconf] + base = self.base + while base is not None: + chain.append(base.themeconf) + base = base.base + options = {} + for conf in reversed(chain): + try: + options.update(conf.items('options')) + except ConfigParser.NoSectionError: + pass + for option, value in overrides.iteritems(): + if option not in options: + raise ThemeError('unsupported theme option %r given' % option) + options[option] = value + return options + def get_dirchain(self): """ Return a list of theme directories, beginning with this theme's,