Add math support to Sphinx.

This commit is contained in:
Georg Brandl 2008-08-06 13:04:14 +00:00
parent b7b483d01f
commit 5941814c4a
17 changed files with 667 additions and 46 deletions

35
CHANGES
View File

@ -13,29 +13,34 @@ New features added
have Sphinx documentation, which will build the docs and place them
in the standard distutils build directory.
* `SerializingHTMLBuilder` was added as new abstract builder that can
be subclassed to serialize build HTML in a specific format. The
`PickleHTMLBuilder` is a concrete subclass of it that uses pickle as
serialization implementation.
* ``SerializingHTMLBuilder`` was added as new abstract builder that
can be subclassed to serialize build HTML in a specific format.
The ``PickleHTMLBuilder`` is a concrete subclass of it that uses
pickle as serialization implementation.
* `JSONHTMLBuilder` was added that similarily to `PickleHTMLBuilder`
dumps the generated HTML into JSON files for further processing.
* ``JSONHTMLBuilder`` was added as another ``SerializingHTMLBuilder``
subclass that dumps the generated HTML into JSON files for further
processing.
* The `automodule` directive now supports the ``synopsis``,
``deprecated`` and ``platform`` options.
* The HTML builders have two additional attributes now that can be used
to disable the anchor-link creation after headlines and definition
links.
* The HTML builders have two additional attributes now that can be
used to disable the anchor-link creation after headlines and
definition links.
* ``Sphinx.add_node()`` now takes optional visitor methods for the HTML,
LaTeX and text translators; this prevents having to manually patch
the classes.
* sphinx.doc.autodoc has a new event ``autodoc-process-signature``
that allows tuning function signature introspection.
* sphinx.doc.autodoc has a new event ``autodoc-process-signature`` that
allows tuning function signature introspection.
* ``Sphinx.add_node()`` now takes optional visitor methods for the
HTML, LaTeX and text translators; this prevents having to manually
patch the classes.
* Added new events: ``env-updated`` and ``missing-reference``.
* Added ``Sphinx.add_javascript()`` that adds scripts to load in the
default HTML template.
* Added new events: ``env-updated``, ``missing-reference``,
``build-finished``.
Release 0.4.2 (Jul 29, 2008)

View File

@ -13,8 +13,30 @@ Since the reST source files can have different extensions (some people like
:confval:`source_suffix`) and different OSes have different path separators,
Sphinx abstracts them: all "document names" are relative to the :term:`source
directory`, the extension is stripped, and path separators are converted to
slashes. All values, parameters and suchlike referring to "documents" expect
such a document name.
slashes :eq:`abc`. All values, parameters and suchlike referring to "documents" expect
such a document :math:`name\sqrt{3}`.
.. math::
:label: abc
3x+4y \sqrt{4}
x+y \\
z+z
.. math:: a+b
c + d & = 5 \\
& = 6
.. math:: 5x + 6
.. math::
:label: def
test
See :eq:`def`.
The TOC tree

View File

@ -21,7 +21,9 @@ import sys, os, re
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.addons.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest']
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.pngmath']
#pngmath_use_preview = True
jsmath_path = '/home/gbr/jsMath/easy/load.js'
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

View File

@ -150,6 +150,14 @@ the following public API:
Add the standard docutils :class:`Transform` subclass *transform* to the list
of transforms that are applied after Sphinx parses a reST document.
.. method:: Sphinx.add_javascript(filename)
Add *filename* to the list of JavaScript files that the default HTML template
will include. The filename must be relative to the HTML static path, see
:confval:`the docs for the config value <html_static_path>`.
.. versionadded:: 0.5
.. method:: Sphinx.connect(event, callback)
Register *callback* to be called when *event* is emitted. For details on
@ -254,6 +262,17 @@ registered event handlers.
.. versionadded:: 0.4
.. event:: build-finished (app, exception)
Emitted when a build has finished, before Sphinx exits, usually used for
cleanup. This event is emitted even when the build process raised an
exception, given as the *exception* argument. The exception is reraised in
the application after the event handlers have run. If the build process
raised no exception, *exception* will be ``None``. This allows to customize
cleanup actions depending on the exception status.
.. versionadded:: 0.5
.. _template-bridge:

