diff options
| -rw-r--r-- | sphinx/io.py | 10 | ||||
| -rw-r--r-- | sphinx/transforms/__init__.py | 223 | ||||
| -rw-r--r-- | sphinx/transforms/i18n.py (renamed from sphinx/transforms.py) | 218 |
3 files changed, 235 insertions, 216 deletions
diff --git a/sphinx/io.py b/sphinx/io.py index 2b965b805..7f6ea2c59 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -14,10 +14,12 @@ from docutils.writers import UnfilteredWriter from six import string_types, text_type from sphinx.transforms import ( - ApplySourceWorkaround, ExtraTranslatableNodes, PreserveTranslatableMessages, Locale, - CitationReferences, DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks, - AutoNumbering, AutoIndexUpgrader, SortIds, RemoveTranslatableInline, - FilterSystemMessages + ApplySourceWorkaround, ExtraTranslatableNodes, CitationReferences, + DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks, SortIds, + AutoNumbering, AutoIndexUpgrader, FilterSystemMessages, +) +from sphinx.transforms.i18n import ( + PreserveTranslatableMessages, Locale, RemoveTranslatableInline, ) from sphinx.util import import_object, split_docinfo diff --git a/sphinx/transforms/__init__.py b/sphinx/transforms/__init__.py new file mode 100644 index 000000000..79ac99c9f --- /dev/null +++ b/sphinx/transforms/__init__.py @@ -0,0 +1,223 @@ +# -*- coding: utf-8 -*- +""" + sphinx.transforms + ~~~~~~~~~~~~~~~~~ + + Docutils transforms used by Sphinx when reading documents. + + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +from docutils import nodes +from docutils.transforms import Transform +from docutils.transforms.parts import ContentsFilter + +from sphinx import addnodes +from sphinx.locale import _ +from sphinx.util.i18n import format_date +from sphinx.util.nodes import apply_source_workaround + +default_substitutions = set([ + 'version', + 'release', + 'today', +]) + + +class DefaultSubstitutions(Transform): + """ + Replace some substitutions if they aren't defined in the document. + """ + # run before the default Substitutions + default_priority = 210 + + def apply(self): + env = self.document.settings.env + config = self.document.settings.env.config + # only handle those not otherwise defined in the document + to_handle = default_substitutions - set(self.document.substitution_defs) + for ref in self.document.traverse(nodes.substitution_reference): + refname = ref['refname'] + if refname in to_handle: + text = config[refname] + if refname == 'today' and not text: + # special handling: can also specify a strftime format + text = format_date(config.today_fmt or _('%b %d, %Y'), + language=config.language, warn=env.warn) + ref.replace_self(nodes.Text(text, text)) + + +class MoveModuleTargets(Transform): + """ + Move module targets that are the first thing in a section to the section + title. + + XXX Python specific + """ + default_priority = 210 + + def apply(self): + for node in self.document.traverse(nodes.target): + if not node['ids']: + continue + if ('ismod' in node and + node.parent.__class__ is nodes.section and + # index 0 is the section title node + node.parent.index(node) == 1): + node.parent['ids'][0:0] = node['ids'] + node.parent.remove(node) + + +class HandleCodeBlocks(Transform): + """ + Several code block related transformations. + """ + default_priority = 210 + + def apply(self): + # move doctest blocks out of blockquotes + for node in self.document.traverse(nodes.block_quote): + if all(isinstance(child, nodes.doctest_block) for child + in node.children): + node.replace_self(node.children) + # combine successive doctest blocks + # for node in self.document.traverse(nodes.doctest_block): + # if node not in node.parent.children: + # continue + # parindex = node.parent.index(node) + # while len(node.parent) > parindex+1 and \ + # isinstance(node.parent[parindex+1], nodes.doctest_block): + # node[0] = nodes.Text(node[0] + '\n\n' + + # node.parent[parindex+1][0]) + # del node.parent[parindex+1] + + +class AutoNumbering(Transform): + """ + Register IDs of tables, figures and literal_blocks to assign numbers. + """ + default_priority = 210 + + def apply(self): + domain = self.document.settings.env.domains['std'] + + for node in self.document.traverse(nodes.Element): + if domain.is_enumerable_node(node) and domain.get_numfig_title(node) is not None: + self.document.note_implicit_target(node) + + +class SortIds(Transform): + """ + Sort secion IDs so that the "id[0-9]+" one comes last. + """ + default_priority = 261 + + def apply(self): + for node in self.document.traverse(nodes.section): + if len(node['ids']) > 1 and node['ids'][0].startswith('id'): + node['ids'] = node['ids'][1:] + [node['ids'][0]] + + +class CitationReferences(Transform): + """ + Replace citation references by pending_xref nodes before the default + docutils transform tries to resolve them. + """ + default_priority = 619 + + def apply(self): + for citnode in self.document.traverse(nodes.citation_reference): + cittext = citnode.astext() + refnode = addnodes.pending_xref(cittext, refdomain='std', reftype='citation', + reftarget=cittext, refwarn=True, + ids=citnode["ids"]) + refnode.source = citnode.source or citnode.parent.source + refnode.line = citnode.line or citnode.parent.line + refnode += nodes.Text('[' + cittext + ']') + citnode.parent.replace(citnode, refnode) + + +TRANSLATABLE_NODES = { + 'literal-block': nodes.literal_block, + 'doctest-block': nodes.doctest_block, + 'raw': nodes.raw, + 'index': addnodes.index, + 'image': nodes.image, +} + + +class ApplySourceWorkaround(Transform): + """ + update source and rawsource attributes + """ + default_priority = 10 + + def apply(self): + for n in self.document.traverse(): + if isinstance(n, nodes.TextElement): + apply_source_workaround(n) + + +class AutoIndexUpgrader(Transform): + """ + Detect old style; 4 column based indices and automatically upgrade to new style. + """ + default_priority = 210 + + def apply(self): + env = self.document.settings.env + for node in self.document.traverse(addnodes.index): + if 'entries' in node and any(len(entry) == 4 for entry in node['entries']): + msg = ('4 column based index found. ' + 'It might be a bug of extensions you use: %r' % node['entries']) + env.warn_node(msg, node) + for i, entry in enumerate(node['entries']): + if len(entry) == 4: + node['entries'][i] = entry + (None,) + + +class ExtraTranslatableNodes(Transform): + """ + make nodes translatable + """ + default_priority = 10 + + def apply(self): + targets = self.document.settings.env.config.gettext_additional_targets + target_nodes = [v for k, v in TRANSLATABLE_NODES.items() if k in targets] + if not target_nodes: + return + + def is_translatable_node(node): + return isinstance(node, tuple(target_nodes)) + + for node in self.document.traverse(is_translatable_node): + node['translatable'] = True + + +class FilterSystemMessages(Transform): + """Filter system messages from a doctree.""" + default_priority = 999 + + def apply(self): + env = self.document.settings.env + filterlevel = env.config.keep_warnings and 2 or 5 + for node in self.document.traverse(nodes.system_message): + if node['level'] < filterlevel: + env.app.debug('%s [filtered system message]', node.astext()) + node.parent.remove(node) + + +class SphinxContentsFilter(ContentsFilter): + """ + Used with BuildEnvironment.add_toc_from() to discard cross-file links + within table-of-contents link nodes. + """ + def visit_pending_xref(self, node): + text = node.astext() + self.parent.append(nodes.literal(text, text)) + raise nodes.SkipNode + + def visit_image(self, node): + raise nodes.SkipNode diff --git a/sphinx/transforms.py b/sphinx/transforms/i18n.py index 516b22843..38c5aef25 100644 --- a/sphinx/transforms.py +++ b/sphinx/transforms/i18n.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """ - sphinx.transforms - ~~~~~~~~~~~~~~~~~ + sphinx.transforms.i18n + ~~~~~~~~~~~~~~~~~~~~~~ Docutils transforms used by Sphinx when reading documents. @@ -15,198 +15,19 @@ from docutils import nodes from docutils.io import StringInput from docutils.utils import relative_path from docutils.transforms import Transform -from docutils.transforms.parts import ContentsFilter from sphinx import addnodes -from sphinx.locale import _, init as init_locale from sphinx.util import split_index_msg +from sphinx.util.i18n import find_catalog from sphinx.util.nodes import ( - traverse_translatable_index, extract_messages, LITERAL_TYPE_NODES, IMAGE_TYPE_NODES, - apply_source_workaround, is_pending_meta, + LITERAL_TYPE_NODES, IMAGE_TYPE_NODES, + extract_messages, is_pending_meta, traverse_translatable_index, ) -from sphinx.util.i18n import find_catalog, format_date from sphinx.util.pycompat import indent +from sphinx.locale import init as init_locale from sphinx.domains.std import make_glossary_term, split_term_classifiers -default_substitutions = set([ - 'version', - 'release', - 'today', -]) - - -class DefaultSubstitutions(Transform): - """ - Replace some substitutions if they aren't defined in the document. - """ - # run before the default Substitutions - default_priority = 210 - - def apply(self): - env = self.document.settings.env - config = self.document.settings.env.config - # only handle those not otherwise defined in the document - to_handle = default_substitutions - set(self.document.substitution_defs) - for ref in self.document.traverse(nodes.substitution_reference): - refname = ref['refname'] - if refname in to_handle: - text = config[refname] - if refname == 'today' and not text: - # special handling: can also specify a strftime format - text = format_date(config.today_fmt or _('%b %d, %Y'), - language=config.language, warn=env.warn) - ref.replace_self(nodes.Text(text, text)) - - -class MoveModuleTargets(Transform): - """ - Move module targets that are the first thing in a section to the section - title. - - XXX Python specific - """ - default_priority = 210 - - def apply(self): - for node in self.document.traverse(nodes.target): - if not node['ids']: - continue - if ('ismod' in node and - node.parent.__class__ is nodes.section and - # index 0 is the section title node - node.parent.index(node) == 1): - node.parent['ids'][0:0] = node['ids'] - node.parent.remove(node) - - -class HandleCodeBlocks(Transform): - """ - Several code block related transformations. - """ - default_priority = 210 - - def apply(self): - # move doctest blocks out of blockquotes - for node in self.document.traverse(nodes.block_quote): - if all(isinstance(child, nodes.doctest_block) for child - in node.children): - node.replace_self(node.children) - # combine successive doctest blocks - # for node in self.document.traverse(nodes.doctest_block): - # if node not in node.parent.children: - # continue - # parindex = node.parent.index(node) - # while len(node.parent) > parindex+1 and \ - # isinstance(node.parent[parindex+1], nodes.doctest_block): - # node[0] = nodes.Text(node[0] + '\n\n' + - # node.parent[parindex+1][0]) - # del node.parent[parindex+1] - - -class AutoNumbering(Transform): - """ - Register IDs of tables, figures and literal_blocks to assign numbers. - """ - default_priority = 210 - - def apply(self): - domain = self.document.settings.env.domains['std'] - - for node in self.document.traverse(nodes.Element): - if domain.is_enumerable_node(node) and domain.get_numfig_title(node) is not None: - self.document.note_implicit_target(node) - - -class SortIds(Transform): - """ - Sort secion IDs so that the "id[0-9]+" one comes last. - """ - default_priority = 261 - - def apply(self): - for node in self.document.traverse(nodes.section): - if len(node['ids']) > 1 and node['ids'][0].startswith('id'): - node['ids'] = node['ids'][1:] + [node['ids'][0]] - - -class CitationReferences(Transform): - """ - Replace citation references by pending_xref nodes before the default - docutils transform tries to resolve them. - """ - default_priority = 619 - - def apply(self): - for citnode in self.document.traverse(nodes.citation_reference): - cittext = citnode.astext() - refnode = addnodes.pending_xref(cittext, refdomain='std', reftype='citation', - reftarget=cittext, refwarn=True, - ids=citnode["ids"]) - refnode.source = citnode.source or citnode.parent.source - refnode.line = citnode.line or citnode.parent.line - refnode += nodes.Text('[' + cittext + ']') - citnode.parent.replace(citnode, refnode) - - -TRANSLATABLE_NODES = { - 'literal-block': nodes.literal_block, - 'doctest-block': nodes.doctest_block, - 'raw': nodes.raw, - 'index': addnodes.index, - 'image': nodes.image, -} - - -class ApplySourceWorkaround(Transform): - """ - update source and rawsource attributes - """ - default_priority = 10 - - def apply(self): - for n in self.document.traverse(): - if isinstance(n, nodes.TextElement): - apply_source_workaround(n) - - -class AutoIndexUpgrader(Transform): - """ - Detect old style; 4 column based indices and automatically upgrade to new style. - """ - default_priority = 210 - - def apply(self): - env = self.document.settings.env - for node in self.document.traverse(addnodes.index): - if 'entries' in node and any(len(entry) == 4 for entry in node['entries']): - msg = ('4 column based index found. ' - 'It might be a bug of extensions you use: %r' % node['entries']) - env.warn_node(msg, node) - for i, entry in enumerate(node['entries']): - if len(entry) == 4: - node['entries'][i] = entry + (None,) - - -class ExtraTranslatableNodes(Transform): - """ - make nodes translatable - """ - default_priority = 10 - - def apply(self): - targets = self.document.settings.env.config.gettext_additional_targets - target_nodes = [v for k, v in TRANSLATABLE_NODES.items() if k in targets] - if not target_nodes: - return - - def is_translatable_node(node): - return isinstance(node, tuple(target_nodes)) - - for node in self.document.traverse(is_translatable_node): - node['translatable'] = True - - def publish_msgstr(app, source, source_path, source_line, config, settings): """Publish msgstr (single line) into docutils document @@ -249,19 +70,6 @@ class PreserveTranslatableMessages(Transform): node.preserve_original_messages() -class FilterSystemMessages(Transform): - """Filter system messages from a doctree.""" - default_priority = 999 - - def apply(self): - env = self.document.settings.env - filterlevel = env.config.keep_warnings and 2 or 5 - for node in self.document.traverse(nodes.system_message): - if node['level'] < filterlevel: - env.app.debug('%s [filtered system message]', node.astext()) - node.parent.remove(node) - - class Locale(Transform): """ Replace translatable nodes with their translated doctree. @@ -608,17 +416,3 @@ class RemoveTranslatableInline(Transform): if 'translatable' in inline: inline.parent.remove(inline) inline.parent += inline.children - - -class SphinxContentsFilter(ContentsFilter): - """ - Used with BuildEnvironment.add_toc_from() to discard cross-file links - within table-of-contents link nodes. - """ - def visit_pending_xref(self, node): - text = node.astext() - self.parent.append(nodes.literal(text, text)) - raise nodes.SkipNode - - def visit_image(self, node): - raise nodes.SkipNode |
