|
From: <mi...@us...> - 2021-05-20 12:23:27
|
Revision: 8751
http://sourceforge.net/p/docutils/code/8751
Author: milde
Date: 2021-05-20 12:23:24 +0000 (Thu, 20 May 2021)
Log Message:
-----------
MathML: Refactor XML output routines.
Modified Paths:
--------------
trunk/docutils/docs/user/mathematics.txt
trunk/docutils/docutils/utils/math/latex2mathml.py
trunk/docutils/test/functional/expected/math_output_mathml.html
Modified: trunk/docutils/docs/user/mathematics.txt
===================================================================
--- trunk/docutils/docs/user/mathematics.txt 2021-05-20 12:23:06 UTC (rev 8750)
+++ trunk/docutils/docs/user/mathematics.txt 2021-05-20 12:23:24 UTC (rev 8751)
@@ -40,7 +40,7 @@
The **math role** can be used for inline mathematical expressions:
``:math:`\psi(r) = \exp(-2r)``` will produce :m:`\psi(r)=\exp(-2r)`.
Inside the backtics you can write anything you would write between dollar
-signs in a LaTeX document.
+signs in a LaTeX document. [#math-syntax]_
.. tip::
@@ -286,14 +286,6 @@
For mathematical variables where style variations are important semantically,
select an appropriate *math alphabet* [#]_.
-.. [#] TeX’s *math alphabets* correspond to the `mathematical
- alphanumeric symbols`__ block in Unicode and the "mathvariant" `style
- attribute`__ in MathML.
-
-
-__ https://en.wikipedia.org/wiki/Mathematical_Alphanumeric_Symbols
-__ https://developer.mozilla.org/en-US/docs/Web/MathML/Attribute
-
.. class:: colwidths-auto
=============== ============================ ==========================
@@ -309,6 +301,13 @@
``\mathtt`` ``\mathtt{0.12}`` `\mathtt{0.12}`
=============== ============================ ==========================
+.. [#] TeX’s *math alphabets* correspond to the `mathematical
+ alphanumeric symbols`__ block in Unicode and the "mathvariant" `style
+ attribute`__ in MathML.
+
+ __ https://en.wikipedia.org/wiki/Mathematical_Alphanumeric_Symbols
+ __ https://developer.mozilla.org/en-US/docs/Web/MathML/Attribute
+
Additional alphabets are defined in LaTeX packages, e.g.
.. class:: colwidths-auto
@@ -324,7 +323,7 @@
.. _isomath: https://www.ctan.org/pkg/isomath
.. _mathrsfs: https://www.ctan.org/pkg/mathrsfs
-This can be used to typeset vector symbols in **bold** *italic*
+This can be used to typeset vector symbols in bold italic
in line with the International Standard [ISO-80000-2].
.. ``\mathbfit{r}^2=x^2+y^2+z^2`` becomes
@@ -397,7 +396,7 @@
======== ===============
.. [#] Punctuation (not ratio):
- Compare spacing in `a\colon b\to c` and `a:b = c`.
+ Compare spacing in `a\colon b\to c` to `a:b = c`.
Relation symbols
Modified: trunk/docutils/docutils/utils/math/latex2mathml.py
===================================================================
--- trunk/docutils/docutils/utils/math/latex2mathml.py 2021-05-20 12:23:06 UTC (rev 8750)
+++ trunk/docutils/docutils/utils/math/latex2mathml.py 2021-05-20 12:23:24 UTC (rev 8751)
@@ -15,8 +15,7 @@
# .. _2-Clause BSD license: https://opensource.org/licenses/BSD-2-Clause
-"""Convert LaTex maths code into presentational MathML.
-"""
+"""Convert LaTex maths code into presentational MathML."""
# .. [1] the original `rst2mathml.py` in `sandbox/jensj/latex_math`
#
@@ -50,7 +49,7 @@
'Upsilon':u'\u03d2', 'Pi':u'\u03a0', 'Omega':u'\u03a9',
'Gamma':u'\u0393', 'Lambda':u'\u039b'}
-# functions -> <mi> + ApplyFunction
+# functions -> <mi>
functions = ['arccos', 'arcsin', 'arctan', 'arg', 'cos', 'cosh',
'cot', 'coth', 'csc', 'deg', 'det', 'dim',
'exp', 'gcd', 'hom', 'inf', 'ker', 'lg',
@@ -250,7 +249,7 @@
# ----------------------
class math(object):
- """Base class for MathML elements."""
+ """Base class for MathML elements and root of MathML trees."""
nchildren = None
"""Expected number of children or None"""
@@ -259,9 +258,7 @@
_level = 0 # indentation level (static class variable)
def __init__(self, *children, **attributes):
- """math(*children **attributes) -> MathML element
- """
-
+ """Set up node with `children` and `attributes`."""
self.children = []
for child in children:
self.append(child)
@@ -270,7 +267,7 @@
# sort attributes for predictable functional tests
# as self.attributes.update(attributes) does not keep order in Python < 3.6
for key in sorted(attributes.keys()):
- self.attributes.setdefault(key, attributes[key])
+ self.attributes[key] = attributes[key]
def __repr__(self):
content = [repr(item) for item in getattr(self, 'children', [])]
@@ -283,16 +280,16 @@
return self.__class__.__name__ + '(%s)' % ', '.join(content)
def full(self):
- """Room for more children?"""
+ """Return boolean indicating whether children may be appended."""
return (self.nchildren is not None
and len(self.children) >= self.nchildren)
def append(self, child):
- """append(child) -> element
-
- Appends child and returns self if self is not full or first
- non-full parent."""
-
+ """Append child and return self or first non-full parent.
+
+ If self is full, go up the tree and return first non-full node or
+ `None`.
+ """
assert not self.full()
self.children.append(child)
child.parent = self
@@ -302,65 +299,53 @@
return node
def close(self):
- """close() -> parent
-
- Close element and return first non-full element."""
-
+ """Close element and return first non-full parent."""
parent = self.parent
while parent.full():
parent = parent.parent
return parent
+
+ def toprettyxml(self):
+ """Return XML representation of self as string."""
+ return ''.join(self._xml())
+
+ def _xml(self, level=0):
+ return ([self.xml_starttag()]
+ + self._xml_body(level)
+ + ['</%s>' % self.__class__.__name__])
- def xml(self):
- """xml() -> xml-string"""
-
- return self.xml_start() + self.xml_body() + self.xml_end()
-
- def xml_start(self):
+ def xml_starttag(self):
# Use k.lower() to allow argument `CLASS` for attribute `class`
# (Python keyword). MathML uses only lowercase attributes.
- attrs = ['%s="%s"'%(k.lower(), v) for k, v
- in getattr(self, 'attributes', {}).items()]
- if not isinstance(self, MathToken): # token elements
- math._level += 1
- return ['<%s>' % ' '.join([self.__class__.__name__] + attrs)]
+ attrs = ['%s="%s"'%(k.lower(), v) for k, v in self.attributes.items()]
+ return '<%s>' % ' '.join([self.__class__.__name__] + attrs)
- def xml_end(self):
+ def _xml_body(self, level=0):
xml = []
- if not isinstance(self, MathToken): # except token elements
- math._level -= 1
- xml.append('\n' + ' ' * math._level)
- xml.append('</%s>' % self.__class__.__name__)
- return xml
-
- def xml_body(self):
- xml = []
- last_child = None
for child in self.children:
- if not (isinstance(last_child, MathToken) and isinstance(child, MathToken)):
- xml.append('\n' + ' ' * math._level)
- xml.extend(child.xml())
- last_child = child
+ xml.extend(['\n', ' ' * (level+1)])
+ xml.extend(child._xml(level+1))
+ xml.extend(['\n', ' ' * level])
return xml
# >>> math(mn(2))
# math(mn(2))
-# >>> math(mn(2)).xml()
-# ['<math>', '\n ', '<mn>', '2', '</mn>', '\n', '</math>']
+# >>> math(mn(2)).toprettyxml()
+# '<math>\n <mn>2</mn>\n</math>'
#
# >>> math(id='eq3')
# math(id='eq3')
-# >>> math(id='eq3').xml()
-# ['<math id="eq3">', '\n', '</math>']
+# >>> math(id='eq3').toprettyxml()
+# '<math id="eq3">\n</math>'
#
# use CLASS to get "class" in XML
# >>> math(CLASS='test')
# math(CLASS='test')
-# >>> math(CLASS='test').xml()
-# ['<math class="test">', '\n', '</math>']
+# >>> math(CLASS='test').toprettyxml()
+# '<math class="test">\n</math>'
-# >>> math(xmlns='http://www.w3.org/1998/Math/MathML').xml()
-# ['<math xmlns="http://www.w3.org/1998/Math/MathML">', '\n', '</math>']
+# >>> math(xmlns='http://www.w3.org/1998/Math/MathML').toprettyxml()
+# '<math xmlns="http://www.w3.org/1998/Math/MathML">\n</math>'
class mrow(math):
"""Group sub-expressions as a horizontal row."""
@@ -372,10 +357,9 @@
# >>> mtable(displaystyle='true')
# mtable(displaystyle='true')
-# >>> math(mtable(displaystyle='true')).xml()
-# ['<math>', '\n ', '<mtable displaystyle="true">', '\n ', '</mtable>', '\n', '</math>']
+# >>> math(mtable(displaystyle='true')).toprettyxml()
+# '<math>\n <mtable displaystyle="true">\n </mtable>\n</math>'
-
# The elements <msqrt>, <mstyle>, <merror>, <mpadded>, <mphantom>, <menclose>,
# <mtd>, <mscarry>, and <math> treat their contents as a single inferred mrow
# formed from all their children.
@@ -385,8 +369,7 @@
class mtd(mrow): pass
class MathToken(math):
- """Token Element: Base class for mo, mi, and mn.
- """
+ """Token Element: Base class for mo, mi, and mn."""
nchildren = 0
entity_table = {ord('<'): u'<', ord('>'): u'>'}
@@ -394,7 +377,7 @@
self.data = data
super(MathToken, self).__init__(**attributes)
- def xml_body(self):
+ def _xml_body(self, level=0):
return [unicode(self.data).translate(self.entity_table)]
class mi(MathToken): pass
@@ -404,7 +387,7 @@
# >>> mo(u'<')
# mo('<')
-# >>> mo(u'<').xml()
+# >>> mo(u'<')._xml()
# ['<mo>', '<', '</mo>']
class MathScriptOrLimit(math):
@@ -412,14 +395,20 @@
nchildren = 2
def __init__(self, *children, **kwargs):
+ """Set up sub/superscript or limit elements.
+
+ The special attribute `reversed` tells that the
+ base and index sub-elements are in reversed order
+ (i.e. as in LaTeX) and will be switched on XML-export.
+ """
self.reversed = kwargs.pop('reversed', False)
math.__init__(self, *children, **kwargs)
-
- def xml(self):
+
+ def _xml(self, level=0):
if self.reversed:
self.children.reverse()
self.reversed = False
- return super(MathScriptOrLimit, self).xml()
+ return super(MathScriptOrLimit, self)._xml(level)
class msub(MathScriptOrLimit): pass
class msup(MathScriptOrLimit): pass
@@ -435,8 +424,8 @@
# munder(mi('lim'), mo('-'), accent='false')
# >>> munder(mo('-'), mi('lim'), accent='false', reversed=True)
# munder(mo('-'), mi('lim'), reversed=True, accent='false')
-# >>> ''.join(munder(mo('-'), mi('lim'), accent='false', reversed=True).xml())
-# '<munder accent="false">\n <mi>lim</mi><mo>-</mo>\n</munder>'
+# >>> munder(mo('-'), mi('lim'), accent='false', reversed=True).toprettyxml()
+# '<munder accent="false">\n <mi>lim</mi>\n <mo>-</mo>\n</munder>'
# >>> msub(mi('x'), mo('-'))
# msub(mi('x'), mo('-'))
@@ -458,14 +447,14 @@
# ~~~~~~~~~~~~~~~~~~~
def tex_cmdname(string):
- """Return leading TeX command name from `string`.
+ """Return leading TeX command name and remainder of `string`.
- >>> tex_cmdname('name2') # up to first non-letter
- ('name', '2')
- >>> tex_cmdname('name 2') # strip trailing whitespace
- ('name', '2')
- >>> tex_cmdname('_2') # single non-letter character
- ('_', '2')
+ >>> tex_cmdname('mymacro2') # up to first non-letter
+ ('mymacro', '2')
+ >>> tex_cmdname('name 2') # strip trailing whitespace
+ ('name', '2')
+ >>> tex_cmdname('_2') # single non-letter character
+ ('_', '2')
"""
m = re.match(r'([a-zA-Z]+) *(.*)', string)
@@ -488,17 +477,15 @@
# --- https://www.w3.org/TR/MathML3/chapter3.html#id.3.1.3.2
def tex_token(string):
- """Take first simple TeX token from `string`.
+ """Return first simple TeX token and remainder of `string`.
- Return token and remainder.
-
- >>> tex_token('{first simple group} {without brackets}')
- ('first simple group', ' {without brackets}')
- >>> tex_token('\\command{without argument}')
- ('\\command', '{without argument}')
- >>> tex_token(' first non-white character')
- ('f', 'irst non-white character')
-
+ >>> tex_token('{first simple group} returned without brackets')
+ ('first simple group', ' returned without brackets')
+ >>> tex_token('\\command{without argument}')
+ ('\\command', '{without argument}')
+ >>> tex_token(' first non-white character')
+ ('f', 'irst non-white character')
+
"""
m = re.match(r"""\s* # leading whitespace
{(?P<token>(\\}|[^{}]|\\{)*)} # {group} without nested groups
@@ -536,14 +523,12 @@
def parse_latex_math(string, inline=True):
- """parse_latex_math(string [,inline]) -> MathML-tree
+ """Return a MathML-tree parsed from `string`.
- Return a MathML-tree parsed from `string`.
+ >>> parse_latex_math('\\alpha')
+ math(mi('α'), xmlns='http://www.w3.org/1998/Math/MathML')
+
Set `inline` to False for displayed math.
-
- >>> parse_latex_math('\\alpha')
- math(mi('α'), xmlns='http://www.w3.org/1998/Math/MathML')
-
"""
# Normalize white-space:
@@ -620,7 +605,6 @@
raise SyntaxError(u'Illegal character: "%s"' % c)
return tree
-
# Test:
# >>> parse_latex_math('', inline=True)
@@ -640,12 +624,12 @@
"""Process LaTeX macro `name` followed by `string`.
If needed, parse `string` for macro argument.
- Return updated current node and remainder:
+ Return updated current node and remainder of `string`:
- >>> handle_keyword('hbar', math(), r' \frac')
- (math(mi('ℏ')), ' \\frac')
- >>> handle_keyword('hspace', math(), r'{1ex} (x)')
- (math(mspace(width='1ex')), ' (x)')
+ >>> handle_keyword('hbar', math(), r' \frac')
+ (math(mi('ℏ')), ' \\frac')
+ >>> handle_keyword('hspace', math(), r'{1ex} (x)')
+ (math(mspace(width='1ex')), ' (x)')
"""
@@ -685,7 +669,9 @@
node = node.append(identifier)
# TODO: only add ApplyFunction when appropriate (not \sin ^2(x), say)
- node = node.append(mo('⁡')) # '\u2061'
+ arg, remainder = tex_token(string)
+ if arg not in ('^', '_'):
+ node = node.append(mo('⁡')) # '\u2061'
return node, string
@@ -746,10 +732,6 @@
node = node.append(mo(small_operators[name], mathsize='75%'))
return node, string
- if name in sumintprod:
- node = node.append(mo(operators[name]))
- return node, string
-
if name in operators:
node = node.append(mo(operators[name]))
return node, string
@@ -903,8 +885,8 @@
def tex2mathml(tex_math, inline=True):
"""Return string with MathML code corresponding to `tex_math`.
- `inline`=True is for inline math and `inline`=False for displayed math.
+ Set `inline` to False for displayed math.
"""
mathml_tree = parse_latex_math(tex_math, inline=inline)
- return ''.join(mathml_tree.xml())
+ return mathml_tree.toprettyxml()
Modified: trunk/docutils/test/functional/expected/math_output_mathml.html
===================================================================
--- trunk/docutils/test/functional/expected/math_output_mathml.html 2021-05-20 12:23:06 UTC (rev 8750)
+++ trunk/docutils/test/functional/expected/math_output_mathml.html 2021-05-20 12:23:24 UTC (rev 8751)
@@ -14,14 +14,22 @@
<p>Docutils supports inline math with the prefix or postfix <span class="docutils literal">:math:</span>
role specificator, <math xmlns="http://www.w3.org/1998/Math/MathML">
- <mi>n</mi><mo>!</mo><mo>+</mo><mi>sin</mi><mo>⁡</mo><mo stretchy="false">(</mo>
+ <mi>n</mi>
+ <mo>!</mo>
+ <mo>+</mo>
+ <mi>sin</mi>
+ <mo>⁡</mo>
+ <mo stretchy="false">(</mo>
<msubsup>
- <mi>x</mi><mi>n</mi><mn>2</mn>
+ <mi>x</mi>
+ <mi>n</mi>
+ <mn>2</mn>
</msubsup>
<mo stretchy="false">)</mo>
</math> and <math xmlns="http://www.w3.org/1998/Math/MathML">
<msub>
- <mi>A</mi><mtext>c</mtext>
+ <mi>A</mi>
+ <mtext>c</mtext>
</msub>
<mo>=</mo>
<mfrac>
@@ -33,7 +41,8 @@
</mrow>
</mfrac>
<msup>
- <mi>d</mi><mn>2</mn>
+ <mi>d</mi>
+ <mn>2</mn>
</msup>
</math>, as well as displayed math via the
<cite>math</cite> directive:</p>
@@ -42,13 +51,20 @@
<mtable class="align" displaystyle="true">
<mtr>
<mtd>
- <mi>f</mi><mo stretchy="false">(</mo><mi>ϵ</mi><mo stretchy="false">)</mo><mo>=</mo>
+ <mi>f</mi>
+ <mo stretchy="false">(</mo>
+ <mi>ϵ</mi>
+ <mo stretchy="false">)</mo>
+ <mo>=</mo>
<mfrac>
<mrow>
<mn>1</mn>
</mrow>
<mrow>
- <mn>1</mn><mo>+</mo><mi>exp</mi><mo>⁡</mo>
+ <mn>1</mn>
+ <mo>+</mo>
+ <mi>exp</mi>
+ <mo>⁡</mo>
<mrow>
<mo>(</mo>
<mfrac>
@@ -57,7 +73,8 @@
</mrow>
<mrow>
<msub>
- <mi>k</mi><mtext>B</mtext>
+ <mi>k</mi>
+ <mtext>B</mtext>
</msub>
<mi>T</mi>
</mrow>
@@ -77,7 +94,8 @@
<mtable class="align" displaystyle="true">
<mtr>
<mtd>
- <mi>N</mi><mo>=</mo>
+ <mi>N</mi>
+ <mo>=</mo>
<mfrac>
<mrow>
<mtext>number of apples</mtext>
@@ -99,7 +117,8 @@
<mtable class="align" displaystyle="true">
<mtr>
<mtd>
- <mi mathvariant="bold">M</mi><mo>=</mo>
+ <mi mathvariant="bold">M</mi>
+ <mo>=</mo>
<mrow>
<mo>(</mo>
<mtable>
@@ -128,7 +147,15 @@
</math>
</div>
<p>is <math xmlns="http://www.w3.org/1998/Math/MathML">
- <mo stretchy="false">|</mo><mi mathvariant="bold">M</mi><mo stretchy="false">|</mo><mo>=</mo><mi>a</mi><mi>d</mi><mo>−</mo><mi>b</mi><mi>c</mi>
+ <mo stretchy="false">|</mo>
+ <mi mathvariant="bold">M</mi>
+ <mo stretchy="false">|</mo>
+ <mo>=</mo>
+ <mi>a</mi>
+ <mi>d</mi>
+ <mo>−</mo>
+ <mi>b</mi>
+ <mi>c</mi>
</math>.</p>
<p>More than one display math block can be put in one math directive.
For example, the following sum and integral with limits:</p>
@@ -138,18 +165,25 @@
<mtr>
<mtd>
<munderover>
- <mo movablelimits="true">∫</mo><mn>0</mn><mn>1</mn>
+ <mo movablelimits="true">∫</mo>
+ <mn>0</mn>
+ <mn>1</mn>
</munderover>
<msup>
- <mi>x</mi><mi>n</mi>
+ <mi>x</mi>
+ <mi>n</mi>
</msup>
- <mi>d</mi><mi>x</mi><mo>=</mo>
+ <mi>d</mi>
+ <mi>x</mi>
+ <mo>=</mo>
<mfrac>
<mrow>
<mn>1</mn>
</mrow>
<mrow>
- <mi>n</mi><mo>+</mo><mn>1</mn>
+ <mi>n</mi>
+ <mo>+</mo>
+ <mn>1</mn>
</mrow>
</mfrac>
</mtd>
@@ -165,14 +199,22 @@
<munderover>
<mo movablelimits="true">∑</mo>
<mrow>
- <mi>n</mi><mo>=</mo><mn>1</mn>
+ <mi>n</mi>
+ <mo>=</mo>
+ <mn>1</mn>
</mrow>
<mi>m</mi>
</munderover>
- <mi>n</mi><mo>=</mo>
+ <mi>n</mi>
+ <mo>=</mo>
<mfrac>
<mrow>
- <mi>m</mi><mo stretchy="false">(</mo><mi>m</mi><mo>+</mo><mn>1</mn><mo stretchy="false">)</mo>
+ <mi>m</mi>
+ <mo stretchy="false">(</mo>
+ <mi>m</mi>
+ <mo>+</mo>
+ <mn>1</mn>
+ <mo stretchy="false">)</mo>
</mrow>
<mrow>
<mn>2</mn>
@@ -191,16 +233,19 @@
<mtable class="align" displaystyle="true">
<mtr>
<mtd>
- <mi>i</mi><mi>ℏ</mi>
+ <mi>i</mi>
+ <mi>ℏ</mi>
<mfrac>
<mrow>
<mo>∂</mo>
</mrow>
<mrow>
- <mo>∂</mo><mi>t</mi>
+ <mo>∂</mo>
+ <mi>t</mi>
</mrow>
</mfrac>
- <mi class="capital-greek">Ψ</mi><mo>=</mo>
+ <mi class="capital-greek">Ψ</mi>
+ <mo>=</mo>
<mover accent="true">
<mrow>
<mi>H</mi>
@@ -207,7 +252,8 @@
</mrow>
<mo>ˆ</mo>
</mover>
- <mi class="capital-greek">Ψ</mi><mo>,</mo>
+ <mi class="capital-greek">Ψ</mi>
+ <mo>,</mo>
</mtd>
</mtr>
</mtable>
@@ -338,15 +384,28 @@
<mtable class="align" displaystyle="true">
<mtr>
<mtd>
- <mtext>MTF</mtext><mo>=</mo>
+ <mtext>MTF</mtext>
+ <mo>=</mo>
<mrow>
<mo>|</mo>
<mfrac>
<mrow>
- <mi mathvariant="script">F</mi><mo>{</mo><mi>s</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>}</mo>
+ <mi mathvariant="script">F</mi>
+ <mo>{</mo>
+ <mi>s</mi>
+ <mo stretchy="false">(</mo>
+ <mi>x</mi>
+ <mo stretchy="false">)</mo>
+ <mo>}</mo>
</mrow>
<mrow>
- <mi mathvariant="script">F</mi><mo>{</mo><mi>s</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>}</mo>
+ <mi mathvariant="script">F</mi>
+ <mo>{</mo>
+ <mi>s</mi>
+ <mo stretchy="false">(</mo>
+ <mi>x</mi>
+ <mo stretchy="false">)</mo>
+ <mo>}</mo>
<msub>
<mo stretchy="false">|</mo>
<mrow>
@@ -356,7 +415,8 @@
<mi>x</mi>
</mrow>
</msub>
- <mo>=</mo><mn>0</mn>
+ <mo>=</mo>
+ <mn>0</mn>
</mrow>
</msub>
</mrow>
@@ -363,7 +423,8 @@
</mfrac>
<mo>|</mo>
</mrow>
- <mo>=</mo><mi mathvariant="normal">abs</mi>
+ <mo>=</mo>
+ <mi mathvariant="normal">abs</mi>
<mrow>
<mo>(</mo>
<mfrac>
@@ -371,13 +432,17 @@
<munderover>
<mo movablelimits="true">∫</mo>
<mrow>
- <mo>−</mo><mo>∞</mo>
+ <mo>−</mo>
+ <mo>∞</mo>
</mrow>
<mrow>
<mo>∞</mo>
</mrow>
</munderover>
- <mi>s</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo>
+ <mi>s</mi>
+ <mo stretchy="false">(</mo>
+ <mi>x</mi>
+ <mo stretchy="false">)</mo>
<msup>
<mi mathvariant="normal">e</mi>
<mrow>
@@ -400,13 +465,18 @@
<munderover>
<mo movablelimits="true">∫</mo>
<mrow>
- <mo>−</mo><mo>∞</mo>
+ <mo>−</mo>
+ <mo>∞</mo>
</mrow>
<mrow>
<mo>∞</mo>
</mrow>
</munderover>
- <mi>s</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mi mathvariant="normal">d</mi>
+ <mi>s</mi>
+ <mo stretchy="false">(</mo>
+ <mi>x</mi>
+ <mo stretchy="false">)</mo>
+ <mi mathvariant="normal">d</mi>
<mrow>
<mi>x</mi>
</mrow>
@@ -434,7 +504,9 @@
<mi mathvariant="normal">out</mi>
</mrow>
</msub>
- <mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo>
+ <mo stretchy="false">(</mo>
+ <mi>x</mi>
+ <mo stretchy="false">)</mo>
</mtd>
<mtd>
<mo>=</mo>
@@ -444,11 +516,21 @@
<mi mathvariant="normal">in</mi>
</mrow>
</msub>
- <mo stretchy="false">(</mo><mi>x</mi><mo>'</mo><mo stretchy="false">)</mo><mo>*</mo>
+ <mo stretchy="false">(</mo>
+ <mi>x</mi>
+ <mo>'</mo>
+ <mo stretchy="false">)</mo>
+ <mo>*</mo>
<msub>
- <mi>s</mi><mi>δ</mi>
+ <mi>s</mi>
+ <mi>δ</mi>
</msub>
- <mo stretchy="false">(</mo><mi>x</mi><mo>−</mo><mi>x</mi><mo>'</mo><mo stretchy="false">)</mo>
+ <mo stretchy="false">(</mo>
+ <mi>x</mi>
+ <mo>−</mo>
+ <mi>x</mi>
+ <mo>'</mo>
+ <mo stretchy="false">)</mo>
</mtd>
</mtr>
<mtr>
@@ -455,7 +537,8 @@
<mtd>
</mtd>
<mtd>
- <mo>=</mo><mo>∫</mo>
+ <mo>=</mo>
+ <mo>∫</mo>
<msub>
<mi>s</mi>
<mrow>
@@ -462,11 +545,23 @@
<mi mathvariant="normal">in</mi>
</mrow>
</msub>
- <mo stretchy="false">(</mo><mi>x</mi><mo>'</mo><mo stretchy="false">)</mo>
+ <mo stretchy="false">(</mo>
+ <mi>x</mi>
+ <mo>'</mo>
+ <mo stretchy="false">)</mo>
<msub>
- <mi>s</mi><mi>δ</mi>
+ <mi>s</mi>
+ <mi>δ</mi>
</msub>
- <mo stretchy="false">(</mo><mi>x</mi><mo>−</mo><mi>x</mi><mo>'</mo><mo stretchy="false">)</mo><mi mathvariant="normal">d</mi><mi>x</mi><mo>'</mo>
+ <mo stretchy="false">(</mo>
+ <mi>x</mi>
+ <mo>−</mo>
+ <mi>x</mi>
+ <mo>'</mo>
+ <mo stretchy="false">)</mo>
+ <mi mathvariant="normal">d</mi>
+ <mi>x</mi>
+ <mo>'</mo>
</mtd>
</mtr>
</mtable>
@@ -478,16 +573,23 @@
<mtable class="align" displaystyle="true">
<mtr>
<mtd>
- <mi mathvariant="normal">sgn</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo>
+ <mi mathvariant="normal">sgn</mi>
+ <mo stretchy="false">(</mo>
+ <mi>x</mi>
+ <mo stretchy="false">)</mo>
+ <mo>=</mo>
<mrow>
<mo>{</mo>
<mtable>
<mtr>
<mtd>
- <mo>−</mo><mn>1</mn>
+ <mo>−</mo>
+ <mn>1</mn>
</mtd>
<mtd>
- <mi>x</mi><mo><</mo><mn>0</mn>
+ <mi>x</mi>
+ <mo><</mo>
+ <mn>0</mn>
</mtd>
</mtr>
<mtr>
@@ -495,7 +597,9 @@
<mn>1</mn>
</mtd>
<mtd>
- <mi>x</mi><mo>></mo><mn>0</mn>
+ <mi>x</mi>
+ <mo>></mo>
+ <mn>0</mn>
</mtd>
</mtr>
</mtable>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2021-05-20 12:23:48
|
Revision: 8752
http://sourceforge.net/p/docutils/code/8752
Author: milde
Date: 2021-05-20 12:23:41 +0000 (Thu, 20 May 2021)
Log Message:
-----------
MathML: new text_optarg(), refactor parse_latex_math(), support more TeX cmds.
tex_optarg(): New function to extract an optional argument
parse_latex_math() now expects a start-node to expand and returns new
current node (makes it usable for nested parsing),
Support for \overset, \underset, \xrightarrow, \xleftarrow.
Modified Paths:
--------------
trunk/docutils/docs/user/mathematics.txt
trunk/docutils/docutils/utils/math/latex2mathml.py
trunk/docutils/test/functional/expected/math_output_mathml.html
Modified: trunk/docutils/docs/user/mathematics.txt
===================================================================
--- trunk/docutils/docs/user/mathematics.txt 2021-05-20 12:23:24 UTC (rev 8751)
+++ trunk/docutils/docs/user/mathematics.txt 2021-05-20 12:23:41 UTC (rev 8752)
@@ -380,10 +380,15 @@
========= =========== ========= =========== ============= ================
Named operators outside the above list can be typeset with
-``\operatorname{name}``, e.g. `\operatorname{sgn}(-3) = -1`.
+``\operatorname{name}``, e.g.
-.. TODO: ``\DeclareMathOperator``
+.. math:: \operatorname{sgn}(-3) = -1.
+The ``\DeclareMathOperator`` command can only be used in the
+`LaTeX preamble`_.
+
+.. _LaTeX preamble: latex.html#latex-preamble
+
Punctuation
-----------
.. class:: colwidths-auto
@@ -406,26 +411,46 @@
~~~~~~
.. class:: colwidths-auto
- ===================== ======================= ===================== =======================
- `\leftarrow` ``\leftarrow`` `\Leftarrow` ``\Leftarrow``
- `\rightarrow` ``\rightarrow`` `\Rightarrow` ``\Rightarrow``
- `\leftrightarrow` ``\leftrightarrow`` `\Leftrightarrow` ``\Leftrightarrow``
+ ====================== ======================== ===================== =======================
+ `\circlearrowleft` ``\circlearrowleft`` `\circlearrowright` ``\circlearrowright``
+ `\curvearrowleft` ``\curvearrowleft`` `\curvearrowright` ``\curvearrowright``
+ `\hookleftarrow` ``\hookleftarrow`` `\hookrightarrow` ``\hookrightarrow``
+ `\leftarrow` ``\leftarrow`` `\rightarrow` ``\rightarrow``
+ `\Leftarrow` ``\Leftarrow`` `\Rightarrow` ``\Rightarrow``
+ `\leftarrowtail` ``\leftarrowtail`` `\rightarrowtail` ``\rightarrowtail``
+ `\leftharpoondown` ``\leftharpoondown`` `\rightharpoondown` ``\rightharpoondown``
+ `\leftharpoonup` ``\leftharpoonup`` `\rightharpoonup` ``\rightharpoonup``
+ `\leftleftarrows` ``\leftleftarrows`` `\rightrightarrows` ``\rightrightarrows``
+ `\leftrightarrow` ``\leftrightarrow`` `\Leftrightarrow` ``\Leftrightarrow``
+ `\leftrightarrows` ``\leftrightarrows`` `\rightleftarrows` ``\rightleftarrows``
+ `\leftrightharpoons` ``\leftrightharpoons`` `\rightleftharpoons` ``\rightleftharpoons``
+ `\leftrightsquigarrow` ``\leftrightsquigarrow`` `\rightsquigarrow` ``\rightsquigarrow``
+ `\Lleftarrow` ``\Lleftarrow`` `\Rrightarrow` ``\Rrightarrow``
+ `\longleftarrow` ``\longleftarrow`` `\longrightarrow` ``\longrightarrow``
+ `\Longleftarrow` ``\Longleftarrow`` `\Longrightarrow` ``\Longrightarrow``
+ `\longleftrightarrow` ``\longleftrightarrow`` `\Longleftrightarrow` ``\Longleftrightarrow``
+ `\looparrowleft` ``\looparrowleft`` `\looparrowright` ``\looparrowright``
+ `\Lsh` ``\Lsh`` `\Rsh` ``\Rsh``
+ `\mapsto` ``\mapsto`` `\longmapsto` ``\longmapsto``
+ `\multimap` ``\multimap``
+ `\nleftarrow` ``\nleftarrow`` `\nrightarrow` ``\nrightarrow``
+ `\nLeftarrow` ``\nLeftarrow`` `\nRightarrow` ``\nRightarrow``
+ `\nleftrightarrow` ``\nleftrightarrow`` `\nLeftrightarrow` ``\nLeftrightarrow``
+ `\nwarrow` ``\nwarrow`` `\nearrow` ``\nearrow``
+ `\swarrow` ``\swarrow`` `\searrow` ``\searrow``
+ `\twoheadleftarrow` ``\twoheadleftarrow`` `\twoheadrightarrow` ``\twoheadrightarrow``
+ `\upharpoonleft` ``\upharpoonleft`` `\upharpoonright` ``\upharpoonright``
+ `\downharpoonleft` ``\downharpoonleft`` `\downharpoonright` ``\downharpoonright``
+ `\upuparrows` ``\upuparrows`` `\downdownarrows` ``\downdownarrows``
+ ====================== ======================== ===================== =======================
- `\longleftarrow` ``\longleftarrow`` `\Longleftarrow` ``\Longleftarrow``
- `\longrightarrow` ``\longrightarrow`` `\Longrightarrow` ``\Longrightarrow``
- `\longleftrightarrow` ``\longleftrightarrow`` `\Longleftrightarrow` ``\Longleftrightarrow``
- `\nearrow` ``\nearrow`` `\leftharpoonup` ``\leftharpoonup``
- `\searrow` ``\searrow`` `\rightharpoonup` ``\rightharpoonup``
- `\swarrow` ``\swarrow`` `\leftharpoondown` ``\leftharpoondown``
- `\nwarrow` ``\nwarrow`` `\rightharpoondown` ``\rightharpoondown``
- `\mapsto` ``\mapsto`` `\hookleftarrow` ``\hookleftarrow``
- `\longmapsto` ``\longmapsto`` `\hookrightarrow` ``\hookrightarrow``
- ===================== ======================= ===================== =======================
-.. TODO: amsmath arrows (see math-guide)
+Synonyms: `\gets` ``\gets``, `\to` ``\to``, `\restriction` ``\restriction``.
+
+
Comparison
~~~~~~~~~~
@@ -533,18 +558,20 @@
take one optional argument (the subscript) and one mandatory argument
(the superscript, possibly empty)::
- \xleftarrow{n+\mu-1}\quad \xrightarrow[T]{n\pm i-1}
+ A \xleftarrow{n+\mu-1} B \xrightarrow[T]{n\pm i-1} C
-TODO
+results in
+.. math:: A \xleftarrow{n+\mu-1} B \xrightarrow[T]{n\pm i-1} C
+
Affixing symbols to other symbols
---------------------------------
-In addition to the standard `accents and embellishments`_, other symbols can
-be placed above or below a base symbol with the \overset and \underset
-commands.
+In addition to the standard `accents and embellishments`_, other symbols
+can be placed above or below a base symbol with the ``\overset`` and
+``\underset`` commands. For example, writing ``\overset{*}{X}`` becomes
+`\overset{*}{X}` and ``\underset{+}{M}`` becomes `\underset{+}{M}`.
-TODO
Matrices
--------
@@ -561,9 +588,9 @@
.. math::
\left(\begin{matrix} a & b \\ c & d \end{matrix}\right)
-
-.. TODO: small matrices, matrices with delimiters built in?
+.. TODO: small matrices, matrices with delimiters built in?
+
For piecewise function definitions there is a cases environment:
.. math::
@@ -670,20 +697,15 @@
<mtd>, <mscarry>, and <math> treat their contents as a single inferred mrow
formed from all their children.
-.. math:: a = \sqrt 2 + x, b = \sqrt{1+x^2}, c = \sqrt\frac{sin(x)}{23},
+.. math:: a = \sqrt 2 + x, b = \sqrt{1+x^2}, c = \sqrt\frac{\sin(x)}{23},
-inline: :math:`a = \sqrt 2 + x, b = \sqrt{1+x^2}, c = \sqrt\frac{sin(x)}{23}`.
+inline: :math:`a = \sqrt 2 + x, b = \sqrt{1+x^2}, c = \sqrt\frac{\sin(x)}{23}`.
Accents vs. embellishments
--------------------------
-MathML with Firefox 78 drops dots on "i" and "j" with accents:
-
-.. math:: \vec i \ne \overrightarrow i
- \text{ and } \vec\lim \ne \overrightarrow\lim.
-
-Accents should be nearer to the base (in MathML Firefox 78, it's vice versa!):
+Accents should be nearer to the base (in MathML Firefox 78, it's vice versa!):
`\vec a \overrightarrow a, \vec l \overrightarrow l, \vec i \overrightarrow i`
and `\bar a \overline a, \bar l \overline l, \bar i \overline i`.
Modified: trunk/docutils/docutils/utils/math/latex2mathml.py
===================================================================
--- trunk/docutils/docutils/utils/math/latex2mathml.py 2021-05-20 12:23:24 UTC (rev 8751)
+++ trunk/docutils/docutils/utils/math/latex2mathml.py 2021-05-20 12:23:41 UTC (rev 8752)
@@ -34,7 +34,14 @@
# Character data
# --------------
-#
+
+# Named XML entities for invalid and invisible characters
+xml_entities = {ord('<'): u'<',
+ ord('>'): u'>',
+ ord('&'): u'&',
+ 0x2061: u'⁡',
+ }
+
# LaTeX math macro to Unicode mappings.
# Character categories.
@@ -253,12 +260,21 @@
nchildren = None
"""Expected number of children or None"""
+ # cf. https://www.w3.org/TR/MathML3/chapter3.html#id.3.1.3.2
parent = None
"""Parent node in MathML DOM tree."""
_level = 0 # indentation level (static class variable)
def __init__(self, *children, **attributes):
- """Set up node with `children` and `attributes`."""
+ """Set up node with `children` and `attributes`.
+
+ Attributes are downcased: Use CLASS to get "class" in XML
+ >>> math(mn(3), CLASS='test')
+ math(mn(3), CLASS='test')
+ >>> math(CLASS='test').toprettyxml()
+ '<math class="test">\n</math>'
+
+ """
self.children = []
for child in children:
self.append(child)
@@ -279,36 +295,39 @@
content += ["%s='%s'"%(k, v) for k, v in self.attributes.items()]
return self.__class__.__name__ + '(%s)' % ', '.join(content)
+ def __len__(self):
+ return len(self.children)
+
def full(self):
"""Return boolean indicating whether children may be appended."""
return (self.nchildren is not None
- and len(self.children) >= self.nchildren)
+ and len(self) >= self.nchildren)
def append(self, child):
"""Append child and return self or first non-full parent.
-
+
If self is full, go up the tree and return first non-full node or
`None`.
"""
- assert not self.full()
+ if self.full():
+ raise SyntaxError('Node %s already full!' % self)
self.children.append(child)
child.parent = self
- node = self
- while node is not None and node.full():
- node = node.parent
- return node
+ if self.full():
+ return self.close()
+ return self
def close(self):
- """Close element and return first non-full parent."""
+ """Close element and return first non-full parent or None."""
parent = self.parent
- while parent.full():
+ while parent is not None and parent.full():
parent = parent.parent
return parent
-
+
def toprettyxml(self):
"""Return XML representation of self as string."""
return ''.join(self._xml())
-
+
def _xml(self, level=0):
return ([self.xml_starttag()]
+ self._xml_body(level)
@@ -328,25 +347,23 @@
xml.extend(['\n', ' ' * level])
return xml
-# >>> math(mn(2))
+# >>> n2 = math(mn(2))
+# >>> n2
# math(mn(2))
-# >>> math(mn(2)).toprettyxml()
+# >>> n2.toprettyxml()
# '<math>\n <mn>2</mn>\n</math>'
-#
-# >>> math(id='eq3')
+# >>> len(n2)
+# 1
+# >>> eq3 = math(id='eq3')
+# >>> eq3
# math(id='eq3')
-# >>> math(id='eq3').toprettyxml()
+# >>> eq3.toprettyxml()
# '<math id="eq3">\n</math>'
-#
-# use CLASS to get "class" in XML
-# >>> math(CLASS='test')
-# math(CLASS='test')
-# >>> math(CLASS='test').toprettyxml()
-# '<math class="test">\n</math>'
+# >>> len(eq3)
+# 0
+# >>> math(CLASS='bold').xml_starttag()
+# '<math class="bold">'
-# >>> math(xmlns='http://www.w3.org/1998/Math/MathML').toprettyxml()
-# '<math xmlns="http://www.w3.org/1998/Math/MathML">\n</math>'
-
class mrow(math):
"""Group sub-expressions as a horizontal row."""
@@ -369,9 +386,11 @@
class mtd(mrow): pass
class MathToken(math):
- """Token Element: Base class for mo, mi, and mn."""
+ """Token Element: contains data instead of children.
+
+ Base class for mo, mi, and mn.
+ """
nchildren = 0
- entity_table = {ord('<'): u'<', ord('>'): u'>'}
def __init__(self, data, **attributes):
self.data = data
@@ -378,7 +397,7 @@
super(MathToken, self).__init__(**attributes)
def _xml_body(self, level=0):
- return [unicode(self.data).translate(self.entity_table)]
+ return [unicode(self.data).translate(xml_entities)]
class mi(MathToken): pass
class mn(MathToken): pass
@@ -396,7 +415,7 @@
def __init__(self, *children, **kwargs):
"""Set up sub/superscript or limit elements.
-
+
The special attribute `reversed` tells that the
base and index sub-elements are in reversed order
(i.e. as in LaTeX) and will be switched on XML-export.
@@ -403,12 +422,14 @@
"""
self.reversed = kwargs.pop('reversed', False)
math.__init__(self, *children, **kwargs)
-
- def _xml(self, level=0):
- if self.reversed:
+
+ def append(self, child):
+ new_current = super(MathScriptOrLimit, self).append(child)
+ # normalize order if full
+ if self.reversed and self.full():
self.children.reverse()
self.reversed = False
- return super(MathScriptOrLimit, self)._xml(level)
+ return new_current
class msub(MathScriptOrLimit): pass
class msup(MathScriptOrLimit): pass
@@ -422,8 +443,15 @@
# >>> munder(mi('lim'), mo('-'), accent='false')
# munder(mi('lim'), mo('-'), accent='false')
-# >>> munder(mo('-'), mi('lim'), accent='false', reversed=True)
-# munder(mo('-'), mi('lim'), reversed=True, accent='false')
+# >>> mu = munder(mo('-'), accent='false', reversed=True)
+# >>> mu
+# munder(mo('-'), reversed=True, accent='false')
+# >>> mu.append(mi('lim'))
+# >>> mu
+# munder(mi('lim'), mo('-'), accent='false')
+# >>> mu.append(mi('lim'))
+# Traceback (most recent call last):
+# SyntaxError: Node munder(mi('lim'), mo('-'), accent='false') already full!
# >>> munder(mo('-'), mi('lim'), accent='false', reversed=True).toprettyxml()
# '<munder accent="false">\n <mi>lim</mi>\n <mo>-</mo>\n</munder>'
# >>> msub(mi('x'), mo('-'))
@@ -473,9 +501,6 @@
# >>> tex_cmdname('') # empty string
# ('', '')
-#
-# --- https://www.w3.org/TR/MathML3/chapter3.html#id.3.1.3.2
-
def tex_token(string):
"""Return first simple TeX token and remainder of `string`.
@@ -485,7 +510,7 @@
('\\command', '{without argument}')
>>> tex_token(' first non-white character')
('f', 'irst non-white character')
-
+
"""
m = re.match(r"""\s* # leading whitespace
{(?P<token>(\\}|[^{}]|\\{)*)} # {group} without nested groups
@@ -521,30 +546,52 @@
# >>> tex_token('') # empty string.
# ('', '')
+def tex_optarg(string):
+ """Return optional argument and remainder.
-def parse_latex_math(string, inline=True):
- """Return a MathML-tree parsed from `string`.
+ >>> tex_optarg('[optional argument] returned without brackets')
+ ('optional argument', ' returned without brackets')
+ >>> tex_optarg('{empty string, if there is no optional arg}')
+ ('', '{empty string, if there is no optional arg}')
- >>> parse_latex_math('\\alpha')
- math(mi('α'), xmlns='http://www.w3.org/1998/Math/MathML')
+ """
+ m = re.match(r"""\s* # leading whitespace
+ \[(?P<optarg>(\\]|[^\[\]]|\\])*)\] # [group] without nested groups
+ (?P<remainder>.*$)
+ """, string, re.VERBOSE)
+ if m is None and not string.startswith('['):
+ return '', string
+ try:
+ return m.group('optarg'), m.group('remainder')
+ except AttributeError:
+ raise SyntaxError('Could not extract optional argument from %r' % string)
+# Test:
+# >>> tex_optarg('[optional argument] after whitespace')
+# ('optional argument', ' after whitespace')
+# >>> tex_optarg('[missing right bracket')
+# Traceback (most recent call last):
+# SyntaxError: Could not extract optional argument from '[missing right bracket'
+# >>> tex_optarg('[group with [nested group]]')
+# Traceback (most recent call last):
+# SyntaxError: Could not extract optional argument from '[group with [nested group]]'
+
+
+def parse_latex_math(node, string):
+ """Append MathML conversion of `string` to `node`.
+
+ Return current node.
+
+ >>> parse_latex_math(math(), r'\alpha')
+ math(mi('α'))
+ >>> parse_latex_math(math(), r'{')
+ mrow()
+
Set `inline` to False for displayed math.
"""
-
# Normalize white-space:
string = ' '.join(string.split())
- # Set up: tree is the whole tree and node is the current element.
- if inline:
- node = math(xmlns='http://www.w3.org/1998/Math/MathML')
- tree = node
- else:
- # block: emulate align* environment with a math table
- node = mtd()
- lines = mtable(mtr(node), displaystyle='true', CLASS='align')
- tree = math(lines, display='block',
- xmlns='http://www.w3.org/1998/Math/MathML')
-
while len(string) > 0:
# Take of first character:
c, string = string[0], string[1:]
@@ -603,28 +650,25 @@
node = entry
else:
raise SyntaxError(u'Illegal character: "%s"' % c)
- return tree
+ return node
# Test:
-# >>> parse_latex_math('', inline=True)
+# >>> parse_latex_math(math(xmlns='http://www.w3.org/1998/Math/MathML'), '')
# math(xmlns='http://www.w3.org/1998/Math/MathML')
-# >>> parse_latex_math('', inline=False)
-# math(mtable(mtr(mtd()), CLASS='align', displaystyle='true'), display='block', xmlns='http://www.w3.org/1998/Math/MathML')
-# >>> parse_latex_math(' \\sqrt{ \\alpha}')
-# math(msqrt(mi('α')), xmlns='http://www.w3.org/1998/Math/MathML')
-# >>> parse_latex_math('\\alpha', inline=False)
-# math(mtable(mtr(mtd(mi('α'))), CLASS='align', displaystyle='true'), display='block', xmlns='http://www.w3.org/1998/Math/MathML')
-# >>> parse_latex_math('\\sqrt 2 \\ne 3')
-# math(msqrt(mn('2')), mo('≠'), mn('3'), xmlns='http://www.w3.org/1998/Math/MathML')
-# >>> parse_latex_math('\\sqrt{2 + 3} < 3')
-# math(msqrt(mn('2'), mo('+'), mn('3')), mo('<'), mn('3'), xmlns='http://www.w3.org/1998/Math/MathML')
+# >>> parse_latex_math(math(), ' \\sqrt{ \\alpha}')
+# math(msqrt(mi('α')))
+# >>> parse_latex_math(math(), '\\sqrt 2 \\ne 3')
+# math(msqrt(mn('2')), mo('≠'), mn('3'))
+# >>> parse_latex_math(math(), '\\sqrt{2 + 3} < 3')
+# math(msqrt(mn('2'), mo('+'), mn('3')), mo('<'), mn('3'))
def handle_keyword(name, node, string):
- """Process LaTeX macro `name` followed by `string`.
+ """Process LaTeX command `name` followed by `string`.
- If needed, parse `string` for macro argument.
- Return updated current node and remainder of `string`:
+ Append result to `node`.
+ If needed, parse `string` for command argument.
+ Return new current node and remainder of `string`:
>>> handle_keyword('hbar', math(), r' \frac')
(math(mi('ℏ')), ' \\frac')
@@ -654,27 +698,26 @@
if name == 'operatorname':
# custom function name ``\operatorname{abs}(x)``
arg, string = tex_token(string)
- identifier = mi(arg, mathvariant='normal')
+ new_node = mi(arg, mathvariant='normal')
else:
- identifier = mi(functions[name])
+ new_node = mi(functions[name])
# functions with embellished names
if name == 'varliminf': # \underline\lim
- identifier = munder(identifier, mo(u'_'))
+ new_node = munder(new_node, mo(u'_'))
elif name == 'varlimsup': # \overline\lim
- identifier = mover(identifier, mo(u'¯'), accent='false')
+ new_node = mover(new_node, mo(u'¯'), accent='false')
elif name == 'varprojlim': # \underleftarrow\lim
- identifier = munder(identifier, mo(u'\u2190'))
+ new_node = munder(new_node, mo(u'\u2190'))
elif name == 'varinjlim': # \underrightarrow\lim
- identifier = munder(identifier, mo(u'\u2192'))
+ new_node = munder(new_node, mo(u'\u2192'))
- node = node.append(identifier)
- # TODO: only add ApplyFunction when appropriate (not \sin ^2(x), say)
- arg, remainder = tex_token(string)
- if arg not in ('^', '_'):
- node = node.append(mo('⁡')) # '\u2061'
+ node = node.append(new_node)
+ # add ApplyFunction when appropriate (not \sin^2(x), say)
+ # cf. https://www.w3.org/TR/MathML3/chapter3.html#presm.mi
+ if string and string[0] not in ('^', '_'):
+ node = node.append(mo(u'\u2061')) # ⁡
return node, string
-
if name in math_alphabets:
arg, remainder = tex_token(string)
if arg[0] == '\\':
@@ -764,8 +807,7 @@
if name in ('text', 'mbox', 'textrm'):
arg, string = tex_token(string)
- # text = arg.replace(' ', ' ', 1).replace(' ', ' ', 1)
- text = re.sub('(^ | $)', ' ', arg)
+ text = re.sub('(^ | $)', u'\u00a0', arg)
node = node.append(mtext(text))
return node, string
@@ -784,23 +826,23 @@
# ==================================
if name == 'sqrt':
- sqrt = msqrt()
+ new_node = msqrt()
if string.startswith('{'): # argument is a group
string = string[1:] # mrow implied, skip opening bracket
else: # no group, enclose only one element
- sqrt.nchildren = 1
- node.append(sqrt)
- return sqrt, string
+ new_node.nchildren = 1
+ node.append(new_node)
+ return new_node, string
if name == 'frac':
- frac = mfrac()
- node.append(frac)
- return frac, string
+ new_node = mfrac()
+ node.append(new_node)
+ return new_node, string
if name == '\\': # end of a row
entry = mtd()
- row = mtr(entry)
- node.close().close().append(row)
+ new_node = mtr(entry)
+ node.close().close().append(new_node)
return entry, string
if name in accents or name in over:
@@ -810,15 +852,40 @@
except KeyError:
ch = accents[name]
acc = 'true'
- ovr = mover(mo(ch), reversed=True, accent=acc)
- node.append(ovr)
- return ovr, string
+ new_node = mover(mo(ch), reversed=True, accent=acc)
+ node.append(new_node)
+ return new_node, string
+ if name == 'overset':
+ new_node = mover(reversed=True)
+ node.append(new_node)
+ return new_node, string
+
if name in under:
- ovr = munder(mo(under[name]), reversed=True)
- node.append(ovr)
- return ovr, string
+ new_node = munder(mo(under[name]), reversed=True)
+ node.append(new_node)
+ return new_node, string
+ if name == 'underset':
+ new_node = munder(reversed=True)
+ node.append(new_node)
+ return new_node, string
+
+ if name in ('xleftarrow', 'xrightarrow'):
+ subscript, string = tex_optarg(string)
+ base = mo(operators[name[1:]])
+ if subscript:
+ new_node = munderover(base)
+ sub_node = mrow()
+ parse_latex_math(sub_node, subscript)
+ if len(sub_node) == 1:
+ sub_node = sub_node.children[0]
+ new_node.append(sub_node)
+ else:
+ new_node = mover(base)
+ node.append(new_node)
+ return new_node, string
+
if name == 'begin':
env_name, string = tex_token(string)
if env_name == 'matrix':
@@ -859,7 +926,7 @@
# >>> handle_keyword('not', math(), '\\equiv \\alpha)') # cmd
# (math(mo('≢')), '\\alpha)')
# >>> handle_keyword('text', math(), '{ for } i>0') # group
-# (math(mtext(' for ')), ' i>0')
+# (math(mtext('\xa0for\xa0')), ' i>0')
# >>> handle_keyword('text', math(), '{B}T') # group
# (math(mtext('B')), 'T')
# >>> handle_keyword('text', math(), '{number of apples}}') # group
@@ -867,11 +934,11 @@
# >>> handle_keyword('text', math(), 'i \\sin(x)') # single char
# (math(mtext('i')), ' \\sin(x)')
# >>> handle_keyword('sin', math(), '(\\alpha)')
-# (math(mi('sin'), mo('⁡')), '(\\alpha)')
+# (math(mi('sin'), mo('\u2061')), '(\\alpha)')
# >>> handle_keyword('sin', math(), ' \\alpha')
-# (math(mi('sin'), mo('⁡')), ' \\alpha')
+# (math(mi('sin'), mo('\u2061')), ' \\alpha')
# >>> handle_keyword('operatorname', math(), '{abs}(x)')
-# (math(mi('abs', mathvariant='normal'), mo('⁡')), '(x)')
+# (math(mi('abs', mathvariant='normal'), mo('\u2061')), '(x)')
# >>> handle_keyword('mathrm', math(), '\\alpha')
# (math(mi('α', mathvariant='normal')), '')
# >>> handle_keyword('mathrm', math(), '{out} = 3')
@@ -880,6 +947,10 @@
# (mover(mo('¯'), reversed=True, accent='false'), '{981}')
# >>> handle_keyword('bar', math(), '{x}')
# (mover(mo('ˉ'), reversed=True, accent='true'), '{x}')
+# >>> handle_keyword('xleftarrow', math(), r'[\alpha]{10}')
+# (munderover(mo('←'), mi('α')), '{10}')
+# >>> handle_keyword('xleftarrow', math(), r'[\alpha=5]{10}')
+# (munderover(mo('←'), mrow(mi('α'), mo('='), mn('5'))), '{10}')
def tex2mathml(tex_math, inline=True):
@@ -887,6 +958,28 @@
Set `inline` to False for displayed math.
"""
+ # Set up tree
+ tree = node = math(xmlns='http://www.w3.org/1998/Math/MathML')
+ if not inline:
+ # block: emulate align* environment with a math table
+ tree.attributes['display']='block'
+ node = mtd()
+ tree.append(mtable(mtr(node), displaystyle='true', CLASS='align'))
- mathml_tree = parse_latex_math(tex_math, inline=inline)
- return mathml_tree.toprettyxml()
+ parse_latex_math(node, tex_math)
+ return tree.toprettyxml()
+
+# >>> print(tex2mathml('3'))
+# <math xmlns="http://www.w3.org/1998/Math/MathML">
+# <mn>3</mn>
+# </math>
+# >>> print(tex2mathml('3', inline=False))
+# <math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
+# <mtable class="align" displaystyle="true">
+# <mtr>
+# <mtd>
+# <mn>3</mn>
+# </mtd>
+# </mtr>
+# </mtable>
+# </math>
Modified: trunk/docutils/test/functional/expected/math_output_mathml.html
===================================================================
--- trunk/docutils/test/functional/expected/math_output_mathml.html 2021-05-20 12:23:24 UTC (rev 8751)
+++ trunk/docutils/test/functional/expected/math_output_mathml.html 2021-05-20 12:23:41 UTC (rev 8752)
@@ -47,7 +47,7 @@
</math>, as well as displayed math via the
<cite>math</cite> directive:</p>
<div>
-<math display="block" xmlns="http://www.w3.org/1998/Math/MathML">
+<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
<mtable class="align" displaystyle="true">
<mtr>
<mtd>
@@ -90,7 +90,7 @@
</div>
<p>Content may start on the first line of the directive, e.g.</p>
<div>
-<math display="block" xmlns="http://www.w3.org/1998/Math/MathML">
+<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
<mtable class="align" displaystyle="true">
<mtr>
<mtd>
@@ -113,7 +113,7 @@
See <a class="reference internal" href="#eq-m">eq:M</a> and <a class="reference internal" href="#eq-schrodinger">eq:schrödinger</a> below.</p>
<p>The determinant of the matrix</p>
<div id="eq-m">
-<math display="block" xmlns="http://www.w3.org/1998/Math/MathML">
+<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
<mtable class="align" displaystyle="true">
<mtr>
<mtd>
@@ -160,7 +160,7 @@
<p>More than one display math block can be put in one math directive.
For example, the following sum and integral with limits:</p>
<div>
-<math display="block" xmlns="http://www.w3.org/1998/Math/MathML">
+<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
<mtable class="align" displaystyle="true">
<mtr>
<mtd>
@@ -192,7 +192,7 @@
</math>
</div>
<div>
-<math display="block" xmlns="http://www.w3.org/1998/Math/MathML">
+<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
<mtable class="align" displaystyle="true">
<mtr>
<mtd>
@@ -229,7 +229,7 @@
directives:</p>
<p>The Schrödinger equation</p>
<div id="eq-schrodinger">
-<math display="block" xmlns="http://www.w3.org/1998/Math/MathML">
+<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
<mtable class="align" displaystyle="true">
<mtr>
<mtd>
@@ -380,7 +380,7 @@
\widehat{xxx} -->
<p>Modulation Transfer Function:</p>
<div>
-<math display="block" xmlns="http://www.w3.org/1998/Math/MathML">
+<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
<mtable class="align" displaystyle="true">
<mtr>
<mtd>
@@ -494,7 +494,7 @@
<span class="docutils literal"><span class="pre">\begin{...}</span> <span class="pre">\end{...}</span></span> pair, the math code is wrapped in an <a class="reference external" href="ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf">AMSmath</a>
<span class="docutils literal">align</span> environment:</p>
<div>
-<math display="block" xmlns="http://www.w3.org/1998/Math/MathML">
+<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
<mtable class="align" displaystyle="true">
<mtr>
<mtd>
@@ -569,7 +569,7 @@
</div>
<p>Cases with the <a class="reference external" href="ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf">AMSmath</a> <span class="docutils literal">cases</span> environment:</p>
<div>
-<math display="block" xmlns="http://www.w3.org/1998/Math/MathML">
+<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
<mtable class="align" displaystyle="true">
<mtr>
<mtd>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development ...
[truncated message content] |
|
From: <mi...@us...> - 2021-05-20 12:24:13
|
Revision: 8753
http://sourceforge.net/p/docutils/code/8753
Author: milde
Date: 2021-05-20 12:24:07 +0000 (Thu, 20 May 2021)
Log Message:
-----------
MathML: fix script/limt order when given as ^{super}_{sub}.
Separate function to handle scripts or limits,
Rename handle_keyword() and math.reverse.
Modified Paths:
--------------
trunk/docutils/docs/user/mathematics.txt
trunk/docutils/docutils/utils/math/latex2mathml.py
Modified: trunk/docutils/docs/user/mathematics.txt
===================================================================
--- trunk/docutils/docs/user/mathematics.txt 2021-05-20 12:23:41 UTC (rev 8752)
+++ trunk/docutils/docs/user/mathematics.txt 2021-05-20 12:24:07 UTC (rev 8753)
@@ -191,7 +191,7 @@
.. math::
A = \left . \frac{1}{1-n}\, \right |_{n=0}^\infty
-
+
The following symbols extend when used with ``\left`` and ``\right``:
Pairing delimiters
@@ -225,8 +225,9 @@
The use of ``|`` and ``\|`` for pairs of vertical bars may produce
incorrect spacing, e.g., ``|k|=|-k|`` produces `|k| = |−k|` and
-``|\sin(x)|`` produces `|\sin(x)|`. The pairing delimiters, e.g. `\lvert
--k\rvert` and `\lvert\sin(x)\rvert`, prevent this problem (in LaTeX and
+``|\sin(x)|`` produces `|\sin(x)|`. The pairing delimiters, e.g.
+`\lvert -k\rvert`
+and `\lvert\sin(x)\rvert`, prevent this problem (in LaTeX and
MathJax).
Vertical Arrows
@@ -702,14 +703,18 @@
inline: :math:`a = \sqrt 2 + x, b = \sqrt{1+x^2}, c = \sqrt\frac{\sin(x)}{23}`.
-Accents vs. embellishments
---------------------------
+Scripts and Limits
+------------------
Accents should be nearer to the base (in MathML Firefox 78, it's vice versa!):
-`\vec a \overrightarrow a, \vec l \overrightarrow l, \vec i \overrightarrow i`
-and `\bar a \overline a, \bar l \overline l, \bar i \overline i`.
+`\bar a \overline a, \bar l \overline l, \bar i \overline i`.
In inline formulas and fractions, the limits on lim, sum and integral should
move to index postions: `\lim_{c\to0} \oint_c f(x) \mathrm{d}x` vs.
.. math:: \lim_{c\to0} \oint_c f(x) \mathrm{d}x
+
+Sub- and superscript may be given in any order:
+`x_i^j = x^j_i` and `\int_0^1 = \int^1_0`.
+
+Double exponent: `x^{10}^4`, `r_T_\mathrm{in}` and `x_i^n^2`.
Modified: trunk/docutils/docutils/utils/math/latex2mathml.py
===================================================================
--- trunk/docutils/docutils/utils/math/latex2mathml.py 2021-05-20 12:23:41 UTC (rev 8752)
+++ trunk/docutils/docutils/utils/math/latex2mathml.py 2021-05-20 12:24:07 UTC (rev 8753)
@@ -66,9 +66,11 @@
functions.update({# functions with a space in the name
'liminf': u'lim\u202finf', 'limsup': u'lim\u202fsup',
'injlim': u'inj\u202flim', 'projlim': u'proj\u202flim',
- # embellished function names (see handle_keyword() below)
+ # embellished function names (see handle_cmdname() below)
'varlimsup': 'lim', 'varliminf': 'lim',
- 'varprojlim': 'lim', 'varinjlim': 'lim'})
+ 'varprojlim': 'lim', 'varinjlim': 'lim',
+ # custom function name
+ 'operatorname': None})
# math font selection -> <mi mathvariant=...> or <mstyle mathvariant=...>
math_alphabets = {# 'cmdname': 'mathvariant value' # package
@@ -106,6 +108,11 @@
'ngeqslant': u'\u2a7e\u0338', # ⩾̸
'nsubseteqq': u'\u2AC5\u0338', # ⫅̸
'nsupseteqq': u'\u2AC6\u0338', # ⫆̸
+ # pairing delimiters
+ 'lvert': '|',
+ 'lVert': u'\u2016', # ‖
+ 'rvert': '|',
+ 'rVert': u'\u2016',
# use <mo> to allow "movablelimits" attribute
'lim': u'lim',
})
@@ -127,22 +134,12 @@
'smallint': u'\u222b', # ∫ INTEGRAL
}
-left_delimiters = {# rspace='0', lspace='0.22em'
- 'lvert': '|',
- 'lVert': u'\u2016' # ‖ DOUBLE VERTICAL LINE
- }
-
-right_delimiters = {# lspace='0', rspace='0.22em'
- 'rvert': '|',
- 'rVert': u'\u2016', # ‖ DOUBLE VERTICAL LINE
- }
-
# operators with limits either over/under or in index position
-sumintprod = ['coprod', 'fatsemi', 'fint', 'iiiint', 'iiint',
- 'iint', 'int', 'oiint', 'oint', 'ointctrclockwise',
- 'prod', 'sqint', 'sum', 'varointclockwise']
-sumintprod += [operators[name] for name in sumintprod]
-sumintprod.append('lim')
+sumintprod = [operators[name] for name in
+ ('coprod', 'fatsemi', 'fint', 'iiiint', 'iiint',
+ 'iint', 'int', 'oiint', 'oint', 'ointctrclockwise',
+ 'prod', 'sqint', 'sum', 'varointclockwise')
+ ] + ['lim']
# pre-composed characters for negated symbols
# see https://www.w3.org/TR/xml-entity-names/#combining
@@ -234,6 +231,7 @@
# Character translations
# ----------------------
# characters with preferred alternative in mathematical use
+# cf. https://www.w3.org/TR/MathML3/chapter7.html#chars.anomalous
anomalous_chars = {'-': u'\u2212', # HYPHEN-MINUS -> MINUS SIGN
':': u'\u2236', # COLON -> RATIO
}
@@ -289,8 +287,8 @@
content = [repr(item) for item in getattr(self, 'children', [])]
if hasattr(self, 'data'):
content.append(repr(self.data))
- if isinstance(self, MathScriptOrLimit) and self.reversed:
- content.append('reversed=True')
+ if isinstance(self, MathScriptOrLimit) and self.switch:
+ content.append('switch=True')
if hasattr(self, 'attributes'):
content += ["%s='%s'"%(k, v) for k, v in self.attributes.items()]
return self.__class__.__name__ + '(%s)' % ', '.join(content)
@@ -416,19 +414,20 @@
def __init__(self, *children, **kwargs):
"""Set up sub/superscript or limit elements.
- The special attribute `reversed` tells that the
- base and index sub-elements are in reversed order
- (i.e. as in LaTeX) and will be switched on XML-export.
+ The special attribute `switch` tells that the
+ last two child elements are in reversed order
+ and must be switched before XML-export.
"""
- self.reversed = kwargs.pop('reversed', False)
+ self.switch = kwargs.pop('switch', False)
math.__init__(self, *children, **kwargs)
def append(self, child):
new_current = super(MathScriptOrLimit, self).append(child)
# normalize order if full
- if self.reversed and self.full():
- self.children.reverse()
- self.reversed = False
+ if self.switch and self.full():
+ self.children[-1], self.children[-2] = self.children[-2], self.children[-1]
+ # self.children.reverse()
+ self.switch = False
return new_current
class msub(MathScriptOrLimit): pass
@@ -443,9 +442,9 @@
# >>> munder(mi('lim'), mo('-'), accent='false')
# munder(mi('lim'), mo('-'), accent='false')
-# >>> mu = munder(mo('-'), accent='false', reversed=True)
+# >>> mu = munder(mo('-'), accent='false', switch=True)
# >>> mu
-# munder(mo('-'), reversed=True, accent='false')
+# munder(mo('-'), switch=True, accent='false')
# >>> mu.append(mi('lim'))
# >>> mu
# munder(mi('lim'), mo('-'), accent='false')
@@ -452,12 +451,15 @@
# >>> mu.append(mi('lim'))
# Traceback (most recent call last):
# SyntaxError: Node munder(mi('lim'), mo('-'), accent='false') already full!
-# >>> munder(mo('-'), mi('lim'), accent='false', reversed=True).toprettyxml()
+# >>> munder(mo('-'), mi('lim'), accent='false', switch=True).toprettyxml()
# '<munder accent="false">\n <mi>lim</mi>\n <mo>-</mo>\n</munder>'
# >>> msub(mi('x'), mo('-'))
# msub(mi('x'), mo('-'))
+# >>> msubsup(mi('base'), mi('sub'), mi('super'))
+# msubsup(mi('base'), mi('sub'), mi('super'))
+# >>> msubsup(mi('base'), mi('super'), mi('sub'), switch=True)
+# msubsup(mi('base'), mi('sub'), mi('super'))
-
class mroot(math):
nchildren = 2
@@ -598,10 +600,21 @@
if c == ' ':
continue # whitespace is ignored in LaTeX math mode
-
if c == '\\': # start of a LaTeX macro
cmdname, string = tex_cmdname(string)
- node, string = handle_keyword(cmdname, node, string)
+ node, string = handle_cmdname(cmdname, node, string)
+ elif c in "_^":
+ node = handle_script_or_limit(node, c)
+ elif c == '{':
+ new_node = mrow()
+ node.append(new_node)
+ node = new_node
+ elif c == '}':
+ node = node.close()
+ elif c == '&':
+ new_node = mtd()
+ node.close().append(new_node)
+ node = new_node
elif c.isalpha():
node = node.append(mi(c))
elif c.isdigit():
@@ -613,41 +626,6 @@
node = node.append(mo(anomalous_chars[c]))
elif c in "+*=<>,.!?';@":
node = node.append(mo(c))
- elif c == '_':
- child = node.children.pop()
- if isinstance(child, msup):
- sub = msubsup(*child.children, reversed=True)
- elif isinstance(child, MathToken) and child.data in sumintprod:
- child.attributes['movablelimits'] = 'true'
- sub = munder(child)
- else:
- sub = msub(child)
- node.append(sub)
- node = sub
- elif c == '^':
- child = node.children.pop()
- if isinstance(child, msub):
- sup = msubsup(*child.children)
- elif isinstance(child, MathToken) and child.data in sumintprod:
- child.attributes['movablelimits'] = 'true'
- sup = mover(child)
- elif (isinstance(child, munder) and
- child.children[0].data in sumintprod):
- sup = munderover(*child.children)
- else:
- sup = msup(child)
- node.append(sup)
- node = sup
- elif c == '{':
- row = mrow()
- node.append(row)
- node = row
- elif c == '}':
- node = node.close()
- elif c == '&':
- entry = mtd()
- node.close().append(entry)
- node = entry
else:
raise SyntaxError(u'Illegal character: "%s"' % c)
return node
@@ -662,8 +640,12 @@
# math(msqrt(mn('2')), mo('≠'), mn('3'))
# >>> parse_latex_math(math(), '\\sqrt{2 + 3} < 3')
# math(msqrt(mn('2'), mo('+'), mn('3')), mo('<'), mn('3'))
+# >>> parse_latex_math(math(), 'x^j_i') # ensure correct order: base, sub, sup
+# math(msubsup(mi('x'), mi('i'), mi('j')))
+# >>> parse_latex_math(math(), '\int^j_i') # ensure correct order
+# math(munderover(mo('∫', movablelimits='true'), mi('i'), mi('j')))
-def handle_keyword(name, node, string):
+def handle_cmdname(name, node, string):
"""Process LaTeX command `name` followed by `string`.
Append result to `node`.
@@ -670,9 +652,9 @@
If needed, parse `string` for command argument.
Return new current node and remainder of `string`:
- >>> handle_keyword('hbar', math(), r' \frac')
+ >>> handle_cmdname('hbar', math(), r' \frac')
(math(mi('ℏ')), ' \\frac')
- >>> handle_keyword('hspace', math(), r'{1ex} (x)')
+ >>> handle_cmdname('hspace', math(), r'{1ex} (x)')
(math(mspace(width='1ex')), ' (x)')
"""
@@ -692,7 +674,7 @@
node = node.append(mi(letters[name]))
return node, string
- if (name in functions or name == 'operatorname'):
+ if (name in functions):
# use <mi> followed by invisible function applicator character
# (see https://www.w3.org/TR/MathML3/chapter3.html#presm.mi)
if name == 'operatorname':
@@ -701,7 +683,7 @@
new_node = mi(arg, mathvariant='normal')
else:
new_node = mi(functions[name])
- # functions with embellished names
+ # compound function symbols:
if name == 'varliminf': # \underline\lim
new_node = munder(new_node, mo(u'_'))
elif name == 'varlimsup': # \overline\lim
@@ -755,14 +737,6 @@
# operator, fence, or separator -> <mo>
- if name in left_delimiters: # opening delimiters
- node = node.append(mo(left_delimiters[name], rspace='0'))
- return node, string
-
- if name in right_delimiters: # closing delimiters
- node = node.append(mo(right_delimiters[name], lspace='0', ))
- return node, string
-
if name == 'colon': # trailing punctuation, not binary relation
node = node.append(mo(':', lspace='0', rspace='0.28em'))
return node, string
@@ -789,7 +763,7 @@
row = mrow()
node.append(row)
node = row
- if delimiter:
+ if delimiter: # may be empty (source '.')
node.append(mo(delimiter))
if name == 'right':
node = node.close()
@@ -852,22 +826,22 @@
except KeyError:
ch = accents[name]
acc = 'true'
- new_node = mover(mo(ch), reversed=True, accent=acc)
+ new_node = mover(mo(ch), switch=True, accent=acc)
node.append(new_node)
return new_node, string
if name == 'overset':
- new_node = mover(reversed=True)
+ new_node = mover(switch=True)
node.append(new_node)
return new_node, string
if name in under:
- new_node = munder(mo(under[name]), reversed=True)
+ new_node = munder(mo(under[name]), switch=True)
node.append(new_node)
return new_node, string
if name == 'underset':
- new_node = munder(reversed=True)
+ new_node = munder(switch=True)
node.append(new_node)
return new_node, string
@@ -917,42 +891,70 @@
raise SyntaxError(u'Unknown LaTeX command: ' + name)
-# >>> handle_keyword('left', math(), '[a\\right]')
+# >>> handle_cmdname('left', math(), '[a\\right]')
# (mrow(mo('[')), 'a\\right]')
-# >>> handle_keyword('left', math(), '. a)') # emtpy \left
+# >>> handle_cmdname('left', math(), '. a)') # emtpy \left
# (mrow(), ' a)')
-# >>> handle_keyword('left', math(), '\\uparrow a)') # cmd
+# >>> handle_cmdname('left', math(), '\\uparrow a)') # cmd
# (mrow(mo('↑')), 'a)')
-# >>> handle_keyword('not', math(), '\\equiv \\alpha)') # cmd
+# >>> handle_cmdname('not', math(), '\\equiv \\alpha)') # cmd
# (math(mo('≢')), '\\alpha)')
-# >>> handle_keyword('text', math(), '{ for } i>0') # group
+# >>> handle_cmdname('text', math(), '{ for } i>0') # group
# (math(mtext('\xa0for\xa0')), ' i>0')
-# >>> handle_keyword('text', math(), '{B}T') # group
+# >>> handle_cmdname('text', math(), '{B}T') # group
# (math(mtext('B')), 'T')
-# >>> handle_keyword('text', math(), '{number of apples}}') # group
+# >>> handle_cmdname('text', math(), '{number of apples}}') # group
# (math(mtext('number of apples')), '}')
-# >>> handle_keyword('text', math(), 'i \\sin(x)') # single char
+# >>> handle_cmdname('text', math(), 'i \\sin(x)') # single char
# (math(mtext('i')), ' \\sin(x)')
-# >>> handle_keyword('sin', math(), '(\\alpha)')
+# >>> handle_cmdname('sin', math(), '(\\alpha)')
# (math(mi('sin'), mo('\u2061')), '(\\alpha)')
-# >>> handle_keyword('sin', math(), ' \\alpha')
+# >>> handle_cmdname('sin', math(), ' \\alpha')
# (math(mi('sin'), mo('\u2061')), ' \\alpha')
-# >>> handle_keyword('operatorname', math(), '{abs}(x)')
+# >>> handle_cmdname('operatorname', math(), '{abs}(x)')
# (math(mi('abs', mathvariant='normal'), mo('\u2061')), '(x)')
-# >>> handle_keyword('mathrm', math(), '\\alpha')
+# >>> handle_cmdname('mathrm', math(), '\\alpha')
# (math(mi('α', mathvariant='normal')), '')
-# >>> handle_keyword('mathrm', math(), '{out} = 3')
+# >>> handle_cmdname('mathrm', math(), '{out} = 3')
# (math(mi('out', mathvariant='normal')), ' = 3')
-# >>> handle_keyword('overline', math(), '{981}')
-# (mover(mo('¯'), reversed=True, accent='false'), '{981}')
-# >>> handle_keyword('bar', math(), '{x}')
-# (mover(mo('ˉ'), reversed=True, accent='true'), '{x}')
-# >>> handle_keyword('xleftarrow', math(), r'[\alpha]{10}')
+# >>> handle_cmdname('overline', math(), '{981}')
+# (mover(mo('¯'), switch=True, accent='false'), '{981}')
+# >>> handle_cmdname('bar', math(), '{x}')
+# (mover(mo('ˉ'), switch=True, accent='true'), '{x}')
+# >>> handle_cmdname('xleftarrow', math(), r'[\alpha]{10}')
# (munderover(mo('←'), mi('α')), '{10}')
-# >>> handle_keyword('xleftarrow', math(), r'[\alpha=5]{10}')
+# >>> handle_cmdname('xleftarrow', math(), r'[\alpha=5]{10}')
# (munderover(mo('←'), mrow(mi('α'), mo('='), mn('5'))), '{10}')
+def handle_script_or_limit(node, c):
+ """Append script or limit element to `node`."""
+ child = node.children.pop()
+ if c == '_':
+ if isinstance(child, msup):
+ new_node = msubsup(*child.children, switch=True)
+ elif isinstance(child, mover):
+ new_node = munderover(*child.children, switch=True)
+ # elif isinstance(child, MathToken) and child.data in sumintprod:
+ elif getattr(child, 'data', '') in sumintprod:
+ child.attributes['movablelimits'] = 'true'
+ new_node = munder(child)
+ else:
+ new_node = msub(child)
+ elif c == '^':
+ if isinstance(child, msub):
+ new_node = msubsup(*child.children)
+ elif isinstance(child, munder):
+ new_node = munderover(*child.children)
+ elif isinstance(child, MathToken) and child.data in sumintprod:
+ child.attributes['movablelimits'] = 'true'
+ new_node = mover(child)
+ else:
+ new_node = msup(child)
+ node.append(new_node)
+ return new_node
+
+
def tex2mathml(tex_math, inline=True):
"""Return string with MathML code corresponding to `tex_math`.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2021-05-20 12:24:26
|
Revision: 8754
http://sourceforge.net/p/docutils/code/8754
Author: milde
Date: 2021-05-20 12:24:25 +0000 (Thu, 20 May 2021)
Log Message:
-----------
MathML fix multi-digit number literals. Support optional arg for \sqrt.
Place consecutive digits and comma/dot in a common <mn> element.
Support the optinal argument to specify a degree of a radical.
Modified Paths:
--------------
trunk/docutils/docs/user/mathematics.txt
trunk/docutils/docutils/utils/math/latex2mathml.py
Modified: trunk/docutils/docs/user/mathematics.txt
===================================================================
--- trunk/docutils/docs/user/mathematics.txt 2021-05-20 12:24:07 UTC (rev 8753)
+++ trunk/docutils/docs/user/mathematics.txt 2021-05-20 12:24:25 UTC (rev 8754)
@@ -180,18 +180,15 @@
---------------------
Unless you indicate otherwise, delimiters in math formulas remain at the
standard size regardless of the height of the enclosed material. To get
-adaptable sizes, use ``\left`` and ``\right`` prefixes.
+adaptable sizes, use ``\left`` and ``\right`` prefixes, for example
+`g(A,B,Y) = f \left(A,B,X=h^{[X]}(Y)\right)` or
-.. math::
+.. math:: a_n = \left(\frac{1}{2}\right)^n
- g(A,B,Y) = f \left(A,B,X=h^{[X]}(Y)\right)
-
Use ``.`` for "empty" delimiters:
-.. math::
+.. math:: A = \left . \frac{1}{1-n}\, \right |_{n=0}^\infty
- A = \left . \frac{1}{1-n}\, \right |_{n=0}^\infty
-
The following symbols extend when used with ``\left`` and ``\right``:
Pairing delimiters
@@ -225,10 +222,9 @@
The use of ``|`` and ``\|`` for pairs of vertical bars may produce
incorrect spacing, e.g., ``|k|=|-k|`` produces `|k| = |−k|` and
-``|\sin(x)|`` produces `|\sin(x)|`. The pairing delimiters, e.g.
-`\lvert -k\rvert`
-and `\lvert\sin(x)\rvert`, prevent this problem (in LaTeX and
-MathJax).
+``|\sin(x)|`` produces `|\sin(x)|`. The pairing delimiters, e.g.
+`\lvert -k\rvert` and `\lvert\sin(x)\rvert`, prevent this problem
+(in LaTeX and MathJax).
Vertical Arrows
~~~~~~~~~~~~~~~
@@ -437,12 +433,12 @@
`\nleftarrow` ``\nleftarrow`` `\nrightarrow` ``\nrightarrow``
`\nLeftarrow` ``\nLeftarrow`` `\nRightarrow` ``\nRightarrow``
`\nleftrightarrow` ``\nleftrightarrow`` `\nLeftrightarrow` ``\nLeftrightarrow``
- `\nwarrow` ``\nwarrow`` `\nearrow` ``\nearrow``
- `\swarrow` ``\swarrow`` `\searrow` ``\searrow``
+ `\nwarrow` ``\nwarrow`` `\nearrow` ``\nearrow``
+ `\swarrow` ``\swarrow`` `\searrow` ``\searrow``
`\twoheadleftarrow` ``\twoheadleftarrow`` `\twoheadrightarrow` ``\twoheadrightarrow``
`\upharpoonleft` ``\upharpoonleft`` `\upharpoonright` ``\upharpoonright``
`\downharpoonleft` ``\downharpoonleft`` `\downharpoonright` ``\downharpoonright``
- `\upuparrows` ``\upuparrows`` `\downdownarrows` ``\downdownarrows``
+ `\upuparrows` ``\upuparrows`` `\downdownarrows` ``\downdownarrows``
====================== ======================== ===================== =======================
@@ -561,7 +557,7 @@
A \xleftarrow{n+\mu-1} B \xrightarrow[T]{n\pm i-1} C
-results in
+results in
.. math:: A \xleftarrow{n+\mu-1} B \xrightarrow[T]{n\pm i-1} C
@@ -624,13 +620,13 @@
.. class:: colwidths-auto
- ===================== ============================== ============================
- command example result
- ===================== ============================== ============================
- ``\sqrt`` ``\sqrt{x^2-1}`` `\sqrt{x^2-1}`
- ``\frac`` ``\frac{1}{2}`` `\frac{1}{2}`
- ``\left``, ``\right`` ``\left(\frac{1}{2}\right)^n`` `\left(\frac{1}{2}\right)^n`
- ===================== ============================== ============================
+ ========= ==================== ==================
+ command example result
+ ========= ==================== ==================
+ ``\sqrt`` ``\sqrt{x^2-1}`` `\sqrt{x^2-1}`
+ .. ``\sqrt[3n]{x^2-1}`` `\sqrt[3n]{x^2-1}`
+ ``\frac`` ``\frac{1}{1-x}`` `\frac{1}{1-x}`
+ ========= ==================== ==================
Text
====
@@ -648,8 +644,6 @@
Currently, math in text is not supported by LaTeX2MathML.
-
-
ToDo
====
@@ -657,10 +651,9 @@
* Math inside text: ``n - 1 \text{if $n$ is odd}``.
* Remove circular refs.
-* Decimal numbers.
-* Implement ``\circledS``? (in short-math-guide.pdf but not in
- the Unicode `Mathematical Character Repertoire`__)
-* ``\DeclareMathOperator``
+* Implement ``\circledS``? Ⓢ (and other characters
+ in the short-math-guide.pdf but not in the
+ Unicode `Mathematical Character Repertoire`__)
__ http://www.unicode.org/reports/tr25/
Modified: trunk/docutils/docutils/utils/math/latex2mathml.py
===================================================================
--- trunk/docutils/docutils/utils/math/latex2mathml.py 2021-05-20 12:24:07 UTC (rev 8753)
+++ trunk/docutils/docutils/utils/math/latex2mathml.py 2021-05-20 12:24:25 UTC (rev 8754)
@@ -109,12 +109,12 @@
'nsubseteqq': u'\u2AC5\u0338', # ⫅̸
'nsupseteqq': u'\u2AC6\u0338', # ⫆̸
# pairing delimiters
- 'lvert': '|',
+ 'lvert': u'|',
'lVert': u'\u2016', # ‖
- 'rvert': '|',
+ 'rvert': u'|',
'rVert': u'\u2016',
# use <mo> to allow "movablelimits" attribute
- 'lim': u'lim',
+ 'lim': u'lim',
})
# special cases
@@ -140,6 +140,7 @@
'iint', 'int', 'oiint', 'oint', 'ointctrclockwise',
'prod', 'sqint', 'sum', 'varointclockwise')
] + ['lim']
+ # TODO: 'sup', 'inf', 'max', 'min
# pre-composed characters for negated symbols
# see https://www.w3.org/TR/xml-entity-names/#combining
@@ -460,7 +461,7 @@
# >>> msubsup(mi('base'), mi('super'), mi('sub'), switch=True)
# msubsup(mi('base'), mi('sub'), mi('super'))
-class mroot(math):
+class mroot(MathScriptOrLimit):
nchildren = 2
class mfrac(math):
@@ -503,6 +504,27 @@
# >>> tex_cmdname('') # empty string
# ('', '')
+def tex_number(string):
+ """Return first number literal and remainder of `string`.
+
+ >>> tex_number('123.4')
+ ('123.4', '')
+
+ """
+ m = re.match(r'([0-9.,]+)(.*)', string)
+ if m is None:
+ return '', string
+ return m.group(1), m.group(2)
+
+# Test:
+#
+# >>> tex_number(' 123.4')
+# ('', ' 123.4')
+# >>> tex_number('23,400')
+# ('23,400', '')
+# >>> tex_number('1 000.4')
+# ('1', ' 000.4')
+
def tex_token(string):
"""Return first simple TeX token and remainder of `string`.
@@ -579,6 +601,8 @@
# SyntaxError: Could not extract optional argument from '[group with [nested group]]'
+
+
def parse_latex_math(node, string):
"""Append MathML conversion of `string` to `node`.
@@ -618,7 +642,8 @@
elif c.isalpha():
node = node.append(mi(c))
elif c.isdigit():
- node = node.append(mn(c))
+ number, string = tex_number(string)
+ node = node.append(mn(c+number))
elif c in "/()[]|":
node = node.append(mo(c, stretchy='false'))
# use dedicated mathematical operator characters
@@ -636,6 +661,8 @@
# math(xmlns='http://www.w3.org/1998/Math/MathML')
# >>> parse_latex_math(math(), ' \\sqrt{ \\alpha}')
# math(msqrt(mi('α')))
+# >>> parse_latex_math(math(), '23.4x')
+# math(mn('23.4'), mi('x'))
# >>> parse_latex_math(math(), '\\sqrt 2 \\ne 3')
# math(msqrt(mn('2')), mo('≠'), mn('3'))
# >>> parse_latex_math(math(), '\\sqrt{2 + 3} < 3')
@@ -800,11 +827,18 @@
# ==================================
if name == 'sqrt':
- new_node = msqrt()
- if string.startswith('{'): # argument is a group
- string = string[1:] # mrow implied, skip opening bracket
- else: # no group, enclose only one element
- new_node.nchildren = 1
+ # TODO: optional arg -> <mroot> <mn>2</mn> <mn>3</mn> </mroot>
+ degree, string = tex_optarg(string)
+ if degree:
+ indexnode = mrow()
+ parse_latex_math(indexnode, degree)
+ new_node = mroot(indexnode, switch=True)
+ else:
+ new_node = msqrt()
+ if string.startswith('{'): # argument is a group
+ string = string[1:] # mrow implied, skip opening bracket
+ else: # no group, enclose only one element
+ new_node.nchildren = 1
node.append(new_node)
return new_node, string
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2021-05-20 12:24:41
|
Revision: 8755
http://sourceforge.net/p/docutils/code/8755
Author: milde
Date: 2021-05-20 12:24:40 +0000 (Thu, 20 May 2021)
Log Message:
-----------
MathML: support \circledR, \circledS, functions that take limits.
Modified Paths:
--------------
trunk/docutils/docs/user/mathematics.txt
trunk/docutils/docutils/utils/math/latex2mathml.py
trunk/docutils/docutils/utils/math/tex2unichar.py
trunk/docutils/docutils/utils/math/unichar2tex.py
Modified: trunk/docutils/docs/user/mathematics.txt
===================================================================
--- trunk/docutils/docs/user/mathematics.txt 2021-05-20 12:24:25 UTC (rev 8754)
+++ trunk/docutils/docs/user/mathematics.txt 2021-05-20 12:24:40 UTC (rev 8755)
@@ -99,13 +99,6 @@
a & = (x + y)^2 \\
& = x^2 + 2xy + y^2
-
-Not *all* math syntax constructs work with every output format, but basic
-everyday-math should work.
-
-If a command or a special symbol is not desribed in this document, then
-it is probably not implemented in the internal LaTeX -> MathML converter.
-
.. _hyperlink references: ../ref/rst/restructuredtext.html#hyperlink-references
@@ -268,13 +261,14 @@
------------------
.. class:: colwidths-auto
-============= =============== ========= =========== ========= =========== ========== ============
-`\aleph` ``\aleph`` `\ell` ``\ell`` `\Game` ``\Game`` `\Bbbk` ``\Bbbk``
-`\beth` ``\beth`` `\eth` ``\eth`` `\hbar` ``\hbar`` `\mho` ``\mho``
-`\gimel` ``\gimel`` `\exists` ``\exists`` `\hslash` ``\hslash`` `\partial` ``\partial``
-`\daleth` ``\daleth`` `\Finv` ``\Finv`` `\Im` ``\Im`` `\Re` ``\Re``
-`\complement` ``\complement`` `\forall` ``\forall`` `\imath` ``\imath`` `\wp` ``\wp``
-============= =============== ========= =========== ========= =========== ========== ============
+========== ============ ============= =============== ========= =========== =========== =============
+`\aleph` ``\aleph`` `\forall` ``\forall`` `\hbar` ``\hbar`` `\ell` ``\ell``
+`\beth` ``\beth`` `\complement` ``\complement`` `\hslash` ``\hslash`` `\wp` ``\wp``
+`\gimel` ``\gimel`` `\exists` ``\exists`` `\Im` ``\Im`` `\Re` ``\Re``
+`\daleth` ``\daleth`` `\Finv` ``\Finv`` `\imath` ``\imath`` `\circledR` ``\circledR``
+`\partial` ``\partial`` `\Game` ``\Game`` `\Bbbk` ``\Bbbk`` `\circledS` ``\circledS``
+`\eth` ``\eth`` `\mho` ``\mho``
+========== ============ ============= =============== ========= =========== =========== =============
Mathematical Alphabets
@@ -607,6 +601,7 @@
:m:`|\quad|` ``|\quad|`` 1 em
:m:`|\;|` ``|\;|`` thick
:m:`|\ |` ``|\ |`` standard
+ :m:`|~|` ``|~|`` non-break
:m:`|\:|` ``|\:|`` medium
:m:`|\,|` ``|\,|`` thin
:m:`| |` ``| |`` none
@@ -651,9 +646,9 @@
* Math inside text: ``n - 1 \text{if $n$ is odd}``.
* Remove circular refs.
-* Implement ``\circledS``? Ⓢ (and other characters
+* Document ``\circledS``, \circledR, implement other characters
in the short-math-guide.pdf but not in the
- Unicode `Mathematical Character Repertoire`__)
+ Unicode `Mathematical Character Repertoire`__
__ http://www.unicode.org/reports/tr25/
@@ -702,11 +697,12 @@
Accents should be nearer to the base (in MathML Firefox 78, it's vice versa!):
`\bar a \overline a, \bar l \overline l, \bar i \overline i`.
-In inline formulas and fractions, the limits on lim, sum and integral should
-move to index postions: `\lim_{c\to0} \oint_c f(x) \mathrm{d}x` vs.
+In inline formulas and fractions, the limits on lim, sum and integrals,
-.. math:: \lim_{c\to0} \oint_c f(x) \mathrm{d}x
+.. math:: \lim_{c\to0} \oint_c f(x) \mathrm{d}x,
+should move to index postions: `\lim_{c\to0} \oint_c f(x) \mathrm{d}x`.
+
Sub- and superscript may be given in any order:
`x_i^j = x^j_i` and `\int_0^1 = \int^1_0`.
Modified: trunk/docutils/docutils/utils/math/latex2mathml.py
===================================================================
--- trunk/docutils/docutils/utils/math/latex2mathml.py 2021-05-20 12:24:25 UTC (rev 8754)
+++ trunk/docutils/docutils/utils/math/latex2mathml.py 2021-05-20 12:24:40 UTC (rev 8755)
@@ -57,12 +57,12 @@
'Gamma':u'\u0393', 'Lambda':u'\u039b'}
# functions -> <mi>
-functions = ['arccos', 'arcsin', 'arctan', 'arg', 'cos', 'cosh',
- 'cot', 'coth', 'csc', 'deg', 'det', 'dim',
- 'exp', 'gcd', 'hom', 'inf', 'ker', 'lg',
- 'ln', 'log', 'max', 'min', 'Pr',
- 'sec', 'sin', 'sinh', 'sup', 'tan', 'tanh']
-functions = dict((name, name) for name in functions)
+functions = dict((name, name) for name in
+ ('arccos', 'arcsin', 'arctan', 'arg', 'cos', 'cosh',
+ 'cot', 'coth', 'csc', 'deg', 'det', 'dim',
+ 'exp', 'gcd', 'hom', 'inf', 'ker', 'lg',
+ 'ln', 'log', 'max', 'min', 'Pr',
+ 'sec', 'sin', 'sinh', 'sup', 'tan', 'tanh'))
functions.update({# functions with a space in the name
'liminf': u'lim\u202finf', 'limsup': u'lim\u202fsup',
'injlim': u'inj\u202flim', 'projlim': u'proj\u202flim',
@@ -72,6 +72,10 @@
# custom function name
'operatorname': None})
+# function with limits, use <mo> to allow "movablelimits" attribute
+functions_with_limits = dict((name, name) for name in
+ ('lim', 'sup', 'inf', 'max', 'min'))
+
# math font selection -> <mi mathvariant=...> or <mstyle mathvariant=...>
math_alphabets = {# 'cmdname': 'mathvariant value' # package
'boldsymbol': 'bold',
@@ -101,6 +105,7 @@
operators.update(tex2unichar.mathopen) # Braces
operators.update(tex2unichar.mathclose) # Braces
operators.update(tex2unichar.mathfence)
+operators.update(functions_with_limits)
operators.update({# negated symbols without pre-composed Unicode character
'nleqq': u'\u2266\u0338', # ≦̸
'ngeqq': u'\u2267\u0338', # ≧̸
@@ -108,13 +113,11 @@
'ngeqslant': u'\u2a7e\u0338', # ⩾̸
'nsubseteqq': u'\u2AC5\u0338', # ⫅̸
'nsupseteqq': u'\u2AC6\u0338', # ⫆̸
- # pairing delimiters
- 'lvert': u'|',
+ # alias commands:
+ 'lvert': u'|', # pairing delimiters
'lVert': u'\u2016', # ‖
'rvert': u'|',
'rVert': u'\u2016',
- # use <mo> to allow "movablelimits" attribute
- 'lim': u'lim',
})
# special cases
@@ -134,13 +137,13 @@
'smallint': u'\u222b', # ∫ INTEGRAL
}
-# operators with limits either over/under or in index position
+# Operators and functions with limits
+# over/under in display formulas and in index position inline
sumintprod = [operators[name] for name in
('coprod', 'fatsemi', 'fint', 'iiiint', 'iiint',
'iint', 'int', 'oiint', 'oint', 'ointctrclockwise',
- 'prod', 'sqint', 'sum', 'varointclockwise')
- ] + ['lim']
- # TODO: 'sup', 'inf', 'max', 'min
+ 'prod', 'sqint', 'sum', 'varointclockwise',
+ 'lim', 'sup', 'inf', 'max', 'min')]
# pre-composed characters for negated symbols
# see https://www.w3.org/TR/xml-entity-names/#combining
@@ -214,13 +217,15 @@
'tilde': u'˜', # u'\u0303',
}
-# limits etc. -> <mover> rsp. <munder>
-over = {'overbrace': u'\u23DE', # TOP CURLY BRACKET
+# limits etc. -> <mover accent="false"> or <munder>
+over = {# 'ddot': u'..',
+ # 'dddot': u'…', # too wide if accent="true"
+ 'overbrace': u'\u23DE', # TOP CURLY BRACKET
'overleftarrow': u'\u2190',
'overleftrightarrow': u'\u2194',
'overline': u'¯',
'overrightarrow': u'\u2192',
- 'vec': u'\u2192', # → (too heavy if accent="true")
+ 'vec': u'\u2192', # → too heavy if accent="true"
'widehat': u'^',
'widetilde': u'~'}
under = {'underbrace': u'\u23DF',
@@ -235,6 +240,7 @@
# cf. https://www.w3.org/TR/MathML3/chapter7.html#chars.anomalous
anomalous_chars = {'-': u'\u2212', # HYPHEN-MINUS -> MINUS SIGN
':': u'\u2236', # COLON -> RATIO
+ '~': u'\u00a0', # NO-BREAK SPACE
}
# blackboard bold (Greek characters not working with "mathvariant" (Firefox 78)
@@ -506,10 +512,10 @@
def tex_number(string):
"""Return first number literal and remainder of `string`.
-
+
>>> tex_number('123.4')
('123.4', '')
-
+
"""
m = re.match(r'([0-9.,]+)(.*)', string)
if m is None:
@@ -517,7 +523,7 @@
return m.group(1), m.group(2)
# Test:
-#
+#
# >>> tex_number(' 123.4')
# ('', ' 123.4')
# >>> tex_number('23,400')
@@ -667,6 +673,8 @@
# math(msqrt(mn('2')), mo('≠'), mn('3'))
# >>> parse_latex_math(math(), '\\sqrt{2 + 3} < 3')
# math(msqrt(mn('2'), mo('+'), mn('3')), mo('<'), mn('3'))
+# >>> parse_latex_math(math(), '\max_x') # function takes limits
+# math(munder(mi('max', movablelimits='true'), mi('x')))
# >>> parse_latex_math(math(), 'x^j_i') # ensure correct order: base, sub, sup
# math(msubsup(mi('x'), mi('i'), mi('j')))
# >>> parse_latex_math(math(), '\int^j_i') # ensure correct order
Modified: trunk/docutils/docutils/utils/math/tex2unichar.py
===================================================================
--- trunk/docutils/docutils/utils/math/tex2unichar.py 2021-05-20 12:24:25 UTC (rev 8754)
+++ trunk/docutils/docutils/utils/math/tex2unichar.py 2021-05-20 12:24:40 UTC (rev 8755)
@@ -315,7 +315,8 @@
'checkmark': u'\u2713', # ✓ CHECK MARK
'circlearrowleft': u'\u21ba', # ↺ ANTICLOCKWISE OPEN CIRCLE ARROW
'circlearrowright': u'\u21bb', # ↻ CLOCKWISE OPEN CIRCLE ARROW
- 'circledR': u'\xae', # ® REGISTERED SIGN
+ 'circledR': u'\u24c7', # Ⓡ CIRCLED LATIN CAPITAL LETTER R
+ 'circledS': u'\u24c8', # Ⓢ CIRCLED LATIN CAPITAL LETTER S
'circledcirc': u'\u25ce', # ◎ BULLSEYE
'clubsuit': u'\u2663', # ♣ BLACK CLUB SUIT
'complement': u'\u2201', # ∁ COMPLEMENT
@@ -383,7 +384,9 @@
'sptilde': u'~', # ~ TILDE
'square': u'\u25fb', # ◻ WHITE MEDIUM SQUARE
'sun': u'\u263c', # ☼ WHITE SUN WITH RAYS
+ 'surd': u'\u221a', # √ SQUARE ROOT
'taurus': u'\u2649', # ♉ TAURUS
+ 'textregistered': u'\u24c7', # Ⓡ CIRCLED LATIN CAPITAL LETTER R
'therefore': u'\u2234', # ∴ THEREFORE
'third': u'\u2034', # ‴ TRIPLE PRIME
'top': u'\u22a4', # ⊤ DOWN TACK
@@ -614,8 +617,6 @@
'searrow': u'\u2198', # ↘ SOUTH EAST ARROW
'sim': u'\u223c', # ∼ TILDE OPERATOR
'simeq': u'\u2243', # ≃ ASYMPTOTICALLY EQUAL TO
- 'smallfrown': u'\u2322', # ⌢ FROWN
- 'smallsmile': u'\u2323', # ⌣ SMILE
'smile': u'\u2323', # ⌣ SMILE
'sqsubset': u'\u228f', # ⊏ SQUARE IMAGE OF
'sqsubseteq': u'\u2291', # ⊑ SQUARE IMAGE OF OR EQUAL TO
Modified: trunk/docutils/docutils/utils/math/unichar2tex.py
===================================================================
--- trunk/docutils/docutils/utils/math/unichar2tex.py 2021-05-20 12:24:25 UTC (rev 8754)
+++ trunk/docutils/docutils/utils/math/unichar2tex.py 2021-05-20 12:24:40 UTC (rev 8755)
@@ -10,7 +10,6 @@
163: u'\\pounds ',
165: u'\\yen ',
172: u'\\neg ',
-174: u'\\circledR ',
177: u'\\pm ',
215: u'\\times ',
240: u'\\eth ',
@@ -56,11 +55,15 @@
981: u'\\phi ',
982: u'\\varpi ',
989: u'\\digamma ',
+1008: u'\\varkappa ',
+1009: u'\\varrho ',
+1013: u'\\epsilon ',
1014: u'\\backepsilon ',
8193: u'\\quad ',
8214: u'\\| ',
8224: u'\\dagger ',
8225: u'\\ddagger ',
+8226: u'\\bullet ',
8230: u'\\ldots ',
8242: u'\\prime ',
8245: u'\\backprime ',
@@ -158,7 +161,7 @@
8706: u'\\partial ',
8707: u'\\exists ',
8708: u'\\nexists ',
-8709: u'\\varnothing ',
+8709: u'\\emptyset ',
8711: u'\\nabla ',
8712: u'\\in ',
8713: u'\\notin ',
@@ -174,7 +177,7 @@
8727: u'\\ast ',
8728: u'\\circ ',
8729: u'\\bullet ',
-8730: u'\\sqrt ',
+8730: u'\\surd ',
8731: u'\\sqrt[3] ',
8732: u'\\sqrt[4] ',
8733: u'\\propto ',
@@ -345,12 +348,16 @@
8995: u'\\smile ',
9182: u'\\overbrace ',
9183: u'\\underbrace ',
+9415: u'\\circledR ',
+9416: u'\\circledS ',
9651: u'\\bigtriangleup ',
+9652: u'\\blacktriangle ',
9655: u'\\rhd ',
9661: u'\\bigtriangledown ',
9665: u'\\lhd ',
9671: u'\\Diamond ',
9674: u'\\lozenge ',
+9711: u'\\bigcirc ',
9723: u'\\square ',
9724: u'\\blacksquare ',
9733: u'\\bigstar ',
@@ -364,6 +371,8 @@
10003: u'\\checkmark ',
10016: u'\\maltese ',
10178: u'\\perp ',
+10187: u'\\diagup ',
+10189: u'\\diagdown ',
10216: u'\\langle ',
10217: u'\\rangle ',
10222: u'\\lgroup ',
@@ -400,6 +409,8 @@
10902: u'\\eqslantgtr ',
10927: u'\\preceq ',
10928: u'\\succeq ',
+10933: u'\\precneqq ',
+10934: u'\\succneqq ',
10935: u'\\precapprox ',
10936: u'\\succapprox ',
10937: u'\\precnapprox ',
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2021-05-20 12:25:04
|
Revision: 8756
http://sourceforge.net/p/docutils/code/8756
Author: milde
Date: 2021-05-20 12:24:59 +0000 (Thu, 20 May 2021)
Log Message:
-----------
MathML: remove unrequired <mrow>s, support more commands.
Support additional commands from the AMS math-guide.
Remove <mrow>, if it is single child and the parent inferres an mrow
or if it has only one child element.
tex_number(): do not return trailing delimiter.
Use class "mathscr" instead of hard-codes font name for \mathscr.
Modified Paths:
--------------
trunk/docutils/docs/user/mathematics.txt
trunk/docutils/docutils/utils/math/latex2mathml.py
trunk/docutils/docutils/utils/math/tex2unichar.py
trunk/docutils/docutils/writers/html5_polyglot/plain.css
trunk/docutils/docutils/writers/html5_polyglot/responsive.css
trunk/docutils/test/functional/expected/math_output_mathml.html
Modified: trunk/docutils/docs/user/mathematics.txt
===================================================================
--- trunk/docutils/docs/user/mathematics.txt 2021-05-20 12:24:40 UTC (rev 8755)
+++ trunk/docutils/docs/user/mathematics.txt 2021-05-20 12:24:59 UTC (rev 8756)
@@ -118,7 +118,7 @@
.. class:: colwidths-auto
=========== ============= =========== ============= ============== ================
- `\acute{x}` ``\acute{x}`` `\dot{t}` ``\dot{t}`` `\hat{H}` ``\hat{H}``
+ `\acute{x}` ``\acute{x}`` `\dot{t}` ``\dot{t}`` `\hat{x}` ``\hat{x}``
`\bar{v}` ``\bar{v}`` `\ddot{t}` ``\ddot{t}`` `\mathring{x}` ``\mathring{x}``
`\breve{x}` ``\breve{x}`` `\dddot{t}` ``\dddot{t}`` `\tilde{n}` ``\tilde{n}``
`\check{x}` ``\check{x}`` `\grave{x}` ``\grave{x}`` `\vec{x}` ``\vec{x}``
@@ -190,28 +190,22 @@
=============== ================= ========================= ===========================
`( )` ``( )`` `\langle \rangle` ``\langle \rangle``
- `[ ]` ``[ ]`` `\lceil \rceil` ``\lceil \rceil``
+ `[ ]` ``[ ]`` `\lceil \rceil` ``\lceil \rceil``
`\{ \}` ``\{ \}`` `\lfloor \rfloor` ``\lfloor \rfloor``
- `\lvert \rvert` ``\lvert \rvert`` `\lVert \rVert` ``\lVert \rVert``
+ `\lvert \rvert` ``\lvert \rvert`` `\lgroup \rgroup` ``\lgroup \rgroup``
+ `\lVert \rVert` ``\lVert \rVert`` `\lmoustache \rmoustache` ``\lmoustache \rmoustache``
=============== ================= ========================= ===========================
-.. The "math-guide" also lists macros for parts of extensible delimiters:
- ============= = ============= = ============ =
- `\lmoustache` ⎰ `\rmoustache` ⎱ `\bracevert` ⎪
- `\lgroup` ⟮ `\rgroup` ⟯ `\arrowvert` ⏐
- .. `\Arrowvert` ‖
- ============= = ============= = ============ =
-
Nonpairing delimiters
~~~~~~~~~~~~~~~~~~~~~
.. class:: colwidths-auto
- =========== ===========================
- `|` ``|`` `\vert` ``\vert``
- `\|` ``\|`` `\Vert` ``\Vert``
- `/` ``/`` `\backslash` ``\backslash``
- =========== ===========================
+ ==== ====== ============ ============== ============ ==============
+ `|` ``|`` `\vert` ``\vert`` `\arrowvert` ``\arrowvert``
+ `\|` ``\|`` `\Vert` ``\Vert`` `\Arrowvert` ``\Arrowvert``
+ `/` ``/`` `\backslash` ``\backslash`` `\bracevert` ``\bracevert``
+ ==== ====== ============ ============== ============ ==============
The use of ``|`` and ``\|`` for pairs of vertical bars may produce
incorrect spacing, e.g., ``|k|=|-k|`` produces `|k| = |−k|` and
@@ -229,6 +223,37 @@
`\updownarrow` ``\updownarrow`` `\Updownarrow` ``\Updownarrow``
=============================== ======================================
+Functions (named operators)
+---------------------------
+.. class:: colwidths-auto
+
+ ========= =========== ========= =========== ============= ================
+ `\arccos` ``\arccos`` `\gcd` ``\gcd`` `\Pr` ``\Pr``
+ `\arcsin` ``\arcsin`` `\hom` ``\hom`` `\projlim` ``\projlim``
+ `\arctan` ``\arctan`` `\inf` ``\inf`` `\sec` ``\sec``
+ `\arg` ``\arg`` `\injlim` ``\injlim`` `\sin` ``\sin``
+ `\cos` ``\cos`` `\ker` ``\ker`` `\sinh` ``\sinh``
+ `\cosh` ``\cosh`` `\lg` ``\lg`` `\sup` ``\sup``
+ `\cot` ``\cot`` `\lim` ``\lim`` `\tan` ``\tan``
+ `\coth` ``\coth`` `\liminf` ``\liminf`` `\tanh` ``\tanh``
+ `\csc` ``\csc`` `\limsup` ``\limsup`` `\varlimsup` ``\varlimsup``
+ `\deg` ``\deg`` `\ln` ``\ln`` `\varliminf` ``\varliminf``
+ `\det` ``\det`` `\log` ``\log`` `\varprojlim` ``\varprojlim``
+ `\dim` ``\dim`` `\max` ``\max`` `\varinjlim` ``\varinjlim``
+ `\exp` ``\exp`` `\min` ``\min``
+ ========= =========== ========= =========== ============= ================
+
+Named operators outside the above list can be typeset with
+``\operatorname{name}``, e.g.
+
+.. math:: \operatorname{sgn}(-3) = -1.
+
+The ``\DeclareMathOperator`` command can only be used in the
+`LaTeX preamble`_.
+
+.. _LaTeX preamble: latex.html#latex-preamble
+
+
Greek letters
-------------
@@ -243,16 +268,16 @@
========== ============ ========== ============ ========== ============ ============== ===============
`\Gamma` ``\Gamma`` `\alpha` ``\alpha`` `\mu` ``\mu`` `\omega` ``\omega``
- `\Delta` ``\Delta`` `\beta` ``\beta`` `\nu` ``\nu`` `\backepsilon` ``\backepsilon``
- `\Lambda` ``\Lambda`` `\gamma` ``\gamma`` `\xi` ``\xi`` `\digamma` ``\digamma``
- `\Omega` ``\Omega`` `\delta` ``\delta`` `\pi` ``\pi`` `\varepsilon` ``\varepsilon``
- `\Phi` ``\Phi`` `\epsilon` ``\epsilon`` `\rho` ``\rho`` `\varkappa` ``\varkappa``
- `\Pi` ``\Pi`` `\zeta` ``\zeta`` `\sigma` ``\sigma`` `\varphi` ``\varphi``
- `\Psi` ``\Psi`` `\eta` ``\eta`` `\tau` ``\tau`` `\varpi` ``\varpi``
- `\Sigma` ``\Sigma`` `\theta` ``\theta`` `\upsilon` ``\upsilon`` `\varrho` ``\varrho``
- `\Theta` ``\Theta`` `\iota` ``\iota`` `\phi` ``\phi`` `\varsigma` ``\varsigma``
- `\Upsilon` ``\Upsilon`` `\kappa` ``\kappa`` `\chi` ``\chi`` `\vartheta` ``\vartheta``
- `\Xi` ``\Xi`` `\lambda` ``\lambda`` `\psi` ``\psi``
+ `\Delta` ``\Delta`` `\beta` ``\beta`` `\nu` ``\nu`` `\digamma` ``\digamma``
+ `\Lambda` ``\Lambda`` `\gamma` ``\gamma`` `\xi` ``\xi`` `\backepsilon` ``\backepsilon``
+ `\Phi` ``\Phi`` `\delta` ``\delta`` `\pi` ``\pi`` `\varepsilon` ``\varepsilon``
+ `\Pi` ``\Pi`` `\epsilon` ``\epsilon`` `\rho` ``\rho`` `\varkappa` ``\varkappa``
+ `\Psi` ``\Psi`` `\zeta` ``\zeta`` `\sigma` ``\sigma`` `\varphi` ``\varphi``
+ `\Sigma` ``\Sigma`` `\eta` ``\eta`` `\tau` ``\tau`` `\varpi` ``\varpi``
+ `\Theta` ``\Theta`` `\theta` ``\theta`` `\upsilon` ``\upsilon`` `\varrho` ``\varrho``
+ `\Upsilon` ``\Upsilon`` `\iota` ``\iota`` `\phi` ``\phi`` `\varsigma` ``\varsigma``
+ `\Xi` ``\Xi`` `\kappa` ``\kappa`` `\chi` ``\chi`` `\vartheta` ``\vartheta``
+ `\Omega` ``\Omega`` `\lambda` ``\lambda`` `\psi` ``\psi``
========== ============ ========== ============ ========== ============ ============== ===============
__ http://mirrors.ctan.org/macros/latex/contrib/isomath/isomath.html#table-2
@@ -262,12 +287,12 @@
.. class:: colwidths-auto
========== ============ ============= =============== ========= =========== =========== =============
-`\aleph` ``\aleph`` `\forall` ``\forall`` `\hbar` ``\hbar`` `\ell` ``\ell``
-`\beth` ``\beth`` `\complement` ``\complement`` `\hslash` ``\hslash`` `\wp` ``\wp``
-`\gimel` ``\gimel`` `\exists` ``\exists`` `\Im` ``\Im`` `\Re` ``\Re``
+`\aleph` ``\aleph`` `\forall` ``\forall`` `\hbar` ``\hbar`` `\ell` ``\ell``
+`\beth` ``\beth`` `\complement` ``\complement`` `\hslash` ``\hslash`` `\wp` ``\wp``
+`\gimel` ``\gimel`` `\exists` ``\exists`` `\Im` ``\Im`` `\Re` ``\Re``
`\daleth` ``\daleth`` `\Finv` ``\Finv`` `\imath` ``\imath`` `\circledR` ``\circledR``
`\partial` ``\partial`` `\Game` ``\Game`` `\Bbbk` ``\Bbbk`` `\circledS` ``\circledS``
-`\eth` ``\eth`` `\mho` ``\mho``
+`\eth` ``\eth`` `\mho` ``\mho``
========== ============ ============= =============== ========= =========== =========== =============
@@ -274,8 +299,9 @@
Mathematical Alphabets
----------------------
-For mathematical variables where style variations are important semantically,
-select an appropriate *math alphabet* [#]_.
+Mathematical alphabets select a combination of font attributes (shape,
+weight, family) [#]_. They are intended for mathematical variables where
+style variations are important semantically.
.. class:: colwidths-auto
@@ -321,7 +347,12 @@
.. math:: \mathbfit{r}^2=x^2+y^2+z^2.
+The package mathrsfs_ (and some drop-in replacements) define the ``\mathscr``
+macro that selects a differently shaped "script" alphabet.
+Compare `\mathscr{A, B, …, Z, a, b, …, z}`
+with `\mathcal{A, B, …, Z, a, b, …, z}`.
+
In contrast to the math alphabet selectors, ``\boldsymbol`` only changes
the *font weight*. In LaTeX, it can be used to get a bold version of any
mathematical symbol (for other output formats, results are mixed):
@@ -350,46 +381,18 @@
==================== ====================== ================ ================== ================= ===================
-Named operators
----------------
-.. class:: colwidths-auto
-
- ========= =========== ========= =========== ============= ================
- `\arccos` ``\arccos`` `\gcd` ``\gcd`` `\Pr` ``\Pr``
- `\arcsin` ``\arcsin`` `\hom` ``\hom`` `\projlim` ``\projlim``
- `\arctan` ``\arctan`` `\inf` ``\inf`` `\sec` ``\sec``
- `\arg` ``\arg`` `\injlim` ``\injlim`` `\sin` ``\sin``
- `\cos` ``\cos`` `\ker` ``\ker`` `\sinh` ``\sinh``
- `\cosh` ``\cosh`` `\lg` ``\lg`` `\sup` ``\sup``
- `\cot` ``\cot`` `\lim` ``\lim`` `\tan` ``\tan``
- `\coth` ``\coth`` `\liminf` ``\liminf`` `\tanh` ``\tanh``
- `\csc` ``\csc`` `\limsup` ``\limsup`` `\varlimsup` ``\varlimsup``
- `\deg` ``\deg`` `\ln` ``\ln`` `\varliminf` ``\varliminf``
- `\det` ``\det`` `\log` ``\log`` `\varprojlim` ``\varprojlim``
- `\dim` ``\dim`` `\max` ``\max`` `\varinjlim` ``\varinjlim``
- `\exp` ``\exp`` `\min` ``\min``
- ========= =========== ========= =========== ============= ================
-
-Named operators outside the above list can be typeset with
-``\operatorname{name}``, e.g.
-
-.. math:: \operatorname{sgn}(-3) = -1.
-
-The ``\DeclareMathOperator`` command can only be used in the
-`LaTeX preamble`_.
-
-.. _LaTeX preamble: latex.html#latex-preamble
-
Punctuation
-----------
.. class:: colwidths-auto
-======== ===============
-`\colon` ``\colon`` [#]_
-`\cdots` ``\cdots``
-`\ddots` ``\ddots``
-`\ddots` ``\ddots``
-======== ===============
+=== ===== ======== =============== ======== ==========
+`.` ``.`` `!` ``!`` `?` ``?``
+`/` ``/`` `\colon` ``\colon`` [#]_ `\dotsb` ``\dotsb``
+`|` ``|`` `\cdots` ``\cdots`` `\dotsc` ``\dotsc``
+`'` ``'`` `\ddots` ``\ddots`` `\dotsi` ``\dotsi``
+`;` ``;`` `\ldots` ``\ldots`` `\dotsm` ``\dotsm``
+`:` ``:`` `\vdots` ``\vdots`` `\dotso` ``\dotso``
+=== ===== ======== =============== ======== ==========
.. [#] Punctuation (not ratio):
Compare spacing in `a\colon b\to c` to `a:b = c`.
@@ -582,6 +585,9 @@
.. TODO: small matrices, matrices with delimiters built in?
+ The environments pmatrix, bmatrix, Bmatrix, vmatrix, and Vmatrix have
+ (respectively) ( ), [ ], { }, | |, and k k delimiters built in.
+
For piecewise function definitions there is a cases environment:
.. math::
@@ -596,19 +602,22 @@
.. class:: colwidths-auto
- ================= ================== =============
- :m:`|\qquad|` ``|\qquad|`` 2 em
- :m:`|\quad|` ``|\quad|`` 1 em
- :m:`|\;|` ``|\;|`` thick
- :m:`|\ |` ``|\ |`` standard
- :m:`|~|` ``|~|`` non-break
- :m:`|\:|` ``|\:|`` medium
- :m:`|\,|` ``|\,|`` thin
- :m:`| |` ``| |`` none
- :m:`|\!|` ``|\!|`` thin negative
- `|\hspace{1ex}|` ``|\hspace{1ex}|`` custom
- ================= ================== =============
+ ===================== ======== =======================
+ :m:`|\qquad|` ``|\qquad|`` (2em)
+ :m:`|\quad|` ``|\quad|`` (1em)
+ :m:`|~|` ``|~|`` ``|\nobreakspace|``
+ :m:`|\ |` ``|\ |`` escaped space
+ :m:`|\;|` ``|\;|`` ``|\thickspace|``
+ :m:`|\:|` ``|\:|`` ``|\medspace|``
+ :m:`|\,|` ``|\,|`` ``|\thinspace|``
+ :m:`| |` ``| |`` regular space (ignored)
+ :m:`|\!|` ``|\!|`` ``|\negthinspace|``
+ :m:`|\negmedspace|` ``|\negmedspace|``
+ :m:`|\negthickspace|` ``|\negthickspace|``
+ `|\hspace{1ex}|` ``|\hspace{1ex}|``
+ ===================== ======== =======================
+.. TODO: \phantom \hphantom, \vphantom
Roots and Fractions
-------------------
@@ -623,6 +632,8 @@
``\frac`` ``\frac{1}{1-x}`` `\frac{1}{1-x}`
========= ==================== ==================
+.. TODO: \dfrac, \tfrac, \binom, \dbinom, \tbinom
+
Text
====
@@ -638,22 +649,11 @@
Currently, math in text is not supported by LaTeX2MathML.
+.. TODO: Math inside text: ``n - 1 \text{if $n$ is odd}``.
-ToDo
-====
-internal LaTeX2MathML
-
-* Math inside text: ``n - 1 \text{if $n$ is odd}``.
-* Remove circular refs.
-* Document ``\circledS``, \circledR, implement other characters
- in the short-math-guide.pdf but not in the
- Unicode `Mathematical Character Repertoire`__
-
-__ http://www.unicode.org/reports/tr25/
-
Tests
-==========
+=====
Font changes
------------
@@ -670,15 +670,8 @@
Unicode supports the following blackboard-bold characters:
`\mathbb{a \ldots z A \ldots Z 0 \ldots 9
-\mathbb\Gamma \mathbb{\Pi} \mathbb {\Sigma}\mathbb\gamma \mathbb\pi}`.
+\mathbb\Gamma \mathbb{\Pi} \mathbb {\Sigma} \mathbb\gamma \mathbb\pi}`.
-The package mathrsfs_ (and some drop-in replacements) define the ``\mathscr``
-macro that selects a differently shaped "script" alphabet.
-Compare `\mathscr{A, B, …, Z, a, b, …, z}`
-with `\mathcal{A, B, …, Z, a, b, …, z}`.
-
-.. _rsfs: https://ctan.org/pkg/mathrsfs
-
Inferred <mrow>s in MathML
~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -707,3 +700,5 @@
`x_i^j = x^j_i` and `\int_0^1 = \int^1_0`.
Double exponent: `x^{10}^4`, `r_T_\mathrm{in}` and `x_i^n^2`.
+
+Binary vs. unary minus operator: `a - b = -c`
Modified: trunk/docutils/docutils/utils/math/latex2mathml.py
===================================================================
--- trunk/docutils/docutils/utils/math/latex2mathml.py 2021-05-20 12:24:40 UTC (rev 8755)
+++ trunk/docutils/docutils/utils/math/latex2mathml.py 2021-05-20 12:24:59 UTC (rev 8756)
@@ -57,7 +57,7 @@
'Gamma':u'\u0393', 'Lambda':u'\u039b'}
# functions -> <mi>
-functions = dict((name, name) for name in
+functions = dict((name, name) for name in
('arccos', 'arcsin', 'arctan', 'arg', 'cos', 'cosh',
'cot', 'coth', 'csc', 'deg', 'det', 'dim',
'exp', 'gcd', 'hom', 'inf', 'ker', 'lg',
@@ -73,7 +73,7 @@
'operatorname': None})
# function with limits, use <mo> to allow "movablelimits" attribute
-functions_with_limits = dict((name, name) for name in
+functions_with_limits = dict((name, name) for name in
('lim', 'sup', 'inf', 'max', 'min'))
# math font selection -> <mi mathvariant=...> or <mstyle mathvariant=...>
@@ -114,10 +114,16 @@
'nsubseteqq': u'\u2AC5\u0338', # ⫅̸
'nsupseteqq': u'\u2AC6\u0338', # ⫆̸
# alias commands:
- 'lvert': u'|', # pairing delimiters
- 'lVert': u'\u2016', # ‖
- 'rvert': u'|',
- 'rVert': u'\u2016',
+ 'lvert': u'|', # left |
+ 'lVert': u'\u2016', # left ‖
+ 'rvert': u'|', # right |
+ 'rVert': u'\u2016', # right ‖
+ 'Arrowvert': u'\u2016', # ‖
+ 'dotsb': u'\u22ef', # ⋯ with binary operators/relations
+ 'dotsc': u'\u2026', # … with commas
+ 'dotsi': u'\u22ef', # ⋯ with integrals
+ 'dotsm': u'\u22ef', # ⋯ multiplication dots
+ 'dotso': u'\u2026', # … other dots
})
# special cases
@@ -132,14 +138,14 @@
'shortparallel': u'\u2225', # ∥
'nshortmid': u'\u2224', # ∤
'nshortparallel': u'\u2226', # ∦
- 'smallfrown': u'\u2322', # ⌢ FROWN
- 'smallsmile': u'\u2323', # ⌣ SMILE
- 'smallint': u'\u222b', # ∫ INTEGRAL
+ 'smallfrown': u'\u2322', # ⌢ FROWN
+ 'smallsmile': u'\u2323', # ⌣ SMILE
+ 'smallint': u'\u222b', # ∫ INTEGRAL
}
# Operators and functions with limits
-# over/under in display formulas and in index position inline
-sumintprod = [operators[name] for name in
+# above/below in display formulas and in index position inline
+with_limits = [operators[name] for name in
('coprod', 'fatsemi', 'fint', 'iiiint', 'iiint',
'iint', 'int', 'oiint', 'oint', 'ointctrclockwise',
'prod', 'sqint', 'sum', 'varointclockwise',
@@ -249,11 +255,6 @@
u'Σ': u'\u2140', # ⅀
u'γ': u'\u213D', # ℽ
u'π': u'\u213C', # ℼ
- r'\Gamma': u'\u213E', # ℾ
- r'\Pi': u'\u213F', # ℿ
- r'\Sigma': u'\u2140', # ⅀
- r'\gamma': u'\u213D', # ℽ
- r'\pi': u'\u213C', # ℼ
}
@@ -369,12 +370,6 @@
# >>> math(CLASS='bold').xml_starttag()
# '<math class="bold">'
-class mrow(math):
- """Group sub-expressions as a horizontal row."""
-
-# >>> mrow(displaystyle='false')
-# mrow(displaystyle='false')
-
class mtable(math): pass
# >>> mtable(displaystyle='true')
@@ -382,13 +377,41 @@
# >>> math(mtable(displaystyle='true')).toprettyxml()
# '<math>\n <mtable displaystyle="true">\n </mtable>\n</math>'
+class mrow(math):
+ """Group sub-expressions as a horizontal row."""
+
+ def close(self):
+ """Close element and return first non-full parent or None.
+
+ Remove <mrow>, if it is single child and the parent inferres an mrow
+ or if it has only one child element.
+ """
+ parent = self.parent
+ if isinstance(parent, MathRowInferred) and parent.nchildren == 1:
+ parent.nchildren = None
+ parent.children = self.children
+ return parent.close()
+ if len(self) == 1:
+ try:
+ parent.children[parent.children.index(self)] = self.children[0]
+ except (AttributeError, ValueError):
+ return self.children[0]
+ return super(mrow, self).close()
+
+# >>> mrow(displaystyle='false')
+# mrow(displaystyle='false')
+
# The elements <msqrt>, <mstyle>, <merror>, <mpadded>, <mphantom>, <menclose>,
# <mtd>, <mscarry>, and <math> treat their contents as a single inferred mrow
# formed from all their children.
-class msqrt(mrow): pass
-class mstyle(mrow): pass
-class mtr(mrow): pass
-class mtd(mrow): pass
+class MathRowInferred(math):
+ """Base class for elements treating content as a single inferred mrow."""
+class mtr(MathRowInferred): pass
+class mtd(MathRowInferred): pass
+class mstyle(MathRowInferred):
+ nchildren = 1
+class msqrt(MathRowInferred):
+ nchildren = 1
class MathToken(math):
"""Token Element: contains data instead of children.
@@ -511,13 +534,13 @@
# ('', '')
def tex_number(string):
- """Return first number literal and remainder of `string`.
+ """Return leading number literal and remainder of `string`.
>>> tex_number('123.4')
('123.4', '')
"""
- m = re.match(r'([0-9.,]+)(.*)', string)
+ m = re.match(r'([0-9.,]*[0-9]+)(.*)', string)
if m is None:
return '', string
return m.group(1), m.group(2)
@@ -524,10 +547,14 @@
# Test:
#
-# >>> tex_number(' 123.4')
-# ('', ' 123.4')
-# >>> tex_number('23,400')
-# ('23,400', '')
+# >>> tex_number(' 23.4b') # leading whitespace -> no number
+# ('', ' 23.4b')
+# >>> tex_number('23,400/2') # comma separator included
+# ('23,400', '/2')
+# >>> tex_number('23. 4/2') # trailing separator not included
+# ('23', '. 4/2')
+# >>> tex_number('4, 2') # trailing separator not included
+# ('4', ', 2')
# >>> tex_number('1 000.4')
# ('1', ' 000.4')
@@ -650,15 +677,15 @@
elif c.isdigit():
number, string = tex_number(string)
node = node.append(mn(c+number))
+ elif c in anomalous_chars:
+ # characters with a special meaning in LaTeX math mode
+ node = node.append(mo(anomalous_chars[c]))
elif c in "/()[]|":
node = node.append(mo(c, stretchy='false'))
- # use dedicated mathematical operator characters
- elif c in anomalous_chars:
- node = node.append(mo(anomalous_chars[c]))
elif c in "+*=<>,.!?';@":
node = node.append(mo(c))
else:
- raise SyntaxError(u'Illegal character: "%s"' % c)
+ raise SyntaxError(u'Unsupported character: "%s"' % c)
return node
# Test:
@@ -673,6 +700,8 @@
# math(msqrt(mn('2')), mo('≠'), mn('3'))
# >>> parse_latex_math(math(), '\\sqrt{2 + 3} < 3')
# math(msqrt(mn('2'), mo('+'), mn('3')), mo('<'), mn('3'))
+# >>> parse_latex_math(math(), '\\sqrt[3]{2 + 3}')
+# math(mroot(mrow(mn('2'), mo('+'), mn('3')), mn('3')))
# >>> parse_latex_math(math(), '\max_x') # function takes limits
# math(munder(mi('max', movablelimits='true'), mi('x')))
# >>> parse_latex_math(math(), 'x^j_i') # ensure correct order: base, sub, sup
@@ -701,10 +730,10 @@
if name in letters:
if name in greek_capitals:
- node = node.append(mi(greek_capitals[name], CLASS='capital-greek'))
# upright in "TeX style" but MathML sets them italic ("ISO style").
# CSS styling does not change the font style in Firefox 78.
# Use 'mathvariant="normal"'?
+ node = node.append(mi(greek_capitals[name], CLASS='capital-greek'))
else:
node = node.append(mi(letters[name]))
return node, string
@@ -718,7 +747,7 @@
new_node = mi(arg, mathvariant='normal')
else:
new_node = mi(functions[name])
- # compound function symbols:
+ # embellished function names:
if name == 'varliminf': # \underline\lim
new_node = munder(new_node, mo(u'_'))
elif name == 'varlimsup': # \overline\lim
@@ -738,36 +767,27 @@
if name in math_alphabets:
arg, remainder = tex_token(string)
if arg[0] == '\\':
- if name == 'mathbb':
- # mathvariant="double-struck" is ignored for Greek letters
- # (tested in Firefox 78). Use literal Unicode characters.
- arg = mathbb.get(arg, arg)
- # convert single letters (so they can be set with <mi>)
+ # convert single letters (so the isalpha() test below works).
arg = letters.get(arg[1:], arg)
-
+ if name == 'mathbb':
+ # mathvariant="double-struck" is ignored for Greek letters
+ # (tested in Firefox 78). Use literal Unicode characters.
+ arg = mathbb.get(arg, arg)
if name == 'boldsymbol':
attributes = {'style': 'font-weight: bold'}
else:
attributes = {'mathvariant': math_alphabets[name]}
if name == 'mathscr':
- # alternative script letter shapes
- attributes['style'] = 'font-family: STIX'
+ attributes['class'] = 'mathscr'
- # one symbol (single letter, name, or number)
- if arg.isalpha():
+ # one symbol (single letter, name, or ⅀)
+ if arg.isalpha() or arg == u'\u2140':
node = node.append(mi(arg, **attributes))
return node, remainder
- if arg.replace('.', '').replace(',', '').isdigit():
- node = node.append(mn(arg, **attributes))
- return node, remainder
- if len(arg) == 1 and arg != '{':
- node = node.append(mo(arg, **attributes))
- return node, remainder
-
# Wrap in <style>
style = mstyle(**attributes)
node.append(style)
- return style, string[1:] # take of the opening '{', <mrow> is inferred
+ return style, string
# operator, fence, or separator -> <mo>
@@ -798,7 +818,7 @@
row = mrow()
node.append(row)
node = row
- if delimiter: # may be empty (source '.')
+ if delimiter: # may be empty
node.append(mo(delimiter))
if name == 'right':
node = node.close()
@@ -813,7 +833,6 @@
return node, string
# arbitrary text (usually comments) -> <mtext>
-
if name in ('text', 'mbox', 'textrm'):
arg, string = tex_token(string)
text = re.sub('(^ | $)', u'\u00a0', arg)
@@ -821,7 +840,6 @@
return node, string
# horizontal space -> <mspace>
-
if name in spaces:
node = node.append(mspace(width='%s'%spaces[name]))
return node, string
@@ -835,18 +853,14 @@
# ==================================
if name == 'sqrt':
- # TODO: optional arg -> <mroot> <mn>2</mn> <mn>3</mn> </mroot>
- degree, string = tex_optarg(string)
- if degree:
+ radix, string = tex_optarg(string)
+ if radix:
indexnode = mrow()
- parse_latex_math(indexnode, degree)
new_node = mroot(indexnode, switch=True)
+ parse_latex_math(indexnode, radix)
+ indexnode.close()
else:
new_node = msqrt()
- if string.startswith('{'): # argument is a group
- string = string[1:] # mrow implied, skip opening bracket
- else: # no group, enclose only one element
- new_node.nchildren = 1
node.append(new_node)
return new_node, string
@@ -977,8 +991,7 @@
new_node = msubsup(*child.children, switch=True)
elif isinstance(child, mover):
new_node = munderover(*child.children, switch=True)
- # elif isinstance(child, MathToken) and child.data in sumintprod:
- elif getattr(child, 'data', '') in sumintprod:
+ elif getattr(child, 'data', '') in with_limits:
child.attributes['movablelimits'] = 'true'
new_node = munder(child)
else:
@@ -988,7 +1001,7 @@
new_node = msubsup(*child.children)
elif isinstance(child, munder):
new_node = munderover(*child.children)
- elif isinstance(child, MathToken) and child.data in sumintprod:
+ elif getattr(child, 'data', '') in with_limits:
child.attributes['movablelimits'] = 'true'
new_node = mover(child)
else:
Modified: trunk/docutils/docutils/utils/math/tex2unichar.py
===================================================================
--- trunk/docutils/docutils/utils/math/tex2unichar.py 2021-05-20 12:24:40 UTC (rev 8755)
+++ trunk/docutils/docutils/utils/math/tex2unichar.py 2021-05-20 12:24:59 UTC (rev 8756)
@@ -295,6 +295,7 @@
'angle': u'\u2220', # ∠ ANGLE
'aquarius': u'\u2652', # ♒ AQUARIUS
'aries': u'\u2648', # ♈ ARIES
+ 'arrowvert': u'\u23d0', # ⏐ VERTICAL LINE EXTENSION
'ast': u'*', # * ASTERISK
'backepsilon': u'\u03f6', # ϶ GREEK REVERSED LUNATE EPSILON SYMBOL
'backprime': u'\u2035', # ‵ REVERSED PRIME
@@ -307,6 +308,7 @@
'blacksquare': u'\u25fc', # ◼ BLACK MEDIUM SQUARE
'bot': u'\u22a5', # ⊥ UP TACK
'boy': u'\u2642', # ♂ MALE SIGN
+ 'bracevert': u'\u23aa', # ⎪ CURLY BRACKET EXTENSION
'cancer': u'\u264b', # ♋ CANCER
'capricornus': u'\u2651', # ♑ CAPRICORN
'cdots': u'\u22ef', # ⋯ MIDLINE HORIZONTAL ELLIPSIS
@@ -347,6 +349,7 @@
'leftturn': u'\u21ba', # ↺ ANTICLOCKWISE OPEN CIRCLE ARROW
'leo': u'\u264c', # ♌ LEO
'libra': u'\u264e', # ♎ LIBRA
+ 'lmoustache': u'\u23b0', # ⎰ UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION
'lnot': u'\xac', # ¬ NOT SIGN
'lozenge': u'\u25ca', # ◊ LOZENGE
'male': u'\u2642', # ♂ MALE SIGN
@@ -369,6 +372,7 @@
'quarternote': u'\u2669', # ♩ QUARTER NOTE
'rightmoon': u'\u263d', # ☽ FIRST QUARTER MOON
'rightturn': u'\u21bb', # ↻ CLOCKWISE OPEN CIRCLE ARROW
+ 'rmoustache': u'\u23b1', # ⎱ UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION
'sagittarius': u'\u2650', # ♐ SAGITTARIUS
'saturn': u'\u2644', # ♄ SATURN
'scorpio': u'\u264f', # ♏ SCORPIUS
Modified: trunk/docutils/docutils/writers/html5_polyglot/plain.css
==================================...
[truncated message content] |
|
From: <mi...@us...> - 2021-05-20 12:25:42
|
Revision: 8757
http://sourceforge.net/p/docutils/code/8757
Author: milde
Date: 2021-05-20 12:25:30 +0000 (Thu, 20 May 2021)
Log Message:
-----------
Document recent changes to MathML support.
Modified Paths:
--------------
trunk/docutils/HISTORY.txt
trunk/docutils/docs/index.txt
trunk/docutils/docs/ref/rst/directives.txt
trunk/docutils/docs/user/config.txt
trunk/docutils/docs/user/html.txt
Added Paths:
-----------
trunk/docutils/docs/ref/rst/mathematics.txt
Removed Paths:
-------------
trunk/docutils/docs/user/mathematics.txt
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2021-05-20 12:24:59 UTC (rev 8756)
+++ trunk/docutils/HISTORY.txt 2021-05-20 12:25:30 UTC (rev 8757)
@@ -29,6 +29,11 @@
- Removed ``unique_combinations`` (obsoleted by ``itertools.combinations``).
+* docutils/utils/latex2mathml.py
+
+ - Major update (fixes and support for additional commands and symbols).
+ Fixes bug #407.
+
* docutils/writers/_html_base.py
- Write footnote brackets and field term colons to HTML, so that
Modified: trunk/docutils/docs/index.txt
===================================================================
--- trunk/docutils/docs/index.txt 2021-05-20 12:24:59 UTC (rev 8756)
+++ trunk/docutils/docs/index.txt 2021-05-20 12:25:30 UTC (rev 8757)
@@ -138,6 +138,8 @@
* `reStructuredText Interpreted Text Roles <ref/rst/roles.html>`__
* `reStructuredText Standard Definition Files
<ref/rst/definitions.html>`_
+* `LaTeX syntax for mathematics <ref/rst/mathematics.html>`__
+ (syntax used in "math" directive and role)
Prehistoric:
Modified: trunk/docutils/docs/ref/rst/directives.txt
===================================================================
--- trunk/docutils/docs/ref/rst/directives.txt 2021-05-20 12:24:59 UTC (rev 8756)
+++ trunk/docutils/docs/ref/rst/directives.txt 2021-05-20 12:25:30 UTC (rev 8757)
@@ -546,8 +546,7 @@
The "math" directive inserts blocks with mathematical content
(display formulas, equations) into the document. The input format is
-*LaTeX math syntax*\ [#math-syntax]_ with support for Unicode
-symbols, for example::
+`LaTeX math syntax`_ with support for Unicode symbols, for example::
.. math::
@@ -558,19 +557,15 @@
configuration setting (or the corresponding ``--math-output``
command line option) select between alternative output formats with
different subsets of supported elements. If a writer does not
-support math typesetting at all, the content is inserted verbatim.
+support math typesetting, the content is inserted verbatim.
-.. [#math-syntax] The supported LaTeX commands include AMS extensions
- (see, e.g., the `Short Math Guide`_).
-
-
For inline formulas, use the `"math" role`_.
-.. _Short Math Guide:
- http://mirrors.ctan.org/info/short-math-guide/short-math-guide.pdf
+.. _LaTeX math syntax: ../../ref/rst/mathematics.html
.. _"math" role: roles.html#math
.. _math_output: ../../user/config.html#math-output
+
Rubric
======
Copied: trunk/docutils/docs/ref/rst/mathematics.txt (from rev 8756, trunk/docutils/docs/user/mathematics.txt)
===================================================================
--- trunk/docutils/docs/ref/rst/mathematics.txt (rev 0)
+++ trunk/docutils/docs/ref/rst/mathematics.txt 2021-05-20 12:25:30 UTC (rev 8757)
@@ -0,0 +1,704 @@
+============================
+LaTeX syntax for mathematics
+============================
+
+.. role:: m(math)
+.. default-role:: math
+.. |latex| replace:: L\ :sup:`A`\ T\ :sub:`E`\ X
+
+.. contents::
+
+Introduction
+============
+
+Since version 0.8, Docutils supports mathematical content with a `"math"
+directive`__ and `role`__.
+The input format is *LaTeX math syntax*\ [#math-syntax]_ with support for
+Unicode symbols.
+
+
+.. [#math-syntax] The supported LaTeX commands include AMS extensions
+ (see, e.g., the `Short Math Guide`_).
+
+ The support is limited to a subset of *LaTeX math* by the conversion
+ required for many output formats. For HTML, the `math_output`_
+ configuration setting (or the corresponding ``--math-output`` command
+ line option) selects between alternative output formats with different
+ subsets of supported elements. If a writer does not support math
+ typesetting, the content is inserted verbatim.
+
+__ https://docutils.sourceforge.io/docs/ref/rst/directives.html#math
+__ https://docutils.sourceforge.io/docs/ref/rst/roles.html#math
+.. _Short Math Guide:
+ http://mirrors.ctan.org/info/short-math-guide/short-math-guide.pdf
+.. _math_output:
+ https://docutils.sourceforge.io/docs/user/config.html#math-output
+
+Inline formulas and displayed equations
+=======================================
+
+The **math role** can be used for inline mathematical expressions:
+``:math:`\psi(r) = \exp(-2r)``` will produce :m:`\psi(r)=\exp(-2r)`.
+Inside the backtics you can write anything you would write between dollar
+signs in a LaTeX document. [#math-syntax]_
+
+.. tip::
+
+ If you put ``.. default-role:: math`` at the top of your
+ document, you can write ```x^2``` instead of the longer
+ version: ``:math:`x^2```. You can also introduce an
+ abreviation like this ``.. role:: m(math)``. That will allow
+ you to write ``:m:`x^2``` or ```x^2`:m:``.
+
+
+The **math directive** is used for displayed equations. It corresponds to
+an ``equation*`` or ``align*`` environment in a LaTeX document. If you
+write::
+
+ .. math:: \psi(r) = e^{-2r}
+
+you will get:
+
+.. math:: \psi(r) = e^{-2r}
+
+A more complex example is the definition of the `Fourier transform`_::
+
+ .. math::
+ :name: Fourier transform
+
+ (\mathcal{F}f)(y)
+ = \frac{1}{\sqrt{2\pi}^{\ n}}
+ \int_{\mathbb{R}^n} f(x)\,
+ e^{-\mathrm{i} y \cdot x} \,\mathrm{d} x.
+
+which is rendered as:
+
+.. math::
+ :name: Fourier transform
+
+ (\mathcal{F}f)(y)
+ = \frac{1}{\sqrt{2\pi}^{\ n}}
+ \int_{\mathbb{R}^n} f(x)\,
+ e^{-\mathrm{i} y \cdot x} \,\mathrm{d} x.
+
+The ``:name:`` option puts a label on the equation that can be
+linked to by `hyperlink references`_.
+
+Displayed equations can use ``\\`` and ``&`` for line shifts and alignments::
+
+ .. math::
+
+ a & = (x + y)^2 \\
+ & = x^2 + 2xy + y^2
+
+LaTeX output will wrap it in an ``align*`` environment.
+The result is:
+
+.. math::
+
+ a & = (x + y)^2 \\
+ & = x^2 + 2xy + y^2
+
+.. _hyperlink references: ../ref/rst/restructuredtext.html#hyperlink-references
+
+
+Mathematical symbols
+====================
+
+The following tables are adapted from the first edition of
+"The LaTeX Companion" (Goossens, Mittelbach, Samarin) and the
+AMS `Short Math Guide`_.
+
+
+Accents and embellishments
+--------------------------
+
+The "narrow" accents are intended for a single-letter base.
+
+.. class:: colwidths-auto
+
+ =========== ============= =========== ============= ============== ================
+ `\acute{x}` ``\acute{x}`` `\dot{t}` ``\dot{t}`` `\hat{x}` ``\hat{x}``
+ `\bar{v}` ``\bar{v}`` `\ddot{t}` ``\ddot{t}`` `\mathring{x}` ``\mathring{x}``
+ `\breve{x}` ``\breve{x}`` `\dddot{t}` ``\dddot{t}`` `\tilde{n}` ``\tilde{n}``
+ `\check{x}` ``\check{x}`` `\grave{x}` ``\grave{x}`` `\vec{x}` ``\vec{x}``
+ =========== ============= =========== ============= ============== ================
+
+When adding an accent to an i or j in math, dotless variants can be
+obtained with ``\imath`` and ``\jmath``: `\hat \imath`, `\vec{\jmath}`.
+
+For embellishments that span multiple symbols, use:
+
+.. class:: colwidths-auto
+
+ ========================== ============================ =========================== =============================
+ `\widetilde{abi}` ``\widetilde{abi}`` `\widehat{abi}` ``\widehat{abi}``
+ `\overline{abi}` ``\overline{abi}`` `\underline{abi}` ``\underline{abi}``
+ `\overbrace{abi}` ``\overbrace{abi}`` `\underbrace{abi}` ``\underbrace{abi}``
+ `\overleftarrow{abi}` ``\overleftarrow{abi}`` `\underleftarrow{abi}` ``\underleftarrow{abi}``
+ `\overrightarrow{abi}` ``\overrightarrow{abi}`` `\underrightarrow{abi}` ``\underrightarrow{abi}``
+ `\overleftrightarrow{abi}` ``\overleftrightarrow{abi}`` `\underleftrightarrow{abi}` ``\underleftrightarrow{abi}``
+ ========================== ============================ =========================== =============================
+
+
+Binary operators
+----------------
+.. class:: colwidths-auto
+
+ ================== ==================== ================= =================== ================== ====================
+ `*` ``*`` `\circledast` ``\circledast`` `\ominus` ``\ominus``
+ `+` ``+`` `\circledcirc` ``\circledcirc`` `\oplus` ``\oplus``
+ `-` ``-`` `\circleddash` ``\circleddash`` `\oslash` ``\oslash``
+ `:` ``:`` `\cup` ``\cup`` `\otimes` ``\otimes``
+ `\Cap` ``\Cap`` `\curlyvee` ``\curlyvee`` `\pm` ``\pm``
+ `\Cup` ``\Cup`` `\curlywedge` ``\curlywedge`` `\rightthreetimes` ``\rightthreetimes``
+ `\amalg` ``\amalg`` `\dagger` ``\dagger`` `\rtimes` ``\rtimes``
+ `\ast` ``\ast`` `\ddagger` ``\ddagger`` `\setminus` ``\setminus``
+ `\bigcirc` ``\bigcirc`` `\diamond` ``\diamond`` `\smallsetminus` ``\smallsetminus``
+ `\bigtriangledown` ``\bigtriangledown`` `\div` ``\div`` `\sqcap` ``\sqcap``
+ `\bigtriangleup` ``\bigtriangleup`` `\divideontimes` ``\divideontimes`` `\sqcup` ``\sqcup``
+ `\boxdot` ``\boxdot`` `\dotplus` ``\dotplus`` `\star` ``\star``
+ `\boxminus` ``\boxminus`` `\doublebarwedge` ``\doublebarwedge`` `\times` ``\times``
+ `\boxplus` ``\boxplus`` `\gtrdot` ``\gtrdot`` `\triangleleft` ``\triangleleft``
+ `\boxtimes` ``\boxtimes`` `\intercal` ``\intercal`` `\triangleright` ``\triangleright``
+ `\bullet` ``\bullet`` `\leftthreetimes` ``\leftthreetimes`` `\uplus` ``\uplus``
+ `\cap` ``\cap`` `\lessdot` ``\lessdot`` `\vee` ``\vee``
+ `\cdot` ``\cdot`` `\ltimes` ``\ltimes`` `\veebar` ``\veebar``
+ `\centerdot` ``\centerdot`` `\mp` ``\mp`` `\wedge` ``\wedge``
+ `\circ` ``\circ`` `\odot` ``\odot`` `\wr` ``\wr``
+ ================== ==================== ================= =================== ================== ====================
+
+
+Extensible delimiters
+---------------------
+Unless you indicate otherwise, delimiters in math formulas remain at the
+standard size regardless of the height of the enclosed material. To get
+adaptable sizes, use ``\left`` and ``\right`` prefixes, for example
+`g(A,B,Y) = f \left(A,B,X=h^{[X]}(Y)\right)` or
+
+.. math:: a_n = \left(\frac{1}{2}\right)^n
+
+Use ``.`` for "empty" delimiters:
+
+.. math:: A = \left . \frac{1}{1-n}\, \right |_{n=0}^\infty
+
+The following symbols extend when used with ``\left`` and ``\right``:
+
+Pairing delimiters
+~~~~~~~~~~~~~~~~~~
+.. class:: colwidths-auto
+
+ =============== ================= ========================= ===========================
+ `( )` ``( )`` `\langle \rangle` ``\langle \rangle``
+ `[ ]` ``[ ]`` `\lceil \rceil` ``\lceil \rceil``
+ `\{ \}` ``\{ \}`` `\lfloor \rfloor` ``\lfloor \rfloor``
+ `\lvert \rvert` ``\lvert \rvert`` `\lgroup \rgroup` ``\lgroup \rgroup``
+ `\lVert \rVert` ``\lVert \rVert`` `\lmoustache \rmoustache` ``\lmoustache \rmoustache``
+ =============== ================= ========================= ===========================
+
+
+Nonpairing delimiters
+~~~~~~~~~~~~~~~~~~~~~
+.. class:: colwidths-auto
+
+ ==== ====== ============ ============== ============ ==============
+ `|` ``|`` `\vert` ``\vert`` `\arrowvert` ``\arrowvert``
+ `\|` ``\|`` `\Vert` ``\Vert`` `\Arrowvert` ``\Arrowvert``
+ `/` ``/`` `\backslash` ``\backslash`` `\bracevert` ``\bracevert``
+ ==== ====== ============ ============== ============ ==============
+
+The use of ``|`` and ``\|`` for pairs of vertical bars may produce
+incorrect spacing, e.g., ``|k|=|-k|`` produces `|k| = |−k|` and
+``|\sin(x)|`` produces `|\sin(x)|`. The pairing delimiters, e.g.
+`\lvert -k\rvert` and `\lvert\sin(x)\rvert`, prevent this problem
+(in LaTeX and MathJax).
+
+Vertical Arrows
+~~~~~~~~~~~~~~~
+.. class:: colwidths-auto
+
+ =============================== ======================================
+ `\uparrow` ``\uparrow`` `\Uparrow` ``\Uparrow``
+ `\downarrow` ``\downarrow`` `\Downarrow` ``\Downarrow``
+ `\updownarrow` ``\updownarrow`` `\Updownarrow` ``\Updownarrow``
+ =============================== ======================================
+
+Functions (named operators)
+---------------------------
+.. class:: colwidths-auto
+
+ ========= =========== ========= =========== ============= ================
+ `\arccos` ``\arccos`` `\gcd` ``\gcd`` `\Pr` ``\Pr``
+ `\arcsin` ``\arcsin`` `\hom` ``\hom`` `\projlim` ``\projlim``
+ `\arctan` ``\arctan`` `\inf` ``\inf`` `\sec` ``\sec``
+ `\arg` ``\arg`` `\injlim` ``\injlim`` `\sin` ``\sin``
+ `\cos` ``\cos`` `\ker` ``\ker`` `\sinh` ``\sinh``
+ `\cosh` ``\cosh`` `\lg` ``\lg`` `\sup` ``\sup``
+ `\cot` ``\cot`` `\lim` ``\lim`` `\tan` ``\tan``
+ `\coth` ``\coth`` `\liminf` ``\liminf`` `\tanh` ``\tanh``
+ `\csc` ``\csc`` `\limsup` ``\limsup`` `\varlimsup` ``\varlimsup``
+ `\deg` ``\deg`` `\ln` ``\ln`` `\varliminf` ``\varliminf``
+ `\det` ``\det`` `\log` ``\log`` `\varprojlim` ``\varprojlim``
+ `\dim` ``\dim`` `\max` ``\max`` `\varinjlim` ``\varinjlim``
+ `\exp` ``\exp`` `\min` ``\min``
+ ========= =========== ========= =========== ============= ================
+
+Named operators outside the above list can be typeset with
+``\operatorname{name}``, e.g.
+
+.. math:: \operatorname{sgn}(-3) = -1.
+
+The ``\DeclareMathOperator`` command can only be used in the
+`LaTeX preamble`_.
+
+.. _LaTeX preamble: latex.html#latex-preamble
+
+
+Greek letters
+-------------
+
+In LaTeX, the default font for capital Greek letters is upright/roman.
+Italic capital Greek letters can be obtained by loading a `package
+providing the "ISO" math style`__. They are used by default in MathML.
+
+Greek letters that have Latin look-alikes are rarely used in math
+formulas and not supported by LaTeX.
+
+.. class:: colwidths-auto
+
+ ========== ============ ========== ============ ========== ============ ============== ===============
+ `\Gamma` ``\Gamma`` `\alpha` ``\alpha`` `\mu` ``\mu`` `\omega` ``\omega``
+ `\Delta` ``\Delta`` `\beta` ``\beta`` `\nu` ``\nu`` `\digamma` ``\digamma``
+ `\Lambda` ``\Lambda`` `\gamma` ``\gamma`` `\xi` ``\xi`` `\backepsilon` ``\backepsilon``
+ `\Phi` ``\Phi`` `\delta` ``\delta`` `\pi` ``\pi`` `\varepsilon` ``\varepsilon``
+ `\Pi` ``\Pi`` `\epsilon` ``\epsilon`` `\rho` ``\rho`` `\varkappa` ``\varkappa``
+ `\Psi` ``\Psi`` `\zeta` ``\zeta`` `\sigma` ``\sigma`` `\varphi` ``\varphi``
+ `\Sigma` ``\Sigma`` `\eta` ``\eta`` `\tau` ``\tau`` `\varpi` ``\varpi``
+ `\Theta` ``\Theta`` `\theta` ``\theta`` `\upsilon` ``\upsilon`` `\varrho` ``\varrho``
+ `\Upsilon` ``\Upsilon`` `\iota` ``\iota`` `\phi` ``\phi`` `\varsigma` ``\varsigma``
+ `\Xi` ``\Xi`` `\kappa` ``\kappa`` `\chi` ``\chi`` `\vartheta` ``\vartheta``
+ `\Omega` ``\Omega`` `\lambda` ``\lambda`` `\psi` ``\psi``
+ ========== ============ ========== ============ ========== ============ ============== ===============
+
+__ http://mirrors.ctan.org/macros/latex/contrib/isomath/isomath.html#table-2
+
+Letterlike symbols
+------------------
+.. class:: colwidths-auto
+
+========== ============ ============= =============== ========= =========== =========== =============
+`\aleph` ``\aleph`` `\forall` ``\forall`` `\hbar` ``\hbar`` `\ell` ``\ell``
+`\beth` ``\beth`` `\complement` ``\complement`` `\hslash` ``\hslash`` `\wp` ``\wp``
+`\gimel` ``\gimel`` `\exists` ``\exists`` `\Im` ``\Im`` `\Re` ``\Re``
+`\daleth` ``\daleth`` `\Finv` ``\Finv`` `\imath` ``\imath`` `\circledR` ``\circledR``
+`\partial` ``\partial`` `\Game` ``\Game`` `\Bbbk` ``\Bbbk`` `\circledS` ``\circledS``
+`\eth` ``\eth`` `\mho` ``\mho``
+========== ============ ============= =============== ========= =========== =========== =============
+
+
+Mathematical Alphabets
+----------------------
+
+Mathematical alphabets select a combination of font attributes (shape,
+weight, family) [#]_. They are intended for mathematical variables where
+style variations are important semantically.
+
+.. class:: colwidths-auto
+
+ =============== ============================ ==========================
+ command example result
+ =============== ============================ ==========================
+ ``\mathbf`` ``\mathbf{r}^2=x^2+y^2+z^2`` `\mathbf{r}^2=x^2+y^2+z^2`
+ ``\mathbb`` ``\mathbb{R \subset C}`` `\mathbb{R \subset C}`
+ ``\mathcal`` ``\mathcal{F}f(x)`` `\mathcal{F}f(x)`
+ ``\mathfrak`` ``\mathfrak{a}`` `\mathfrak{a}`
+ ``\mathit`` ``\mathit{\Gamma}`` `\mathit{\Gamma}`
+ ``\mathrm`` ``s_\mathrm{out}`` `s_\mathrm{out}`
+ ``\mathsf`` ``\mathsf x`` `\mathsf x`
+ ``\mathtt`` ``\mathtt{0.12}`` `\mathtt{0.12}`
+ =============== ============================ ==========================
+
+.. [#] TeX’s *math alphabets* correspond to the `mathematical
+ alphanumeric symbols`__ block in Unicode and the "mathvariant" `style
+ attribute`__ in MathML.
+
+ __ https://en.wikipedia.org/wiki/Mathematical_Alphanumeric_Symbols
+ __ https://developer.mozilla.org/en-US/docs/Web/MathML/Attribute
+
+Additional alphabets are defined in LaTeX packages, e.g.
+
+.. class:: colwidths-auto
+
+ =========== ============= ======================
+ TeX command LaTeX package MathML "mathvariant"
+ =========== ============= ======================
+ mathbfit isomath_ bold-italic
+ mathsfit isomath_ sans-serif-italic
+ mathsfbfit isomath_ sans-serif-bold-italic
+ mathscr mathrsfs_ script
+ =========== ============= ======================
+.. _isomath: https://www.ctan.org/pkg/isomath
+.. _mathrsfs: https://www.ctan.org/pkg/mathrsfs
+
+This can be used to typeset vector symbols in bold italic
+in line with the International Standard [ISO-80000-2].
+
+.. ``\mathbfit{r}^2=x^2+y^2+z^2`` becomes
+
+ .. math:: \mathbfit{r}^2=x^2+y^2+z^2.
+
+The package mathrsfs_ (and some drop-in replacements) define the ``\mathscr``
+macro that selects a differently shaped "script" alphabet.
+Compare `\mathscr{A, B, …, Z, a, b, …, z}`
+with `\mathcal{A, B, …, Z, a, b, …, z}`.
+
+
+In contrast to the math alphabet selectors, ``\boldsymbol`` only changes
+the *font weight*. In LaTeX, it can be used to get a bold version of any
+mathematical symbol (for other output formats, results are mixed):
+
+.. math::
+ \boldsymbol{abs(x) \pm \alpha \approx 3 \Gamma \quad \forall x \in R}
+
+
+Miscellaneous symbols
+---------------------
+.. class:: colwidths-auto
+
+==================== ====================== ================ ================== ================= ===================
+`\#` ``\#`` `\clubsuit` ``\clubsuit`` `\neg` ``\neg``
+`\&` ``\&`` `\diamondsuit` ``\diamondsuit`` `\nexists` ``\nexists``
+`\angle` ``\angle`` `\emptyset` ``\emptyset`` `\prime` ``\prime``
+`\backprime` ``\backprime`` `\exists` ``\exists`` `\sharp` ``\sharp``
+`\bigstar` ``\bigstar`` `\flat` ``\flat`` `\spadesuit` ``\spadesuit``
+`\blacklozenge` ``\blacklozenge`` `\forall` ``\forall`` `\sphericalangle` ``\sphericalangle``
+`\blacksquare` ``\blacksquare`` `\heartsuit` ``\heartsuit`` `\square` ``\square``
+`\blacktriangle` ``\blacktriangle`` `\infty` ``\infty`` `\surd` ``\surd``
+`\blacktriangledown` ``\blacktriangledown`` `\lozenge` ``\lozenge`` `\top` ``\top``
+`\bot` ``\bot`` `\measuredangle` ``\measuredangle`` `\triangle` ``\triangle``
+`\diagdown` ``\diagdown`` `\nabla` ``\nabla`` `\triangledown` ``\triangledown``
+`\diagup` ``\diagup`` `\natural` ``\natural`` `\varnothing` ``\varnothing``
+==================== ====================== ================ ================== ================= ===================
+
+
+Punctuation
+-----------
+.. class:: colwidths-auto
+
+=== ===== ======== =============== ======== ==========
+`.` ``.`` `!` ``!`` `?` ``?``
+`/` ``/`` `\colon` ``\colon`` [#]_ `\dotsb` ``\dotsb``
+`|` ``|`` `\cdots` ``\cdots`` `\dotsc` ``\dotsc``
+`'` ``'`` `\ddots` ``\ddots`` `\dotsi` ``\dotsi``
+`;` ``;`` `\ldots` ``\ldots`` `\dotsm` ``\dotsm``
+`:` ``:`` `\vdots` ``\vdots`` `\dotso` ``\dotso``
+=== ===== ======== =============== ======== ==========
+
+.. [#] Punctuation (not ratio):
+ Compare spacing in `a\colon b\to c` to `a:b = c`.
+
+
+Relation symbols
+----------------
+
+Arrows
+~~~~~~
+.. class:: colwidths-auto
+
+ ====================== ======================== ===================== =======================
+ `\circlearrowleft` ``\circlearrowleft`` `\circlearrowright` ``\circlearrowright``
+ `\curvearrowleft` ``\curvearrowleft`` `\curvearrowright` ``\curvearrowright``
+ `\hookleftarrow` ``\hookleftarrow`` `\hookrightarrow` ``\hookrightarrow``
+ `\leftarrow` ``\leftarrow`` `\rightarrow` ``\rightarrow``
+ `\Leftarrow` ``\Leftarrow`` `\Rightarrow` ``\Rightarrow``
+ `\leftarrowtail` ``\leftarrowtail`` `\rightarrowtail` ``\rightarrowtail``
+ `\leftharpoondown` ``\leftharpoondown`` `\rightharpoondown` ``\rightharpoondown``
+ `\leftharpoonup` ``\leftharpoonup`` `\rightharpoonup` ``\rightharpoonup``
+ `\leftleftarrows` ``\leftleftarrows`` `\rightrightarrows` ``\rightrightarrows``
+ `\leftrightarrow` ``\leftrightarrow`` `\Leftrightarrow` ``\Leftrightarrow``
+ `\leftrightarrows` ``\leftrightarrows`` `\rightleftarrows` ``\rightleftarrows``
+ `\leftrightharpoons` ``\leftrightharpoons`` `\rightleftharpoons` ``\rightleftharpoons``
+ `\leftrightsquigarrow` ``\leftrightsquigarrow`` `\rightsquigarrow` ``\rightsquigarrow``
+ `\Lleftarrow` ``\Lleftarrow`` `\Rrightarrow` ``\Rrightarrow``
+ `\longleftarrow` ``\longleftarrow`` `\longrightarrow` ``\longrightarrow``
+ `\Longleftarrow` ``\Longleftarrow`` `\Longrightarrow` ``\Longrightarrow``
+ `\longleftrightarrow` ``\longleftrightarrow`` `\Longleftrightarrow` ``\Longleftrightarrow``
+ `\looparrowleft` ``\looparrowleft`` `\looparrowright` ``\looparrowright``
+ `\Lsh` ``\Lsh`` `\Rsh` ``\Rsh``
+ `\mapsto` ``\mapsto`` `\longmapsto` ``\longmapsto``
+ `\multimap` ``\multimap``
+ `\nleftarrow` ``\nleftarrow`` `\nrightarrow` ``\nrightarrow``
+ `\nLeftarrow` ``\nLeftarrow`` `\nRightarrow` ``\nRightarrow``
+ `\nleftrightarrow` ``\nleftrightarrow`` `\nLeftrightarrow` ``\nLeftrightarrow``
+ `\nwarrow` ``\nwarrow`` `\nearrow` ``\nearrow``
+ `\swarrow` ``\swarrow`` `\searrow` ``\searrow``
+ `\twoheadleftarrow` ``\twoheadleftarrow`` `\twoheadrightarrow` ``\twoheadrightarrow``
+ `\upharpoonleft` ``\upharpoonleft`` `\upharpoonright` ``\upharpoonright``
+ `\downharpoonleft` ``\downharpoonleft`` `\downharpoonright` ``\downharpoonright``
+ `\upuparrows` ``\upuparrows`` `\downdownarrows` ``\downdownarrows``
+ ====================== ======================== ===================== =======================
+
+
+
+
+
+Synonyms: `\gets` ``\gets``, `\to` ``\to``, `\restriction` ``\restriction``.
+
+
+Comparison
+~~~~~~~~~~
+
+.. class:: colwidths-auto
+
+================ ================== ============= =============== ============= =============== =============== =================
+`<` ``<`` `\geq` ``\geq`` `\ll` ``\ll`` `\prec` ``\prec``
+`=` ``=`` `\geqq` ``\geqq`` `\lll` ``\lll`` `\precapprox` ``\precapprox``
+`>` ``>`` `\geqslant` ``\geqslant`` `\lnapprox` ``\lnapprox`` `\preccurlyeq` ``\preccurlyeq``
+`\approx` ``\approx`` `\gg` ``\gg`` `\lneq` ``\lneq`` `\preceq` ``\preceq``
+`\approxeq` ``\approxeq`` `\ggg` ``\ggg`` `\lneqq` ``\lneqq`` `\precnapprox` ``\precnapprox``
+`\asymp` ``\asymp`` `\gnapprox` ``\gnapprox`` `\lnsim` ``\lnsim`` `\precneqq` ``\precneqq``
+`\backsim` ``\backsim`` `\gneq` ``\gneq`` `\ncong` ``\ncong`` `\precnsim` ``\precnsim``
+`\backsimeq` ``\backsimeq`` `\gneqq` ``\gneqq`` `\neq` ``\neq`` `\precsim` ``\precsim``
+`\bumpeq` ``\bumpeq`` `\gnsim` ``\gnsim`` `\ngeq` ``\ngeq`` `\risingdotseq` ``\risingdotseq``
+`\Bumpeq` ``\Bumpeq`` `\gtrapprox` ``\gtrapprox`` `\ngeqq` ``\ngeqq`` `\sim` ``\sim``
+`\circeq` ``\circeq`` `\gtreqless` ``\gtreqless`` `\ngeqslant` ``\ngeqslant`` `\simeq` ``\simeq``
+`\cong` ``\cong`` `\gtreqqless` ``\gtreqqless`` `\ngtr` ``\ngtr`` `\succ` ``\succ``
+`\curlyeqprec` ``\curlyeqprec`` `\gtrless` ``\gtrless`` `\nleq` ``\nleq`` `\succapprox` ``\succapprox``
+`\curlyeqsucc` ``\curlyeqsucc`` `\gtrsim` ``\gtrsim`` `\nleqq` ``\nleqq`` `\succcurlyeq` ``\succcurlyeq``
+`\doteq` ``\doteq`` `\leq` ``\leq`` `\nleqslant` ``\nleqslant`` `\succeq` ``\succeq``
+`\doteqdot` ``\doteqdot`` `\leqq` ``\leqq`` `\nless` ``\nless`` `\succnapprox` ``\succnapprox``
+`\eqcirc` ``\eqcirc`` `\leqslant` ``\leqslant`` `\nprec` ``\nprec`` `\succneqq` ``\succneqq``
+`\eqsim` ``\eqsim`` `\lessapprox` ``\lessapprox`` `\npreceq` ``\npreceq`` `\succnsim` ``\succnsim``
+`\eqslantgtr` ``\eqslantgtr`` `\lesseqgtr` ``\lesseqgtr`` `\nsim` ``\nsim`` `\succsim` ``\succsim``
+`\eqslantless` ``\eqslantless`` `\lesseqqgtr` ``\lesseqqgtr`` `\nsucc` ``\nsucc`` `\thickapprox` ``\thickapprox``
+`\equiv` ``\equiv`` `\lessgtr` ``\lessgtr`` `\nsucceq` ``\nsucceq`` `\thicksim` ``\thicksim``
+`\fallingdotseq` ``\fallingdotseq`` `\lesssim` ``\lesssim`` `\triangleq` ``\triangleq``
+================ ================== ============= =============== ============= =============== =============== =================
+
+The commands ``\lvertneqq`` and ``\gvertneqq`` are not supported by
+LateX2MathML, as there is no corresponding Unicode character.
+
+Synonyms: `\ne` ``\ne``, `\le` ``\le``, `\ge` ``\ge``, `\Doteq`
+``\Doteq``, `\llless` ``\llless``, `\gggtr` ``\gggtr``,
+`\not =` ``\not =``, `\not \equiv` ``\not \equiv``.
+
+
+Miscellaneous relations
+~~~~~~~~~~~~~~~~~~~~~~~
+.. class:: colwidths-auto
+
+ ===================== ======================= =================== ===================== =================== =====================
+ `\backepsilon` ``\backepsilon`` `\ntrianglelefteq` ``\ntrianglelefteq`` `\subseteq` ``\subseteq``
+ `\because` ``\because`` `\ntriangleright` ``\ntriangleright`` `\subseteqq` ``\subseteqq``
+ `\between` ``\between`` `\ntrianglerighteq` ``\ntrianglerighteq`` `\subsetneq` ``\subsetneq``
+ `\blacktriangleleft` ``\blacktriangleleft`` `\nvdash` ``\nvdash`` `\subsetneqq` ``\subsetneqq``
+ `\blacktriangleright` ``\blacktriangleright`` `\nVdash` ``\nVdash`` `\supset` ``\supset``
+ `\bowtie` ``\bowtie`` `\nvDash` ``\nvDash`` `\Supset` ...
[truncated message content] |
|
From: <mi...@us...> - 2021-05-27 15:06:42
|
Revision: 8758
http://sourceforge.net/p/docutils/code/8758
Author: milde
Date: 2021-05-27 15:06:37 +0000 (Thu, 27 May 2021)
Log Message:
-----------
MathML: refactor and extend.
New method math.extend(), dictionary-like access to attributes.
Update/Correct list of operators/functions with limits above/below in display formulas.
Add support for:
- more matrix environments,
- more fraction commands,
- delimiter-size commands,
- limits/nolimits commands,
- phantom and boxed commands,
- layout style commands.
Modified Paths:
--------------
trunk/docutils/docs/ref/rst/mathematics.txt
trunk/docutils/docutils/utils/math/latex2mathml.py
trunk/docutils/test/functional/expected/math_output_mathml.html
Modified: trunk/docutils/docs/ref/rst/mathematics.txt
===================================================================
--- trunk/docutils/docs/ref/rst/mathematics.txt 2021-05-20 12:25:30 UTC (rev 8757)
+++ trunk/docutils/docs/ref/rst/mathematics.txt 2021-05-27 15:06:37 UTC (rev 8758)
@@ -6,6 +6,7 @@
.. default-role:: math
.. |latex| replace:: L\ :sup:`A`\ T\ :sub:`E`\ X
+.. sectnum::
.. contents::
Introduction
@@ -248,6 +249,8 @@
.. math:: \operatorname{sgn}(-3) = -1.
+.. TODO: \operatorname* for function name with limits.
+
The ``\DeclareMathOperator`` command can only be used in the
`LaTeX preamble`_.
@@ -358,7 +361,7 @@
mathematical symbol (for other output formats, results are mixed):
.. math::
- \boldsymbol{abs(x) \pm \alpha \approx 3 \Gamma \quad \forall x \in R}
+ \boldsymbol{abs(x)\pm\alpha \approx 3\Gamma \quad \forall x\in\mathbb{R}}
Miscellaneous symbols
@@ -523,19 +526,19 @@
.. class:: colwidths-auto
========================= ========================= ========================= ===========================
- `\sum` ``\sum`` `\prod` ``\prod`` `\bigcap` ``\bigcap`` `\bigodot` ``\bigodot``
- `\int` ``\int`` `\coprod` ``\coprod`` `\bigcup` ``\bigcup`` `\bigoplus` ``\bigoplus``
+ `\sum` ``\sum`` `\prod` ``\prod`` `\bigcap` ``\bigcap`` `\bigodot` ``\bigodot``
+ `\int` ``\int`` `\coprod` ``\coprod`` `\bigcup` ``\bigcup`` `\bigoplus` ``\bigoplus``
`\oint` ``\oint`` `\bigwedge` ``\bigwedge`` `\biguplus` ``\biguplus`` `\bigotimes` ``\bigotimes``
- `\smallint` ``\smallint`` `\bigvee` ``\bigvee`` `\bigsqcup` ``\bigsqcup``
+ `\smallint` ``\smallint`` `\bigvee` ``\bigvee`` `\bigsqcup` ``\bigsqcup``
========================= ========================= ========================= ===========================
-Larger symbols are used in displayed formulas:
+Larger symbols are used in displayed formulas, sum-like symbols have
+indices above/below the symbol (see also `scripts and limits`_):
-.. math::
+.. math:: \sum_{n=1}^N a_n \qquad
+ \int_0^1f(x)\,dx \qquad
+ \prod_{i=1}^{10} b_i \ldots
- \sum\ \int\ \oint \bigcap \prod \ldots
-
-
Notations
=========
@@ -574,54 +577,74 @@
``&``::
.. math::
+ \left(\begin{matrix} a & b \\ c & d \end{matrix}\right)
- \left(\begin{matrix} a & b \\ c & d \end{matrix}\right)
-
Result:
.. math::
+ \left(\begin{matrix} a & b \\ c & d \end{matrix}\right)
- \left(\begin{matrix} a & b \\ c & d \end{matrix}\right)
+The environments ``pmatrix``, ``bmatrix``, ``Bmatrix``, ``vmatrix``, and
+``Vmatrix`` have (respectively) ( ), [ ], { }, \| \|, and `\Vert\ \Vert`
+delimiters built in, e.g.
-.. TODO: small matrices, matrices with delimiters built in?
+.. math:: \begin{pmatrix} a & b \\ c & d \end{pmatrix} \qquad
+ \begin{bmatrix} a & b \\ c & d \end{bmatrix} \qquad
+ \begin{Vmatrix} a & b \\ c & d \end{Vmatrix}
- The environments pmatrix, bmatrix, Bmatrix, vmatrix, and Vmatrix have
- (respectively) ( ), [ ], { }, | |, and k k delimiters built in.
+To produce a small matrix suitable for use in text, there is a
+``smallmatrix`` environment
+`\bigl(\begin{smallmatrix} a & b \\ c & d \end{smallmatrix}\bigr)`
+that comes closer to fitting within a single text line than a normal
+matrix.
-For piecewise function definitions there is a cases environment:
-.. math::
+For piecewise function definitions there is a ``cases`` environment:
- \mathrm{sgn}(x) = \begin{cases}
- -1 & x<0\\
- 1 & x>0
- \end{cases}
+.. math:: \mathrm{sgn}(x) = \begin{cases}
+ -1 & x<0\\
+ 1 & x>0
+ \end{cases}
-Horizontal space
+Spacing commands
----------------
+Horizontal spacing of elements can be controled with the following
+commands:
+
.. class:: colwidths-auto
===================== ======== =======================
- :m:`|\qquad|` ``|\qquad|`` (2em)
- :m:`|\quad|` ``|\quad|`` (1em)
- :m:`|~|` ``|~|`` ``|\nobreakspace|``
- :m:`|\ |` ``|\ |`` escaped space
- :m:`|\;|` ``|\;|`` ``|\thickspace|``
- :m:`|\:|` ``|\:|`` ``|\medspace|``
- :m:`|\,|` ``|\,|`` ``|\thinspace|``
- :m:`| |` ``| |`` regular space (ignored)
- :m:`|\!|` ``|\!|`` ``|\negthinspace|``
- :m:`|\negmedspace|` ``|\negmedspace|``
- :m:`|\negthickspace|` ``|\negthickspace|``
- `|\hspace{1ex}|` ``|\hspace{1ex}|``
+ :m:`3\qquad8` ``3\qquad8`` (2em)
+ :m:`3\quad8` ``3\quad8`` (1em)
+ :m:`3~8` ``3~8`` ``3\nobreakspace8``
+ :m:`3\ 8` ``3\ 8`` escaped space
+ :m:`3\;8` ``3\;8`` ``3\thickspace8``
+ :m:`3\:8` ``3\:8`` ``3\medspace8``
+ :m:`3\,8` ``3\,8`` ``3\thinspace8``
+ :m:`3 8` ``3 8`` regular space (ignored)
+ :m:`3\!8` ``3\!8`` ``3\negthinspace8``
+ :m:`3\negmedspace8` ``3\negmedspace8``
+ :m:`3\negthickspace8` ``3\negthickspace8``
+ `3\hspace{1ex}8` ``3\hspace{1ex}8``
===================== ======== =======================
-.. TODO: \phantom \hphantom, \vphantom
+Whitespace is ignored in LaTeX math mode.
+Negative spacing does not work with MathML (in Firefox 78).
-Roots and Fractions
--------------------
+There are also three commands that leave a space equal to the height and
+width of its argument. For example ``\phantom{XXX}`` results in space as
+wide and high as three X’s:
+.. math:: \frac{\phantom{XXX}+1}{XXX-1}
+
+The commands ``\hphantom`` and ``\vphantom`` insert space with the heigth
+rsp. width of the argument. They are not supported with `math_output`_
+MathML.
+
+Roots
+-----
+
.. class:: colwidths-auto
========= ==================== ==================
@@ -629,11 +652,116 @@
========= ==================== ==================
``\sqrt`` ``\sqrt{x^2-1}`` `\sqrt{x^2-1}`
.. ``\sqrt[3n]{x^2-1}`` `\sqrt[3n]{x^2-1}`
- ``\frac`` ``\frac{1}{1-x}`` `\frac{1}{1-x}`
+ .. ``\sqrt\frac{1}{2}`` `\sqrt\frac{1}{2}`
========= ==================== ==================
-.. TODO: \dfrac, \tfrac, \binom, \dbinom, \tbinom
+Boxed formulas
+--------------
+The command ``\boxed`` puts a box around its argument:
+
+.. math:: \boxed{\eta \leq C(\delta(\eta) +\Lambda_M(0,\delta))}
+
+
+
+Fractions and related constructions
+===================================
+
+The ``\frac`` command takes two ar guments, numerator and denominator,
+and typesets them in normal fraction form. Use ``\dfrac`` or ``\tfrac`` to
+force text style and display style respectively.
+
+.. math:: \frac{x+1}{x-1} \quad
+ \dfrac{x+1}{x-1} \quad
+ \tfrac{x+1}{x-1}
+
+and in text: `\frac{x+1}{x-1}`, `\dfrac{x+1}{x-1}`, `\tfrac{x+1}{x-1}`.
+
+For binomial expressions such as `\binom{n}{k}`,
+there are ``\binom``, ``\dbinom`` and ``\tbinom`` commands::
+
+ 2^k-\binom{k}{1}2^{k-1}+\binom{k}{2}2^{k-2}
+
+prints
+
+.. math:: 2^k-\binom{k}{1}2^{k-1}+\binom{k}{2}2^{k-2}
+
+The ``\cfrac`` command for continued fractions uses displaystyle and
+padding for sub-fractions:
+
+.. math:: \cfrac{1}{\sqrt{2}+
+ \cfrac{1}{\sqrt{2}+
+ \cfrac{1}{\sqrt{2}+\dotsb
+ }}}
+ \text{ vs. }
+ \frac{1}{\sqrt{2}+
+ \frac{1}{\sqrt{2}+
+ \frac{1}{\sqrt{2}+\dotsb
+ }}}
+
+It supports the optional argument ``[l]`` or ``[r]`` for
+left or right placement of the numerator:
+
+.. math:: \cfrac[l]{x}{x-1} \quad
+ \cfrac{x}{x-1} \quad
+ \cfrac[r]{x}{x-1}
+
+
+Delimiter sizes
+===============
+
+Besides the automatic scaling of `extensible delimiters`_ with ``\left``
+and ``\right``, there are four commands to manually select delimiters of
+fixed size:
+
+.. class:: colwidths-auto
+
+ ========= ============== ============== ============== ============== =============== ===============
+ Sizing no ``\left`` ``\bigl`` ``\Bigl`` ``\biggl`` ``\Biggl``
+ command ``\right`` ``\bigr`` ``\Bigr`` ``\biggr`` ``\Biggr``
+ --------- -------------- -------------- -------------- -------------- --------------- ---------------
+ Result `\displaystyle `\displaystyle `\displaystyle `\displaystyle `\displaystyle `\displaystyle
+ (b) \left(b\right) \bigl(b\bigr) \Bigl(b\Bigr) \biggl(b\biggr) \Biggl(b\Biggr)
+ (\frac{c}{d})` \left(\frac{c} \bigl(\frac{c} \Bigl(\frac{c} \biggl(\frac{c} \Biggl(\frac{c}
+ {d}\right)` {d}\bigr)` {d}\Bigr)` {d}\biggr)` {d}\Biggr)`
+ ========= ============== ============== ============== ============== =============== ===============
+
+There are two or three situations where the delimiter size is commonly
+adjusted using these commands:
+
+The first kind of adjustment is done for cumulative operators with
+limits, such as summation signs. With ``\left`` and ``\right`` the
+delimiters usually turn out larger than necessary, and using the ``Big``
+or ``bigg`` sizes instead gives better results:
+
+.. math::
+ \left[\sum_i a_i\left\lvert\sum_j x_{ij}\right\rvert^p\right]^{1/p}
+ \text{ versus }
+ \biggl[\sum_i a_i\Bigl\lvert\sum_j x_{ij}\Bigr\rvert^p\biggr]^{1/p}
+
+The second kind of situation is clustered pairs of delimiters, where
+\left and \right make them all the same size (because that is adequate to
+cover the encompassed material), but what you really want is to make some
+of the delimiters slightly larger to make the nesting easier to see.
+
+.. math:: \left((a_1 b_1) - (a_2 b_2)\right)
+ \left((a_2 b_1) + (a_1 b_2)\right)
+ \quad\text{versus}\quad
+ \bigl((a_1 b_1) - (a_2 b_2)\bigr)
+ \bigl((a_2 b_1) + (a_1 b_2)\bigr)
+
+The third kind of situation is a slightly oversize object in running
+text, such as `\left|\frac{b'}{d'}\right|` where the delimiters produced
+by ``\left`` and ``\right`` cause too much line spreading. [#]_ In that case
+``\bigl`` and ``\bigr`` can be used to produce delimiters that are larger
+than the base size but still able to fit within the normal line spacing:
+`\bigl|\frac{b'}{d'}\bigr|`.
+
+.. [#] With MathML, an example would be parentheses
+ around a ``smallmatrix`` environment
+ `\left(\begin{smallmatrix} a & b \\ c & d \end{smallmatrix}\right)`
+ vs. `\Bigl(\begin{smallmatrix} a & b \\ c & d \end{smallmatrix}\Bigr)`.
+
Text
====
@@ -647,14 +775,93 @@
.. Math:: f_{[x_{i-1},x_i]} \text{ is monotonic for } i = 1,\,…,\,c+1
-Currently, math in text is not supported by LaTeX2MathML.
+``$`` signs can be used for math commands inside the text, e.g.
-.. TODO: Math inside text: ``n - 1 \text{if $n$ is odd}``.
+.. math:: (-1)^n = \begin{cases} -1 \quad \text{if $n$ is odd} \\
+ +1 \quad \text{if $n$ is even.}
+ \end{cases}
+.. TODO: ``\mod`` and its relatives
+ --------------------------
-Tests
-=====
+ Commands ``\mod``, ``\bmod``, ``\pmod``, ``\pod`` deal with the special
+ spacing conventions of “mod” notation. ``\mod`` and ``\pod`` are
+ variants of ``\pmod`` preferred by some authors; ``\mod`` omits the
+ parentheses, whereas ``\pod`` omits the “mod” and retains the
+ parentheses.
+ \gcd(n,m\bmod n) ;\quad x\equiv y\pmod b
+ ;\quad x\equiv y\mod c ;\quad x\equiv y\pod d
+
+
+Integrals and sums
+==================
+
+The limits on integrals, sums, and similar symbols are placed either to
+the side of or above and below the base symbol, depending on convention
+and context. In inline formulas and fractions, the limits on sums, and
+similar symbols like
+
+.. math:: \lim_{n\to\infty} \sum_1^n \frac{1}{n}
+
+move to index postions: `\lim_{n\to\infty} \sum_1^n \frac{1}{n}`.
+
+The commands ``\limits`` and ``\nolimits`` override the automatic
+placement of the limits; ``\displaylimits`` means to use standard
+positioning as for the \sum command. They should follow immediately after
+the operator to which they apply.
+
+Compare the same term with default positions, ``\limits``, and
+``\nolimits`` in inline and display mode: `\lim_{x\to0}f(x)`,
+`\lim\limits_{x\to0}f(x)`, `\lim\nolimits_{x\to0}f(x)`, vs.
+
+.. math:: \lim_{x\to0}f(x), \quad
+ \lim\limits_{x\to0}f(x) \quad
+ \lim\nolimits_{x\to0}f(x).
+
+.. TODO: \substack
+
+.. TODO: \sideset
+
+
+Changing the size of elements in a formula
+==========================================
+
+The declarations [#]_ ``\displaystyle``, ``\textstyle``,
+``\scriptstyle``, and ``\scriptscriptstyle``, select a symbol size and
+spacing that would be applied in (respectively) display math, inline
+math, first-order subscript, or second-order subscript, even when the
+current context would normally yield some other size.
+
+For example ``:math:`\displaystyle \sum_{n=0}^\infty
+\frac{1}{n}``` is printed as `\displaystyle \sum_{n=0}^\infty \frac{1}{n}`
+rather than `\sum_{n=0}^\infty \frac{1}{n}` and ::
+
+ \frac{\scriptstyle\sum_{n > 0} z^n}
+ {\displaystyle\prod_{1\leq k\leq n} (1-q^k)}
+
+yields
+
+.. math::
+
+ \frac{\scriptstyle\sum_{n > 0} z^n}
+ {\displaystyle\prod_{1\leq k\leq n} (1-q^k)}
+ \text{ instead of the default }
+ \frac{\sum_{n > 0} z^n}
+ {\prod_{1\leq k\leq n} (1-q^k)}.
+
+.. [#] "Declarations" are commands that affect processing of the current
+ "group". In particular, notice where the braces fall that delimit the
+ effect of the command: Right: ``{\displaystyle ...}`` Wrong:
+ ``\displaystyle{...}``.
+
+ With math_output_ MathML, the declaration must be the first element
+ after the opening bracket.
+
+
+Appendix: Tests
+===============
+
Font changes
------------
@@ -690,15 +897,9 @@
Accents should be nearer to the base (in MathML Firefox 78, it's vice versa!):
`\bar a \overline a, \bar l \overline l, \bar i \overline i`.
-In inline formulas and fractions, the limits on lim, sum and integrals,
-
-.. math:: \lim_{c\to0} \oint_c f(x) \mathrm{d}x,
-
-should move to index postions: `\lim_{c\to0} \oint_c f(x) \mathrm{d}x`.
-
Sub- and superscript may be given in any order:
`x_i^j = x^j_i` and `\int_0^1 = \int^1_0`.
-Double exponent: `x^{10}^4`, `r_T_\mathrm{in}` and `x_i^n^2`.
+Double exponent: `x^{10^4}`, `r_{T_\mathrm{in}}` and `x_i^{n^2}`.
Binary vs. unary minus operator: `a - b = -c`
Modified: trunk/docutils/docutils/utils/math/latex2mathml.py
===================================================================
--- trunk/docutils/docutils/utils/math/latex2mathml.py 2021-05-20 12:25:30 UTC (rev 8757)
+++ trunk/docutils/docutils/utils/math/latex2mathml.py 2021-05-27 15:06:37 UTC (rev 8758)
@@ -57,24 +57,28 @@
'Gamma':u'\u0393', 'Lambda':u'\u039b'}
# functions -> <mi>
-functions = dict((name, name) for name in
- ('arccos', 'arcsin', 'arctan', 'arg', 'cos', 'cosh',
- 'cot', 'coth', 'csc', 'deg', 'det', 'dim',
- 'exp', 'gcd', 'hom', 'inf', 'ker', 'lg',
- 'ln', 'log', 'max', 'min', 'Pr',
- 'sec', 'sin', 'sinh', 'sup', 'tan', 'tanh'))
-functions.update({# functions with a space in the name
- 'liminf': u'lim\u202finf', 'limsup': u'lim\u202fsup',
- 'injlim': u'inj\u202flim', 'projlim': u'proj\u202flim',
- # embellished function names (see handle_cmdname() below)
- 'varlimsup': 'lim', 'varliminf': 'lim',
- 'varprojlim': 'lim', 'varinjlim': 'lim',
- # custom function name
- 'operatorname': None})
+functions = {# functions with a space in the name
+ 'liminf': u'lim\u202finf',
+ 'limsup': u'lim\u202fsup',
+ 'injlim': u'inj\u202flim',
+ 'projlim': u'proj\u202flim',
+ # embellished function names (see handle_cmd() below)
+ 'varlimsup': 'lim',
+ 'varliminf': 'lim',
+ 'varprojlim': 'lim',
+ 'varinjlim': 'lim',
+ # custom function name
+ 'operatorname': None,
+ }
+functions.update((name, name) for name in
+ ('arccos', 'arcsin', 'arctan', 'arg', 'cos',
+ 'cosh', 'cot', 'coth', 'csc', 'deg',
+ 'det', 'dim', 'exp', 'gcd', 'hom',
+ 'ker', 'lg', 'ln', 'log', 'Pr',
+ 'sec', 'sin', 'sinh', 'tan', 'tanh'))
+# Function with limits: 'lim', 'sup', 'inf', 'max', 'min':
+# use <mo> to allow "movablelimits" attribute (see below).
-# function with limits, use <mo> to allow "movablelimits" attribute
-functions_with_limits = dict((name, name) for name in
- ('lim', 'sup', 'inf', 'max', 'min'))
# math font selection -> <mi mathvariant=...> or <mstyle mathvariant=...>
math_alphabets = {# 'cmdname': 'mathvariant value' # package
@@ -98,6 +102,15 @@
# operator, fence, or separator -> <mo>
+
+math_fences = {# mathfence aliases with adapted spacing
+ 'lvert': u'|', # left |
+ 'lVert': u'\u2016', # left ‖
+ 'rvert': u'|', # right |
+ 'rVert': u'\u2016', # right ‖
+ 'Arrowvert': u'\u2016', # ‖
+ }
+
operators = tex2unichar.mathbin # Binary symbols
operators.update(tex2unichar.mathrel) # Relation symbols, arrow symbols
operators.update(tex2unichar.mathord) # Miscellaneous symbols
@@ -105,7 +118,7 @@
operators.update(tex2unichar.mathopen) # Braces
operators.update(tex2unichar.mathclose) # Braces
operators.update(tex2unichar.mathfence)
-operators.update(functions_with_limits)
+operators.update(math_fences)
operators.update({# negated symbols without pre-composed Unicode character
'nleqq': u'\u2266\u0338', # ≦̸
'ngeqq': u'\u2267\u0338', # ≧̸
@@ -114,16 +127,17 @@
'nsubseteqq': u'\u2AC5\u0338', # ⫅̸
'nsupseteqq': u'\u2AC6\u0338', # ⫆̸
# alias commands:
- 'lvert': u'|', # left |
- 'lVert': u'\u2016', # left ‖
- 'rvert': u'|', # right |
- 'rVert': u'\u2016', # right ‖
- 'Arrowvert': u'\u2016', # ‖
- 'dotsb': u'\u22ef', # ⋯ with binary operators/relations
- 'dotsc': u'\u2026', # … with commas
- 'dotsi': u'\u22ef', # ⋯ with integrals
- 'dotsm': u'\u22ef', # ⋯ multiplication dots
- 'dotso': u'\u2026', # … other dots
+ 'dotsb': u'\u22ef', # ⋯ with binary operators/relations
+ 'dotsc': u'\u2026', # … with commas
+ 'dotsi': u'\u22ef', # ⋯ with integrals
+ 'dotsm': u'\u22ef', # ⋯ multiplication dots
+ 'dotso': u'\u2026', # … other dots
+ # functions with movable limits (requires <mo>)
+ 'lim': 'lim',
+ 'sup': 'sup',
+ 'inf': 'inf',
+ 'max': 'max',
+ 'min': 'min',
})
# special cases
@@ -143,14 +157,23 @@
'smallint': u'\u222b', # ∫ INTEGRAL
}
-# Operators and functions with limits
-# above/below in display formulas and in index position inline
-with_limits = [operators[name] for name in
- ('coprod', 'fatsemi', 'fint', 'iiiint', 'iiint',
- 'iint', 'int', 'oiint', 'oint', 'ointctrclockwise',
- 'prod', 'sqint', 'sum', 'varointclockwise',
- 'lim', 'sup', 'inf', 'max', 'min')]
+# Operators and functions with limits above/below in display formulas
+# and in index position inline (movablelimits="true")
+displaylimits = [operators[name] for name in
+ ('bigcap', 'bigcup', 'bigodot', 'bigoplus', 'bigotimes',
+ 'bigsqcup', 'biguplus', 'bigvee', 'bigwedge',
+ 'coprod', 'prod', 'sum',
+ 'lim', 'max', 'min', 'sup', 'inf')]
+# Depending on settings, integrals may also be in this category.
+# (e.g. if "amsmath" is loaded with option "intlimits", see
+# http://mirror.ctan.org/macros/latex/required/amsmath/amsldoc.pdf)
+# displaylimits.extend(('fint', 'iiiint', 'iiint', 'iint', 'int', 'oiint',
+# 'oint', 'ointctrclockwise', 'sqint',
+# 'varointclockwise',))
+# >>> print(' '.join(displaylimits))
+# ⋂ ⋃ ⨀ ⨁ ⨂ ⨆ ⨄ ⋁ ⋀ ∐ ∏ ∑ lim max min sup inf
+
# pre-composed characters for negated symbols
# see https://www.w3.org/TR/xml-entity-names/#combining
negatables = {'=': u'\u2260',
@@ -158,36 +181,21 @@
r'\equiv': u'\u2262'}
# extensible delimiters allowed in left/right cmds
-stretchables = {'(': '(',
- ')': ')',
- '[': '[',
- ']': ']',
- '/': '/',
- r'\backslash': '\\',
- '|': '|',
- '.': '', # emty fence
- r'\uparrow': u'\u2191', # ↑ UPWARDS ARROW
- r'\downarrow': u'\u2193', # ↓ DOWNWARDS ARROW
- r'\updownarrow': u'\u2195', # ↕ UP DOWN ARROW
- r'\Uparrow': u'\u21d1', # ⇑ UPWARDS DOUBLE ARROW
- r'\Downarrow': u'\u21d3', # ⇓ DOWNWARDS DOUBLE ARROW
- r'\Updownarrow': u'\u21d5', # ⇕ UP DOWN DOUBLE ARROW
- }
-for (key, value) in tex2unichar.mathfence.items():
- stretchables['\\'+key] = value
-for (key, value) in tex2unichar.mathopen.items():
- stretchables['\\'+key] = value
-for (key, value) in tex2unichar.mathclose.items():
- stretchables['\\'+key] = value
-# shorter with {**something} syntax, new in 3.5
-# if sys.version_info >= (3, 5):
-# for (key, value) in {**tex2unichar.mathclose,
-# **tex2unichar.mathopen,
-# **tex2unichar.mathfence}.items():
-# stretchables['\\'+key] = value
+stretchables = {'backslash': '\\',
+ 'uparrow': u'\u2191', # ↑ UPWARDS ARROW
+ 'downarrow': u'\u2193', # ↓ DOWNWARDS ARROW
+ 'updownarrow': u'\u2195', # ↕ UP DOWN ARROW
+ 'Uparrow': u'\u21d1', # ⇑ UPWARDS DOUBLE ARROW
+ 'Downarrow': u'\u21d3', # ⇓ DOWNWARDS DOUBLE ARROW
+ 'Updownarrow': u'\u21d5', # ⇕ UP DOWN DOUBLE ARROW
+ }
+stretchables.update(tex2unichar.mathfence)
+stretchables.update(tex2unichar.mathopen)
+stretchables.update(tex2unichar.mathclose)
+stretchables.update(math_fences)
# >>> print(' '.join(sorted(set(stretchables.values()))))
-# ( ) / [ \ ] { | } ‖ ↑ ↓ ↕ ⇑ ⇓ ⇕ ⌈ ⌉ ⌊ ⌋ ⌜ ⌝ ⌞ ⌟ ⟅ ⟆ ⟦ ⟧ ⟨ ⟩ ⟮ ⟯ ⦇ ⦈
+# [ \ ] { | } ‖ ↑ ↓ ↕ ⇑ ⇓ ⇕ ⌈ ⌉ ⌊ ⌋ ⌜ ⌝ ⌞ ⌟ ⟅ ⟆ ⟦ ⟧ ⟨ ⟩ ⟮ ⟯ ⦇ ⦈
# horizontal space -> <mspace>
@@ -258,6 +266,47 @@
}
+matrices = {'matrix': ('', ''),
+ 'smallmatrix': ('', ''), # smaller, see begin_environment()!
+ 'pmatrix': ('(', ')'),
+ 'bmatrix': ('[', ']'),
+ 'Bmatrix': ('{', '}'),
+ 'vmatrix': ('|', '|'),
+ 'Vmatrix': (u'\u2016', u'\u2016'), # ‖
+ 'cases': ('{', ''),
+ }
+
+layout_styles = {
+ 'displaystyle': {'displaystyle': 'true', 'scriptlevel': '0'},
+ 'textstyle': {'displaystyle': 'false', 'scriptlevel': '0'},
+ 'scriptstyle': {'displaystyle': 'false', 'scriptlevel': '1'},
+ 'scriptscriptstyle': {'displaystyle': 'false', 'scriptlevel': '2'},
+ }
+# See also https://www.w3.org/TR/MathML3/chapter3.html#presm.scriptlevel
+
+fractions = {# name: style_attrs, frac_attrs
+ 'frac': ({}, {}),
+ 'cfrac': ({'displaystyle': 'true', 'scriptlevel': '0',
+ 'CLASS': 'cfrac'}, {}), # in LaTeX with padding
+ 'dfrac': (layout_styles['displaystyle'], {}),
+ 'tfrac': (layout_styles['textstyle'], {}),
+ 'binom': ({}, {'linethickness': 0}),
+ 'dbinom': (layout_styles['displaystyle'], {'linethickness': 0}),
+ 'tbinom': (layout_styles['textstyle'], {'linethickness': 0}),
+ }
+
+delimiter_sizes = {'left': '',
+ 'right': '',
+ 'bigl': '1.2em',
+ 'bigr': '1.2em',
+ 'Bigl': '1.623em',
+ 'Bigr': '1.623em',
+ 'biggl': '2.047em',
+ 'biggr': '2.047em',
+ 'Biggl': '2.470em',
+ 'Biggr': '2.470em',
+ }
+
# MathML element classes
# ----------------------
@@ -282,8 +331,7 @@
"""
self.children = []
- for child in children:
- self.append(child)
+ self.extend(children)
self.attributes = collections.OrderedDict()
# sort attributes for predictable functional tests
@@ -295,7 +343,7 @@
content = [repr(item) for item in getattr(self, 'children', [])]
if hasattr(self, 'data'):
content.append(repr(self.data))
- if isinstance(self, MathScriptOrLimit) and self.switch:
+ if isinstance(self, MathSchema) and self.switch:
content.append('switch=True')
if hasattr(self, 'attributes'):
content += ["%s='%s'"%(k, v) for k, v in self.attributes.items()]
@@ -304,6 +352,13 @@
def __len__(self):
return len(self.children)
+ # emulate dictionary-like access to attributes
+ # see `docutils.nodes.Element` for dict/list interface
+ def __getitem__(self, key):
+ return self.attributes[key]
+ def __setitem__(self, key, item):
+ self.attributes[key] = item
+
def full(self):
"""Return boolean indicating whether children may be appended."""
return (self.nchildren is not None
@@ -323,6 +378,11 @@
return self.close()
return self
+ def extend(self, children):
+ for child in children:
+ self.append(child)
+ return self
+
def close(self):
"""Close element and return first non-full parent or None."""
parent = self.parent
@@ -383,17 +443,20 @@
def close(self):
"""Close element and return first non-full parent or None.
- Remove <mrow>, if it is single child and the parent inferres an mrow
+ Remove <mrow>, if it is single child and the parent infers an mrow
or if it has only one child element.
"""
parent = self.parent
- if isinstance(parent, MathRowInferred) and parent.nchildren == 1:
+ if isinstance(parent, MathRowSchema) and parent.nchildren == 1:
parent.nchildren = None
parent.children = self.children
+ for child in self.children:
+ child.parent = parent
return parent.close()
if len(self) == 1:
try:
parent.children[parent.children.index(self)] = self.children[0]
+ self.children[0].parent = parent
except (AttributeError, ValueError):
return self.children[0]
return super(mrow, self).close()
@@ -404,17 +467,21 @@
# The elements <msqrt>, <mstyle>, <merror>, <mpadded>, <mphantom>, <menclose>,
# <mtd>, <mscarry>, and <math> treat their contents as a single inferred mrow
# formed from all their children.
-class MathRowInferred(math):
+class MathRowSchema(math):
"""Base class for elements treating content as a single inferred mrow."""
-class mtr(MathRowInferred): pass
-class mtd(MathRowInferred): pass
-class mstyle(MathRowInferred):
- nchildren = 1
-class msqrt(MathRowInferred):
- nchildren = 1
+class mtr(MathRowSchema): pass
+class mtd(MathRowSchema): pass
+class mphantom(MathRowSchema):
+ nchildren = 1 # \phantom expects one argument or a group
+class mstyle(MathRowSchema):
+ nchildren = 1 # \mathrm, ... expect one argument or a group
+class msqrt(MathRowSchema):
+ nchildren = 1 # \sqrt expects one argument or a group
+class menclose(MathRowSchema):
+ nchildren = 1 # \boxed expects one argument or a group
class MathToken(math):
- """Token Element: contains data instead of children.
+ """Token Element: contains textual data instead of children.
Base class for mo, mi, and mn.
"""
@@ -437,22 +504,21 @@
# >>> mo(u'<')._xml()
# ['<mo>', '<', '</mo>']
-class MathScriptOrLimit(math):
- """Base class for script and limit schemata."""
+class MathSchema(math):
+ """Base class for schemata expecting 2 or more children.
+
+ The special attribute `switch` indicates that the last two child
+ elements are in reversed order and must be switched before XML-export.
+ """
+
nchildren = 2
def __init__(self, *children, **kwargs):
- """Set up sub/superscript or limit elements.
-
- The special attribute `switch` tells that the
- last two child elements are in reversed order
- and must be switched before XML-export.
- """
self.swit...
[truncated message content] |
|
From: <mi...@us...> - 2021-05-27 15:06:55
|
Revision: 8759
http://sourceforge.net/p/docutils/code/8759
Author: milde
Date: 2021-05-27 15:06:51 +0000 (Thu, 27 May 2021)
Log Message:
-----------
Minor documentation update.
Modified Paths:
--------------
trunk/docutils/FAQ.txt
trunk/docutils/docs/user/config.txt
trunk/docutils/docutils/writers/_html_base.py
Modified: trunk/docutils/FAQ.txt
===================================================================
--- trunk/docutils/FAQ.txt 2021-05-27 15:06:37 UTC (rev 8758)
+++ trunk/docutils/FAQ.txt 2021-05-27 15:06:51 UTC (rev 8759)
@@ -983,10 +983,22 @@
.. note:: For the html5 writer, `initial_header_level`_ defaults to
``2`` because this is what the `HTML5 standard`__ expects as
start value for headings nested in <section> elements.
+
+ .. Sectioning content elements are always considered subsections of
+ their nearest ancestor *sectioning root* [#]_ or their nearest
+ ancestor element of *sectioning content* [#]_, whichever is nearest,
+ [...]
+
+ .. [#] <blockquote>, <body>, <details>, <dialog>, <fieldset>,
+ <figure>, <td>
+ .. [#] <article>, <aside>, <nav>, <section>
+
+ I.e., a top-level <section> is a subsection of <body>.
__ https://www.w3.org/TR/html53/sections.html#headings-and-sections
+
How are lists formatted in HTML?
--------------------------------
Modified: trunk/docutils/docs/user/config.txt
===================================================================
--- trunk/docutils/docs/user/config.txt 2021-05-27 15:06:37 UTC (rev 8758)
+++ trunk/docutils/docs/user/config.txt 2021-05-27 15:06:51 UTC (rev 8759)
@@ -1106,7 +1106,7 @@
"align" (or other equation-aligning) environment. (C++)
LaTeXML_
- Comprehensive macro support but very slow. (Perl)
+ Comprehensive macro support but *very* slow. (Perl)
TtM_
No "matrix", "align" and "cases" environments. Support may be removed.
Modified: trunk/docutils/docutils/writers/_html_base.py
===================================================================
--- trunk/docutils/docutils/writers/_html_base.py 2021-05-27 15:06:37 UTC (rev 8758)
+++ trunk/docutils/docutils/writers/_html_base.py 2021-05-27 15:06:51 UTC (rev 8759)
@@ -880,7 +880,7 @@
def visit_field_list(self, node):
atts = {}
- classes = node.setdefault('classes', [])
+ classes = node.setdefault('classes', [])
for i, cls in enumerate(classes):
if cls.startswith('field-indent-'):
try:
@@ -1628,9 +1628,11 @@
if isinstance(node.parent, nodes.topic):
self.body.append(
self.starttag(node, 'p', '', CLASS='topic-title'))
+ # TODO: use role="heading" or <h1>? (HTML5 only)
elif isinstance(node.parent, nodes.sidebar):
self.body.append(
self.starttag(node, 'p', '', CLASS='sidebar-title'))
+ # TODO: use role="heading" or <h1>? (HTML5 only)
elif isinstance(node.parent, nodes.Admonition):
self.body.append(
self.starttag(node, 'p', '', CLASS='admonition-title'))
@@ -1645,6 +1647,8 @@
else:
assert isinstance(node.parent, nodes.section)
h_level = self.section_level + self.initial_header_level - 1
+ # TODO: use '<h6 aria-level="%s">' % h_level
+ # for h_level > 6 (HTML5 only)
atts = {}
if (len(node.parent) >= 2 and
isinstance(node.parent[1], nodes.subtitle)):
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2021-06-17 09:58:30
|
Revision: 8760
http://sourceforge.net/p/docutils/code/8760
Author: milde
Date: 2021-06-17 09:58:31 +0000 (Thu, 17 Jun 2021)
Log Message:
-----------
MathML: refactor and extend.
Only wrap displayed math in <mtable> if there are multiple rows.
Fix alignment and spacing in multi-line equations.
Fix size commands for extensible delimiters.
Add support for commands \displaylimits, \mspace, \intop, \ointop.
math.get(): new method, return attribute or optional default.
tex_token(): don't skip leading whitespace, don't return groups
tex_group(): new function -- return first group or token and remainder.
tex_group_or_token(): new function
Modified Paths:
--------------
trunk/docutils/docs/ref/rst/mathematics.txt
trunk/docutils/docutils/utils/math/__init__.py
trunk/docutils/docutils/utils/math/latex2mathml.py
trunk/docutils/docutils/utils/math/tex2unichar.py
trunk/docutils/test/functional/expected/math_output_mathml.html
Modified: trunk/docutils/docs/ref/rst/mathematics.txt
===================================================================
--- trunk/docutils/docs/ref/rst/mathematics.txt 2021-05-27 15:06:51 UTC (rev 8759)
+++ trunk/docutils/docs/ref/rst/mathematics.txt 2021-06-17 09:58:31 UTC (rev 8760)
@@ -6,35 +6,17 @@
.. default-role:: math
.. |latex| replace:: L\ :sup:`A`\ T\ :sub:`E`\ X
+:abstract: Docutils supports mathematical content with a `"math"
+ directive`__ and `role`__. The input format is *LaTeX math
+ syntax*\ [#math-syntax]_ with support for Unicode symbols.
+
.. sectnum::
.. contents::
-Introduction
-============
-
-Since version 0.8, Docutils supports mathematical content with a `"math"
-directive`__ and `role`__.
-The input format is *LaTeX math syntax*\ [#math-syntax]_ with support for
-Unicode symbols.
-
-
-.. [#math-syntax] The supported LaTeX commands include AMS extensions
- (see, e.g., the `Short Math Guide`_).
-
- The support is limited to a subset of *LaTeX math* by the conversion
- required for many output formats. For HTML, the `math_output`_
- configuration setting (or the corresponding ``--math-output`` command
- line option) selects between alternative output formats with different
- subsets of supported elements. If a writer does not support math
- typesetting, the content is inserted verbatim.
-
__ https://docutils.sourceforge.io/docs/ref/rst/directives.html#math
__ https://docutils.sourceforge.io/docs/ref/rst/roles.html#math
-.. _Short Math Guide:
- http://mirrors.ctan.org/info/short-math-guide/short-math-guide.pdf
-.. _math_output:
- https://docutils.sourceforge.io/docs/user/config.html#math-output
+
Inline formulas and displayed equations
=======================================
@@ -89,8 +71,8 @@
.. math::
- a & = (x + y)^2 \\
- & = x^2 + 2xy + y^2
+ a &= (x + y)^2 &\qquad b &= (x - y)^2 \\
+ &= x^2 + 2xy + y^2 & &= x^2 - 2xy + y^2
LaTeX output will wrap it in an ``align*`` environment.
The result is:
@@ -97,12 +79,28 @@
.. math::
- a & = (x + y)^2 \\
- & = x^2 + 2xy + y^2
+ a &= (x + y)^2 & b &= (x - y)^2 \\
+ &= x^2 + 2xy + y^2 & &= x^2 - 2xy + y^2
-.. _hyperlink references: ../ref/rst/restructuredtext.html#hyperlink-references
+.. [#math-syntax] The supported LaTeX commands include AMS extensions
+ (see, e.g., the `Short Math Guide`_).
+ The support is limited to a subset of *LaTeX math* by the conversion
+ required for many output formats. For HTML, the `math_output`_
+ configuration setting (or the corresponding ``--math-output`` command
+ line option) selects between alternative output formats with different
+ subsets of supported elements. If a writer does not support math
+ typesetting, the content is inserted verbatim.
+
+.. _hyperlink references:
+ ../ref/rst/restructuredtext.html#hyperlink-references
+.. _Short Math Guide:
+ http://mirrors.ctan.org/info/short-math-guide/short-math-guide.pdf
+.. _math_output:
+ https://docutils.sourceforge.io/docs/user/config.html#math-output
+
+
Mathematical symbols
====================
@@ -183,6 +181,8 @@
.. math:: A = \left . \frac{1}{1-n}\, \right |_{n=0}^\infty
+See also the commands for fixed `delimiter sizes`_ below.
+
The following symbols extend when used with ``\left`` and ``\right``:
Pairing delimiters
@@ -214,6 +214,8 @@
`\lvert -k\rvert` and `\lvert\sin(x)\rvert`, prevent this problem
(in LaTeX and MathJax).
+.. TODO: fix spacing before unary minus (see also cases example below).
+
Vertical Arrows
~~~~~~~~~~~~~~~
.. class:: colwidths-auto
@@ -261,7 +263,7 @@
-------------
In LaTeX, the default font for capital Greek letters is upright/roman.
-Italic capital Greek letters can be obtained by loading a `package
+*Italic* capital Greek letters can be obtained by loading a `package
providing the "ISO" math style`__. They are used by default in MathML.
Greek letters that have Latin look-alikes are rarely used in math
@@ -289,16 +291,15 @@
------------------
.. class:: colwidths-auto
-========== ============ ============= =============== ========= =========== =========== =============
-`\aleph` ``\aleph`` `\forall` ``\forall`` `\hbar` ``\hbar`` `\ell` ``\ell``
-`\beth` ``\beth`` `\complement` ``\complement`` `\hslash` ``\hslash`` `\wp` ``\wp``
-`\gimel` ``\gimel`` `\exists` ``\exists`` `\Im` ``\Im`` `\Re` ``\Re``
-`\daleth` ``\daleth`` `\Finv` ``\Finv`` `\imath` ``\imath`` `\circledR` ``\circledR``
-`\partial` ``\partial`` `\Game` ``\Game`` `\Bbbk` ``\Bbbk`` `\circledS` ``\circledS``
-`\eth` ``\eth`` `\mho` ``\mho``
-========== ============ ============= =============== ========= =========== =========== =============
+ ============= =============== ========== ============ ========== ============ =========== =============
+ `\forall` ``\forall`` `\aleph` ``\aleph`` `\hbar` ``\hbar`` `\ell` ``\ell``
+ `\complement` ``\complement`` `\beth` ``\beth`` `\hslash` ``\hslash`` `\wp` ``\wp``
+ `\exists` ``\exists`` `\gimel` ``\gimel`` `\Im` ``\Im`` `\Re` ``\Re``
+ `\Finv` ``\Finv`` `\daleth` ``\daleth`` `\imath` ``\imath`` `\circledR` ``\circledR``
+ `\Game` ``\Game`` `\partial` ``\partial`` `\jmath` ``\jmath`` `\circledS` ``\circledS``
+ `\mho` ``\mho`` `\eth` ``\eth`` `\Bbbk` ``\Bbbk``
+ ============= =============== ========== ============ ========== ============ =========== =============
-
Mathematical Alphabets
----------------------
@@ -400,7 +401,6 @@
.. [#] Punctuation (not ratio):
Compare spacing in `a\colon b\to c` to `a:b = c`.
-
Relation symbols
----------------
@@ -577,12 +577,12 @@
``&``::
.. math::
- \left(\begin{matrix} a & b \\ c & d \end{matrix}\right)
+ \left ( \begin{matrix} a & b \\ c & d \end{matrix}\right)
Result:
.. math::
- \left(\begin{matrix} a & b \\ c & d \end{matrix}\right)
+ \left ( \begin{matrix} a & b \\ c & d \end{matrix} \right)
The environments ``pmatrix``, ``bmatrix``, ``Bmatrix``, ``vmatrix``, and
``Vmatrix`` have (respectively) ( ), [ ], { }, \| \|, and `\Vert\ \Vert`
@@ -602,8 +602,8 @@
For piecewise function definitions there is a ``cases`` environment:
.. math:: \mathrm{sgn}(x) = \begin{cases}
- -1 & x<0\\
- 1 & x>0
+ \, -1 & x<0\\
+ \,\phantom{-}1 & x>0
\end{cases}
Spacing commands
@@ -614,22 +614,25 @@
.. class:: colwidths-auto
- ===================== ======== =======================
- :m:`3\qquad8` ``3\qquad8`` (2em)
- :m:`3\quad8` ``3\quad8`` (1em)
- :m:`3~8` ``3~8`` ``3\nobreakspace8``
- :m:`3\ 8` ``3\ 8`` escaped space
- :m:`3\;8` ``3\;8`` ``3\thickspace8``
- :m:`3\:8` ``3\:8`` ``3\medspace8``
- :m:`3\,8` ``3\,8`` ``3\thinspace8``
- :m:`3 8` ``3 8`` regular space (ignored)
- :m:`3\!8` ``3\!8`` ``3\negthinspace8``
- :m:`3\negmedspace8` ``3\negmedspace8``
- :m:`3\negthickspace8` ``3\negthickspace8``
- `3\hspace{1ex}8` ``3\hspace{1ex}8``
- ===================== ======== =======================
+ ====================== ======== ===================== ==================
+ :m:`3\qquad |` ``3\qquad |`` = 2em
+ :m:`3\quad |` ``3\quad |`` = 1em
+ :m:`3~|` ``3~|`` ``3\nobreakspace |``
+ :m:`3\ |` ``3\ |`` escaped space
+ :m:`3\;|` ``3\;|`` ``3\thickspace |``
+ :m:`3\:|` ``3\:|`` ``3\medspace |``
+ :m:`3\,|` ``3\,|`` ``3\thinspace |``
+ :m:`3 |` ``3 |`` regular space [#]_
+ :m:`3\!|` ``3\!|`` ``3\negthinspace |``
+ :m:`3\negmedspace |` ``3\negmedspace |``
+ :m:`3\negthickspace |` ``3\negthickspace |``
+ `3\hspace{1ex}|` ``3\hspace{1ex}|`` custom length
+ `3\mspace{20mu}|` ``3\mspace{20mu}|`` custom length [#]_
+ ====================== ======== ===================== ==================
-Whitespace is ignored in LaTeX math mode.
+.. [#] Whitespace characters are ignored in LaTeX math mode.
+.. [#] Unit must be 'mu' (1 mu = 1/18em).
+
Negative spacing does not work with MathML (in Firefox 78).
There are also three commands that leave a space equal to the height and
@@ -638,8 +641,8 @@
.. math:: \frac{\phantom{XXX}+1}{XXX-1}
-The commands ``\hphantom`` and ``\vphantom`` insert space with the heigth
-rsp. width of the argument. They are not supported with `math_output`_
+The commands ``\hphantom`` and ``\vphantom`` insert space with the
+width or height of the argument. They are not supported with `math_output`_
MathML.
Roots
@@ -668,7 +671,8 @@
===================================
The ``\frac`` command takes two ar guments, numerator and denominator,
-and typesets them in normal fraction form. Use ``\dfrac`` or ``\tfrac`` to
+and typesets them in normal fraction form. For example, ``U = \frac{R}{I}``
+produces `U = \frac{R}{I}`. Use ``\dfrac`` or ``\tfrac`` to
force text style and display style respectively.
.. math:: \frac{x+1}{x-1} \quad
@@ -689,15 +693,17 @@
The ``\cfrac`` command for continued fractions uses displaystyle and
padding for sub-fractions:
-.. math:: \cfrac{1}{\sqrt{2}+
- \cfrac{1}{\sqrt{2}+
- \cfrac{1}{\sqrt{2}+\dotsb
- }}}
- \text{ vs. }
- \frac{1}{\sqrt{2}+
- \frac{1}{\sqrt{2}+
- \frac{1}{\sqrt{2}+\dotsb
- }}}
+.. math:: \frac{\pi}{4} = 1 + \cfrac{1^2}{
+ 2 + \cfrac{3^2}{
+ 2 + \cfrac{5^2}{
+ 2 + \cfrac{7^2}{2 + \cdots}
+ }}}
+ \qquad \text{vs.}\qquad
+ \frac{\pi}{4} = 1 + \frac{1^2}{
+ 2 + \frac{3^2}{
+ 2 + \frac{5^2}{
+ 2 + \frac{7^2}{2 + \cdots}
+ }}}
It supports the optional argument ``[l]`` or ``[r]`` for
left or right placement of the numerator:
@@ -775,12 +781,15 @@
.. Math:: f_{[x_{i-1},x_i]} \text{ is monotonic for } i = 1,\,…,\,c+1
-``$`` signs can be used for math commands inside the text, e.g.
+The text may contain math commands wrapped in ``$`` signs, e.g.
-.. math:: (-1)^n = \begin{cases} -1 \quad \text{if $n$ is odd} \\
- +1 \quad \text{if $n$ is even.}
- \end{cases}
+.. math:: (-1)^{n_i} = \begin{cases} -1 \quad \text{if $n_i$ is odd} \\
+ +1 \quad \text{if $n_i$ is even.}
+ \end{cases}
+.. TODO ignore {}, handle text-mode commands
+
+
.. TODO: ``\mod`` and its relatives
--------------------------
@@ -806,8 +815,18 @@
move to index postions: `\lim_{n\to\infty} \sum_1^n \frac{1}{n}`.
-The commands ``\limits`` and ``\nolimits`` override the automatic
-placement of the limits; ``\displaylimits`` means to use standard
+Altering the placement of limits
+--------------------------------
+
+The commands ``\intop`` and ``\ointop`` produce integral signs with
+limits as in sums and similar: `\intop_0^1`, `\ointop_c` and
+
+.. math:: \intop_0^1 \quad \ointop_c
+ \quad \text{vs.} \quad
+ \int^1_0 \quad \oint_c
+
+The commands ``\limits`` and ``\nolimits`` override the default placement
+of the limits for any operator; ``\displaylimits`` forces standard
positioning as for the \sum command. They should follow immediately after
the operator to which they apply.
@@ -859,11 +878,15 @@
after the opening bracket.
-Appendix: Tests
-===============
+Appendix
+========
+Tests
+-----
+
+
Font changes
-------------
+~~~~~~~~~~~~
Math alphabet macros change the default alphabet ("mathvariant" in
MathML), leaving some symbols unchanged:
@@ -879,6 +902,7 @@
`\mathbb{a \ldots z A \ldots Z 0 \ldots 9
\mathbb\Gamma \mathbb{\Pi} \mathbb {\Sigma} \mathbb\gamma \mathbb\pi}`.
+
Inferred <mrow>s in MathML
~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -888,11 +912,11 @@
.. math:: a = \sqrt 2 + x, b = \sqrt{1+x^2}, c = \sqrt\frac{\sin(x)}{23},
-
inline: :math:`a = \sqrt 2 + x, b = \sqrt{1+x^2}, c = \sqrt\frac{\sin(x)}{23}`.
+
Scripts and Limits
-------------------
+~~~~~~~~~~~~~~~~~~
Accents should be nearer to the base (in MathML Firefox 78, it's vice versa!):
`\bar a \overline a, \bar l \overline l, \bar i \overline i`.
@@ -902,4 +926,52 @@
Double exponent: `x^{10^4}`, `r_{T_\mathrm{in}}` and `x_i^{n^2}`.
-Binary vs. unary minus operator: `a - b = -c`
+
+Nested groups
+~~~~~~~~~~~~~
+
+tex-token returns "{" for nested groups:
+
+.. math:: \text{das ist ein {toller} text (unescaped \{ and \} is
+ ignored by LaTeX)}
+
+Big delimiters
+~~~~~~~~~~~~~~
+
+Test ``\left``, ``\right``, and the \bigl/\bigr, … size commands
+with extensible delimiters.
+
+.. math::
+ \left.(b\right)\ \bigl(b\Bigr)\ \biggl(b\Biggr)
+ \quad
+ \left.[b\right]\ \bigl[b\Bigr]\ \biggl[b\Biggr]
+ \quad
+ \left.\{b\right \} \ \bigl\{b\Bigr \} \ \biggl\{b\Biggr \}
+ \quad
+ \left.\langle b\right\rangle\ \bigl\langle b\Bigr\rangle\ \biggl\langle b\Biggr\rangle
+ \quad
+ \left.\lceil b\right\rceil\ \bigl\lceil b\Bigr\rceil\ \biggl\lceil b\Biggr\rceil
+
+ \left.\lfloor b\right\rfloor\ \bigl\lfloor b\Bigr\rfloor\ \biggl\lfloor b\Biggr\rfloor
+ \quad
+ \left.\lgroup b\right\rgroup\ \bigl\lgroup b\Bigr\rgroup\ \biggl\lgroup b\Biggr\rgroup
+ \quad
+ \left.\lmoustache b\right\rmoustache\ \bigl\lmoustache b\Bigr\rmoustache\ \biggl\lmoustache b\Biggr\rmoustache
+ \quad
+ \left.\lvert b\right\rvert\ \bigl\lvert b\Bigr\rvert\ \biggl\lvert b\Biggr\rvert
+ \quad
+ \left.\lVert b\right\rVert\ \bigl\lVert b\Bigr\rVert\ \biggl\lVert b\Biggr\rVert
+
+ \left.|b\right\|\ \bigl|b\Bigr\|\ \biggl|b\Biggr\|
+ \quad
+ \left./b\right\backslash\ \bigl/b\Bigr\backslash\ \biggl/b\Biggr\backslash
+ \quad
+ \left.(b\right)\ \bigl(b\Bigr)\ \biggl(b\Biggr)
+ \quad
+ \left.\arrowvert b\right\Arrowvert\ \bigl\arrowvert b\Bigr\Arrowvert\ \biggl\arrowvert b\Biggr\Arrowvert
+
+ \left.\bracevert b\right\bracevert\ \bigl\bracevert b\Bigr\bracevert\ \biggl\bracevert b\Biggr\bracevert
+ \quad
+ \left.\vert \frac{b}{a}\right\Vert\ \bigl\vert b\Bigr\Vert\ \biggl\vert b\Biggr\Vert
+ \quad
+
Modified: trunk/docutils/docutils/utils/math/__init__.py
===================================================================
--- trunk/docutils/docutils/utils/math/__init__.py 2021-05-27 15:06:51 UTC (rev 8759)
+++ trunk/docutils/docutils/utils/math/__init__.py 2021-06-17 09:58:31 UTC (rev 8760)
@@ -25,6 +25,12 @@
# helpers for Docutils math support
# =================================
+def toplevel_code(code):
+ """Return string (LaTeX math) `code` with environments stripped out."""
+ chunks = code.split(r'\begin{')
+ return r'\begin{'.join([chunk.split(r'\end{')[-1]
+ for chunk in chunks])
+
def pick_math_environment(code, numbered=False):
"""Return the right math environment to display `code`.
@@ -35,11 +41,7 @@
If `numbered` evaluates to ``False``, the "starred" versions are used
to suppress numbering.
"""
- # cut out environment content:
- chunks = code.split(r'\begin{')
- toplevel_code = ''.join([chunk.split(r'\end{')[-1]
- for chunk in chunks])
- if toplevel_code.find(r'\\') >= 0:
+ if toplevel_code(code).find(r'\\') >= 0:
env = 'align'
else:
env = 'equation'
Modified: trunk/docutils/docutils/utils/math/latex2mathml.py
===================================================================
--- trunk/docutils/docutils/utils/math/latex2mathml.py 2021-05-27 15:06:51 UTC (rev 8759)
+++ trunk/docutils/docutils/utils/math/latex2mathml.py 2021-06-17 09:58:31 UTC (rev 8760)
@@ -29,7 +29,7 @@
if sys.version_info >= (3, 0):
unicode = str # noqa
-from docutils.utils.math import tex2unichar
+from docutils.utils.math import tex2unichar, toplevel_code
# Character data
@@ -159,11 +159,10 @@
# Operators and functions with limits above/below in display formulas
# and in index position inline (movablelimits="true")
-displaylimits = [operators[name] for name in
- ('bigcap', 'bigcup', 'bigodot', 'bigoplus', 'bigotimes',
+displaylimits = ('bigcap', 'bigcup', 'bigodot', 'bigoplus', 'bigotimes',
'bigsqcup', 'biguplus', 'bigvee', 'bigwedge',
- 'coprod', 'prod', 'sum',
- 'lim', 'max', 'min', 'sup', 'inf')]
+ 'coprod', 'intop', 'ointop', 'prod', 'sum',
+ 'lim', 'max', 'min', 'sup', 'inf')
# Depending on settings, integrals may also be in this category.
# (e.g. if "amsmath" is loaded with option "intlimits", see
# http://mirror.ctan.org/macros/latex/required/amsmath/amsldoc.pdf)
@@ -171,8 +170,6 @@
# 'oint', 'ointctrclockwise', 'sqint',
# 'varointclockwise',))
-# >>> print(' '.join(displaylimits))
-# ⋂ ⋃ ⨀ ⨁ ⨂ ⨆ ⨄ ⋁ ⋀ ∐ ∏ ∑ lim max min sup inf
# pre-composed characters for negated symbols
# see https://www.w3.org/TR/xml-entity-names/#combining
@@ -188,6 +185,10 @@
'Uparrow': u'\u21d1', # ⇑ UPWARDS DOUBLE ARROW
'Downarrow': u'\u21d3', # ⇓ DOWNWARDS DOUBLE ARROW
'Updownarrow': u'\u21d5', # ⇕ UP DOWN DOUBLE ARROW
+ 'lmoustache': u'\u23b0', # ⎰ UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION
+ 'rmoustache': u'\u23b1', # ⎱ UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION
+ 'arrowvert': u'\u23d0', # ⏐ VERTICAL LINE EXTENSION
+ 'bracevert': u'\u23aa', # ⎪ CURLY BRACKET EXTENSION
}
stretchables.update(tex2unichar.mathfence)
stretchables.update(tex2unichar.mathopen)
@@ -195,9 +196,8 @@
stretchables.update(math_fences)
# >>> print(' '.join(sorted(set(stretchables.values()))))
-# [ \ ] { | } ‖ ↑ ↓ ↕ ⇑ ⇓ ⇕ ⌈ ⌉ ⌊ ⌋ ⌜ ⌝ ⌞ ⌟ ⟅ ⟆ ⟦ ⟧ ⟨ ⟩ ⟮ ⟯ ⦇ ⦈
+# [ \ ] { | } ‖ ↑ ↓ ↕ ⇑ ⇓ ⇕ ⌈ ⌉ ⌊ ⌋ ⌜ ⌝ ⌞ ⌟ ⎪ ⎰ ⎱ ⏐ ⟅ ⟆ ⟦ ⟧ ⟨ ⟩ ⟮ ⟯ ⦇ ⦈
-
# horizontal space -> <mspace>
spaces = {'qquad': '2em', # two \quad
@@ -216,7 +216,7 @@
'!': '-0.1667em', # negthinspace
}
-# accents -> <mover accent="true">
+# accents -> <mover accent="true"> # TODO: stretchy="false"
# TeX spacing combining
accents = {'acute': u'´', # u'\u0301',
'bar': u'ˉ', # u'\u0304',
@@ -225,6 +225,7 @@
'dot': u'˙', # u'\u0307',
'ddot': u'¨', # u'\u0308',
'dddot': u'\u20DB', # '…' too wide
+ # TODO: ddddot
'grave': u'`', # u'\u0300',
'hat': u'ˆ', # u'\u0302',
'mathring': u'˚', # u'\u030A',
@@ -358,6 +359,8 @@
return self.attributes[key]
def __setitem__(self, key, item):
self.attributes[key] = item
+ def get(self, *args, **kwargs):
+ return self.attributes.get(*args, **kwargs)
def full(self):
"""Return boolean indicating whether children may be appended."""
@@ -627,48 +630,104 @@
def tex_token(string):
"""Return first simple TeX token and remainder of `string`.
- >>> tex_token('{first simple group} returned without brackets')
- ('first simple group', ' returned without brackets')
>>> tex_token('\\command{without argument}')
('\\command', '{without argument}')
- >>> tex_token(' first non-white character')
- ('f', 'irst non-white character')
+ >>> tex_token('or first character')
+ ('o', 'r first character')
"""
- m = re.match(r"""\s* # leading whitespace
- {(?P<token>(\\}|[^{}]|\\{)*)} # {group} without nested groups
- (?P<remainder>.*$)
+ m = re.match(r"""((?P<cmd>\\[a-zA-Z]+)\s* # TeX command, skip whitespace
+ |(?P<chcmd>\\.) # one-character TeX command
+ |(?P<ch>.?)) # first character (or empty)
+ (?P<remainder>.*$) # remaining part of string
""", string, re.VERBOSE)
- if m is None:
- m = re.match(r"""\s* # leading whitespace
- (?P<token>\\([a-zA-Z]+))\s* # \cmdname
- (?P<remainder>.*$)
- """, string, re.VERBOSE)
- if m is None:
- m = re.match(r"""\s* # leading whitespace
- (?P<token>.?) # first character or empty string
- (?P<remainder>.*$)
- """, string, re.VERBOSE)
+ cmd, chcmd, ch, remainder = m.group('cmd', 'chcmd', 'ch', 'remainder')
+ return cmd or chcmd or ch, remainder
- return m.group('token'), m.group('remainder')
-
# Test:
#
-# >>> tex_token('{opening bracket of group with {nested group}}')
-# ('{', 'opening bracket of group with {nested group}}')
-# >>> tex_token('{group with \\{escaped\\} brackets}')
-# ('group with \\{escaped\\} brackets', '')
-# >>> tex_token('{group followed by closing bracket}} from outer group')
-# ('group followed by closing bracket', '} from outer group')
-# >>> tex_token(' {skip leading whitespace}')
-# ('skip leading whitespace', '')
-# >>> tex_token(' \\skip{leading whitespace}')
-# ('\\skip', '{leading whitespace}')
+# >>> tex_token('{opening bracket of group}')
+# ('{', 'opening bracket of group}')
# >>> tex_token('\\skip whitespace after macro name')
# ('\\skip', 'whitespace after macro name')
+# >>> tex_token('. but not after single char')
+# ('.', ' but not after single char')
# >>> tex_token('') # empty string.
# ('', '')
+# >>> tex_token('\{escaped bracket')
+# ('\\{', 'escaped bracket')
+def tex_group(string):
+ """Return first TeX group or token and remainder of `string`.
+
+ >>> tex_group('{first group} returned without brackets')
+ ('first group', ' returned without brackets')
+
+ """
+ split_index = 0
+ nest_level = 0 # level of {{nested} groups}
+ escape = False # the next character is escaped (\)
+
+ if not string.startswith('{'):
+ # special case: there is no group, return first token and remainder
+ return string[:1], string[1:]
+ for c in string:
+ split_index += 1
+ if escape:
+ escape = False
+ elif c == '\\':
+ escape = True
+ elif c == '{':
+ nest_level += 1
+ elif c == '}':
+ nest_level -= 1
+ if nest_level == 0:
+ break
+ else:
+ raise SyntaxError('Group without closing bracket')
+ return string[1:split_index-1], string[split_index:]
+
+
+
+# >>> tex_group('{} empty group')
+# ('', ' empty group')
+# >>> tex_group('{group with {nested} group} ')
+# ('group with {nested} group', ' ')
+# >>> tex_group('{group with {nested group}} at the end')
+# ('group with {nested group}', ' at the end')
+# >>> tex_group('{{group} {with {{complex }nesting}} constructs}')
+# ('{group} {with {{complex }nesting}} constructs', '')
+# >>> tex_group('{group with \\{escaped\\} brackets}')
+# ('group with \\{escaped\\} brackets', '')
+# >>> tex_group('{group followed by closing bracket}} from outer group')
+# ('group followed by closing bracket', '} from outer group')
+# >>> tex_group('No group? Return first character.')
+# ('N', 'o group? Return first character.')
+# >>> tex_group(' {also whitespace}')
+# (' ', '{also whitespace}')
+
+
+def tex_token_or_group(string):
+ """Return first TeX group or token and remainder of `string`.
+
+ >>> tex_token_or_group('\\command{without argument}')
+ ('\\command', '{without argument}')
+ >>> tex_token_or_group('first character')
+ ('f', 'irst character')
+ >>> tex_token_or_group(' also whitespace')
+ (' ', 'also whitespace')
+ >>> tex_token_or_group('{first group} keep rest')
+ ('first group', ' keep rest')
+
+ """
+ arg, remainder = tex_token(string)
+ if arg == '{':
+ arg, remainder = tex_group(string.lstrip())
+ return arg, remainder
+
+# >>> tex_token_or_group('\{no group but left bracket')
+# ('\\{', 'no group but left bracket')
+
def tex_optarg(string):
"""Return optional argument and remainder.
@@ -797,13 +856,13 @@
# identifier -> <mi>
if name in letters:
+ new_node = mi(letters[name])
if name in greek_capitals:
# upright in "TeX style" but MathML sets them italic ("ISO style").
# CSS styling does not change the font style in Firefox 78.
# Use 'mathvariant="normal"'?
- node = node.append(mi(greek_capitals[name], CLASS='capital-greek'))
- else:
- node = node.append(mi(letters[name]))
+ new_node['class'] = 'capital-greek'
+ node = node.append(new_node)
return node, string
if (name in functions):
@@ -812,7 +871,7 @@
if name == 'operatorname':
# custom function name, e.g. ``\operatorname{abs}(x)``
# TODO: \operatorname* -> with limits
- arg, string = tex_token(string)
+ arg, string = tex_token_or_group(string)
new_node = mi(arg, mathvariant='normal')
else:
new_node = mi(functions[name])
@@ -834,22 +893,22 @@
return node, string
if name in math_alphabets:
- arg, remainder = tex_token(string)
- if arg[0] == '\\':
+ if name == 'boldsymbol':
+ attributes = {'style': 'font-weight: bold'}
+ else:
+ attributes = {'mathvariant': math_alphabets[name]}
+ if name == 'mathscr':
+ attributes['class'] = 'mathscr'
+ # Check for single symbol (letter, name, or ⅀)
+ arg, remainder = tex_token_or_group(string)
+ if arg.startswith('\\'):
# convert single letters (so the isalpha() test below works).
+ # TODO: convert all LICRs in a group (\matrm{\mu\Omega})
arg = letters.get(arg[1:], arg)
if name == 'mathbb':
# mathvariant="double-struck" is ignored for Greek letters
# (tested in Firefox 78). Use literal Unicode characters.
arg = mathbb.get(arg, arg)
- if name == 'boldsymbol':
- attributes = {'style': 'font-weight: bold'}
- else:
- attributes = {'mathvariant': math_alphabets[name]}
- if name == 'mathscr':
- attributes['class'] = 'mathscr'
-
- # one symbol (single letter, name, or ⅀)
if arg.isalpha() or arg == u'\u2140':
node = node.append(mi(arg, **attributes))
return node, remainder
@@ -874,21 +933,26 @@
return node, string
if name in operators:
- node = node.append(mo(operators[name]))
+ if name in displaylimits and string and string[0] in ' _^':
+ node = node.append(mo(operators[name], movablelimits = 'true'))
+ else:
+ node = node.append(mo(operators[name]))
return node, string
if name in delimiter_sizes:
delimiter_attributes = {}
size = delimiter_sizes[name]
- delimiter, string = tex_token(string)
+ delimiter, string = tex_token_or_group(string)
if delimiter not in '()[]/|.':
try:
delimiter = stretchables[delimiter.lstrip('\\')]
except KeyError:
- raise SyntaxError(u'Missing "\\%s" delimiter!' % name)
+ raise SyntaxError(u'Unsupported "\\%s" delimiter "%s"!'
+ % (name, delimiter))
if size:
delimiter_attributes['maxsize'] = size
delimiter_attributes['minsize'] = size
+ delimiter_attributes['symmetric'] = 'true'
if name == 'left' or name.endswith('l'):
row = mrow()
node.append(row)
@@ -900,7 +964,7 @@
return node, string
if name == 'not':
- arg, string = tex_token(string)
+ arg, string = tex_token_or_group(string)
try:
node = node.append(mo(negatables[arg]))
except KeyError:
@@ -909,7 +973,7 @@
# arbitrary text (usually comments) -> <mtext>
if name in ('text', 'mbox', 'textrm'):
- arg, string = tex_token(string)
+ arg, string = tex_token_or_group(string)
parts = arg.split('$') # extract inline math
for i, part in enumerate(parts):
if i % 2 == 0: # i is even
@@ -924,8 +988,10 @@
node = node.append(mspace(width='%s'%spaces[name]))
return node, string
- if na...
[truncated message content] |
|
From: <mi...@us...> - 2021-06-17 09:58:57
|
Revision: 8761
http://sourceforge.net/p/docutils/code/8761
Author: milde
Date: 2021-06-17 09:58:56 +0000 (Thu, 17 Jun 2021)
Log Message:
-----------
math: update latex <-> unicode mappings.
Re-generate mappings from the database "unimathsymbols.txt".
Modified Paths:
--------------
trunk/docutils/docs/ref/rst/mathematics.txt
trunk/docutils/docutils/utils/math/tex2unichar.py
trunk/docutils/docutils/utils/math/unichar2tex.py
Modified: trunk/docutils/docs/ref/rst/mathematics.txt
===================================================================
--- trunk/docutils/docs/ref/rst/mathematics.txt 2021-06-17 09:58:31 UTC (rev 8760)
+++ trunk/docutils/docs/ref/rst/mathematics.txt 2021-06-17 09:58:56 UTC (rev 8761)
@@ -262,10 +262,6 @@
Greek letters
-------------
-In LaTeX, the default font for capital Greek letters is upright/roman.
-*Italic* capital Greek letters can be obtained by loading a `package
-providing the "ISO" math style`__. They are used by default in MathML.
-
Greek letters that have Latin look-alikes are rarely used in math
formulas and not supported by LaTeX.
@@ -285,8 +281,19 @@
`\Omega` ``\Omega`` `\lambda` ``\lambda`` `\psi` ``\psi``
========== ============ ========== ============ ========== ============ ============== ===============
+In LaTeX, the default font for capital Greek letters is upright/roman.
+*Italic* capital Greek letters can be obtained by loading a `package
+providing the "ISO" math style`__. They are used by default in MathML.
+
+Individual Greek italic capitals can also be achieved preceding the
+letter name with ``var`` like ``\varPhi``:
+`\varGamma\ \varDelta\ \varLambda\ \varPhi\ \varPi\ \varPsi\ \varSigma\
+\varTheta\ \varUpsilon\ \varXi\ \varOmega`
+
+
__ http://mirrors.ctan.org/macros/latex/contrib/isomath/isomath.html#table-2
+
Letterlike symbols
------------------
.. class:: colwidths-auto
@@ -481,9 +488,9 @@
The commands ``\lvertneqq`` and ``\gvertneqq`` are not supported by
LateX2MathML, as there is no corresponding Unicode character.
-Synonyms: `\ne` ``\ne``, `\le` ``\le``, `\ge` ``\ge``, `\Doteq`
-``\Doteq``, `\llless` ``\llless``, `\gggtr` ``\gggtr``,
-`\not =` ``\not =``, `\not \equiv` ``\not \equiv``.
+Synonyms: `\ne` ``\ne``, `\le` ``\le``, `\ge` ``\ge``,
+`\Doteq` ``\Doteq``, `\llless` ``\llless``, `\gggtr` ``\gggtr``,
+`\not=` ``\not=``, `\not\equiv` ``\not\equiv``.
Miscellaneous relations
@@ -974,4 +981,3 @@
\quad
\left.\vert \frac{b}{a}\right\Vert\ \bigl\vert b\Bigr\Vert\ \biggl\vert b\Biggr\Vert
\quad
-
Modified: trunk/docutils/docutils/utils/math/tex2unichar.py
===================================================================
--- trunk/docutils/docutils/utils/math/tex2unichar.py 2021-06-17 09:58:31 UTC (rev 8760)
+++ trunk/docutils/docutils/utils/math/tex2unichar.py 2021-06-17 09:58:56 UTC (rev 8761)
@@ -4,7 +4,7 @@
# Generated with ``write_tex2unichar.py`` from the data in
# http://milde.users.sourceforge.net/LUCR/Math/
-# Includes commands from: wasysym, stmaryrd, mathdots, mathabx, esint, bbold, amsxtra, amsmath, amssymb, standard LaTeX
+# Includes commands from: wasysym, stmaryrd, txfonts, mathdots, mathabx, esint, bbold, amsxtra, amsmath, amssymb, standard LaTeX
mathaccent = {
'acute': u'\u0301', # ́ COMBINING ACUTE ACCENT
@@ -11,8 +11,8 @@
'bar': u'\u0304', # ̄ COMBINING MACRON
'breve': u'\u0306', # ̆ COMBINING BREVE
'check': u'\u030c', # ̌ COMBINING CARON
- 'ddddot': u'\u20dc', # x⃜ COMBINING FOUR DOTS ABOVE
- 'dddot': u'\u20db', # x⃛ COMBINING THREE DOTS ABOVE
+ 'ddddot': u'\u20dc', # ⃜ COMBINING FOUR DOTS ABOVE
+ 'dddot': u'\u20db', # ⃛ COMBINING THREE DOTS ABOVE
'ddot': u'\u0308', # ̈ COMBINING DIAERESIS
'dot': u'\u0307', # ̇ COMBINING DOT ABOVE
'grave': u'\u0300', # ̀ COMBINING GRAVE ACCENT
@@ -19,18 +19,16 @@
'hat': u'\u0302', # ̂ COMBINING CIRCUMFLEX ACCENT
'mathring': u'\u030a', # ̊ COMBINING RING ABOVE
'not': u'\u0338', # ̸ COMBINING LONG SOLIDUS OVERLAY
- 'overleftarrow': u'\u20d6', # x⃖ COMBINING LEFT ARROW ABOVE
- 'overleftrightarrow': u'\u20e1', # x⃡ COMBINING LEFT RIGHT ARROW ABOVE
+ 'overleftarrow': u'\u20d6', # ⃖ COMBINING LEFT ARROW ABOVE
+ 'overleftrightarrow': u'\u20e1', # ⃡ COMBINING LEFT RIGHT ARROW ABOVE
'overline': u'\u0305', # ̅ COMBINING OVERLINE
- 'overrightarrow': u'\u20d7', # x⃗ COMBINING RIGHT ARROW ABOVE
+ 'overrightarrow': u'\u20d7', # ⃗ COMBINING RIGHT ARROW ABOVE
'tilde': u'\u0303', # ̃ COMBINING TILDE
'underbar': u'\u0331', # ̱ COMBINING MACRON BELOW
- 'underleftarrow': u'\u20ee', # x⃮ COMBINING LEFT ARROW BELOW
+ 'underleftarrow': u'\u20ee', # ⃮ COMBINING LEFT ARROW BELOW
'underline': u'\u0332', # ̲ COMBINING LOW LINE
- 'underrightarrow': u'\u20ef', # x⃯ COMBINING RIGHT ARROW BELOW
- 'vec': u'\u20d7', # x⃗ COMBINING RIGHT ARROW ABOVE
- 'widehat': u'\u0302', # ̂ COMBINING CIRCUMFLEX ACCENT
- 'widetilde': u'\u0303', # ̃ COMBINING TILDE
+ 'underrightarrow': u'\u20ef', # ⃯ COMBINING RIGHT ARROW BELOW
+ 'vec': u'\u20d7', # ⃗ COMBINING RIGHT ARROW ABOVE
}
mathalpha = {
'Bbbk': u'\U0001d55c', # 𝕜 MATHEMATICAL DOUBLE-STRUCK SMALL K
@@ -115,10 +113,8 @@
'bigtriangleup': u'\u25b3', # △ WHITE UP-POINTING TRIANGLE
'bindnasrepma': u'\u214b', # ⅋ TURNED AMPERSAND
'blacklozenge': u'\u29eb', # ⧫ BLACK LOZENGE
- 'blacktriangle': u'\u25b4', # ▴ BLACK UP-POINTING SMALL TRIANGLE
- 'blacktriangledown': u'\u25be', # ▾ BLACK DOWN-POINTING SMALL TRIANGLE
- 'blacktriangleleft': u'\u25c2', # ◂ BLACK LEFT-POINTING SMALL TRIANGLE
- 'blacktriangleright': u'\u25b8', # ▸ BLACK RIGHT-POINTING SMALL TRIANGLE
+ 'blacktriangleleft': u'\u25c0', # ◀ BLACK LEFT-POINTING TRIANGLE
+ 'blacktriangleright': u'\u25b6', # ▶ BLACK RIGHT-POINTING TRIANGLE
'blacktriangleup': u'\u25b4', # ▴ BLACK UP-POINTING SMALL TRIANGLE
'boxast': u'\u29c6', # ⧆ SQUARED ASTERISK
'boxbar': u'\u25eb', # ◫ WHITE SQUARE WITH VERTICAL BISECTING LINE
@@ -135,8 +131,11 @@
'cdot': u'\u22c5', # ⋅ DOT OPERATOR
'circ': u'\u2218', # ∘ RING OPERATOR
'circledast': u'\u229b', # ⊛ CIRCLED ASTERISK OPERATOR
+ 'circledbslash': u'\u29b8', # ⦸ CIRCLED REVERSE SOLIDUS
'circledcirc': u'\u229a', # ⊚ CIRCLED RING OPERATOR
'circleddash': u'\u229d', # ⊝ CIRCLED DASH
+ 'circledgtr': u'\u29c1', # ⧁ CIRCLED GREATER-THAN
+ 'circledless': u'\u29c0', # ⧀ CIRCLED LESS-THAN
'cup': u'\u222a', # ∪ UNION
'curlyvee': u'\u22ce', # ⋎ CURLY LOGICAL OR
'curlywedge': u'\u22cf', # ⋏ CURLY LOGICAL AND
@@ -145,13 +144,14 @@
'diamond': u'\u22c4', # ⋄ DIAMOND OPERATOR
'div': u'\xf7', # ÷ DIVISION SIGN
'divideontimes': u'\u22c7', # ⋇ DIVISION TIMES
+ 'dotdiv': u'\u2238', # ∸ DOT MINUS
'dotplus': u'\u2214', # ∔ DOT PLUS
'doublebarwedge': u'\u2a5e', # ⩞ LOGICAL AND WITH DOUBLE OVERBAR
'intercal': u'\u22ba', # ⊺ INTERCALATE
'interleave': u'\u2af4', # ⫴ TRIPLE VERTICAL BAR BINARY RELATION
+ 'invamp': u'\u214b', # ⅋ TURNED AMPERSAND
'land': u'\u2227', # ∧ LOGICAL AND
'leftthreetimes': u'\u22cb', # ⋋ LEFT SEMIDIRECT PRODUCT
- 'lhd': u'\u25c1', # ◁ WHITE LEFT-POINTING TRIANGLE
'lor': u'\u2228', # ∨ LOGICAL OR
'ltimes': u'\u22c9', # ⋉ LEFT NORMAL FACTOR SEMIDIRECT PRODUCT
'mp': u'\u2213', # ∓ MINUS-OR-PLUS SIGN
@@ -161,7 +161,6 @@
'oslash': u'\u2298', # ⊘ CIRCLED DIVISION SLASH
'otimes': u'\u2297', # ⊗ CIRCLED TIMES
'pm': u'\xb1', # ± PLUS-MINUS SIGN
- 'rhd': u'\u25b7', # ▷ WHITE RIGHT-POINTING TRIANGLE
'rightthreetimes': u'\u22cc', # ⋌ RIGHT SEMIDIRECT PRODUCT
'rtimes': u'\u22ca', # ⋊ RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT
'setminus': u'\u29f5', # ⧵ REVERSE SOLIDUS OPERATOR
@@ -178,10 +177,11 @@
'talloblong': u'\u2afe', # ⫾ WHITE VERTICAL BAR
'times': u'\xd7', # × MULTIPLICATION SIGN
'triangle': u'\u25b3', # △ WHITE UP-POINTING TRIANGLE
- 'triangledown': u'\u25bf', # ▿ WHITE DOWN-POINTING SMALL TRIANGLE
- 'triangleleft': u'\u25c3', # ◃ WHITE LEFT-POINTING SMALL TRIANGLE
- 'triangleright': u'\u25b9', # ▹ WHITE RIGHT-POINTING SMALL TRIANGLE
+ 'triangledown': u'\u25bd', # ▽ WHITE DOWN-POINTING TRIANGLE
+ 'triangleleft': u'\u25c1', # ◁ WHITE LEFT-POINTING TRIANGLE
+ 'triangleright': u'\u25b7', # ▷ WHITE RIGHT-POINTING TRIANGLE
'uplus': u'\u228e', # ⊎ MULTISET UNION
+ 'varparallel': u'\u2afd', # ⫽ DOUBLE SOLIDUS OPERATOR
'vartriangle': u'\u25b3', # △ WHITE UP-POINTING TRIANGLE
'vee': u'\u2228', # ∨ LOGICAL OR
'veebar': u'\u22bb', # ⊻ XOR
@@ -209,7 +209,6 @@
'|': u'\u2016', # ‖ DOUBLE VERTICAL LINE
}
mathop = {
- 'Join': u'\u2a1d', # ⨝ JOIN
'bigcap': u'\u22c2', # ⋂ N-ARY INTERSECTION
'bigcup': u'\u22c3', # ⋃ N-ARY UNION
'biginterleave': u'\u2afc', # ⫼ LARGE TRIPLE VERTICAL BAR OPERATOR
@@ -216,6 +215,7 @@
'bigodot': u'\u2a00', # ⨀ N-ARY CIRCLED DOT OPERATOR
'bigoplus': u'\u2a01', # ⨁ N-ARY CIRCLED PLUS OPERATOR
'bigotimes': u'\u2a02', # ⨂ N-ARY CIRCLED TIMES OPERATOR
+ 'bigsqcap': u'\u2a05', # ⨅ N-ARY SQUARE INTERSECTION OPERATOR
'bigsqcup': u'\u2a06', # ⨆ N-ARY SQUARE UNION OPERATOR
'biguplus': u'\u2a04', # ⨄ N-ARY UNION OPERATOR WITH PLUS
'bigvee': u'\u22c1', # ⋁ N-ARY LOGICAL OR
@@ -228,6 +228,7 @@
'iint': u'\u222c', # ∬ DOUBLE INTEGRAL
'int': u'\u222b', # ∫ INTEGRAL
'intop': u'\u222b', # ∫ INTEGRAL
+ 'oiiint': u'\u2230', # ∰ VOLUME INTEGRAL
'oiint': u'\u222f', # ∯ SURFACE INTEGRAL
'oint': u'\u222e', # ∮ CONTOUR INTEGRAL
'ointctrclockwise': u'\u2233', # ∳ ANTICLOCKWISE CONTOUR INTEGRAL
@@ -236,6 +237,7 @@
'sqint': u'\u2a16', # ⨖ QUATERNION INTEGRAL OPERATOR
'sum': u'\u2211', # ∑ N-ARY SUMMATION
'varointclockwise': u'\u2232', # ∲ CLOCKWISE CONTOUR INTEGRAL
+ 'varprod': u'\u2a09', # ⨉ N-ARY TIMES OPERATOR
}
mathopen = {
'Lbag': u'\u27c5', # ⟅ LEFT S-SHAPED BAG DELIMITER
@@ -267,9 +269,12 @@
'APLrightarrowbox': u'\u2348', # ⍈ APL FUNCTIONAL SYMBOL QUAD RIGHTWARDS ARROW
'APLuparrowbox': u'\u2350', # ⍐ APL FUNCTIONAL SYMBOL QUAD UPWARDS ARROW
'Aries': u'\u2648', # ♈ ARIES
+ 'Box': u'\u2b1c', # ⬜ WHITE LARGE SQUARE
'CIRCLE': u'\u25cf', # ● BLACK CIRCLE
'CheckedBox': u'\u2611', # ☑ BALLOT BOX WITH CHECK
'Diamond': u'\u25c7', # ◇ WHITE DIAMOND
+ 'Diamondblack': u'\u25c6', # ◆ BLACK DIAMOND
+ 'Diamonddot': u'\u27d0', # ⟐ WHITE DIAMOND WITH CENTRED DOT
'Finv': u'\u2132', # Ⅎ TURNED CAPITAL F
'Game': u'\u2141', # ⅁ TURNED SANS-SERIF CAPITAL G
'Gemini': u'\u264a', # ♊ GEMINI
@@ -281,9 +286,11 @@
'Mars': u'\u2642', # ♂ MALE SIGN
'Mercury': u'\u263f', # ☿ MERCURY
'Neptune': u'\u2646', # ♆ NEPTUNE
+ 'P': u'\xb6', # ¶ PILCROW SIGN
'Pluto': u'\u2647', # ♇ PLUTO
'RIGHTCIRCLE': u'\u25d7', # ◗ RIGHT HALF BLACK CIRCLE
'RIGHTcircle': u'\u25d1', # ◑ CIRCLE WITH RIGHT HALF BLACK
+ 'S': u'\xa7', # § SECTION SIGN
'Saturn': u'\u2644', # ♄ SATURN
'Scorpio': u'\u264f', # ♏ SCORPIUS
'Square': u'\u2610', # ☐ BALLOT BOX
@@ -308,6 +315,8 @@
'blacklozenge': u'\u2b27', # ⬧ BLACK MEDIUM LOZENGE
'blacksmiley': u'\u263b', # ☻ BLACK SMILING FACE
'blacksquare': u'\u25fc', # ◼ BLACK MEDIUM SQUARE
+ 'blacktriangle': u'\u25b2', # ▲ BLACK UP-POINTING TRIANGLE
+ 'blacktriangledown': u'\u25bc', # ▼ BLACK DOWN-POINTING TRIANGLE
'bot': u'\u22a5', # ⊥ UP TACK
'boy': u'\u2642', # ♂ MALE SIGN
'bracevert': u'\u23aa', # ⎪ CURLY BRACKET EXTENSION
@@ -324,11 +333,8 @@
'circledcirc': u'\u25ce', # ◎ BULLSEYE
'clubsuit': u'\u2663', # ♣ BLACK CLUB SUIT
'complement': u'\u2201', # ∁ COMPLEMENT
- 'dasharrow': u'\u21e2', # ⇢ RIGHTWARDS DASHED ARROW
- 'dashleftarrow': u'\u21e0', # ⇠ LEFTWARDS DASHED ARROW
- 'dashrightarrow': u'\u21e2', # ⇢ RIGHTWARDS DASHED ARROW
- 'diagdown': u'\u27cd', # ⟍
- 'diagup': u'\u27cb', # ⟋
+ 'diagdown': u'\u27cd', # ⟍ MATHEMATICAL FALLING DIAGONAL
+ 'diagup': u'\u27cb', # ⟋ MATHEMATICAL RISING DIAGONAL
'diameter': u'\u2300', # ⌀ DIAMETER SIGN
'diamondsuit': u'\u2662', # ♢ WHITE DIAMOND SUIT
'earth': u'\u2641', # ♁ EARTH
@@ -356,8 +362,12 @@
'lozenge': u'\u25ca', # ◊ LOZENGE
'male': u'\u2642', # ♂ MALE SIGN
'maltese': u'\u2720', # ✠ MALTESE CROSS
+ 'mathcent': u'\xa2', # ¢ CENT SIGN
'mathdollar': u'$', # $ DOLLAR SIGN
+ 'mathsterling': u'\xa3', # £ POUND SIGN
'measuredangle': u'\u2221', # ∡ MEASURED ANGLE
+ 'medbullet': u'\u26ab', # ⚫ MEDIUM BLACK CIRCLE
+ 'medcirc': u'\u26aa', # ⚪ MEDIUM WHITE CIRCLE
'mercury': u'\u263f', # ☿ MERCURY
'mho': u'\u2127', # ℧ INVERTED OHM SIGN
'nabla': u'\u2207', # ∇ NABLA
@@ -380,7 +390,6 @@
'scorpio': u'\u264f', # ♏ SCORPIUS
'second': u'\u2033', # ″ DOUBLE PRIME
'sharp': u'\u266f', # ♯ MUSIC SHARP SIGN
- 'sim': u'~', # ~ TILDE
'slash': u'/', # / SOLIDUS
'smiley': u'\u263a', # ☺ WHITE SMILING FACE
'spadesuit': u'\u2660', # ♠ BLACK SPADE SUIT
@@ -392,7 +401,6 @@
'sun': u'\u263c', # ☼ WHITE SUN WITH RAYS
'surd': u'\u221a', # √ SQUARE ROOT
'taurus': u'\u2649', # ♉ TAURUS
- 'textregistered': u'\u24c7', # Ⓡ CIRCLED LATIN CAPITAL LETTER R
'therefore': u'\u2234', # ∴ THEREFORE
'third': u'\u2034', # ‴ TRIPLE PRIME
'top': u'\u22a4', # ⊤ DOWN TACK
@@ -401,7 +409,12 @@
'twonotes': u'\u266b', # ♫ BEAMED EIGHTH NOTES
'uranus': u'\u2645', # ♅ URANUS
'varEarth': u'\u2641', # ♁ EARTH
+ 'varclubsuit': u'\u2667', # ♧ WHITE CLUB SUIT
+ 'vardiamondsuit': u'\u2666', # ♦ BLACK DIAMOND SUIT
+ 'varheartsuit': u'\u2665', # ♥ BLACK HEART SUIT
'varnothing': u'\u2300', # ⌀ DIAMETER SIGN
+ 'varspadesuit': u'\u2664', # ♤ WHITE SPADE SUIT
+ 'vdots': u'\u22ee', # ⋮ VERTICAL ELLIPSIS
'virgo': u'\u264d', # ♍ VIRGO
'wasylozenge': u'\u2311', # ⌑ SQUARE LOZENGE
'wasytherefore': u'\u2234', # ∴ THEREFORE
@@ -416,7 +429,9 @@
'sqrt[4]': u'\u221c', # ∜ FOURTH ROOT
}
mathrel = {
+ 'Bot': u'\u2aeb', # ⫫ DOUBLE UP TACK
'Bumpeq': u'\u224e', # ≎ GEOMETRICALLY EQUIVALENT TO
+ 'Coloneqq': u'\u2a74', # ⩴ DOUBLE COLON EQUAL
'Doteq': u'\u2251', # ≑ GEOMETRICALLY EQUAL TO
'Downarrow': u'\u21d3', # ⇓ DOWNWARDS DOUBLE ARROW
'Leftarrow': u'\u21d0', # ⇐ LEFTWARDS DOUBLE ARROW
@@ -430,11 +445,17 @@
'Lsh': u'\u21b0', # ↰ UPWARDS ARROW WITH TIP LEFTWARDS
'Mapsfrom': u'\u2906', # ⤆ LEFTWARDS DOUBLE ARROW FROM BAR
'Mapsto': u'\u2907', # ⤇ RIGHTWARDS DOUBLE ARROW FROM BAR
+ 'Nearrow': u'\u21d7', # ⇗ NORTH EAST DOUBLE ARROW
+ 'Nwarrow': u'\u21d6', # ⇖ NORTH WEST DOUBLE ARROW
+ 'Perp': u'\u2aeb', # ⫫ DOUBLE UP TACK
'Rightarrow': u'\u21d2', # ⇒ RIGHTWARDS DOUBLE ARROW
'Rrightarrow': u'\u21db', # ⇛ RIGHTWARDS TRIPLE ARROW
'Rsh': u'\u21b1', # ↱ UPWARDS ARROW WITH TIP RIGHTWARDS
+ 'Searrow': u'\u21d8', # ⇘ SOUTH EAST DOUBLE ARROW
'Subset': u'\u22d0', # ⋐ DOUBLE SUBSET
'Supset': u'\u22d1', # ⋑ DOUBLE SUPERSET
+ 'Swarrow': u'\u21d9', # ⇙ SOUTH WEST DOUBLE ARROW
+ 'Top': u'\u2aea', # ⫪ DOUBLE DOWN TACK
'Uparrow': u'\u21d1', # ⇑ UPWARDS DOUBLE ARROW
'Updownarrow': u'\u21d5', # ⇕ UP DOWN DOUBLE ARROW
'VDash': u'\u22ab', # ⊫ DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
@@ -455,6 +476,7 @@
'bumpeq': u'\u224f', # ≏ DIFFERENCE BETWEEN
'circeq': u'\u2257', # ≗ RING EQUAL TO
'coloneq': u'\u2254', # ≔ COLON EQUALS
+ 'coloneqq': u'\u2254', # ≔ COLON EQUALS
'cong': u'\u2245', # ≅ APPROXIMATELY EQUAL TO
'corresponds': u'\u2259', # ≙ ESTIMATES
'curlyeqprec': u'\u22de', # ⋞ EQUAL TO OR PRECEDES
@@ -461,6 +483,9 @@
'curlyeqsucc': u'\u22df', # ⋟ EQUAL TO OR SUCCEEDS
'curvearrowleft': u'\u21b6', # ↶ ANTICLOCKWISE TOP SEMICIRCLE ARROW
'curvearrowright': u'\u21b7', # ↷ CLOCKWISE TOP SEMICIRCLE ARROW
+ 'dasharrow': u'\u21e2', # ⇢ RIGHTWARDS DASHED ARROW
+ 'dashleftarrow': u'\u21e0', # ⇠ LEFTWARDS DASHED ARROW
+ 'dashrightarrow': u'\u21e2', # ⇢ RIGHTWARDS DASHED ARROW
'dashv': u'\u22a3', # ⊣ LEFT TACK
'ddots': u'\u22f1', # ⋱ DOWN RIGHT DIAGONAL ELLIPSIS
'dlsh': u'\u21b2', # ↲ DOWNWARDS ARROW WITH TIP LEFTWARDS
@@ -476,6 +501,7 @@
'drsh': u'\u21b3', # ↳ DOWNWARDS ARROW WITH TIP RIGHTWARDS
'eqcirc': u'\u2256', # ≖ RING IN EQUAL TO
'eqcolon': u'\u2255', # ≕ EQUALS COLON
+ 'eqqcolon': u'\u2255', # ≕ EQUALS COLON
'eqsim': u'\u2242', # ≂ MINUS TILDE
'eqslantgtr': u'\u2a96', # ⪖ SLANTED EQUAL TO OR GREATER-THAN
'eqslantless': u'\u2a95', # ⪕ SLANTED EQUAL TO OR LESS-THAN
@@ -509,6 +535,7 @@
'implies': u'\u27f9', # ⟹ LONG RIGHTWARDS DOUBLE ARROW
'in': u'\u2208', # ∈ ELEMENT OF
'le': u'\u2264', # ≤ LESS-THAN OR EQUAL TO
+ 'leadsto': u'\u2933', # ⤳ WAVE ARROW POINTING DIRECTLY RIGHT
'leftarrow': u'\u2190', # ← LEFTWARDS ARROW
'leftarrowtail': u'\u21a2', # ↢ LEFTWARDS ARROW WITH TAIL
'leftarrowtriangle': u'\u21fd', # ⇽ LEFTWARDS OPEN-HEADED ARROW
@@ -534,6 +561,7 @@
'lesseqqgtr': u'\u2a8b', # ⪋ LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN
'lessgtr': u'\u2276', # ≶ LESS-THAN OR GREATER-THAN
'lesssim': u'\u2272', # ≲ LESS-THAN OR EQUIVALENT TO
+ 'lhd': u'\u22b2', # ⊲ NORMAL SUBGROUP OF
'lightning': u'\u21af', # ↯ DOWNWARDS ZIGZAG ARROW
'll': u'\u226a', # ≪ MUCH LESS-THAN
'llcurly': u'\u2abb', # ⪻ DOUBLE PRECEDES
@@ -550,11 +578,16 @@
'longrightarrow': u'\u27f6', # ⟶ LONG RIGHTWARDS ARROW
'looparrowleft': u'\u21ab', # ↫ LEFTWARDS ARROW WITH LOOP
'looparrowright': u'\u21ac', # ↬ RIGHTWARDS ARROW WITH LOOP
+ 'lrtimes': u'\u22c8', # ⋈ BOWTIE
'mapsfrom': u'\u21a4', # ↤ LEFTWARDS ARROW FROM BAR
'mapsto': u'\u21a6', # ↦ RIGHTWARDS ARROW FROM BAR
'mid': u'\u2223', # ∣ DIVIDES
'models': u'\u22a7', # ⊧ MODELS
'multimap': u'\u22b8', # ⊸ MULTIMAP
+ 'multimapboth': u'\u29df', # ⧟ DOUBLE-ENDED MULTIMAP
+ 'multimapdotbothA': u'\u22b6', # ⊶ ORIGINAL OF
+ 'multimapdotbothB': u'\u22b7', # ⊷ IMAGE OF
+ 'multimapinv': u'\u27dc', # ⟜ LEFT MULTIMAP
'nLeftarrow': u'\u21cd', # ⇍ LEFTWARDS DOUBLE ARROW WITH STROKE
'nLeftrightarrow': u'\u21ce', # ⇎ LEFT RIGHT DOUBLE ARROW WITH STROKE
'nRightarrow': u'\u21cf', # ⇏ RIGHTWARDS DOUBLE ARROW WITH STROKE
@@ -574,6 +607,7 @@
'nmid': u'\u2224', # ∤ DOES NOT DIVIDE
'notasymp': u'\u226d', # ≭ NOT EQUIVALENT TO
'notin': u'\u2209', # ∉ NOT AN ELEMENT OF
+ 'notni': u'\u220c', # ∌ DOES NOT CONTAIN AS MEMBER
'notowner': u'\u220c', # ∌ DOES NOT CONTAIN AS MEMBER
'notslash': u'\u233f', # ⌿ APL FUNCTIONAL SYMBOL SLASH BAR
'nparallel': u'\u2226', # ∦ NOT PARALLEL TO
@@ -581,6 +615,7 @@
'npreceq': u'\u22e0', # ⋠ DOES NOT PRECEDE OR EQUAL
'nrightarrow': u'\u219b', # ↛ RIGHTWARDS ARROW WITH STROKE
'nsim': u'\u2241', # ≁ NOT TILDE
+ 'nsimeq': u'\u2244', # ≄ NOT ASYMPTOTICALLY EQUAL TO
'nsubseteq': u'\u2288', # ⊈ NEITHER A SUBSET OF NOR EQUAL TO
'nsucc': u'\u2281', # ⊁ DOES NOT SUCCEED
'nsucceq': u'\u22e1', # ⋡ DOES NOT SUCCEED OR EQUAL
@@ -600,6 +635,7 @@
'precapprox': u'\u2ab7', # ⪷ PRECEDES ABOVE ALMOST EQUAL TO
'preccurlyeq': u'\u227c', # ≼ PRECEDES OR EQUAL TO
'preceq': u'\u2aaf', # ⪯ PRECEDES ABOVE SINGLE-LINE EQUALS SIGN
+ 'preceqq': u'\u2ab3', # ⪳ PRECEDES ABOVE EQUALS SIGN
'precnapprox': u'\u2ab9', # ⪹ PRECEDES ABOVE NOT ALMOST EQUAL TO
'precneqq': u'\u2ab5', # ⪵ PRECEDES ABOVE NOT EQUAL TO
'precnsim': u'\u22e8', # ⋨ PRECEDES BUT NOT EQUIVALENT TO
@@ -606,6 +642,7 @@
'precsim': u'\u227e', # ≾ PRECEDES OR EQUIVALENT TO
'propto': u'\u221d', # ∝ PROPORTIONAL TO
'restriction': u'\u21be', # ↾ UPWARDS HARPOON WITH BARB RIGHTWARDS
+ 'rhd': u'\u22b3', # ⊳ CONTAINS AS NORMAL SUBGROUP
'rightarrow': u'\u2192', # → RIGHTWARDS ARROW
'rightarrowtail': u'\u21a3', # ↣ RIGHTWARDS ARROW WITH TAIL
'rightarrowtriangle': u'\u21fe', # ⇾ RIGHTWARDS OPEN-HEADED ARROW
@@ -628,6 +665,8 @@
'sqsubseteq': u'\u2291', # ⊑ SQUARE IMAGE OF OR EQUAL TO
'sqsupset': u'\u2290', # ⊐ SQUARE ORIGINAL OF
'sqsupseteq': u'\u2292', # ⊒ SQUARE ORIGINAL OF OR EQUAL TO
+ 'strictfi': u'\u297c', # ⥼ LEFT FISH TAIL
+ 'strictif': u'\u297d', # ⥽ RIGHT FISH TAIL
'subset': u'\u2282', # ⊂ SUBSET OF
'subseteq': u'\u2286', # ⊆ SUBSET OF OR EQUAL TO
'subseteqq': u'\u2ac5', # ⫅ SUBSET OF ABOVE EQUALS SIGN
@@ -637,6 +676,7 @@
'succapprox': u'\u2ab8', # ⪸ SUCCEEDS ABOVE ALMOST EQUAL TO
'succcurlyeq': u'\u227d', # ≽ SUCCEEDS OR EQUAL TO
'succeq': u'\u2ab0', # ⪰ SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN
+ 'succeqq': u'\u2ab4', # ⪴ SUCCEEDS ABOVE EQUALS SIGN
'succnapprox': u'\u2aba', # ⪺ SUCCEEDS ABOVE NOT ALMOST EQUAL TO
'succneqq': u'\u2ab6', # ⪶ SUCCEEDS ABOVE NOT EQUAL TO
'succnsim': u'\u22e9', # ⋩ SUCCEEDS BUT NOT EQUIVALENT TO
@@ -666,13 +706,17 @@
'vartriangleleft': u'\u22b2', # ⊲ NORMAL SUBGROUP OF
'vartriangleright': u'\u22b3', # ⊳ CONTAINS AS NORMAL SUBGROUP
'vdash': u'\u22a2', # ⊢ RIGHT TACK
- 'vdots': u'\u22ee', # ⋮ VERTICAL ELLIPSIS
}
mathunder = {
'underbrace': u'\u23df', # ⏟ BOTTOM CURLY BRACKET
}
space = {
+ ' ': u' ', # SPACE
+ ',': u'\u2006', # SIX-PER-EM SPACE
':': u'\u205f', # MEDIUM MATHEMATICAL SPACE
+ ';': u'\u2004', # THREE-PER-EM SPACE
'medspace': u'\u205f', # MEDIUM MATHEMATICAL SPACE
- 'quad': u'\u2001', # EM QUAD
+ 'quad': u'\u2003', # EM SPACE
+ 'thickspace': u'\u2004', # THREE-PER-EM SPACE
+ 'thinspace': u'\u2006', # SIX-PER-EM SPACE
}
Modified: trunk/docutils/docutils/utils/math/unichar2tex.py
===================================================================
--- trunk/docutils/docutils/utils/math/unichar2tex.py 2021-06-17 09:58:31 UTC (rev 8760)
+++ trunk/docutils/docutils/utils/math/unichar2tex.py 2021-06-17 09:58:56 UTC (rev 8761)
@@ -9,8 +9,10 @@
160: u'~',
163: u'\\pounds ',
165: u'\\yen ',
+167: u'\\S ',
172: u'\\neg ',
177: u'\\pm ',
+182: u'\\P ',
215: u'\\times ',
240: u'\\eth ',
247: u'\\div ',
@@ -60,6 +62,8 @@
1013: u'\\epsilon ',
1014: u'\\backepsilon ',
8193: u'\\quad ',
+8195: u'\\quad ',
+8198: u'\\, ',
8214: u'\\| ',
8224: u'\\dagger ',
8225: u'\\ddagger ',
@@ -346,15 +350,20 @@
8991: u'\\lrcorner ',
8994: u'\\frown ',
8995: u'\\smile ',
+9130: u'\\bracevert ',
+9136: u'\\lmoustache ',
+9137: u'\\rmoustache ',
+9168: u'\\arrowvert ',
9182: u'\\overbrace ',
9183: u'\\underbrace ',
9415: u'\\circledR ',
9416: u'\\circledS ',
+9650: u'\\blacktriangle ',
9651: u'\\bigtriangleup ',
-9652: u'\\blacktriangle ',
-9655: u'\\rhd ',
+9655: u'\\triangleright ',
+9660: u'\\blacktriangledown ',
9661: u'\\bigtriangledown ',
-9665: u'\\lhd ',
+9665: u'\\triangleleft ',
9671: u'\\Diamond ',
9674: u'\\lozenge ',
9711: u'\\bigcirc ',
@@ -392,7 +401,6 @@
10756: u'\\biguplus ',
10758: u'\\bigsqcup ',
10764: u'\\iiiint ',
-10781: u'\\Join ',
10815: u'\\amalg ',
10846: u'\\doublebarwedge ',
10877: u'\\leqslant ',
@@ -419,6 +427,7 @@
10950: u'\\supseteqq ',
10955: u'\\subsetneqq ',
10956: u'\\supsetneqq ',
+11036: u'\\Box ',
119808: u'\\mathbf{A}',
119809: u'\\mathbf{B}',
119810: u'\\mathbf{C}',
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2021-06-17 09:59:22
|
Revision: 8763
http://sourceforge.net/p/docutils/code/8763
Author: milde
Date: 2021-06-17 09:59:21 +0000 (Thu, 17 Jun 2021)
Log Message:
-----------
MathML: Refactor negating with ``\not``, simplify code.
Reorganise character data.
Allow all operators to be negated by preceding ``\not``.
Use Unicode normalization to get available pre-composed characters.
Modified Paths:
--------------
trunk/docutils/docs/ref/rst/mathematics.txt
trunk/docutils/docutils/utils/math/latex2mathml.py
Modified: trunk/docutils/docs/ref/rst/mathematics.txt
===================================================================
--- trunk/docutils/docs/ref/rst/mathematics.txt 2021-06-17 09:59:05 UTC (rev 8762)
+++ trunk/docutils/docs/ref/rst/mathematics.txt 2021-06-17 09:59:21 UTC (rev 8763)
@@ -489,9 +489,11 @@
LateX2MathML, as there is no corresponding Unicode character.
Synonyms: `\ne` ``\ne``, `\le` ``\le``, `\ge` ``\ge``,
-`\Doteq` ``\Doteq``, `\llless` ``\llless``, `\gggtr` ``\gggtr``,
-`\not=` ``\not=``, `\not\equiv` ``\not\equiv``.
+`\Doteq` ``\Doteq``, `\llless` ``\llless``, `\gggtr` ``\gggtr``.
+Symbols can be negated prepending ``\not``, e.g.
+`\not=` ``\not=``, `\not\equiv` ``\not\equiv``,
+`\not\gtrless` ``\not\gtrless``, `\not\lessgtr` ``\not\lessgtr``.
Miscellaneous relations
~~~~~~~~~~~~~~~~~~~~~~~
@@ -522,8 +524,11 @@
`\ntriangleleft` ``\ntriangleleft`` `\Subset` ``\Subset``
===================== ======================= =================== ===================== =================== =====================
-Synonyms: `\owns` ``\owns``, `\not\in` ``\not\in``.
+Synonyms: `\owns` ``\owns``.
+Symbols can be negated prepending ``\not``, e.g.
+`\not\in` ``\not\in``, `\not\ni` ``\not\ni``.
+
The commands ``\varsubsetneq``, ``\varsubsetneqq``, ``\varsupsetneq``,
and ``\varsupsetneqq`` are not supported by LateX2MathML, as there is no
corresponding Unicode character.
@@ -790,13 +795,13 @@
The text may contain math commands wrapped in ``$`` signs, e.g.
-.. math:: (-1)^{n_i} = \begin{cases} -1 \quad \text{if $n_i$ is odd} \\
+.. math:: (-1)^{n_i} = \begin{cases} -1 \quad \text{if $n_i$ is odd,} \\
+1 \quad \text{if $n_i$ is even.}
\end{cases}
.. TODO ignore {}, handle text-mode commands
-
+
.. TODO: ``\mod`` and its relatives
--------------------------
@@ -917,7 +922,9 @@
<mtd>, <mscarry>, and <math> treat their contents as a single inferred mrow
formed from all their children.
-.. math:: a = \sqrt 2 + x, b = \sqrt{1+x^2}, c = \sqrt\frac{\sin(x)}{23},
+.. math:: a = \sqrt 2 + x,\quad
+ b = \sqrt{1+x^2},\quad
+ c = \sqrt\frac{\sin(x)}{23},
inline: :math:`a = \sqrt 2 + x, b = \sqrt{1+x^2}, c = \sqrt\frac{\sin(x)}{23}`.
@@ -942,8 +949,8 @@
.. math:: \text{das ist ein {toller} text (unescaped \{ and \} is
ignored by LaTeX)}
-Big delimiters
-~~~~~~~~~~~~~~
+Big delimiters and symbols
+~~~~~~~~~~~~~~~~~~~~~~~~~~
Test ``\left``, ``\right``, and the \bigl/\bigr, … size commands
with extensible delimiters.
@@ -981,3 +988,20 @@
\quad
\left.\vert \frac{b}{a}\right\Vert\ \bigl\vert b\Bigr\Vert\ \biggl\vert b\Biggr\Vert
\quad
+
+
+Variable-sized operators:
+
+Inline: `\sum\ \int\ \oint\ \smallint\ \prod\ \coprod\ \bigwedge\
+\bigvee\ \bigcap\ \bigcup\ \biguplus\ \bigsqcup\ \bigodot\ \bigoplus\
+\bigotimes` and Display:
+
+.. math:: \sum\ \int\ \oint\ \smallint\ \prod\ \coprod\ \bigwedge
+ \ \bigvee\ \bigcap\ \bigcup\ \biguplus\ \bigsqcup\ \bigodot
+ \ \bigoplus\ \bigotimes
+ \ \iiint\ \iiiint
+
+Text
+~~~~
+
+The text may contain non-ASCII characters: `n_\text{Stoß}`.
Modified: trunk/docutils/docutils/utils/math/latex2mathml.py
===================================================================
--- trunk/docutils/docutils/utils/math/latex2mathml.py 2021-06-17 09:59:05 UTC (rev 8762)
+++ trunk/docutils/docutils/utils/math/latex2mathml.py 2021-06-17 09:59:21 UTC (rev 8763)
@@ -26,6 +26,7 @@
import collections
import re
import sys
+import unicodedata
if sys.version_info >= (3, 0):
unicode = str # noqa
@@ -35,13 +36,6 @@
# Character data
# --------------
-# Named XML entities for invalid and invisible characters
-xml_entities = {ord('<'): u'<',
- ord('>'): u'>',
- ord('&'): u'&',
- 0x2061: u'⁡',
- }
-
# LaTeX math macro to Unicode mappings.
# Character categories.
@@ -103,43 +97,60 @@
# operator, fence, or separator -> <mo>
-math_fences = {# mathfence aliases with adapted spacing
- 'lvert': u'|', # left |
- 'lVert': u'\u2016', # left ‖
- 'rvert': u'|', # right |
- 'rVert': u'\u2016', # right ‖
- 'Arrowvert': u'\u2016', # ‖
- }
+stretchables = {# extensible delimiters allowed in left/right cmds
+ 'backslash': '\\',
+ 'uparrow': u'\u2191', # ↑ UPWARDS ARROW
+ 'downarrow': u'\u2193', # ↓ DOWNWARDS ARROW
+ 'updownarrow': u'\u2195', # ↕ UP DOWN ARROW
+ 'Uparrow': u'\u21d1', # ⇑ UPWARDS DOUBLE ARROW
+ 'Downarrow': u'\u21d3', # ⇓ DOWNWARDS DOUBLE ARROW
+ 'Updownarrow': u'\u21d5', # ⇕ UP DOWN DOUBLE ARROW
+ 'lmoustache': u'\u23b0', # ⎰ UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION
+ 'rmoustache': u'\u23b1', # ⎱ UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION
+ 'arrowvert': u'\u23d0', # ⏐ VERTICAL LINE EXTENSION
+ 'bracevert': u'\u23aa', # ⎪ CURLY BRACKET EXTENSION
+ 'lvert': u'|', # left |
+ 'lVert': u'\u2016', # left ‖
+ 'rvert': u'|', # right |
+ 'rVert': u'\u2016', # right ‖
+ 'Arrowvert': u'\u2016', # ‖
+ }
+stretchables.update(tex2unichar.mathfence)
+stretchables.update(tex2unichar.mathopen) # Braces
+stretchables.update(tex2unichar.mathclose) # Braces
-operators = tex2unichar.mathbin # Binary symbols
+# >>> print(' '.join(sorted(set(stretchables.values()))))
+# [ \ ] { | } ‖ ↑ ↓ ↕ ⇑ ⇓ ⇕ ⌈ ⌉ ⌊ ⌋ ⌜ ⌝ ⌞ ⌟ ⎪ ⎰ ⎱ ⏐ ⟅ ⟆ ⟦ ⟧ ⟨ ⟩ ⟮ ⟯ ⦇ ⦈
+
+operators = {# negated symbols without pre-composed Unicode character
+ 'nleqq': u'\u2266\u0338', # ≦̸
+ 'ngeqq': u'\u2267\u0338', # ≧̸
+ 'nleqslant': u'\u2a7d\u0338', # ⩽̸
+ 'ngeqslant': u'\u2a7e\u0338', # ⩾̸
+ 'ngtrless': u'\u2277\u0338', # txfonts
+ 'nlessgtr': u'\u2276\u0338', # txfonts
+ 'nsubseteqq': u'\u2AC5\u0338', # ⫅̸
+ 'nsupseteqq': u'\u2AC6\u0338', # ⫆̸
+ # alias commands:
+ 'dotsb': u'\u22ef', # ⋯ with binary operators/relations
+ 'dotsc': u'\u2026', # … with commas
+ 'dotsi': u'\u22ef', # ⋯ with integrals
+ 'dotsm': u'\u22ef', # ⋯ multiplication dots
+ 'dotso': u'\u2026', # … other dots
+ # functions with movable limits (requires <mo>)
+ 'lim': 'lim',
+ 'sup': 'sup',
+ 'inf': 'inf',
+ 'max': 'max',
+ 'min': 'min',
+ }
+operators.update(tex2unichar.mathbin) # Binary symbols
operators.update(tex2unichar.mathrel) # Relation symbols, arrow symbols
operators.update(tex2unichar.mathord) # Miscellaneous symbols
operators.update(tex2unichar.mathop) # Variable-sized symbols
-operators.update(tex2unichar.mathopen) # Braces
-operators.update(tex2unichar.mathclose) # Braces
-operators.update(tex2unichar.mathfence)
-operators.update(math_fences)
-operators.update({# negated symbols without pre-composed Unicode character
- 'nleqq': u'\u2266\u0338', # ≦̸
- 'ngeqq': u'\u2267\u0338', # ≧̸
- 'nleqslant': u'\u2a7d\u0338', # ⩽̸
- 'ngeqslant': u'\u2a7e\u0338', # ⩾̸
- 'nsubseteqq': u'\u2AC5\u0338', # ⫅̸
- 'nsupseteqq': u'\u2AC6\u0338', # ⫆̸
- # alias commands:
- 'dotsb': u'\u22ef', # ⋯ with binary operators/relations
- 'dotsc': u'\u2026', # … with commas
- 'dotsi': u'\u22ef', # ⋯ with integrals
- 'dotsm': u'\u22ef', # ⋯ multiplication dots
- 'dotso': u'\u2026', # … other dots
- # functions with movable limits (requires <mo>)
- 'lim': 'lim',
- 'sup': 'sup',
- 'inf': 'inf',
- 'max': 'max',
- 'min': 'min',
- })
+operators.update(stretchables)
+
# special cases
thick_operators = {# style='font-weight: bold;'
@@ -171,38 +182,10 @@
# 'varointclockwise',))
-# pre-composed characters for negated symbols
-# see https://www.w3.org/TR/xml-entity-names/#combining
-negatables = {'=': u'\u2260',
- r'\in': u'\u2209',
- r'\equiv': u'\u2262'}
-
-# extensible delimiters allowed in left/right cmds
-stretchables = {'backslash': '\\',
- 'uparrow': u'\u2191', # ↑ UPWARDS ARROW
- 'downarrow': u'\u2193', # ↓ DOWNWARDS ARROW
- 'updownarrow': u'\u2195', # ↕ UP DOWN ARROW
- 'Uparrow': u'\u21d1', # ⇑ UPWARDS DOUBLE ARROW
- 'Downarrow': u'\u21d3', # ⇓ DOWNWARDS DOUBLE ARROW
- 'Updownarrow': u'\u21d5', # ⇕ UP DOWN DOUBLE ARROW
- 'lmoustache': u'\u23b0', # ⎰ UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION
- 'rmoustache': u'\u23b1', # ⎱ UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION
- 'arrowvert': u'\u23d0', # ⏐ VERTICAL LINE EXTENSION
- 'bracevert': u'\u23aa', # ⎪ CURLY BRACKET EXTENSION
- }
-stretchables.update(tex2unichar.mathfence)
-stretchables.update(tex2unichar.mathopen)
-stretchables.update(tex2unichar.mathclose)
-stretchables.update(math_fences)
-
-# >>> print(' '.join(sorted(set(stretchables.values()))))
-# [ \ ] { | } ‖ ↑ ↓ ↕ ⇑ ⇓ ⇕ ⌈ ⌉ ⌊ ⌋ ⌜ ⌝ ⌞ ⌟ ⎪ ⎰ ⎱ ⏐ ⟅ ⟆ ⟦ ⟧ ⟨ ⟩ ⟮ ⟯ ⦇ ⦈
-
# horizontal space -> <mspace>
spaces = {'qquad': '2em', # two \quad
'quad': '1em', # 18 mu
- 'qquad': '2em', # two \quad
'thickspace': '0.2778em', # 5mu = 5/18em
'medspace': '0.2222em', # 4mu = 2/9em
'thinspace': '0.1667em', # 3mu = 1/6em
@@ -210,9 +193,9 @@
'negmedspace': '-0.2222em', # -4mu = -2/9em
'negthickspace': '-0.2778em', # -5mu = -5/18em
' ': '0.25em', # inter word space
- ';': '0.2778em', # thickspace
- ':': '0.2222em', # medspace
- ',': '0.1667em', # thinspace
+ ';': '0.2778em', # 5mu thickspace
+ ':': '0.2222em', # 4mu medspace
+ ',': '0.1667em', # 3mu thinspace
'!': '-0.1667em', # negthinspace
}
@@ -320,6 +303,12 @@
parent = None
"""Parent node in MathML DOM tree."""
_level = 0 # indentation level (static class variable)
+ xml_entities = { # for invalid and invisible characters
+ ord('<'): u'<',
+ ord('>'): u'>',
+ ord('&'): u'&',
+ 0x2061: u'⁡',
+ }
def __init__(self, *children, **attributes):
"""Set up node with `children` and `attributes`.
@@ -495,7 +484,7 @@
super(MathToken, self).__init__(**attributes)
def _xml_body(self, level=0):
- return [unicode(self.data).translate(xml_entities)]
+ return [unicode(self.data).translate(self.xml_entities)]
class mi(MathToken): pass
class mn(MathToken): pass
@@ -773,7 +762,7 @@
tree = node
while len(string) > 0:
- # Take of first character:
+ # Take off first character:
c, string = string[0], string[1:]
if c == ' ':
@@ -964,11 +953,16 @@
return node, string
if name == 'not':
- arg, string = tex_token_or_group(string)
- try:
- node = node.append(mo(negatables[arg]))
- except KeyError:
- raise SyntaxError(u'"\\not: Cannot negate: %s!'%arg)
+ arg, string = tex_token(string)
+ if arg == '{':
+ return node, '{\\not ' + string
+ if arg.startswith('\\'): # LaTeX macro
+ try:
+ arg = operators[arg[1:]]
+ except KeyError:
+ raise SyntaxError(u'\\not: Cannot negate: "%s"!'%arg)
+ arg = unicodedata.normalize('NFC', arg+u'\u0338')
+ node = node.append(mo(arg))
return node, string
# arbitrary text (usually comments) -> <mtext>
@@ -1334,16 +1328,16 @@
# TODO: look up more symbols from tr25, e.g.
-#
-#
+#
+#
# Table 2.8 Using Vertical Line or Solidus Overlay
# some of the negated forms of mathematical relations that can only be
# encoded by using either U+0338 COMBINING LONG SOLIDUS OVERLAY or U+20D2
# COMBINING LONG VERTICAL LINE OVERLAY . (For issues with using 0338 in
# MathML, see Section 3.2.7, Combining Marks.
-#
+#
# Table 2.9 Variants of Mathematical Symbols using VS1?
-#
+#
# Sequence Description
# 0030 + VS1 DIGIT ZERO - short diagonal stroke form
# 2205 + VS1 EMPTY SET - zero with long diagonal stroke overlay form
@@ -1370,4 +1364,3 @@
# 2AAD + VS1 LARGER THAN OR slanted EQUAL
# 2ACB + VS1 SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members
# 2ACC + VS1 SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members
-
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2021-06-17 14:33:10
|
Revision: 8766
http://sourceforge.net/p/docutils/code/8766
Author: milde
Date: 2021-06-17 14:33:09 +0000 (Thu, 17 Jun 2021)
Log Message:
-----------
Make "meta" a standard node.
Fixes also bug #241.
Modified Paths:
--------------
trunk/docutils/HISTORY.txt
trunk/docutils/RELEASE-NOTES.txt
trunk/docutils/docs/ref/doctree.txt
trunk/docutils/docs/ref/docutils.dtd
trunk/docutils/docs/ref/rst/directives.txt
trunk/docutils/docs/ref/rst/restructuredtext.txt
trunk/docutils/docs/ref/transforms.txt
trunk/docutils/docs/user/config.txt
trunk/docutils/docutils/nodes.py
trunk/docutils/docutils/parsers/rst/directives/__init__.py
trunk/docutils/docutils/parsers/rst/directives/misc.py
trunk/docutils/docutils/transforms/components.py
trunk/docutils/docutils/writers/latex2e/__init__.py
trunk/docutils/test/functional/expected/standalone_rst_docutils_xml.xml
trunk/docutils/test/functional/expected/standalone_rst_xetex.tex
trunk/docutils/test/test_parsers/test_rst/test_directives/test_meta.py
Removed Paths:
-------------
trunk/docutils/docutils/parsers/rst/directives/html.py
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2021-06-17 09:59:43 UTC (rev 8765)
+++ trunk/docutils/HISTORY.txt 2021-06-17 14:33:09 UTC (rev 8766)
@@ -18,6 +18,20 @@
- ``Node.traverse()`` returns an iterator instead of a list.
+ - Make meta__ a standard Docutils doctree node. Writers may ignore
+ "meta" nodes if they are not supported by the output format.
+
+ __ docs/ref/doctree.html#meta
+
+* docutils/parsers/rst/directives/html.py
+
+ - Removed. (Meta directive moved to ``misc.py``.)
+
+* docutils/parsers/rst/directives/misc.py
+
+ - `Meta` directive class (moved from html.py) inserts `meta`
+ (instead of `pending`) nodes.
+
* docutils/tools/math/math2html, docutils/writers/html5_polyglot/math.css
- Fix bug #244 Wrong subscript/superscript order with
@@ -58,6 +72,7 @@
- Remove IE 6 compatibility workarounds ``iepngfix.htc`` and
``blank.gif`` (fixes bug #169).
+
Release 0.17.1 (2021-04-16)
===========================
@@ -80,6 +95,7 @@
- Apply patch #160: move macro defs above ``.TH``
(thanks Willie and sorry for the delay).
+
Release 0.17 (2021-04-03)
=========================
Modified: trunk/docutils/RELEASE-NOTES.txt
===================================================================
--- trunk/docutils/RELEASE-NOTES.txt 2021-06-17 09:59:43 UTC (rev 8765)
+++ trunk/docutils/RELEASE-NOTES.txt 2021-06-17 14:33:09 UTC (rev 8766)
@@ -38,17 +38,6 @@
* `htm4css1` writer: Support the embed_images_ option.
-* Make <meta> a standard Docutils doctree node.
-
- The `meta directive`__ will insert <meta> instead of pending nodes.
- Writers may ignore some or all <meta> elements if they are not
- supported by the output format.
-
- The ``transforms/components.Filter`` class will become obsolete by
- this change and may be removed in future.
-
- __ docs/ref/rst/directives.html#meta
-
* Remove the "rawsource" attribute and argument from nodes.Text:
we store the null-escaped text in Text nodes since 0.16 so there is no
additional information in the rawsource.
@@ -108,7 +97,11 @@
* ``nodes.Node.traverse()`` returns an iterator instead of a list.
+* Make meta__ a standard Docutils doctree node.
+ __ docs/ref/doctree.html#meta
+
+
Release 0.17.1 (2021-04-16)
===========================
Modified: trunk/docutils/docs/ref/doctree.txt
===================================================================
--- trunk/docutils/docs/ref/doctree.txt 2021-06-17 09:59:43 UTC (rev 8765)
+++ trunk/docutils/docs/ref/doctree.txt 2021-06-17 14:33:09 UTC (rev 8766)
@@ -111,7 +111,7 @@
Simple structuctural subelements (title_, subtitle_) contain text
data; the others are compound and do not directly contain text data.
-Category members: title_, subtitle_, decoration_, docinfo_,
+Category members: title_, subtitle_, decoration_, docinfo_, meta_,
transition_
@@ -1607,10 +1607,11 @@
``docinfo``
===========
-The ``docinfo`` element is a container for document bibliographic
+The ``docinfo`` element is a container for displayed document bibliographic
data, or meta-data (data about the document). It corresponds to the
front matter of a book, such as the title page and copyright page.
+See also the meta_ element (for "hidden" meta-data).
Details
-------
@@ -1839,12 +1840,9 @@
:Attributes:
The ``document`` element contains the `common attributes`_ (ids_,
- names_, dupnames_, source_, and classes_), plus an optional title__
- attribute which stores the document title metadata.
+ names_, dupnames_, source_, and classes_), plus an optional
+ `title attribute`_ which stores the document title metadata.
- __ `title (attribute)`_
-
-
Examples
--------
@@ -2705,7 +2703,6 @@
Examples
--------
-reStructuredText uses a directive to indicate a ``line_block``.
Example source::
Take it away, Eric the Orchestra Leader!
@@ -3006,7 +3003,56 @@
The ``math`` element contains the `common attributes`_
(ids_, names_, dupnames_, source_, and classes_).
+``meta``
+========
+The ``meta`` element is a container for "hidden" document
+bibliographic data, or meta-data (data about the document).
+It corresponds to HTML META tags.
+
+See also the docinfo_ element for displayed meta-data.
+The document's `title attribute`_ stores the metadate document title.
+
+
+Details
+-------
+
+:Category:
+ `Structural Subelements`_
+
+:Parents:
+ Only the document_ element contains ``meta``.
+
+:Children:
+ None.
+
+:Analogues:
+ ``meta`` is analogous to the HTML "meta" element
+ or the file properties in ODT or PDF documents.
+
+:Processing:
+ The ``meta`` element is stored as metadata if the export format
+ supports this. It is typically invisible and may be omitted from
+ the processed output.
+
+ Meta-data may also be extracted from docinfo_ children
+ or the document_ attributes (title).
+
+The `"meta" directive`_ is used to create a ``meta`` element.
+reStructuredText_ source::
+
+ .. meta::
+ :description lang=en: An amusing story
+ :description lang=fr: Un histoire amusant
+
+Pseudo-XML_ fragment from simple parsing::
+
+ <meta content="An amusing story" lang="en" name="description">
+ <meta content="Un histoire amusant" lang="fr" name="description">
+
+.. _"meta" directive: rst/directives.html#meta
+
+
``note``
========
@@ -4537,9 +4583,8 @@
_`number`
The attribute value must be a number. Resolves to ``NMTOKEN``.
- Used in the `level`_, `morecols`_, `scale`_, and `start`_ attributes.
+ Used in the `scale`_, and `start`_ attributes.
-
_`measure`
A number which may be immediately followed by a unit or percent sign.
Resolves to CDATA.
@@ -4887,6 +4932,18 @@
The ``suffix`` attribute is used in the enumerated_list_ element.
+.. _title attribute:
+
+``title``
+=========
+
+Attribute type: `CDATA`_. Default value: none.
+
+The ``title`` attribute stores the title metadata of a document_. This
+title is typically not part of the rendered document. It may for
+example be used in HTML's ``title`` element.
+
+
``width``
==========
@@ -4910,18 +4967,6 @@
instance.
-.. _title (attribute):
-
-``title``
-=========
-
-Attribute type: `CDATA`_. Default value: none.
-
-The ``title`` attribute stores the title metadata of a document. This
-title is typically not part of the rendered document. It may for
-example be used in HTML's ``title`` element.
-
-
----------------------------
Parameter Entity Reference
----------------------------
@@ -5252,7 +5297,7 @@
An additional restriction, which cannot be expressed in the language
of DTDs, is imposed by software:
-
+
* A transition may not occur at the end of a document or section.
The `%structure.model;`_ parameter entity is directly employed in the
Modified: trunk/docutils/docs/ref/docutils.dtd
===================================================================
--- trunk/docutils/docs/ref/docutils.dtd 2021-06-17 09:59:43 UTC (rev 8765)
+++ trunk/docutils/docs/ref/docutils.dtd 2021-06-17 14:33:09 UTC (rev 8766)
@@ -254,6 +254,7 @@
<!ELEMENT document
( (title, subtitle?)?,
decoration?,
+ meta?,
(docinfo, transition?)?,
%structure.model; )>
<!ATTLIST document
@@ -281,7 +282,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-->
-<!-- Container for bibliographic elements. May not be empty. -->
+<!-- Container for bibliographic elements. Must not be empty. -->
<!ELEMENT docinfo (%bibliographic.elements;)+>
<!ATTLIST docinfo %basic.atts;>
@@ -322,6 +323,10 @@
<!ELEMENT copyright %text.model;>
<!ATTLIST copyright %basic.atts;>
+<!-- Container for "hidden" meta-data. Must not be empty. -->
+<!ELEMENT meta (field_list+)>
+<!ATTLIST meta %basic.atts;>
+
<!--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Decoration Elements
Modified: trunk/docutils/docs/ref/rst/directives.txt
===================================================================
--- trunk/docutils/docs/ref/rst/directives.txt 2021-06-17 09:59:43 UTC (rev 8765)
+++ trunk/docutils/docs/ref/rst/directives.txt 2021-06-17 14:33:09 UTC (rev 8766)
@@ -76,7 +76,7 @@
:Directive Types: "attention", "caution", "danger", "error", "hint",
"important", "note", "tip", "warning", "admonition"
:Doctree Elements: attention, caution, danger, error, hint, important,
- note, tip, warning, admonition_, title
+ note, tip, warning, admonition_, title_
:Directive Arguments: None.
:Directive Options: `:class:`_, `:name:`_
:Directive Content: Interpreted as body elements.
@@ -128,7 +128,7 @@
==================
:Directive Type: "admonition"
-:Doctree Elements: admonition_, title
+:Doctree Elements: admonition_, title_
:Directive Arguments: One, required (admonition title)
:Directive Options: `:class:`_, `:name:`_
:Directive Content: Interpreted as body elements.
@@ -512,7 +512,7 @@
The following options are recognized:
-``number-lines`` : [integer]
+``number-lines`` : [integer] (start line number)
Precede every line with a line number.
The optional argument is the number of the first line (defaut 1).
@@ -1853,7 +1853,7 @@
========
:Directive Type: "meta"
-:Doctree Element: pending_, meta (non-standard)
+:Doctree Element: meta_
:Directive Arguments: None.
:Directive Options: None.
:Directive Content: Must contain a flat field list.
@@ -1866,7 +1866,7 @@
.. note:: Data from some `bibliographic fields`_ is automatically
extracted and stored as metadata, too. However, Bibliographic
- Fields are also visible in the document's screen rendering or
+ Fields are also displayed in the document's screen rendering or
printout.
For an "invisible" *document title*, see the `metadata document
@@ -1912,13 +1912,11 @@
<meta http-equiv="Content-Type"
content="text/html; charset=ISO-8859-1">
-
.. [#] "Metadata" is data about data, in this case data about the
document. Metadata is, e.g., used to describe and classify web
pages in the World Wide Web, in a form that is easy for search
engines to extract and collate.
-
.. _HTML meta elements:
https://html.spec.whatwg.org/multipage/semantics.html#the-meta-element
.. _ODT file properties:
@@ -1931,16 +1929,19 @@
=======================
:Directive Type: "title"
-:Doctree Element: None.
+:Doctree Element: Sets the document's `title attribute`_.
:Directive Arguments: One, required (the title text).
:Directive Options: None.
:Directive Content: None.
The "title" directive specifies the document title as metadata, which
-does not become part of the document body. It overrides a
-document-supplied title. For example, in HTML output the metadata
-document title appears in the title bar of the browser window.
+does not become part of the document body. It overrides the
+document-supplied `document title`_ and the `"title" configuration
+setting`_. For example, in HTML output the metadata document title
+appears in the title bar of the browser window.
+.. _document title: restructuredtext.html#document-title
+.. _"title" configuration setting: ../../user/config.html#title
Restructuredtext-Test-Directive
===============================
@@ -2017,6 +2018,7 @@
.. _length: restructuredtext.html#length-units
.. _line_block: ../doctree.html#line-block
.. _math_block: ../doctree.html#math-block
+.. _meta: ../doctree.html#meta
.. _pending: ../doctree.html#pending
.. _percentage: restructuredtext.html#percentage-units
.. _raw: ../doctree.html#raw
@@ -2024,6 +2026,7 @@
.. _sidebar: ../doctree.html#sidebar
.. _table: ../doctree.html#table
.. _title: ../doctree.html#title
+.. _title attribute: ../doctree.html#title-attribute
.. _topic: ../doctree.html#topic
Modified: trunk/docutils/docs/ref/rst/restructuredtext.txt
===================================================================
--- trunk/docutils/docs/ref/rst/restructuredtext.txt 2021-06-17 09:59:43 UTC (rev 8765)
+++ trunk/docutils/docs/ref/rst/restructuredtext.txt 2021-06-17 14:33:09 UTC (rev 8766)
@@ -359,7 +359,7 @@
In `URI context` [#uri-context]_, backslash-escaped whitespace
represents a single space.
-
+
Backslashes have no special meaning in `literal context` [#literal-context]_.
Here, a single backslash represents a literal backslash, without having
to double up. [#caveat]_
@@ -474,9 +474,11 @@
the sections are then lifted up a level or two. See the `DocTitle
transform`_ for details.
-.. [#] The `title configuration setting`__ and the `title directive`__
- set a document title that does not become part of the document body.
+.. [#] The `"title" configuration setting`__ and the `"title"
+ directive`__ set the document's `title attribute`_ that does not
+ become part of the document body.
+ .. _title attribute: ../doctree.html#title-attribute
__ ../../user/config.html#title
__ directives.html#metadata-document-title
Modified: trunk/docutils/docs/ref/transforms.txt
===================================================================
--- trunk/docutils/docs/ref/transforms.txt 2021-06-17 09:59:43 UTC (rev 8765)
+++ trunk/docutils/docs/ref/transforms.txt 2021-06-17 14:33:09 UTC (rev 8766)
@@ -92,7 +92,7 @@
peps.PEPZero peps.Headers (t/p) 760
-components.Filter "meta" (d/p) 780
+components.Filter *not used* 780
universal.Decorations Reader (r) 820
Modified: trunk/docutils/docs/user/config.txt
===================================================================
--- trunk/docutils/docs/user/config.txt 2021-06-17 09:59:43 UTC (rev 8765)
+++ trunk/docutils/docs/user/config.txt 2021-06-17 14:33:09 UTC (rev 8766)
@@ -559,14 +559,19 @@
title
-----
-The `document title`_ as metadata, which does not become part of the
-document body. It overrides a document-supplied title. For
-example, in HTML output the metadata document title appears in the
-title bar of the browser window.
+The `document title` as metadata which does not become part of the
+document body. Stored as the document's `title attribute`_.
+For example, in HTML output the metadata document title
+appears in the title bar of the browser window.
+This setting overrides a displayed `document title`_ and
+is overridden by a `"title" directive`_.
+
Default: none. Option: ``--title``.
+.. _title attribute: ../ref/doctree.html#title-attribute
.. _document title: ../ref/rst/restructuredtext.html#document-title
+.. _"title" directive: ../ref/rst/directives.html#metadata-document-title
toc_backlinks
-------------
@@ -1092,7 +1097,7 @@
With the "html4css1" writer, the resulting HTML document does
not validate, as there is no DTD for `MathML + XHTML Transitional`.
However, MathML-enabled browsers will render it fine.
-
+
__ https://developer.mozilla.org/en-US/docs/Web/MathML
#browser_compatibility
__ ../ref/rst/mathematics.html
Modified: trunk/docutils/docutils/nodes.py
===================================================================
--- trunk/docutils/docutils/nodes.py 2021-06-17 09:59:43 UTC (rev 8765)
+++ trunk/docutils/docutils/nodes.py 2021-06-17 14:33:09 UTC (rev 8766)
@@ -40,7 +40,6 @@
# ==============================
class Node(object):
-
"""Abstract base class of nodes in a document tree."""
parent = None
@@ -1590,6 +1589,13 @@
class rubric(Titular, TextElement): pass
+# ==================
+# Meta-Data Element
+# ==================
+
+class meta(PreBibliographic, Element):
+ """Container for "invisible" bibliographic data, or meta-data."""
+
# ========================
# Bibliographic Elements
# ========================
@@ -1914,7 +1920,7 @@
header hint
image important inline
label legend line line_block list_item literal literal_block
- math math_block
+ math math_block meta
note
option option_argument option_group option_list option_list_item
option_string organization
@@ -1945,9 +1951,9 @@
"``depart_`` + node class name", resp.
This is a base class for visitors whose ``visit_...`` & ``depart_...``
- methods should be implemented for *all* node types encountered (such as
- for `docutils.writers.Writer` subclasses). Unimplemented methods will
- raise exceptions.
+ methods must be implemented for *all* compulsory node types encountered
+ (such as for `docutils.writers.Writer` subclasses).
+ Unimplemented methods will raise exceptions (except for optional nodes).
For sparse traversals, where only certain node types are of interest, use
subclass `SparseNodeVisitor` instead. When (mostly or entirely) uniform
@@ -1958,7 +1964,7 @@
1995.
"""
- optional = ()
+ optional = (meta)
"""
Tuple containing node class names (as strings).
Modified: trunk/docutils/docutils/parsers/rst/directives/__init__.py
===================================================================
--- trunk/docutils/docutils/parsers/rst/directives/__init__.py 2021-06-17 09:59:43 UTC (rev 8765)
+++ trunk/docutils/docutils/parsers/rst/directives/__init__.py 2021-06-17 14:33:09 UTC (rev 8766)
@@ -57,7 +57,7 @@
#'footnotes': ('parts', 'footnotes'),
#'citations': ('parts', 'citations'),
'target-notes': ('references', 'TargetNotes'),
- 'meta': ('html', 'Meta'),
+ 'meta': ('misc', 'Meta'),
#'imagemap': ('html', 'imagemap'),
'raw': ('misc', 'Raw'),
'include': ('misc', 'Include'),
Deleted: trunk/docutils/docutils/parsers/rst/directives/html.py
===================================================================
--- trunk/docutils/docutils/parsers/rst/directives/html.py 2021-06-17 09:59:43 UTC (rev 8765)
+++ trunk/docutils/docutils/parsers/rst/directives/html.py 2021-06-17 14:33:09 UTC (rev 8766)
@@ -1,88 +0,0 @@
-# $Id$
-# Author: David Goodger <go...@py...>
-# Copyright: This module has been placed in the public domain.
-
-"""
-Directives for typically HTML-specific constructs.
-"""
-
-__docformat__ = 'reStructuredText'
-
-import sys
-from docutils import nodes, utils
-from docutils.parsers.rst import Directive
-from docutils.parsers.rst import states
-from docutils.transforms import components
-
-
-class MetaBody(states.SpecializedBody):
-
- class meta(nodes.Special, nodes.PreBibliographic, nodes.Element):
- """HTML-specific "meta" element."""
- pass
-
- def field_marker(self, match, context, next_state):
- """Meta element."""
- node, blank_finish = self.parsemeta(match)
- self.parent += node
- return [], next_state, []
-
- def parsemeta(self, match):
- name = self.parse_field_marker(match)
- name = utils.unescape(utils.escape2null(name))
- indented, indent, line_offset, blank_finish = \
- self.state_machine.get_first_known_indented(match.end())
- node = self.meta()
- pending = nodes.pending(components.Filter,
- {'component': 'writer',
- 'format': 'html,latex,odt',
- 'nodes': [node]})
- node['content'] = utils.unescape(utils.escape2null(
- ' '.join(indented)))
- if not indented:
- line = self.state_machine.line
- msg = self.reporter.info(
- 'No content for meta tag "%s".' % name,
- nodes.literal_block(line, line))
- return msg, blank_finish
- tokens = name.split()
- try:
- attname, val = utils.extract_name_value(tokens[0])[0]
- node[attname.lower()] = val
- except utils.NameValueError:
- node['name'] = tokens[0]
- for token in tokens[1:]:
- try:
- attname, val = utils.extract_name_value(token)[0]
- node[attname.lower()] = val
- except utils.NameValueError as detail:
- line = self.state_machine.line
- msg = self.reporter.error(
- 'Error parsing meta tag attribute "%s": %s.'
- % (token, detail), nodes.literal_block(line, line))
- return msg, blank_finish
- self.document.note_pending(pending)
- return pending, blank_finish
-
-
-class Meta(Directive):
-
- has_content = True
-
- SMkwargs = {'state_classes': (MetaBody,)}
-
- def run(self):
- self.assert_has_content()
- node = nodes.Element()
- new_line_offset, blank_finish = self.state.nested_list_parse(
- self.content, self.content_offset, node,
- initial_state='MetaBody', blank_finish=True,
- state_machine_kwargs=self.SMkwargs)
- if (new_line_offset - self.content_offset) != len(self.content):
- # incomplete parse of block?
- error = self.state_machine.reporter.error(
- 'Invalid meta directive.',
- nodes.literal_block(self.block_text, self.block_text),
- line=self.lineno)
- node += error
- return node.children
Modified: trunk/docutils/docutils/parsers/rst/directives/misc.py
===================================================================
--- trunk/docutils/docutils/parsers/rst/directives/misc.py 2021-06-17 09:59:43 UTC (rev 8765)
+++ trunk/docutils/docutils/parsers/rst/directives/misc.py 2021-06-17 14:33:09 UTC (rev 8766)
@@ -506,6 +506,71 @@
return []
+class MetaBody(states.SpecializedBody):
+
+ def field_marker(self, match, context, next_state):
+ """Meta element."""
+ node, blank_finish = self.parsemeta(match)
+ self.parent += node
+ return [], next_state, []
+
+ def parsemeta(self, match):
+ name = self.parse_field_marker(match)
+ name = utils.unescape(utils.escape2null(name))
+ indented, indent, line_offset, blank_finish = \
+ self.state_machine.get_first_known_indented(match.end())
+ node = nodes.meta()
+ node['content'] = utils.unescape(utils.escape2null(
+ ' '.join(indented)))
+ if not indented:
+ line = self.state_machine.line
+ msg = self.reporter.info(
+ 'No content for meta tag "%s".' % name,
+ nodes.literal_block(line, line))
+ return msg, blank_finish
+ tokens = name.split()
+ try:
+ attname, val = utils.extract_name_value(tokens[0])[0]
+ node[attname.lower()] = val
+ except utils.NameValueError:
+ node['name'] = tokens[0]
+ for token in tokens[1:]:
+ try:
+ attname, val = utils.extract_name_value(token)[0]
+ node[attname.lower()] = val
+ except utils.NameValueError as detail:
+ line = self.state_machine.line
+ msg = self.reporter.error(
+ 'Error parsing meta tag attribute "%s": %s.'
+ % (token, detail), nodes.literal_block(line, line))
+ return msg, blank_finish
+ # self.document.note_pending(pending)
+ return node, blank_finish
+
+
+class Meta(Directive):
+
+ has_content = True
+
+ SMkwargs = {'state_classes': (MetaBody,)}
+
+ def run(self):
+ self.assert_has_content()
+ node = nodes.Element()
+ new_line_offset, blank_finish = self.state.nested_list_parse(
+ self.content, self.content_offset, node,
+ initial_state='MetaBody', blank_finish=True,
+ state_machine_kwargs=self.SMkwargs)
+ if (new_line_offset - self.content_offset) != len(self.content):
+ # incomplete parse of block?
+ error = self.state_machine.reporter.error(
+ 'Invalid meta directive.',
+ nodes.literal_block(self.block_text, self.block_text),
+ line=self.lineno)
+ node += error
+ return node.children
+
+
class Date(Directive):
has_content = True
Modified: trunk/docutils/docutils/transforms/components.py
===================================================================
--- trunk/docutils/docutils/transforms/components.py 2021-06-17 09:59:43 UTC (rev 8765)
+++ trunk/docutils/docutils/transforms/components.py 2021-06-17 14:33:09 UTC (rev 8766)
@@ -32,13 +32,18 @@
``details['nodes']`` (a list of nodes); otherwise, the "pending" element
is removed.
- For example, the reStructuredText "meta" directive creates a "pending"
- element containing a "meta" element (in ``pending.details['nodes']``).
- Only writers (``pending.details['component'] == 'writer'``) supporting the
- "html", latex, or "odf" formats
- (``pending.details['format'] == 'html,latex,odf'``) will include the
- "meta" element; it will be deleted from the output of all other writers.
+ For example, up to version 0.17, the reStructuredText "meta"
+ directive created a "pending" element containing a "meta" element
+ (in ``pending.details['nodes']``).
+ Only writers (``pending.details['component'] == 'writer'``)
+ supporting the "html", "latex", or "odf" formats
+ (``pending.details['format'] == 'html,latex,odf'``) included the
+ "meta" element; it was deleted from the output of all other writers.
+
+ This transform is no longer used by Docutils, it may be removed in future.
"""
+ # TODO: clean up or keep this for 3rd party (or possible future) use?
+ # (GM 2021-05-18)
default_priority = 780
Modified: trunk/docutils/docutils/writers/latex2e/__init__.py
===================================================================
--- trunk/docutils/docutils/writers/latex2e/__init__.py 2021-06-17 09:59:43 UTC (rev 8765)
+++ trunk/docutils/docutils/writers/latex2e/__init__.py 2021-06-17 14:33:09 UTC (rev 8766)
@@ -2586,6 +2586,7 @@
self.pdfinfo.append(' addtopdfproducer={%s},'%content)
else:
# generic interface (case sensitive!)
+ # TODO: filter irrelevant nodes ("http-equiv", ...)?
self.pdfinfo.append(' pdfinfo={%s={%s}},'%(name, content))
def depart_meta(self, node):
Modified: trunk/docutils/test/functional/expected/standalone_rst_docutils_xml.xml
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_docutils_xml.xml 2021-06-17 09:59:43 UTC (rev 8765)
+++ trunk/docutils/test/functional/expected/standalone_rst_docutils_xml.xml 2021-06-17 14:33:09 UTC (rev 8766)
@@ -1365,6 +1365,10 @@
<title auto="1" refid="toc-entry-53"><generated classes="sectnum">2.14.11 </generated>Meta</title>
<paragraph>The <reference anonymous="1" name="“meta” directive" refuri="https://docutils.sourceforge.io/docs/ref/rst/directives.html#metadata">“meta” directive</reference> <footnote_reference auto="1" ids="footnote-reference-17" refid="footnote-10">9</footnote_reference> is used to specify metadata to be stored in,
e.g., HTML META tags or ODT file properties.</paragraph>
+ <meta content="reStructuredText, test, parser" name="keywords">
+ </meta>
+ <meta content="A test document, containing at least one example of each reStructuredText construct." lang="en" name="description">
+ </meta>
<target anonymous="1" ids="target-6" refuri="https://docutils.sourceforge.io/docs/ref/rst/directives.html#metadata"></target>
</section>
</section>
Modified: trunk/docutils/test/functional/expected/standalone_rst_xetex.tex
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_xetex.tex 2021-06-17 09:59:43 UTC (rev 8765)
+++ trunk/docutils/test/functional/expected/standalone_rst_xetex.tex 2021-06-17 14:33:09 UTC (rev 8766)
@@ -47,6 +47,8 @@
}{}
\hypersetup{
pdftitle={reStructuredText Test Document},
+ pdfkeywords={reStructuredText, test, parser},
+ pdfinfo={description={A test document, containing at least one example of each reStructuredText construct.}},
pdfauthor={David Goodger;Me;Myself;I}
}
Modified: trunk/docutils/test/test_parsers/test_rst/test_directives/test_meta.py
===================================================================
--- trunk/docutils/test/test_parsers/test_rst/test_directives/test_meta.py 2021-06-17 09:59:43 UTC (rev 8765)
+++ trunk/docutils/test/test_parsers/test_rst/test_directives/test_meta.py 2021-06-17 14:33:09 UTC (rev 8766)
@@ -29,22 +29,8 @@
""",
"""\
<document source="test data">
- <pending>
- .. internal attributes:
- .transform: docutils.transforms.components.Filter
- .details:
- component: 'writer'
- format: 'html,latex,odt'
- nodes:
- <meta conten...
[truncated message content] |
|
From: <mi...@us...> - 2021-06-17 14:33:28
|
Revision: 8767
http://sourceforge.net/p/docutils/code/8767
Author: milde
Date: 2021-06-17 14:33:28 +0000 (Thu, 17 Jun 2021)
Log Message:
-----------
Insert "meta" nodes at begin of document.
Modified Paths:
--------------
trunk/docutils/docs/ref/docutils.dtd
trunk/docutils/docutils/nodes.py
trunk/docutils/docutils/parsers/rst/directives/misc.py
trunk/docutils/docutils/transforms/frontmatter.py
trunk/docutils/test/functional/expected/standalone_rst_docutils_xml.xml
trunk/docutils/test/functional/expected/standalone_rst_html4css1.html
trunk/docutils/test/functional/expected/standalone_rst_html5.html
trunk/docutils/test/functional/expected/standalone_rst_pseudoxml.txt
trunk/docutils/test/test_parsers/test_rst/test_directives/test_meta.py
Modified: trunk/docutils/docs/ref/docutils.dtd
===================================================================
--- trunk/docutils/docs/ref/docutils.dtd 2021-06-17 14:33:09 UTC (rev 8766)
+++ trunk/docutils/docs/ref/docutils.dtd 2021-06-17 14:33:28 UTC (rev 8767)
@@ -253,8 +253,8 @@
<!-- Optional elements may be generated by internal processing. -->
<!ELEMENT document
( (title, subtitle?)?,
+ meta?,
decoration?,
- meta?,
(docinfo, transition?)?,
%structure.model; )>
<!ATTLIST document
Modified: trunk/docutils/docutils/nodes.py
===================================================================
--- trunk/docutils/docutils/nodes.py 2021-06-17 14:33:09 UTC (rev 8766)
+++ trunk/docutils/docutils/nodes.py 2021-06-17 14:33:28 UTC (rev 8767)
@@ -1572,7 +1572,7 @@
def get_decoration(self):
if not self.decoration:
self.decoration = decoration()
- index = self.first_child_not_matching_class(Titular)
+ index = self.first_child_not_matching_class((Titular, meta))
if index is None:
self.append(self.decoration)
else:
Modified: trunk/docutils/docutils/parsers/rst/directives/misc.py
===================================================================
--- trunk/docutils/docutils/parsers/rst/directives/misc.py 2021-06-17 14:33:09 UTC (rev 8766)
+++ trunk/docutils/docutils/parsers/rst/directives/misc.py 2021-06-17 14:33:28 UTC (rev 8767)
@@ -544,7 +544,6 @@
'Error parsing meta tag attribute "%s": %s.'
% (token, detail), nodes.literal_block(line, line))
return msg, blank_finish
- # self.document.note_pending(pending)
return node, blank_finish
@@ -568,7 +567,11 @@
nodes.literal_block(self.block_text, self.block_text),
line=self.lineno)
node += error
- return node.children
+ # insert at begin of document
+ index = self.state.document.first_child_not_matching_class(
+ (nodes.Titular, nodes.meta)) or 0
+ self.state.document[index:index] = node.children
+ return []
class Date(Directive):
Modified: trunk/docutils/docutils/transforms/frontmatter.py
===================================================================
--- trunk/docutils/docutils/transforms/frontmatter.py 2021-06-17 14:33:09 UTC (rev 8766)
+++ trunk/docutils/docutils/transforms/frontmatter.py 2021-06-17 14:33:28 UTC (rev 8767)
@@ -393,7 +393,7 @@
candidate = document[index]
if isinstance(candidate, nodes.field_list):
biblioindex = document.first_child_not_matching_class(
- (nodes.Titular, nodes.Decorative))
+ (nodes.Titular, nodes.Decorative, nodes.meta))
nodelist = self.extract_bibliographic(candidate)
del document[index] # untransformed field list (candidate)
document[biblioindex:biblioindex] = nodelist
Modified: trunk/docutils/test/functional/expected/standalone_rst_docutils_xml.xml
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_docutils_xml.xml 2021-06-17 14:33:09 UTC (rev 8766)
+++ trunk/docutils/test/functional/expected/standalone_rst_docutils_xml.xml 2021-06-17 14:33:28 UTC (rev 8767)
@@ -4,6 +4,10 @@
<document ids="restructuredtext-test-document doctitle" names="restructuredtext\ test\ document doctitle" source="functional/input/standalone_rst_docutils_xml.txt" title="reStructuredText Test Document">
<title>reStructuredText Test Document</title>
<subtitle ids="examples-of-syntax-constructs subtitle" names="examples\ of\ syntax\ constructs subtitle">Examples of Syntax Constructs</subtitle>
+ <meta content="reStructuredText, test, parser" name="keywords">
+ </meta>
+ <meta content="A test document, containing at least one example of each reStructuredText construct." lang="en" name="description">
+ </meta>
<decoration>
<header>
<paragraph>Document header</paragraph>
@@ -1365,10 +1369,6 @@
<title auto="1" refid="toc-entry-53"><generated classes="sectnum">2.14.11 </generated>Meta</title>
<paragraph>The <reference anonymous="1" name="“meta” directive" refuri="https://docutils.sourceforge.io/docs/ref/rst/directives.html#metadata">“meta” directive</reference> <footnote_reference auto="1" ids="footnote-reference-17" refid="footnote-10">9</footnote_reference> is used to specify metadata to be stored in,
e.g., HTML META tags or ODT file properties.</paragraph>
- <meta content="reStructuredText, test, parser" name="keywords">
- </meta>
- <meta content="A test document, containing at least one example of each reStructuredText construct." lang="en" name="description">
- </meta>
<target anonymous="1" ids="target-6" refuri="https://docutils.sourceforge.io/docs/ref/rst/directives.html#metadata"></target>
</section>
</section>
Modified: trunk/docutils/test/functional/expected/standalone_rst_html4css1.html
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_html4css1.html 2021-06-17 14:33:09 UTC (rev 8766)
+++ trunk/docutils/test/functional/expected/standalone_rst_html4css1.html 2021-06-17 14:33:28 UTC (rev 8767)
@@ -5,13 +5,13 @@
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.18b.dev: http://docutils.sourceforge.net/" />
<title>reStructuredText Test Document</title>
+<meta content="reStructuredText, test, parser" name="keywords" />
+<meta content="A test document, containing at least one example of each reStructuredText construct." lang="en" name="description" />
<meta name="author" content="David Goodger" />
<meta name="authors" content="Me Myself I" />
<meta name="organization" content="humankind" />
<meta name="date" content="Now, or yesterday. Or maybe even before yesterday." />
<meta name="copyright" content="This document has been placed in the public domain. You may do with it as you wish. You may copy, modify, redistribute, reattribute, sell, buy, rent, lease, destroy, or improve it, quote it at length, excerpt, incorporate, collate, fold, staple, or mutilate it, or do anything else to it that your or anyone else's heart desires." />
-<meta content="reStructuredText, test, parser" name="keywords" />
-<meta content="A test document, containing at least one example of each reStructuredText construct." lang="en" name="description" />
<link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" />
<link rel="stylesheet" href="../input/data/math.css" type="text/css" />
</head>
Modified: trunk/docutils/test/functional/expected/standalone_rst_html5.html
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_html5.html 2021-06-17 14:33:09 UTC (rev 8766)
+++ trunk/docutils/test/functional/expected/standalone_rst_html5.html 2021-06-17 14:33:28 UTC (rev 8767)
@@ -5,6 +5,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="generator" content="Docutils 0.18b.dev: http://docutils.sourceforge.net/" />
<title>reStructuredText Test Document</title>
+<meta content="reStructuredText, test, parser" name="keywords" />
+<meta content="A test document, containing at least one example of each reStructuredText construct." lang="en" name="description" xml:lang="en" />
<meta name="author" content="David Goodger" />
<meta name="author" content="Me" />
<meta name="author" content="Myself" />
@@ -11,8 +13,6 @@
<meta name="author" content="I" />
<meta name="dcterms.date" content="Now, or yesterday. Or maybe even before yesterday." />
<meta name="dcterms.rights" content="This document has been placed in the public domain. You may do with it as you wish. You may copy, modify, redistribute, reattribute, sell, buy, rent, lease, destroy, or improve it, quote it at length, excerpt, incorporate, collate, fold, staple, or mutilate it, or do anything else to it that your or anyone else's heart desires." />
-<meta content="reStructuredText, test, parser" name="keywords" />
-<meta content="A test document, containing at least one example of each reStructuredText construct." lang="en" name="description" xml:lang="en" />
<link rel="schema.dcterms" href="http://purl.org/dc/terms/"/>
<link rel="stylesheet" href="../input/data/minimal.css" type="text/css" />
<link rel="stylesheet" href="../input/data/plain.css" type="text/css" />
Modified: trunk/docutils/test/functional/expected/standalone_rst_pseudoxml.txt
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_pseudoxml.txt 2021-06-17 14:33:09 UTC (rev 8766)
+++ trunk/docutils/test/functional/expected/standalone_rst_pseudoxml.txt 2021-06-17 14:33:28 UTC (rev 8767)
@@ -3,6 +3,8 @@
reStructuredText Test Document
<subtitle ids="examples-of-syntax-constructs subtitle" names="examples\ of\ syntax\ constructs subtitle">
Examples of Syntax Constructs
+ <meta content="reStructuredText, test, parser" name="keywords">
+ <meta content="A test document, containing at least one example of each reStructuredText construct." lang="en" name="description">
<decoration>
<header>
<paragraph>
@@ -1995,8 +1997,6 @@
9
is used to specify metadata to be stored in,
e.g., HTML META tags or ODT file properties.
- <meta content="reStructuredText, test, parser" name="keywords">
- <meta content="A test document, containing at least one example of each reStructuredText construct." lang="en" name="description">
<target anonymous="1" ids="target-6" refuri="https://docutils.sourceforge.io/docs/ref/rst/directives.html#metadata">
<section ids="substitution-definitions" names="substitution\ definitions">
<title auto="1" refid="toc-entry-34">
Modified: trunk/docutils/test/test_parsers/test_rst/test_directives/test_meta.py
===================================================================
--- trunk/docutils/test/test_parsers/test_rst/test_directives/test_meta.py 2021-06-17 14:33:09 UTC (rev 8766)
+++ trunk/docutils/test/test_parsers/test_rst/test_directives/test_meta.py 2021-06-17 14:33:28 UTC (rev 8767)
@@ -67,9 +67,9 @@
""",
"""\
<document source="test data">
+ <meta content="content" name="name">
<paragraph>
Paragraph
- <meta content="content" name="name">
"""],
["""\
.. meta::
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2021-06-17 19:25:03
|
Revision: 8769
http://sourceforge.net/p/docutils/code/8769
Author: milde
Date: 2021-06-17 19:25:04 +0000 (Thu, 17 Jun 2021)
Log Message:
-----------
Apply patch #181 by John Thorvald Wodder II.
LaTeX Writer: Fix tocdepth when chapter/part in use.
Modified Paths:
--------------
trunk/docutils/HISTORY.txt
trunk/docutils/docutils/writers/latex2e/__init__.py
trunk/docutils/test/test_writers/test_latex2e.py
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2021-06-17 14:33:39 UTC (rev 8768)
+++ trunk/docutils/HISTORY.txt 2021-06-17 19:25:04 UTC (rev 8769)
@@ -58,6 +58,9 @@
- The setting `legacy_class_functions`_ now defaults to "False".
Adapt stylesheets modifying ``\DUadmonition`` and/or ``\DUtitle``.
+
+ - Apply patch #181 "Fix tocdepth when chapter/part in use" by
+ John Thorvald Wodder II.
* docutils/writers/latex2e/docutils.sty
Modified: trunk/docutils/docutils/writers/latex2e/__init__.py
===================================================================
--- trunk/docutils/docutils/writers/latex2e/__init__.py 2021-06-17 14:33:39 UTC (rev 8768)
+++ trunk/docutils/docutils/writers/latex2e/__init__.py 2021-06-17 19:25:04 UTC (rev 8769)
@@ -794,7 +794,22 @@
# unsupported levels
return 'DUtitle'
+ def latex_section_depth(self, depth):
+ """
+ Return LaTeX equivalent of Docutils section level `depth`.
+
+ Given the value of the ``:depth:`` option of the "contents" or
+ "sectnum" directive, return the corresponding value for the
+ LaTeX ``tocdepth`` or ``secnumdepth`` counters.
+ """
+ depth = min(depth, len(self.sections)) # limit to supported levels
+ if 'chapter' in self.sections:
+ depth -= 1
+ if self.sections[0] == 'part':
+ depth -= 1
+ return depth
+
class Table(object):
"""Manage a table while traversing.
@@ -1283,9 +1298,6 @@
# LaTeX Toc
# include all supported sections in toc and PDF bookmarks
# (or use documentclass-default (as currently))?
- ## if self.use_latex_toc:
- ## self.requirements['tocdepth'] = (r'\setcounter{tocdepth}{%d}' %
- ## len(self.d_class.sections))
# Section numbering
if settings.sectnum_xform: # section numbering by Docutils
@@ -1304,16 +1316,8 @@
# 4 paragraph
# 5 subparagraph
if secnumdepth is not None:
- # limit to supported levels
- secnumdepth = min(secnumdepth, len(self.d_class.sections))
- # adjust to document class and use_part_section settings
- if 'chapter' in self.d_class.sections:
- secnumdepth -= 1
- if self.d_class.sections[0] == 'part':
- secnumdepth -= 1
- PreambleCmds.secnumdepth = \
- r'\setcounter{secnumdepth}{%d}' % secnumdepth
-
+ PreambleCmds.secnumdepth = (r'\setcounter{secnumdepth}{%d}'
+ % self.d_class.latex_section_depth(secnumdepth))
# start with specified number:
if (hasattr(settings, 'sectnum_start') and
settings.sectnum_start != 1):
@@ -3166,10 +3170,11 @@
self.minitoc(node, title, depth)
return
if depth:
- self.out.append('\\setcounter{tocdepth}{%d}\n' % depth)
+ self.out.append('\n\\setcounter{tocdepth}{%d}\n'
+ % self.d_class.latex_section_depth(depth))
if title != 'Contents':
- self.out.append('\n\\renewcommand{\\contentsname}{%s}' %
- title)
+ self.out.append('\n\\renewcommand{\\contentsname}{%s}'
+ % title)
self.out.append('\n\\tableofcontents\n')
self.has_latex_toc = True
# ignore rest of node content
Modified: trunk/docutils/test/test_writers/test_latex2e.py
===================================================================
--- trunk/docutils/test/test_writers/test_latex2e.py 2021-06-17 14:33:39 UTC (rev 8768)
+++ trunk/docutils/test/test_writers/test_latex2e.py 2021-06-17 19:25:04 UTC (rev 8769)
@@ -23,6 +23,9 @@
s.generateTests(totest)
settings['use_latex_toc'] = True
s.generateTests(totest_latex_toc)
+ settings['documentclass'] = 'book'
+ s.generateTests(totest_latex_toc_book)
+ del settings['documentclass']
settings['use_latex_toc'] = False
settings['sectnum_xform'] = False
s.generateTests(totest_latex_sectnum)
@@ -120,6 +123,7 @@
totest = {}
totest_latex_toc = {}
+totest_latex_toc_book = {}
totest_latex_sectnum = {}
totest_latex_citations = {}
totest_stylesheet = {}
@@ -315,7 +319,65 @@
"""],
]
+totest_latex_toc['depth'] = [
+# input
+["""\
+.. contents::
+ :depth: 1
+first section
+-------------
+""",
+## # expected output
+head_template.substitute(dict(parts,
+ requirements=parts['requirements'] + '\\setcounter{secnumdepth}{0}\n'
+)) + r"""
+\phantomsection\label{contents}
+\pdfbookmark[1]{Contents}{contents}
+\setcounter{tocdepth}{1}
+
+\tableofcontents
+
+
+\section{first section%
+ \label{first-section}%
+}
+
+\end{document}
+"""],
+]
+
+totest_latex_toc_book['depth'] = [
+# input
+["""\
+.. contents::
+ :depth: 1
+
+first chapter
+-------------
+""",
+## # expected output
+head_template.substitute(dict(parts,
+ head_prefix=r"""\documentclass[a4paper]{book}
+""",
+ requirements=parts['requirements'] + '\\setcounter{secnumdepth}{0}\n'
+)) + r"""
+\phantomsection\label{contents}
+\pdfbookmark[1]{Contents}{contents}
+\setcounter{tocdepth}{0}
+
+\tableofcontents
+
+
+\chapter{first chapter%
+ \label{first-chapter}%
+}
+
+\end{document}
+"""],
+]
+
+
totest_latex_sectnum['no_sectnum'] = [
# input
["""\
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2021-06-18 18:54:15
|
Revision: 8770
http://sourceforge.net/p/docutils/code/8770
Author: milde
Date: 2021-06-18 18:54:14 +0000 (Fri, 18 Jun 2021)
Log Message:
-----------
nodes.document.make_id(): keep leading numbers and hyphens if possible.
I.e. if the id_prefix setting is non-empty.
Modified Paths:
--------------
trunk/docutils/HISTORY.txt
trunk/docutils/RELEASE-NOTES.txt
trunk/docutils/docutils/nodes.py
trunk/docutils/test/test_nodes.py
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2021-06-17 19:25:04 UTC (rev 8769)
+++ trunk/docutils/HISTORY.txt 2021-06-18 18:54:14 UTC (rev 8770)
@@ -16,11 +16,14 @@
* docutils/nodes.py
- - ``Node.traverse()`` returns an iterator instead of a list.
-
- Make meta__ a standard Docutils doctree node. Writers may ignore
"meta" nodes if they are not supported by the output format.
+ - ``Node.traverse()`` returns an iterator instead of a list.
+
+ - document.make_id(): Keep leading number and hyphen characters from `name`
+ if the id_prefix setting is non-empty.
+
__ docs/ref/doctree.html#meta
* docutils/parsers/rst/directives/html.py
Modified: trunk/docutils/RELEASE-NOTES.txt
===================================================================
--- trunk/docutils/RELEASE-NOTES.txt 2021-06-17 19:25:04 UTC (rev 8769)
+++ trunk/docutils/RELEASE-NOTES.txt 2021-06-18 18:54:14 UTC (rev 8770)
@@ -30,8 +30,8 @@
definition list with class value "details".
- Move attribution behind the blockquote to comply with the
- __`"living standard"`?
- HTML5__ allows <cite> elements inside a blockquote (cf. Example 16).
+ `"living standard"`__?
+ (HTML5__ allows <cite> elements inside a blockquote, cf. Example 16.)
__ https://html.spec.whatwg.org/#the-blockquote-element
__ https://www.w3.org/TR/html52/grouping-content.html#the-blockquote-element
@@ -42,14 +42,6 @@
we store the null-escaped text in Text nodes since 0.16 so there is no
additional information in the rawsource.
-* If the id_prefix_ setting is non-empty, leading number and hyphen characters
- will not be stripped from a `reference name`_ during `identifier
- normalization`_. This may change generated `identifier keys`.
-
- Example: with ``--id-prefix="DU-"``, a section with title "34. May"
- currently gets the identifier key ``DU-may`` and after the change the
- identifier key ``DU-34-may``.
-
* The default value for auto_id_prefix_ will change to "%". This means
auto-generated IDs will use the tag name as prefix. Set auto_id_prefix_ to
"id" if you want unchanged auto-IDs or to "%" if you want the new
@@ -72,8 +64,6 @@
.. _auto_id_prefix: docs/user/config.html#auto-id-prefix
.. _rst2html.py: docs/user/tools.html#rst2html-py
.. _reference name: docs/ref/rst/restructuredtext.html#reference-names
-.. _identifier normalization:
- docs/ref/rst/directives.html#identifier-normalization
.. _html_writer: docs/user/config.html#html-writer
@@ -80,28 +70,44 @@
Release 0.18.dev
================
-* Removed files:
-
- - ``iepngfix.htc`` and ``blank.gif`` (IE 6 workaround for `s5_html`).
+* Output changes:
-* Removed function: ``utils.unique_combinations``
- (obsoleted by ``itertools.combinations``).
+ Identifiers:
+ If the id_prefix_ setting is non-empty, leading number and hyphen
+ characters will not be stripped from a `reference name`_ during
+ `identifier normalization`_.
-* HTML5 writer: changes to HTML output
+ Example: with ``--id-prefix="DU-"``, a section with title "34. May"
+ currently gets the identifier key ``DU-may`` and after the change the
+ identifier key ``DU-34-may``.
- - Write footnote brackets and field term colons to HTML, so that
- they are present also without CSS and when copying text.
+ HTML5:
+ Write footnote brackets and field term colons to HTML, so that they
+ are present also without CSS and when copying text.
-* LaTeX writer: `legacy_class_functions`_ setting default changed to "False".
+ LaTeX:
+ `legacy_class_functions`_ setting default changed to
+ "False", admonitions are now environments.
* ``nodes.Node.traverse()`` returns an iterator instead of a list.
-
* Make meta__ a standard Docutils doctree node.
__ docs/ref/doctree.html#meta
+* Removed files:
+ - ``iepngfix.htc`` and ``blank.gif`` (IE 6 workaround for `s5_html`).
+
+* Removed function: ``utils.unique_combinations``
+ (obsoleted by ``itertools.combinations``).
+
+* Various bugfixes and improvements (see HISTORY_).
+
+.. _identifier normalization:
+ docs/ref/rst/directives.html#identifier-normalization
+
+
Release 0.17.1 (2021-04-16)
===========================
Modified: trunk/docutils/docutils/nodes.py
===================================================================
--- trunk/docutils/docutils/nodes.py 2021-06-17 19:25:04 UTC (rev 8769)
+++ trunk/docutils/docutils/nodes.py 2021-06-18 18:54:14 UTC (rev 8770)
@@ -1363,10 +1363,13 @@
base_id = ''
id = ''
for name in node['names']:
- base_id = make_id(name)
+ if id_prefix:
+ # allow names starting with numbers if `id_prefix`
+ base_id = make_id('x'+name)[1:]
+ else:
+ base_id = make_id(name)
+ # TODO: normalize id-prefix? (would make code simpler)
id = id_prefix + base_id
- # TODO: allow names starting with numbers if `id_prefix`
- # is non-empty: id = make_id(id_prefix + name)
if base_id and id not in self.ids:
break
else:
Modified: trunk/docutils/test/test_nodes.py
===================================================================
--- trunk/docutils/test/test_nodes.py 2021-06-17 19:25:04 UTC (rev 8769)
+++ trunk/docutils/test/test_nodes.py 2021-06-18 18:54:14 UTC (rev 8770)
@@ -701,7 +701,7 @@
self.assertEqual(ids, [['P-test'],
['P-auto1'],
['P-auto2'],
- ['P-auto3']])
+ ['P-2019-10-30']])
def test_set_id_descriptive_auto_id(self):
# Use name or tag-name for auto-id.
@@ -730,7 +730,7 @@
self.assertEqual(ids, [['P:test'],
['P:a-section-1'],
['P:test-1'],
- ['P:a-footnote-1']])
+ ['P:2019-10-30']])
class MiscFunctionTests(unittest.TestCase):
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2021-06-18 18:55:10
|
Revision: 8771
http://sourceforge.net/p/docutils/code/8771
Author: milde
Date: 2021-06-18 18:55:08 +0000 (Fri, 18 Jun 2021)
Log Message:
-----------
Change default value for the "auto_id_prefix" setting to "%".
Auto-generated IDs use the tag name as prefix.
Set auto_id_prefix_ to "id" if you want unchanged auto-IDs.
Modified Paths:
--------------
trunk/docutils/HISTORY.txt
trunk/docutils/RELEASE-NOTES.txt
trunk/docutils/docs/user/config.txt
trunk/docutils/docutils/frontend.py
trunk/docutils/test/functional/expected/odt_footnotes.odt
trunk/docutils/test/test_nodes.py
trunk/docutils/test/test_parsers/test_recommonmark/test_targets.py
trunk/docutils/test/test_parsers/test_rst/test_character_level_inline_markup.py
trunk/docutils/test/test_parsers/test_rst/test_citations.py
trunk/docutils/test/test_parsers/test_rst/test_definition_lists.py
trunk/docutils/test/test_parsers/test_rst/test_directives/test_include.py
trunk/docutils/test/test_parsers/test_rst/test_directives/test_line_blocks.py
trunk/docutils/test/test_parsers/test_rst/test_directives/test_replace.py
trunk/docutils/test/test_parsers/test_rst/test_directives/test_role.py
trunk/docutils/test/test_parsers/test_rst/test_directives/test_tables.py
trunk/docutils/test/test_parsers/test_rst/test_east_asian_text.py
trunk/docutils/test/test_parsers/test_rst/test_field_lists.py
trunk/docutils/test/test_parsers/test_rst/test_footnotes.py
trunk/docutils/test/test_parsers/test_rst/test_inline_markup.py
trunk/docutils/test/test_parsers/test_rst/test_interpreted.py
trunk/docutils/test/test_parsers/test_rst/test_line_blocks.py
trunk/docutils/test/test_parsers/test_rst/test_section_headers.py
trunk/docutils/test/test_parsers/test_rst/test_substitutions.py
trunk/docutils/test/test_parsers/test_rst/test_targets.py
trunk/docutils/test/test_publisher.py
trunk/docutils/test/test_readers/test_pep/test_inline_markup.py
trunk/docutils/test/test_transforms/test_contents.py
trunk/docutils/test/test_transforms/test_footnotes.py
trunk/docutils/test/test_transforms/test_hyperlinks.py
trunk/docutils/test/test_transforms/test_messages.py
trunk/docutils/test/test_transforms/test_peps.py
trunk/docutils/test/test_transforms/test_sectnum.py
trunk/docutils/test/test_transforms/test_smartquotes.py
trunk/docutils/test/test_transforms/test_substitution_expansion_length_limit.py
trunk/docutils/test/test_transforms/test_substitutions.py
trunk/docutils/test/test_transforms/test_target_notes.py
trunk/docutils/test/test_writers/test_latex2e.py
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2021-06-18 18:54:14 UTC (rev 8770)
+++ trunk/docutils/HISTORY.txt 2021-06-18 18:55:08 UTC (rev 8771)
@@ -14,18 +14,23 @@
Changes Since 0.17.1
====================
+* docutils/frontend.py
+
+ - The default value for the "auto_id_prefix" setting changed to "%":
+ auto-generated IDs use the tag name as prefix.
+
* docutils/nodes.py
- Make meta__ a standard Docutils doctree node. Writers may ignore
"meta" nodes if they are not supported by the output format.
+ __ docs/ref/doctree.html#meta
+
+ - document.make_id(): Keep leading number and hyphen characters
+ from `name` if the id_prefix setting is non-empty.
+
- ``Node.traverse()`` returns an iterator instead of a list.
-
- - document.make_id(): Keep leading number and hyphen characters from `name`
- if the id_prefix setting is non-empty.
- __ docs/ref/doctree.html#meta
-
* docutils/parsers/rst/directives/html.py
- Removed. (Meta directive moved to ``misc.py``.)
Modified: trunk/docutils/RELEASE-NOTES.txt
===================================================================
--- trunk/docutils/RELEASE-NOTES.txt 2021-06-18 18:54:14 UTC (rev 8770)
+++ trunk/docutils/RELEASE-NOTES.txt 2021-06-18 18:55:08 UTC (rev 8771)
@@ -42,11 +42,6 @@
we store the null-escaped text in Text nodes since 0.16 so there is no
additional information in the rawsource.
-* The default value for auto_id_prefix_ will change to "%". This means
- auto-generated IDs will use the tag name as prefix. Set auto_id_prefix_ to
- "id" if you want unchanged auto-IDs or to "%" if you want the new
- feature already in 0.17.
-
* The default HTML writer "html" with frontend ``rst2html.py`` may change
from "html4css1" to "html5".
@@ -60,8 +55,6 @@
* The html_writer_ option of the ``buildhtml.py`` application is
obsoleted by ``--writer`` and will be removed in future.
-.. _id_prefix: docs/user/config.html#id-prefix
-.. _auto_id_prefix: docs/user/config.html#auto-id-prefix
.. _rst2html.py: docs/user/tools.html#rst2html-py
.. _reference name: docs/ref/rst/restructuredtext.html#reference-names
.. _html_writer: docs/user/config.html#html-writer
@@ -77,10 +70,15 @@
characters will not be stripped from a `reference name`_ during
`identifier normalization`_.
- Example: with ``--id-prefix="DU-"``, a section with title "34. May"
- currently gets the identifier key ``DU-may`` and after the change the
- identifier key ``DU-34-may``.
+ Example:
+ with ``--id-prefix="DU-"``, a section with title "34. May"
+ currently gets the identifier key ``DU-may`` and after the
+ change the identifier key ``DU-34-may``.
+ The default value for the auto_id_prefix_ setting changed to "%":
+ use the tag name as prefix for auto-generated IDs.
+ Set auto_id_prefix_ to "id" if you want unchanged auto-IDs.
+
HTML5:
Write footnote brackets and field term colons to HTML, so that they
are present also without CSS and when copying text.
@@ -93,8 +91,6 @@
* Make meta__ a standard Docutils doctree node.
- __ docs/ref/doctree.html#meta
-
* Removed files:
- ``iepngfix.htc`` and ``blank.gif`` (IE 6 workaround for `s5_html`).
@@ -104,8 +100,11 @@
* Various bugfixes and improvements (see HISTORY_).
+__ docs/ref/doctree.html#meta
.. _identifier normalization:
docs/ref/rst/directives.html#identifier-normalization
+.. _id_prefix: docs/user/config.html#id-prefix
+.. _auto_id_prefix: docs/user/config.html#auto-id-prefix
Release 0.17.1 (2021-04-16)
Modified: trunk/docutils/docs/user/config.txt
===================================================================
--- trunk/docutils/docs/user/config.txt 2021-06-18 18:54:14 UTC (rev 8770)
+++ trunk/docutils/docs/user/config.txt 2021-06-18 18:55:08 UTC (rev 8771)
@@ -210,7 +210,7 @@
A trailing "%" is replaced with the tag name (new in Docutils 0.16).
-Default: "id" (`will change to "%" in future`__).
+Default: "%" (changed in 0.18 from "id").
Option: ``--auto-id-prefix`` (hidden, intended mainly for programmatic use).
.. _identifier normalization:
Modified: trunk/docutils/docutils/frontend.py
===================================================================
--- trunk/docutils/docutils/frontend.py 2021-06-18 18:54:14 UTC (rev 8770)
+++ trunk/docutils/docutils/frontend.py 2021-06-18 18:55:08 UTC (rev 8771)
@@ -556,7 +556,7 @@
['--help', '-h'], {'action': 'help'}),
# Typically not useful for non-programmatical use:
(SUPPRESS_HELP, ['--id-prefix'], {'default': ''}),
- (SUPPRESS_HELP, ['--auto-id-prefix'], {'default': 'id'}),
+ (SUPPRESS_HELP, ['--auto-id-prefix'], {'default': '%'}),
# Hidden options, for development use only:
(SUPPRESS_HELP, ['--dump-settings'], {'action': 'store_true'}),
(SUPPRESS_HELP, ['--dump-internals'], {'action': 'store_true'}),
Modified: trunk/docutils/test/functional/expected/odt_footnotes.odt
===================================================================
(Binary files differ)
Modified: trunk/docutils/test/test_nodes.py
===================================================================
--- trunk/docutils/test/test_nodes.py 2021-06-18 18:54:14 UTC (rev 8770)
+++ trunk/docutils/test/test_nodes.py 2021-06-18 18:55:08 UTC (rev 8771)
@@ -686,7 +686,8 @@
for element in self.elements:
self.document.set_id(element)
ids = [element['ids'] for element in self.elements]
- self.assertEqual(ids, [['test'], ['id1'], ['id2'], ['id3']])
+ self.assertEqual(ids, [['test'], ['section-1'],
+ ['test-1'], ['footnote-1']])
def test_set_id_custom(self):
# Custom prefixes.
Modified: trunk/docutils/test/test_parsers/test_recommonmark/test_targets.py
===================================================================
--- trunk/docutils/test/test_parsers/test_recommonmark/test_targets.py 2021-06-18 18:54:14 UTC (rev 8770)
+++ trunk/docutils/test/test_parsers/test_recommonmark/test_targets.py 2021-06-18 18:55:08 UTC (rev 8771)
@@ -107,10 +107,10 @@
Title
<paragraph>
Paragraph.
- <section dupnames="title" ids="id1">
+ <section dupnames="title" ids="title-1">
<title>
Title
- <system_message backrefs="id1" level="1" line="8" source="test data" type="INFO">
+ <system_message backrefs="title-1" level="1" line="8" source="test data" type="INFO">
<paragraph>
Duplicate implicit target name: "title".
<paragraph>
Modified: trunk/docutils/test/test_parsers/test_rst/test_character_level_inline_markup.py
===================================================================
--- trunk/docutils/test/test_parsers/test_rst/test_character_level_inline_markup.py 2021-06-18 18:54:14 UTC (rev 8770)
+++ trunk/docutils/test/test_parsers/test_rst/test_character_level_inline_markup.py 2021-06-18 18:55:08 UTC (rev 8771)
@@ -114,10 +114,10 @@
(escaped; whitespace before end-string).
<paragraph>
However, '
- <problematic ids="id2" refid="id1">
+ <problematic ids="problematic-1" refid="system-message-1">
*
args' triggers a warning.
- <system_message backrefs="id2" ids="id1" level="2" line="15" source="test data" type="WARNING">
+ <system_message backrefs="problematic-1" ids="system-message-1" level="2" line="15" source="test data" type="WARNING">
<paragraph>
Inline emphasis start-string without end-string.
<paragraph>
@@ -124,10 +124,10 @@
Also \n\
<emphasis>
this
- <problematic ids="id4" refid="id3">
+ <problematic ids="problematic-2" refid="system-message-2">
*
.
- <system_message backrefs="id4" ids="id3" level="2" line="17" source="test data" type="WARNING">
+ <system_message backrefs="problematic-2" ids="system-message-2" level="2" line="17" source="test data" type="WARNING">
<paragraph>
Inline emphasis start-string without end-string.
"""],
@@ -214,10 +214,10 @@
"""\
<document source="test data">
<paragraph>
- <problematic ids="id2" refid="id1">
+ <problematic ids="problematic-1" refid="system-message-1">
``
literal without closing backquotes
- <system_message backrefs="id2" ids="id1" level="2" line="1" source="test data" type="WARNING">
+ <system_message backrefs="problematic-1" ids="system-message-1" level="2" line="1" source="test data" type="WARNING">
<paragraph>
Inline literal start-string without end-string.
"""],
@@ -328,20 +328,20 @@
<document source="test data">
<paragraph>
Adjacent footnote refs are possible with simple-inline-markup:
- <footnote_reference auto="*" ids="id1">
- <footnote_reference auto="1" ids="id2" refname="label">
+ <footnote_reference auto="*" ids="footnote-reference-1">
+ <footnote_reference auto="1" ids="footnote-reference-2" refname="label">
\n\
- <footnote_reference auto="1" ids="id3">
- <footnote_reference ids="id4" refname="2">
+ <footnote_reference auto="1" ids="footnote-reference-3">
+ <footnote_reference ids="footnote-reference-4" refname="2">
2
\n\
- <footnote_reference ids="id5" refname="1">
+ <footnote_reference ids="footnote-reference-5" refname="1">
1
- <footnote_reference auto="*" ids="id6">
- <footnote auto="1" ids="id7">
+ <footnote_reference auto="*" ids="footnote-reference-6">
+ <footnote auto="1" ids="footnote-1">
<paragraph>
test1
- <footnote auto="*" ids="id8">
+ <footnote auto="*" ids="footnote-2">
<paragraph>
test2
"""],
@@ -356,9 +356,9 @@
<document source="test data">
<paragraph>
Adjacent citation refs are possible with simple-inline-markup:
- <citation_reference ids="id1" refname="citation">
+ <citation_reference ids="citation-reference-1" refname="citation">
citation
- <citation_reference ids="id2" refname="cit1">
+ <citation_reference ids="citation-reference-2" refname="cit1">
CIT1
"""],
]
@@ -399,7 +399,7 @@
<paragraph>
<reference refuri="http://example.com/*content">
http://example.com/*content
- <problematic ids="id2" refid="id1">
+ <problematic ids="problematic-1" refid="system-message-1">
*
/whatever
<reference refuri="http://example.com/">
@@ -407,7 +407,7 @@
<reference name="rST_for" refname="rst_for">
rST_for
all.html
- <system_message backrefs="id2" ids="id1" level="2" line="8" source="test data" type="WARNING">
+ <system_message backrefs="problematic-1" ids="system-message-1" level="2" line="8" source="test data" type="WARNING">
<paragraph>
Inline emphasis start-string without end-string.
"""],
Modified: trunk/docutils/test/test_parsers/test_rst/test_citations.py
===================================================================
--- trunk/docutils/test/test_parsers/test_rst/test_citations.py 2021-06-18 18:54:14 UTC (rev 8770)
+++ trunk/docutils/test/test_parsers/test_rst/test_citations.py 2021-06-18 18:55:08 UTC (rev 8771)
@@ -156,7 +156,7 @@
citation.withdot
<paragraph>
one dot
- <citation ids="id1" names="citation-withdot">
+ <citation ids="citation-withdot-1" names="citation-withdot">
<label>
citation-withdot
<paragraph>
Modified: trunk/docutils/test/test_parsers/test_rst/test_definition_lists.py
===================================================================
--- trunk/docutils/test/test_parsers/test_rst/test_definition_lists.py 2021-06-18 18:54:14 UTC (rev 8770)
+++ trunk/docutils/test/test_parsers/test_rst/test_definition_lists.py 2021-06-18 18:55:08 UTC (rev 8771)
@@ -299,75 +299,75 @@
<definition_list_item>
<term>
Term \n\
- <problematic ids="id2" refid="id1">
+ <problematic ids="problematic-1" refid="system-message-1">
`
with \n\
- <problematic ids="id4" refid="id3">
+ <problematic ids="problematic-2" refid="system-message-2">
*
inline \n\
- <problematic ids="id6" refid="id5">
+ <problematic ids="problematic-3" refid="system-message-3">
``
text \n\
- <problematic ids="id8" refid="id7">
+ <problematic ids="problematic-4" refid="system-message-4">
**
errors
<classifier>
classifier \n\
- <problematic ids="id10" refid="id9">
+ <problematic ids="problematic-5" refid="system-message-5">
`
with \n\
- <problematic ids="id12" refid="id11">
+ <problematic ids="problematic-6" refid="system-message-6">
*
errors \n\
- <problematic ids="id14" refid="id13">
+ <problematic ids="problematic-7" refid="system-message-7">
``
too
<definition>
- <system_message backrefs="id2" ids="id1" level="2" line="1" source="test data" type="WARNING">
+ <system_message backrefs="problematic-1" ids="system-message-1" level="2" line="1" source="test data" type="WARNING">
<paragraph>
Inline interpreted text or phrase reference start-string without end-string.
- <system_message backrefs="id4" ids="id3" level="2" line="1" source="test data" type="WARNING">
+ <system_message backrefs="problematic-2" ids="system-message-2" level="2" line="1" source="test data" type="WARNING">
<paragraph>
Inline emphasis start-string without end-string.
- <system_message backrefs="id6" ids="id5" level="2" line="1" source="test data" type="WARNING">
+ <system_message backrefs="problematic-3" ids="system-message-3" level="2" line="1" source="test data" type="WARNING">
<paragraph>
Inline literal start-string without end-string.
- <system_message backrefs="id8" ids="id7" level="2" line="1" source="test data" type="WARNING">
+ <system_message backrefs="problematic-4" ids="system-message-4" level="2" line="1" source="test data" type="WARNING">
<paragraph>
Inline strong start-string without end-string.
- <system_message backrefs="id10" ids="id9" level="2" line="1" source="test data" type="WARNING">
+ <system_message backrefs="problematic-5" ids="system-message-5" level="2" line="1" source="test data" type="WARNING">
<paragraph>
Inline interpreted text or phrase reference start-string without end-string.
- <system_message backrefs="id12" ids="id11" level="2" line="1" source="test data" type="WARNING">
+ <system_message backrefs="problematic-6" ids="system-message-6" level="2" line="1" source="test data" type="WARNING">
<paragraph>
Inline emphasis start-string without end-string.
- <system_message backrefs="id14" ids="id13" level="2" line="1" source="test data" type="WARNING">
+ <system_message backrefs="problematic-7" ids="system-message-7" level="2" line="1" source="test data" type="WARNING">
<paragraph>
Inline literal start-string without end-string.
<paragraph>
Definition \n\
- <problematic ids="id16" refid="id15">
+ <problematic ids="problematic-8" refid="system-message-8">
`
with \n\
- <problematic ids="id18" refid="id17">
+ <problematic ids="problematic-9" refid="system-message-9">
*
inline \n\
- <problematic ids="id20" refid="id19">
+ <problematic ids="problematic-10" refid="system-message-10">
``
text \n\
- <problematic ids="id22" refid="id21">
+ <problematic ids="problematic-11" refid="system-message-11">
**
markup errors.
- <system_message backrefs="id16" ids="id15" level="2" line="2" source="test data" type="WARNING">
+ <system_message backrefs="problematic-8" ids="system-message-8" level="2" line="2" source="test data" type="WARNING">
<paragraph>
Inline interpreted text or phrase reference start-string without end-string.
- <system_message backrefs="id18" ids="id17" level="2" line="2" source="test data" type="WARNING">
+ <system_message backrefs="problematic-9" ids="system-message-9" level="2" line="2" source="test data" type="WARNING">
<paragraph>
Inline emphasis start-string without end-string.
- <system_message backrefs="id20" ids="id19" level="2" line="2" source="test data" type="WARNING">
+ <system_message backrefs="problematic-10" ids="system-message-10" level="2" line="2" source="test data" type="WARNING">
<paragraph>
Inline literal start-string without end-string.
- <system_message backrefs="id22" ids="id21" level="2" line="2" source="test data" type="WARNING">
+ <system_message backrefs="problematic-11" ids="system-message-11" level="2" line="2" source="test data" type="WARNING">
<paragraph>
Inline strong start-string without end-string.
"""],
Modified: trunk/docutils/test/test_parsers/test_rst/test_directives/test_include.py
===================================================================
--- trunk/docutils/test/test_parsers/test_rst/test_directives/test_include.py 2021-06-18 18:54:14 UTC (rev 8770)
+++ trunk/docutils/test/test_parsers/test_rst/test_directives/test_include.py 2021-06-18 18:55:08 UTC (rev 8771)
@@ -307,10 +307,10 @@
<literal>
test_include.py
.
- <section dupnames="inclusion\\ 1" ids="id1">
+ <section dupnames="inclusion\\ 1" ids="inclusion-1-1">
<title>
Inclusion 1
- <system_message backrefs="id1" level="1" line="2" source="%s" type="INFO">
+ <system_message backrefs="inclusion-1-1" level="1" line="2" source="%s" type="INFO">
<paragraph>
Duplicate implicit target name: "inclusion 1".
<paragraph>
@@ -347,10 +347,10 @@
test_include.py
.
<transition>
- <section dupnames="inclusion\\ 1" ids="id1">
+ <section dupnames="inclusion\\ 1" ids="inclusion-1-1">
<title>
Inclusion 1
- <system_message backrefs="id1" level="1" line="2" source="%s" type="INFO">
+ <system_message backrefs="inclusion-1-1" level="1" line="2" source="%s" type="INFO">
<paragraph>
Duplicate implicit target name: "inclusion 1".
<paragraph>
@@ -551,10 +551,10 @@
Block quote ends without a blank line; unexpected unindent.
<paragraph>
error
- <section dupnames="hi" ids="id1">
+ <section dupnames="hi" ids="hi-1">
<title>
hi
- <system_message backrefs="id1" level="1" line="10" source="%(source)s" type="INFO">
+ <system_message backrefs="hi-1" level="1" line="10" source="%(source)s" type="INFO">
<paragraph>
Duplicate implicit target name: "hi".
<system_message level="4" line="12" source="%(source)s" type="SEVERE">
@@ -698,17 +698,17 @@
<paragraph>
$ with inconsistent quoting.
<paragraph>
- <problematic ids="id3" refid="id2">
+ <problematic ids="problematic-1" refid="system-message-1">
:unknown-role:`role`
\n\
and \n\
- <problematic ids="id5" refid="id4">
+ <problematic ids="problematic-2" refid="system-message-2">
*
unbalanced
- <problematic ids="id7" refid="id6">
+ <problematic ids="problematic-3" refid="system-message-3">
`
inline
- <problematic ids="id9" refid="id8">
+ <problematic ids="problematic-4" refid="system-message-4">
**
markup
<system_message level="1" line="63" source="%(source)s" type="INFO">
@@ -715,22 +715,22 @@
<paragraph>
No role entry for "unknown-role" in module "docutils.parsers.rst.languages.en".
Trying "unknown-role" as canonical role name.
- <system_message backrefs="id3" ids="id2" level="3" line="63" source="%(source)s" type="ERROR">
+ <system_message backrefs="problematic-1" ids="system-message-1" level="3" line="63" source="%(source)s" type="ERROR">
<paragraph>
Unknown interpreted text role "unknown-role".
- <system_message backrefs="id5" ids="id4" level="2" line="63" source="%(source)s" type="WARNING">
+ <system_message backrefs="problematic-2" ids="system-message-2" level="2" line="63" source="%(source)s" type="WARNING">
<paragraph>
Inline emphasis start-string without end-string.
- <system_message backrefs="id7" ids="id6" level="2" line="63" source="%(source)s" type="WARNING">
+ <system_message backrefs="problematic-3" ids="system-message-3" level="2" line="63" source="%(source)s" type="WARNING">
<paragraph>
Inline interpreted text or phrase reference start-string without end-string.
- <system_message backrefs="id9" ids="id8" level="2" line="63" source="%(source)s" type="WARNING">
+ <system_message backrefs="problematic-4" ids="system-message-4" level="2" line="63" source="%(source)s" type="WARNING">
<paragraph>
Inline strong start-string without end-string.
<paragraph>
- <problematic ids="id11" refid="id10">
+ <problematic ids="problematic-5" refid="system-message-5">
:PEP:`-1`
- <system_message backrefs="id11" ids="id10" level="3" line="68" source="%(source)s" type="ERROR">
+ <system_message backrefs="problematic-5" ids="system-message-5" level="3" line="68" source="%(source)s" type="ERROR">
<paragraph>
PEP number must be a number from 0 to 9999; "-1" is invalid.
<system_message level="1" line="66" source="%(source)s" type="INFO">
Modified: trunk/docutils/test/test_parsers/test_rst/test_directives/test_line_blocks.py
===================================================================
--- trunk/docutils/test/test_parsers/test_rst/test_directives/test_line_blocks.py 2021-06-18 18:54:14 UTC (rev 8770)
+++ trunk/docutils/test/test_parsers/test_rst/test_directives/test_line_blocks.py 2021-06-18 18:55:08 UTC (rev 8771)
@@ -67,13 +67,13 @@
<line_block>
<line>
Inline markup \n\
- <problematic ids="id2" refid="id1">
+ <problematic ids="problematic-1" refid="system-message-1">
*
may not span
<line_block>
<line>
multiple lines* of a line block.
- <system_message backrefs="id2" ids="id1" level="2" line="3" source="test data" type="WARNING">
+ <system_message backrefs="problematic-1" ids="system-message-1" level="2" line="3" source="test data" type="WARNING">
<paragraph>
Inline emphasis start-string without end-string.
"""],
Modified: trunk/docutils/test/test_parsers/test_rst/test_directives/test_replace.py
===================================================================
--- trunk/docutils/test/test_parsers/test_rst/test_directives/test_replace.py 2021-06-18 18:54:14 UTC (rev 8770)
+++ trunk/docutils/test/test_parsers/test_rst/test_directives/test_replace.py 2021-06-18 18:55:08 UTC (rev 8771)
@@ -101,13 +101,13 @@
""",
"""\
<document source="test data">
- <system_message ids="id1" level="2" line="1" source="test data" type="WARNING">
+ <system_message ids="system-message-1" level="2" line="1" source="test data" type="WARNING">
<paragraph>
Inline emphasis start-string without end-string.
- <system_message ids="id3" level="2" line="1" source="test data" type="WARNING">
+ <system_message ids="system-message-2" level="2" line="1" source="test data" type="WARNING">
<paragraph>
Inline strong start-string without end-string.
- <system_message ids="id5" level="2" line="1" source="test data" type="WARNING">
+ <system_message ids="system-message-3" level="2" line="1" source="test data" type="WARNING">
<paragraph>
Inline literal start-string without end-string.
<system_message level="3" line="1" source="test data" type="ERROR">
@@ -114,7 +114,7 @@
<paragraph>
Substitution definition contains illegal element <problematic>:
<literal_block xml:space="preserve">
- <problematic ids="id2" refid="id1">
+ <problematic ids="problematic-1" refid="system-message-1">
*
<literal_block xml:space="preserve">
.. |name| replace:: *error in **inline ``markup
Modified: trunk/docutils/test/test_parsers/test_rst/test_directives/test_role.py
===================================================================
--- trunk/docutils/test/test_parsers/test_rst/test_directives/test_role.py 2021-06-18 18:54:14 UTC (rev 8770)
+++ trunk/docutils/test/test_parsers/test_rst/test_directives/test_role.py 2021-06-18 18:55:08 UTC (rev 8771)
@@ -65,7 +65,7 @@
<document source="test data">
<paragraph>
Must define \n\
- <problematic ids="id2" refid="id1">
+ <problematic ids="problematic-1" refid="system-message-1">
:custom:`interpreted`
before using it.
<system_message level="1" line="1" source="test data" type="INFO">
@@ -72,7 +72,7 @@
<paragraph>
No role entry for "custom" in module "docutils.parsers.rst.languages.en".
Trying "custom" as canonical role name.
- <system_message backrefs="id2" ids="id1" level="3" line="1" source="test data" type="ERROR">
+ <system_message backrefs="problematic-1" ids="system-message-1" level="3" line="1" source="test data" type="ERROR">
<paragraph>
Unknown interpreted text role "custom".
<paragraph>
@@ -263,10 +263,10 @@
<document source="test data">
<paragraph>
Can't use the \n\
- <problematic ids="id2" refid="id1">
+ <pr...
[truncated message content] |
|
From: <mi...@us...> - 2021-06-25 20:56:24
|
Revision: 8772
http://sourceforge.net/p/docutils/code/8772
Author: milde
Date: 2021-06-25 20:56:23 +0000 (Fri, 25 Jun 2021)
Log Message:
-----------
HTML5: small fixes, preparation for footnote handling refactoring.
Modified Paths:
--------------
trunk/docutils/docs/ref/doctree.txt
trunk/docutils/docs/user/config.txt
trunk/docutils/docutils/parsers/rst/states.py
trunk/docutils/docutils/writers/_html_base.py
trunk/docutils/docutils/writers/html5_polyglot/math.css
trunk/docutils/docutils/writers/html5_polyglot/minimal.css
trunk/docutils/docutils/writers/html5_polyglot/plain.css
trunk/docutils/docutils/writers/html5_polyglot/responsive.css
Modified: trunk/docutils/docs/ref/doctree.txt
===================================================================
--- trunk/docutils/docs/ref/doctree.txt 2021-06-18 18:55:08 UTC (rev 8771)
+++ trunk/docutils/docs/ref/doctree.txt 2021-06-25 20:56:23 UTC (rev 8772)
@@ -2379,16 +2379,27 @@
``footnote`` is similar to the `DocBook "footnote"`_ element but does
not create a footnote_reference_.
- There is `no equivalent in HTML`__. The ARIA_ role `"note"`__, or the
- DPub-ARIA role `"doc-footnote"`__ may be used semantically represent
- footnotes in HTML. As the spatial positioning is not determined,
- the corresponding `epub:type`__ is the deprecated "note" (rather
- than "footnote" or "endnote").
+ There is `no equivalent in HTML`__. The ARIA role `"note"`__ may be
+ used to mark an `<aside> or <section> element`__ as "a section whose
+ content is parenthetic or ancillary to the main content of the
+ resource".
+ ``footnote`` elements can be used for both,
+
+ * notes that occur within the body of the document (`epub:type`__
+ *footnote* or DPub-ARIA role `"doc-footnote"`__) or
+
+ * collections of notes that occur at the end of a section or the
+ document (`epub:type` *endnote*,DPub-ARIA role
+ `"doc-endnotes"`__).
+
+
__ https://www.w3.org/TR/html51/common-idioms-without-dedicated-elements.html#footnotes
__ https://www.w3.org/TR/wai-aria-1.1/#note
+ __ https://www.w3.org/TR/html-aria/#docconformance
+ __ https://idpf.github.io/epub-vocabs/structure/#notes
__ https://www.w3.org/TR/dpub-aria-1.0/#doc-footnote
- __ https://idpf.github.io/epub-vocabs/structure/#notes
+ __ https://www.w3.org/TR/dpub-aria-1.0/#doc-endnotes
:Processing:
A ``footnote`` element should be set off from the rest of the
Modified: trunk/docutils/docs/user/config.txt
===================================================================
--- trunk/docutils/docs/user/config.txt 2021-06-18 18:55:08 UTC (rev 8771)
+++ trunk/docutils/docs/user/config.txt 2021-06-25 20:56:23 UTC (rev 8772)
@@ -215,7 +215,6 @@
.. _identifier normalization:
../ref/rst/directives.html#identifier-normalization
-__ ../../RELEASE-NOTES.html#future-changes
datestamp
---------
Modified: trunk/docutils/docutils/parsers/rst/states.py
===================================================================
--- trunk/docutils/docutils/parsers/rst/states.py 2021-06-18 18:55:08 UTC (rev 8771)
+++ trunk/docutils/docutils/parsers/rst/states.py 2021-06-25 20:56:23 UTC (rev 8772)
@@ -328,7 +328,7 @@
def check_subsection(self, source, style, lineno):
"""
- Check for a valid subsection header. Return 1 (true) or None (false).
+ Check for a valid subsection header. Return True or False.
When a new section is reached that isn't a subsection of the current
section, back up the line count (use ``previous_line(-x)``), then
@@ -350,10 +350,10 @@
except ValueError: # new title style
if len(title_styles) == memo.section_level: # new subsection
title_styles.append(style)
- return 1
+ return True
else: # not at lowest level
self.parent += self.title_inconsistent(source, lineno)
- return None
+ return False
if level <= mylevel: # sibling or supersection
memo.section_level = level # bubble up to parent section
if len(style) == 2:
@@ -362,10 +362,10 @@
self.state_machine.previous_line(len(style) + 1)
raise EOFError # let parent section re-evaluate
if level == mylevel + 1: # immediate subsection
- return 1
+ return True
else: # invalid subsection
self.parent += self.title_inconsistent(source, lineno)
- return None
+ return False
def title_inconsistent(self, sourcetext, lineno):
error = self.reporter.severe(
Modified: trunk/docutils/docutils/writers/_html_base.py
===================================================================
--- trunk/docutils/docutils/writers/_html_base.py 2021-06-18 18:55:08 UTC (rev 8771)
+++ trunk/docutils/docutils/writers/_html_base.py 2021-06-25 20:56:23 UTC (rev 8772)
@@ -335,7 +335,6 @@
self.compact_field_list = False
self.in_docinfo = False
self.in_sidebar = False
- self.in_footnote_list = False
self.title = []
self.subtitle = []
self.header = []
@@ -624,22 +623,10 @@
self.body.append('</p>\n')
def visit_citation(self, node):
- # Use definition list for bibliographic references.
- # Join adjacent citation entries.
- # TODO: use <aside>.
- if not self.in_footnote_list:
- listnode = node.copy()
- listnode['ids'] = []
- self.body.append(self.starttag(listnode, 'dl', CLASS='citation'))
- # self.body.append('<dl class="citation">\n')
- self.in_footnote_list = True
+ self.visit_footnote(node)
def depart_citation(self, node):
- self.body.append('</dd>\n')
- if not isinstance(node.next_node(descend=False, siblings=True),
- nodes.citation):
- self.body.append('</dl>\n')
- self.in_footnote_list = False
+ self.depart_footnote(node)
def visit_citation_reference(self, node):
href = '#'
@@ -935,7 +922,6 @@
def depart_figure(self, node):
self.body.append('</div>\n')
- # use HTML 5 <footer> element?
def visit_footer(self, node):
self.context.append(len(self.body))
@@ -950,19 +936,21 @@
del self.body[start:]
def visit_footnote(self, node):
- if not self.in_footnote_list:
+ previous_node = node.parent[node.parent.index(node)-1]
+ if not isinstance(previous_node, type(node)):
listnode = node.copy()
listnode['ids'] = []
- classes = 'footnote ' + self.settings.footnote_references
+ if isinstance(node, nodes.citation):
+ classes = 'citation'
+ else:
+ classes = 'footnote ' + self.settings.footnote_references
self.body.append(self.starttag(listnode, 'dl', CLASS=classes))
- self.in_footnote_list = True
def depart_footnote(self, node):
self.body.append('</dd>\n')
if not isinstance(node.next_node(descend=False, siblings=True),
- nodes.footnote):
+ type(node)):
self.body.append('</dl>\n')
- self.in_footnote_list = False
def visit_footnote_reference(self, node):
href = '#' + node['refid']
Modified: trunk/docutils/docutils/writers/html5_polyglot/math.css
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/math.css 2021-06-18 18:55:08 UTC (rev 8771)
+++ trunk/docutils/docutils/writers/html5_polyglot/math.css 2021-06-25 20:56:23 UTC (rev 8772)
@@ -88,7 +88,7 @@
padding: 0ex;
border-top: thin solid;
}
-sub, sup {
+math sub, math sup {
font-size: 80%;
}
sup.numerator, sup.unit {
Modified: trunk/docutils/docutils/writers/html5_polyglot/minimal.css
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/minimal.css 2021-06-18 18:55:08 UTC (rev 8771)
+++ trunk/docutils/docutils/writers/html5_polyglot/minimal.css 2021-06-25 20:56:23 UTC (rev 8772)
@@ -1,8 +1,8 @@
/* Minimal style sheet for the HTML output of Docutils. */
/* */
/* :Author: Günter Milde, based on html4css1.css by David Goodger */
-/* :Id: $Id$ */
-/* :Copyright: © 2015 Günter Milde. */
+/* :Id: $Id$ */
+/* :Copyright: © 2015, 2021 Günter Milde. */
/* :License: Released under the terms of the `2-Clause BSD license`_, */
/* in short: */
/* */
@@ -14,11 +14,10 @@
/* */
/* .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause */
-/* This CSS2.1_ stylesheet defines rules for Docutils elements without */
-/* HTML equivalent. It is required to make the document semantic visible. */
-/* */
-/* .. _CSS2.1: http://www.w3.org/TR/CSS2 */
-/* .. _validates: http://jigsaw.w3.org/css-validator/validator$link */
+/* This CSS3 stylesheet defines rules for Docutils elements without */
+/* HTML equivalent. It is required to make the document semantics visible. */
+/* */
+/* .. _validates: http://jigsaw.w3.org/css-validator/validator$link */
/* titles */
p.topic-title,
@@ -76,7 +75,6 @@
/* Nested Paragraphs */
p:first-child { margin-top: 0; }
p:last-child { margin-bottom: 0; }
-td > p, th > p { margin-bottom: 0; }
/* Table of Contents */
.topic.contents { margin: 0.5em 0; }
Modified: trunk/docutils/docutils/writers/html5_polyglot/plain.css
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/plain.css 2021-06-18 18:55:08 UTC (rev 8771)
+++ trunk/docutils/docutils/writers/html5_polyglot/plain.css 2021-06-25 20:56:23 UTC (rev 8772)
@@ -27,7 +27,7 @@
--field-indent: 9em; /* default indent of fields in field lists */
}
main, footer, header {
- line-height:1.3;
+ line-height:1.6;
/* avoid long lines --> better reading */
/* optimum is 45…75 characters/line <http://webtypography.net/2.1.2> */
/* OTOH: lines should not be too short because of missing hyphenation, */
@@ -59,14 +59,12 @@
p, ol, ul, dl, li,
div.line-block,
div.topic,
+.footnote, .citation,
div > math,
table {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
-p:first-child { margin-top: 0; }
-/* (:last-child is new in CSS 3) */
-p:last-child { margin-bottom: 0; }
h1, h2, h3, h4, h5, h6, dd {
margin-bottom: 0.5em;
@@ -278,6 +276,8 @@
/* Inline Markup */
/* ============= */
+sup, sub { line-height: 0.8; } /* do not add leading for lines with sup/sub */
+
/* Inline Literals */
/* possible values: normal, nowrap, pre, pre-wrap, pre-line */
/* span.docutils.literal { white-space: pre-wrap; } */
Modified: trunk/docutils/docutils/writers/html5_polyglot/responsive.css
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/responsive.css 2021-06-18 18:55:08 UTC (rev 8771)
+++ trunk/docutils/docutils/writers/html5_polyglot/responsive.css 2021-06-25 20:56:23 UTC (rev 8772)
@@ -40,11 +40,15 @@
margin: auto;
max-width: 100rem;
}
+sup, sub { /* avoid additional inter-line space for lines with sup/sub */
+ line-height: 1;
+}
/* Vertical Space (Parskip) */
p, ol, ul, dl, li,
div.line-block,
div.topic,
+.footnote, .citation,
div > math,
table {
margin-top: 0.5em;
@@ -173,17 +177,10 @@
}
/* Footnotes and Citations */
-dl.footnote {
+.footnote {
font-size: small;
- padding-left: 0.5em;
- border-left: solid;
- border-left-width: thin;
}
-dl.citation > dt.label span.fn-bracket {
- display: none;
-}
-
/* Images, Figures, and Tables */
img {
display: block;
@@ -281,10 +278,10 @@
overflow-wrap: inherit;
}
/* Undecorated Links */
-/* a.footnote-reference, a.fn-backref, .fn-backref a, */
/* a.citation-reference, */
+/* .contents a, */
.citation a.fn-backref,
-.contents a, a.toc-backref {
+a.toc-backref {
color: inherit;
}
a:link:hover {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2021-06-25 20:56:47
|
Revision: 8773
http://sourceforge.net/p/docutils/code/8773
Author: milde
Date: 2021-06-25 20:56:46 +0000 (Fri, 25 Jun 2021)
Log Message:
-----------
HTML5: Semantic markup for footnotes.
Use "aside" instead of a description list for footnotes and citations.
While providing decent standard rendering, footnote label and text
are no instance of a "definition term" and "definition".
Use "invisible" footnote label brackets instead of display="none"
with superscript footnotes so that the brackets are kept with
drag-and-drop.
Adapt stylesheets.
Modified Paths:
--------------
trunk/docutils/RELEASE-NOTES.txt
trunk/docutils/docutils/writers/_html_base.py
trunk/docutils/docutils/writers/html5_polyglot/__init__.py
trunk/docutils/docutils/writers/html5_polyglot/minimal.css
trunk/docutils/docutils/writers/html5_polyglot/plain.css
trunk/docutils/docutils/writers/html5_polyglot/responsive.css
trunk/docutils/docutils/writers/html5_polyglot/tuftig.css
trunk/docutils/test/functional/expected/footnotes_html5.html
trunk/docutils/test/functional/expected/standalone_rst_html5.html
trunk/docutils/test/functional/input/footnotes.txt
Modified: trunk/docutils/RELEASE-NOTES.txt
===================================================================
--- trunk/docutils/RELEASE-NOTES.txt 2021-06-25 20:56:23 UTC (rev 8772)
+++ trunk/docutils/RELEASE-NOTES.txt 2021-06-25 20:56:46 UTC (rev 8773)
@@ -22,7 +22,7 @@
* `html5` writer:
- - Use semantic tags <aside> for footnote text, citations, for topics
+ - Use semantic tags <aside> for topics
(except abstract), admonitions, and system messages, and <nav> for
the Table of Contents.
@@ -70,7 +70,7 @@
characters will not be stripped from a `reference name`_ during
`identifier normalization`_.
- Example:
+ Example:
with ``--id-prefix="DU-"``, a section with title "34. May"
currently gets the identifier key ``DU-may`` and after the
change the identifier key ``DU-34-may``.
@@ -83,6 +83,8 @@
Write footnote brackets and field term colons to HTML, so that they
are present also without CSS and when copying text.
+ Use semantic tag <aside> for footnote text and citations.
+
LaTeX:
`legacy_class_functions`_ setting default changed to
"False", admonitions are now environments.
Modified: trunk/docutils/docutils/writers/_html_base.py
===================================================================
--- trunk/docutils/docutils/writers/_html_base.py 2021-06-25 20:56:23 UTC (rev 8772)
+++ trunk/docutils/docutils/writers/_html_base.py 2021-06-25 20:56:46 UTC (rev 8773)
@@ -417,7 +417,7 @@
ids = []
for (name, value) in attributes.items():
atts[name.lower()] = value
- classes = []
+ classes = atts.pop('classes', [])
languages = []
# unify class arguments and move language specification
for cls in node.get('classes', []) + atts.pop('class', '').split():
@@ -935,22 +935,17 @@
self.body_suffix[:0] = footer
del self.body[start:]
+ # use HTML5 element <aside> with ARIA role "note" for footnote text
+ # (the html4css1 writer uses a table instead).
def visit_footnote(self, node):
- previous_node = node.parent[node.parent.index(node)-1]
- if not isinstance(previous_node, type(node)):
- listnode = node.copy()
- listnode['ids'] = []
- if isinstance(node, nodes.citation):
- classes = 'citation'
- else:
- classes = 'footnote ' + self.settings.footnote_references
- self.body.append(self.starttag(listnode, 'dl', CLASS=classes))
+ classes = [node.tagname]
+ if isinstance(node, nodes.footnote):
+ classes.append(self.settings.footnote_references)
+ self.body.append(self.starttag(node, 'aside',
+ classes=classes, role="note"))
def depart_footnote(self, node):
- self.body.append('</dd>\n')
- if not isinstance(node.next_node(descend=False, siblings=True),
- type(node)):
- self.body.append('</dl>\n')
+ self.body.append('</aside>\n')
def visit_footnote_reference(self, node):
href = '#' + node['refid']
@@ -1085,32 +1080,26 @@
# footnote and citation labels:
def visit_label(self, node):
- # pass parent node to get id into starttag:
- self.body.append(self.starttag(node.parent, 'dt', '', CLASS='label'))
- # backlinks to the footnote/citation reference(s):
+ self.body.append('<span class="label">')
+ self.body.append('<span class="fn-bracket">[</span>')
+ # footnote/citation backrefs:
if self.settings.footnote_backlinks:
backrefs = node.parent['backrefs']
if len(backrefs) == 1:
self.body.append('<a class="fn-backref" href="#%s">'
% backrefs[0])
- # bracket (hidden by CSS for superscript footnotes)
- self.body.append('<span class="fn-bracket">[</span>')
def depart_label(self, node):
- self.body.append('<span class="fn-bracket">]</span>')
- # backlinks to the footnote/citation reference(s):
- if self.settings.footnote_backlinks:
- backrefs = node.parent['backrefs']
- else:
- backrefs = []
+ backrefs = node.parent.get('backrefs', [])
if len(backrefs) == 1:
self.body.append('</a>')
+ self.body.append('<span class="fn-bracket">]</span>')
+ self.body.append('</span>\n')
if len(backrefs) > 1:
backlinks = ['<a href="#%s">%s</a>' % (ref, i)
for (i, ref) in enumerate(backrefs, 1)]
- self.body.append('<span class="fn-backref">(%s)</span>'
+ self.body.append('<span class="fn-backref">(%s)</span>\n'
% ','.join(backlinks))
- self.body.append('</dt>\n<dd>')
def visit_legend(self, node):
self.body.append(self.starttag(node, 'div', CLASS='legend'))
Modified: trunk/docutils/docutils/writers/html5_polyglot/__init__.py
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/__init__.py 2021-06-25 20:56:23 UTC (rev 8772)
+++ trunk/docutils/docutils/writers/html5_polyglot/__init__.py 2021-06-25 20:56:46 UTC (rev 8773)
@@ -256,7 +256,7 @@
self.body_prefix.extend(header)
self.header.extend(header)
del self.body[start:]
-
+
# MIME types supported by the HTML5 <video> element
videotypes = ('video/mp4', 'video/webm', 'video/ogg')
Modified: trunk/docutils/docutils/writers/html5_polyglot/minimal.css
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/minimal.css 2021-06-25 20:56:23 UTC (rev 8772)
+++ trunk/docutils/docutils/writers/html5_polyglot/minimal.css 2021-06-25 20:56:46 UTC (rev 8773)
@@ -101,16 +101,12 @@
/* bold field name, content starts on the same line */
dl.field-list,
dl.option-list,
-dl.docinfo,
-dl.footnote,
-dl.citation {
+dl.docinfo {
display: flow-root;
}
dl.field-list > dt,
dl.option-list > dt,
-dl.docinfo > dt,
-dl.footnote > dt,
-dl.citation > dt {
+dl.docinfo > dt {
font-weight: bold;
clear: left;
float: left;
@@ -151,23 +147,55 @@
span.option { white-space: nowrap; }
/* Footnotes and Citations */
-dl.footnote.superscript > dd { margin-left: 0.7em; }
-dl.footnote.brackets > dd { margin-left: 1.6em; }
-dl.footnote > dt { font-weight: normal; }
+
+.footnote, .citation {
+ margin: 1em 0; /* default paragraph skip (Firefox) */
+}
+/* hanging indent */
+.footnote { padding-left: 1.7em; }
+.citation { padding-left: 2em; }
+.footnote.superscript { padding-left: 1em; }
+.footnote > .label { margin-left: -1.7em; }
+.citation > .label { margin-left: -2em; }
+.footnote.superscript > .label { margin-left: -1em; }
+
+.footnote > .label + *,
+.citation > .label + * {
+ display: inline-block;
+ margin-top: 0;
+ vertical-align: top;
+}
+.footnote > .fn-backref + *,
+.citation > .fn-backref + * {
+ margin-top: 0;
+}
+.footnote > .label + p, .footnote > .fn-backref + p,
+.citation > .label + p, .citation > .fn-backref + p {
+ display: inline;
+ vertical-align: inherit;
+}
+
+.fn-backref > a { font-style: italic; }
+
+/* superscript footnotes */
a.footnote-reference.superscript,
-dl.footnote.superscript > dt.label {
+.footnote.superscript > .label,
+.footnote.superscript > .fn-backref {
vertical-align: super;
- font-size: small;
+ font-size: smaller;
+ line-height: 1;
}
-a.footnote-reference.superscript > span.fn-bracket,
-dl.footnote.superscript > dt.label span.fn-bracket {
- display: none;
+a.footnote-reference.superscript > .fn-bracket,
+.footnote.superscript > .label > .fn-bracket {
+ /* hide brackets in display but leave for copy/paste */
+ display: inline-block;
+ width: 0;
+ overflow: hidden;
}
-dt.label > span.fn-backref {
- margin-left: 0.2em;
- font-weight: normal;
+.footnote-reference.superscript + .footnote-reference.superscript {
+ padding-left: 0.15em; /* separate consecutive footnote references */
+ /* TODO: unfortunately, "+" also selects with text between the references. */
}
-dt.label > span.fn-backref > a { font-style: italic; }
/* Alignment */
.align-left {
Modified: trunk/docutils/docutils/writers/html5_polyglot/plain.css
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/plain.css 2021-06-25 20:56:23 UTC (rev 8772)
+++ trunk/docutils/docutils/writers/html5_polyglot/plain.css 2021-06-25 20:56:46 UTC (rev 8773)
@@ -184,11 +184,18 @@
/* ----------------------- */
/* line on the left */
-dl.footnote {
- padding-left: 1ex;
- border-left: solid;
- border-left-width: thin;
+.footnote {
+ border-left: solid thin;
+ padding-left: 2.1em;
+ margin-bottom: 0;
}
+.footnote + .footnote {
+ padding-top: 0.5em;
+ margin-top: 0;
+}
+.footnote.superscript {
+ padding-left: 1.2em;
+}
/* Directives */
/* ---------- */
@@ -261,7 +268,7 @@
/* Math */
/* for math-output=MathML (for math-output=HTML, see math.css) */
mtable.align > mtr > mtd { /* emulate AMS "align" environment. */
- text-align: left;
+ text-align: left;
}
mstyle.mathscr, mi.mathscr {
font-family: STIX;
Modified: trunk/docutils/docutils/writers/html5_polyglot/responsive.css
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/responsive.css 2021-06-25 20:56:23 UTC (rev 8772)
+++ trunk/docutils/docutils/writers/html5_polyglot/responsive.css 2021-06-25 20:56:46 UTC (rev 8773)
@@ -340,7 +340,7 @@
/* Math */
/* for math-output=MathML (for math-output=HTML, see math.css) */
mtable.align > mtr > mtd { /* emulate AMS "align" environment. */
- text-align: left;
+ text-align: left;
}
mstyle.mathscr, mi.mathscr {
font-family: STIX;
Modified: trunk/docutils/docutils/writers/html5_polyglot/tuftig.css
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/tuftig.css 2021-06-25 20:56:23 UTC (rev 8772)
+++ trunk/docutils/docutils/writers/html5_polyglot/tuftig.css 2021-06-25 20:56:46 UTC (rev 8773)
@@ -46,7 +46,8 @@
/* vertical space (parskip) */
p, ol, ul, dl, li,
div.line-block,
-div.topic,
+.topic,
+.footnote, .citation,
table {
margin-top: 0.5em;
margin-bottom: 0.5em;
@@ -249,6 +250,9 @@
figcaption {
font-size: 0.8em;
}
+.fullwidth > figcaption {
+ font-size: inherit;
+}
figure.numbered > figcaption > p:before {
counter-increment: figure;
content: "Figure " counter(figure) ": ";
@@ -276,8 +280,7 @@
}
/* Admonitions and System Messages */
-.admonition,
-div.system-message {
+.admonition, .system-message {
border-style: solid;
border-color: silver;
border-width: thin;
@@ -324,7 +327,7 @@
}
/* undecorated links */
.contents a:link, a.toc-backref:link, a.image-reference:link,
-a.footnote-reference:link, a.fn-backref:link, .fn-backref a:link,
+a[role="doc-noteref"]:link, a[role="doc-backlink"]:link, .backrefs a:link,
a.citation-reference:link,
a[href^="#system-message"] {
text-decoration: none;
@@ -408,11 +411,8 @@
figure.marginal > figcaption {
font-size: 1em;
}
-dl.footnote {
- font-size: 0.8em;
- padding-left: 1ex;
- border-left: solid;
- border-left-width: thin;
+.footnote {
+ font-size: smaller;
overflow: auto;
}
@@ -463,11 +463,11 @@
/* Main text elements */
main > *, section > *,
figure > img,
- dl.footnote.align-left, /* override the placement in the margin */
- dl.citation.align-left {
+ .footnote.align-left, /* override the placement in the margin */
+ .citation.align-left {
grid-column: content-start / content-end;
}
- dl.citation.align-left {
+ .citation.align-left {
font-size: 1em;
}
figure > img { /* indent */
@@ -478,8 +478,8 @@
/* Margin Elements */
/* Sidebar, Footnotes, Citations, Captions */
aside.sidebar,
- dl.footnote,
- dl.citation,
+ .footnote,
+ .citation,
figcaption,
/* table > caption, does not work :(*/
.marginal,
@@ -490,6 +490,7 @@
width: auto;
max-width: 55em;
margin: 0.5em 0;
+ border: none;
padding: 0;
font-size: 0.8em;
text-align: initial; /* overwrite align-* */
@@ -502,14 +503,16 @@
display: block;
margin: 0.5em 0;
}
- dl.footnote {
+ .footnote {
padding-left: 0;
border-left: none;
}
- dl.citation > dd,
- dl.footnote.superscript > dd {
- margin-left: 0;
+ .citation {
+ padding-left: 1em;
}
+ .citation .label {
+ margin-left: -1em;
+ }
/* Fullwidth Elements */
h1.title, p.subtitle,
@@ -520,7 +523,8 @@
div.system-message,
pre,
.fullwidth,
- .fullwidth img {
+ .fullwidth img,
+ .fullwidth figcaption {
/* background-color: Linen; */
grid-column: content-start / end;
margin-right: calc(10% - 3rem);
Modified: trunk/docutils/test/functional/expected/footnotes_html5.html
===================================================================
--- trunk/docutils/test/functional/expected/footnotes_html5.html 2021-06-25 20:56:23 UTC (rev 8772)
+++ trunk/docutils/test/functional/expected/footnotes_html5.html 2021-06-25 20:56:46 UTC (rev 8773)
@@ -14,53 +14,114 @@
<p>Paragraphs may contain footnote references (manually numbered<a class="footnote-reference superscript" href="#footnote-1" id="footnote-reference-1"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></a>, anonymous auto-numbered<a class="footnote-reference superscript" href="#footnote-2" id="footnote-reference-2"><span class="fn-bracket">[</span>3<span class="fn-bracket">]</span></a>, labeled auto-numbered<a class="footnote-reference superscript" href="#label" id="footnote-reference-3"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></a>, or
symbolic<a class="footnote-reference superscript" href="#footnote-3" id="footnote-reference-4"><span class="fn-bracket">[</span>*<span class="fn-bracket">]</span></a>) or citation references (<a class="citation-reference" href="#cit2002" id="citation-reference-1">[CIT2002]</a>, <a class="citation-reference" href="#du2015" id="citation-reference-2">[DU2015]</a>).</p>
-<dl class="footnote superscript">
-<dt class="label" id="footnote-1"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span><span class="fn-backref">(<a href="#footnote-reference-1">1</a>,<a href="#footnote-reference-5">2</a>)</span></dt>
-<dd><p>A footnote contains body elements, consistently indented by at
+<aside class="footnote superscript" id="footnote-1" role="note">
+<span class="label"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></span>
+<span class="fn-backref">(<a href="#footnote-reference-1">1</a>,<a href="#footnote-reference-5">2</a>)</span>
+<p>A footnote contains body elements, consistently indented by at
least 3 spaces.</p>
<p>This is the footnote's second paragraph.</p>
-</dd>
-<dt class="label" id="label"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span><span class="fn-backref">(<a href="#footnote-reference-3">1</a>,<a href="#footnote-reference-6">2</a>)</span></dt>
-<dd><p>Footnotes may be numbered, either manually (as in<a class="footnote-reference superscript" href="#footnote-1" id="footnote-reference-5"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></a>) or
+</aside>
+<aside class="footnote superscript" id="label" role="note">
+<span class="label"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></span>
+<span class="fn-backref">(<a href="#footnote-reference-3">1</a>,<a href="#footnote-reference-6">2</a>)</span>
+<p>Footnotes may be numbered, either manually (as in<a class="footnote-reference superscript" href="#footnote-1" id="footnote-reference-5"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></a>) or
automatically using a "#"-prefixed label. This footnote has a
label so it can be referred to from multiple places, both as a
footnote reference (<a class="footnote-reference superscript" href="#label" id="footnote-reference-6"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></a>) and as a <a class="reference internal" href="#label">hyperlink reference</a>.</p>
-</dd>
-<dt class="label" id="footnote-2"><a class="fn-backref" href="#footnote-reference-2"><span class="fn-bracket">[</span>3<span class="fn-bracket">]</span></a></dt>
-<dd><p>This footnote is numbered automatically and anonymously using a
+</aside>
+<aside class="footnote superscript" id="footnote-2" role="note">
+<span class="label"><span class="fn-bracket">[</span><a class="fn-backref" href="#footnote-reference-2">3</a><span class="fn-bracket">]</span></span>
+<p>This footnote is numbered automatically and anonymously using a
label of "#" only.</p>
<p>This is the second paragraph.</p>
<p>And this is the third paragraph.</p>
-</dd>
-<dt class="label" id="footnote-3"><a class="fn-backref" href="#footnote-reference-4"><span class="fn-bracket">[</span>*<span class="fn-bracket">]</span></a></dt>
-<dd><p>Footnotes may also use symbols, specified with a "*" label.
+</aside>
+<aside class="footnote superscript" id="footnote-3" role="note">
+<span class="label"><span class="fn-bracket">[</span><a class="fn-backref" href="#footnote-reference-4">*</a><span class="fn-bracket">]</span></span>
+<p>Footnotes may also use symbols, specified with a "*" label.
Here's a reference to the next footnote:<a class="footnote-reference superscript" href="#footnote-4" id="footnote-reference-7"><span class="fn-bracket">[</span>†<span class="fn-bracket">]</span></a>.</p>
-</dd>
-<dt class="label" id="footnote-4"><a class="fn-backref" href="#footnote-reference-7"><span class="fn-bracket">[</span>†<span class="fn-bracket">]</span></a></dt>
-<dd><p>This footnote shows the next symbol in the sequence.</p>
-</dd>
-<dt class="label" id="footnote-5"><span class="fn-bracket">[</span>4<span class="fn-bracket">]</span></dt>
-<dd><p>Here's an unreferenced footnote, with a reference to a
+</aside>
+<aside class="footnote superscript" id="footnote-4" role="note">
+<span class="label"><span class="fn-bracket">[</span><a class="fn-backref" href="#footnote-reference-7">†</a><span class="fn-bracket">]</span></span>
+<p>This footnote shows the next symbol in the sequence.</p>
+</aside>
+<aside class="footnote superscript" id="footnote-5" role="note">
+<span class="label"><span class="fn-bracket">[</span>4<span class="fn-bracket">]</span></span>
+<p>Here's an unreferenced footnote, with a reference to a
nonexistent footnote:<a class="footnote-reference superscript" href="#footnote-6" id="footnote-reference-8"><span class="fn-bracket">[</span>5<span class="fn-bracket">]</span></a>.</p>
-</dd>
-</dl>
+</aside>
<section id="citations">
<h2>Citations</h2>
-<dl class="citation">
-<dt class="label" id="cit2002"><span class="fn-bracket">[</span>CIT2002<span class="fn-bracket">]</span><span class="fn-backref">(<a href="#citation-reference-1">1</a>,<a href="#citation-reference-3">2</a>)</span></dt>
-<dd><p>Citations are text-labeled footnotes. They may be
+<aside class="citation" id="cit2002" role="note">
+<span class="label"><span class="fn-bracket">[</span>CIT2002<span class="fn-bracket">]</span></span>
+<span class="fn-backref">(<a href="#citation-reference-1">1</a>,<a href="#citation-reference-3">2</a>)</span>
+<p>Citations are text-labeled footnotes. They may be
rendered separately and differently from footnotes.</p>
+</aside>
+<aside class="citation" id="du2015" role="note">
+<span class="label"><span class="fn-bracket">[</span><a class="fn-backref" href="#citation-reference-2">DU2015</a><span class="fn-bracket">]</span></span>
+<p><cite>Example document</cite>, Hometown: 2015.</p>
+</aside>
+<p>Here's a reference to the above, <a class="citation-reference" href="#cit2002" id="citation-reference-3">[CIT2002]</a>.</p>
+<aside class="footnote superscript" id="footnote-6" role="note">
+<span class="label"><span class="fn-bracket">[</span><a class="fn-backref" href="#footnote-reference-8">5</a><span class="fn-bracket">]</span></span>
+<p>this footnote is missing in the standard example document.</p>
+</aside>
+<p>Footnotes may contain block elements like lists<a class="footnote-reference superscript" href="#list-note" id="footnote-reference-9"><span class="fn-bracket">[</span>7<span class="fn-bracket">]</span></a><a class="footnote-reference superscript" href="#footnote-7" id="footnote-reference-10"><span class="fn-bracket">[</span>6<span class="fn-bracket">]</span></a>,
+admonitions<a class="footnote-reference superscript" href="#footnote-8" id="footnote-reference-11"><span class="fn-bracket">[</span>8<span class="fn-bracket">]</span></a>, or tables<a class="footnote-reference superscript" href="#footnote-9" id="footnote-reference-12"><span class="fn-bracket">[</span>9<span class="fn-bracket">]</span></a>.</p>
+<aside class="footnote superscript" id="footnote-7" role="note">
+<span class="label"><span class="fn-bracket">[</span><a class="fn-backref" href="#footnote-reference-10">6</a><span class="fn-bracket">]</span></span>
+<ol class="arabic simple">
+<li><p>An ordered list</p></li>
+<li><p>in a footnote.</p></li>
+</ol>
+</aside>
+<aside class="footnote superscript" id="list-note" role="note">
+<span class="label"><span class="fn-bracket">[</span>7<span class="fn-bracket">]</span></span>
+<span class="fn-backref">(<a href="#footnote-reference-9">1</a>,<a href="#footnote-reference-13">2</a>)</span>
+<ul class="simple">
+<li><p>An unordered list (bullet list)</p></li>
+<li><p>in a footnote.</p></li>
+</ul>
+<p>And a trailing paragraph.</p>
+</aside>
+<aside class="footnote superscript" id="footnote-8" role="note">
+<span class="label"><span class="fn-bracket">[</span><a class="fn-backref" href="#footnote-reference-11">8</a><span class="fn-bracket">]</span></span>
+<dl class="field-list simple">
+<dt>Field<span class="colon">:</span></dt>
+<dd><p>list</p>
</dd>
-<dt class="label" id="du2015"><a class="fn-backref" href="#citation-reference-2"><span class="fn-bracket">[</span>DU2015<span class="fn-bracket">]</span></a></dt>
-<dd><p><cite>Example document</cite>, Hometown: 2015.</p>
+<dt>with<span class="colon">:</span></dt>
+<dd><p>2 items.</p>
</dd>
</dl>
-<p>Here's a reference to the above, <a class="citation-reference" href="#cit2002" id="citation-reference-3">[CIT2002]</a>.</p>
-<dl class="footnote superscript">
-<dt class="label" id="footnote-6"><a class="fn-backref" href="#footnote-reference-8"><span class="fn-bracket">[</span>5<span class="fn-bracket">]</span></a></dt>
-<dd><p>this footnote is missing in the standard example document.</p>
-</dd>
-</dl>
+</aside>
+<aside class="footnote superscript" id="footnote-9" role="note">
+<span class="label"><span class="fn-bracket">[</span><a class="fn-backref" href="#footnote-reference-12">9</a><span class="fn-bracket">]</span></span>
+<div class="admonition note">
+<p class="admonition-title">Note</p>
+<p>This is a note in a note.</p>
+</div>
+</aside>
+<aside class="footnote superscript" id="footnote-10" role="note">
+<span class="label"><span class="fn-bracket">[</span>10<span class="fn-bracket">]</span></span>
+<table>
+<colgroup>
+<col style="width: 36%" />
+<col style="width: 64%" />
+</colgroup>
+<tbody>
+<tr><td><p>a</p></td>
+<td><p>table</p></td>
+</tr>
+<tr><td><p>in a</p></td>
+<td><p>footnote</p></td>
+</tr>
+</tbody>
+</table>
+</aside>
+<p>This<a class="footnote-reference superscript" href="#list-note" id="footnote-reference-13"><span class="fn-bracket">[</span>7<span class="fn-bracket">]</span></a> is a second reference to the footnote containing
+a bullet. list.</p>
</section>
</main>
</body>
Modified: trunk/docutils/test/functional/expected/standalone_rst_html5.html
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_html5.html 2021-06-25 20:56:23 UTC (rev 8772)
+++ trunk/docutils/test/functional/expected/standalone_rst_html5.html 2021-06-25 20:56:46 UTC (rev 8773)
@@ -470,45 +470,51 @@
</section>
<section id="footnotes">
<h3><a class="toc-backref" href="#toc-entry-17"><span class="sectnum">2.11</span> Footnotes</a></h3>
-<dl class="footnote brackets">
-<dt class="label" id="footnote-1"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span><span class="fn-backref">(<a href="#footnote-reference-1">1</a>,<a href="#footnote-reference-5">2</a>,<a href="#footnote-reference-9">3</a>)</span></dt>
-<dd><p>A footnote contains body elements, consistently indented by at
+<aside class="footnote brackets" id="footnote-1" role="note">
+<span class="label"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></span>
+<span class="fn-backref">(<a href="#footnote-reference-1">1</a>,<a href="#footnote-reference-5">2</a>,<a href="#footnote-reference-9">3</a>)</span>
+<p>A footnote contains body elements, consistently indented by at
least 3 spaces.</p>
<p>This is the footnote's second paragraph.</p>
-</dd>
-<dt class="label" id="label"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span><span class="fn-backref">(<a href="#footnote-reference-3">1</a>,<a href="#footnote-reference-6">2</a>)</span></dt>
-<dd><p>Footnotes may be numbered, either manually (as in <a class="footnote-reference brackets" href="#footnote-1" id="footnote-reference-5"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></a>) or
+</aside>
+<aside class="footnote brackets" id="label" role="note">
+<span class="label"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></span>
+<span class="fn-backref">(<a href="#footnote-reference-3">1</a>,<a href="#footnote-reference-6">2</a>)</span>
+<p>Footnotes may be numbered, either manually (as in <a class="footnote-reference brackets" href="#footnote-1" id="footnote-reference-5"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></a>) or
automatically using a "#"-prefixed label. This footnote has a
label so it can be referred to from multiple places, both as a
footnote reference (<a class="footnote-reference brackets" href="#label" id="footnote-reference-6"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></a>) and as a <a class="reference internal" href="#label">hyperlink reference</a>.</p>
-</dd>
-<dt class="label" id="footnote-2"><a class="fn-backref" href="#footnote-reference-2"><span class="fn-bracket">[</span>3<span class="fn-bracket">]</span></a></dt>
-<dd><p>This footnote is numbered automatically and anonymously using a
+</aside>
+<aside class="footnote brackets" id="footnote-2" role="note">
+<span class="label"><span class="fn-bracket">[</span><a class="fn-backref" href="#footnote-reference-2">3</a><span class="fn-bracket">]</span></span>
+<p>This footnote is numbered automatically and anonymously using a
label of "#" only.</p>
<p>This is the second paragraph.</p>
<p>And this is the third paragraph.</p>
-</dd>
-<dt class="label" id="footnote-3"><a class="fn-backref" href="#footnote-reference-4"><span class="fn-bracket">[</span>*<span class="fn-bracket">]</span></a></dt>
-<dd><p>Footnotes may also use symbols, specified with a "*" label.
+</aside>
+<aside class="footnote brackets" id="footnote-3" role="note">
+<span class="label"><span class="fn-bracket">[</span><a class="fn-backref" href="#footnote-reference-4">*</a><span class="fn-bracket">]</span></span>
+<p>Footnotes may also use symbols, specified with a "*" label.
Here's a reference to the next footnote: <a class="footnote-reference brackets" href="#footnote-4" id="footnote-reference-7"><span class="fn-bracket">[</span>†<span class="fn-bracket">]</span></a>.</p>
-</dd>
-<dt class="label" id="footnote-4"><a class="fn-backref" href="#footnote-reference-7"><span class="fn-bracket">[</span>†<span class="fn-bracket">]</span></a></dt>
-<dd><p>This footnote shows the next symbol in the sequence.</p>
-</dd>
-<dt class="label" id="footnote-5"><span class="fn-bracket">[</span>4<span class="fn-bracket">]</span></dt>
-<dd><p>Here's an unreferenced footnote, with a reference to a
+</aside>
+<aside class="footnote brackets" id="footnote-4" role="note">
+<span class="label"><span class="fn-bracket">[</span><a class="fn-backref" href="#footnote-reference-7">†</a><span class="fn-bracket">]</span></span>
+<p>This footnote shows the next symbol in the sequence.</p>
+</aside>
+<aside class="footnote brackets" id="footnote-5" role="note">
+<span class="label"><span class="fn-bracket">[</span>4<span class="fn-bracket">]</span></span>
+<p>Here's an unreferenced footnote, with a reference to a
nonexistent footnote: <a href="#system-message-2"><span class="problematic" id="footnote-reference-8">[5]_</span></a>.</p>
-</dd>
-</dl>
+</aside>
</section>
<section id="citations">
<h3><a class="toc-backref" href="#toc-entry-18"><span class="sectnum">2.12</span> Citations</a></h3>
-<dl class="citation">
-<dt class="label" id="cit2002"><span class="fn-bracket">[</spa...
[truncated message content] |
|
From: <mi...@us...> - 2021-06-25 20:57:07
|
Revision: 8774
http://sourceforge.net/p/docutils/code/8774
Author: milde
Date: 2021-06-25 20:57:05 +0000 (Fri, 25 Jun 2021)
Log Message:
-----------
Code simplification in writers.
Use node[...] instead of node.get(...) for basic attributes.
Remove HTMLTranslator.topic_classes auxiliary attribute.
HTML5: Do not add "compound-first", "compound-middle",
or "compound-last" to elements nested in a compound.
Modified Paths:
--------------
trunk/docutils/HISTORY.txt
trunk/docutils/RELEASE-NOTES.txt
trunk/docutils/docutils/writers/_html_base.py
trunk/docutils/docutils/writers/html4css1/__init__.py
trunk/docutils/docutils/writers/html5_polyglot/__init__.py
trunk/docutils/docutils/writers/latex2e/__init__.py
trunk/docutils/test/functional/expected/standalone_rst_html5.html
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2021-06-25 20:56:46 UTC (rev 8773)
+++ trunk/docutils/HISTORY.txt 2021-06-25 20:57:05 UTC (rev 8774)
@@ -25,7 +25,7 @@
"meta" nodes if they are not supported by the output format.
__ docs/ref/doctree.html#meta
-
+
- document.make_id(): Keep leading number and hyphen characters
from `name` if the id_prefix setting is non-empty.
@@ -62,11 +62,19 @@
they are present also without CSS and when copying text.
Adapt ``minimal.css``.
+ - Use semantic tag <aside> for footnote text and citations.
+
+ - Do not add "compound-first", "compound-middle", or "compound-last" to
+ elements nested in a compound (no change with `html4css1`).
+
+ - Removed attribute ``HTMLTranslator.topic_classes``
+
+
* docutils/writers/latex2e/__init__.py
- The setting `legacy_class_functions`_ now defaults to "False".
Adapt stylesheets modifying ``\DUadmonition`` and/or ``\DUtitle``.
-
+
- Apply patch #181 "Fix tocdepth when chapter/part in use" by
John Thorvald Wodder II.
Modified: trunk/docutils/RELEASE-NOTES.txt
===================================================================
--- trunk/docutils/RELEASE-NOTES.txt 2021-06-25 20:56:46 UTC (rev 8773)
+++ trunk/docutils/RELEASE-NOTES.txt 2021-06-25 20:57:05 UTC (rev 8774)
@@ -85,6 +85,10 @@
Use semantic tag <aside> for footnote text and citations.
+ Do not add "compound-first", "compound-middle", or "compound-last" to
+ elements nested in a compound. Use child selector and "first-child",
+ "last-child" pseudo classes instead.
+
LaTeX:
`legacy_class_functions`_ setting default changed to
"False", admonitions are now environments.
@@ -100,6 +104,9 @@
* Removed function: ``utils.unique_combinations``
(obsoleted by ``itertools.combinations``).
+* Removed attribute: ``HTMLTranslator.topic_classes``
+ (check node.parent.classes instead).
+
* Various bugfixes and improvements (see HISTORY_).
__ docs/ref/doctree.html#meta
Modified: trunk/docutils/docutils/writers/_html_base.py
===================================================================
--- trunk/docutils/docutils/writers/_html_base.py 2021-06-25 20:56:46 UTC (rev 8773)
+++ trunk/docutils/docutils/writers/_html_base.py 2021-06-25 20:57:05 UTC (rev 8774)
@@ -328,7 +328,6 @@
Used by visit_* and depart_* functions in conjunction with the tree
traversal. Make sure that the pops correspond to the pushes."""
- self.topic_classes = []
self.colspecs = []
self.compact_p = True
self.compact_simple = False
@@ -521,8 +520,7 @@
self.depart_docinfo_item()
def visit_admonition(self, node):
- node['classes'].insert(0, 'admonition')
- self.body.append(self.starttag(node, 'div'))
+ self.body.append(self.starttag(node, 'div', classes=['admonition']))
def depart_admonition(self, node=None):
self.body.append('</div>\n')
@@ -596,8 +594,7 @@
and not self.settings.compact_lists):
return False
# Table of Contents:
- if (self.topic_classes == ['contents']):
- # TODO: look in parent nodes, remove self.topic_classes?
+ if 'contents' in node.parent['classes']:
return True
# check the list items:
return self.check_simple_list(node)
@@ -683,11 +680,6 @@
def visit_compound(self, node):
self.body.append(self.starttag(node, 'div', CLASS='compound'))
- if len(node) > 1:
- node[0]['classes'].append('compound-first')
- node[-1]['classes'].append('compound-last')
- for child in node[1:-1]:
- child['classes'].append('compound-middle')
def depart_compound(self, node):
self.body.append('</div>\n')
@@ -730,21 +722,14 @@
self.body.append('</dd>\n')
def visit_definition_list(self, node):
- if self.is_compactable(node):
- node.setdefault('classes', []).append('simple')
- self.body.append(self.starttag(node, 'dl'))
+ classes = ['simple'] if self.is_compactable(node) else []
+ self.body.append(self.starttag(node, 'dl', classes=classes))
def depart_definition_list(self, node):
self.body.append('</dl>\n')
def visit_definition_list_item(self, node):
- # pass class arguments, ids and names to definition term:
- node.children[0]['classes'] = (
- node.get('classes', []) + node.children[0].get('classes', []))
- node.children[0]['ids'] = (
- node.get('ids', []) + node.children[0].get('ids', []))
- node.children[0]['names'] = (
- node.get('names', []) + node.children[0].get('names', []))
+ pass
def depart_definition_list_item(self, node):
pass
@@ -757,10 +742,10 @@
def visit_docinfo(self, node):
self.context.append(len(self.body))
- classes = 'docinfo'
+ classes = ['docinfo']
if (self.is_compactable(node)):
- classes += ' simple'
- self.body.append(self.starttag(node, 'dl', CLASS=classes))
+ classes.append('simple')
+ self.body.append(self.starttag(node, 'dl', classes=classes))
def depart_docinfo(self, node):
self.body.append('</dl>\n')
@@ -783,7 +768,7 @@
def visit_doctest_block(self, node):
self.body.append(self.starttag(node, 'pre', suffix='',
- CLASS='code python doctest'))
+ classes=['code', 'python', 'doctest']))
def depart_doctest_block(self, node):
self.body.append('\n</pre>\n')
@@ -825,18 +810,16 @@
self.body.append('</em>')
def visit_entry(self, node):
- atts = {'class': []}
+ atts = {'classes': []}
if isinstance(node.parent.parent, nodes.thead):
- atts['class'].append('head')
+ atts['classes'].append('head')
if node.parent.parent.parent.stubs[node.parent.column]:
# "stubs" list is an attribute of the tgroup element
- atts['class'].append('stub')
- if atts['class']:
+ atts['classes'].append('stub')
+ if atts['classes']:
tagname = 'th'
- atts['class'] = ' '.join(atts['class'])
else:
tagname = 'td'
- del atts['class']
node.parent.column += 1
if 'morerows' in node:
atts['rowspan'] = node['morerows'] + 1
@@ -845,21 +828,18 @@
node.parent.column += node['morecols']
self.body.append(self.starttag(node, tagname, '', **atts))
self.context.append('</%s>\n' % tagname.lower())
- # TODO: why does the html4css1 writer insert an NBSP into empty cells?
- # if len(node) == 0: # empty cell
- # self.body.append(' ') # no-break space
def depart_entry(self, node):
self.body.append(self.context.pop())
def visit_enumerated_list(self, node):
- atts = {}
+ atts = {'classes': []}
if 'start' in node:
atts['start'] = node['start']
if 'enumtype' in node:
- atts['class'] = node['enumtype']
+ atts['classes'].append(node['enumtype'])
if self.is_compactable(node):
- atts['class'] = (atts.get('class', '') + ' simple').strip()
+ atts['classes'].append('simple')
self.body.append(self.starttag(node, 'ol', **atts))
def depart_enumerated_list(self, node):
@@ -893,10 +873,9 @@
pass
# as field is ignored, pass class arguments to field-name and field-body:
-
def visit_field_name(self, node):
self.body.append(self.starttag(node, 'dt', '',
- CLASS=''.join(node.parent['classes'])))
+ classes=node.parent['classes']))
def depart_field_name(self, node):
self.body.append('<span class="colon">:</span></dt>\n')
@@ -903,7 +882,7 @@
def visit_field_body(self, node):
self.body.append(self.starttag(node, 'dd', '',
- CLASS=''.join(node.parent['classes'])))
+ classes=node.parent['classes']))
# prevent misalignment of following content if the field is empty:
if not node.children:
self.body.append('<p></p>')
@@ -949,9 +928,9 @@
def visit_footnote_reference(self, node):
href = '#' + node['refid']
- classes = 'footnote-reference ' + self.settings.footnote_references
+ classes = ['footnote-reference', self.settings.footnote_references]
self.body.append(self.starttag(node, 'a', suffix='',
- CLASS=classes, href=href))
+ classes=classes, href=href))
self.body.append('<span class="fn-bracket">[</span>')
def depart_footnote_reference(self, node):
@@ -1130,7 +1109,7 @@
# inline literal
def visit_literal(self, node):
# special case: "code" role
- classes = node.get('classes', [])
+ classes = node['classes']
if 'code' in classes:
# filter 'code' from class arguments
classes.pop(classes.index('code'))
@@ -1158,11 +1137,11 @@
def visit_literal_block(self, node):
self.body.append(self.starttag(node, 'pre', '', CLASS='literal-block'))
- if 'code' in node.get('classes', []):
+ if 'code' in node['classes']:
self.body.append('<code>')
def depart_literal_block(self, node):
- if 'code' in node.get('classes', []):
+ if 'code' in node['classes']:
self.body.append('</code>')
self.body.append('</pre>\n')
@@ -1388,12 +1367,15 @@
def visit_raw(self, node):
if 'html' in node.get('format', '').split():
- t = isinstance(node.parent, nodes.TextElement) and 'span' or 'div'
+ if isinstance(node.parent, nodes.TextElement):
+ tagname = 'span'
+ else:
+ tagname = 'div'
if node['classes']:
- self.body.append(self.starttag(node, t, suffix=''))
+ self.body.append(self.starttag(node, tagname, suffix=''))
self.body.append(node.astext())
if node['classes']:
- self.body.append('</%s>' % t)
+ self.body.append('</%s>' % tagname)
# Keep non-HTML raw text out of output:
raise nodes.SkipNode
@@ -1490,16 +1472,16 @@
# h1–h6 elements must not be used to markup subheadings, subtitles,
# alternative titles and taglines unless intended to be the heading for a
# new section or subsection.
- # -- http://www.w3.org/TR/html/sections.html#headings-and-sections
+ # -- http://www.w3.org/TR/html51/sections.html#headings-and-sections
def visit_subtitle(self, node):
if isinstance(node.parent, nodes.sidebar):
- classes = 'sidebar-subtitle'
+ classes = ['sidebar-subtitle']
elif isinstance(node.parent, nodes.document):
- classes = 'subtitle'
+ classes = ['subtitle']
self.in_document_title = len(self.body)+1
elif isinstance(node.parent, nodes.section):
- classes = 'section-subtitle'
- self.body.append(self.starttag(node, 'p', '', CLASS=classes))
+ classes = ['section-subtitle']
+ self.body.append(self.starttag(node, 'p', '', classes=classes))
def depart_subtitle(self, node):
self.body.append('</p>\n')
@@ -1546,12 +1528,9 @@
self.body.append('</div>\n')
def visit_table(self, node):
- atts = {}
- classes = node.setdefault('classes', [])
- classes += [cls.strip(u' \t\n')
- for cls in self.settings.table_style.split(',')]
+ atts = {'classes': self.settings.table_style.replace(',', ' ').split()}
if 'align' in node:
- classes.append('align-%s' % node['align'])
+ atts['classes'].append('align-%s' % node['align'])
if 'width' in node:
atts['style'] = 'width: %s;' % node['width']
tag = self.starttag(node, 'table', **atts)
@@ -1579,7 +1558,10 @@
self.body.append('</tbody>\n')
def visit_term(self, node):
- self.body.append(self.starttag(node, 'dt', ''))
+ # The parent node (definition_list_item) is omitted in HTML.
+ self.body.append(self.starttag(node, 'dt', '',
+ classes=node.parent['classes'],
+ ids=node.parent['ids']))
def depart_term(self, node):
# Leave the end tag to `self.visit_definition()`,
@@ -1660,11 +1642,9 @@
def visit_topic(self, node):
self.body.append(self.starttag(node, 'div', CLASS='topic'))
- self.topic_classes = node['classes']
def depart_topic(self, node):
self.body.append('</div>\n')
- self.topic_classes = []
def visit_transition(self, node):
self.body.append(self.emptytag(node, 'hr', CLASS='docutils'))
Modified: trunk/docutils/docutils/writers/html4css1/__init__.py
===================================================================
--- trunk/docutils/docutils/writers/html4css1/__init__.py 2021-06-25 20:56:46 UTC (rev 8773)
+++ trunk/docutils/docutils/writers/html4css1/__init__.py 2021-06-25 20:57:05 UTC (rev 8774)
@@ -236,7 +236,7 @@
or (self.settings.compact_lists
and 'open' not in node['classes']
and (self.compact_simple
- or self.topic_classes == ['contents']
+ or 'contents' in node.parent['classes']
# TODO: self.in_contents
or self.check_simple_list(node))))
@@ -260,6 +260,18 @@
self.body.append(self.starttag(node, 'span', '', CLASS='classifier'))
# ersatz for first/last pseudo-classes
+ def visit_compound(self, node):
+ self.body.append(self.starttag(node, 'div', CLASS='compound'))
+ if len(node) > 1:
+ node[0]['classes'].append('compound-first')
+ node[-1]['classes'].append('compound-last')
+ for child in node[1:-1]:
+ child['classes'].append('compound-middle')
+
+ def depart_compound(self, node):
+ self.body.append('</div>\n')
+
+ # ersatz for first/last pseudo-classes
def visit_definition(self, node):
self.body.append('</dt>\n')
self.body.append(self.starttag(node, 'dd', ''))
@@ -579,7 +591,7 @@
# cater for limited styling options in CSS1 using hard-coded NBSPs
def visit_literal(self, node):
# special case: "code" role
- classes = node.get('classes', [])
+ classes = node['classes']
if 'code' in classes:
# filter 'code' from class arguments
node['classes'] = [cls for cls in classes if cls != 'code']
Modified: trunk/docutils/docutils/writers/html5_polyglot/__init__.py
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/__init__.py 2021-06-25 20:56:46 UTC (rev 8773)
+++ trunk/docutils/docutils/writers/html5_polyglot/__init__.py 2021-06-25 20:57:05 UTC (rev 8774)
@@ -151,7 +151,7 @@
def visit_container(self, node):
# If there is exactly one of the "supported block tags" in
# the list of class values, use it as tag name:
- classes = node.get('classes', [])
+ classes = node['classes']
tags = [cls for cls in classes
if cls in self.supported_block_tags]
if len(tags) == 1:
@@ -256,7 +256,7 @@
self.body_prefix.extend(header)
self.header.extend(header)
del self.body[start:]
-
+
# MIME types supported by the HTML5 <video> element
videotypes = ('video/mp4', 'video/webm', 'video/ogg')
@@ -273,7 +273,7 @@
atts['height'] = node['height'].replace('px', '')
if 'align' in node:
atts['class'] = 'align-%s' % node['align']
- if 'controls' in node.get('classes', []):
+ if 'controls' in node['classes']:
atts['controls'] = 'controls'
atts['title'] = node.get('alt', uri)
@@ -297,7 +297,7 @@
'b', 'i', 'q', 's', 'u'))
def visit_inline(self, node):
# Use `supported_inline_tags` if found in class values
- classes = node.get('classes', [])
+ classes = node['classes']
tags = [cls for cls in self.supported_inline_tags
if cls in classes]
if len(tags):
@@ -333,7 +333,7 @@
# use HTML text-level tags if matching class value found
def visit_literal(self, node):
- classes = node.get('classes', [])
+ classes = node['classes']
tags = [cls for cls in self.supported_inline_tags
if cls in classes]
if len(tags):
@@ -410,8 +410,6 @@
and isinstance(node.parent, nodes.document)):
self.body_prefix[0] = '</head>\n<body class="with-toc">\n'
self.body.append(self.starttag(node, 'div', CLASS='topic'))
- self.topic_classes = node['classes'] # TODO: remove?
def depart_topic(self, node):
self.body.append('</div>\n')
- self.topic_classes = []
Modified: trunk/docutils/docutils/writers/latex2e/__init__.py
===================================================================
--- trunk/docutils/docutils/writers/latex2e/__init__.py 2021-06-25 20:56:46 UTC (rev 8773)
+++ trunk/docutils/docutils/writers/latex2e/__init__.py 2021-06-25 20:57:05 UTC (rev 8774)
@@ -797,10 +797,10 @@
def latex_section_depth(self, depth):
"""
Return LaTeX equivalent of Docutils section level `depth`.
-
+
Given the value of the ``:depth:`` option of the "contents" or
"sectnum" directive, return the corresponding value for the
- LaTeX ``tocdepth`` or ``secnumdepth`` counters.
+ LaTeX ``tocdepth`` or ``secnumdepth`` counters.
"""
depth = min(depth, len(self.sections)) # limit to supported levels
if 'chapter' in self.sections:
@@ -1525,7 +1525,7 @@
If `set_anchor` is True, an anchor is set with \\phantomsection.
If `protect` is True, the \\label cmd is made robust.
"""
- labels = ['\\label{%s}' % id for id in node.get('ids', [])]
+ labels = ['\\label{%s}' % id for id in node['ids']]
if protect:
labels = ['\\protect'+label for label in labels]
if set_anchor and labels:
@@ -2211,7 +2211,7 @@
self.out.append('\\begin{figure} %% align = "%s"\n' % alignment)
else:
self.out.append('\\begin{figure}\n')
- if node.get('ids'):
+ if node['ids']:
self.out += self.ids_to_labels(node) + ['\n']
def depart_figure(self, node):
@@ -2395,7 +2395,7 @@
self.out.extend(post)
def depart_image(self, node):
- if node.get('ids'):
+ if node['ids']:
self.out += self.ids_to_labels(node) + ['\n']
def visit_inline(self, node): # <span>, i.e. custom roles
@@ -2511,7 +2511,7 @@
_use_listings = (literal_env == 'lstlisting') and _use_env
# Labels and classes:
- if node.get('ids'):
+ if node['ids']:
self.out += ['\n'] + self.ids_to_labels(node)
self.duclass_open(node)
# Highlight code?
@@ -2602,7 +2602,7 @@
self.visit_inline(node)
self.requirements['amsmath'] = r'\usepackage{amsmath}'
math_code = node.astext().translate(unichar2tex.uni2tex_table)
- if node.get('ids'):
+ if node['ids']:
math_code = '\n'.join([math_code] + self.ids_to_labels(node))
if math_env == '$':
if self.alltt:
@@ -2709,7 +2709,7 @@
self.out.append('\n')
else:
self.out.append('\n')
- if node.get('ids'):
+ if node['ids']:
self.out += self.ids_to_labels(node) + ['\n']
if node['classes']:
self.visit_inline(node)
@@ -2970,7 +2970,7 @@
self.active_table = self.table_stack.pop()
# Insert hyperlabel after (long)table, as
# other places (beginning, caption) result in LaTeX errors.
- if node.get('ids'):
+ if node['ids']:
self.out += self.ids_to_labels(node, set_anchor=False) + ['\n']
self.duclass_close(node)
Modified: trunk/docutils/test/functional/expected/standalone_rst_html5.html
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_html5.html 2021-06-25 20:56:46 UTC (rev 8773)
+++ trunk/docutils/test/functional/expected/standalone_rst_html5.html 2021-06-25 20:57:05 UTC (rev 8774)
@@ -896,45 +896,45 @@
is a single logical paragraph containing multiple physical body
elements. For example:</p>
<div class="compound">
-<p class="compound-first">The 'rm' command is very dangerous. If you are logged
+<p>The 'rm' command is very dangerous. If you are logged
in as root and enter</p>
-<pre class="compound-middle literal-block">cd /
+<pre class="literal-block">cd /
rm -rf *</pre>
-<p class="compound-last">you will erase the entire contents of your file system.</p>
+<p>you will erase the entire contents of your file system.</p>
</div>
<p>Test the handling and display of compound paragraphs:</p>
<div class="some-class compound">
-<p class="compound-first">Compound 2, paragraph 1,</p>
-<p class="compound-middle">compound 2, paragraph 2,</p>
-<ul class="compound-middle simple">
+<p>Compound 2, paragraph 1,</p>
+<p>compound 2, paragraph 2,</p>
+<ul class="simple">
<li><p>list item 1,</p></li>
<li><p>list item 2,</p></li>
</ul>
-<p class="compound-last">compound 2, paragraph 3.</p>
+<p>compound 2, paragraph 3.</p>
</div>
<div class="compound">
<p>Compound 3, only consisting of one paragraph.</p>
</div>
<div class="compound">
-<pre class="compound-first literal-block">Compound 4.
+<pre class="literal-block">Compound 4.
This one starts with a literal block.</pre>
-<p class="compound-last">Compound 4, paragraph following the literal block.</p>
+<p>Compound 4, paragraph following the literal block.</p>
</div>
<p>Now something <em>really</em> perverted -- a nested compound block. This is
just to test that it works at all; the results don't have to be
meaningful.</p>
<div class="compound">
-<p class="compound-first">Compound 5, block 1 (a paragraph).</p>
-<div class="compound-middle compound">
-<p class="compound-first">Compound 6 is block 2 in compound 5.</p>
-<p class="compound-last">Compound 6, another paragraph.</p>
+<p>Compound 5, block 1 (a paragraph).</p>
+<div class="compound">
+<p>Compound 6 is block 2 in compound 5.</p>
+<p>Compound 6, another paragraph.</p>
</div>
-<p class="compound-last">Compound 5, block 3 (a paragraph).</p>
+<p>Compound 5, block 3 (a paragraph).</p>
</div>
<div class="compound">
-<p class="compound-first">Compound 7, tests the inclusion of various block-level
+<p>Compound 7, tests the inclusion of various block-level
elements in one logical paragraph. First a table,</p>
-<table class="compound-middle">
+<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
@@ -957,48 +957,48 @@
</tr>
</tbody>
</table>
-<p class="compound-middle">followed by a paragraph. This physical paragraph is
+<p>followed by a paragraph. This physical paragraph is
actually a continuation of the paragraph before the table. It is followed
by</p>
-<blockquote class="compound-middle">
+<blockquote>
<p>a quote and</p>
</blockquote>
-<ol class="compound-middle arabic simple">
+<ol class="arabic simple">
<li><p>an enumerated list,</p></li>
</ol>
-<p class="compound-middle">a paragraph,</p>
-<dl class="compound-middle option-list">
+<p>a paragraph,</p>
+<dl class="option-list">
<dt><kbd><span class="option">--an</span></kbd></dt>
<dd><p>option list,</p>
</dd>
</dl>
-<p class="compound-middle">a paragraph,</p>
-<dl class="compound-middle field-list simple">
+<p>a paragraph,</p>
+<dl class="field-list simple">
<dt>a field<span class="colon">:</span></dt>
<dd><p>list,</p>
</dd>
</dl>
-<p class="compound-middle">a paragraph,</p>
-<dl class="compound-middle simple">
+<p>a paragraph,</p>
+<dl class="simple">
<dt>a definition</dt>
<dd><p>list,</p>
</dd>
</dl>
-<p class="compound-middle">a paragraph, an image:</p>
-<img alt="../../../docs/user/rst/images/biohazard.png" class="compound-middle" src="../../../docs/user/rst/images/biohazard.png" />
-<p class="compound-middle">a paragraph,</p>
-<div class="compound-middle line-block">
+<p>a paragraph, an image:</p>
+<img alt="../../../docs/user/rst/images/biohazard.png" src="../../../docs/user/rst/images/biohazard.png" />
+<p>a paragraph,</p>
+<div class="line-block">
<div class="line">a line</div>
<div class="line">block,</div>
</div>
-<p class="compound-middle">a paragraph followed by a comment,</p>
+<p>a paragraph followed by a comment,</p>
<!-- this is a comment -->
-<p class="compound-middle">a paragraph, a</p>
-<div class="admonition note compound-middle">
+<p>a paragraph, a</p>
+<div class="admonition note">
<p class="admonition-title">Note</p>
<p>with content</p>
</div>
-<p class="compound-last">and the final paragraph of the compound 7.</p>
+<p>and the final paragraph of the compound 7.</p>
</div>
</section>
<section id="parsed-literal-blocks">
@@ -1225,7 +1225,7 @@
</tr>
</tbody>
</table>
-<table class="colwidths-auto align-center">
+<table class="align-center colwidths-auto">
<caption>center aligned list table</caption>
<tbody>
<tr><td><p>Albatross</p></td>
@@ -1493,7 +1493,7 @@
</ul>
<p>"Booktabs" style table, numbered, centre-aligned, with auto-sized columns:</p>
<blockquote>
-<table class="booktabs numbered colwidths-auto align-center">
+<table class="align-center booktabs numbered colwidths-auto">
<caption>I/O values</caption>
<thead>
<tr><th class="head" colspan="2"><p>Input</p></th>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2021-06-25 20:57:43
|
Revision: 8775
http://sourceforge.net/p/docutils/code/8775
Author: milde
Date: 2021-06-25 20:57:36 +0000 (Fri, 25 Jun 2021)
Log Message:
-----------
HTM5 Use semantic tags for topics, admontions, system-messages, and toc.
<aside> for topics (except abstract and toc), admonitions,
and system messages.
<nav> and DPub Aria role="doc-toc" for the Table of Contents.
Modified Paths:
--------------
trunk/docutils/HISTORY.txt
trunk/docutils/RELEASE-NOTES.txt
trunk/docutils/docutils/writers/_html_base.py
trunk/docutils/docutils/writers/html5_polyglot/__init__.py
trunk/docutils/docutils/writers/html5_polyglot/minimal.css
trunk/docutils/docutils/writers/html5_polyglot/plain.css
trunk/docutils/docutils/writers/html5_polyglot/responsive.css
trunk/docutils/docutils/writers/html5_polyglot/tuftig.css
trunk/docutils/test/functional/expected/footnotes_html5.html
trunk/docutils/test/functional/expected/standalone_rst_html5.html
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2021-06-25 20:57:05 UTC (rev 8774)
+++ trunk/docutils/HISTORY.txt 2021-06-25 20:57:36 UTC (rev 8775)
@@ -40,7 +40,7 @@
- `Meta` directive class (moved from html.py) inserts `meta`
(instead of `pending`) nodes.
-* docutils/tools/math/math2html, docutils/writers/html5_polyglot/math.css
+* docutils/tools/math/math2html;
- Fix bug #244 Wrong subscript/superscript order with
``--math-output=HTML``.
@@ -62,7 +62,8 @@
they are present also without CSS and when copying text.
Adapt ``minimal.css``.
- - Use semantic tag <aside> for footnote text and citations.
+ - Use semantic tags <aside> and <nav> for footnote text and citations,
+ topics, admonitions, and system-messages.
- Do not add "compound-first", "compound-middle", or "compound-last" to
elements nested in a compound (no change with `html4css1`).
Modified: trunk/docutils/RELEASE-NOTES.txt
===================================================================
--- trunk/docutils/RELEASE-NOTES.txt 2021-06-25 20:57:05 UTC (rev 8774)
+++ trunk/docutils/RELEASE-NOTES.txt 2021-06-25 20:57:36 UTC (rev 8775)
@@ -22,10 +22,6 @@
* `html5` writer:
- - Use semantic tags <aside> for topics
- (except abstract), admonitions, and system messages, and <nav> for
- the Table of Contents.
-
- Use <summary> and <details> tags for term and definition of a
definition list with class value "details".
@@ -83,7 +79,9 @@
Write footnote brackets and field term colons to HTML, so that they
are present also without CSS and when copying text.
- Use semantic tag <aside> for footnote text and citations.
+ Use semantic tag <aside> for footnote text and citations,
+ topics (except abstract and toc), admonitions, and system messages
+ Use <nav> for the Table of Contents.
Do not add "compound-first", "compound-middle", or "compound-last" to
elements nested in a compound. Use child selector and "first-child",
Modified: trunk/docutils/docutils/writers/_html_base.py
===================================================================
--- trunk/docutils/docutils/writers/_html_base.py 2021-06-25 20:57:05 UTC (rev 8774)
+++ trunk/docutils/docutils/writers/_html_base.py 2021-06-25 20:57:36 UTC (rev 8775)
@@ -520,10 +520,10 @@
self.depart_docinfo_item()
def visit_admonition(self, node):
- self.body.append(self.starttag(node, 'div', classes=['admonition']))
+ self.body.append(self.starttag(node, 'aside', classes=['admonition']))
def depart_admonition(self, node=None):
- self.body.append('</div>\n')
+ self.body.append('</aside>\n')
attribution_formats = {'dash': (u'\u2014', ''),
'parentheses': ('(', ')'),
@@ -1499,7 +1499,7 @@
self.body.append('</sup>')
def visit_system_message(self, node):
- self.body.append(self.starttag(node, 'div', CLASS='system-message'))
+ self.body.append(self.starttag(node, 'aside', CLASS='system-message'))
self.body.append('<p class="system-message-title">')
backref_text = ''
if len(node['backrefs']):
@@ -1525,7 +1525,7 @@
self.encode(node['source']), line, backref_text))
def depart_system_message(self, node):
- self.body.append('</div>\n')
+ self.body.append('</aside>\n')
def visit_table(self, node):
atts = {'classes': self.settings.table_style.replace(',', ' ').split()}
Modified: trunk/docutils/docutils/writers/html5_polyglot/__init__.py
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/__init__.py 2021-06-25 20:57:05 UTC (rev 8774)
+++ trunk/docutils/docutils/writers/html5_polyglot/__init__.py 2021-06-25 20:57:36 UTC (rev 8775)
@@ -402,14 +402,27 @@
self.body.append('</aside>\n')
self.in_sidebar = False
+ # Use new HTML5 element <aside> or <nav>
# Add class value to <body>, if there is a ToC in the document
- # (see responsive.css how this is used for sidebar navigation).
- # TODO: use the new HTML5 element <aside>?
+ # (see responsive.css how this is used for a navigation sidebar).
def visit_topic(self, node):
- if ('contents' in node['classes']
- and isinstance(node.parent, nodes.document)):
- self.body_prefix[0] = '</head>\n<body class="with-toc">\n'
- self.body.append(self.starttag(node, 'div', CLASS='topic'))
+ atts = {'classes': ['topic']}
+ if 'contents' in node['classes']:
+ node.html_tagname = 'nav'
+ del(atts['classes'])
+ if isinstance(node.parent, nodes.document):
+ atts['role'] = 'doc-toc'
+ self.body_prefix[0] = '</head>\n<body class="with-toc">\n'
+ elif 'abstract' in node['classes']:
+ node.html_tagname = 'div'
+ atts['role'] = 'doc-abstract'
+ elif 'dedication' in node['classes']:
+ node.html_tagname = 'div'
+ atts['role'] = 'doc-dedication'
+ else:
+ node.html_tagname = 'aside'
+ self.body.append(self.starttag(node, node.html_tagname, **atts))
def depart_topic(self, node):
- self.body.append('</div>\n')
+ self.body.append('</%s>\n'%node.html_tagname)
+ del(node.html_tagname)
Modified: trunk/docutils/docutils/writers/html5_polyglot/minimal.css
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/minimal.css 2021-06-25 20:57:05 UTC (rev 8774)
+++ trunk/docutils/docutils/writers/html5_polyglot/minimal.css 2021-06-25 20:57:36 UTC (rev 8775)
@@ -42,8 +42,8 @@
h1 + p.subtitle {
font-size: 1.6em;
}
-h2 + p.section-subtitle, a.toc-backref {
- color: black;
+a.toc-backref {
+ color: inherit;
text-decoration: none;
}
@@ -77,10 +77,8 @@
p:last-child { margin-bottom: 0; }
/* Table of Contents */
-.topic.contents { margin: 0.5em 0; }
-.topic.contents ul.auto-toc {
+.contents ul.auto-toc { /* section numbers present */
list-style-type: none;
- padding-left: 1.5em;
}
/* Enumerated Lists */
@@ -222,16 +220,12 @@
}
/* Text Blocks */
-blockquote,
-div.topic,
-aside.topic {
- margin: 1em 2em;
-}
+.topic { margin: 1em 2em; }
.sidebar,
.admonition,
.system-message {
+ margin: 1em 2em;
border: thin solid;
- margin: 1em 2em;
padding: 0.5em 1em;
}
.sidebar {
Modified: trunk/docutils/docutils/writers/html5_polyglot/plain.css
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/plain.css 2021-06-25 20:57:05 UTC (rev 8774)
+++ trunk/docutils/docutils/writers/html5_polyglot/plain.css 2021-06-25 20:57:36 UTC (rev 8775)
@@ -45,6 +45,15 @@
border: none;
}
+/* Table of Contents */
+ul.auto-toc > li > p {
+ padding-left: 1em;
+ text-indent: -1em;
+}
+nav.contents ul {
+ padding-left: 1em;
+}
+
/* Transitions */
hr.docutils {
width: 80%;
@@ -58,7 +67,6 @@
/* vertical space (parskip) */
p, ol, ul, dl, li,
div.line-block,
-div.topic,
.footnote, .citation,
div > math,
table {
@@ -114,8 +122,8 @@
/* Bibliographic Fields */
-/* generally, bibliographic fields use special definition list dl.docinfo */
-/* but dedication and abstract are placed into "topic" divs */
+/* generally, bibliographic fields use dl.docinfo */
+/* but dedication and abstract are placed into divs */
div.abstract p.topic-title {
text-align: center;
}
@@ -137,14 +145,10 @@
font-family: monospace;
}
-/* Block Quotes */
-blockquote > table,
-div.topic > table {
- margin-top: 0;
- margin-bottom: 0;
-}
+/* Block Quotes and Topics */
+bockquote { margin: 1em 2em; }
blockquote p.attribution,
-div.topic p.attribution {
+.topic p.attribution {
text-align: right;
margin-left: 20%;
}
Modified: trunk/docutils/docutils/writers/html5_polyglot/responsive.css
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/responsive.css 2021-06-25 20:57:05 UTC (rev 8774)
+++ trunk/docutils/docutils/writers/html5_polyglot/responsive.css 2021-06-25 20:57:36 UTC (rev 8775)
@@ -47,7 +47,7 @@
/* Vertical Space (Parskip) */
p, ol, ul, dl, li,
div.line-block,
-div.topic,
+.topic,
.footnote, .citation,
div > math,
table {
@@ -58,14 +58,9 @@
dl > dd {
margin-bottom: 0.5em;
}
-blockquote > table,
-div.topic > table {
- margin-top: 0;
- margin-bottom: 0;
-}
/* Indented Blocks */
-blockquote, figure, div.topic {
+blockquote, figure, .topic {
margin: 1em 2%;
padding-left: 1em;
}
@@ -83,7 +78,7 @@
}
/* Frontmatter */
-div.topic.dedication {
+div.dedication {
padding: 0;
margin: 1.4em 0;
font-style: italic;
@@ -94,39 +89,34 @@
}
blockquote p.attribution,
-div.topic p.attribution {
+.topic p.attribution {
text-align: right;
}
/* Table of Contents */
-nav.contents,
-div.topic.contents {
- padding: 0;
-}
ul.auto-toc > li > p {
padding-left: 1em;
text-indent: -1em;
}
-nav.contents ul,
-div.topic.contents ul {
+nav.contents ul {
padding-left: 1em;
}
-main > div.topic.contents ul:not(.auto-toc) {
+main > nav.contents ul:not(.auto-toc) {
list-style-type: square;
}
-main > div.topic.contents ul ul:not(.auto-toc) {
+main > nav.contents ul ul:not(.auto-toc) {
list-style-type: disc;
}
-main > div.topic.contents ul ul ul:not(.auto-toc) {
+main > nav.contents ul ul ul:not(.auto-toc) {
list-style-type: '\2023\ ';
}
-main > div.topic.contents ul ul ul ul:not(.auto-toc) {
+main > nav.contents ul ul ul ul:not(.auto-toc) {
list-style-type: '\2B29\ ';
}
-main > div.topic.contents ul ul ul ul ul:not(.auto-toc) {
+main > nav.contents ul ul ul ul ul:not(.auto-toc) {
list-style-type: '\00B7\ ';
}
-div.topic.contents ul > li::marker {
+nav.contents ul > li::marker {
color: grey;
}
@@ -277,17 +267,16 @@
.contents a, a.toc-backref, a.citation-reference {
overflow-wrap: inherit;
}
-/* Undecorated Links */
+/* Undecorated Links (see also minimal.css) */
/* a.citation-reference, */
/* .contents a, */
-.citation a.fn-backref,
-a.toc-backref {
+.citation a.fn-backref {
color: inherit;
}
a:link:hover {
text-decoration: underline;}
/* highlight the active ToC entry */
-.topic.contents :target {
+.contents :target {
background-color: #d2e6ec;
}
@@ -392,7 +381,7 @@
padding-left: min(22%, 22rem);
padding-right: 7%;
}
- main > div.topic.contents { /* exclude local ToCs */
+ main > nav.contents { /* global ToC */
position: fixed;
top: 0;
left: 0;
@@ -403,7 +392,7 @@
padding: 1em 2% 0 2%;
overflow: auto;
}
- main > div.topic.contents > * {
+ main > nav.contents > * {
padding-left: 0;
}
}
Modified: trunk/docutils/docutils/writers/html5_polyglot/tuftig.css
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/tuftig.css 2021-06-25 20:57:05 UTC (rev 8774)
+++ trunk/docutils/docutils/writers/html5_polyglot/tuftig.css 2021-06-25 20:57:36 UTC (rev 8775)
@@ -63,15 +63,10 @@
p:last-child {
margin-bottom: 0;
}
-blockquote > table,
-div.topic > table {
- margin-top: 0;
- margin-bottom: 0;
-}
/* Indented Blocks */
blockquote,
-div.topic {
+.topic {
/* background-color: Honeydew; */
margin: 0.5em 2%;
padding-left: 1em;
@@ -138,7 +133,7 @@
}
/* Dedication and Abstract */
-div.topic.dedication {
+div.dedication {
padding: 0;
margin-left: 0;
font-style: italic;
@@ -151,12 +146,12 @@
/* Attribution */
blockquote p.attribution,
-div.topic p.attribution {
+.topic p.attribution {
text-align: right;
}
/* Table of Contents */
-div.topic.contents {
+nav.contents {
padding: 0;
font-style: italic;
}
@@ -164,7 +159,7 @@
padding-left: 1em;
text-indent: -1em;
}
-div.topic.contents ul {
+nav.contents ul {
padding-left: 1em;
}
@@ -517,10 +512,10 @@
/* Fullwidth Elements */
h1.title, p.subtitle,
dl.docinfo,
- div.topic.abstract,
- div.topic.dedication,
- div.topic.contents,
- div.system-message,
+ div.abstract,
+ div.dedication,
+ nav.contents,
+ aside.system-message,
pre,
.fullwidth,
.fullwidth img,
@@ -538,7 +533,7 @@
main, header, footer {
padding-left: 30%;
}
- main > div.topic.contents {
+ main > nav.contents {
position: fixed;
top: 0;
left: 0;
@@ -550,7 +545,7 @@
padding: 5.5em 2%;
overflow: auto;
}
- main > div.topic.contents > * {
+ main > nav.contents > * {
padding-left: 0;
}
}
Modified: trunk/docutils/test/functional/expected/footnotes_html5.html
===================================================================
--- trunk/docutils/test/functional/expected/footnotes_html5.html 2021-06-25 20:57:05 UTC (rev 8774)
+++ trunk/docutils/test/functional/expected/footnotes_html5.html 2021-06-25 20:57:36 UTC (rev 8775)
@@ -98,11 +98,11 @@
</aside>
<aside class="footnote superscript" id="footnote-9" role="note">
<span class="label"><span class="fn-bracket">[</span><a class="fn-backref" href="#footnote-reference-12">9</a><span class="fn-bracket">]</span></span>
-<div class="admonition note">
+<aside class="admonition note">
<p class="admonition-title">Note</p>
<p>This is a note in a note.</p>
-</div>
</aside>
+</aside>
<aside class="footnote superscript" id="footnote-10" role="note">
<span class="label"><span class="fn-bracket">[</span>10<span class="fn-bracket">]</span></span>
<table>
Modified: trunk/docutils/test/functional/expected/standalone_rst_html5.html
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_html5.html 2021-06-25 20:57:05 UTC (rev 8774)
+++ trunk/docutils/test/functional/expected/standalone_rst_html5.html 2021-06-25 20:57:36 UTC (rev 8775)
@@ -68,11 +68,11 @@
<p>Like this.</p>
</dd>
</dl>
-<div class="dedication topic">
+<div class="topic dedication" role="doc-dedication">
<p class="topic-title">Dedication</p>
<p>For Docutils users & co-developers.</p>
</div>
-<div class="abstract topic">
+<div class="topic abstract" role="doc-abstract">
<p class="topic-title">Abstract</p>
<p>This is a test document, containing at least one example of each
reStructuredText construct.</p>
@@ -82,7 +82,7 @@
<!-- Above is the document title, and below is the subtitle.
They are transformed from section titles after parsing. -->
<!-- bibliographic fields (which also require a transform): -->
-<div class="contents topic" id="table-of-contents">
+<nav class="contents" id="table-of-contents" role="doc-toc">
<p class="topic-title">Table of Contents</p>
<ul class="auto-toc simple">
<li><p><a class="reference internal" href="#structural-elements" id="toc-entry-1"><span class="sectnum">1</span> Structural Elements</a></p>
@@ -159,7 +159,7 @@
</li>
<li><p><a class="reference internal" href="#error-handling" id="toc-entry-52"><span class="sectnum">4</span> Error Handling</a></p></li>
</ul>
-</div>
+</nav>
<section id="structural-elements">
<h2><a class="toc-backref" href="#toc-entry-1"><span class="sectnum">1</span> Structural Elements</a></h2>
<section id="section-title">
@@ -546,7 +546,7 @@
</section>
<section id="directives">
<h3><a class="toc-backref" href="#toc-entry-22"><span class="sectnum">2.14</span> Directives</a></h3>
-<div class="contents local topic" id="contents">
+<nav class="contents local" id="contents">
<ul class="auto-toc simple">
<li><p><a class="reference internal" href="#document-parts" id="toc-entry-53"><span class="sectnum">2.14.1</span> Document Parts</a></p></li>
<li><p><a class="reference internal" href="#images-and-figures" id="toc-entry-54"><span class="sectnum">2.14.2</span> Images and Figures</a></p></li>
@@ -560,7 +560,7 @@
<li><p><a class="reference internal" href="#code" id="toc-entry-62"><span class="sectnum">2.14.10</span> Code</a></p></li>
<li><p><a class="reference internal" href="#meta" id="toc-entry-63"><span class="sectnum">2.14.11</span> Meta</a></p></li>
</ul>
-</div>
+</nav>
<p>These are just a sample of the many reStructuredText Directives. For
others, please see <a class="reference external" href="https://docutils.sourceforge.io/docs/ref/rst/directives.html">reStructuredText Directives</a> <a class="footnote-reference brackets" href="#footnote-13" id="footnote-reference-27"><span class="fn-bracket">[</span>13<span class="fn-bracket">]</span></a>.</p>
<section id="document-parts">
@@ -763,27 +763,27 @@
</section>
<section id="admonitions">
<h4><a class="toc-backref" href="#toc-entry-56"><span class="sectnum">2.14.4</span> Admonitions</a></h4>
-<div class="admonition attention">
+<aside class="admonition attention">
<p class="admonition-title">Attention!</p>
<p>Directives at large.</p>
-</div>
-<div class="admonition caution">
+</aside>
+<aside class="admonition caution">
<p class="admonition-title">Caution!</p>
<p>Don't take any wooden nickels.</p>
-</div>
-<div class="admonition danger">
+</aside>
+<aside class="admonition danger">
<p class="admonition-title">!DANGER!</p>
<p>Mad scientist at work!</p>
-</div>
-<div class="admonition error">
+</aside>
+<aside class="admonition error">
<p class="admonition-title">Error</p>
<p>Does not compute.</p>
-</div>
-<div class="admonition hint">
+</aside>
+<aside class="admonition hint">
<p class="admonition-title">Hint</p>
<p>It's bigger than a bread box.</p>
-</div>
-<div class="admonition important">
+</aside>
+<aside class="admonition important">
<p class="admonition-title">Important</p>
<ul class="simple">
<li><p>Wash behind your ears.</p></li>
@@ -791,24 +791,24 @@
<li><p>Call your mother.</p></li>
<li><p>Back up your data.</p></li>
</ul>
-</div>
-<div class="admonition note">
+</aside>
+<aside class="admonition note">
<p class="admonition-title">Note</p>
<p>This is a note.</p>
-</div>
-<div class="admonition tip">
+</aside>
+<aside class="admonition tip">
<p class="admonition-title">Tip</p>
<p>15% if the service is good.</p>
-</div>
-<div class="admonition warning">
+</aside>
+<aside class="admonition warning">
<p class="admonition-title">Warning</p>
<p>Strong prose may provoke extreme mental exertion.
Reader discretion is strongly advised.</p>
-</div>
-<div class="admonition admonition-and-by-the-way">
+</aside>
+<aside class="admonition admonition-and-by-the-way">
<p class="admonition-title">And, by the way...</p>
<p>You can make up your own admonition too.</p>
-</div>
+</aside>
</section>
<section id="topics-sidebars-and-rubrics">
<h4><a class="toc-backref" href="#toc-entry-57"><span class="sectnum">2.14.5</span> Topics, Sidebars, and Rubrics</a></h4>
@@ -824,10 +824,10 @@
</aside>
<p>A <em>topic</em> is like a block quote with a title, or a self-contained section
with no subsections.</p>
-<div class="topic">
+<aside class="topic">
<p class="topic-title">Topic Title</p>
<p>This is a topic.</p>
-</div>
+</aside>
<p>A <em>rubric</em> is like an informal heading that doesn't correspond to the
document's structure. It is typically highlighted in red (hence the name).</p>
<p class="rubric">This is a rubric</p>
@@ -994,10 +994,10 @@
<p>a paragraph followed by a comment,</p>
<!-- this is a comment -->
<p>a paragraph, a</p>
-<div class="admonition note">
+<aside class="admonition note">
<p class="admonition-title">Note</p>
<p>with content</p>
-</div>
+</aside>
<p>and the final paragraph of the compound 7.</p>
</div>
</section>
@@ -1779,26 +1779,26 @@
</section>
<section class="system-messages">
<h2>Docutils System Messages</h2>
-<div class="system-message" id="system-message-1">
+<aside class="system-message" id="system-message-1">
<p class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">functional/input/data/standard.txt</span>, line 99); <em><a href="#problematic-1">backlink</a></em></p>
<p>Undefined substitution referenced: "problematic".</p>
-</div>
-<div class="system-message" id="system-message-2">
+</aside>
+<aside class="system-message" id="system-message-2">
<p class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">functional/input/data/standard.txt</span>, line 387); <em><a href="#footnote-reference-8">backlink</a></em></p>
<p>Unknown target name: "5".</p>
-</div>
-<div class="system-message" id="system-message-3">
+</aside>
+<aside class="system-message" id="system-message-3">
<p class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">functional/input/data/standard.txt</span>, line 396); <em><a href="#citation-reference-3">backlink</a></em></p>
<p>Unknown target name: "nonexistent".</p>
-</div>
-<div class="system-message" id="system-message-4">
+</aside>
+<aside class="system-message" id="system-message-4">
<p class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">functional/input/data/standard.txt</span>, line 423); <em><a href="#problematic-2">backlink</a></em></p>
<p>Unknown target name: "hyperlink reference without a target".</p>
-</div>
-<div class="system-message" id="system-message-5">
+</aside>
+<aside class="system-message" id="system-message-5">
<p class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">functional/input/data/standard.txt</span>, line 436); <em><a href="#problematic-3">backlink</a></em></p>
<p>Duplicate target name, cannot be used as a unique reference: "duplicate target names".</p>
-</div>
+</aside>
</section>
</main>
<footer>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2021-06-25 20:58:19
|
Revision: 8777
http://sourceforge.net/p/docutils/code/8777
Author: milde
Date: 2021-06-25 20:58:17 +0000 (Fri, 25 Jun 2021)
Log Message:
-----------
HTML5: More ARIA roles, more descriptive class name.
ARIA roles for footnote references and backlinks.
Use class value "backrefs" instead of "fn-backref" for a span of
back-references.
Modified Paths:
--------------
trunk/docutils/HISTORY.txt
trunk/docutils/RELEASE-NOTES.txt
trunk/docutils/docutils/writers/_html_base.py
trunk/docutils/docutils/writers/html5_polyglot/minimal.css
trunk/docutils/docutils/writers/html5_polyglot/plain.css
trunk/docutils/test/functional/expected/footnotes_html5.html
trunk/docutils/test/functional/expected/standalone_rst_html5.html
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2021-06-25 20:57:58 UTC (rev 8776)
+++ trunk/docutils/HISTORY.txt 2021-06-25 20:58:17 UTC (rev 8777)
@@ -65,12 +65,22 @@
- Use semantic tags <aside> and <nav> for footnote text and citations,
topics, admonitions, and system-messages.
- - Do not add "compound-first", "compound-middle", or "compound-last" to
- elements nested in a compound (no change with `html4css1`).
+ - Use ARIA roles to enable accessible HTML for abstract, dedication,
+ the table of contents, footnote, references, footnotes, citations,
+ and backlinks.
+ - Do not set classes "compound-first", "compound-middle", or
+ "compound-last" to elements nested in a compound.
+ Use class value "backrefs" instead of "fn-backref" for a span of
+ back-references.
+
- Removed attribute ``HTMLTranslator.topic_classes``
+* docutils/writers/html4css1/__init__.py:
+ - Overwrite methods using semantic tags and roles to keep backwards
+ compatibility.
+
* docutils/writers/latex2e/__init__.py
- The setting `legacy_class_functions`_ now defaults to "False".
Modified: trunk/docutils/RELEASE-NOTES.txt
===================================================================
--- trunk/docutils/RELEASE-NOTES.txt 2021-06-25 20:57:58 UTC (rev 8776)
+++ trunk/docutils/RELEASE-NOTES.txt 2021-06-25 20:58:17 UTC (rev 8777)
@@ -25,6 +25,11 @@
- Use <summary> and <details> tags for term and definition of a
definition list with class value "details".
+ - Do not longer set the "footnote-reference" class value for footnote
+ references. Since 0.18, you can use the CSS selector
+ ``[role="doc-noteref"]`` instead of ``.footnote-reference``
+ (see minimal.css for examples).
+
- Move attribution behind the blockquote to comply with the
`"living standard"`__?
(HTML5__ allows <cite> elements inside a blockquote, cf. Example 16.)
@@ -79,17 +84,19 @@
Write footnote brackets and field term colons to HTML, so that they
are present also without CSS and when copying text.
- Use semantic tag <aside> for footnote text and citations,
+ Use semantic tag <aside> for footnote text and citations,
topics (except abstract and toc), admonitions, and system messages
Use <nav> for the Table of Contents.
Do not add "compound-first", "compound-middle", or "compound-last" to
- elements nested in a compound. Use child selector and "first-child",
- "last-child" pseudo classes instead.
+ elements nested in a compound. Use child selector and ":first-child",
+ ":last-child" pseudo classes instead.
+ Use class value "backrefs" instead of "fn-backref" for a span of
+ back-references.
LaTeX:
- `legacy_class_functions`_ setting default changed to
- "False", admonitions are now environments.
+ `legacy_class_functions`_ setting default changed to "False":
+ admonitions are now environments.
* ``nodes.Node.traverse()`` returns an iterator instead of a list.
Modified: trunk/docutils/docutils/writers/_html_base.py
===================================================================
--- trunk/docutils/docutils/writers/_html_base.py 2021-06-25 20:57:58 UTC (rev 8776)
+++ trunk/docutils/docutils/writers/_html_base.py 2021-06-25 20:58:17 UTC (rev 8777)
@@ -635,6 +635,7 @@
# 'Citation reference missing.'
self.body.append(self.starttag(
node, 'a', '[', CLASS='citation-reference', href=href))
+ # TODO: role='doc-biblioref' # HTML5 only
def depart_citation_reference(self, node):
self.body.append(']</a>')
@@ -916,6 +917,9 @@
# use HTML5 element <aside> with ARIA role "note" for footnote text
# (the html4css1 writer uses a table instead).
+ # TODO: role='doc-biblioentry' for citations
+ # (requires wrapping in an element with role='list'
+ # https://www.w3.org/TR/dpub-aria-1.0/#doc-biblioentry)
def visit_footnote(self, node):
classes = [node.tagname]
if isinstance(node, nodes.footnote):
@@ -929,8 +933,8 @@
def visit_footnote_reference(self, node):
href = '#' + node['refid']
classes = ['footnote-reference', self.settings.footnote_references]
- self.body.append(self.starttag(node, 'a', suffix='',
- classes=classes, href=href))
+ self.body.append(self.starttag(node, 'a', suffix='', classes=classes,
+ role='doc-noteref', href=href))
self.body.append('<span class="fn-bracket">[</span>')
def depart_footnote_reference(self, node):
@@ -1063,10 +1067,10 @@
self.body.append('<span class="fn-bracket">[</span>')
# footnote/citation backrefs:
if self.settings.footnote_backlinks:
- backrefs = node.parent['backrefs']
+ backrefs = node.parent.get('backrefs', [])
if len(backrefs) == 1:
- self.body.append('<a class="fn-backref" href="#%s">'
- % backrefs[0])
+ self.body.append('<a role="doc-backlink"'
+ ' href="#%s">' % backrefs[0])
def depart_label(self, node):
backrefs = node.parent.get('backrefs', [])
@@ -1075,9 +1079,9 @@
self.body.append('<span class="fn-bracket">]</span>')
self.body.append('</span>\n')
if len(backrefs) > 1:
- backlinks = ['<a href="#%s">%s</a>' % (ref, i)
+ backlinks = ['<a role="doc-backlink" href="#%s">%s</a>' % (ref, i)
for (i, ref) in enumerate(backrefs, 1)]
- self.body.append('<span class="fn-backref">(%s)</span>\n'
+ self.body.append('<span class="backrefs">(%s)</span>\n'
% ','.join(backlinks))
def visit_legend(self, node):
@@ -1617,6 +1621,7 @@
atts = {}
if node.hasattr('refid'):
atts['class'] = 'toc-backref'
+ # atts['role'] = 'doc-backlink' # HTML5 only
atts['href'] = '#' + node['refid']
if atts:
self.body.append(self.starttag({}, 'a', '', **atts))
Modified: trunk/docutils/docutils/writers/html5_polyglot/minimal.css
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/minimal.css 2021-06-25 20:57:58 UTC (rev 8776)
+++ trunk/docutils/docutils/writers/html5_polyglot/minimal.css 2021-06-25 20:58:17 UTC (rev 8777)
@@ -163,27 +163,27 @@
margin-top: 0;
vertical-align: top;
}
-.footnote > .fn-backref + *,
-.citation > .fn-backref + * {
+.footnote > .backrefs + *,
+.citation > .backrefs + * {
margin-top: 0;
}
-.footnote > .label + p, .footnote > .fn-backref + p,
-.citation > .label + p, .citation > .fn-backref + p {
+.footnote > .label + p, .footnote > .backrefs + p,
+.citation > .label + p, .citation > .backrefs + p {
display: inline;
vertical-align: inherit;
}
-.fn-backref > a { font-style: italic; }
+.backrefs > a { font-style: italic; }
/* superscript footnotes */
-a.footnote-reference.superscript,
+a[role="doc-noteref"].superscript,
.footnote.superscript > .label,
-.footnote.superscript > .fn-backref {
+.footnote.superscript > .backrefs {
vertical-align: super;
font-size: smaller;
line-height: 1;
}
-a.footnote-reference.superscript > .fn-bracket,
+a[role="doc-noteref"].superscript > .fn-bracket,
.footnote.superscript > .label > .fn-bracket {
/* hide brackets in display but leave for copy/paste */
display: inline-block;
@@ -190,7 +190,7 @@
width: 0;
overflow: hidden;
}
-.footnote-reference.superscript + .footnote-reference.superscript {
+[role="doc-noteref"].superscript + [role="doc-noteref"].superscript {
padding-left: 0.15em; /* separate consecutive footnote references */
/* TODO: unfortunately, "+" also selects with text between the references. */
}
Modified: trunk/docutils/docutils/writers/html5_polyglot/plain.css
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/plain.css 2021-06-25 20:57:58 UTC (rev 8776)
+++ trunk/docutils/docutils/writers/html5_polyglot/plain.css 2021-06-25 20:58:17 UTC (rev 8777)
@@ -301,6 +301,6 @@
/* Internal Targets */
/* span.target.internal */
/* Footnote References */
-/* a.footnote-reference */
+/* a[role="doc-noteref"] */
/* Citation References */
/* a.citation-reference */
Modified: trunk/docutils/test/functional/expected/footnotes_html5.html
===================================================================
--- trunk/docutils/test/functional/expected/footnotes_html5.html 2021-06-25 20:57:58 UTC (rev 8776)
+++ trunk/docutils/test/functional/expected/footnotes_html5.html 2021-06-25 20:58:17 UTC (rev 8777)
@@ -12,11 +12,11 @@
<main id="test-footnote-and-citation-rendering">
<h1 class="title">Test footnote and citation rendering</h1>
-<p>Paragraphs may contain footnote references (manually numbered<a class="footnote-reference superscript" href="#footnote-1" id="footnote-reference-1"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></a>, anonymous auto-numbered<a class="footnote-reference superscript" href="#footnote-2" id="footnote-reference-2"><span class="fn-bracket">[</span>3<span class="fn-bracket">]</span></a>, labeled auto-numbered<a class="footnote-reference superscript" href="#label" id="footnote-reference-3"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></a>, or
-symbolic<a class="footnote-reference superscript" href="#footnote-3" id="footnote-reference-4"><span class="fn-bracket">[</span>*<span class="fn-bracket">]</span></a>) or citation references (<a class="citation-reference" href="#cit2002" id="citation-reference-1">[CIT2002]</a>, <a class="citation-reference" href="#du2015" id="citation-reference-2">[DU2015]</a>).</p>
+<p>Paragraphs may contain footnote references (manually numbered<a class="footnote-reference superscript" href="#footnote-1" id="footnote-reference-1" role="doc-noteref"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></a>, anonymous auto-numbered<a class="footnote-reference superscript" href="#footnote-2" id="footnote-reference-2" role="doc-noteref"><span class="fn-bracket">[</span>3<span class="fn-bracket">]</span></a>, labeled auto-numbered<a class="footnote-reference superscript" href="#label" id="footnote-reference-3" role="doc-noteref"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></a>, or
+symbolic<a class="footnote-reference superscript" href="#footnote-3" id="footnote-reference-4" role="doc-noteref"><span class="fn-bracket">[</span>*<span class="fn-bracket">]</span></a>) or citation references (<a class="citation-reference" href="#cit2002" id="citation-reference-1">[CIT2002]</a>, <a class="citation-reference" href="#du2015" id="citation-reference-2">[DU2015]</a>).</p>
<aside class="footnote superscript" id="footnote-1" role="note">
<span class="label"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></span>
-<span class="fn-backref">(<a href="#footnote-reference-1">1</a>,<a href="#footnote-reference-5">2</a>)</span>
+<span class="backrefs">(<a role="doc-backlink" href="#footnote-reference-1">1</a>,<a role="doc-backlink" href="#footnote-reference-5">2</a>)</span>
<p>A footnote contains body elements, consistently indented by at
least 3 spaces.</p>
<p>This is the footnote's second paragraph.</p>
@@ -23,14 +23,14 @@
</aside>
<aside class="footnote superscript" id="label" role="note">
<span class="label"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></span>
-<span class="fn-backref">(<a href="#footnote-reference-3">1</a>,<a href="#footnote-reference-6">2</a>)</span>
-<p>Footnotes may be numbered, either manually (as in<a class="footnote-reference superscript" href="#footnote-1" id="footnote-reference-5"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></a>) or
+<span class="backrefs">(<a role="doc-backlink" href="#footnote-reference-3">1</a>,<a role="doc-backlink" href="#footnote-reference-6">2</a>)</span>
+<p>Footnotes may be numbered, either manually (as in<a class="footnote-reference superscript" href="#footnote-1" id="footnote-reference-5" role="doc-noteref"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></a>) or
automatically using a "#"-prefixed label. This footnote has a
label so it can be referred to from multiple places, both as a
-footnote reference (<a class="footnote-reference superscript" href="#label" id="footnote-reference-6"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></a>) and as a <a class="reference internal" href="#label">hyperlink reference</a>.</p>
+footnote reference (<a class="footnote-reference superscript" href="#label" id="footnote-reference-6" role="doc-noteref"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></a>) and as a <a class="reference internal" href="#label">hyperlink reference</a>.</p>
</aside>
<aside class="footnote superscript" id="footnote-2" role="note">
-<span class="label"><span class="fn-bracket">[</span><a class="fn-backref" href="#footnote-reference-2">3</a><span class="fn-bracket">]</span></span>
+<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-2">3</a><span class="fn-bracket">]</span></span>
<p>This footnote is numbered automatically and anonymously using a
label of "#" only.</p>
<p>This is the second paragraph.</p>
@@ -37,40 +37,40 @@
<p>And this is the third paragraph.</p>
</aside>
<aside class="footnote superscript" id="footnote-3" role="note">
-<span class="label"><span class="fn-bracket">[</span><a class="fn-backref" href="#footnote-reference-4">*</a><span class="fn-bracket">]</span></span>
+<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-4">*</a><span class="fn-bracket">]</span></span>
<p>Footnotes may also use symbols, specified with a "*" label.
-Here's a reference to the next footnote:<a class="footnote-reference superscript" href="#footnote-4" id="footnote-reference-7"><span class="fn-bracket">[</span>†<span class="fn-bracket">]</span></a>.</p>
+Here's a reference to the next footnote:<a class="footnote-reference superscript" href="#footnote-4" id="footnote-reference-7" role="doc-noteref"><span class="fn-bracket">[</span>†<span class="fn-bracket">]</span></a>.</p>
</aside>
<aside class="footnote superscript" id="footnote-4" role="note">
-<span class="label"><span class="fn-bracket">[</span><a class="fn-backref" href="#footnote-reference-7">†</a><span class="fn-bracket">]</span></span>
+<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-7">†</a><span class="fn-bracket">]</span></span>
<p>This footnote shows the next symbol in the sequence.</p>
</aside>
<aside class="footnote superscript" id="footnote-5" role="note">
<span class="label"><span class="fn-bracket">[</span>4<span class="fn-bracket">]</span></span>
<p>Here's an unreferenced footnote, with a reference to a
-nonexistent footnote:<a class="footnote-reference superscript" href="#footnote-6" id="footnote-reference-8"><span class="fn-bracket">[</span>5<span class="fn-bracket">]</span></a>.</p>
+nonexistent footnote:<a class="footnote-reference superscript" href="#footnote-6" id="footnote-reference-8" role="doc-noteref"><span class="fn-bracket">[</span>5<span class="fn-bracket">]</span></a>.</p>
</aside>
<section id="citations">
<h2>Citations</h2>
<aside class="citation" id="cit2002" role="note">
<span class="label"><span class="fn-bracket">[</span>CIT2002<span class="fn-bracket">]</span></span>
-<span class="fn-backref">(<a href="#citation-reference-1">1</a>,<a href="#citation-reference-3">2</a>)</span>
+<span class="backrefs">(<a role="doc-backlink" href="#citation-reference-1">1</a>,<a role="doc-backlink" href="#citation-reference-3">2</a>)</span>
<p>Citations are text-labeled footnotes. They may be
rendered separately and differently from footnotes.</p>
</aside>
<aside class="citation" id="du2015" role="note">
-<span class="label"><span class="fn-bracket">[</span><a class="fn-backref" href="#citation-reference-2">DU2015</a><span class="fn-bracket">]</span></span>
+<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#citation-reference-2">DU2015</a><span class="fn-bracket">]</span></span>
<p><cite>Example document</cite>, Hometown: 2015.</p>
</aside>
<p>Here's a reference to the above, <a class="citation-reference" href="#cit2002" id="citation-reference-3">[CIT2002]</a>.</p>
<aside class="footnote superscript" id="footnote-6" role="note">
-<span class="label"><span class="fn-bracket">[</span><a class="fn-backref" href="#footnote-reference-8">5</a><span class="fn-bracket">]</span></span>
+<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-8">5</a><span class="fn-bracket">]</span></span>
<p>this footnote is missing in the standard example document.</p>
</aside>
-<p>Footnotes may contain block elements like lists<a class="footnote-reference superscript" href="#list-note" id="footnote-reference-9"><span class="fn-bracket">[</span>7<span class="fn-bracket">]</span></a><a class="footnote-reference superscript" href="#footnote-7" id="footnote-reference-10"><span class="fn-bracket">[</span>6<span class="fn-bracket">]</span></a>,
-admonitions<a class="footnote-reference superscript" href="#footnote-8" id="footnote-reference-11"><span class="fn-bracket">[</span>8<span class="fn-bracket">]</span></a>, or tables<a class="footnote-reference superscript" href="#footnote-9" id="footnote-reference-12"><span class="fn-bracket">[</span>9<span class="fn-bracket">]</span></a>.</p>
+<p>Footnotes may contain block elements like lists<a class="footnote-reference superscript" href="#list-note" id="footnote-reference-9" role="doc-noteref"><span class="fn-bracket">[</span>7<span class="fn-bracket">]</span></a><a class="footnote-reference superscript" href="#footnote-7" id="footnote-reference-10" role="doc-noteref"><span class="fn-bracket">[</span>6<span class="fn-bracket">]</span></a>,
+admonitions<a class="footnote-reference superscript" href="#footnote-8" id="footnote-reference-11" role="doc-noteref"><span class="fn-bracket">[</span>8<span class="fn-bracket">]</span></a>, or tables<a class="footnote-reference superscript" href="#footnote-9" id="footnote-reference-12" role="doc-noteref"><span class="fn-bracket">[</span>9<span class="fn-bracket">]</span></a>.</p>
<aside class="footnote superscript" id="footnote-7" role="note">
-<span class="label"><span class="fn-bracket">[</span><a class="fn-backref" href="#footnote-reference-10">6</a><span class="fn-bracket">]</span></span>
+<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-10">6</a><span class="fn-bracket">]</span></span>
<ol class="arabic simple">
<li><p>An ordered list</p></li>
<li><p>in a footnote.</p></li>
@@ -78,7 +78,7 @@
</aside>
<aside class="footnote superscript" id="list-note" role="note">
<span class="label"><span class="fn-bracket">[</span>7<span class="fn-bracket">]</span></span>
-<span class="fn-backref">(<a href="#footnote-reference-9">1</a>,<a href="#footnote-reference-13">2</a>)</span>
+<span class="backrefs">(<a role="doc-backlink" href="#footnote-reference-9">1</a>,<a role="doc-backlink" href="#footnote-reference-13">2</a>)</span>
<ul class="simple">
<li><p>An unordered list (bullet list)</p></li>
<li><p>in a footnote.</p></li>
@@ -86,7 +86,7 @@
<p>And a trailing paragraph.</p>
</aside>
<aside class="footnote superscript" id="footnote-8" role="note">
-<span class="label"><span class="fn-bracket">[</span><a class="fn-backref" href="#footnote-reference-11">8</a><span class="fn-bracket">]</span></span>
+<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-11">8</a><span class="fn-bracket">]</span></span>
<dl class="field-list simple">
<dt>Field<span class="colon">:</span></dt>
<dd><p>list</p>
@@ -97,7 +97,7 @@
</dl>
</aside>
<aside class="footnote superscript" id="footnote-9" role="note">
-<span class="label"><span class="fn-bracket">[</span><a class="fn-backref" href="#footnote-reference-12">9</a><span class="fn-bracket">]</span></span>
+<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-12">9</a><span class="fn-bracket">]</span></span>
<aside class="admonition note">
<p class="admonition-title">Note</p>
<p>This is a note in a note.</p>
@@ -120,7 +120,7 @@
</tbody>
</table>
</aside>
-<p>This<a class="footnote-reference superscript" href="#list-note" id="footnote-reference-13"><span class="fn-bracket">[</span>7<span class="fn-bracket">]</span></a> is a second reference to the footnote containing
+<p>This<a class="footnote-reference superscript" href="#list-note" id="footnote-reference-13" role="doc-noteref"><span class="fn-bracket">[</span>7<span class="fn-bracket">]</span></a> is a second reference to the footnote containing
a bullet. list.</p>
</section>
</main>
Modified: trunk/docutils/test/functional/expected/standalone_rst_html5.html
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_html5.html 2021-06-25 20:57:58 UTC (rev 8776)
+++ trunk/docutils/test/functional/expected/standalone_rst_html5.html 2021-06-25 20:58:17 UTC (rev 8777)
@@ -189,12 +189,12 @@
<h4><a class="toc-backref" href="#toc-entry-7"><span class="sectnum">2.1.1</span> Inline Markup</a></h4>
<p>Paragraphs contain text and may contain inline markup: <em>emphasis</em>,
<strong>strong emphasis</strong>, <span class="docutils literal">inline literals</span>, standalone hyperlinks
-(<a class="reference external" href="http://www.python.org">http://www.python.org</a>), external hyperlinks (<a class="reference external" href="http://www.python.org/">Python</a> <a class="footnote-reference brackets" href="#footnote-7" id="footnote-reference-18"><span class="fn-bracket">[</span>7<span class="fn-bracket">]</span></a>), internal
+(<a class="reference external" href="http://www.python.org">http://www.python.org</a>), external hyperlinks (<a class="reference external" href="http://www.python.org/">Python</a> <a class="footnote-reference brackets" href="#footnote-7" id="footnote-reference-18" role="doc-noteref"><span class="fn-bracket">[</span>7<span class="fn-bracket">]</span></a>), internal
cross-references (<a class="reference internal" href="#example">example</a>), external hyperlinks with embedded URIs
(<a class="reference external" href="http://www.python.org">Python web site</a>), <a class="reference external" href="http://www.python.org/">anonymous hyperlink
-references</a> <a class="footnote-reference brackets" href="#footnote-7" id="footnote-reference-25"><span class="fn-bracket">[</span>7<span class="fn-bracket">]</span></a> (<a class="reference external" href="https://docutils.sourceforge.io/">a second reference</a> <a class="footnote-reference brackets" href="#footnote-12" id="footnote-reference-26"><span class="fn-bracket">[</span>12<span class="fn-bracket">]</span></a>), footnote references (manually
-numbered <a class="footnote-reference brackets" href="#footnote-1" id="footnote-reference-1"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></a>, anonymous auto-numbered <a class="footnote-reference brackets" href="#footnote-2" id="footnote-reference-2"><span class="fn-bracket">[</span>3<span class="fn-bracket">]</span></a>, labeled auto-numbered
-<a class="footnote-reference brackets" href="#label" id="footnote-reference-3"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></a>, or symbolic <a class="footnote-reference brackets" href="#footnote-3" id="footnote-reference-4"><span class="fn-bracket">[</span>*<span class="fn-bracket">]</span></a>), citation references (see <a class="citation-reference" href="#cit2002" id="citation-reference-1">[CIT2002]</a>),
+references</a> <a class="footnote-reference brackets" href="#footnote-7" id="footnote-reference-25" role="doc-noteref"><span class="fn-bracket">[</span>7<span class="fn-bracket">]</span></a> (<a class="reference external" href="https://docutils.sourceforge.io/">a second reference</a> <a class="footnote-reference brackets" href="#footnote-12" id="footnote-reference-26" role="doc-noteref"><span class="fn-bracket">[</span>12<span class="fn-bracket">]</span></a>), footnote references (manually
+numbered <a class="footnote-reference brackets" href="#footnote-1" id="footnote-reference-1" role="doc-noteref"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></a>, anonymous auto-numbered <a class="footnote-reference brackets" href="#footnote-2" id="footnote-reference-2" role="doc-noteref"><span class="fn-bracket">[</span>3<span class="fn-bracket">]</span></a>, labeled auto-numbered
+<a class="footnote-reference brackets" href="#label" id="footnote-reference-3" role="doc-noteref"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></a>, or symbolic <a class="footnote-reference brackets" href="#footnote-3" id="footnote-reference-4" role="doc-noteref"><span class="fn-bracket">[</span>*<span class="fn-bracket">]</span></a>), citation references (see <a class="citation-reference" href="#cit2002" id="citation-reference-1">[CIT2002]</a>),
substitution references (<img alt="EXAMPLE" src="../../../docs/user/rst/images/biohazard.png" /> &
a <em>trimmed heart</em> <span class="docutils literal">(U+2665):</span>♥), and <span class="target" id="inline-hyperlink-targets">inline hyperlink targets</span>
(see <a class="reference internal" href="#targets">Targets</a> below for a reference back to here). Character-level
@@ -472,7 +472,7 @@
<h3><a class="toc-backref" href="#toc-entry-17"><span class="sectnum">2.11</span> Footnotes</a></h3>
<aside class="footnote brackets" id="footnote-1" role="note">
<span class="label"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></span>
-<span class="fn-backref">(<a href="#footnote-reference-1">1</a>,<a href="#footnote-reference-5">2</a>,<a href="#footnote-reference-9">3</a>)</span>
+<span class="backrefs">(<a role="doc-backlink" href="#footnote-reference-1">1</a>,<a role="doc-backlink" href="#footnote-reference-5">2</a>,<a role="doc-backlink" href="#footnote-reference-9">3</a>)</span>
<p>A footnote contains body elements, consistently indented by at
least 3 spaces.</p>
<p>This is the footnote's second paragraph.</p>
@@ -479,14 +479,14 @@
</aside>
<aside class="footnote brackets" id="label" role="note">
<span class="label"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></span>
-<span class="fn-backref">(<a href="#footnote-reference-3">1</a>,<a href="#footnote-reference-6">2</a>)</span>
-<p>Footnotes may be numbered, either manually (as in <a class="footnote-reference brackets" href="#footnote-1" id="footnote-reference-5"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></a>) or
+<span class="backrefs">(<a role="doc-backlink" href="#footnote-reference-3">1</a>,<a role="doc-backlink" href="#footnote-reference-6">2</a>)</span>
+<p>Footnotes may be numbered, either manually (as in <a class="footnote-reference brackets" href="#footnote-1" id="footnote-reference-5" role="doc-noteref"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></a>) or
automatically using a "#"-prefixed label. This footnote has a
label so it can be referred to from multiple places, both as a
-footnote reference (<a class="footnote-reference brackets" href="#label" id="footnote-reference-6"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></a>) and as a <a class="reference internal" href="#label">hyperlink reference</a>.</p>
+footnote reference (<a class="footnote-reference brackets" href="#label" id="footnote-reference-6" role="doc-noteref"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></a>) and as a <a class="reference internal" href="#label">hyperlink reference</a>.</p>
</aside>
<aside class="footnote brackets" id="footnote-2" role="note">
-<span class="label"><span class="fn-bracket">[</span><a class="fn-backref" href="#footnote-reference-2">3</a><span class="fn-bracket">]</span></span>
+<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-2">3</a><span class="fn-bracket">]</span></span>
<p>This footnote is numbered automatically and anonymously using a
label of "#" only.</p>
<p>This is the second paragraph.</p>
@@ -493,12 +493,12 @@
<p>And this is the third paragraph.</p>
</aside>
<aside class="footnote brackets" id="footnote-3" role="note">
-<span class="label"><span class="fn-bracket">[</span><a class="fn-backref" href="#footnote-reference-4">*</a><span class="fn-bracket">]</span></span>
+<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-4">*</a><span class="fn-bracket">]</span></span>
<p>Footnotes may also use symbols, specified with a "*" label.
-Here's a reference to the next footnote: <a class="footnote-reference brackets" href="#footnote-4" id="footnote-reference-7"><spa...
[truncated message content] |
|
From: <mi...@us...> - 2021-06-25 20:58:56
|
Revision: 8779
http://sourceforge.net/p/docutils/code/8779
Author: milde
Date: 2021-06-25 20:58:55 +0000 (Fri, 25 Jun 2021)
Log Message:
-----------
HTML5: ARIA roles for citations and citation-references.
Use <div> with DPub ARIA role "doc-biblioentry" for citations.
Wrapping citations in a list (required for elements with role
"doc-biblioentry").
Use role "doc-biblioref" for citation-references.
Modified Paths:
--------------
trunk/docutils/docutils/nodes.py
trunk/docutils/docutils/writers/_html_base.py
trunk/docutils/docutils/writers/html4css1/__init__.py
trunk/docutils/docutils/writers/html5_polyglot/minimal.css
trunk/docutils/test/functional/expected/footnotes_html5.html
trunk/docutils/test/functional/expected/standalone_rst_html5.html
trunk/docutils/test/functional/input/footnotes.txt
Modified: trunk/docutils/docutils/nodes.py
===================================================================
--- trunk/docutils/docutils/nodes.py 2021-06-25 20:58:33 UTC (rev 8778)
+++ trunk/docutils/docutils/nodes.py 2021-06-25 20:58:55 UTC (rev 8779)
@@ -324,6 +324,13 @@
except StopIteration:
return None
+ def previous_sibling(self):
+ """Return preceding sibling node or ``None``."""
+ try:
+ return self.parent[self.parent.index(self)-1]
+ except (AttributeError, IndexError):
+ return None
+
if sys.version_info < (3, 0):
class reprunicode(unicode):
"""
Modified: trunk/docutils/docutils/writers/_html_base.py
===================================================================
--- trunk/docutils/docutils/writers/_html_base.py 2021-06-25 20:58:33 UTC (rev 8778)
+++ trunk/docutils/docutils/writers/_html_base.py 2021-06-25 20:58:55 UTC (rev 8779)
@@ -619,12 +619,23 @@
def depart_caption(self, node):
self.body.append('</p>\n')
+ # Use semantic tag and DPub role (HTML4 uses a table)
def visit_citation(self, node):
- self.visit_footnote(node)
+ # role 'doc-bibloentry' requires wrapping in an element with
+ # role 'list' and an element with role 'doc-bibliography'
+ # https://www.w3.org/TR/dpub-aria-1.0/#doc-biblioentry)
+ if not isinstance(node.previous_sibling(), type(node)):
+ self.body.append('<div role="list" class="citation-list">\n')
+ self.body.append(self.starttag(node, 'div', classes=[node.tagname],
+ role="doc-biblioentry"))
def depart_citation(self, node):
- self.depart_footnote(node)
+ self.body.append('</div>\n')
+ next_node = node.next_node(descend=False, siblings=True)
+ if not isinstance(next_node, type(node)):
+ self.body.append('</div>\n')
+ # Use DPub role (overwritten in HTML4)
def visit_citation_reference(self, node):
href = '#'
if 'refid' in node:
@@ -633,9 +644,9 @@
href += self.document.nameids[node['refname']]
# else: # TODO system message (or already in the transform)?
# 'Citation reference missing.'
- self.body.append(self.starttag(
- node, 'a', '[', CLASS='citation-reference', href=href))
- # TODO: role='doc-biblioref' # HTML5 only
+ self.body.append(self.starttag(node, 'a', suffix='[', href=href,
+ classes=['citation-reference'],
+ role='doc-biblioref'))
def depart_citation_reference(self, node):
self.body.append(']</a>')
@@ -916,16 +927,11 @@
del self.body[start:]
# use HTML5 element <aside> with ARIA role "note" for footnote text
- # (the html4css1 writer uses a table instead).
- # TODO: role='doc-biblioentry' for citations
- # (requires wrapping in an element with role='list'
- # https://www.w3.org/TR/dpub-aria-1.0/#doc-biblioentry)
+ # (the html4css1 writer uses a table).
def visit_footnote(self, node):
- classes = [node.tagname]
- if isinstance(node, nodes.footnote):
- classes.append(self.settings.footnote_references)
- self.body.append(self.starttag(node, 'aside',
- classes=classes, role="note"))
+ classes = [node.tagname, self.settings.footnote_references]
+ self.body.append(self.starttag(node, 'aside', classes=classes,
+ role="note"))
def depart_footnote(self, node):
self.body.append('</aside>\n')
@@ -1076,8 +1082,7 @@
backrefs = node.parent.get('backrefs', [])
if len(backrefs) == 1:
self.body.append('</a>')
- self.body.append('<span class="fn-bracket">]</span>')
- self.body.append('</span>\n')
+ self.body.append('<span class="fn-bracket">]</span></span>\n')
if len(backrefs) > 1:
backlinks = ['<a role="doc-backlink" href="#%s">%s</a>' % (ref, i)
for (i, ref) in enumerate(backrefs, 1)]
Modified: trunk/docutils/docutils/writers/html4css1/__init__.py
===================================================================
--- trunk/docutils/docutils/writers/html4css1/__init__.py 2021-06-25 20:58:33 UTC (rev 8778)
+++ trunk/docutils/docutils/writers/html4css1/__init__.py 2021-06-25 20:58:55 UTC (rev 8779)
@@ -260,6 +260,18 @@
self.body.append('</td></tr>\n'
'</tbody>\n</table>\n')
+ def visit_citation_reference(self, node):
+ href = '#'
+ if 'refid' in node:
+ href += node['refid']
+ elif 'refname' in node:
+ href += self.document.nameids[node['refname']]
+ self.body.append(self.starttag(node, 'a', suffix='[', href=href,
+ classes=['citation-reference']))
+
+ def depart_citation_reference(self, node):
+ self.body.append(']</a>')
+
# insert classifier-delimiter (not required with CSS2)
def visit_classifier(self, node):
self.body.append(' <span class="classifier-delimiter">:</span> ')
@@ -345,7 +357,7 @@
def depart_doctest_block(self, node):
self.body.append('\n</pre>\n')
-
+
# insert an NBSP into empty cells, ersatz for first/last
def visit_entry(self, node):
writers._html_base.HTMLTranslator.visit_entry(self, node)
Modified: trunk/docutils/docutils/writers/html5_polyglot/minimal.css
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/minimal.css 2021-06-25 20:58:33 UTC (rev 8778)
+++ trunk/docutils/docutils/writers/html5_polyglot/minimal.css 2021-06-25 20:58:55 UTC (rev 8779)
@@ -146,16 +146,14 @@
/* Footnotes and Citations */
-.footnote, .citation {
- margin: 1em 0; /* default paragraph skip (Firefox) */
-}
+.footnote, .citation { margin: 1em 0; } /* default paragraph skip (Firefox) */
/* hanging indent */
+.citation { padding-left: 2em; }
.footnote { padding-left: 1.7em; }
-.citation { padding-left: 2em; }
-.footnote.superscript { padding-left: 1em; }
+.footnote.superscript { padding-left: 0.9em; }
+.citation > .label { margin-left: -2em; }
.footnote > .label { margin-left: -1.7em; }
-.citation > .label { margin-left: -2em; }
-.footnote.superscript > .label { margin-left: -1em; }
+.footnote.superscript > .label { margin-left: -0.9em; }
.footnote > .label + *,
.citation > .label + * {
Modified: trunk/docutils/test/functional/expected/footnotes_html5.html
===================================================================
--- trunk/docutils/test/functional/expected/footnotes_html5.html 2021-06-25 20:58:33 UTC (rev 8778)
+++ trunk/docutils/test/functional/expected/footnotes_html5.html 2021-06-25 20:58:55 UTC (rev 8779)
@@ -13,7 +13,7 @@
<h1 class="title">Test footnote and citation rendering</h1>
<p>Paragraphs may contain footnote references (manually numbered<a class="footnote-reference superscript" href="#footnote-1" id="footnote-reference-1" role="doc-noteref"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></a>, anonymous auto-numbered<a class="footnote-reference superscript" href="#footnote-2" id="footnote-reference-2" role="doc-noteref"><span class="fn-bracket">[</span>3<span class="fn-bracket">]</span></a>, labeled auto-numbered<a class="footnote-reference superscript" href="#label" id="footnote-reference-3" role="doc-noteref"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></a>, or
-symbolic<a class="footnote-reference superscript" href="#footnote-3" id="footnote-reference-4" role="doc-noteref"><span class="fn-bracket">[</span>*<span class="fn-bracket">]</span></a>) or citation references (<a class="citation-reference" href="#cit2002" id="citation-reference-1">[CIT2002]</a>, <a class="citation-reference" href="#du2015" id="citation-reference-2">[DU2015]</a>).</p>
+symbolic<a class="footnote-reference superscript" href="#footnote-3" id="footnote-reference-4" role="doc-noteref"><span class="fn-bracket">[</span>*<span class="fn-bracket">]</span></a>) or citation references (<a class="citation-reference" href="#cit2002" id="citation-reference-1" role="doc-biblioref">[CIT2002]</a>, <a class="citation-reference" href="#du2015" id="citation-reference-2" role="doc-biblioref">[DU2015]</a>).</p>
<aside class="footnote superscript" id="footnote-1" role="note">
<span class="label"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></span>
<span class="backrefs">(<a role="doc-backlink" href="#footnote-reference-1">1</a>,<a role="doc-backlink" href="#footnote-reference-5">2</a>)</span>
@@ -52,25 +52,27 @@
</aside>
<section id="citations">
<h2>Citations</h2>
-<aside class="citation" id="cit2002" role="note">
+<div role="list" class="citation-list">
+<div class="citation" id="cit2002" role="doc-biblioentry">
<span class="label"><span class="fn-bracket">[</span>CIT2002<span class="fn-bracket">]</span></span>
<span class="backrefs">(<a role="doc-backlink" href="#citation-reference-1">1</a>,<a role="doc-backlink" href="#citation-reference-3">2</a>)</span>
<p>Citations are text-labeled footnotes. They may be
rendered separately and differently from footnotes.</p>
-</aside>
-<aside class="citation" id="du2015" role="note">
+</div>
+<div class="citation" id="du2015" role="doc-biblioentry">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#citation-reference-2">DU2015</a><span class="fn-bracket">]</span></span>
<p><cite>Example document</cite>, Hometown: 2015.</p>
-</aside>
-<p>Here's a reference to the above, <a class="citation-reference" href="#cit2002" id="citation-reference-3">[CIT2002]</a>.</p>
+</div>
+</div>
+<p>Here's a reference to the above, <a class="citation-reference" href="#cit2002" id="citation-reference-3" role="doc-biblioref">[CIT2002]</a>.</p>
<aside class="footnote superscript" id="footnote-6" role="note">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-8">5</a><span class="fn-bracket">]</span></span>
<p>this footnote is missing in the standard example document.</p>
</aside>
-<p>Footnotes may contain block elements like lists<a class="footnote-reference superscript" href="#list-note" id="footnote-reference-9" role="doc-noteref"><span class="fn-bracket">[</span>7<span class="fn-bracket">]</span></a><a class="footnote-reference superscript" href="#footnote-7" id="footnote-reference-10" role="doc-noteref"><span class="fn-bracket">[</span>6<span class="fn-bracket">]</span></a>,
-admonitions<a class="footnote-reference superscript" href="#footnote-8" id="footnote-reference-11" role="doc-noteref"><span class="fn-bracket">[</span>8<span class="fn-bracket">]</span></a>, or tables<a class="footnote-reference superscript" href="#footnote-9" id="footnote-reference-12" role="doc-noteref"><span class="fn-bracket">[</span>9<span class="fn-bracket">]</span></a>.</p>
+<p>Footnotes may contain block elements like lists<a class="footnote-reference superscript" href="#footnote-7" id="footnote-reference-9" role="doc-noteref"><span class="fn-bracket">[</span>6<span class="fn-bracket">]</span></a><a class="footnote-reference superscript" href="#list-note" id="footnote-reference-10" role="doc-noteref"><span class="fn-bracket">[</span>7<span class="fn-bracket">]</span></a><a class="footnote-reference superscript" href="#footnote-8" id="footnote-reference-11" role="doc-noteref"><span class="fn-bracket">[</span>8<span class="fn-bracket">]</span></a>,
+admonitions<a class="footnote-reference superscript" href="#footnote-9" id="footnote-reference-12" role="doc-noteref"><span class="fn-bracket">[</span>9<span class="fn-bracket">]</span></a>, or tables<a class="footnote-reference superscript" href="#footnote-10" id="footnote-reference-13" role="doc-noteref"><span class="fn-bracket">[</span>10<span class="fn-bracket">]</span></a>.</p>
<aside class="footnote superscript" id="footnote-7" role="note">
-<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-10">6</a><span class="fn-bracket">]</span></span>
+<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-9">6</a><span class="fn-bracket">]</span></span>
<ol class="arabic simple">
<li><p>An ordered list</p></li>
<li><p>in a footnote.</p></li>
@@ -78,7 +80,7 @@
</aside>
<aside class="footnote superscript" id="list-note" role="note">
<span class="label"><span class="fn-bracket">[</span>7<span class="fn-bracket">]</span></span>
-<span class="backrefs">(<a role="doc-backlink" href="#footnote-reference-9">1</a>,<a role="doc-backlink" href="#footnote-reference-13">2</a>)</span>
+<span class="backrefs">(<a role="doc-backlink" href="#footnote-reference-10">1</a>,<a role="doc-backlink" href="#footnote-reference-14">2</a>)</span>
<ul class="simple">
<li><p>An unordered list (bullet list)</p></li>
<li><p>in a footnote.</p></li>
@@ -104,7 +106,7 @@
</aside>
</aside>
<aside class="footnote superscript" id="footnote-10" role="note">
-<span class="label"><span class="fn-bracket">[</span>10<span class="fn-bracket">]</span></span>
+<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-13">10</a><span class="fn-bracket">]</span></span>
<table>
<colgroup>
<col style="width: 36%" />
@@ -120,7 +122,7 @@
</tbody>
</table>
</aside>
-<p>This<a class="footnote-reference superscript" href="#list-note" id="footnote-reference-13" role="doc-noteref"><span class="fn-bracket">[</span>7<span class="fn-bracket">]</span></a> is a second reference to the footnote containing
+<p>This<a class="footnote-reference superscript" href="#list-note" id="footnote-reference-14" role="doc-noteref"><span class="fn-bracket">[</span>7<span class="fn-bracket">]</span></a> is a second reference to the footnote containing
a bullet. list.</p>
</section>
</main>
Modified: trunk/docutils/test/functional/expected/standalone_rst_html5.html
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_html5.html 2021-06-25 20:58:33 UTC (rev 8778)
+++ trunk/docutils/test/functional/expected/standalone_rst_html5.html 2021-06-25 20:58:55 UTC (rev 8779)
@@ -194,7 +194,7 @@
(<a class="reference external" href="http://www.python.org">Python web site</a>), <a class="reference external" href="http://www.python.org/">anonymous hyperlink
references</a> <a class="footnote-reference brackets" href="#footnote-7" id="footnote-reference-25" role="doc-noteref"><span class="fn-bracket">[</span>7<span class="fn-bracket">]</span></a> (<a class="reference external" href="https://docutils.sourceforge.io/">a second reference</a> <a class="footnote-reference brackets" href="#footnote-12" id="footnote-reference-26" role="doc-noteref"><span class="fn-bracket">[</span>12<span class="fn-bracket">]</span></a>), footnote references (manually
numbered <a class="footnote-reference brackets" href="#footnote-1" id="footnote-reference-1" role="doc-noteref"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></a>, anonymous auto-numbered <a class="footnote-reference brackets" href="#footnote-2" id="footnote-reference-2" role="doc-noteref"><span class="fn-bracket">[</span>3<span class="fn-bracket">]</span></a>, labeled auto-numbered
-<a class="footnote-reference brackets" href="#label" id="footnote-reference-3" role="doc-noteref"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></a>, or symbolic <a class="footnote-reference brackets" href="#footnote-3" id="footnote-reference-4" role="doc-noteref"><span class="fn-bracket">[</span>*<span class="fn-bracket">]</span></a>), citation references (see <a class="citation-reference" href="#cit2002" id="citation-reference-1">[CIT2002]</a>),
+<a class="footnote-reference brackets" href="#label" id="footnote-reference-3" role="doc-noteref"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></a>, or symbolic <a class="footnote-reference brackets" href="#footnote-3" id="footnote-reference-4" role="doc-noteref"><span class="fn-bracket">[</span>*<span class="fn-bracket">]</span></a>), citation references (see <a class="citation-reference" href="#cit2002" id="citation-reference-1" role="doc-biblioref">[CIT2002]</a>),
substitution references (<img alt="EXAMPLE" src="../../../docs/user/rst/images/biohazard.png" /> &
a <em>trimmed heart</em> <span class="docutils literal">(U+2665):</span>♥), and <span class="target" id="inline-hyperlink-targets">inline hyperlink targets</span>
(see <a class="reference internal" href="#targets">Targets</a> below for a reference back to here). Character-level
@@ -509,13 +509,15 @@
</section>
<section id="citations">
<h3><a class="toc-backref" href="#toc-entry-18"><span class="sectnum">2.12</span> Citations</a></h3>
-<aside class="citation" id="cit2002" role="note">
+<div role="list" class="citation-list">
+<div class="citation" id="cit2002" role="doc-biblioentry">
<span class="label"><span class="fn-bracket">[</span>CIT2002<span class="fn-bracket">]</span></span>
<span class="backrefs">(<a role="doc-backlink" href="#citation-reference-1">1</a>,<a role="doc-backlink" href="#citation-reference-2">2</a>)</span>
<p>Citations are text-labeled footnotes. They may be
rendered separately and differently from footnotes.</p>
-</aside>
-<p>Here's a reference to the above, <a class="citation-reference" href="#cit2002" id="citation-reference-2">[CIT2002]</a>, and a <a href="#system-message-3"><span class="problematic" id="citation-reference-3">[nonexistent]_</span></a>
+</div>
+</div>
+<p>Here's a reference to the above, <a class="citation-reference" href="#cit2002" id="citation-reference-2" role="doc-biblioref">[CIT2002]</a>, and a <a href="#system-message-3"><span class="problematic" id="citation-reference-3">[nonexistent]_</span></a>
citation.</p>
</section>
<section id="targets">
Modified: trunk/docutils/test/functional/input/footnotes.txt
===================================================================
--- trunk/docutils/test/functional/input/footnotes.txt 2021-06-25 20:58:33 UTC (rev 8778)
+++ trunk/docutils/test/functional/input/footnotes.txt 2021-06-25 20:58:55 UTC (rev 8779)
@@ -16,7 +16,7 @@
.. [5] this footnote is missing in the standard example document.
-Footnotes may contain block elements like lists [#list-note]_ [#]_,
+Footnotes may contain block elements like lists [#]_ [#list-note]_ [#]_,
admonitions [#]_, or tables [#]_.
.. [#] #. An ordered list
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2021-06-26 22:17:05
|
Revision: 8781
http://sourceforge.net/p/docutils/code/8781
Author: milde
Date: 2021-06-26 22:17:04 +0000 (Sat, 26 Jun 2021)
Log Message:
-----------
Update TODO documentation.
Modified Paths:
--------------
trunk/docutils/docs/dev/todo.txt
trunk/docutils/docutils/writers/latex2e/__init__.py
Modified: trunk/docutils/docs/dev/todo.txt
===================================================================
--- trunk/docutils/docs/dev/todo.txt 2021-06-25 20:59:26 UTC (rev 8780)
+++ trunk/docutils/docs/dev/todo.txt 2021-06-26 22:17:04 UTC (rev 8781)
@@ -2447,30 +2447,40 @@
* Paragraph following field-list or table in compound is indented.
- This is a problem with the current DUfieldlist definition and with
- the use of "longtable" for tables.
- See `LaTeX constructs and packages instead of re-implementations`_ for
- alternatives.
+ This is a problem with the current DUfieldlist definition and with the
+ use of "longtable" for tables. See `other LaTeX constructs and packages
+ instead of re-implementations`_ for alternatives.
Generate clean and configurable LaTeX source
----------------------------------------------
-* Check the generated source with package `nag`.
+Which packages do we want to use?
++ base and "recommended" packages
+
+ (packages that should be in a "reasonably sized and reasonably modern
+ LaTeX installation like the `texlive-latex-recommended` Debian package,
+ say):
+
++ No "fancy" or "exotic" requirements.
+
++ pointers to advanced packages and their use in the `latex writer
+ documentation`_.
+
Configurable placement of figure and table floats
`````````````````````````````````````````````````
* Special class argument to individually place figures?
- Either:
+ Example::
- placement-<optional arg> -> \figure[<optional arg>]{...}
+ .. figure:: foo.pdf
+ :class: place-here-if-possible place-top place-bottom
- e.g. ``.. class:: placement-htb``,
+ would be written as ``\figure[htb]{...}`` with
+ the optional args:
- or more verbose:
-
:H: place-here
:h: place-here-if-possible
:t: place-top
@@ -2477,121 +2487,79 @@
:b: place-bottom
:p: place-on-extra-page
- e.g.: ``.. class:: place-here-if-possible place-top place-bottom``
+ Alternative: class value = "place-" + optional arg, e.g. ``:class:
+ place-htb``.
- Maybe support both variants?
+Footnotes
+`````````
++ True footnotes with LaTeX auto-numbering (as option ``--latex-footnotes``)
+ (also for target-footnotes):
+ Write ``\footnote{<footnote content>}`` at the place of the
+ ``<footnote_reference>`` node.
-LaTeX constructs and packages instead of re-implementations
-```````````````````````````````````````````````````````````
++ Open questions:
-Which packages do we want to use?
+ - Load hyperref_ with option "hyperfootnotes" and/or
+ package footnotebackref_ or leave this to the user?
- + base and "recommended" packages
+ - Consider cases where LaTeX does not support footnotes
+ (inside tables__, headings__, caption, ...).
+ Use ftnxtra_, tabularx_, tabulary_, longtable_?
- (packages that should be in a "reasonably sized and reasonably modern
- LaTeX installation like the `texlive-latex-recommended` Debian package,
- say):
+ __ http://www.tex.ac.uk/cgi-bin/texfaq2html?label=footintab
+ __ http://www.tex.ac.uk/cgi-bin/texfaq2html?label=ftnsect
- + No "fancy" or "exotic" requirements.
+ - Consider `multiple footnote refs to common footnote text`__.
- + pointers to advanced packages and their use in the `latex writer
- documentation`_.
+ KOMA-script classes and the KOMA scrextend_ package provide
+ ``\footref`` that can be used for additional references to a
+ ``\label``-ed footnote. Since 2021-05-01, ``\footref`` is provided
+ by the LaTeX core, too.
-* footnotes
+ __ http://www.tex.ac.uk/cgi-bin/texfaq2html?label=multfoot
- + True footnotes with LaTeX auto-numbering (as option ``--latex-footnotes``)
- (also for target-footnotes):
+ - Consider numbered vs. symbolic footnotes.
- - attach footnote text to footnote-symobol node
- - write \footnote{<footnote text>}
- - consider cases where LaTeX does not support footnotes
- (inside tables, headings, ...)?
- - consider multiple footnote refs to common footnote text.
++ document customization (links to how-to and packages)
- .. Quote:
+.. Footnote packages at CTAN (www.ctan.org/pkg/<packagename>):
- If the symbol you want is not one of the ones listed, you'll need to
- redefine ``\@fnsymbol`` and add it, e.g. perhaps like::
+ :footnote: provides a "savenotes" environment which collects all
+ footnotes and emits them at ``end{savenotes}``
+ (texlive-latex-recommended)
- \def\@fnsymbol#1{\ifcase#1\hbox{}\or *\or \dagger\or \ddagger\or
- \mathchar "278\or \mathchar "27B\or \|\or **\or \dagger\dagger \or
- \ddagger\ddagger \or \mathchar"27C \else\@ctrerr\fi\relax}
+ :ftnxtra_: fixes the issue of footnote inside \caption{},
+ tabular environment and \section{} like commands.
- which would allow \symbolfootnote[10]{footnote} to have a club as its
- mark.
+ :footnotebackref_: bidirectional links to/from footnote mark to
+ footnote text.
- + document customization (links to how-to and packages):
+.. Footnote Discussion:
- .. Footnote packages:
+ `German tutorial
+ <http://www2.informatik.hu-berlin.de/~ahamann/studies/footnotes.pdf>`__
- :footnote: texlive-latex-recommended % savenotes environment
- :footmisc: texlive-latex-extra % formatting options
- :manyfoot: texlive-latex-extra
- :bigfoot: texlive-latex-extra
- :perpage: texlive-latex-extra
- :ftnxtra: new on CTAN
- fixes the issue of footnote inside \caption{},
- tabular environment and \section{} like commands.
+ `wikibooks: footnote workarounds
+ <https://en.wikibooks.org/wiki/LaTeX/Footnotes_and_Margin_Notes#Common_problems_and_workarounds>`__
+.. _footnotebackref: https://www.ctan.org/pkg/footnotebackref
+.. _ftnxtra: https://www.ctan.org/pkg/ftnxtra
+.. _hyperref: https://www.ctan.org/pkg/hyperref
+.. _longtable: https://www.ctan.org/pkg/longtable
+.. _scrextend: https://www.ctan.org/pkg/longtable
+.. _tabularx: https://www.ctan.org/pkg/tabularx
- German tutorial:
- http://www2.informatik.hu-berlin.de/~ahamann/studies/footnotes.pdf
- .. Footnote FAQs:
+Other LaTeX constructs and packages instead of re-implementations
+`````````````````````````````````````````````````````````````````
- `Footnotes whose texts are identical
- <http://www.tex.ac.uk/cgi-bin/texfaq2html?label=repfootnote>`__
+* Check the generated source with package `nag`.
- * label per hand or use footmisc
+* enumitem_ (texlive-latex-extra) for field-lists?
- `More than one sequence of footnotes
- <http://www.tex.ac.uk/cgi-bin/texfaq2html?label=multfoot>`__
+.. _enumitem: https://www.ctan.org/pkg/enumitem
- * manyfoot, bigfoot
-
- `Footnotes in tables
- <http://www.tex.ac.uk/cgi-bin/texfaq2html?label=footintab>`__
-
- * `tabularx` and longtable allow footnotes.
- * `footnote` provides a "savenotes" environment which collects all
- footnotes and emits them at ``end{savenotes}``
-
- `Footnotes in LaTeX section headings
- <http://www.tex.ac.uk/cgi-bin/texfaq2html?label=ftnsect>`__
-
- * Take advantage of the fact that the mandatory argument doesn't
- move if the optional argument is present::
-
- \section[title] {title\footnote{title ftnt}}
-
- * Use the footmisc package, with package option stable - this modifies
- footnotes so that they softly and silently vanish away if used in a
- moving argument.
-
- * Use ftnxtra.
-
- `Footnotes numbered per page
- <http://www.tex.ac.uk/cgi-bin/texfaq2html?label=footnpp>`__
-
- * perpage provides a general mechanism for resetting counters per page
- * footmisc provides a package option perpage
-
-* use `eqlist` or `enumitem` (texlive-latex-extra) for field-lists?
-
-* ``--use-latex-when-possible`` »super option« that would set the
- following::
-
- --no-section-numbering
- --use-latex-toc
- --use-latex-docinfo
- --use-latex-abstract
- --use-latex-footnotes
- --use-latex-citations
-
- ? (My preference is to default to use-latex-* whenever possible [GM])
-
-
Default layout
--------------
@@ -2624,12 +2592,8 @@
- \\ % subtitle%
+ \\[0.5em] % subtitle%
-.. _PSNFSS documentation:
- http://mirror.ctan.org/macros/latex/required/psnfss/psnfss2e.pdf
.. _compound paragraph:
../ref/rst/directives.html#compound-paragraph
-.. _fixltx2e:
- http://mirror.ctan.org/help/Catalogue/entries/fixltx2e.html
Tables
``````
@@ -2642,8 +2606,7 @@
+ use tabularx column type ``X`` and let LaTeX decide width, or
+ use tabulary_?
- .. _tabulary:
- http://tug.ctan.org/cgi-bin/ctanPackageInformation.py?id=tabulary
+ .. _tabulary: https://www.ctan.org/pkg/tabulary
* From comp.text.tex (13. 4. 2011):
@@ -2751,23 +2714,7 @@
.. _bibstuff: http://code.google.com/p/bibstuff/
-Allow choice between utf8 (standard) and utf8x (extended) encodings
-```````````````````````````````````````````````````````````````````
-* Allow the user to select *utf8* or *utf8x* LaTeX encoding. (Docutil's
- output encoding becomes LaTeX's input encoding.)
-
-The `ucs` package provides extended support for UTF-8 encoding in LaTeX
-via the `inputenc`-option ``utf8x``. It is, however, a non-standard
-extension and no longer developed.
-
-Ideas:
- a) Python has 4 names for the UTF-8 encoding (``utf_8, U8, UTF, utf8``)
- give a special meaning to one of the aliases,
-
- b) scan "stylesheets" and "latex-preamble" options and use ``utf8x``
- if it contains ``ucs``
-
XeTeX writer
````````````
Modified: trunk/docutils/docutils/writers/latex2e/__init__.py
===================================================================
--- trunk/docutils/docutils/writers/latex2e/__init__.py 2021-06-25 20:59:26 UTC (rev 8780)
+++ trunk/docutils/docutils/writers/latex2e/__init__.py 2021-06-26 22:17:04 UTC (rev 8781)
@@ -2257,15 +2257,14 @@
elif 'refname' in node:
href = self.document.nameids[node['refname']]
# if not self.docutils_footnotes:
- # TODO: insert footnote content at (or near) this place
- # print("footnote-ref to", node['refid'])
- # footnotes = (self.document.footnotes +
- # self.document.autofootnotes +
- # self.document.symbol_footnotes)
- # for footnote in footnotes:
- # # print(footnote['ids'])
- # if node.get('refid', '') in footnote['ids']:
- # print('matches', footnote['ids'])
+ # # TODO: insert footnote content at (or near) this place
+ # # see also docs/dev/todo.txt
+ # try:
+ # referenced_node = self.document.ids[node['refid']]
+ # except (AttributeError, KeyError):
+ # self.document.reporter.error(
+ # 'unresolved footnote-reference %s' % node)
+ # print('footnote-ref to %s' % referenced_node)
format = self.settings.footnote_references
if format == 'brackets':
self.append_hypertargets(node)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2021-06-30 07:47:33
|
Revision: 8782
http://sourceforge.net/p/docutils/code/8782
Author: milde
Date: 2021-06-30 07:47:30 +0000 (Wed, 30 Jun 2021)
Log Message:
-----------
Do not use deprecated "rawsource" argument when creating node.Text instances.
The "rawsource" argument of ``nodes.Text.__init__`` is ignored and deprecated.
Fix the documentation of nodes.Text.__new__().
Modified Paths:
--------------
trunk/docutils/docutils/nodes.py
trunk/docutils/docutils/parsers/rst/roles.py
trunk/docutils/docutils/parsers/rst/states.py
trunk/docutils/docutils/transforms/frontmatter.py
trunk/docutils/docutils/transforms/universal.py
trunk/docutils/test/test_nodes.py
Modified: trunk/docutils/docutils/nodes.py
===================================================================
--- trunk/docutils/docutils/nodes.py 2021-06-26 22:17:04 UTC (rev 8781)
+++ trunk/docutils/docutils/nodes.py 2021-06-30 07:47:30 UTC (rev 8782)
@@ -381,18 +381,16 @@
if sys.version_info > (3, 0):
def __new__(cls, data, rawsource=None):
- """Prevent the rawsource argument from propagating to str."""
+ """Assert that `data` is not an array of bytes."""
if isinstance(data, bytes):
raise TypeError('expecting str data, not bytes')
return reprunicode.__new__(cls, data)
else:
def __new__(cls, data, rawsource=None):
- """Prevent the rawsource argument from propagating to str."""
return reprunicode.__new__(cls, data)
- def __init__(self, data, rawsource=''):
- self.rawsource = rawsource
- """The raw text from which this element was constructed."""
+ def __init__(self, data, rawsource=None):
+ """The `rawsource` argument is ignored and deprecated."""
def shortrepr(self, maxlen=18):
data = self
@@ -419,7 +417,7 @@
# an infinite loop
def copy(self):
- return self.__class__(reprunicode(self), rawsource=self.rawsource)
+ return self.__class__(reprunicode(self))
def deepcopy(self):
return self.copy()
@@ -444,10 +442,10 @@
# taken care of by UserString.
def rstrip(self, chars=None):
- return self.__class__(reprunicode.rstrip(self, chars), self.rawsource)
+ return self.__class__(reprunicode.rstrip(self, chars))
def lstrip(self, chars=None):
- return self.__class__(reprunicode.lstrip(self, chars), self.rawsource)
+ return self.__class__(reprunicode.lstrip(self, chars))
class Element(Node):
Modified: trunk/docutils/docutils/parsers/rst/roles.py
===================================================================
--- trunk/docutils/docutils/parsers/rst/roles.py 2021-06-26 22:17:04 UTC (rev 8781)
+++ trunk/docutils/docutils/parsers/rst/roles.py 2021-06-30 07:47:30 UTC (rev 8782)
@@ -346,7 +346,7 @@
node += nodes.inline(value, value, classes=classes)
else:
# insert as Text to decrease the verbosity of the output
- node += nodes.Text(value, value)
+ node += nodes.Text(value)
return [node], []
Modified: trunk/docutils/docutils/parsers/rst/states.py
===================================================================
--- trunk/docutils/docutils/parsers/rst/states.py 2021-06-26 22:17:04 UTC (rev 8781)
+++ trunk/docutils/docutils/parsers/rst/states.py 2021-06-30 07:47:30 UTC (rev 8782)
@@ -1043,7 +1043,7 @@
self.implicit_inline(text[match.end():], lineno))
except MarkupMismatch:
pass
- return [nodes.Text(text, unescape(text, True))]
+ return [nodes.Text(text)]
dispatch = {'*': emphasis,
'**': strong,
Modified: trunk/docutils/docutils/transforms/frontmatter.py
===================================================================
--- trunk/docutils/docutils/transforms/frontmatter.py 2021-06-26 22:17:04 UTC (rev 8781)
+++ trunk/docutils/docutils/transforms/frontmatter.py 2021-06-30 07:47:30 UTC (rev 8782)
@@ -523,8 +523,7 @@
if len(authornames) > 1:
break
authornames = (name.strip() for name in authornames)
- authors = [[nodes.Text(name, utils.unescape(name, True))]
- for name in authornames if name]
+ authors = [[nodes.Text(name)] for name in authornames if name]
return authors
def authors_from_bullet_list(self, field):
Modified: trunk/docutils/docutils/transforms/universal.py
===================================================================
--- trunk/docutils/docutils/transforms/universal.py 2021-06-26 22:17:04 UTC (rev 8781)
+++ trunk/docutils/docutils/transforms/universal.py 2021-06-30 07:47:30 UTC (rev 8782)
@@ -321,7 +321,6 @@
attr=self.smartquotes_action, language=lang)
for txtnode, newtext in zip(txtnodes, teacher):
- txtnode.parent.replace(txtnode, nodes.Text(newtext,
- rawsource=txtnode.rawsource))
+ txtnode.parent.replace(txtnode, nodes.Text(newtext))
self.unsupported_languages = set() # reset
Modified: trunk/docutils/test/test_nodes.py
===================================================================
--- trunk/docutils/test/test_nodes.py 2021-06-26 22:17:04 UTC (rev 8781)
+++ trunk/docutils/test/test_nodes.py 2021-06-30 07:47:30 UTC (rev 8782)
@@ -58,7 +58,7 @@
self.assertEqual(self.text.pformat(), u'Line 1.\nLine 2.\n')
def test_strip(self):
- text = nodes.Text(' was noch ', r' \was\ noch \\ ')
+ text = nodes.Text(' was noch ')
stripped = text.lstrip().rstrip()
stripped2 = text.lstrip(' wahn').rstrip(' wahn')
self.assertEqual(stripped, u'was noch')
@@ -330,7 +330,7 @@
self.assertEqual(len(parent), 5)
def test_unicode(self):
- node = nodes.Element(u'Möhren', nodes.Text(u'Möhren', u'Möhren'))
+ node = nodes.Element(u'Möhren', nodes.Text(u'Möhren'))
self.assertEqual(unicode(node), u'<Element>Möhren</Element>')
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|