166
doc/ext/math.rst Normal file
View File

@ -0,0 +1,166 @@
.. highlight:: rest
Math support in Sphinx
======================
.. module:: sphinx.ext.mathbase
:synopsis: Common math support for pngmath and jsmath.
.. versionadded:: 0.5
Since mathematical notation isn't natively supported by HTML in any way, Sphinx
supports math in documentation with two extensions.
The basic math support that is common to both extensions is contained in
:mod:`sphinx.ext.mathbase`. Other math support extensions should, if possible,
reuse that support too.
The input language for mathematics is LaTeX markup. This is the de-facto
standard for plain-text math notation and has the added advantage that no
further translation is necessary when building LaTeX output.
:mod:`mathbase` defines these new markup elements:
.. role:: math
Role for inline math. Use like this::
Since Pythagoras, we know that :math:`a^2 + b^2 = c^2`.
.. directive:: math
Directive for displayed math (math that takes the whole line for itself).
The directive supports multiple equations, which should be separated by a
blank line::
.. math::
(a + b)^2 = a^2 + 2ab + b^2
(a - b)^2 = a^2 - 2ab + b^2
In addition, each single equation is set within a ``split`` environment,
which means that you can have multiple aligned lines in an equation,
aligned at ``&`` and separated by ``\\``::
.. math::
(a + b)^2 &= (a + b)(a + b) \\
&= a^2 + 2ab + b^2
For more details, look into the documentation of the `AmSMath LaTeX
package`_.
When the math is only one line of text, it can also be given as a directive
argument::
.. math:: (a + b)^2 = a^2 + 2ab + b^2
Normally, equations are not numbered. If you want your equation to get a
number, use the ``label`` option. When given, it selects a label for the
equation, by which it can be cross-referenced, and causes an equation number
to be issued. See :role:`eqref` for an example. The numbering style depends
on the output format.
.. role:: eqref
Role for cross-referencing equations via their label. This currently works
only within the same document. Example::
.. math:: e^{i\pi} + 1 = 0
:label: euler
Euler's identity, equation :eqref:`euler`, was elected one of the most
beautiful mathematical formulas.
:mod:`sphinx.ext.pngmath` -- Render math as PNG images
------------------------------------------------------
.. module:: sphinx.ext.pngmath
:synopsis: Render math as PNG images.
This extension renders math via LaTeX and dvipng_ into PNG images. This of
course means that the computer where the docs are built must have both programs
available.
There are various config values you can set to influence how the images are built:
.. confval:: pngmath_latex
The command name with which to invoke LaTeX. The default is ``'latex'``; you
may need to set this to a full path if ``latex`` not in the executable search
path.
Since this setting is not portable from system to system, it is normally not
useful to set it in ``conf.py``; rather, giving it on the
:program:`sphinx-build` command line via the :option:`-D` option should be
preferable, like this::
sphinx-build -b html -D pngmath_latex=C:\tex\latex.exe . _build/html
.. confval:: pngmath_dvipng
The command name with which to invoke ``dvipng``. The default is
``'dvipng'``; you may need to set this to a full path if ``dvipng`` is not in
the executable search path.
.. confval:: pngmath_latex_preamble
Additional LaTeX code to put into the preamble of the short LaTeX files that
are used to translate the math snippets. This is empty by default. Use it
e.g. to add more packages whose commands you want to use in the math.
.. confval:: pngmath_dvipng_args
Additional arguments to give to dvipng, as a list. This is empty by default.
Arguments you might want to add here are e.g. ``['-bg', 'Transparent']``,
which produces PNGs with a transparent background. This is not enabled by
default because some Internet Explorer versions don't like transparent PNGs.
.. confval:: pngmath_use_preview
``dvipng`` has the ability to determine the "depth" of the rendered text: for
example, when typesetting a fraction inline, the baseline of surrounding text
should not be flush with the bottom of the image, rather the image should
extend a bit below the baseline. This is what TeX calls "depth". When this
is enabled, the images put into the HTML document will get a
``vertical-align`` style that correctly aligns the baselines.
Unfortunately, this only works when the `preview-latex package`_ is
installed. Therefore, the default for this option is ``False``.
:mod:`sphinx.ext.jsmath` -- Render math via JavaScript
------------------------------------------------------
.. module:: sphinx.ext.jsmath
:synopsis: Render math via JavaScript.
This extension puts math as-is into the HTML files. The JavaScript package
jsMath_ is then loaded and transforms the LaTeX markup to readable math live in
the browser.
Because jsMath (and the necessary fonts) is very large, it is not included in
Sphinx. You must install it yourself, and give Sphinx its path in this config
value:
.. confval:: jsmath_path
The path to the JavaScript file to include in the HTML files in order to load
JSMath. There is no default.
The path can be absolute or relative; if it is relative, it is relative to
the root of the built docs.
For example, if you put JSMath into the static path of the Sphinx docs, this
value would be ``_static/jsMath/easy/load.js``. If you host more than one
Sphinx documentation set on one server, it is advisable to install jsMath in
a shared location.
.. _dvipng: http://savannah.nongnu.org/projects/dvipng/
.. _jsMath: http://www.math.union.edu/~dpvc/jsmath/
.. _preview-latex package: http://www.gnu.org/software/auctex/preview-latex.html
.. _AmSMath LaTeX package: http://www.ams.org/tex/amslatex.html

