Merge with stable

Conflicts:
	sphinx/environment.py
	sphinx/ext/autodoc.py
	sphinx/writers/latex.py
This commit is contained in:
shimizukawa 2016-02-09 22:17:05 +09:00
commit 980653f277
13 changed files with 297 additions and 150 deletions

18
CHANGES
View File

@ -85,9 +85,24 @@ Documentation
Release 1.3.6 (in development)
==============================
Features added
--------------
* #1873, #1876, #2278: Add ``page_source_suffix`` html context variable. This should be
introduced with :confval:`source_parsers` feature. Thanks for Eric Holscher.
Bugs fixed
----------
* #2265: Fix babel is used in spite of disabling it on ``latex_elements``
* #2295: Avoid mutating dictionary errors while enumerating members in autodoc
with Python 3
* #2291: Fix pdflatex "Counter too large" error from footnotes inside tables of contents
* #2292: Fix some footnotes disappear from LaTeX output
* #2287: ``sphinx.transforms.Locale`` always uses rst parser. Sphinx i18n feature should
support parsers that specified source_parsers.
Release 1.3.5 (released Jan 24, 2016)
=====================================
@ -103,7 +118,8 @@ Bugs fixed
* #2243: Ignore strange docstring types for classes, do not crash
* #2247: Fix #2205 breaks make html for definition list with classifiers
that contains regular-expression like string
* #1565: Show warning if Pygments throws an ErrorToken
* #1565: Sphinx will now emit a warning that highlighting was skipped if the syntax
is incorrect for `code-block`, `literalinclude` and so on.
* #2211: Fix paragraphs in table cell doesn't work in Latex output
* #2253: ``:pyobject:`` option of ``literalinclude`` directive can't detect indented
body block when the block starts with blank or comment lines.

View File

@ -106,17 +106,23 @@ This section describe a easy way to translate with sphinx-intl.
#. Translate your po files under `./locale/<lang>/LC_MESSAGES/`.
#. Build mo files and make translated document.
#. make translated document.
You need a :confval:`language` parameter in ``conf.py`` or you may also
specify the parameter on the command line::
$ sphinx-intl build
$ make -e SPHINXOPTS="-D language='de'" html
Congratulations! You got the translated documentation in the ``_build/html``
directory.
.. versionadded:: 1.3
sphinx-build that is invoked by make command will build po files into mo files.
If you are using 1.2.x or earlier, please invoke ``sphinx-intl build`` command
before make command.
Translating
^^^^^^^^^^^
@ -251,9 +257,8 @@ easy to fetch and push translations.
...
Done.
Build po files into mo and make html::
Invoke make html::
$ sphinx-intl build
$ make -e SPHINXOPTS="-D language='de'" html

View File

@ -35,7 +35,8 @@ from sphinx.errors import SphinxError, SphinxWarning, ExtensionError, \
from sphinx.domains import ObjType, BUILTIN_DOMAINS
from sphinx.domains.std import GenericObject, Target, StandardDomain
from sphinx.builders import BUILTIN_BUILDERS
from sphinx.environment import BuildEnvironment, SphinxStandaloneReader
from sphinx.environment import BuildEnvironment
from sphinx.io import SphinxStandaloneReader
from sphinx.util import pycompat # noqa: imported for side-effects
from sphinx.util import import_object
from sphinx.util.tags import Tags

View File

