diff options
| author | tk0miya <i.tkomiya@gmail.com> | 2014-10-06 23:57:16 +0900 |
|---|---|---|
| committer | tk0miya <i.tkomiya@gmail.com> | 2014-10-06 23:57:16 +0900 |
| commit | 6e2e4d12b96413b460ec01dc9c5d90519ce8d079 (patch) | |
| tree | 3c8238f06b7c2e33fcdb37663779d45bbc92d98e /sphinx | |
| parent | 72d21037e99936a76d51aab4b6b7b88ba3144f20 (diff) | |
| parent | 541467233bd282b400d139b150da111e09880264 (diff) | |
| download | sphinx-6e2e4d12b96413b460ec01dc9c5d90519ce8d079.tar.gz | |
Merge with default
Diffstat (limited to 'sphinx')
| -rw-r--r-- | sphinx/addnodes.py | 4 | ||||
| -rw-r--r-- | sphinx/domains/std.py | 75 | ||||
| -rw-r--r-- | sphinx/environment.py | 19 | ||||
| -rw-r--r-- | sphinx/util/__init__.py | 17 | ||||
| -rw-r--r-- | sphinx/writers/html.py | 6 | ||||
| -rw-r--r-- | sphinx/writers/latex.py | 26 | ||||
| -rw-r--r-- | sphinx/writers/manpage.py | 5 | ||||
| -rw-r--r-- | sphinx/writers/texinfo.py | 5 | ||||
| -rw-r--r-- | sphinx/writers/text.py | 5 |
9 files changed, 126 insertions, 36 deletions
diff --git a/sphinx/addnodes.py b/sphinx/addnodes.py index 9d8c4690..362abd5a 100644 --- a/sphinx/addnodes.py +++ b/sphinx/addnodes.py @@ -184,6 +184,10 @@ class pending_xref(nodes.Inline, nodes.Element): """ +class number_reference(nodes.reference): + """Node for number references, similar to pending_xref.""" + + class download_reference(nodes.reference): """Node for download references, similar to pending_xref.""" diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py index 0338a6b5..03228da2 100644 --- a/sphinx/domains/std.py +++ b/sphinx/domains/std.py @@ -22,7 +22,7 @@ from sphinx.roles import XRefRole from sphinx.locale import l_, _ from sphinx.domains import Domain, ObjType from sphinx.directives import ObjectDescription -from sphinx.util import ws_re +from sphinx.util import ws_re, get_figtype from sphinx.util.nodes import clean_astext, make_refnode from sphinx.util.compat import Directive @@ -466,6 +466,9 @@ class StandardDomain(Domain): # links to headings or arbitrary labels 'ref': XRefRole(lowercase=True, innernodeclass=nodes.emphasis, warn_dangling=True), + # links to labels of numbered figures, tables and code-blocks + 'numref': XRefRole(lowercase=True, + warn_dangling=True), # links to labels, without a different title 'keyword': XRefRole(warn_dangling=True), } @@ -489,6 +492,7 @@ class StandardDomain(Domain): 'term': 'term not in glossary: %(target)s', 'ref': 'undefined label: %(target)s (if the link has no caption ' 'the label must precede a section header)', + 'numref': 'undefined label: %(target)s', 'keyword': 'unknown keyword: %(target)s', } @@ -574,6 +578,28 @@ class StandardDomain(Domain): continue labels[name] = docname, labelid, sectname + def build_reference_node(self, fromdocname, builder, + docname, labelid, sectname, + **options): + nodeclass = options.pop('nodeclass', nodes.reference) + newnode = nodeclass('', '', internal=True, **options) + innernode = nodes.emphasis(sectname, sectname) + if docname == fromdocname: + newnode['refid'] = labelid + else: + # set more info in contnode; in case the + # get_relative_uri call raises NoUri, + # the builder will then have to resolve these + contnode = addnodes.pending_xref('') + contnode['refdocname'] = docname + contnode['refsectname'] = sectname + newnode['refuri'] = builder.get_relative_uri( + fromdocname, docname) + if labelid: + newnode['refuri'] += '#' + labelid + newnode.append(innernode) + return newnode + def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode): if typ == 'ref': @@ -589,23 +615,38 @@ class StandardDomain(Domain): ('', '', '')) if not docname: return None - newnode = nodes.reference('', '', internal=True) - innernode = nodes.emphasis(sectname, sectname) - if docname == fromdocname: - newnode['refid'] = labelid + + return self.build_reference_node(fromdocname, builder, + docname, labelid, sectname) + elif typ == 'numref': + docname, labelid = self.data['anonlabels'].get(target, ('', '')) + if not docname: + return None + + if env.config.numfig is False: + env.warn(fromdocname, 'numfig is disabled. :numref: is ignored.') + return contnode + + try: + target = env.get_doctree(docname).ids[labelid] + figtype = get_figtype(target) + figure_id = target['ids'][0] + fignumber = env.toc_fignumbers[docname][figtype][figure_id] + except (KeyError, IndexError): + return None + + title = contnode.astext() + if labelid == title: + prefix = env.config.numfig_prefix.get(figtype, '') + title = prefix.replace('%s', '#') + newtitle = prefix % '.'.join(map(str, fignumber)) else: - # set more info in contnode; in case the - # get_relative_uri call raises NoUri, - # the builder will then have to resolve these - contnode = addnodes.pending_xref('') - contnode['refdocname'] = docname - contnode['refsectname'] = sectname - newnode['refuri'] = builder.get_relative_uri( - fromdocname, docname) - if labelid: - newnode['refuri'] += '#' + labelid - newnode.append(innernode) - return newnode + newtitle = title.replace('#', '.'.join(map(str, fignumber))) + + return self.build_reference_node(fromdocname, builder, + docname, labelid, newtitle, + nodeclass=addnodes.number_reference, + title=title) elif typ == 'keyword': # keywords are oddballs: they are referenced by named labels docname, labelid, _ = self.data['labels'].get(target, ('', '', '')) diff --git a/sphinx/environment.py b/sphinx/environment.py index 9111e34f..38cf2d8c 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -37,7 +37,7 @@ from docutils.frontend import OptionParser from sphinx import addnodes from sphinx.util import url_re, get_matching_docs, docname_join, split_into, \ - FilenameUniqDict + FilenameUniqDict, get_figtype from sphinx.util.nodes import clean_astext, make_refnode, WarningStream from sphinx.util.osutil import SEP, find_catalog_files, getcwd, fs_encoding from sphinx.util.console import bold, purple @@ -1706,9 +1706,6 @@ class BuildEnvironment: self.toc_fignumbers = {} fignum_counter = {} - def has_child(node, cls): - return any(isinstance(child, cls) for child in node) - def get_section_number(docname, section): anchorname = '#' + section['ids'][0] secnumbers = self.toc_secnumbers.get(docname, {}) @@ -1750,16 +1747,10 @@ class BuildEnvironment: continue - if isinstance(subnode, nodes.figure): - figure_id = subnode['ids'][0] - register_fignumber(docname, secnum, 'figure', figure_id) - elif isinstance(subnode, nodes.table): - table_id = subnode['ids'][0] - register_fignumber(docname, secnum, 'table', table_id) - elif isinstance(subnode, nodes.container): - if has_child(subnode, nodes.literal_block): - code_block_id = subnode['ids'][0] - register_fignumber(docname, secnum, 'code-block', code_block_id) + figtype = get_figtype(subnode) + if figtype and subnode['ids']: + register_fignumber(docname, secnum, + figtype, subnode['ids'][0]) _walk_doctree(docname, subnode, secnum) diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py index e7277520..024e25b1 100644 --- a/sphinx/util/__init__.py +++ b/sphinx/util/__init__.py @@ -475,3 +475,20 @@ class PeekableIterator(object): item = next(self) self.push(item) return item + + +def get_figtype(node): + """Return figtype for given node.""" + def has_child(node, cls): + return any(isinstance(child, cls) for child in node) + + from docutils import nodes + if isinstance(node, nodes.figure): + return 'figure' + elif isinstance(node, nodes.table): + return 'table' + elif isinstance(node, nodes.container): + if has_child(node, nodes.literal_block): + return 'code-block' + + return None diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py index 1d2cff05..1c7bed99 100644 --- a/sphinx/writers/html.py +++ b/sphinx/writers/html.py @@ -207,6 +207,12 @@ class HTMLTranslator(BaseTranslator): self.body.append(('%s' + self.secnumber_suffix) % '.'.join(map(str, node['secnumber']))) + def visit_number_reference(self, node): + self.visit_reference(node) + + def depart_number_reference(self, node): + self.depart_reference(node) + # overwritten -- we don't want source comments to show up in the HTML def visit_comment(self, node): raise nodes.SkipNode diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index ea79761f..dd85a806 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -682,6 +682,9 @@ class LaTeXTranslator(nodes.NodeVisitor): if not self.table.longtable and self.table.caption is not None: self.body.append(u'\n\n\\begin{threeparttable}\n' u'\\capstart\\caption{%s}\n' % self.table.caption) + for id in self.next_table_ids: + self.body.append(self.hypertarget(id, anchor=False)) + self.next_table_ids.clear() if self.table.longtable: self.body.append('\n\\begin{longtable}') endmacro = '\\end{longtable}\n\n' @@ -709,11 +712,11 @@ class LaTeXTranslator(nodes.NodeVisitor): else: self.body.append('{|' + ('L|' * self.table.colcount) + '}\n') if self.table.longtable and self.table.caption is not None: - self.body.append(u'\\caption{%s} \\\\\n' % self.table.caption) - if self.table.caption is not None: + self.body.append(u'\\caption{%s}' % self.table.caption) for id in self.next_table_ids: self.body.append(self.hypertarget(id, anchor=False)) self.next_table_ids.clear() + self.body.append(u'\\\\\n') if self.table.longtable: self.body.append('\\hline\n') self.body.extend(self.tableheaders) @@ -1114,7 +1117,7 @@ class LaTeXTranslator(nodes.NodeVisitor): return elif isinstance(next, nodes.table): # same for tables, but only if they have a caption - for n in node: + for n in next: if isinstance(n, nodes.title): if node.get('refid'): self.next_table_ids.add(node['refid']) @@ -1244,6 +1247,18 @@ class LaTeXTranslator(nodes.NodeVisitor): def depart_reference(self, node): self.body.append(self.context.pop()) + def visit_number_reference(self, node): + if node.get('refid'): + id = self.curfilestack[-1] + ':' + node['refid'] + else: + id = node.get('refuri', '')[1:].replace('#', ':') + + ref = '\\ref{%s}' % self.idescape(id) + title = node.get('title', '#') + self.body.append(title.replace('#', ref)) + + raise nodes.SkipNode + def visit_download_reference(self, node): pass def depart_download_reference(self, node): @@ -1511,11 +1526,12 @@ class LaTeXTranslator(nodes.NodeVisitor): for id in self.next_literal_ids: ids += self.hypertarget(id, anchor=False) self.next_literal_ids.clear() - self.body.append('\n\\begin{literal-block}' + ids) + self.body.append('\n\\begin{literal-block}\n') + self.context.append(ids + '\n\\end{literal-block}\n') def depart_container(self, node): if node.get('literal_block'): - self.body.append('\\end{literal-block}\n') + self.body.append(self.context.pop()) def visit_decoration(self, node): pass diff --git a/sphinx/writers/manpage.py b/sphinx/writers/manpage.py index 8d49f807..bc842057 100644 --- a/sphinx/writers/manpage.py +++ b/sphinx/writers/manpage.py @@ -246,6 +246,11 @@ class ManualPageTranslator(BaseTranslator): '>']) raise nodes.SkipNode + def visit_number_reference(self, node): + text = nodes.Text(node.get('title', '#')) + self.visit_Text(text) + raise nodes.SkipNode + def visit_centered(self, node): self.ensure_eol() self.body.append('.sp\n.ce\n') diff --git a/sphinx/writers/texinfo.py b/sphinx/writers/texinfo.py index 61d2e62f..93d4d6aa 100644 --- a/sphinx/writers/texinfo.py +++ b/sphinx/writers/texinfo.py @@ -722,6 +722,11 @@ class TexinfoTranslator(nodes.NodeVisitor): def depart_reference(self, node): pass + def visit_number_reference(self, node): + text = nodes.Text(node.get('title', '#')) + self.visit_Text(text) + raise nodes.SkipNode + def visit_title_reference(self, node): text = node.astext() self.body.append('@cite{%s}' % self.escape_arg(text)) diff --git a/sphinx/writers/text.py b/sphinx/writers/text.py index 5b32b05a..efd32df3 100644 --- a/sphinx/writers/text.py +++ b/sphinx/writers/text.py @@ -748,6 +748,11 @@ class TextTranslator(nodes.NodeVisitor): def depart_reference(self, node): pass + def visit_number_reference(self, node): + text = nodes.Text(node.get('title', '#')) + self.visit_Text(text) + raise nodes.SkipNode + def visit_download_reference(self, node): pass def depart_download_reference(self, node): |