View File

@ -35,6 +35,7 @@ These extensions are built in and can be activated by respective entries in the
ext/autodoc
ext/doctest
ext/intersphinx
ext/math
ext/refcounting
ext/ifconfig
ext/coverage

View File

@ -50,7 +50,7 @@ Modi:
def main(argv=sys.argv):
# delay-import these to be able to get sphinx.__version__ from setup.py
# even without docutils installed
from sphinx.application import Sphinx
from sphinx.application import Sphinx, SphinxError
from docutils.utils import SystemMessage
if not sys.stdout.isatty() or sys.platform == 'win32':
@ -124,15 +124,7 @@ def main(argv=sys.argv):
try:
app = Sphinx(srcdir, confdir, outdir, doctreedir, buildername,
confoverrides, status, sys.stderr, freshenv)
if not app.builder:
return 1
if all_files:
app.builder.build_all()
elif filenames:
app.builder.build_specific(filenames)
else:
app.builder.build_update()
app.build(all_files, filenames)
except KeyboardInterrupt:
if use_pdb:
import pdb
@ -151,6 +143,9 @@ def main(argv=sys.argv):
if isinstance(err, SystemMessage):
print >>sys.stderr, darkred('reST markup error:')
print >>sys.stderr, err.args[0].encode('ascii', 'backslashreplace')
elif isinstance(err, SphinxError):
print >>sys.stderr, darkred('%s:' % err.category)
print >>sys.stderr, err
else:
print >>sys.stderr, darkred('Exception occurred:')
print >>sys.stderr, format_exception_cut_frames().rstrip()

View File

