mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge with stable
Conflicts: sphinx/environment.py sphinx/ext/autodoc.py sphinx/writers/latex.py
This commit is contained in:
commit
980653f277
18
CHANGES
18
CHANGES
@ -85,9 +85,24 @@ Documentation
|
|||||||
Release 1.3.6 (in development)
|
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
|
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)
|
Release 1.3.5 (released Jan 24, 2016)
|
||||||
=====================================
|
=====================================
|
||||||
@ -103,7 +118,8 @@ Bugs fixed
|
|||||||
* #2243: Ignore strange docstring types for classes, do not crash
|
* #2243: Ignore strange docstring types for classes, do not crash
|
||||||
* #2247: Fix #2205 breaks make html for definition list with classifiers
|
* #2247: Fix #2205 breaks make html for definition list with classifiers
|
||||||
that contains regular-expression like string
|
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
|
* #2211: Fix paragraphs in table cell doesn't work in Latex output
|
||||||
* #2253: ``:pyobject:`` option of ``literalinclude`` directive can't detect indented
|
* #2253: ``:pyobject:`` option of ``literalinclude`` directive can't detect indented
|
||||||
body block when the block starts with blank or comment lines.
|
body block when the block starts with blank or comment lines.
|
||||||
|
13
doc/intl.rst
13
doc/intl.rst
@ -106,17 +106,23 @@ This section describe a easy way to translate with sphinx-intl.
|
|||||||
|
|
||||||
#. Translate your po files under `./locale/<lang>/LC_MESSAGES/`.
|
#. 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
|
You need a :confval:`language` parameter in ``conf.py`` or you may also
|
||||||
specify the parameter on the command line::
|
specify the parameter on the command line::
|
||||||
|
|
||||||
$ sphinx-intl build
|
|
||||||
$ make -e SPHINXOPTS="-D language='de'" html
|
$ make -e SPHINXOPTS="-D language='de'" html
|
||||||
|
|
||||||
Congratulations! You got the translated documentation in the ``_build/html``
|
Congratulations! You got the translated documentation in the ``_build/html``
|
||||||
directory.
|
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
|
Translating
|
||||||
^^^^^^^^^^^
|
^^^^^^^^^^^
|
||||||
@ -251,9 +257,8 @@ easy to fetch and push translations.
|
|||||||
...
|
...
|
||||||
Done.
|
Done.
|
||||||
|
|
||||||
Build po files into mo and make html::
|
Invoke make html::
|
||||||
|
|
||||||
$ sphinx-intl build
|
|
||||||
$ make -e SPHINXOPTS="-D language='de'" html
|
$ make -e SPHINXOPTS="-D language='de'" html
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,7 +35,8 @@ from sphinx.errors import SphinxError, SphinxWarning, ExtensionError, \
|
|||||||
from sphinx.domains import ObjType, BUILTIN_DOMAINS
|
from sphinx.domains import ObjType, BUILTIN_DOMAINS
|
||||||
from sphinx.domains.std import GenericObject, Target, StandardDomain
|
from sphinx.domains.std import GenericObject, Target, StandardDomain
|
||||||
from sphinx.builders import BUILTIN_BUILDERS
|
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 pycompat # noqa: imported for side-effects
|
||||||
from sphinx.util import import_object
|
from sphinx.util import import_object
|
||||||
from sphinx.util.tags import Tags
|
from sphinx.util.tags import Tags
|
||||||
|
@ -23,24 +23,23 @@ from os import path
|
|||||||
from glob import glob
|
from glob import glob
|
||||||
from itertools import groupby
|
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 six.moves import cPickle as pickle
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
from docutils.io import FileInput, NullOutput
|
from docutils.io import NullOutput
|
||||||
from docutils.core import Publisher
|
from docutils.core import Publisher
|
||||||
from docutils.utils import Reporter, relative_path, get_source_line
|
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 import roles, directives
|
||||||
from docutils.parsers.rst.languages import en as english
|
from docutils.parsers.rst.languages import en as english
|
||||||
from docutils.parsers.rst.directives.html import MetaBody
|
from docutils.parsers.rst.directives.html import MetaBody
|
||||||
from docutils.writers import UnfilteredWriter
|
|
||||||
from docutils.frontend import OptionParser
|
from docutils.frontend import OptionParser
|
||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
|
from sphinx.io import SphinxStandaloneReader, SphinxDummyWriter, SphinxFileInput
|
||||||
from sphinx.util import url_re, get_matching_docs, docname_join, split_into, \
|
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.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.i18n import find_catalog_files
|
||||||
from sphinx.util.console import bold, purple
|
from sphinx.util.console import bold, purple
|
||||||
from sphinx.util.matching import compile_matchers
|
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.errors import SphinxError, ExtensionError
|
||||||
from sphinx.locale import _
|
from sphinx.locale import _
|
||||||
from sphinx.versioning import add_uids, merge_doctrees
|
from sphinx.versioning import add_uids, merge_doctrees
|
||||||
from sphinx.transforms import (
|
from sphinx.transforms import SphinxContentsFilter
|
||||||
DefaultSubstitutions, MoveModuleTargets, ApplySourceWorkaround,
|
|
||||||
HandleCodeBlocks, AutoNumbering, SortIds, CitationReferences, Locale,
|
|
||||||
RemoveTranslatableInline, SphinxContentsFilter, ExtraTranslatableNodes,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
orig_role_function = roles.role
|
orig_role_function = roles.role
|
||||||
orig_directive_function = directives.directive
|
orig_directive_function = directives.directive
|
||||||
@ -97,77 +91,6 @@ class NoUri(Exception):
|
|||||||
pass
|
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:
|
class BuildEnvironment:
|
||||||
"""
|
"""
|
||||||
The environment in which the ReST files are translated.
|
The environment in which the ReST files are translated.
|
||||||
@ -859,9 +782,7 @@ class BuildEnvironment:
|
|||||||
# save the parsed doctree
|
# save the parsed doctree
|
||||||
doctree_filename = self.doc2path(docname, self.doctreedir,
|
doctree_filename = self.doc2path(docname, self.doctreedir,
|
||||||
'.doctree')
|
'.doctree')
|
||||||
dirname = path.dirname(doctree_filename)
|
ensuredir(path.dirname(doctree_filename))
|
||||||
if not path.isdir(dirname):
|
|
||||||
os.makedirs(dirname)
|
|
||||||
f = open(doctree_filename, 'wb')
|
f = open(doctree_filename, 'wb')
|
||||||
try:
|
try:
|
||||||
pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL)
|
pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL)
|
||||||
|
125
sphinx/io.py
Normal file
125
sphinx/io.py
Normal 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
|
@ -9,6 +9,7 @@
|
|||||||
:license: BSD, see LICENSE for details.
|
:license: BSD, see LICENSE for details.
|
||||||
"""
|
"""
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
|
@ -12,8 +12,8 @@
|
|||||||
from os import path
|
from os import path
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
from docutils.utils import new_document, relative_path
|
from docutils.io import StringInput
|
||||||
from docutils.parsers.rst import Parser as RSTParser
|
from docutils.utils import relative_path
|
||||||
from docutils.transforms import Transform
|
from docutils.transforms import Transform
|
||||||
from docutils.transforms.parts import ContentsFilter
|
from docutils.transforms.parts import ContentsFilter
|
||||||
|
|
||||||
@ -202,21 +202,35 @@ class ExtraTranslatableNodes(Transform):
|
|||||||
node['translatable'] = True
|
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.
|
from sphinx.io import SphinxI18nReader
|
||||||
|
reader = SphinxI18nReader(
|
||||||
reST text lines for translation do not have the original source line number.
|
app=app,
|
||||||
This class provides the correct line numbers when reporting.
|
parsers=config.source_parsers,
|
||||||
"""
|
parser_name='restructuredtext', # default parser
|
||||||
def __init__(self, source, line):
|
)
|
||||||
self.source, self.line = source, line
|
reader.set_lineno_for_reporter(source_line)
|
||||||
|
doc = reader.read(
|
||||||
def set_reporter(self, document):
|
source=StringInput(source=source, source_path=source_path),
|
||||||
document.reporter.get_source_and_line = self.get_source_and_line
|
parser=reader.parser,
|
||||||
|
settings=settings,
|
||||||
def get_source_and_line(self, lineno=None):
|
)
|
||||||
return self.source, self.line
|
try:
|
||||||
|
doc = doc[0]
|
||||||
|
except IndexError: # empty node
|
||||||
|
pass
|
||||||
|
return doc
|
||||||
|
|
||||||
|
|
||||||
class Locale(Transform):
|
class Locale(Transform):
|
||||||
@ -244,8 +258,6 @@ class Locale(Transform):
|
|||||||
if not has_catalog:
|
if not has_catalog:
|
||||||
return
|
return
|
||||||
|
|
||||||
parser = RSTParser()
|
|
||||||
|
|
||||||
# phase1: replace reference ids with translated names
|
# phase1: replace reference ids with translated names
|
||||||
for node, msg in extract_messages(self.document):
|
for node, msg in extract_messages(self.document):
|
||||||
msgstr = catalog.gettext(msg)
|
msgstr = catalog.gettext(msg)
|
||||||
@ -267,13 +279,8 @@ class Locale(Transform):
|
|||||||
if isinstance(node, LITERAL_TYPE_NODES):
|
if isinstance(node, LITERAL_TYPE_NODES):
|
||||||
msgstr = '::\n\n' + indent(msgstr, ' '*3)
|
msgstr = '::\n\n' + indent(msgstr, ' '*3)
|
||||||
|
|
||||||
patch = new_document(source, settings)
|
patch = publish_msgstr(
|
||||||
CustomLocaleReporter(node.source, node.line).set_reporter(patch)
|
env.app, msgstr, source, node.line, env.config, settings)
|
||||||
parser.parse(msgstr, patch)
|
|
||||||
try:
|
|
||||||
patch = patch[0]
|
|
||||||
except IndexError: # empty node
|
|
||||||
pass
|
|
||||||
# XXX doctest and other block markup
|
# XXX doctest and other block markup
|
||||||
if not isinstance(patch, nodes.paragraph):
|
if not isinstance(patch, nodes.paragraph):
|
||||||
continue # skip for now
|
continue # skip for now
|
||||||
@ -390,13 +397,8 @@ class Locale(Transform):
|
|||||||
if isinstance(node, LITERAL_TYPE_NODES):
|
if isinstance(node, LITERAL_TYPE_NODES):
|
||||||
msgstr = '::\n\n' + indent(msgstr, ' '*3)
|
msgstr = '::\n\n' + indent(msgstr, ' '*3)
|
||||||
|
|
||||||
patch = new_document(source, settings)
|
patch = publish_msgstr(
|
||||||
CustomLocaleReporter(node.source, node.line).set_reporter(patch)
|
env.app, msgstr, source, node.line, env.config, settings)
|
||||||
parser.parse(msgstr, patch)
|
|
||||||
try:
|
|
||||||
patch = patch[0]
|
|
||||||
except IndexError: # empty node
|
|
||||||
pass
|
|
||||||
# XXX doctest and other block markup
|
# XXX doctest and other block markup
|
||||||
if not isinstance(
|
if not isinstance(
|
||||||
patch,
|
patch,
|
||||||
|
@ -141,8 +141,9 @@ def find_source_node(node):
|
|||||||
return pnode.source
|
return pnode.source
|
||||||
|
|
||||||
|
|
||||||
def traverse_parent(node):
|
def traverse_parent(node, cls=None):
|
||||||
while node:
|
while node:
|
||||||
|
if cls is None or isinstance(node, cls):
|
||||||
yield node
|
yield node
|
||||||
node = node.parent
|
node = node.parent
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ from sphinx import highlighting
|
|||||||
from sphinx.errors import SphinxError
|
from sphinx.errors import SphinxError
|
||||||
from sphinx.locale import admonitionlabels, _
|
from sphinx.locale import admonitionlabels, _
|
||||||
from sphinx.util import split_into
|
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.osutil import ustrftime
|
||||||
from sphinx.util.texescape import tex_escape_map, tex_replace_map
|
from sphinx.util.texescape import tex_escape_map, tex_replace_map
|
||||||
from sphinx.util.smartypants import educate_quotes_latex
|
from sphinx.util.smartypants import educate_quotes_latex
|
||||||
@ -174,6 +174,10 @@ class ShowUrlsTransform(object):
|
|||||||
if node.astext() != uri:
|
if node.astext() != uri:
|
||||||
index = node.parent.index(node)
|
index = node.parent.index(node)
|
||||||
if show_urls == 'footnote':
|
if show_urls == 'footnote':
|
||||||
|
if list(traverse_parent(node, nodes.topic)):
|
||||||
|
# should not expand references in topics
|
||||||
|
pass
|
||||||
|
else:
|
||||||
footnote_nodes = self.create_footnote(uri)
|
footnote_nodes = self.create_footnote(uri)
|
||||||
for i, fn in enumerate(footnote_nodes):
|
for i, fn in enumerate(footnote_nodes):
|
||||||
node.parent.insert(index + i + 1, fn)
|
node.parent.insert(index + i + 1, fn)
|
||||||
@ -210,9 +214,14 @@ class ShowUrlsTransform(object):
|
|||||||
def is_auto_footnote(node):
|
def is_auto_footnote(node):
|
||||||
return isinstance(node, nodes.footnote) and node.get('auto')
|
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):
|
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
|
return is_footnote_ref
|
||||||
|
|
||||||
@ -231,7 +240,7 @@ class ShowUrlsTransform(object):
|
|||||||
footnote['names'].remove(old_label)
|
footnote['names'].remove(old_label)
|
||||||
footnote['names'].append(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.remove(footnote_ref[0])
|
||||||
footnote_ref += nodes.Text(label)
|
footnote_ref += nodes.Text(label)
|
||||||
|
|
||||||
@ -378,12 +387,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
return '\\usepackage{%s}' % (packagename,)
|
return '\\usepackage{%s}' % (packagename,)
|
||||||
usepackages = (declare_package(*p) for p in builder.usepackages)
|
usepackages = (declare_package(*p) for p in builder.usepackages)
|
||||||
self.elements['usepackages'] += "\n".join(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
|
# allow the user to override them all
|
||||||
self.elements.update(builder.config.latex_elements)
|
self.elements.update(builder.config.latex_elements)
|
||||||
if self.elements['extraclassoptions']:
|
if self.elements['extraclassoptions']:
|
||||||
@ -396,6 +399,12 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
else:
|
else:
|
||||||
self.elements['tocdepth'] = ('\\setcounter{tocdepth}{%d}' %
|
self.elements['tocdepth'] = ('\\setcounter{tocdepth}{%d}' %
|
||||||
(document['tocdepth'] - 1))
|
(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(
|
self.highlighter = highlighting.PygmentsBridge(
|
||||||
'latex',
|
'latex',
|
||||||
|
6
tests/roots/test-footnotes/bar.rst
Normal file
6
tests/roots/test-footnotes/bar.rst
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
bar
|
||||||
|
===
|
||||||
|
|
||||||
|
Same footnote number [1]_ in bar.rst
|
||||||
|
|
||||||
|
.. [1] footnote in bar
|
6
tests/roots/test-footnotes/baz.rst
Normal file
6
tests/roots/test-footnotes/baz.rst
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
baz
|
||||||
|
===
|
||||||
|
|
||||||
|
Auto footnote number [#]_ in baz.rst
|
||||||
|
|
||||||
|
.. [#] footnote in baz
|
@ -2,6 +2,14 @@
|
|||||||
test-footenotes
|
test-footenotes
|
||||||
===============
|
===============
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
|
||||||
|
bar
|
||||||
|
baz
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
:local:
|
||||||
|
|
||||||
The section with a reference to [AuthorYear]_
|
The section with a reference to [AuthorYear]_
|
||||||
=============================================
|
=============================================
|
||||||
|
|
||||||
|
@ -264,6 +264,25 @@ def test_numref_with_language_ja(app, status, warning):
|
|||||||
assert '\\hyperref[baz:code22]{Code-\\ref{baz:code22}}' in result
|
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')
|
@with_app(buildername='latex')
|
||||||
def test_latex_add_latex_package(app, status, warning):
|
def test_latex_add_latex_package(app, status, warning):
|
||||||
app.add_latex_package('foo')
|
app.add_latex_package('foo')
|
||||||
@ -423,6 +442,15 @@ def test_latex_show_urls_is_inline(app, status, warning):
|
|||||||
print(result)
|
print(result)
|
||||||
print(status.getvalue())
|
print(status.getvalue())
|
||||||
print(warning.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 'First footnote: \\footnote[2]{\nFirst\n}' in result
|
||||||
assert 'Second footnote: \\footnote[1]{\nSecond\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
|
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(result)
|
||||||
print(status.getvalue())
|
print(status.getvalue())
|
||||||
print(warning.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 'Second footnote: \\footnote[1]{\nSecond\n}' in result
|
||||||
assert ('\\href{http://sphinx-doc.org/}{Sphinx}'
|
assert ('\\href{http://sphinx-doc.org/}{Sphinx}'
|
||||||
'\\footnote[3]{\nhttp://sphinx-doc.org/\n}' in result)
|
'\\footnote[4]{\nhttp://sphinx-doc.org/\n}' in result)
|
||||||
assert 'Third footnote: \\footnote[5]{\nThird\n}' in result
|
assert 'Third footnote: \\footnote[6]{\nThird\n}' in result
|
||||||
assert ('\\href{http://sphinx-doc.org/~test/}{URL including tilde}'
|
assert ('\\href{http://sphinx-doc.org/~test/}{URL including tilde}'
|
||||||
'\\footnote[4]{\nhttp://sphinx-doc.org/\\textasciitilde{}test/\n}' in result)
|
'\\footnote[5]{\nhttp://sphinx-doc.org/\\textasciitilde{}test/\n}' in result)
|
||||||
assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term}\\protect\\footnotemark[7]}] '
|
assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term}\\protect\\footnotemark[8]}] '
|
||||||
'\\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]}] '
|
|
||||||
'\\leavevmode\\footnotetext[8]{\nhttp://sphinx-doc.org/\n}\nDescription' in result)
|
'\\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}'
|
assert ('\\href{https://github.com/sphinx-doc/sphinx}'
|
||||||
'{https://github.com/sphinx-doc/sphinx}\n' in result)
|
'{https://github.com/sphinx-doc/sphinx}\n' in result)
|
||||||
assert ('\\href{mailto:sphinx-dev@googlegroups.com}'
|
assert ('\\href{mailto:sphinx-dev@googlegroups.com}'
|
||||||
@ -477,6 +514,15 @@ def test_latex_show_urls_is_no(app, status, warning):
|
|||||||
print(result)
|
print(result)
|
||||||
print(status.getvalue())
|
print(status.getvalue())
|
||||||
print(warning.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 'First footnote: \\footnote[2]{\nFirst\n}' in result
|
||||||
assert 'Second footnote: \\footnote[1]{\nSecond\n}' in result
|
assert 'Second footnote: \\footnote[1]{\nSecond\n}' in result
|
||||||
assert '\\href{http://sphinx-doc.org/}{Sphinx}' in result
|
assert '\\href{http://sphinx-doc.org/}{Sphinx}' in result
|
||||||
|
Loading…
Reference in New Issue
Block a user