@ -23,24 +23,23 @@ from os import path
from glob import glob
from itertools import groupby
from six import iteritems, itervalues, text_type, class_types, string_types, next
from six import iteritems, itervalues, text_type, class_types, next
from six.moves import cPickle as pickle
from docutils import nodes
from docutils.io import FileInput, NullOutput
from docutils.io import NullOutput
from docutils.core import Publisher
from docutils.utils import Reporter, relative_path, get_source_line
from docutils.readers import standalone
from docutils.parsers.rst import roles, directives
from docutils.parsers.rst.languages import en as english
from docutils.parsers.rst.directives.html import MetaBody
from docutils.writers import UnfilteredWriter
from docutils.frontend import OptionParser
from sphinx import addnodes
from sphinx.io import SphinxStandaloneReader, SphinxDummyWriter, SphinxFileInput
from sphinx.util import url_re, get_matching_docs, docname_join, split_into, \
FilenameUniqDict, get_figtype, import_object, split_index_msg, split_docinfo
FilenameUniqDict, get_figtype, import_object, split_index_msg
from sphinx.util.nodes import clean_astext, make_refnode, WarningStream, is_translatable
from sphinx.util.osutil import SEP, getcwd, fs_encoding
from sphinx.util.osutil import SEP, getcwd, fs_encoding, ensuredir
from sphinx.util.i18n import find_catalog_files
from sphinx.util.console import bold, purple
from sphinx.util.matching import compile_matchers
@ -49,12 +48,7 @@ from sphinx.util.websupport import is_commentable
from sphinx.errors import SphinxError, ExtensionError
from sphinx.locale import _
from sphinx.versioning import add_uids, merge_doctrees
from sphinx.transforms import (
DefaultSubstitutions, MoveModuleTargets, ApplySourceWorkaround,
HandleCodeBlocks, AutoNumbering, SortIds, CitationReferences, Locale,
RemoveTranslatableInline, SphinxContentsFilter, ExtraTranslatableNodes,
)
from sphinx.transforms import SphinxContentsFilter
orig_role_function = roles.role
orig_directive_function = directives.directive
@ -97,77 +91,6 @@ class NoUri(Exception):
pass
class SphinxStandaloneReader(standalone.Reader):
"""
Add our own transforms.
"""
transforms = [ApplySourceWorkaround, ExtraTranslatableNodes, Locale, CitationReferences,
DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks,
AutoNumbering, SortIds, RemoveTranslatableInline]
def __init__(self, app, parsers={}, *args, **kwargs):
standalone.Reader.__init__(self, *args, **kwargs)
self.parser_map = {}
for suffix, parser_class in parsers.items():
if isinstance(parser_class, string_types):
parser_class = import_object(parser_class, 'source parser')
parser = parser_class()
if hasattr(parser, 'set_application'):
parser.set_application(app)
self.parser_map[suffix] = parser
def read(self, source, parser, settings):
self.source = source
for suffix in self.parser_map:
if source.source_path.endswith(suffix):
self.parser = self.parser_map[suffix]
break
if not self.parser:
self.parser = parser
self.settings = settings
self.input = self.source.read()
self.parse()
return self.document
def get_transforms(self):
return standalone.Reader.get_transforms(self) + self.transforms
class SphinxDummyWriter(UnfilteredWriter):
supported = ('html',) # needed to keep "meta" nodes
def translate(self):
pass
class SphinxFileInput(FileInput):
def __init__(self, app, env, *args, **kwds):
self.app = app
self.env = env
kwds['error_handler'] = 'sphinx' # py3: handle error on open.
FileInput.__init__(self, *args, **kwds)
def decode(self, data):
if isinstance(data, text_type): # py3: `data` already decoded.
return data
return data.decode(self.encoding, 'sphinx') # py2: decoding
def read(self):
data = FileInput.read(self)
if self.app:
arg = [data]
self.app.emit('source-read', self.env.docname, arg)
data = arg[0]
docinfo, data = split_docinfo(data)
if self.env.config.rst_epilog:
data = data + '\n' + self.env.config.rst_epilog + '\n'
if self.env.config.rst_prolog:
data = self.env.config.rst_prolog + '\n' + data
return docinfo + data
class BuildEnvironment:
"""
The environment in which the ReST files are translated.
@ -859,9 +782,7 @@ class BuildEnvironment:
# save the parsed doctree
doctree_filename = self.doc2path(docname, self.doctreedir,
'.doctree')
dirname = path.dirname(doctree_filename)
if not path.isdir(dirname):
os.makedirs(dirname)
ensuredir(path.dirname(doctree_filename))
f = open(doctree_filename, 'wb')
try:
pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL)

125
sphinx/io.py Normal file
View File

@ -0,0 +1,125 @@
# -*- coding: utf-8 -*-
"""
sphinx.io
~~~~~~~~~
Input/Output files
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from docutils.io import FileInput
from docutils.readers import standalone
from docutils.writers import UnfilteredWriter
from six import string_types, text_type
from sphinx.transforms import ApplySourceWorkaround, ExtraTranslatableNodes, Locale, \
CitationReferences, DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks, \
AutoNumbering, SortIds, RemoveTranslatableInline
from sphinx.util import import_object, split_docinfo
class SphinxBaseReader(standalone.Reader):
"""
Add our source parsers
"""
def __init__(self, app, parsers={}, *args, **kwargs):
standalone.Reader.__init__(self, *args, **kwargs)
self.parser_map = {}
for suffix, parser_class in parsers.items():
if isinstance(parser_class, string_types):
parser_class = import_object(parser_class, 'source parser')
parser = parser_class()
if hasattr(parser, 'set_application'):
parser.set_application(app)
self.parser_map[suffix] = parser
def read(self, source, parser, settings):
self.source = source
for suffix in self.parser_map:
if source.source_path.endswith(suffix):
self.parser = self.parser_map[suffix]
break
if not self.parser:
self.parser = parser
self.settings = settings
self.input = self.source.read()
self.parse()
return self.document
def get_transforms(self):
return standalone.Reader.get_transforms(self) + self.transforms
class SphinxStandaloneReader(SphinxBaseReader):
"""
Add our own transforms.
"""
transforms = [ApplySourceWorkaround, ExtraTranslatableNodes, Locale, CitationReferences,
DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks,
AutoNumbering, SortIds, RemoveTranslatableInline]
class SphinxI18nReader(SphinxBaseReader):
"""
Replacer for document.reporter.get_source_and_line method.
reST text lines for translation do not have the original source line number.
This class provides the correct line numbers when reporting.
"""
transforms = [ApplySourceWorkaround, ExtraTranslatableNodes, CitationReferences,
DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks,
AutoNumbering, SortIds, RemoveTranslatableInline]
def __init__(self, *args, **kwargs):
SphinxBaseReader.__init__(self, *args, **kwargs)
self.lineno = None
def set_lineno_for_reporter(self, lineno):
self.lineno = lineno
def new_document(self):
document = SphinxBaseReader.new_document(self)
reporter = document.reporter
def get_source_and_line(lineno=None):
return reporter.source, self.lineno
reporter.get_source_and_line = get_source_and_line
return document
class SphinxDummyWriter(UnfilteredWriter):
supported = ('html',) # needed to keep "meta" nodes
def translate(self):
pass
class SphinxFileInput(FileInput):
def __init__(self, app, env, *args, **kwds):
self.app = app
self.env = env
kwds['error_handler'] = 'sphinx' # py3: handle error on open.
FileInput.__init__(self, *args, **kwds)
def decode(self, data):
if isinstance(data, text_type): # py3: `data` already decoded.
return data
return data.decode(self.encoding, 'sphinx') # py2: decoding
def read(self):
data = FileInput.read(self)
if self.app:
arg = [data]
self.app.emit('source-read', self.env.docname, arg)
data = arg[0]
docinfo, data = split_docinfo(data)
if self.env.config.rst_epilog:
data = data + '\n' + self.env.config.rst_epilog + '\n'
if self.env.config.rst_prolog:
data = self.env.config.rst_prolog + '\n' + data
return docinfo + data

