diff options
Diffstat (limited to 'sphinx/util/nodes.py')
-rw-r--r-- | sphinx/util/nodes.py | 123 |
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 |