1 # -*- coding: utf-8 -*- |
|
2 """ |
|
3 sphinx.ext.mathbase |
|
4 ~~~~~~~~~~~~~~~~~~~ |
|
5 |
|
6 Set up math support in source files and LaTeX/text output. |
|
7 |
|
8 :copyright: 2008 by Georg Brandl. |
|
9 :license: BSD. |
|
10 """ |
|
11 |
|
12 from docutils import nodes, utils |
|
13 from docutils.parsers.rst import directives |
|
14 |
|
15 |
|
16 class math(nodes.Inline, nodes.TextElement): |
|
17 pass |
|
18 |
|
19 class displaymath(nodes.Part, nodes.Element): |
|
20 pass |
|
21 |
|
22 class eqref(nodes.Inline, nodes.TextElement): |
|
23 pass |
|
24 |
|
25 |
|
26 def wrap_displaymath(math, label): |
|
27 parts = math.split('\n\n') |
|
28 ret = [] |
|
29 for i, part in enumerate(parts): |
|
30 if label is not None and i == 0: |
|
31 ret.append('\\begin{split}%s\\end{split}' % part + |
|
32 (label and '\\label{'+label+'}' or '')) |
|
33 else: |
|
34 ret.append('\\begin{split}%s\\end{split}\\notag' % part) |
|
35 return '\\begin{gather}\n' + '\\\\'.join(ret) + '\n\\end{gather}' |
|
36 |
|
37 |
|
38 def math_role(role, rawtext, text, lineno, inliner, options={}, content=[]): |
|
39 latex = utils.unescape(text, restore_backslashes=True) |
|
40 return [math(latex=latex)], [] |
|
41 |
|
42 def eq_role(role, rawtext, text, lineno, inliner, options={}, content=[]): |
|
43 text = utils.unescape(text) |
|
44 node = eqref('(?)', '(?)', target=text) |
|
45 node['docname'] = inliner.document.settings.env.docname |
|
46 return [node], [] |
|
47 |
|
48 def math_directive(name, arguments, options, content, lineno, |
|
49 content_offset, block_text, state, state_machine): |
|
50 latex = '\n'.join(content) |
|
51 if arguments and arguments[0]: |
|
52 latex = arguments[0] + '\n\n' + latex |
|
53 node = displaymath() |
|
54 node['latex'] = latex |
|
55 node['label'] = options.get('label', None) |
|
56 node['nowrap'] = 'nowrap' in options |
|
57 node['docname'] = state.document.settings.env.docname |
|
58 ret = [node] |
|
59 if node['label']: |
|
60 tnode = nodes.target('', '', ids=['equation-' + node['label']]) |
|
61 state.document.note_explicit_target(tnode) |
|
62 ret.insert(0, tnode) |
|
63 return ret |
|
64 |
|
65 |
|
66 def latex_visit_math(self, node): |
|
67 self.body.append('$' + node['latex'] + '$') |
|
68 raise nodes.SkipNode |
|
69 |
|
70 def latex_visit_displaymath(self, node): |
|
71 if node['nowrap']: |
|
72 self.body.append(node['latex']) |
|
73 else: |
|
74 label = node['label'] and node['docname'] + '-' + node['label'] or None |
|
75 self.body.append(wrap_displaymath(node['latex'], label)) |
|
76 raise nodes.SkipNode |
|
77 |
|
78 def latex_visit_eqref(self, node): |
|
79 self.body.append('\\eqref{%s-%s}' % (node['docname'], node['target'])) |
|
80 raise nodes.SkipNode |
|
81 |
|
82 |
|
83 def text_visit_math(self, node): |
|
84 self.add_text(node['latex']) |
|
85 raise nodes.SkipNode |
|
86 |
|
87 def text_visit_displaymath(self, node): |
|
88 self.new_state() |
|
89 self.add_text(node['latex']) |
|
90 self.end_state() |
|
91 raise nodes.SkipNode |
|
92 |
|
93 def text_visit_eqref(self, node): |
|
94 self.add_text(node['target']) |
|
95 raise nodes.SkipNode |
|
96 |
|
97 |
|
98 def html_visit_eqref(self, node): |
|
99 self.body.append('<a href="#equation-%s">' % node['target']) |
|
100 |
|
101 def html_depart_eqref(self, node): |
|
102 self.body.append('</a>') |
|
103 |
|
104 |
|
105 def number_equations(app, doctree, docname): |
|
106 num = 0 |
|
107 numbers = {} |
|
108 for node in doctree.traverse(displaymath): |
|
109 if node['label'] is not None: |
|
110 num += 1 |
|
111 node['number'] = num |
|
112 numbers[node['label']] = num |
|
113 else: |
|
114 node['number'] = None |
|
115 for node in doctree.traverse(eqref): |
|
116 if node['target'] not in numbers: |
|
117 continue |
|
118 num = '(%d)' % numbers[node['target']] |
|
119 node[0] = nodes.Text(num, num) |
|
120 |
|
121 |
|
122 def setup(app, htmlinlinevisitors, htmldisplayvisitors): |
|
123 app.add_node(math, |
|
124 latex=(latex_visit_math, None), |
|
125 text=(text_visit_math, None), |
|
126 html=htmlinlinevisitors) |
|
127 app.add_node(displaymath, |
|
128 latex=(latex_visit_displaymath, None), |
|
129 text=(text_visit_displaymath, None), |
|
130 html=htmldisplayvisitors) |
|
131 app.add_node(eqref, |
|
132 latex=(latex_visit_eqref, None), |
|
133 text=(text_visit_eqref, None), |
|
134 html=(html_visit_eqref, html_depart_eqref)) |
|
135 app.add_role('math', math_role) |
|
136 app.add_role('eq', eq_role) |
|
137 app.add_directive('math', math_directive, 1, (0, 1, 1), |
|
138 label=directives.unchanged, nowrap=directives.flag) |
|
139 app.connect('doctree-resolved', number_equations) |
|