View File

@ -9,6 +9,7 @@
:license: BSD, see LICENSE for details.
"""
from __future__ import print_function
from __future__ import absolute_import
import re
import os

View File

@ -12,8 +12,8 @@
from os import path
from docutils import nodes
from docutils.utils import new_document, relative_path
from docutils.parsers.rst import Parser as RSTParser
from docutils.io import StringInput
from docutils.utils import relative_path
from docutils.transforms import Transform
from docutils.transforms.parts import ContentsFilter
@ -202,21 +202,35 @@ class ExtraTranslatableNodes(Transform):
node['translatable'] = True
class CustomLocaleReporter(object):
def publish_msgstr(app, source, source_path, source_line, config, settings):
"""Publish msgstr (single line) into docutils document
:param sphinx.application.Sphinx app: sphinx application
:param unicode source: source text
:param unicode source_path: source path for warning indication
:param source_line: source line for warning indication
:param sphinx.config.Config config: sphinx config
:param docutils.frontend.Values settings: docutils settings
:return: document
:rtype: docutils.nodes.document
"""
Replacer for document.reporter.get_source_and_line method.
reST text lines for translation do not have the original source line number.
This class provides the correct line numbers when reporting.
"""
def __init__(self, source, line):
self.source, self.line = source, line
def set_reporter(self, document):
document.reporter.get_source_and_line = self.get_source_and_line
def get_source_and_line(self, lineno=None):
return self.source, self.line
from sphinx.io import SphinxI18nReader
reader = SphinxI18nReader(
app=app,
parsers=config.source_parsers,
parser_name='restructuredtext', # default parser
)
reader.set_lineno_for_reporter(source_line)
doc = reader.read(
source=StringInput(source=source, source_path=source_path),
parser=reader.parser,
settings=settings,
)
try:
doc = doc[0]
except IndexError: # empty node
pass
return doc
class Locale(Transform):
@ -244,8 +258,6 @@ class Locale(Transform):
if not has_catalog:
return
parser = RSTParser()
# phase1: replace reference ids with translated names
for node, msg in extract_messages(self.document):
msgstr = catalog.gettext(msg)
@ -267,13 +279,8 @@ class Locale(Transform):
if isinstance(node, LITERAL_TYPE_NODES):
msgstr = '::\n\n' + indent(msgstr, ' '*3)
patch = new_document(source, settings)
CustomLocaleReporter(node.source, node.line).set_reporter(patch)
parser.parse(msgstr, patch)
try:
patch = patch[0]
except IndexError: # empty node
pass
patch = publish_msgstr(
env.app, msgstr, source, node.line, env.config, settings)
# XXX doctest and other block markup
if not isinstance(patch, nodes.paragraph):
continue # skip for now
@ -390,13 +397,8 @@ class Locale(Transform):
if isinstance(node, LITERAL_TYPE_NODES):
msgstr = '::\n\n' + indent(msgstr, ' '*3)
patch = new_document(source, settings)
CustomLocaleReporter(node.source, node.line).set_reporter(patch)
parser.parse(msgstr, patch)
try:
patch = patch[0]
except IndexError: # empty node
pass
patch = publish_msgstr(
env.app, msgstr, source, node.line, env.config, settings)
# XXX doctest and other block markup
if not isinstance(
patch,

View File

@ -141,9 +141,10 @@ def find_source_node(node):
return pnode.source
def traverse_parent(node):
def traverse_parent(node, cls=None):
while node:
yield node
if cls is None or isinstance(node, cls):
yield node
node = node.parent

View File

@ -25,7 +25,7 @@ from sphinx import highlighting
from sphinx.errors import SphinxError
from sphinx.locale import admonitionlabels, _
from sphinx.util import split_into
from sphinx.util.nodes import clean_astext
from sphinx.util.nodes import clean_astext, traverse_parent
from sphinx.util.osutil import ustrftime
from sphinx.util.texescape import tex_escape_map, tex_replace_map
from sphinx.util.smartypants import educate_quotes_latex
@ -174,11 +174,15 @@ class ShowUrlsTransform(object):
if node.astext() != uri:
index = node.parent.index(node)
if show_urls == 'footnote':
footnote_nodes = self.create_footnote(uri)
for i, fn in enumerate(footnote_nodes):
node.parent.insert(index + i + 1, fn)
if list(traverse_parent(node, nodes.topic)):
# should not expand references in topics
pass
else:
footnote_nodes = self.create_footnote(uri)
for i, fn in enumerate(footnote_nodes):
node.parent.insert(index + i + 1, fn)
self.expanded = True
self.expanded = True
else: # all other true values (b/w compat)
textnode = nodes.Text(" (%s)" % uri)
node.parent.insert(index + 1, textnode)
@ -210,9 +214,14 @@ class ShowUrlsTransform(object):
def is_auto_footnote(node):
return isinstance(node, nodes.footnote) and node.get('auto')
def footnote_ref_by(ids):
def footnote_ref_by(node):
ids = node['ids']
parent = list(traverse_parent(node, (nodes.document, addnodes.start_of_file)))[0]
def is_footnote_ref(node):
return isinstance(node, nodes.footnote_reference) and ids[0] == node['refid']
return (isinstance(node, nodes.footnote_reference) and
ids[0] == node['refid'] and
parent in list(traverse_parent(node)))
return is_footnote_ref
@ -231,7 +240,7 @@ class ShowUrlsTransform(object):
footnote['names'].remove(old_label)
footnote['names'].append(label)
for footnote_ref in self.document.traverse(footnote_ref_by(footnote['ids'])):
for footnote_ref in self.document.traverse(footnote_ref_by(footnote)):
footnote_ref.remove(footnote_ref[0])
footnote_ref += nodes.Text(label)
@ -378,12 +387,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
return '\\usepackage{%s}' % (packagename,)
usepackages = (declare_package(*p) for p in builder.usepackages)
self.elements['usepackages'] += "\n".join(usepackages)
if getattr(document.settings, 'contentsname', None):
self.elements['contentsname'] = \
self.babel_renewcommand('\\contentsname', document.settings.contentsname)
self.elements['pageautorefname'] = \
self.babel_defmacro('\\pageautorefname', self.encode(_('page')))
self.elements['numfig_format'] = self.generate_numfig_format(builder)
# allow the user to override them all
self.elements.update(builder.config.latex_elements)
if self.elements['extraclassoptions']:
@ -396,6 +399,12 @@ class LaTeXTranslator(nodes.NodeVisitor):
else:
self.elements['tocdepth'] = ('\\setcounter{tocdepth}{%d}' %
(document['tocdepth'] - 1))
if getattr(document.settings, 'contentsname', None):
self.elements['contentsname'] = \
self.babel_renewcommand('\\contentsname', document.settings.contentsname)
self.elements['pageautorefname'] = \
self.babel_defmacro('\\pageautorefname', self.encode(_('page')))
self.elements['numfig_format'] = self.generate_numfig_format(builder)
self.highlighter = highlighting.PygmentsBridge(
'latex',

View File

@ -0,0 +1,6 @@
bar
===
Same footnote number [1]_ in bar.rst
.. [1] footnote in bar

View File

@ -0,0 +1,6 @@
baz
===
Auto footnote number [#]_ in baz.rst
.. [#] footnote in baz

View File

@ -2,6 +2,14 @@
test-footenotes
===============
.. toctree::
bar
baz
.. contents::
:local:
The section with a reference to [AuthorYear]_
=============================================

View File

@ -264,6 +264,25 @@ def test_numref_with_language_ja(app, status, warning):
assert '\\hyperref[baz:code22]{Code-\\ref{baz:code22}}' in result
@with_app(buildername='latex', testroot='numfig',
confoverrides={'numfig': True, 'language': 'ru', 'latex_elements': {'babel': ''}})
def test_numref_on_bable_disabled(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
print(result)
print(status.getvalue())
print(warning.getvalue())
assert '\\renewcommand{\\figurename}{Fig. }' in result
assert '\\renewcommand{\\tablename}{Table }' in result
assert '\\SetupFloatingEnvironment{literal-block}{name=Listing }' in result
assert '\\hyperref[index:fig1]{Fig. \\ref{index:fig1}}' in result
assert '\\hyperref[baz:fig22]{Figure\\ref{baz:fig22}}' in result
assert '\\hyperref[index:table-1]{Table \\ref{index:table-1}}' in result
assert '\\hyperref[baz:table22]{Table:\\ref{baz:table22}}' in result
assert '\\hyperref[index:code-1]{Listing \\ref{index:code-1}}' in result
assert '\\hyperref[baz:code22]{Code-\\ref{baz:code22}}' in result
@with_app(buildername='latex')
def test_latex_add_latex_package(app, status, warning):
app.add_latex_package('foo')
@ -423,6 +442,15 @@ def test_latex_show_urls_is_inline(app, status, warning):
print(result)
print(status.getvalue())
print(warning.getvalue())
assert 'Same footnote number \\footnote[1]{\nfootnote in bar\n} in bar.rst' in result
assert 'Auto footnote number \\footnote[1]{\nfootnote in baz\n} in baz.rst' in result
assert ('\\phantomsection\\label{index:id26}{\\hyperref[index:the\\string-section'
'\\string-with\\string-a\\string-reference\\string-to\\string-authoryear]'
'{\\emph{The section with a reference to \\phantomsection\\label{index:id1}'
'{\\hyperref[index:authoryear]{\\emph{{[}AuthorYear{]}}}}}}}' in result)
assert ('\\phantomsection\\label{index:id27}{\\hyperref[index:the\\string-section'
'\\string-with\\string-a\\string-reference\\string-to]{\\emph{The section '
'with a reference to }}}' in result)
assert 'First footnote: \\footnote[2]{\nFirst\n}' in result
assert 'Second footnote: \\footnote[1]{\nSecond\n}' in result
assert '\\href{http://sphinx-doc.org/}{Sphinx} (http://sphinx-doc.org/)' in result
@ -449,20 +477,29 @@ def test_latex_show_urls_is_footnote(app, status, warning):
print(result)
print(status.getvalue())
print(warning.getvalue())
assert 'First footnote: \\footnote[2]{\nFirst\n}' in result
assert 'Same footnote number \\footnote[1]{\nfootnote in bar\n} in bar.rst' in result
assert 'Auto footnote number \\footnote[2]{\nfootnote in baz\n} in baz.rst' in result
assert ('\\phantomsection\\label{index:id26}{\\hyperref[index:the\\string-section'
'\\string-with\\string-a\\string-reference\\string-to\\string-authoryear]'
'{\\emph{The section with a reference to \\phantomsection\\label{index:id1}'
'{\\hyperref[index:authoryear]{\\emph{{[}AuthorYear{]}}}}}}}' in result)
assert ('\\phantomsection\\label{index:id27}{\\hyperref[index:the\\string-section'
'\\string-with\\string-a\\string-reference\\string-to]{\\emph{The section '
'with a reference to }}}' in result)
assert 'First footnote: \\footnote[3]{\nFirst\n}' in result
assert 'Second footnote: \\footnote[1]{\nSecond\n}' in result
assert ('\\href{http://sphinx-doc.org/}{Sphinx}'
'\\footnote[3]{\nhttp://sphinx-doc.org/\n}' in result)
assert 'Third footnote: \\footnote[5]{\nThird\n}' in result
'\\footnote[4]{\nhttp://sphinx-doc.org/\n}' in result)
assert 'Third footnote: \\footnote[6]{\nThird\n}' in result
assert ('\\href{http://sphinx-doc.org/~test/}{URL including tilde}'
'\\footnote[4]{\nhttp://sphinx-doc.org/\\textasciitilde{}test/\n}' in result)
assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term}\\protect\\footnotemark[7]}] '
'\\leavevmode\\footnotetext[7]{\nhttp://sphinx-doc.org/\n}\nDescription' in result)
assert ('\\item[{Footnote in term \\protect\\footnotemark[9]}] '
'\\leavevmode\\footnotetext[9]{\nFootnote in term\n}\nDescription' in result)
assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist}\\protect'
'\\footnotemark[8]}] '
'\\footnote[5]{\nhttp://sphinx-doc.org/\\textasciitilde{}test/\n}' in result)
assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term}\\protect\\footnotemark[8]}] '
'\\leavevmode\\footnotetext[8]{\nhttp://sphinx-doc.org/\n}\nDescription' in result)
assert ('\\item[{Footnote in term \\protect\\footnotemark[10]}] '
'\\leavevmode\\footnotetext[10]{\nFootnote in term\n}\nDescription' in result)
assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist}\\protect'
'\\footnotemark[9]}] '
'\\leavevmode\\footnotetext[9]{\nhttp://sphinx-doc.org/\n}\nDescription' in result)
assert ('\\href{https://github.com/sphinx-doc/sphinx}'
'{https://github.com/sphinx-doc/sphinx}\n' in result)
assert ('\\href{mailto:sphinx-dev@googlegroups.com}'
@ -477,6 +514,15 @@ def test_latex_show_urls_is_no(app, status, warning):
print(result)
print(status.getvalue())
print(warning.getvalue())
assert 'Same footnote number \\footnote[1]{\nfootnote in bar\n} in bar.rst' in result
assert 'Auto footnote number \\footnote[1]{\nfootnote in baz\n} in baz.rst' in result
assert ('\\phantomsection\\label{index:id26}{\\hyperref[index:the\\string-section'
'\\string-with\\string-a\\string-reference\\string-to\\string-authoryear]'
'{\\emph{The section with a reference to \\phantomsection\\label{index:id1}'
'{\\hyperref[index:authoryear]{\\emph{{[}AuthorYear{]}}}}}}}' in result)
assert ('\\phantomsection\\label{index:id27}{\\hyperref[index:the\\string-section'
'\\string-with\\string-a\\string-reference\\string-to]{\\emph{The section '
'with a reference to }}}' in result)
assert 'First footnote: \\footnote[2]{\nFirst\n}' in result
assert 'Second footnote: \\footnote[1]{\nSecond\n}' in result
assert '\\href{http://sphinx-doc.org/}{Sphinx}' in result