summaryrefslogtreecommitdiff
path: root/sphinx/util/nodes.py
diff options
context:
space:
mode:
Diffstat (limited to 'sphinx/util/nodes.py')
-rw-r--r--sphinx/util/nodes.py123
1 files changed, 76 insertions, 47 deletions
diff --git a/sphinx/util/nodes.py b/sphinx/util/nodes.py
index b7b5073d..c2b7edf4 100644
--- a/sphinx/util/nodes.py
+++ b/sphinx/util/nodes.py
@@ -10,12 +10,11 @@
"""
import re
-import types
from docutils import nodes
-from docutils.statemachine import StateMachine
from sphinx import addnodes
+from sphinx.locale import pairindextypes
class WarningStream(object):
@@ -34,8 +33,38 @@ class WarningStream(object):
explicit_title_re = re.compile(r'^(.+?)\s*(?<!\x00)<(.*?)>$', re.DOTALL)
caption_ref_re = explicit_title_re # b/w compat alias
+IGNORED_NODES = (
+ nodes.Invisible,
+ nodes.Inline,
+ nodes.literal_block,
+ nodes.doctest_block,
+ #XXX there are probably more
+)
+def extract_messages(doctree):
+ """Extract translatable messages from a document tree."""
+ for node in doctree.traverse(nodes.TextElement):
+ if not node.source:
+ continue # built-in message
+ if isinstance(node, IGNORED_NODES):
+ continue
+ # <field_name>orphan</field_name>
+ # XXX ignore all metadata (== docinfo)
+ if isinstance(node, nodes.field_name) and node.children[0] == 'orphan':
+ continue
+
+ msg = node.rawsource.replace('\n', ' ').strip()
+ # XXX nodes rendering empty are likely a bug in sphinx.addnodes
+ if msg:
+ yield node, msg
+
def nested_parse_with_titles(state, content, node):
+ """Version of state.nested_parse() that allows titles and does not require
+ titles to have the same decoration as the calling document.
+
+ This is useful when the parsed content comes from a completely different
+ context, such as docstrings.
+ """
# hack around title style bookkeeping
surrounding_title_styles = state.memo.title_styles
surrounding_section_level = state.memo.section_level
@@ -64,6 +93,46 @@ def split_explicit_title(text):
return False, text, text
+indextypes = [
+ 'single', 'pair', 'double', 'triple', 'see', 'seealso',
+]
+
+def process_index_entry(entry, targetid):
+ indexentries = []
+ entry = entry.strip()
+ oentry = entry
+ main = ''
+ if entry.startswith('!'):
+ main = 'main'
+ entry = entry[1:].lstrip()
+ for type in pairindextypes:
+ if entry.startswith(type+':'):
+ value = entry[len(type)+1:].strip()
+ value = pairindextypes[type] + '; ' + value
+ indexentries.append(('pair', value, targetid, main))
+ break
+ else:
+ for type in indextypes:
+ if entry.startswith(type+':'):
+ value = entry[len(type)+1:].strip()
+ if type == 'double':
+ type = 'pair'
+ indexentries.append((type, value, targetid, main))
+ break
+ # shorthand notation for single entries
+ else:
+ for value in oentry.split(','):
+ value = value.strip()
+ main = ''
+ if value.startswith('!'):
+ main = 'main'
+ value = value[1:].lstrip()
+ if not value:
+ continue
+ indexentries.append(('single', value, targetid, main))
+ return indexentries
+
+
def inline_all_toctrees(builder, docnameset, docname, tree, colorfunc):
"""Inline all toctrees in the *tree*.
@@ -105,53 +174,13 @@ def make_refnode(builder, fromdocname, todocname, targetid, child, title=None):
return node
-if hasattr(StateMachine, 'get_source_and_line'):
- def set_source_info(directive, node):
- node.source, node.line = \
- directive.state_machine.get_source_and_line(directive.lineno)
- def set_role_source_info(inliner, lineno, node):
+def set_source_info(directive, node):
+ node.source, node.line = \
+ directive.state_machine.get_source_and_line(directive.lineno)
+
+def set_role_source_info(inliner, lineno, node):
node.source, node.line = \
inliner.reporter.locator(lineno)
-else:
- # docutils <= 0.6 compatibility
- def set_source_info(directive, node):
- node.line = directive.lineno
- def set_role_source_info(inliner, lineno, node):
- node.line = lineno
-
-# monkey-patch Node.traverse to get more speed
-# traverse() is called so many times during a build that it saves
-# on average 20-25% overall build time!
-
-def _all_traverse(self, result):
- """Version of Node.traverse() that doesn't need a condition."""
- result.append(self)
- for child in self.children:
- child._all_traverse(result)
- return result
-
-def _fast_traverse(self, cls, result):
- """Version of Node.traverse() that only supports instance checks."""
- if isinstance(self, cls):
- result.append(self)
- for child in self.children:
- child._fast_traverse(cls, result)
- return result
-
-def _new_traverse(self, condition=None,
- include_self=1, descend=1, siblings=0, ascend=0):
- if include_self and descend and not siblings and not ascend:
- if condition is None:
- return self._all_traverse([])
- elif isinstance(condition, (types.ClassType, type)):
- return self._fast_traverse(condition, [])
- return self._old_traverse(condition, include_self,
- descend, siblings, ascend)
-
-nodes.Node._old_traverse = nodes.Node.traverse
-nodes.Node._all_traverse = _all_traverse
-nodes.Node._fast_traverse = _fast_traverse
-nodes.Node.traverse = _new_traverse
# monkey-patch Node.__contains__ to get consistent "in" operator behavior
# across docutils versions