[19dcb933] | 1 | from docutils.nodes import figure, caption, Text, reference, raw, SkipNode, Element |
---|
| 2 | from sphinx.roles import XRefRole |
---|
| 3 | |
---|
| 4 | |
---|
| 5 | # Element classes |
---|
| 6 | |
---|
| 7 | class page_ref(reference): |
---|
| 8 | pass |
---|
| 9 | |
---|
| 10 | class num_ref(reference): |
---|
| 11 | pass |
---|
| 12 | |
---|
| 13 | |
---|
| 14 | # Visit/depart functions |
---|
| 15 | |
---|
| 16 | def skip_num_ref(self, node): |
---|
| 17 | raise SkipNode |
---|
| 18 | |
---|
| 19 | def skip_page_ref(self, node): |
---|
| 20 | raise SkipNode |
---|
| 21 | |
---|
| 22 | def latex_visit_page_ref(self, node): |
---|
| 23 | self.body.append("\\pageref{%s:%s}" % (node['refdoc'], node['reftarget'])) |
---|
| 24 | raise SkipNode |
---|
| 25 | |
---|
| 26 | def latex_visit_num_ref(self, node): |
---|
| 27 | fields = node['reftarget'].split('#') |
---|
| 28 | if len(fields) > 1: |
---|
| 29 | label, target = fields |
---|
| 30 | ref_link = '%s:%s' % (node['refdoc'], target) |
---|
| 31 | latex = "\\hyperref[%s]{%s \\ref*{%s}}" % (ref_link, label, ref_link) |
---|
| 32 | self.body.append(latex) |
---|
| 33 | else: |
---|
| 34 | self.body.append('\\ref{%s:%s}' % (node['refdoc'], fields[0])) |
---|
| 35 | |
---|
| 36 | raise SkipNode |
---|
| 37 | |
---|
| 38 | |
---|
| 39 | def doctree_read(app, doctree): |
---|
| 40 | # first generate figure numbers for each figure |
---|
| 41 | env = app.builder.env |
---|
| 42 | figid_docname_map = getattr(env, 'figid_docname_map', {}) |
---|
| 43 | |
---|
| 44 | for figure_info in doctree.traverse(figure): |
---|
| 45 | for id in figure_info['ids']: |
---|
| 46 | figid_docname_map[id] = env.docname |
---|
| 47 | |
---|
| 48 | env.figid_docname_map = figid_docname_map |
---|
| 49 | |
---|
| 50 | |
---|
| 51 | def doctree_resolved(app, doctree, docname): |
---|
| 52 | i = 1 |
---|
| 53 | figids = {} |
---|
| 54 | for figure_info in doctree.traverse(figure): |
---|
| 55 | if app.builder.name != 'latex' and app.config.number_figures: |
---|
| 56 | for cap in figure_info.traverse(caption): |
---|
| 57 | cap[0] = Text("%s %d: %s" % (app.config.figure_caption_prefix, i, cap[0])) |
---|
| 58 | |
---|
| 59 | for id in figure_info['ids']: |
---|
| 60 | figids[id] = i |
---|
| 61 | |
---|
| 62 | i += 1 |
---|
| 63 | |
---|
| 64 | |
---|
| 65 | # replace numfig nodes with links |
---|
| 66 | if app.builder.name != 'latex': |
---|
| 67 | for ref_info in doctree.traverse(num_ref): |
---|
| 68 | if '#' in ref_info['reftarget']: |
---|
| 69 | label, target = ref_info['reftarget'].split('#') |
---|
| 70 | labelfmt = label + " %d" |
---|
| 71 | else: |
---|
| 72 | labelfmt = '%d' |
---|
| 73 | target = ref_info['reftarget'] |
---|
| 74 | |
---|
| 75 | if target not in figids: |
---|
| 76 | continue |
---|
| 77 | |
---|
| 78 | if app.builder.name == 'html': |
---|
| 79 | target_doc = app.builder.env.figid_docname_map[target] |
---|
| 80 | link = "%s#%s" % (app.builder.get_relative_uri(docname, target_doc), |
---|
| 81 | target) |
---|
| 82 | html = '<a class="pageref" href="%s">%s</a>' % (link, labelfmt %(figids[target])) |
---|
| 83 | ref_info.replace_self(raw(html, html, format='html')) |
---|
| 84 | else: |
---|
| 85 | ref_info.replace_self(Text(labelfmt % (figids[target]))) |
---|
| 86 | |
---|
| 87 | |
---|
| 88 | def clean_env(app): |
---|
| 89 | app.builder.env.i=1 |
---|
| 90 | app.builder.env.figid_docname_map = {} |
---|
| 91 | |
---|
| 92 | def setup(app): |
---|
| 93 | app.add_config_value('number_figures', True, True) |
---|
| 94 | app.add_config_value('figure_caption_prefix', "Figure", True) |
---|
| 95 | |
---|
| 96 | app.add_node(page_ref, |
---|
| 97 | text=(skip_page_ref, None), |
---|
| 98 | html=(skip_page_ref, None), |
---|
| 99 | latex=(latex_visit_page_ref, None)) |
---|
| 100 | |
---|
| 101 | app.add_role('page', XRefRole(nodeclass=page_ref)) |
---|
| 102 | |
---|
| 103 | app.add_node(num_ref, |
---|
| 104 | latex=(latex_visit_num_ref, None), |
---|
| 105 | html=(skip_num_ref, None)) |
---|
| 106 | |
---|
| 107 | app.add_role('num', XRefRole(nodeclass=num_ref)) |
---|
| 108 | |
---|
| 109 | app.connect("builder-inited", clean_env) |
---|
| 110 | app.connect('doctree-read', doctree_read) |
---|
| 111 | app.connect('doctree-resolved', doctree_resolved) |
---|