@ -13,6 +13,7 @@
"""
import sys
import posixpath
from docutils import nodes
from docutils.parsers.rst import directives, roles
@ -20,14 +21,22 @@ from docutils.parsers.rst import directives, roles
import sphinx
from sphinx.roles import xfileref_role, innernodetypes
from sphinx.config import Config
from sphinx.builder import builtin_builders
from sphinx.builder import builtin_builders, StandaloneHTMLBuilder
from sphinx.directives import desc_directive, target_directive, additional_xref_types
from sphinx.environment import SphinxStandaloneReader
from sphinx.util.console import bold
class ExtensionError(Exception):
class SphinxError(Exception):
"""
Base class for Sphinx errors that are shown to the user in a nicer
way than normal exceptions.
"""
category = 'Sphinx error'
class ExtensionError(SphinxError):
"""Raised if something's wrong with the configuration."""
category = 'Extension error'
def __init__(self, message, orig_exc=None):
self.message = message
@ -53,6 +62,7 @@ events = {
'doctree-resolved': 'doctree, docname',
'env-updated': 'env',
'html-page-context': 'pagename, context, doctree or None',
'build-finished': 'exception',
}
CONFIG_FILENAME = 'conf.py'
@ -94,8 +104,7 @@ class Sphinx(object):
print >>status, 'No builder selected, using default: html'
buildername = 'html'
if buildername not in self.builderclasses:
print >>warning, 'Builder name %s not registered' % buildername
return
raise SphinxError('Builder name %s not registered' % buildername)
self.info(bold('Sphinx v%s, building %s' % (sphinx.__version__, buildername)))
@ -103,6 +112,20 @@ class Sphinx(object):
self.builder = builderclass(self, freshenv=freshenv)
self.emit('builder-inited')
def build(self, all_files, filenames):
try:
if all_files:
self.builder.build_all()
elif filenames:
self.builder.build_specific(filenames)
else:
self.builder.build_update()
except Exception, err:
self.emit('build-finished', err)
raise
else:
self.emit('build-finished', None)
def warn(self, message):
self._warncount += 1
self._warning.write('WARNING: %s\n' % message)
@ -244,6 +267,10 @@ class Sphinx(object):
def add_transform(self, transform):
SphinxStandaloneReader.transforms.append(transform)
def add_javascript(self, filename):
StandaloneHTMLBuilder.script_files.append(
posixpath.join('_static', filename))
class TemplateBridge(object):
"""

View File

@ -305,6 +305,7 @@ class StandaloneHTMLBuilder(Builder):
copysource = True
out_suffix = '.html'
indexer_format = json
script_files = ['_static/jquery.js', '_static/doctools.js']
supported_image_types = ['image/svg+xml', 'image/png', 'image/gif',
'image/jpeg']
searchindex_filename = 'searchindex.json'
@ -388,6 +389,7 @@ class StandaloneHTMLBuilder(Builder):
shorttitle = self.config.html_short_title,
show_sphinx = self.config.html_show_sphinx,
file_suffix = self.out_suffix,
script_files = self.script_files,
sphinx_version = __version__,
rellinks = rellinks,
builder = self.name,

52
sphinx/ext/jsmath.py Normal file
View File

@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-
"""
sphinx.ext.jsmath
~~~~~~~~~~~~~~~~~
Set up everything for use of JSMath to display math in HTML
via JavaScript.
:copyright: 2008 by Georg Brandl.
:license: BSD.
"""
from docutils import nodes
from sphinx.application import ExtensionError
from sphinx.ext.mathbase import setup as mathbase_setup, wrap_displaymath
def html_visit_math(self, node):
self.body.append(self.starttag(node, 'span', '', CLASS='math'))
self.body.append(self.encode(node['latex']) + '</span>')
raise nodes.SkipNode
def html_visit_displaymath(self, node):
for i, part in enumerate(node['latex'].split('\n\n')):
part = self.encode(part)
if i == 0:
# necessary to e.g. set the id property correctly
if node['number']:
self.body.append('<span class="eqno">(%s)</span>' % node['number'])
self.body.append(self.starttag(node, 'div', CLASS='math'))
else:
# but only once!
self.body.append('<div class="math">')
if '&' in part or '\\\\' in part:
self.body.append('\\begin{split}' + part + '\\end{split}')
else:
self.body.append(part)
self.body.append('</div>\n')
raise nodes.SkipNode
def builder_inited(app):
if not app.config.jsmath_path:
raise ExtensionError('jsmath_path config value must be set for the '
'jsmath extension to work')
app.add_javascript(app.config.jsmath_path)
def setup(app):
mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
app.add_config_value('jsmath_path', '', False)
app.connect('builder-inited', builder_inited)

135
sphinx/ext/mathbase.py Normal file
View File

@ -0,0 +1,135 @@
# -*- coding: utf-8 -*-
"""
sphinx.ext.mathbase
~~~~~~~~~~~~~~~~~~~
Set up math support in source files and LaTeX/text output.
:copyright: 2008 by Georg Brandl.
:license: BSD.
"""
from docutils import nodes, utils
from docutils.parsers.rst import directives
class math(nodes.Inline, nodes.TextElement):
pass
class displaymath(nodes.Part, nodes.Element):
pass
class eqref(nodes.Inline, nodes.TextElement):
pass
def wrap_displaymath(math, label):
parts = math.split('\n\n')
ret = []
for i, part in enumerate(parts):
if label is not None and i == 0:
ret.append('\\begin{split}%s\\end{split}' % part +
(label and '\\label{'+label+'}' or ''))
else:
ret.append('\\begin{split}%s\\end{split}\\notag' % part)
return '\\begin{gather}\n' + '\\\\'.join(ret) + '\n\\end{gather}'
def math_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
latex = utils.unescape(text, restore_backslashes=True)
return [math(latex=latex)], []
def eq_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
text = utils.unescape(text)
node = eqref('(?)', '(?)', target=text)
node['docname'] = inliner.document.settings.env.docname
return [node], []
def math_directive(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine):
latex = '\n'.join(content)
if arguments and arguments[0]:
latex = arguments[0] + '\n\n' + latex
node = displaymath()
node['latex'] = latex
node['label'] = options.get('label', None)
node['docname'] = state.document.settings.env.docname
ret = [node]
if node['label']:
tnode = nodes.target('', '', ids=['equation-' + node['label']])
state.document.note_explicit_target(tnode)
ret.insert(0, tnode)
return ret
def latex_visit_math(self, node):
self.body.append('$' + node['latex'] + '$')
raise nodes.SkipNode
def latex_visit_displaymath(self, node):
self.body.append(wrap_displaymath(node['latex'],
node['docname'] + '-' + node['label']))
raise nodes.SkipNode
def latex_visit_eqref(self, node):
self.body.append('\\eqref{%s-%s}' % (node['docname'], node['target']))
raise nodes.SkipNode
def text_visit_math(self, node):
self.add_text(node['latex'])
raise nodes.SkipNode
def text_visit_displaymath(self, node):
self.new_state()
self.add_text(node['latex'])
self.end_state()
raise nodes.SkipNode
def text_visit_eqref(self, node):
self.add_text(node['label'])
raise nodes.SkipNode
def html_visit_eqref(self, node):
self.body.append('<a href="#equation-%s">' % node['target'])
def html_depart_eqref(self, node):
self.body.append('</a>')
def number_equations(app, doctree, docname):
num = 0
numbers = {}
for node in doctree.traverse(displaymath):
if node['label'] is not None:
num += 1
node['number'] = num
numbers[node['label']] = num
else:
node['number'] = None
for node in doctree.traverse(eqref):
if node['target'] not in numbers:
continue
num = '(%d)' % numbers[node['target']]
node[0] = nodes.Text(num, num)
def setup(app, htmlinlinevisitors, htmldisplayvisitors):
app.add_node(math,
latex=(latex_visit_math, None),
text=(text_visit_math, None),
html=htmlinlinevisitors)
app.add_node(displaymath,
latex=(latex_visit_displaymath, None),
text=(text_visit_displaymath, None),
html=htmldisplayvisitors)
app.add_node(eqref,
latex=(latex_visit_eqref, None),
text=(text_visit_eqref, None),
html=(html_visit_eqref, html_depart_eqref))
app.add_role('math', math_role)
app.add_role('eq', eq_role)
app.add_directive('math', math_directive, 1, (0, 1, 1),
label=directives.unchanged)
app.connect('doctree-resolved', number_equations)

189
sphinx/ext/pngmath.py Normal file
View File

@ -0,0 +1,189 @@
# -*- coding: utf-8 -*-
"""
sphinx.ext.pngmath
~~~~~~~~~~~~~~~~~~
Render math in HTML via dvipng.
:copyright: 2008 by Georg Brandl.
:license: BSD.
"""
import re
import shutil
import tempfile
import posixpath
from os import path
from subprocess import Popen, PIPE
try:
from hashlib import sha
except ImportError:
from sha import sha
from docutils import nodes
from sphinx.util import ensuredir
from sphinx.application import SphinxError
from sphinx.ext.mathbase import setup as mathbase_setup, wrap_displaymath
class MathExtError(SphinxError):
category = 'Math extension error'
DOC_HEAD = r'''
\documentclass[12pt]{article}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage{amsthm}
\usepackage{amssymb}
\usepackage{amsfonts}
\usepackage{bm}
\pagestyle{empty}
'''
DOC_BODY = r'''
\begin{document}
%s
\end{document}
'''
DOC_BODY_PREVIEW = r'''
\usepackage[active]{preview}
\begin{document}
\begin{preview}
%s
\end{preview}
\end{document}
'''
depth_re = re.compile(r'\[\d+ depth=(-?\d+)\]')
def render_math(self, math):
"""
Render the LaTeX math expression *math* using latex and dvipng.
Return the filename relative to the built document and the "depth",
that is, the distance of image bottom and baseline in pixels, if the
option to use preview_latex is switched on.
Error handling may seem strange, but follows a pattern: if LaTeX or
dvipng aren't available, only a warning is generated (since that enables
people on machines without these programs to at least build the rest
of the docs successfully). If the programs are there, however, they
may not fail since that indicates a problem in the math source.
"""
use_preview = self.builder.config.pngmath_use_preview
shasum = "%s.png" % sha(math).hexdigest()
relfn = posixpath.join(self.builder.imgpath, 'math', shasum)
outfn = path.join(self.builder.outdir, '_images', 'math', shasum)
latex = DOC_HEAD + self.builder.config.pngmath_latex_preamble
latex += (use_preview and DOC_BODY_PREVIEW or DOC_BODY) % math
if isinstance(latex, unicode):
latex = latex.encode('utf-8')
# use only one tempdir per build -- the use of a directory is cleaner
# than using temporary files, since we can clean up everything at once
# just removing the whole directory (see cleanup_tempdir)
if not hasattr(self.builder, '_mathpng_tempdir'):
tempdir = self.builder._mathpng_tempdir = tempfile.mkdtemp()
else:
tempdir = self.builder._mathpng_tempdir
tf = open(path.join(tempdir, 'math.tex'), 'w')
tf.write(latex)
tf.close()
ltx_args = [self.builder.config.pngmath_latex,
'--interaction=nonstopmode',
'--output-directory=' + tempdir,
'math.tex']
try:
p = Popen(ltx_args, stdout=PIPE, stderr=PIPE)
except OSError, err:
if err.errno != 2: # No such file or directory
raise
if not hasattr(self.builder, '_mathpng_warned_latex'):
self.builder.warn('LaTeX command %r cannot be run (needed for math '
'display), check the pngmath_latex setting' %
self.builder.config.pngmath_latex)
self.builder._mathpng_warned_latex = True
return relfn, None
stdout, stderr = p.communicate()
if p.returncode != 0:
raise MathExtError('latex exited with error:\n' + stdout)
ensuredir(path.dirname(outfn))
# use some standard dvipng arguments
dvipng_args = [self.builder.config.pngmath_dvipng, '-o', outfn,
'-bg', 'Transparent', '-T', 'tight', '-z9']
# add custom ones from config value
dvipng_args.extend(self.builder.config.pngmath_dvipng_args)
if use_preview:
dvipng_args.append('--depth')
# last, the input file name
dvipng_args.append(path.join(tempdir, 'math.dvi'))
try:
p = Popen(dvipng_args, stdout=PIPE, stderr=PIPE)
except OSError, err:
if err.errno != 2: # No such file or directory
raise
if not hasattr(self.builder, '_mathpng_warned_dvipng'):
self.builder.warn('dvipng command %r cannot be run (needed for math '
'display), check the pngmath_dvipng setting' %
self.builder.config.pngmath_dvipng)
self.builder._mathpng_warned_dvipng = True
return relfn, None
stdout, stderr = p.communicate()
if p.returncode != 0:
raise MathExtError('dvipng exited with error:\n[stdout]\n%s\n[stderr]%s'
% (stdout, stderr))
depth = None
if use_preview:
for line in stdout.splitlines():
m = depth_re.match(line)
if m:
depth = int(m.group(1))
break
return relfn, depth
def cleanup_tempdir(app, exc):
if exc:
return
if not hasattr(app.builder, '_mathpng_tempdir'):
return
try:
shutil.rmtree(app.builder._mathpng_tempdir)
except Exception:
pass
def html_visit_math(self, node):
fname, depth = render_math(self, '$'+node['latex']+'$')
self.body.append('<img src="%s" alt="%s" %s/>' %
(fname, self.encode(node['latex']),
depth and 'style="vertical-align: %dpx" ' % (-depth) or ''))
raise nodes.SkipNode
def html_visit_displaymath(self, node):
latex = wrap_displaymath(node['latex'], None)
fname, depth = render_math(self, latex)
self.body.append(self.starttag(node, 'div', CLASS='math'))
self.body.append('<p>')
if node['number']:
self.body.append('<span class="eqno">(%s)</span>' % node['number'])
self.body.append('<img src="%s" alt="%s" />\n</div>' %
(fname, self.encode(node['latex'])))
self.body.append('</p>')
raise nodes.SkipNode
def setup(app):
mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
app.add_config_value('pngmath_dvipng', 'dvipng', False)
app.add_config_value('pngmath_latex', 'latex', False)
app.add_config_value('pngmath_use_preview', False, False)
app.add_config_value('pngmath_dvipng_args', [], False)
app.add_config_value('pngmath_latex_preamble', '', False)
app.connect('build-finished', cleanup_tempdir)

View File

@ -814,6 +814,14 @@ form.comment textarea {
border: 3px solid red;
}
div.math {
text-align: center;
}
span.eqno {
float: right;
}
/* :::: PRINT :::: */
@media print {
div.document,

File diff suppressed because one or more lines are too long

View File

@ -502,3 +502,11 @@ ul.search li div.context {
ul.keywordmatches li.goodmatch a {
font-weight: bold;
}
div.math {
text-align: center;
}
span.eqno {
float: right;
}

View File

@ -108,9 +108,9 @@
FILE_SUFFIX: '{{ file_suffix }}'
};
</script>
<script type="text/javascript" src="{{ pathto('_static/jquery.js', 1) }}"></script>
<script type="text/javascript" src="{{ pathto('_static/interface.js', 1) }}"></script>
<script type="text/javascript" src="{{ pathto('_static/doctools.js', 1) }}"></script>
{%- for scriptfile in script_files %}
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
{%- endfor %}
{%- if use_opensearch %}
<link rel="search" type="application/opensearchdescription+xml"
title="Search within {{ docstitle }}"

View File

@ -1,8 +1,6 @@
{% extends "layout.html" %}
{% set title = 'Search' %}
{% block extrahead %}
<script type="text/javascript" src="{{ pathto('_static/searchtools.js', 1) }}"></script>
{% endblock %}
{% set script_files = script_files + ['searchtools.js'] %}
{% block body %}
<h1 id="search-documentation">Search</h1>
<p>