diff --git a/sphinx/application.py b/sphinx/application.py
index 6ada00b6d..a8049b933 100644
--- a/sphinx/application.py
+++ b/sphinx/application.py
@@ -106,6 +106,7 @@ builtin_extensions = (
'sphinx.environment.collectors.dependencies',
'sphinx.environment.collectors.asset',
'sphinx.environment.collectors.metadata',
+ 'sphinx.environment.collectors.title',
) # type: Tuple[unicode, ...]
CONFIG_FILENAME = 'conf.py'
diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py
index 105c4e208..fd975c4ea 100644
--- a/sphinx/environment/__init__.py
+++ b/sphinx/environment/__init__.py
@@ -46,7 +46,6 @@ from sphinx.util.parallel import ParallelTasks, parallel_available, make_chunks
from sphinx.util.websupport import is_commentable
from sphinx.errors import SphinxError, ExtensionError
from sphinx.versioning import add_uids, merge_doctrees
-from sphinx.transforms import SphinxContentsFilter
from sphinx.deprecation import RemovedInSphinx20Warning
from sphinx.environment.managers.indexentries import IndexEntries
from sphinx.environment.managers.toctree import Toctree
@@ -312,8 +311,6 @@ class BuildEnvironment(object):
if docname in self.all_docs:
self.all_docs.pop(docname, None)
self.reread_always.discard(docname)
- self.titles.pop(docname, None)
- self.longtitles.pop(docname, None)
for version, changes in self.versionchanges.items():
new = [change for change in changes if change[1] != docname]
@@ -337,8 +334,6 @@ class BuildEnvironment(object):
self.all_docs[docname] = other.all_docs[docname]
if docname in other.reread_always:
self.reread_always.add(docname)
- self.titles[docname] = other.titles[docname]
- self.longtitles[docname] = other.longtitles[docname]
for version, changes in other.versionchanges.items():
self.versionchanges.setdefault(version, []).extend(
@@ -723,7 +718,6 @@ class BuildEnvironment(object):
doctree = pub.document
# post-processing
- self.create_title_from(docname, doctree)
for manager in itervalues(self.managers):
manager.process_doc(docname, doctree)
for domain in itervalues(self.domains):
@@ -848,32 +842,6 @@ class BuildEnvironment(object):
self.ref_context.get('py:module'),
self.temp_data.get('object'), node.astext()))
- # post-processing of read doctrees
-
- def create_title_from(self, docname, document):
- # type: (unicode, nodes.Node) -> None
- """Add a title node to the document (just copy the first section title),
- and store that title in the environment.
- """
- titlenode = nodes.title()
- longtitlenode = titlenode
- # explicit title set with title directive; use this only for
- # the
tag in HTML output
- if 'title' in document:
- longtitlenode = nodes.title()
- longtitlenode += nodes.Text(document['title'])
- # look for first section title and use that as the title
- for node in document.traverse(nodes.section):
- visitor = SphinxContentsFilter(document)
- node[0].walkabout(visitor)
- titlenode += visitor.get_entry_text()
- break
- else:
- # document has no title
- titlenode += nodes.Text('')
- self.titles[docname] = titlenode
- self.longtitles[docname] = longtitlenode
-
def note_toctree(self, docname, toctreenode):
# type: (unicode, addnodes.toctree) -> None
"""Note a TOC tree directive in a document and gather information about
diff --git a/sphinx/environment/collectors/title.py b/sphinx/environment/collectors/title.py
new file mode 100644
index 000000000..a5316fe94
--- /dev/null
+++ b/sphinx/environment/collectors/title.py
@@ -0,0 +1,65 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.environment.collectors.title
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ The title collector components for sphinx.environment.
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from docutils import nodes
+
+from sphinx.environment.collectors import EnvironmentCollector
+from sphinx.transforms import SphinxContentsFilter
+
+if False:
+ # For type annotation
+ from docutils import nodes # NOQA
+ from sphinx.sphinx import Sphinx # NOQA
+ from sphinx.environment import BuildEnvironment # NOQA
+
+
+class TitleCollector(EnvironmentCollector):
+ """title collector for sphinx.environment."""
+
+ def clear_doc(self, app, env, docname):
+ # type: (Sphinx, BuildEnvironment, unicode) -> None
+ env.titles.pop(docname, None)
+ env.longtitles.pop(docname, None)
+
+ def merge_other(self, app, env, docnames, other):
+ # type: (Sphinx, BuildEnvironment, Set[unicode], BuildEnvironment) -> None
+ for docname in docnames:
+ env.titles[docname] = other.titles[docname]
+ env.longtitles[docname] = other.longtitles[docname]
+
+ def process_doc(self, app, doctree):
+ # type: (Sphinx, nodes.Node) -> None
+ """Add a title node to the document (just copy the first section title),
+ and store that title in the environment.
+ """
+ titlenode = nodes.title()
+ longtitlenode = titlenode
+ # explicit title set with title directive; use this only for
+ # the tag in HTML output
+ if 'title' in doctree:
+ longtitlenode = nodes.title()
+ longtitlenode += nodes.Text(doctree['title'])
+ # look for first section title and use that as the title
+ for node in doctree.traverse(nodes.section):
+ visitor = SphinxContentsFilter(doctree)
+ node[0].walkabout(visitor)
+ titlenode += visitor.get_entry_text()
+ break
+ else:
+ # document has no title
+ titlenode += nodes.Text('')
+ app.env.titles[app.env.docname] = titlenode
+ app.env.longtitles[app.env.docname] = longtitlenode
+
+
+def setup(app):
+ # type: (Sphinx) -> None
+ app.add_env_collector(TitleCollector)