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) |
---|