diff --git a/CHANGES b/CHANGES index c55645bc9..b86edafaf 100644 --- a/CHANGES +++ b/CHANGES @@ -28,6 +28,11 @@ New features added * Defaults for configuration values can now be callables, which allows dynamic defaults. +* The new ``html-page-context`` event can be used to include custom values + into the context used when rendering an HTML template. + +* Add document metadata to the values in the default template context. + Bugs fixed ---------- diff --git a/doc/conf.py b/doc/conf.py index 653679b69..c17d1f769 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -162,7 +162,25 @@ def parse_role(env, sig, signode): return sig +event_sig_re = re.compile(r'([a-zA-Z-]+)\s*\((.*)\)') + +def parse_event(env, sig, signode): + m = event_sig_re.match(sig) + if not m: + signode += addnodes.desc_name(sig, sig) + return sig + name, args = m.groups() + signode += addnodes.desc_name(name, name) + plist = addnodes.desc_parameterlist() + for arg in args.split(','): + arg = arg.strip() + plist += addnodes.desc_parameter(arg, arg) + signode += plist + return name + + def setup(app): app.add_description_unit('directive', 'dir', 'pair: %s; directive', parse_directive) app.add_description_unit('role', 'role', 'pair: %s; role', parse_role) app.add_description_unit('confval', 'confval', 'pair: %s; configuration value') + app.add_description_unit('event', 'event', 'pair: %s; event', parse_event) diff --git a/doc/ext/appapi.rst b/doc/ext/appapi.rst index 616708ad8..edd0537a6 100644 --- a/doc/ext/appapi.rst +++ b/doc/ext/appapi.rst @@ -162,22 +162,43 @@ package. Sphinx core events ------------------ -These events are known to the core: +These events are known to the core. The arguments showed are given to the +registered event handlers. -.. tabularcolumns:: |l|L|L| +.. event:: builder-inited () + + Emitted the builder object has been created. + +.. event:: doctree-read (doctree) + + Emitted when a doctree has been parsed and read by the environment, and is + about to be pickled. + +.. event:: doctree-resolved (doctree, docname) + + Emitted when a doctree has been "resolved" by the environment, that is, all + references and TOCs have been inserted. + +.. event:: page-context (pagename, templatename, context, doctree) + + Emitted when the HTML builder has created a context dictionary to render a + template with -- this can be used to add custom elements to the context. + + The *pagename* argument is the canonical name of the page being rendered, + that is, without ``.html`` suffix and using slashes as path separators. The + *templatename* is the name of the template to render, this will be + ``'page.html'`` for all pages from reST documents. + + The *context* argument is a dictionary of values that are given to the + template engine to render the page and can be modified to include custom + values. Keys must be strings. + + The *doctree* argument will be a doctree when the page is created from a reST + documents; it will be ``None`` when the page is created from an HTML template + alone. + + .. versionadded:: 0.4 -====================== =================================== ========= -Event name Emitted when Arguments -====================== =================================== ========= -``'builder-inited'`` the builder object has been created -none- -``'doctree-read'`` a doctree has been parsed and read *doctree* - by the environment, and is about to - be pickled -``'doctree-resolved'`` a doctree has been "resolved" by *doctree*, *docname* - the environment, that is, all - references and TOCs have been - inserted -====================== =================================== ========= .. _template-bridge: diff --git a/sphinx/application.py b/sphinx/application.py index d136f0be5..68edd588c 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -49,7 +49,8 @@ class ExtensionError(Exception): events = { 'builder-inited': '', 'doctree-read' : 'the doctree before being pickled', - 'doctree-resolved' : 'the doctree, the docname', + 'doctree-resolved' : 'doctree, docname', + 'html-page-context': 'pagename, context, doctree or None', } class Sphinx(object): diff --git a/sphinx/builder.py b/sphinx/builder.py index f9e391735..2c1646eba 100644 --- a/sphinx/builder.py +++ b/sphinx/builder.py @@ -341,19 +341,13 @@ class StandaloneHTMLBuilder(Builder): show_sphinx = self.config.html_show_sphinx, builder = self.name, parents = [], - titles = {}, logo = logo, len = len, # the built-in ) - def write_doc(self, docname, doctree): - destination = StringOutput(encoding='utf-8') - doctree.settings = self.docsettings - - self.imgpath = relative_uri(self.get_target_uri(docname), '_images') - self.docwriter.write(doctree, destination) - self.docwriter.assemble_parts() - + def get_doc_context(self, docname, body): + """Collect items for the template context of a page.""" + # find out relations prev = next = None parents = [] related = self.env.toctree_relations.get(docname) @@ -383,27 +377,40 @@ class StandaloneHTMLBuilder(Builder): # "back to index" link already parents.reverse() + # title rendered as HTML title = titles.get(docname) - if title: - title = self.render_partial(title)['title'] - else: - title = '' - self.globalcontext['titles'][docname] = title + title = title and self.render_partial(title)['title'] or '' + # the name for the copied source sourcename = self.config.html_copy_source and docname + '.txt' or '' - ctx = dict( - title = title, - sourcename = sourcename, - body = self.docwriter.parts['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 - display_toc = (self.env.toc_num_entries[docname] > 1), + + # metadata for the document + meta = self.env.metadata.get(docname) + + return dict( parents = parents, prev = prev, next = next, + title = title, + meta = meta, + body = body, + sourcename = sourcename, + toc = self.render_partial(self.env.get_toc_for(docname))['fragment'], + # only display a TOC if there's more than one item to show + display_toc = (self.env.toc_num_entries[docname] > 1), ) - self.index_page(docname, doctree, title) - self.handle_page(docname, ctx) + def write_doc(self, docname, doctree): + destination = StringOutput(encoding='utf-8') + doctree.settings = self.docsettings + + self.imgpath = relative_uri(self.get_target_uri(docname), '_images') + self.docwriter.write(doctree, destination) + self.docwriter.assemble_parts() + body = self.docwriter.parts['fragment'] + + ctx = self.get_doc_context(docname, body) + self.index_page(docname, doctree, ctx.get('title', '')) + self.handle_page(docname, ctx, event_arg=doctree) def finish(self): self.info(bold('writing additional files...'), nonl=1) @@ -569,9 +576,10 @@ class StandaloneHTMLBuilder(Builder): return docname + self.out_suffix def handle_page(self, pagename, addctx, templatename='page.html', - outfilename=None): + outfilename=None, event_arg=None): ctx = self.globalcontext.copy() - ctx['current_page_name'] = pagename + # current_page_name is backwards compatibility + ctx['pagename'] = ctx['current_page_name'] = pagename def pathto(otheruri, resource=False, baseuri=self.get_target_uri(pagename)): @@ -580,11 +588,11 @@ class StandaloneHTMLBuilder(Builder): return relative_uri(baseuri, otheruri) ctx['pathto'] = pathto ctx['hasdoc'] = lambda name: name in self.env.all_docs - sidebarfile = self.config.html_sidebars.get(pagename) - if sidebarfile: - ctx['customsidebar'] = sidebarfile + ctx['customsidebar'] = self.config.html_sidebars.get(pagename) ctx.update(addctx) + self.app.emit('html-page-context', pagename, templatename, ctx, event_arg) + output = self.templates.render(templatename, ctx) if not outfilename: outfilename = path.join(self.outdir, os_path(pagename) + self.out_suffix) diff --git a/sphinx/templates/layout.html b/sphinx/templates/layout.html index d1fc566c8..749209fb3 100644 --- a/sphinx/templates/layout.html +++ b/sphinx/templates/layout.html @@ -75,7 +75,7 @@ {{ rendertemplate(customsidebar) }} {%- endif %} {%- block sidebarsearch %} - {%- if current_page_name != "search" %} + {%- if pagename != "search" %}