mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge pull request #4166 from jahn/math_numfig
Number equations across pages and by section (fix #3991, #4080)
This commit is contained in:
commit
e2bf2ef11d
1
CHANGES
1
CHANGES
@ -49,6 +49,7 @@ Features added
|
|||||||
* HTML themes can set up default sidebars through ``theme.conf``
|
* HTML themes can set up default sidebars through ``theme.conf``
|
||||||
* #3160: html: Use ``<kdb>`` to represent ``:kbd:`` role
|
* #3160: html: Use ``<kdb>`` to represent ``:kbd:`` role
|
||||||
* #4212: autosummary: catch all exceptions when importing modules
|
* #4212: autosummary: catch all exceptions when importing modules
|
||||||
|
* #3991, #4080: Add :confval:`math_numfig` for equation numbering by section
|
||||||
|
|
||||||
|
|
||||||
Features removed
|
Features removed
|
||||||
|
@ -44,6 +44,16 @@ or use Python raw strings (``r"raw"``).
|
|||||||
|
|
||||||
Example: ``'Eq.{number}'`` is rendered as ``Eq.10``
|
Example: ``'Eq.{number}'`` is rendered as ``Eq.10``
|
||||||
|
|
||||||
|
.. confval:: math_numfig
|
||||||
|
|
||||||
|
If ``True``, displayed math equations are numbered across pages in html and
|
||||||
|
related (epub, ...) output when :confval:`numfig` is enabled.
|
||||||
|
:confval:`numfig_secnum_depth` is respected. The :rst:role:`eq` role must
|
||||||
|
be used to reference equation numbers, not the :rst:role:`numref` role.
|
||||||
|
Default is ``True``.
|
||||||
|
|
||||||
|
.. versionadded:: 1.7
|
||||||
|
|
||||||
:mod:`.mathbase` defines these new markup elements:
|
:mod:`.mathbase` defines these new markup elements:
|
||||||
|
|
||||||
.. rst:role:: math
|
.. rst:role:: math
|
||||||
|
@ -30,6 +30,7 @@ from sphinx.util.png import read_png_depth, write_png_depth
|
|||||||
from sphinx.util.osutil import ensuredir, ENOENT, cd
|
from sphinx.util.osutil import ensuredir, ENOENT, cd
|
||||||
from sphinx.util.pycompat import sys_encoding
|
from sphinx.util.pycompat import sys_encoding
|
||||||
from sphinx.ext.mathbase import setup_math as mathbase_setup, wrap_displaymath
|
from sphinx.ext.mathbase import setup_math as mathbase_setup, wrap_displaymath
|
||||||
|
from sphinx.ext.mathbase import get_node_equation_number
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
@ -333,7 +334,8 @@ def html_visit_displaymath(self, node):
|
|||||||
self.body.append(self.starttag(node, 'div', CLASS='math'))
|
self.body.append(self.starttag(node, 'div', CLASS='math'))
|
||||||
self.body.append('<p>')
|
self.body.append('<p>')
|
||||||
if node['number']:
|
if node['number']:
|
||||||
self.body.append('<span class="eqno">(%s)' % node['number'])
|
number = get_node_equation_number(self, node)
|
||||||
|
self.body.append('<span class="eqno">(%s)' % number)
|
||||||
self.add_permalink_ref(node, _('Permalink to this equation'))
|
self.add_permalink_ref(node, _('Permalink to this equation'))
|
||||||
self.body.append('</span>')
|
self.body.append('</span>')
|
||||||
if fname is None:
|
if fname is None:
|
||||||
|
@ -16,6 +16,7 @@ import sphinx
|
|||||||
from sphinx.locale import _
|
from sphinx.locale import _
|
||||||
from sphinx.application import ExtensionError
|
from sphinx.application import ExtensionError
|
||||||
from sphinx.ext.mathbase import setup_math as mathbase_setup
|
from sphinx.ext.mathbase import setup_math as mathbase_setup
|
||||||
|
from sphinx.ext.mathbase import get_node_equation_number
|
||||||
|
|
||||||
|
|
||||||
def html_visit_math(self, node):
|
def html_visit_math(self, node):
|
||||||
@ -35,7 +36,8 @@ def html_visit_displaymath(self, node):
|
|||||||
if i == 0:
|
if i == 0:
|
||||||
# necessary to e.g. set the id property correctly
|
# necessary to e.g. set the id property correctly
|
||||||
if node['number']:
|
if node['number']:
|
||||||
self.body.append('<span class="eqno">(%s)' % node['number'])
|
number = get_node_equation_number(self, node)
|
||||||
|
self.body.append('<span class="eqno">(%s)' % number)
|
||||||
self.add_permalink_ref(node, _('Permalink to this equation'))
|
self.add_permalink_ref(node, _('Permalink to this equation'))
|
||||||
self.body.append('</span>')
|
self.body.append('</span>')
|
||||||
self.body.append(self.starttag(node, 'div', CLASS='math'))
|
self.body.append(self.starttag(node, 'div', CLASS='math'))
|
||||||
|
@ -84,6 +84,13 @@ class MathDomain(Domain):
|
|||||||
newnode['target'] = target
|
newnode['target'] = target
|
||||||
return newnode
|
return newnode
|
||||||
else:
|
else:
|
||||||
|
if env.config.math_numfig and env.config.numfig:
|
||||||
|
if docname in env.toc_fignumbers:
|
||||||
|
id = 'equation-' + target
|
||||||
|
number = env.toc_fignumbers[docname]['displaymath'].get(id, ())
|
||||||
|
number = '.'.join(map(str, number))
|
||||||
|
else:
|
||||||
|
number = ''
|
||||||
try:
|
try:
|
||||||
eqref_format = env.config.math_eqref_format or "({number})"
|
eqref_format = env.config.math_eqref_format or "({number})"
|
||||||
title = nodes.Text(eqref_format.format(number=number))
|
title = nodes.Text(eqref_format.format(number=number))
|
||||||
@ -126,6 +133,23 @@ class MathDomain(Domain):
|
|||||||
return len(targets) + 1
|
return len(targets) + 1
|
||||||
|
|
||||||
|
|
||||||
|
def get_node_equation_number(writer, node):
|
||||||
|
if writer.builder.config.math_numfig and writer.builder.config.numfig:
|
||||||
|
figtype = 'displaymath'
|
||||||
|
if writer.builder.name == 'singlehtml':
|
||||||
|
key = u"%s/%s" % (writer.docnames[-1], figtype)
|
||||||
|
else:
|
||||||
|
key = figtype
|
||||||
|
|
||||||
|
id = node['ids'][0]
|
||||||
|
number = writer.builder.fignumbers.get(key, {}).get(id, ())
|
||||||
|
number = '.'.join(map(str, number))
|
||||||
|
else:
|
||||||
|
number = node['number']
|
||||||
|
|
||||||
|
return number
|
||||||
|
|
||||||
|
|
||||||
def wrap_displaymath(math, label, numbering):
|
def wrap_displaymath(math, label, numbering):
|
||||||
# type: (unicode, unicode, bool) -> unicode
|
# type: (unicode, unicode, bool) -> unicode
|
||||||
def is_equation(part):
|
def is_equation(part):
|
||||||
@ -341,6 +365,7 @@ def setup_math(app, htmlinlinevisitors, htmldisplayvisitors):
|
|||||||
# type: (Sphinx, Tuple[Callable, Any], Tuple[Callable, Any]) -> None
|
# type: (Sphinx, Tuple[Callable, Any], Tuple[Callable, Any]) -> None
|
||||||
app.add_config_value('math_number_all', False, 'env')
|
app.add_config_value('math_number_all', False, 'env')
|
||||||
app.add_config_value('math_eqref_format', None, 'env', string_classes)
|
app.add_config_value('math_eqref_format', None, 'env', string_classes)
|
||||||
|
app.add_config_value('math_numfig', True, 'env')
|
||||||
app.add_domain(MathDomain)
|
app.add_domain(MathDomain)
|
||||||
app.add_node(math, override=True,
|
app.add_node(math, override=True,
|
||||||
latex=(latex_visit_math, None),
|
latex=(latex_visit_math, None),
|
||||||
@ -348,7 +373,7 @@ def setup_math(app, htmlinlinevisitors, htmldisplayvisitors):
|
|||||||
man=(man_visit_math, None),
|
man=(man_visit_math, None),
|
||||||
texinfo=(texinfo_visit_math, None),
|
texinfo=(texinfo_visit_math, None),
|
||||||
html=htmlinlinevisitors)
|
html=htmlinlinevisitors)
|
||||||
app.add_node(displaymath,
|
app.add_enumerable_node(displaymath, 'displaymath',
|
||||||
latex=(latex_visit_displaymath, None),
|
latex=(latex_visit_displaymath, None),
|
||||||
text=(text_visit_displaymath, None),
|
text=(text_visit_displaymath, None),
|
||||||
man=(man_visit_displaymath, man_depart_displaymath),
|
man=(man_visit_displaymath, man_depart_displaymath),
|
||||||
|
@ -17,6 +17,7 @@ import sphinx
|
|||||||
from sphinx.locale import _
|
from sphinx.locale import _
|
||||||
from sphinx.errors import ExtensionError
|
from sphinx.errors import ExtensionError
|
||||||
from sphinx.ext.mathbase import setup_math as mathbase_setup
|
from sphinx.ext.mathbase import setup_math as mathbase_setup
|
||||||
|
from sphinx.ext.mathbase import get_node_equation_number
|
||||||
|
|
||||||
|
|
||||||
def html_visit_math(self, node):
|
def html_visit_math(self, node):
|
||||||
@ -36,7 +37,8 @@ def html_visit_displaymath(self, node):
|
|||||||
|
|
||||||
# necessary to e.g. set the id property correctly
|
# necessary to e.g. set the id property correctly
|
||||||
if node['number']:
|
if node['number']:
|
||||||
self.body.append('<span class="eqno">(%s)' % node['number'])
|
number = get_node_equation_number(self, node)
|
||||||
|
self.body.append('<span class="eqno">(%s)' % number)
|
||||||
self.add_permalink_ref(node, _('Permalink to this equation'))
|
self.add_permalink_ref(node, _('Permalink to this equation'))
|
||||||
self.body.append('</span>')
|
self.body.append('</span>')
|
||||||
self.body.append(self.builder.config.mathjax_display[0])
|
self.body.append(self.builder.config.mathjax_display[0])
|
||||||
|
@ -30,6 +30,7 @@ from sphinx.util.png import read_png_depth, write_png_depth
|
|||||||
from sphinx.util.osutil import ensuredir, ENOENT, cd
|
from sphinx.util.osutil import ensuredir, ENOENT, cd
|
||||||
from sphinx.util.pycompat import sys_encoding
|
from sphinx.util.pycompat import sys_encoding
|
||||||
from sphinx.ext.mathbase import setup_math as mathbase_setup, wrap_displaymath
|
from sphinx.ext.mathbase import setup_math as mathbase_setup, wrap_displaymath
|
||||||
|
from sphinx.ext.mathbase import get_node_equation_number
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
@ -242,7 +243,8 @@ def html_visit_displaymath(self, node):
|
|||||||
self.body.append(self.starttag(node, 'div', CLASS='math'))
|
self.body.append(self.starttag(node, 'div', CLASS='math'))
|
||||||
self.body.append('<p>')
|
self.body.append('<p>')
|
||||||
if node['number']:
|
if node['number']:
|
||||||
self.body.append('<span class="eqno">(%s)</span>' % node['number'])
|
number = get_node_equation_number(self, node)
|
||||||
|
self.body.append('<span class="eqno">(%s)</span>' % number)
|
||||||
if fname is None:
|
if fname is None:
|
||||||
# something failed -- use text-only as a bad substitute
|
# something failed -- use text-only as a bad substitute
|
||||||
self.body.append('<span class="math">%s</span></p>\n</div>' %
|
self.body.append('<span class="math">%s</span></p>\n</div>' %
|
||||||
|
@ -2,8 +2,10 @@ Test Math
|
|||||||
=========
|
=========
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
|
:numbered: 1
|
||||||
|
|
||||||
math
|
math
|
||||||
|
page
|
||||||
|
|
||||||
.. math:: a^2+b^2=c^2
|
.. math:: a^2+b^2=c^2
|
||||||
|
|
||||||
|
9
tests/roots/test-ext-math/page.rst
Normal file
9
tests/roots/test-ext-math/page.rst
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
Test multiple pages
|
||||||
|
===================
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
:label: bar
|
||||||
|
|
||||||
|
a = b + 1
|
||||||
|
|
||||||
|
Referencing equations :eq:`foo` and :eq:`bar`.
|
@ -157,3 +157,52 @@ def test_math_eqref_format_latex(app, status, warning):
|
|||||||
content = (app.outdir / 'test.tex').text()
|
content = (app.outdir / 'test.tex').text()
|
||||||
macro = r'Referencing equation Eq.\\ref{equation:math:foo}.'
|
macro = r'Referencing equation Eq.\\ref{equation:math:foo}.'
|
||||||
assert re.search(macro, content, re.S)
|
assert re.search(macro, content, re.S)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-math',
|
||||||
|
confoverrides={'extensions': ['sphinx.ext.mathjax'],
|
||||||
|
'numfig': True,
|
||||||
|
'math_numfig': True})
|
||||||
|
def test_mathjax_numfig_html(app, status, warning):
|
||||||
|
app.builder.build_all()
|
||||||
|
|
||||||
|
content = (app.outdir / 'math.html').text()
|
||||||
|
html = ('<div class="math" id="equation-math:0">\n'
|
||||||
|
'<span class="eqno">(1.2)')
|
||||||
|
assert html in content
|
||||||
|
html = ('<p>Referencing equation <a class="reference internal" '
|
||||||
|
'href="#equation-foo">(1.1)</a>.</p>')
|
||||||
|
assert html in content
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-math',
|
||||||
|
confoverrides={'extensions': ['sphinx.ext.jsmath'],
|
||||||
|
'jsmath_path': 'dummy.js',
|
||||||
|
'numfig': True,
|
||||||
|
'math_numfig': True})
|
||||||
|
def test_jsmath_numfig_html(app, status, warning):
|
||||||
|
app.builder.build_all()
|
||||||
|
|
||||||
|
content = (app.outdir / 'math.html').text()
|
||||||
|
html = '<span class="eqno">(1.2)<a class="headerlink" href="#equation-math:0"'
|
||||||
|
assert html in content
|
||||||
|
html = ('<p>Referencing equation <a class="reference internal" '
|
||||||
|
'href="#equation-foo">(1.1)</a>.</p>')
|
||||||
|
assert html in content
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-math',
|
||||||
|
confoverrides={'extensions': ['sphinx.ext.imgmath'],
|
||||||
|
'numfig': True,
|
||||||
|
'numfig_secnum_depth': 0,
|
||||||
|
'math_numfig': True})
|
||||||
|
def test_imgmath_numfig_html(app, status, warning):
|
||||||
|
app.builder.build_all()
|
||||||
|
|
||||||
|
content = (app.outdir / 'page.html').text()
|
||||||
|
html = '<span class="eqno">(3)<a class="headerlink" href="#equation-bar"'
|
||||||
|
assert html in content
|
||||||
|
html = ('<p>Referencing equations <a class="reference internal" '
|
||||||
|
'href="math.html#equation-foo">(1)</a> and '
|
||||||
|
'<a class="reference internal" href="#equation-bar">(3)</a>.</p>')
|
||||||
|
assert html in content
|
||||||
|
Loading…
Reference in New Issue
Block a user