|
From: <mi...@us...> - 2023-11-13 18:30:04
|
Revision: 9473
http://sourceforge.net/p/docutils/code/9473
Author: milde
Date: 2023-11-13 18:29:27 +0000 (Mon, 13 Nov 2023)
Log Message:
-----------
Fix option_marker parsing (bugs:#474).
Don't split at `", "` inside angle brackets.
Modified Paths:
--------------
trunk/docutils/HISTORY.txt
trunk/docutils/docs/ref/rst/restructuredtext.txt
trunk/docutils/docutils/parsers/rst/states.py
trunk/docutils/test/functional/expected/latex_memoir.tex
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/functional/expected/standalone_rst_xetex.tex
trunk/docutils/test/functional/input/data/standard.txt
trunk/docutils/test/test_parsers/test_rst/test_option_lists.py
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2023-11-10 13:17:34 UTC (rev 9472)
+++ trunk/docutils/HISTORY.txt 2023-11-13 18:29:27 UTC (rev 9473)
@@ -62,6 +62,10 @@
- Move `parsers.rst.directives.Table.process_header_option()` to
`parsers.rst.directives.CSVTable`.
+* docutils/parsers/rst/states.py
+
+ - Don't split inside "< >" when parsing "option groups" (fixes bug #474).
+
* docutils/utils/roman.py
- Update to version `1.4 <https://pypi.org/project/roman/4.1/>`__.
@@ -207,8 +211,8 @@
* docutils/writers/html5_polyglot/__init__.py
- - Do not use HTML5 text-level tags inside <code> and <code-block>
- (fixes bug #476).
+ - Do not convert class values to HTML5 text-level tags inside
+ <code> and <code-block> (fixes bug #476).
* docutils/writers/latex2e/__init__.py
Modified: trunk/docutils/docs/ref/rst/restructuredtext.txt
===================================================================
--- trunk/docutils/docs/ref/rst/restructuredtext.txt 2023-11-10 13:17:34 UTC (rev 9472)
+++ trunk/docutils/docs/ref/rst/restructuredtext.txt 2023-11-13 18:29:27 UTC (rev 9473)
@@ -1040,19 +1040,19 @@
documenting them. For example::
-a Output all.
- -b Output both (this description is
- quite long).
-c arg Output just arg.
--long Output all day long.
+ /V A VMS/DOS-style option.
-p This option has two paragraphs in the description.
This is the first.
- This is the second. Blank lines may be omitted between
- options (as above) or left in (as here and below).
+ This is the second.
+ Blank lines may be omitted between options
+ (as above) or left in (as here and below).
- --very-long-option A VMS-style option. Note the adjustment for
- the required two spaces.
+ --very-long-option A VMS-style option. Note the adjustment
+ for the required two spaces.
--an-even-longer-option
The description can also start on the next line.
@@ -1062,8 +1062,12 @@
-f FILE, --file=FILE These two options are synonyms; both have
arguments.
- /V A VMS/DOS-style option.
+ -f <[path]file> Option argument placeholders must start with
+ a letter or be wrapped in angle brackets.
+ -d <src dest> Angle brackets are also required if an option
+ expects more than one argument.
+
There are several types of options recognized by reStructuredText:
- Short POSIX options consist of one dash and an option letter.
Modified: trunk/docutils/docutils/parsers/rst/states.py
===================================================================
--- trunk/docutils/docutils/parsers/rst/states.py 2023-11-10 13:17:34 UTC (rev 9472)
+++ trunk/docutils/docutils/parsers/rst/states.py 2023-11-13 18:29:27 UTC (rev 9473)
@@ -1552,7 +1552,8 @@
:Exception: `MarkupError` for invalid option markers.
"""
optlist = []
- optionstrings = match.group().rstrip().split(', ')
+ # split at ", ", except inside < > (complex arguments)
+ optionstrings = re.split(r', (?![^<]*>)', match.group().rstrip())
for optionstring in optionstrings:
tokens = optionstring.split()
delimiter = ' '
Modified: trunk/docutils/test/functional/expected/latex_memoir.tex
===================================================================
--- trunk/docutils/test/functional/expected/latex_memoir.tex 2023-11-10 13:17:34 UTC (rev 9472)
+++ trunk/docutils/test/functional/expected/latex_memoir.tex 2023-11-13 18:29:27 UTC (rev 9473)
@@ -511,11 +511,12 @@
\item[-b file] options can have arguments
and long descriptions
-\item[-{}-long] options can be long also
+\item[-{}-long] options can be long, too
-\item[-{}-input=file] long options can also have
-arguments
+\item[-{}-input=file] long options can also have arguments
+\item[/V] DOS/VMS-style option
+
\item[-{}-very-long-option] The description can also start on the next line.
The description may contain multiple body elements,
@@ -527,7 +528,11 @@
\item[-1 file, -{}-one=file, -{}-two file] Multiple options with arguments.
-\item[/V] DOS/VMS-style options too
+\item[-f <{[}path{]}file>] Option argumens must start with a letter
+or be wrapped in angle brackets.
+
+\item[-d <src dest>] Angle brackets are also required if an
+option expects more than one argument.
\end{DUoptionlist}
There must be at least two spaces between the option and the
@@ -2087,7 +2092,7 @@
\DUtitle[system-message]{system-message
\raisebox{1em}{\hypertarget{system-message-2}{}}}
-{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~387
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~390
\hyperlink{footnote-reference-8}{
Unknown target name: \textquotedbl{}5\textquotedbl{}.
@@ -2097,7 +2102,7 @@
\DUtitle[system-message]{system-message
\raisebox{1em}{\hypertarget{system-message-3}{}}}
-{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~396
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~399
\hyperlink{citation-reference-3}{
Unknown target name: \textquotedbl{}nonexistent\textquotedbl{}.
@@ -2107,7 +2112,7 @@
\DUtitle[system-message]{system-message
\raisebox{1em}{\hypertarget{system-message-4}{}}}
-{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~423
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~426
\hyperlink{problematic-2}{
Unknown target name: \textquotedbl{}hyperlink reference without a target\textquotedbl{}.
@@ -2117,7 +2122,7 @@
\DUtitle[system-message]{system-message
\raisebox{1em}{\hypertarget{system-message-5}{}}}
-{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~436
+{\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~439
\hyperlink{problematic-3}{
Duplicate target name, cannot be used as a unique reference: \textquotedbl{}duplicate target names\textquotedbl{}.
Modified: trunk/docutils/test/functional/expected/standalone_rst_docutils_xml.xml
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_docutils_xml.xml 2023-11-10 13:17:34 UTC (rev 9472)
+++ trunk/docutils/test/functional/expected/standalone_rst_docutils_xml.xml 2023-11-13 18:29:27 UTC (rev 9473)
@@ -474,7 +474,7 @@
</option>
</option_group>
<description>
- <paragraph>options can be long also</paragraph>
+ <paragraph>options can be long, too</paragraph>
</description>
</option_list_item>
<option_list_item>
@@ -485,13 +485,22 @@
</option>
</option_group>
<description>
- <paragraph>long options can also have
- arguments</paragraph>
+ <paragraph>long options can also have arguments</paragraph>
</description>
</option_list_item>
<option_list_item>
<option_group>
<option>
+ <option_string>/V</option_string>
+ </option>
+ </option_group>
+ <description>
+ <paragraph>DOS/VMS-style option</paragraph>
+ </description>
+ </option_list_item>
+ <option_list_item>
+ <option_group>
+ <option>
<option_string>--very-long-option</option_string>
</option>
</option_group>
@@ -552,13 +561,27 @@
<option_list_item>
<option_group>
<option>
- <option_string>/V</option_string>
+ <option_string>-f</option_string>
+ <option_argument delimiter=" "><[path]file></option_argument>
</option>
</option_group>
<description>
- <paragraph>DOS/VMS-style options too</paragraph>
+ <paragraph>Option argumens must start with a letter
+ or be wrapped in angle brackets.</paragraph>
</description>
</option_list_item>
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>-d</option_string>
+ <option_argument delimiter=" "><src dest></option_argument>
+ </option>
+ </option_group>
+ <description>
+ <paragraph>Angle brackets are also required if an
+ option expects more than one argument.</paragraph>
+ </description>
+ </option_list_item>
</option_list>
<paragraph>There must be at least two spaces between the option and the
description.</paragraph>
@@ -749,7 +772,7 @@
</section>
<section dupnames="duplicate\ target\ names" ids="duplicate-target-names-1">
<title auto="1" refid="toc-entry-21"><generated classes="sectnum">2.13.2 </generated>Duplicate Target Names</title>
- <system_message backrefs="duplicate-target-names-1" level="1" line="434" source="functional/input/data/standard.txt" type="INFO">
+ <system_message backrefs="duplicate-target-names-1" level="1" line="437" source="functional/input/data/standard.txt" type="INFO">
<paragraph>Duplicate implicit target name: "duplicate target names".</paragraph>
</system_message>
<paragraph>Since there are two "Duplicate Target Names" section headers, we
@@ -1744,43 +1767,43 @@
<system_message backrefs="problematic-1" ids="system-message-1" level="3" line="99" source="functional/input/data/standard.txt" type="ERROR">
<paragraph>Undefined substitution referenced: "problematic".</paragraph>
</system_message>
- <system_message backrefs="footnote-reference-8" ids="system-message-2" level="3" line="387" source="functional/input/data/standard.txt" type="ERROR">
+ <system_message backrefs="footnote-reference-8" ids="system-message-2" level="3" line="390" source="functional/input/data/standard.txt" type="ERROR">
<paragraph>Unknown target name: "5".</paragraph>
</system_message>
- <system_message backrefs="citation-reference-3" ids="system-message-3" level="3" line="396" source="functional/input/data/standard.txt" type="ERROR">
+ <system_message backrefs="citation-reference-3" ids="system-message-3" level="3" line="399" source="functional/input/data/standard.txt" type="ERROR">
<paragraph>Unknown target name: "nonexistent".</paragraph>
</system_message>
- <system_message backrefs="problematic-2" ids="system-message-4" level="3" line="423" source="functional/input/data/standard.txt" type="ERROR">
+ <system_message backrefs="problematic-2" ids="system-message-4" level="3" line="426" source="functional/input/data/standard.txt" type="ERROR">
<paragraph>Unknown target name: "hyperlink reference without a target".</paragraph>
</system_message>
- <system_message backrefs="problematic-3" ids="system-message-5" level="3" line="436" source="functional/input/data/standard.txt" type="ERROR">
+ <system_message backrefs="problematic-3" ids="system-message-5" level="3" line="439" source="functional/input/data/standard.txt" type="ERROR">
<paragraph>Duplicate target name, cannot be used as a unique reference: "duplicate target names".</paragraph>
</system_message>
<system_message level="1" line="159" source="functional/input/data/standard.txt" type="INFO">
<paragraph>Hyperlink target "target" is not referenced.</paragraph>
</system_message>
- <system_message level="1" line="401" source="functional/input/data/standard.txt" type="INFO">
+ <system_message level="1" line="404" source="functional/input/data/standard.txt" type="INFO">
<paragraph>Hyperlink target "another-target" is not referenced.</paragraph>
</system_message>
- <system_message level="1" line="471" source="functional/input/data/standard.txt" type="INFO">
+ <system_message level="1" line="474" source="functional/input/data/standard.txt" type="INFO">
<paragraph>Hyperlink target "image-target-1" is not referenced.</paragraph>
</system_message>
- <system_message level="1" line="472" source="functional/input/data/standard.txt" type="INFO">
+ <system_message level="1" line="475" source="functional/input/data/standard.txt" type="INFO">
<paragraph>Hyperlink target "image-target-2" is not referenced.</paragraph>
</system_message>
- <system_message level="1" line="473" source="functional/input/data/standard.txt" type="INFO">
+ <system_message level="1" line="476" source="functional/input/data/standard.txt" type="INFO">
<paragraph>Hyperlink target "image-target-3" is not referenced.</paragraph>
</system_message>
- <system_message level="1" line="636" source="functional/input/data/standard.txt" type="INFO">
+ <system_message level="1" line="639" source="functional/input/data/standard.txt" type="INFO">
<paragraph>Hyperlink target "target1" is not referenced.</paragraph>
</system_message>
- <system_message level="1" line="637" source="functional/input/data/standard.txt" type="INFO">
+ <system_message level="1" line="640" source="functional/input/data/standard.txt" type="INFO">
<paragraph>Hyperlink target "target2" is not referenced.</paragraph>
</system_message>
- <system_message level="1" line="682" source="functional/input/data/standard.txt" type="INFO">
+ <system_message level="1" line="685" source="functional/input/data/standard.txt" type="INFO">
<paragraph>Hyperlink target "docutils" is not referenced.</paragraph>
</system_message>
- <system_message level="1" line="848" source="functional/input/data/standard.txt" type="INFO">
+ <system_message level="1" line="851" source="functional/input/data/standard.txt" type="INFO">
<paragraph>Hyperlink target "hyperlink targets" is not referenced.</paragraph>
</system_message>
</section>
Modified: trunk/docutils/test/functional/expected/standalone_rst_html4css1.html
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_html4css1.html 2023-11-10 13:17:34 UTC (rev 9472)
+++ trunk/docutils/test/functional/expected/standalone_rst_html4css1.html 2023-11-13 18:29:27 UTC (rev 9473)
@@ -314,11 +314,13 @@
and long descriptions</td></tr>
<tr><td class="option-group">
<kbd><span class="option">--long</span></kbd></td>
-<td>options can be long also</td></tr>
+<td>options can be long, too</td></tr>
<tr><td class="option-group">
<kbd><span class="option">--input=<var>file</var></span></kbd></td>
-<td>long options can also have
-arguments</td></tr>
+<td>long options can also have arguments</td></tr>
+<tr><td class="option-group">
+<kbd><span class="option">/V</span></kbd></td>
+<td>DOS/VMS-style option</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">--very-long-option</span></kbd></td>
</tr>
@@ -336,9 +338,15 @@
<kbd><span class="option">-1 <var>file</var></span>, <span class="option">--one=<var>file</var></span>, <span class="option">--two <var>file</var></span></kbd></td>
</tr>
<tr><td> </td><td>Multiple options with arguments.</td></tr>
+<tr><td class="option-group" colspan="2">
+<kbd><span class="option">-f <var><[path]file></var></span></kbd></td>
+</tr>
+<tr><td> </td><td>Option argumens must start with a letter
+or be wrapped in angle brackets.</td></tr>
<tr><td class="option-group">
-<kbd><span class="option">/V</span></kbd></td>
-<td>DOS/VMS-style options too</td></tr>
+<kbd><span class="option">-d <var><src dest></var></span></kbd></td>
+<td>Angle brackets are also required if an
+option expects more than one argument.</td></tr>
</tbody>
</table>
<p>There must be at least two spaces between the option and the
@@ -1348,16 +1356,16 @@
<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">functional/input/data/standard.txt</tt>, line 99); <em><a href="#problematic-1">backlink</a></em></p>
Undefined substitution referenced: "problematic".</div>
<div class="system-message" id="system-message-2">
-<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">functional/input/data/standard.txt</tt>, line 387); <em><a href="#footnote-reference-8">backlink</a></em></p>
+<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">functional/input/data/standard.txt</tt>, line 390); <em><a href="#footnote-reference-8">backlink</a></em></p>
Unknown target name: "5".</div>
<div class="system-message" id="system-message-3">
-<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">functional/input/data/standard.txt</tt>, line 396); <em><a href="#citation-reference-3">backlink</a></em></p>
+<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">functional/input/data/standard.txt</tt>, line 399); <em><a href="#citation-reference-3">backlink</a></em></p>
Unknown target name: "nonexistent".</div>
<div class="system-message" id="system-message-4">
-<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">functional/input/data/standard.txt</tt>, line 423); <em><a href="#problematic-2">backlink</a></em></p>
+<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">functional/input/data/standard.txt</tt>, line 426); <em><a href="#problematic-2">backlink</a></em></p>
Unknown target name: "hyperlink reference without a target".</div>
<div class="system-message" id="system-message-5">
-<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">functional/input/data/standard.txt</tt>, line 436); <em><a href="#problematic-3">backlink</a></em></p>
+<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">functional/input/data/standard.txt</tt>, line 439); <em><a href="#problematic-3">backlink</a></em></p>
Duplicate target name, cannot be used as a unique reference: "duplicate target names".</div>
</div>
</div>
Modified: trunk/docutils/test/functional/expected/standalone_rst_html5.html
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_html5.html 2023-11-10 13:17:34 UTC (rev 9472)
+++ trunk/docutils/test/functional/expected/standalone_rst_html5.html 2023-11-13 18:29:27 UTC (rev 9473)
@@ -329,12 +329,14 @@
and long descriptions</p>
</dd>
<dt><kbd><span class="option">--long</span></kbd></dt>
-<dd><p>options can be long also</p>
+<dd><p>options can be long, too</p>
</dd>
<dt><kbd><span class="option">--input=<var>file</var></span></kbd></dt>
-<dd><p>long options can also have
-arguments</p>
+<dd><p>long options can also have arguments</p>
</dd>
+<dt><kbd><span class="option">/V</span></kbd></dt>
+<dd><p>DOS/VMS-style option</p>
+</dd>
<dt><kbd><span class="option">--very-long-option</span></kbd></dt>
<dd><p>The description can also start on the next line.</p>
<p>The description may contain multiple body elements,
@@ -349,9 +351,14 @@
<dt><kbd><span class="option">-1 <var>file</var></span>, <span class="option">--one=<var>file</var></span>, <span class="option">--two <var>file</var></span></kbd></dt>
<dd><p>Multiple options with arguments.</p>
</dd>
-<dt><kbd><span class="option">/V</span></kbd></dt>
-<dd><p>DOS/VMS-style options too</p>
+<dt><kbd><span class="option">-f <var><[path]file></var></span></kbd></dt>
+<dd><p>Option argumens must start with a letter
+or be wrapped in angle brackets.</p>
</dd>
+<dt><kbd><span class="option">-d <var><src dest></var></span></kbd></dt>
+<dd><p>Angle brackets are also required if an
+option expects more than one argument.</p>
+</dd>
</dl>
<p>There must be at least two spaces between the option and the
description.</p>
@@ -1912,19 +1919,19 @@
<p>Undefined substitution referenced: "problematic".</p>
</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 class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">functional/input/data/standard.txt</span>, line 390); <em><a href="#footnote-reference-8">backlink</a></em></p>
<p>Unknown target name: "5".</p>
</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 class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">functional/input/data/standard.txt</span>, line 399); <em><a href="#citation-reference-3">backlink</a></em></p>
<p>Unknown target name: "nonexistent".</p>
</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 class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">functional/input/data/standard.txt</span>, line 426); <em><a href="#problematic-2">backlink</a></em></p>
<p>Unknown target name: "hyperlink reference without a target".</p>
</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 class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">functional/input/data/standard.txt</span>, line 439); <em><a href="#problematic-3">backlink</a></em></p>
<p>Duplicate target name, cannot be used as a unique reference: "duplicate target names".</p>
</aside>
</section>
Modified: trunk/docutils/test/functional/expected/standalone_rst_pseudoxml.txt
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_pseudoxml.txt 2023-11-10 13:17:34 UTC (rev 9472)
+++ trunk/docutils/test/functional/expected/standalone_rst_pseudoxml.txt 2023-11-13 18:29:27 UTC (rev 9473)
@@ -765,7 +765,7 @@
--long
<description>
<paragraph>
- options can be long also
+ options can be long, too
<option_list_item>
<option_group>
<option>
@@ -775,12 +775,19 @@
file
<description>
<paragraph>
- long options can also have
- arguments
+ long options can also have arguments
<option_list_item>
<option_group>
<option>
<option_string>
+ /V
+ <description>
+ <paragraph>
+ DOS/VMS-style option
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
--very-long-option
<description>
<paragraph>
@@ -837,10 +844,24 @@
<option_group>
<option>
<option_string>
- /V
+ -f
+ <option_argument delimiter=" ">
+ <[path]file>
<description>
<paragraph>
- DOS/VMS-style options too
+ Option argumens must start with a letter
+ or be wrapped in angle brackets.
+ <option_list_item>
+ <option_group>
+ <option>
+ <option_string>
+ -d
+ <option_argument delimiter=" ">
+ <src dest>
+ <description>
+ <paragraph>
+ Angle brackets are also required if an
+ option expects more than one argument.
<paragraph>
There must be at least two spaces between the option and the
description.
@@ -1152,7 +1173,7 @@
<generated classes="sectnum">
2.13.2
Duplicate Target Names
- <system_message backrefs="duplicate-target-names-1" level="1" line="434" source="functional/input/data/standard.txt" type="INFO">
+ <system_message backrefs="duplicate-target-names-1" level="1" line="437" source="functional/input/data/standard.txt" type="INFO">
<paragraph>
Duplicate implicit target name: "duplicate target names".
<paragraph>
@@ -2377,42 +2398,42 @@
<system_message backrefs="problematic-1" ids="system-message-1" level="3" line="99" source="functional/input/data/standard.txt" type="ERROR">
<paragraph>
Undefined substitution referenced: "problematic".
- <system_message backrefs="footnote-reference-8" ids="system-message-2" level="3" line="387" source="functional/input/data/standard.txt" type="ERROR">
+ <system_message backrefs="footnote-reference-8" ids="system-message-2" level="3" line="390" source="functional/input/data/standard.txt" type="ERROR">
<paragraph>
Unknown target name: "5".
- <system_message backrefs="citation-reference-3" ids="system-message-3" level="3" line="396" source="functional/input/data/standard.txt" type="ERROR">
+ <system_message backrefs="citation-reference-3" ids="system-message-3" level="3" line="399" source="functional/input/data/standard.txt" type="ERROR">
<paragraph>
Unknown target name: "nonexistent".
- <system_message backrefs="problematic-2" ids="system-message-4" level="3" line="423" source="functional/input/data/standard.txt" type="ERROR">
+ <system_message backrefs="problematic-2" ids="system-message-4" level="3" line="426" source="functional/input/data/standard.txt" type="ERROR">
<paragraph>
Unknown target name: "hyperlink reference without a target".
- <system_message backrefs="problematic-3" ids="system-message-5" level="3" line="436" source="functional/input/data/standard.txt" type="ERROR">
+ <system_message backrefs="problematic-3" ids="system-message-5" level="3" line="439" source="functional/input/data/standard.txt" type="ERROR">
<paragraph>
Duplicate target name, cannot be used as a unique reference: "duplicate target names".
<system_message level="1" line="159" source="functional/input/data/standard.txt" type="INFO">
<paragraph>
Hyperlink target "target" is not referenced.
- <system_message level="1" line="401" source="functional/input/data/standard.txt" type="INFO">
+ <system_message level="1" line="404" source="functional/input/data/standard.txt" type="INFO">
<paragraph>
Hyperlink target "another-target" is not referenced.
- <system_message level="1" line="471" source="functional/input/data/standard.txt" type="INFO">
+ <system_message level="1" line="474" source="functional/input/data/standard.txt" type="INFO">
<paragraph>
Hy...
[truncated message content] |
|
From: <mi...@us...> - 2023-11-13 22:30:03
|
Revision: 9475
http://sourceforge.net/p/docutils/code/9475
Author: milde
Date: 2023-11-13 22:30:00 +0000 (Mon, 13 Nov 2023)
Log Message:
-----------
Add source and line info to `<admonition>` and `<definition_list>` nodes.
Based on [patch:#202] by Hood Chatham.
Modified Paths:
--------------
trunk/docutils/docutils/parsers/rst/directives/admonitions.py
trunk/docutils/docutils/parsers/rst/states.py
trunk/docutils/test/test_parsers/test_rst/includes/include14.txt
trunk/docutils/test/test_parsers/test_rst/test_source_line.py
Modified: trunk/docutils/docutils/parsers/rst/directives/admonitions.py
===================================================================
--- trunk/docutils/docutils/parsers/rst/directives/admonitions.py 2023-11-13 21:15:49 UTC (rev 9474)
+++ trunk/docutils/docutils/parsers/rst/directives/admonitions.py 2023-11-13 22:30:00 UTC (rev 9475)
@@ -31,6 +31,8 @@
text = '\n'.join(self.content)
admonition_node = self.node_class(text, **self.options)
self.add_name(admonition_node)
+ admonition_node.source, admonition_node.line = \
+ self.state_machine.get_source_and_line(self.lineno)
if self.node_class is nodes.admonition:
title_text = self.arguments[0]
textnodes, messages = self.state.inline_text(title_text,
Modified: trunk/docutils/docutils/parsers/rst/states.py
===================================================================
--- trunk/docutils/docutils/parsers/rst/states.py 2023-11-13 21:15:49 UTC (rev 9474)
+++ trunk/docutils/docutils/parsers/rst/states.py 2023-11-13 22:30:00 UTC (rev 9475)
@@ -2729,6 +2729,8 @@
def indent(self, match, context, next_state):
"""Definition list item."""
definitionlist = nodes.definition_list()
+ (definitionlist.src,
+ definitionlist.line) = self.state_machine.get_source_and_line()
definitionlistitem, blank_finish = self.definition_list_item(context)
definitionlist += definitionlistitem
self.parent += definitionlist
Modified: trunk/docutils/test/test_parsers/test_rst/includes/include14.txt
===================================================================
--- trunk/docutils/test/test_parsers/test_rst/includes/include14.txt 2023-11-13 21:15:49 UTC (rev 9474)
+++ trunk/docutils/test/test_parsers/test_rst/includes/include14.txt 2023-11-13 22:30:00 UTC (rev 9475)
@@ -10,3 +10,10 @@
* second item in line 10
1. enumerated list in line 12
+
+.. admonition:: line 14
+
+ Generic admonition text in line 16
+
+line 18
+ definition list item in line 19
Modified: trunk/docutils/test/test_parsers/test_rst/test_source_line.py
===================================================================
--- trunk/docutils/test/test_parsers/test_rst/test_source_line.py 2023-11-13 21:15:49 UTC (rev 9474)
+++ trunk/docutils/test/test_parsers/test_rst/test_source_line.py 2023-11-13 22:30:00 UTC (rev 9475)
@@ -43,6 +43,8 @@
class TransformTestCase(unittest.TestCase):
+ maxDiff = None
+
def test_transforms(self):
parser = Parser()
settings = get_default_settings(Parser)
@@ -167,11 +169,11 @@
<attribution internal:line="16" internal:source="test data">
attribution in line 16
"""],
-["""\
+[f"""\
Paragraph
-.. include:: %s
-""" % include14,
+.. include:: {include14}
+""",
f"""\
<document source="test data">
<paragraph internal:line="1" internal:source="test data">
@@ -199,6 +201,18 @@
<list_item internal:source="{include14}">
<paragraph internal:line="12" internal:source="{include14}">
enumerated list in line 12
+ <admonition classes="admonition-line-14" internal:line="14" internal:source="{include14}">
+ <title internal:line="14" internal:source="{include14}">
+ line 14
+ <paragraph internal:line="16" internal:source="{include14}">
+ Generic admonition text in line 16
+ <definition_list internal:line="19" internal:source="{include14}">
+ <definition_list_item internal:line="19" internal:source="{include14}">
+ <term internal:line="19" internal:source="{include14}">
+ line 18
+ <definition>
+ <paragraph internal:line="19" internal:source="{include14}">
+ definition list item in line 19
"""],
["""\
Paragraph
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2023-11-18 22:04:22
|
Revision: 9478
http://sourceforge.net/p/docutils/code/9478
Author: milde
Date: 2023-11-18 22:04:20 +0000 (Sat, 18 Nov 2023)
Log Message:
-----------
Various small documentation edits.
Format hyperlink targets,
more precise explanation of the "include" directive's `:tab-width:` option,
comments and explanations.
Modified Paths:
--------------
trunk/docutils/RELEASE-NOTES.txt
trunk/docutils/docs/ref/rst/directives.txt
trunk/docutils/docutils/writers/html5_polyglot/__init__.py
trunk/docutils/test/test_parsers/test_rst/test_directives/test_include.py
Modified: trunk/docutils/RELEASE-NOTES.txt
===================================================================
--- trunk/docutils/RELEASE-NOTES.txt 2023-11-18 21:48:30 UTC (rev 9477)
+++ trunk/docutils/RELEASE-NOTES.txt 2023-11-18 22:04:20 UTC (rev 9478)
@@ -188,8 +188,6 @@
configuration setting is None, '', 'utf-8-sig', 'utf-16', or 'utf-32'.
Do not remove other ZWNBSPs.
- .. _input encoding: docs/api/publisher.html#encodings
-
* "html5" writer:
Stop setting the "footnote-reference" class value for footnote references.
You can use the CSS selector ``[role="doc-noteref"]``
@@ -207,6 +205,7 @@
- File ``install.py``. See README.txt__ for alternatives.
+.. _input encoding: docs/api/publisher.html#encodings
.. _csv-table: docs/ref/rst/directives.html#csv-table
__ README.html#installation
@@ -244,8 +243,6 @@
are now ignored by the "xetex" writer.
Place common settings in section `[latex writers]`_.
- .. _[latex writers]: docs/user/config.html#latex-writers
-
- New command line setting output_. Obsoletes the ``<destination>``
positional argument (cf. `future changes`__).
@@ -264,8 +261,6 @@
- Removed. Use the coverage.py_ project instead,
``coverage run test/alltests.py`` and ``coverage report``.
- .. _coverage.py: https://pypi.org/project/coverage/
-
* tools/
- Moved ``quicktest.py`` to ``tools/dev/``.
@@ -272,7 +267,9 @@
* Bugfixes and improvements (see HISTORY_).
+.. _[latex writers]: docs/user/config.html#latex-writers
.. _output: docs/user/config.html#output
+.. _coverage.py: https://pypi.org/project/coverage/
Release 0.19 (2022-07-05)
@@ -293,9 +290,6 @@
* After package installation, the CLI commands ``python -m docutils`` and
``docutils`` start the `generic command line front end tool`_.
- .. _generic command line front end tool:
- docs/user/tools.html#generic-command-line-front-end
-
* Support parsing "Markdown" input with 3rd party parsers
myst_, pycmark_, or recommonmark_.
@@ -306,6 +300,8 @@
* Various bugfixes and improvements (see HISTORY_).
+.. _generic command line front end tool:
+ docs/user/tools.html#generic-command-line-front-end
.. _myst: https://pypi.org/project/myst-docutils
.. _pycmark: https://pypi.org/project/pycmark/
.. _recommonmark: https://pypi.org/project/recommonmark/
@@ -358,7 +354,6 @@
widths, if the `"widths" option`_ is set and not "auto".
The table-style__ setting "colwidths-grid" restores the current default.
- .. _"widths" option: __ docs/ref/rst/directives.html#table
__ docs/user/config.html#table-style
- Items of a definition list with class argument "details" are
@@ -394,6 +389,8 @@
* New standard Docutils doctree node: <meta__>.
+ __ docs/ref/doctree.html#meta
+
* New configuration settings:
- [latex writers] legacy_column_widths_ and
@@ -429,9 +426,9 @@
Fix spelling errors in documentation and docstrings.
Thanks to Dimitri Papadopoulos.
-__ docs/ref/doctree.html#meta
+.. _"widths" option: __ docs/ref/rst/directives.html#table
.. _identifier normalization:
- docs/ref/rst/directives.html#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
.. _details disclosure elements:
@@ -545,9 +542,6 @@
"html4" or "html5" (deprecated in favour of the `"writer" setting`_
in Docutils 0.18).
- .. _"writer" setting:
- docs/user/config.html#writer-buildhtml-application
-
* docutils/io.py
- Remove the `handle_io_errors` argument from io.FileInput/Output.
@@ -556,11 +550,12 @@
- If `auto_id_prefix`_ ends with "%", this is replaced with the tag name.
- .. _auto_id_prefix: docs/user/config.html#auto-id-prefix
-
* Various bugfixes and improvements (see HISTORY_).
+.. _"writer" setting: docs/user/config.html#writer-buildhtml-application
+.. _auto_id_prefix: docs/user/config.html#auto-id-prefix
+
Release 0.15 (2019-07-20)
=========================
@@ -641,8 +636,6 @@
- New HTML writer generating `HTML 5`_.
- .. _HTML 5: https://www.w3.org/TR/html5/
-
* tools/
- New front-end ``rst2html5.py``.
@@ -658,7 +651,9 @@
* rst.el: The problem with ``electric-indent-mode`` has been fixed.
+.. _HTML 5: https://www.w3.org/TR/html5/
+
Release 0.12 (2014-07-06)
=========================
@@ -695,8 +690,6 @@
- Avoid repeated class declarations in html4css1 writer
(modified version of patch [ 104 ]).
- .. _math-output: docs/user/config.html#math-output
-
* docutils/writers/latex2e/__init__.py
- Drop the simple algorithm replacing straight double quotes with
@@ -706,13 +699,15 @@
where stylesheets are found. Used by `stylesheet_path` when expanding
relative path arguments.
- .. _SmartQuotes: docs/user/config.html#smart-quotes
-
* docutils/writers/manpage.py
- Fix [3607063] handle lines starting with a period.
- Fix option separating comma was bold (thanks to Bill Morris).
+.. _math-output: docs/user/config.html#math-output
+.. _SmartQuotes: docs/user/config.html#smart-quotes
+
+
Release 0.10 (2012-12-16)
=========================
@@ -909,9 +904,9 @@
- Drop the special `output_encoding`__ default ("latin-1").
The Docutils wide default (usually "UTF-8") is used instead.
-__ docs/user/config.html#docutils-footnotes
-__ docs/user/latex.html#hyperlinks
-__ docs/user/latex.html#output-encoding
+ __ docs/user/config.html#docutils-footnotes
+ __ docs/user/latex.html#hyperlinks
+ __ docs/user/latex.html#output-encoding
* manpage writer:
@@ -951,9 +946,9 @@
(aligning the figure not its contents).
- Align images with class "align-[right|center|left]"
(allows setting the alignment of an image in a figure).
- - Hard tabs in literal inclusions are replaced by spaces. This is
- configurable via the new "tab-width" option of the "include" directive
- (a negative tab-width prevents tab expansion).
+ - Hard tabs **in literal inclusions** are replaced by spaces.
+ This is configurable via the new ``:tab-width:`` option of the
+ `"include" directive`_ (a negative tab-width prevents tab expansion).
* HTML writer:
@@ -993,7 +988,10 @@
- moved from sandbox to Doctutils core.
+.. _"include" directive:
+ docs/ref/rst/directives.html#including-an-external-document-fragment
+
Release 0.5 (2008-06-25)
========================
Modified: trunk/docutils/docs/ref/rst/directives.txt
===================================================================
--- trunk/docutils/docs/ref/rst/directives.txt 2023-11-18 21:48:30 UTC (rev 9477)
+++ trunk/docutils/docs/ref/rst/directives.txt 2023-11-18 22:04:20 UTC (rev 9478)
@@ -1512,8 +1512,9 @@
``tab-width`` : integer_
Number of spaces for hard tab expansion.
- A negative value prevents expansion of hard tabs. Defaults to the
- tab_width_ configuration setting.
+ Must be a positive integer, except for literal inclusions and code,
+ where a negative value prevents expansion of hard tabs.
+ Defaults to the tab_width_ configuration setting.
.. _tab_width: ../../user/config.html#tab-width
Modified: trunk/docutils/docutils/writers/html5_polyglot/__init__.py
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/__init__.py 2023-11-18 21:48:30 UTC (rev 9477)
+++ trunk/docutils/docutils/writers/html5_polyglot/__init__.py 2023-11-18 22:04:20 UTC (rev 9478)
@@ -284,11 +284,13 @@
def visit_inline(self, node):
classes = node['classes']
node.html5tagname = 'span'
+ # Special handling for "code" directive content
if (isinstance(node.parent, nodes.literal_block)
and 'code' in node.parent.get('classes')
or isinstance(node.parent, nodes.literal)
and getattr(node.parent, 'html5tagname', None) == 'code'):
if classes == ['ln']:
+ # line numbers are not part of the "fragment of computer code"
if self.body[-1] == '<code>':
del self.body[-1]
else:
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 2023-11-18 21:48:30 UTC (rev 9477)
+++ trunk/docutils/test/test_parsers/test_rst/test_directives/test_include.py 2023-11-18 22:04:20 UTC (rev 9478)
@@ -38,6 +38,8 @@
class ParserTestCase(unittest.TestCase):
+ maxDiff = None
+
def test_parser(self):
# eventually skip optional parts:
if not with_pygments:
@@ -1035,7 +1037,7 @@
:end-before: mork of ork
"""],
[f"""\
-TAB expansion with literal include:
+Default TAB expansion with literal include:
.. include:: {include_literal}
:literal:
@@ -1043,7 +1045,7 @@
f"""\
<document source="test data">
<paragraph>
- TAB expansion with literal include:
+ Default TAB expansion with literal include:
<literal_block source="{include_literal}" xml:space="preserve">
Literal included this should **not** be *marked* `up`.
<- leading raw tab.
@@ -1192,7 +1194,7 @@
.
"""],
[f"""\
-TAB expansion with included code:
+Default TAB expansion with included code:
.. include:: {include_literal}
:code: rst
@@ -1200,7 +1202,7 @@
f"""\
<document source="test data">
<paragraph>
- TAB expansion with included code:
+ Default TAB expansion with included code:
<literal_block classes="code rst" source="{include_literal}" xml:space="preserve">
Literal included this should \n\
<inline classes="generic strong">
@@ -1228,7 +1230,7 @@
""" if PYGMENTS_2_14_PLUS else f"""\
<document source="test data">
<paragraph>
- TAB expansion with included code:
+ Default TAB expansion with included code:
<literal_block classes="code rst" source="{include_literal}" xml:space="preserve">
Literal included this should \n\
<inline classes="generic strong">
@@ -1303,7 +1305,7 @@
normalized.
"""],
[f"""\
-Custom TAB expansion with included code:
+No TAB expansion with included code:
.. include:: {include_literal}
:code: rst
@@ -1312,7 +1314,7 @@
f"""\
<document source="test data">
<paragraph>
- Custom TAB expansion with included code:
+ No TAB expansion with included code:
<literal_block classes="code rst" source="{include_literal}" xml:space="preserve">
Literal included this should \n\
<inline classes="generic strong">
@@ -1340,7 +1342,7 @@
""" if PYGMENTS_2_14_PLUS else f"""\
<document source="test data">
<paragraph>
- Custom TAB expansion with included code:
+ No TAB expansion with included code:
<literal_block classes="code rst" source="{include_literal}" xml:space="preserve">
Literal included this should \n\
<inline classes="generic strong">
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2023-11-19 09:44:30
|
Revision: 9480
http://sourceforge.net/p/docutils/code/9480
Author: milde
Date: 2023-11-19 09:44:17 +0000 (Sun, 19 Nov 2023)
Log Message:
-----------
More smartquotes optimizations.
Simplify regexps (we don't need to consider HTML character entities
when transforming a Docutils document tree).
Modified Paths:
--------------
trunk/docutils/HISTORY.txt
trunk/docutils/docutils/utils/smartquotes.py
trunk/docutils/test/test_transforms/test_smartquotes.py
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2023-11-19 09:44:04 UTC (rev 9479)
+++ trunk/docutils/HISTORY.txt 2023-11-19 09:44:17 UTC (rev 9480)
@@ -71,6 +71,11 @@
- Update to version `1.4 <https://pypi.org/project/roman/4.1/>`__.
Fixes feature-requests:#95 (license is now ZPL 2.1).
+* docutils/utils/smartquotes.py
+
+ - Pre-compile regexps once, not with every call of `educateQuotes()`
+ (patch #206 by Chris Sewell). Simplify regexps.
+
* docutils/writers/latex2e/__init__.py
- Fix placement of hyperlink target (label) for tables (bug #440).
Modified: trunk/docutils/docutils/utils/smartquotes.py
===================================================================
--- trunk/docutils/docutils/utils/smartquotes.py 2023-11-19 09:44:04 UTC (rev 9479)
+++ trunk/docutils/docutils/utils/smartquotes.py 2023-11-19 09:44:17 UTC (rev 9480)
@@ -1,6 +1,6 @@
#!/usr/bin/python3
# :Id: $Id$
-# :Copyright: © 2010 Günter Milde,
+# :Copyright: © 2010-2023 Günter Milde,
# original `SmartyPants`_: © 2003 John Gruber
# smartypants.py: © 2004, 2007 Chad Miller
# :Maintainer: doc...@li...
@@ -149,19 +149,13 @@
posts (and final HTML output) will appear with smart quotes, em-dashes,
and proper ellipses.
-SmartyPants does not modify characters within ``<pre>``, ``<code>``, ``<kbd>``,
-``<math>`` or ``<script>`` tag blocks. Typically, these tags are used to
-display text where smart quotes and other "smart punctuation" would not be
-appropriate, such as source code or example markup.
-
-
Backslash Escapes
=================
If you need to use literal straight quotes (or plain hyphens and periods),
`smartquotes` accepts the following backslash escape sequences to force
-ASCII-punctuation. Mind, that you need two backslashes as Docutils expands it,
-too.
+ASCII-punctuation. Mind, that you need two backslashes in "docstrings", as
+Python expands them, too.
======== =========
Escape Character
@@ -259,6 +253,10 @@
Version History
===============
+1.10 2023-11-18
+ - Pre-compile regexps once, not with every call of `educateQuotes()`
+ (patch #206 by Chris Sewell). Simplify regexps.
+
1.9 2022-03-04
- Code cleanup. Require Python 3.
@@ -387,10 +385,10 @@
class smartchars:
"""Smart quotes and dashes"""
- endash = '–' # "–" EN DASH
- emdash = '—' # "—" EM DASH
- ellipsis = '…' # "…" HORIZONTAL ELLIPSIS
- apostrophe = '’' # "’" RIGHT SINGLE QUOTATION MARK
+ endash = '–' # EN DASH
+ emdash = '—' # EM DASH
+ ellipsis = '…' # HORIZONTAL ELLIPSIS
+ apostrophe = '’' # RIGHT SINGLE QUOTATION MARK
# quote characters (language-specific, set in __init__())
# https://en.wikipedia.org/wiki/Non-English_usage_of_quotation_marks
@@ -509,9 +507,9 @@
# character classes:
_CH_CLASSES = {'open': '[([{]', # opening braces
'close': r'[^\s]', # everything except whitespace
- 'punct': r"""[-!" #\$\%'()*+,.\/:;<=>?\@\[\\\]\^_`{|}~]""",
- 'dash': r'[-–—]|&[mn]dash;|&\#8211;|&\#8212;|&\#x201[34];',
- 'sep': '[\\s\u200B\u200C]| ', # Whitespace, ZWSP, ZWNJ
+ 'punct': r"""[-!" #\$\%'()*+,.\/:;<=>?\@\[\\\]\^_`{|}~]""",
+ 'dash': r'[-–—]',
+ 'sep': '[\\s\u200B\u200C]', # Whitespace, ZWSP, ZWNJ
}
START_SINGLE = re.compile(r"^'(?=%s\\B)" % _CH_CLASSES['punct'])
START_DOUBLE = re.compile(r'^"(?=%s\\B)' % _CH_CLASSES['punct'])
@@ -679,7 +677,7 @@
Returns: The `text`, with "educated" curly quote characters.
Example input: "Isn't this fun?"
- Example output: “Isn’t this fun?“;
+ Example output: “Isn’t this fun?“
"""
smart = smartchars(language)
@@ -737,7 +735,7 @@
Returns: The `text`, with ``backticks'' -style double quotes
translated into HTML curly quote entities.
Example input: ``Isn't this fun?''
- Example output: “Isn't this fun?“;
+ Example output: “Isn't this fun?“
"""
smart = smartchars(language)
@@ -813,7 +811,7 @@
an ellipsis character.
Example input: Huh...?
- Example output: Huh…?
+ Example output: Huh…?
"""
text = text.replace(r'...', smartchars.ellipsis)
Modified: trunk/docutils/test/test_transforms/test_smartquotes.py
===================================================================
--- trunk/docutils/test/test_transforms/test_smartquotes.py 2023-11-19 09:44:04 UTC (rev 9479)
+++ trunk/docutils/test/test_transforms/test_smartquotes.py 2023-11-19 09:44:17 UTC (rev 9480)
@@ -32,6 +32,8 @@
class TransformTestCase(unittest.TestCase):
+ maxDiff = None
+
def test_transforms(self):
parser = Parser()
settings = get_default_settings(Parser)
@@ -183,7 +185,6 @@
escaped space\\ "a" and\\ 'a',
hyphen -"a", -'a'
-—"a",—'a'
en dash –"a"–'a',
em dash —"a"—'a'.
@@ -210,7 +211,6 @@
escaped space“a” and‘a’,
<paragraph>
hyphen -“a”, -‘a’
- —“a”,—‘a’
en dash –“a”–‘a’,
em dash —“a”—‘a’.
<paragraph>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2023-11-19 21:19:26
|
Revision: 9481
http://sourceforge.net/p/docutils/code/9481
Author: milde
Date: 2023-11-19 21:19:20 +0000 (Sun, 19 Nov 2023)
Log Message:
-----------
Smartquotes optimizations part 3.
Skip regexp substitutions if there are no quotes to "educate".
Together, the optimizations bring down the time spent on the smartquotes transformation from
20% to 10% of the total rst2html5 conversion time.
(Tested with py-spy on `builthtml` of the Docutils docs directory.)
Modified Paths:
--------------
trunk/docutils/HISTORY.txt
trunk/docutils/docutils/utils/smartquotes.py
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2023-11-19 09:44:17 UTC (rev 9480)
+++ trunk/docutils/HISTORY.txt 2023-11-19 21:19:20 UTC (rev 9481)
@@ -74,7 +74,8 @@
* docutils/utils/smartquotes.py
- Pre-compile regexps once, not with every call of `educateQuotes()`
- (patch #206 by Chris Sewell). Simplify regexps.
+ (patch #206 by Chris Sewell); simplify regexps; skip replacement
+ rules if there is nothing to replace.
* docutils/writers/latex2e/__init__.py
Modified: trunk/docutils/docutils/utils/smartquotes.py
===================================================================
--- trunk/docutils/docutils/utils/smartquotes.py 2023-11-19 09:44:17 UTC (rev 9480)
+++ trunk/docutils/docutils/utils/smartquotes.py 2023-11-19 21:19:20 UTC (rev 9481)
@@ -142,7 +142,7 @@
- Straight quotes ( " and ' ) into "curly" quote characters
- Backticks-style quotes (\`\`like this'') into "curly" quote characters
- Dashes (``--`` and ``---``) into en- and em-dash entities
-- Three consecutive dots (``...`` or ``. . .``) into an ellipsis entity
+- Three consecutive dots (``...`` or ``. . .``) into an ellipsis ``…``.
This means you can write, edit, and save your posts using plain old
ASCII straight quotes, plain dashes, and plain dots, but your published
@@ -548,6 +548,9 @@
""", re.VERBOSE)
+regexes = RegularExpressions()
+
+
default_smartypants_attr = '1'
@@ -679,10 +682,11 @@
Example input: "Isn't this fun?"
Example output: “Isn’t this fun?“
"""
-
smart = smartchars(language)
- regexes = RegularExpressions()
+ if not re.search('[-"\']', text):
+ return text
+
# Special case if the very first character is a quote
# followed by punctuation at a non-word-break. Use closing quotes.
# TODO: example (when does this match?)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2023-11-25 21:08:35
|
Revision: 9483
http://sourceforge.net/p/docutils/code/9483
Author: milde
Date: 2023-11-25 21:08:33 +0000 (Sat, 25 Nov 2023)
Log Message:
-----------
Support moving images (video) in the "html4" writer.
Include image files in the formats "mp4", "ogg", and "webm"
as `<object>` nodes to get image support on par with the "html5" writer.
Modified Paths:
--------------
trunk/docutils/HISTORY.txt
trunk/docutils/docs/ref/rst/directives.txt
trunk/docutils/docutils/writers/html4css1/__init__.py
trunk/docutils/test/functional/expected/misc_rst_html4css1.html
trunk/docutils/test/functional/input/misc_rst_html4css1.txt
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2023-11-20 18:13:55 UTC (rev 9482)
+++ trunk/docutils/HISTORY.txt 2023-11-25 21:08:33 UTC (rev 9483)
@@ -77,6 +77,10 @@
(patch #206 by Chris Sewell); simplify regexps; skip replacement
rules if there is nothing to replace.
+* docutils/writers/html4css1/__init__.py
+
+ - Support video inclusion via `<object>` tags.
+
* docutils/writers/latex2e/__init__.py
- Fix placement of hyperlink target (label) for tables (bug #440).
Modified: trunk/docutils/docs/ref/rst/directives.txt
===================================================================
--- trunk/docutils/docs/ref/rst/directives.txt 2023-11-20 18:13:55 UTC (rev 9482)
+++ trunk/docutils/docs/ref/rst/directives.txt 2023-11-25 21:08:33 UTC (rev 9483)
@@ -169,7 +169,7 @@
----------- ------------- ----------------------------- -----------------
.. SVG PDF PNG JPG GIF APNG AVIF WebM MP4 OGG
=========== ====== ====== ===== ===== ===== ===== ===== ===== ===== =====
- HTML4_ ✓ [#]_ ✓ ✓ ✓ (✓) (✓)
+ HTML4_ [#]_ ✓ ✓ ✓ ✓ (✓) (✓) ✓ ✓ ✓
HTML5_ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓
@@ -182,8 +182,9 @@
ends with an extension matching one of the listed video formats
(since Docutils 0.17).
- .. [#] The html4 writer uses an ``<object>`` tag for SVG images
- for better compatibility with older browsers.
+ .. [#] The html4 writer uses an ``<object>`` tag for SVG images and
+ videos for compatibility with older browsers and for XHTML1.1
+ conformance respectively.
.. [#] When compiling with ``pdflatex``, ``xelatex``, or ``lualatex``.
The original ``latex`` engine supports only the EPS image format.
Modified: trunk/docutils/docutils/writers/html4css1/__init__.py
===================================================================
--- trunk/docutils/docutils/writers/html4css1/__init__.py 2023-11-20 18:13:55 UTC (rev 9482)
+++ trunk/docutils/docutils/writers/html4css1/__init__.py 2023-11-25 21:08:33 UTC (rev 9483)
@@ -541,7 +541,11 @@
# (SVG not supported by IE up to version 8,
# html4css1 strives for IE6 compatibility.)
object_image_types = {'.svg': 'image/svg+xml',
- '.swf': 'application/x-shockwave-flash'}
+ '.swf': 'application/x-shockwave-flash',
+ '.mp4': 'video/mp4',
+ '.webm': 'video/webm',
+ '.ogg': 'video/ogg',
+ }
def visit_image(self, node):
atts = {}
Modified: trunk/docutils/test/functional/expected/misc_rst_html4css1.html
===================================================================
--- trunk/docutils/test/functional/expected/misc_rst_html4css1.html 2023-11-20 18:13:55 UTC (rev 9482)
+++ trunk/docutils/test/functional/expected/misc_rst_html4css1.html 2023-11-25 21:08:33 UTC (rev 9483)
@@ -61,6 +61,24 @@
IDs after <a class="reference external" href="https://docutils.sourceforge.io/docs/ref/rst/directives.html#identifier-normalization">identifier normalization</a> of the section's reference name.</p>
</div>
</div>
+<div class="section" id="moving-images-video">
+<h1>Moving images (video)</h1>
+<p>If the URL given to <cite>images and figures</cite> hints to a video format
+supported by HTML 5 (MIME types 'video/mp4', 'video/webm', or
+'video/ogg'), the HTML5 writer will place it in a <a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video">video element</a>.</p>
+<object class="align-left" data="../../../docs/user/rst/images/pens.mp4" type="video/mp4">left-aligned test video</object>
+<p>A class option value "controls" tells the browser to display controls
+for video playback.</p>
+<p>It is a good idea to include width and height attributes. If
+height and width are not set, the page might flicker while the video
+loads. According to the <a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video">HTML5 spec</a>, hight and width must be
+specified as pixel values.</p>
+<div class="figure align-center">
+<object class="controls" data="../../../docs/user/rst/images/pens.mp4" style="width: 200px;" type="video/mp4">test video in a figure</object>
+<p class="caption">Simple test video in a centered figure</p>
</div>
+<p>A video like this <object data="../../../docs/user/rst/images/pens.mp4" style="width: 60px;" type="video/mp4">rotating pens video</object> can be included inline via substitution.</p>
+</div>
+</div>
</body>
</html>
Modified: trunk/docutils/test/functional/input/misc_rst_html4css1.txt
===================================================================
--- trunk/docutils/test/functional/input/misc_rst_html4css1.txt 2023-11-20 18:13:55 UTC (rev 9482)
+++ trunk/docutils/test/functional/input/misc_rst_html4css1.txt 2023-11-25 21:08:33 UTC (rev 9483)
@@ -3,3 +3,5 @@
===============================
.. include:: data/section_titles.txt
+
+.. include:: data/video.txt
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2023-11-25 21:09:09
|
Revision: 9485
http://sourceforge.net/p/docutils/code/9485
Author: milde
Date: 2023-11-25 21:09:05 +0000 (Sat, 25 Nov 2023)
Log Message:
-----------
Support `<video>` in "_html_base", use "style" attribute for size.
Move the handling of "moving images" from "html5_polyglot" to
"_html_base". Now all HTML writers support insertion of video content.
The :width: and :height: image directive options are passed to HTML
via the "style" attribute (supports length units).
Modified Paths:
--------------
trunk/docutils/HISTORY.txt
trunk/docutils/docutils/writers/_html_base.py
trunk/docutils/docutils/writers/html5_polyglot/__init__.py
trunk/docutils/test/functional/expected/misc_rst_html5.html
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2023-11-25 21:08:53 UTC (rev 9484)
+++ trunk/docutils/HISTORY.txt 2023-11-25 21:09:05 UTC (rev 9485)
@@ -81,6 +81,11 @@
- Support video inclusion via `<object>` tags.
+* docutils/writers/_html_base.py
+
+ - Support for video inclusion via `<video>` tags
+ (moved here from writers/html5_polyglot/__init__.py).
+
* docutils/writers/latex2e/__init__.py
- Fix placement of hyperlink target (label) for tables (bug #440).
Modified: trunk/docutils/docutils/writers/_html_base.py
===================================================================
--- trunk/docutils/docutils/writers/_html_base.py 2023-11-25 21:08:53 UTC (rev 9484)
+++ trunk/docutils/docutils/writers/_html_base.py 2023-11-25 21:09:05 UTC (rev 9485)
@@ -1005,6 +1005,9 @@
self.header.extend(header)
del self.body[start:]
+ # MIME types supported by the HTML5 <video> element
+ videotypes = ('video/mp4', 'video/webm', 'video/ogg')
+
def visit_image(self, node):
atts = {}
uri = node['uri']
@@ -1011,7 +1014,6 @@
uri_parts = urllib.parse.urlparse(uri)
imagepath = ''
mimetype = mimetypes.guess_type(uri)[0]
- scaling_problems = []
# image size
if 'width' in node:
atts['width'] = node['width']
@@ -1020,10 +1022,13 @@
if 'scale' in node:
if 'width' not in node or 'height' not in node:
# try reading size from image file
+ scaling_problems = []
if uri_parts.scheme not in ('', 'file'):
- scaling_problems.append('Works only for local images.')
+ scaling_problems.append('Can only read local images.')
if not PIL:
scaling_problems.append('Requires Python Imaging Library.')
+ if mimetype in self.videotypes:
+ scaling_problems.append('PIL cannot read video images.')
if not self.settings.file_insertion_enabled:
scaling_problems.append('Reading external files disabled.')
if not scaling_problems:
@@ -1037,9 +1042,10 @@
self.settings.record_dependencies.add(
imagepath.replace('\\', '/'))
if scaling_problems:
- self.document.reporter.warning(
- '\n '.join([f'Cannot scale "{imagepath or uri}".']
- + scaling_problems))
+ msg = ['Cannot scale image!',
+ f'Could not get size from "{imagepath or uri}":',
+ *scaling_problems]
+ self.document.reporter.warning('\n '.join(msg))
else:
if 'width' not in atts:
atts['width'] = '%dpx' % imgsize[0]
@@ -1056,8 +1062,8 @@
style = []
for att_name in 'width', 'height':
if att_name in atts:
+ # Interpret unitless values as pixels:
if re.match(r'^[0-9.]+$', atts[att_name]):
- # Interpret unitless values as pixels.
atts[att_name] += 'px'
style.append('%s: %s;' % (att_name, atts[att_name]))
del atts[att_name]
@@ -1070,8 +1076,22 @@
suffix = ''
else:
suffix = '\n'
+
if 'align' in node:
atts['class'] = 'align-%s' % node['align']
+
+ # moving image -> use <video>
+ if mimetype in self.videotypes:
+ fallback = node.get('alt', uri)
+ atts['title'] = fallback
+ if 'controls' in node['classes']:
+ node['classes'].remove('controls')
+ atts['controls'] = 'controls'
+ self.body.append(
+ self.starttag(node, "video", suffix, src=uri, **atts)
+ + f'<a href="{uri}">{fallback}</a>{suffix}</video>{suffix}')
+ return
+
# Embed image file (embedded SVG or data URI):
if self.image_loading == 'embed':
if uri_parts.scheme not in ('', 'file'):
Modified: trunk/docutils/docutils/writers/html5_polyglot/__init__.py
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/__init__.py 2023-11-25 21:08:53 UTC (rev 9484)
+++ trunk/docutils/docutils/writers/html5_polyglot/__init__.py 2023-11-25 21:09:05 UTC (rev 9485)
@@ -26,7 +26,6 @@
"""
__docformat__ = 'reStructuredText'
-import mimetypes
from pathlib import Path
from docutils import frontend, nodes
@@ -238,43 +237,6 @@
self.header.extend(header)
del self.body[start:]
- # MIME types supported by the HTML5 <video> element
- videotypes = ('video/mp4', 'video/webm', 'video/ogg')
-
- def visit_image(self, node):
- atts = {}
- uri = node['uri']
- mimetype = mimetypes.guess_type(uri)[0]
- if mimetype not in self.videotypes:
- return super().visit_image(node)
- # image size
- if 'width' in node:
- atts['width'] = node['width'].replace('px', '')
- if 'height' in node:
- atts['height'] = node['height'].replace('px', '')
- if 'align' in node:
- atts['class'] = f"align-{node['align']}"
- if 'controls' in node['classes']:
- atts['controls'] = 'controls'
- node['classes'].remove('controls')
- atts['title'] = node.get('alt', uri)
- if getattr(self.settings, 'image_loading', None) == 'lazy':
- atts['loading'] = 'lazy'
- # No newline in inline context or if surrounded by <a>...</a>.
- if (isinstance(node.parent, nodes.TextElement)
- or (isinstance(node.parent, nodes.reference)
- and not isinstance(node.parent.parent, nodes.TextElement))):
- suffix = ''
- else:
- suffix = '\n'
- fallback = node.get('alt', uri)
- self.body.append(
- self.starttag(node, "video", suffix, src=uri, **atts)
- + f'<a href="{uri}">{fallback}</a>{suffix}</video>{suffix}')
-
- def depart_image(self, node):
- pass
-
# use HTML text-level tags if matching class value found
supported_inline_tags = {'code', 'kbd', 'dfn', 'samp', 'var',
'bdi', 'del', 'ins', 'mark', 'small',
Modified: trunk/docutils/test/functional/expected/misc_rst_html5.html
===================================================================
--- trunk/docutils/test/functional/expected/misc_rst_html5.html 2023-11-25 21:08:53 UTC (rev 9484)
+++ trunk/docutils/test/functional/expected/misc_rst_html5.html 2023-11-25 21:09:05 UTC (rev 9485)
@@ -136,7 +136,7 @@
loads. According to the <a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video">HTML5 spec</a>, hight and width must be
specified as pixel values.</p>
<figure class="align-center">
-<video controls="controls" src="../../../docs/user/rst/images/pens.mp4" title="test video in a figure" width="200">
+<video controls="controls" src="../../../docs/user/rst/images/pens.mp4" style="width: 200px;" title="test video in a figure">
<a href="../../../docs/user/rst/images/pens.mp4">test video in a figure</a>
</video>
<figcaption>
@@ -143,7 +143,7 @@
<p>Simple test video in a centered figure</p>
</figcaption>
</figure>
-<p>A video like this <video src="../../../docs/user/rst/images/pens.mp4" title="rotating pens video" width="60"><a href="../../../docs/user/rst/images/pens.mp4">rotating pens video</a></video> can be included inline via substitution.</p>
+<p>A video like this <video src="../../../docs/user/rst/images/pens.mp4" style="width: 60px;" title="rotating pens video"><a href="../../../docs/user/rst/images/pens.mp4">rotating pens video</a></video> can be included inline via substitution.</p>
</section>
</main>
</body>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2023-11-25 21:09:20
|
Revision: 9486
http://sourceforge.net/p/docutils/code/9486
Author: milde
Date: 2023-11-25 21:09:17 +0000 (Sat, 25 Nov 2023)
Log Message:
-----------
Simplify handling of legacy setting "embed_images".
Simplify code converting "embed_images" to a "image_loading" default.
Wrap deprecation message.
Modified Paths:
--------------
trunk/docutils/docutils/writers/_html_base.py
trunk/docutils/test/test_writers/test_html5_polyglot_misc.py
Modified: trunk/docutils/docutils/writers/_html_base.py
===================================================================
--- trunk/docutils/docutils/writers/_html_base.py 2023-11-25 21:09:05 UTC (rev 9485)
+++ trunk/docutils/docutils/writers/_html_base.py 2023-11-25 21:09:17 UTC (rev 9486)
@@ -286,22 +286,17 @@
settings.language_code, document.reporter)
self.initial_header_level = int(settings.initial_header_level)
# image_loading (only defined for HTML5 writer)
- self.image_loading = getattr(settings, 'image_loading', None)
- # legacy setting embed_images:
- if getattr(settings, 'embed_images', None) is True:
- warnings.warn('The configuration setting "embed_images" '
- 'will be removed in Docutils 2.0. '
- 'Use "image_loading: embed".',
+ _image_loading_default = 'link'
+ # convert legacy setting embed_images:
+ if getattr(settings, 'embed_images', None) is not None:
+ if settings.embed_images:
+ _image_loading_default = 'embed'
+ warnings.warn('The configuration setting "embed_images"\n'
+ ' will be removed in Docutils 2.0. '
+ f'Use "image_loading: {_image_loading_default}".',
FutureWarning, stacklevel=8)
- if self.image_loading is None:
- self.image_loading = 'embed'
- if getattr(settings, 'embed_images', None) is False:
- warnings.warn('The configuration setting "embed_images" '
- 'will be removed in Docutils 2.0. '
- 'Use "image_loading: link".',
- FutureWarning, stacklevel=8)
- if self.image_loading is None:
- self.image_loading = 'link' # default
+ self.image_loading = getattr(settings,
+ 'image_loading', _image_loading_default)
self.math_output = settings.math_output.split()
self.math_output_options = self.math_output[1:]
self.math_output = self.math_output[0].lower()
Modified: trunk/docutils/test/test_writers/test_html5_polyglot_misc.py
===================================================================
--- trunk/docutils/test/test_writers/test_html5_polyglot_misc.py 2023-11-25 21:09:05 UTC (rev 9485)
+++ trunk/docutils/test/test_writers/test_html5_polyglot_misc.py 2023-11-25 21:09:17 UTC (rev 9486)
@@ -163,7 +163,7 @@
'output_encoding': 'unicode',
}
with self.assertWarnsRegex(FutureWarning,
- '"embed_images" will be removed'):
+ '"embed_images"\n will be removed'):
core.publish_string('warnings test', writer_name='html5',
settings_overrides=my_settings)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2023-11-25 21:09:32
|
Revision: 9487
http://sourceforge.net/p/docutils/code/9487
Author: milde
Date: 2023-11-25 21:09:29 +0000 (Sat, 25 Nov 2023)
Log Message:
-----------
Adapt path before reading image file.
In order to work in the output document, relative image URIs relate
to the output directory. To determine the image size from the image or
embed the image, the writer must access the image file at build time.
The change ensures that the same URI can be used for images referenced
in the output document and embedded images also when CWD and output
directory differ.
Modified Paths:
--------------
trunk/docutils/HISTORY.txt
trunk/docutils/docutils/writers/_html_base.py
trunk/docutils/docutils/writers/html4css1/__init__.py
trunk/docutils/test/functional/expected/misc_rst_html5.html
trunk/docutils/test/functional/input/data/embed_images.txt
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2023-11-25 21:09:17 UTC (rev 9486)
+++ trunk/docutils/HISTORY.txt 2023-11-25 21:09:29 UTC (rev 9487)
@@ -85,6 +85,9 @@
- Support for video inclusion via `<video>` tags
(moved here from writers/html5_polyglot/__init__.py).
+ - New auxiliary function `HTMLTranslator.uri2imagepath()`
+ ensures the image file can also be read when
+ CWD and output directory differ.
* docutils/writers/latex2e/__init__.py
Modified: trunk/docutils/docutils/writers/_html_base.py
===================================================================
--- trunk/docutils/docutils/writers/_html_base.py 2023-11-25 21:09:17 UTC (rev 9486)
+++ trunk/docutils/docutils/writers/_html_base.py 2023-11-25 21:09:29 UTC (rev 9487)
@@ -22,7 +22,6 @@
import os.path
import re
import urllib
-from urllib.request import url2pathname # unquote and use local path sep
import warnings
import docutils
@@ -493,6 +492,29 @@
return
child['classes'].append(class_)
+ def uri2imagepath(self, uri):
+ """Get filesystem path corresponding to an URI.
+
+ The image directive expects an image URI. Some writers require the
+ corresponding image path to read the image size from the file or to
+ embed the image in the output.
+
+ In order to work in the output document, relative image URIs relate
+ to the output directory. For access by the writer, the corresponding
+ image path must be relative to the current working directory.
+
+ Provisional: the function's location, interface and behaviour
+ may change without advance warning.
+ """
+ destination = self.settings._destination or ''
+ uri_parts = urllib.parse.urlparse(uri)
+ imagepath = urllib.request.url2pathname(uri_parts.path)
+ if not os.path.isabs(imagepath):
+ destdir = os.path.abspath(os.path.dirname(destination))
+ imagepath = utils.relative_path(None,
+ os.path.join(destdir, imagepath))
+ return imagepath
+
def visit_Text(self, node):
text = node.astext()
encoded = self.encode(text)
@@ -1004,11 +1026,13 @@
videotypes = ('video/mp4', 'video/webm', 'video/ogg')
def visit_image(self, node):
- atts = {}
uri = node['uri']
uri_parts = urllib.parse.urlparse(uri)
imagepath = ''
mimetype = mimetypes.guess_type(uri)[0]
+ atts = {} # attributes for the HTML tag
+ if 'align' in node:
+ atts['class'] = 'align-%s' % node['align']
# image size
if 'width' in node:
atts['width'] = node['width']
@@ -1027,7 +1051,7 @@
if not self.settings.file_insertion_enabled:
scaling_problems.append('Reading external files disabled.')
if not scaling_problems:
- imagepath = url2pathname(uri_parts.path)
+ imagepath = self.uri2imagepath(uri)
try:
with PIL.Image.open(imagepath) as img:
imgsize = img.size
@@ -1054,6 +1078,7 @@
atts[att_name] = '%s%s' % (
float(match.group(1)) * (float(node['scale']) / 100),
match.group(2))
+ # set size with "style" attribute (more universal, accepts dimensions)
style = []
for att_name in 'width', 'height':
if att_name in atts:
@@ -1064,17 +1089,14 @@
del atts[att_name]
if style:
atts['style'] = ' '.join(style)
+ # No newlines around inline images or if surrounded by <a>...</a>.
if (isinstance(node.parent, nodes.TextElement)
or (isinstance(node.parent, nodes.reference)
and not isinstance(node.parent.parent, nodes.TextElement))):
- # Inline context or surrounded by <a>...</a>.
suffix = ''
else:
suffix = '\n'
- if 'align' in node:
- atts['class'] = 'align-%s' % node['align']
-
# moving image -> use <video>
if mimetype in self.videotypes:
fallback = node.get('alt', uri)
@@ -1093,14 +1115,9 @@
self.document.reporter.error(
f'Cannot embed remote image "{uri}"')
# TODO: read with urllib.request?
- imagepath = imagepath or url2pathname(uri_parts.path)
- # TODO: adapt relative imagepath?
- # if not os.path.isabs(imagepath):
- # _src, _ln = utils.get_source_line(node)
- # dirname = os.path.dirname(_src or '')
- # imagepath = os.path.join(dirname, imagepath)
+ imagepath = imagepath or self.uri2imagepath(uri)
try:
- with open(url2pathname(uri), 'rb') as imagefile:
+ with open(imagepath, 'rb') as imagefile:
imagedata = imagefile.read()
except OSError as err:
self.document.reporter.error('Cannot embed image %r: %s'
@@ -1116,6 +1133,7 @@
uri = 'data:%s;base64,%s' % (mimetype, data64)
elif self.image_loading == 'lazy':
atts['loading'] = 'lazy'
+
if mimetype == 'application/x-shockwave-flash':
atts['type'] = mimetype
# do NOT use an empty tag: incorrect rendering in browsers
Modified: trunk/docutils/docutils/writers/html4css1/__init__.py
===================================================================
--- trunk/docutils/docutils/writers/html4css1/__init__.py 2023-11-25 21:09:17 UTC (rev 9486)
+++ trunk/docutils/docutils/writers/html4css1/__init__.py 2023-11-25 21:09:29 UTC (rev 9487)
@@ -19,7 +19,7 @@
from docutils import frontend, nodes, writers
from docutils.writers import _html_base
-from docutils.writers._html_base import PIL, url2pathname
+from docutils.writers._html_base import PIL
class Writer(writers._html_base.Writer):
@@ -565,7 +565,7 @@
if 'scale' in node:
if (PIL and ('width' not in node or 'height' not in node)
and self.settings.file_insertion_enabled):
- imagepath = url2pathname(uri)
+ imagepath = self.uri2imagepath(uri)
try:
with PIL.Image.open(imagepath) as img:
img_size = img.size
Modified: trunk/docutils/test/functional/expected/misc_rst_html5.html
===================================================================
--- trunk/docutils/test/functional/expected/misc_rst_html5.html 2023-11-25 21:09:17 UTC (rev 9486)
+++ trunk/docutils/test/functional/expected/misc_rst_html5.html 2023-11-25 21:09:29 UTC (rev 9487)
@@ -52,7 +52,7 @@
<li><p><a class="reference internal" href="#substitutions-fail" id="toc-entry-12">Substitutions work</a></p></li>
</ul>
</li>
-<li><p><a class="reference internal" href="#embedded-images" id="toc-entry-13">Embedded Images</a></p></li>
+<li><p><a class="reference internal" href="#embedded-images" id="toc-entry-13">Embedded images</a></p></li>
<li><p><a class="reference internal" href="#moving-images-video" id="toc-entry-14">Moving images (video)</a></p></li>
</ul>
</nav>
@@ -107,11 +107,10 @@
</section>
</section>
<section id="embedded-images">
-<h2><a class="toc-backref" href="#contents" role="doc-backlink">Embedded Images</a><a class="self-link" title="link to this section" href="#embedded-images"></a></h2>
-<p>The “embed” flag tells Docutils that it should
-try to embed the image in the output document.</p>
-<p>If the image can be read from the local file system, it is <a class="reference external" href="https://en.wikipedia.org/wiki/Base64">base64</a>
-encoded and included as a <a class="reference external" href="https://en.wikipedia.org/wiki/Data_URI_scheme">data URI</a>.
+<h2><a class="toc-backref" href="#contents" role="doc-backlink">Embedded images</a><a class="self-link" title="link to this section" href="#embedded-images"></a></h2>
+<p>The <a class="reference external" href="https://docutils.sourceforge.io/docs/user/config.html#image-loading">image_loading</a> setting can be used to tell the “html5” writer to
+embed images in the output document.
+The image is <a class="reference external" href="https://en.wikipedia.org/wiki/Base64">base64</a> encoded and included as a <a class="reference external" href="https://en.wikipedia.org/wiki/Data_URI_scheme">data URI</a>.
In future, SVG images may be directly inserted into HTML5.</p>
<figure class="align-center">
<img alt="biohazard" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABGdBTUEAANkE3LLaAgAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAAZQTFRF////AAAAVcLTfgAAAAF0Uk5TAEDm2GYAAAA2SURBVHicYmBRYOAQYJCQYJC+wSBjAUL2fxjq6hgueTNM7AQh3g0MzAdAiP0BUBYAAAD//wMA4pkLDrFBDzUAAAAASUVORK5CYII=" />
Modified: trunk/docutils/test/functional/input/data/embed_images.txt
===================================================================
--- trunk/docutils/test/functional/input/data/embed_images.txt 2023-11-25 21:09:17 UTC (rev 9486)
+++ trunk/docutils/test/functional/input/data/embed_images.txt 2023-11-25 21:09:29 UTC (rev 9487)
@@ -1,14 +1,12 @@
-Embedded Images
+Embedded images
===============
-The "embed" flag tells Docutils that it should
-try to embed the image in the output document.
-
-If the image can be read from the local file system, it is base64_
-encoded and included as a `data URI`_.
+The image_loading_ setting can be used to tell the "html5" writer to
+embed images in the output document.
+The image is base64_ encoded and included as a `data URI`_.
In future, SVG images may be directly inserted into HTML5.
-.. figure:: ../docs/user/rst/images/biohazard.png
+.. figure:: ../../../docs/user/rst/images/biohazard.png
:alt: biohazard
:align: center
@@ -16,8 +14,10 @@
Embedded inline image |inline-embedded| scaled to a height of 0.8 em.
-.. |inline-embedded| image:: ../docs/user/rst/images/biohazard.png
+.. |inline-embedded| image:: file:../../../docs/user/rst/images/biohazard.png
:height: 0.8 em
+.. _image_loading:
+ https://docutils.sourceforge.io/docs/user/config.html#image-loading
.. _base64: https://en.wikipedia.org/wiki/Base64
.. _data URI: https://en.wikipedia.org/wiki/Data_URI_scheme
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2023-11-29 16:58:17
|
Revision: 9492
http://sourceforge.net/p/docutils/code/9492
Author: milde
Date: 2023-11-29 16:58:13 +0000 (Wed, 29 Nov 2023)
Log Message:
-----------
Config setting "root-prefix": configurable root directory for included files.
Cf. [feature-requests:#91]
The "root_prefix" setting is also applied when a writer converts an image
URI to a local filesystem path.
(The image file may be red by the writer to get the image size (HTML
writers) or to embed it in the output (HTML5 and ODT writers).)
Modified Paths:
--------------
trunk/docutils/docs/ref/rst/directives.txt
trunk/docutils/docs/user/config.txt
trunk/docutils/docutils/frontend.py
trunk/docutils/docutils/parsers/rst/directives/misc.py
trunk/docutils/docutils/parsers/rst/directives/tables.py
trunk/docutils/docutils/writers/_html_base.py
trunk/docutils/docutils/writers/odf_odt/__init__.py
trunk/docutils/test/data/help/docutils.txt
trunk/docutils/test/data/help/rst2html.txt
trunk/docutils/test/data/help/rst2latex.txt
trunk/docutils/test/test_writers/test_html4css1_parts.py
trunk/docutils/test/test_writers/test_html5_polyglot_parts.py
Added Paths:
-----------
trunk/docutils/test/test_parsers/test_rst/test_root_prefix.py
Modified: trunk/docutils/docs/ref/rst/directives.txt
===================================================================
--- trunk/docutils/docs/ref/rst/directives.txt 2023-11-29 16:57:50 UTC (rev 9491)
+++ trunk/docutils/docs/ref/rst/directives.txt 2023-11-29 16:58:13 UTC (rev 9492)
@@ -2166,6 +2166,9 @@
*path*
local filesystem path. Newlines are removed.
+ The `root_prefix`_ configuration setting can be used to tell Docutils
+ to interpret absolute paths (starting with "/") relative to a "project
+ directory".
.. _text:
@@ -2195,7 +2198,6 @@
.. _percentage: restructuredtext.html#percentage-units
.. _reference name:
.. _reference names: restructuredtext.html#reference-names
-
.. _identifier keys: ../doctree.html#ids-type
.. _inline elements: ../doctree.html#inline-elements
.. _class names: ../doctree.html#classname
@@ -2203,6 +2205,7 @@
.. _classes attribute: ../doctree.html#classes
.. _ids attribute: ../doctree.html#ids
.. _names attribute: ../doctree.html#names
+.. _root_prefix: ../../user/config.html#root-prefix
.. _title attribute: ../doctree.html#title-attribute
.. _<admonition>: ../doctree.html#admonition
.. _<attention>: ../doctree.html#attention
Modified: trunk/docutils/docs/user/config.txt
===================================================================
--- trunk/docutils/docs/user/config.txt 2023-11-29 16:57:50 UTC (rev 9491)
+++ trunk/docutils/docs/user/config.txt 2023-11-29 16:58:13 UTC (rev 9492)
@@ -514,6 +514,25 @@
Default: warning (2).
Options: ``--report, -r, --verbose, -v, --quiet, -q``.
+root_prefix
+-----------
+
+Base directory, prepended to a filesystem path__ starting with "/" when
+including files with the "include_", "raw_", or "csv-table_" directives.
+
+Also applied when a writer converts an image URI to a local filesystem
+path in order to determine the image size or embed the image in the output.
+
+Default: "/" (no change).
+Option: ``--root-prefix``
+
+New in Docutils 0.21.
+
+__ ../ref/rst/directives.html#path
+__ ../ref/rst/directives.html#uri
+.. _image: ../ref/rst/directives.html#image
+.. _figure: ../ref/rst/directives.html#figure
+
sectnum_xform
-------------
Modified: trunk/docutils/docutils/frontend.py
===================================================================
--- trunk/docutils/docutils/frontend.py 2023-11-29 16:57:50 UTC (rev 9491)
+++ trunk/docutils/docutils/frontend.py 2023-11-29 16:58:13 UTC (rev 9492)
@@ -481,6 +481,10 @@
('Do not include a datestamp of any kind.',
['--no-datestamp'], {'action': 'store_const', 'const': None,
'dest': 'datestamp'}),
+ ('Base directory for absolute paths when reading '
+ 'from the local filesystem. Default "/".',
+ ['--root-prefix'],
+ {'default': '/', 'metavar': '<path>'}),
('Include a "View document source" link.',
['--source-link', '-s'], {'action': 'store_true',
'validator': validate_boolean}),
Modified: trunk/docutils/docutils/parsers/rst/directives/misc.py
===================================================================
--- trunk/docutils/docutils/parsers/rst/directives/misc.py 2023-11-29 16:57:50 UTC (rev 9491)
+++ trunk/docutils/docutils/parsers/rst/directives/misc.py 2023-11-29 16:58:13 UTC (rev 9492)
@@ -19,6 +19,20 @@
from docutils.transforms import misc
+def adapt_path(path, source='', root_prefix='/'):
+ # Adapt path to files to include or embed.
+ # `root_prefix` is prepended to absolute paths (cf. root_prefix setting),
+ # `source` is the `current_source` of the including directive (which may
+ # be a file included by the main document).
+ if path.startswith('/'):
+ base = Path(root_prefix)
+ path = path[1:]
+ else:
+ base = Path(source).parent
+ # pepend "base" and convert to relative path for shorter system messages
+ return utils.relative_path(None, base/path)
+
+
class Include(Directive):
"""
@@ -65,11 +79,11 @@
current_source = self.state.document.current_source
path = directives.path(self.arguments[0])
if path.startswith('<') and path.endswith('>'):
- _base = self.standard_include_path
- path = path[1:-1]
+ path = '/' + path[1:-1]
+ root_prefix = self.standard_include_path
else:
- _base = Path(current_source).parent
- path = utils.relative_path(None, _base/path)
+ root_prefix = settings.root_prefix
+ path = adapt_path(path, current_source, root_prefix)
encoding = self.options.get('encoding', settings.input_encoding)
error_handler = settings.input_encoding_error_handler
try:
@@ -245,9 +259,9 @@
raise self.error(
'The "file" and "url" options may not be simultaneously '
'specified for the "%s" directive.' % self.name)
- path = self.options['file']
- _base = Path(self.state.document.current_source).parent
- path = utils.relative_path(None, _base/path)
+ path = adapt_path(self.options['file'],
+ self.state.document.current_source,
+ settings.root_prefix)
try:
raw_file = io.FileInput(source_path=path,
encoding=encoding,
Modified: trunk/docutils/docutils/parsers/rst/directives/tables.py
===================================================================
--- trunk/docutils/docutils/parsers/rst/directives/tables.py 2023-11-29 16:57:50 UTC (rev 9491)
+++ trunk/docutils/docutils/parsers/rst/directives/tables.py 2023-11-29 16:58:13 UTC (rev 9492)
@@ -10,15 +10,15 @@
import csv
-from pathlib import Path
from urllib.request import urlopen
from urllib.error import URLError
import warnings
-from docutils import nodes, statemachine, utils
+from docutils import nodes, statemachine
from docutils.io import FileInput, StringInput
from docutils.parsers.rst import Directive
from docutils.parsers.rst import directives
+from docutils.parsers.rst.directives.misc import adapt_path
from docutils.utils import SystemMessagePropagation
@@ -344,10 +344,9 @@
nodes.literal_block(self.block_text, self.block_text),
line=self.lineno)
raise SystemMessagePropagation(error)
- source = self.options['file']
- # resolve path to external file
- _base = Path(self.state.document.current_source).parent
- source = utils.relative_path(None, _base/source)
+ source = adapt_path(self.options['file'],
+ self.state.document.current_source,
+ settings.root_prefix)
try:
csv_file = FileInput(source_path=source,
encoding=encoding,
Modified: trunk/docutils/docutils/writers/_html_base.py
===================================================================
--- trunk/docutils/docutils/writers/_html_base.py 2023-11-29 16:57:50 UTC (rev 9491)
+++ trunk/docutils/docutils/writers/_html_base.py 2023-11-29 16:58:13 UTC (rev 9492)
@@ -20,6 +20,7 @@
import mimetypes
import os
import os.path
+from pathlib import Path
import re
import urllib
import warnings
@@ -499,6 +500,8 @@
corresponding image path to read the image size from the file or to
embed the image in the output.
+ Absolute URIs consider the "root_prefix" setting.
+
In order to work in the output document, relative image URIs relate
to the output directory. For access by the writer, the corresponding
image path must be relative to the current working directory.
@@ -509,7 +512,10 @@
destination = self.settings._destination or ''
uri_parts = urllib.parse.urlparse(uri)
imagepath = urllib.request.url2pathname(uri_parts.path)
- if not os.path.isabs(imagepath):
+ if imagepath.startswith('/'):
+ root_prefix = Path(self.settings.root_prefix)
+ imagepath = (root_prefix/imagepath[1:]).as_posix()
+ elif not os.path.isabs(imagepath): # exclude absolute Windows paths
destdir = os.path.abspath(os.path.dirname(destination))
imagepath = utils.relative_path(None,
os.path.join(destdir, imagepath))
Modified: trunk/docutils/docutils/writers/odf_odt/__init__.py
===================================================================
--- trunk/docutils/docutils/writers/odf_odt/__init__.py 2023-11-29 16:57:50 UTC (rev 9491)
+++ trunk/docutils/docutils/writers/odf_odt/__init__.py 2023-11-29 16:58:13 UTC (rev 9492)
@@ -19,13 +19,12 @@
import locale
import os
import os.path
+from pathlib import Path
import re
import subprocess
import tempfile
import time
-from urllib.error import URLError
-from urllib.parse import urlparse
-from urllib.request import urlopen, url2pathname
+import urllib
import weakref
from xml.etree import ElementTree as etree
from xml.dom import minidom
@@ -2119,10 +2118,13 @@
def visit_image(self, node):
# Capture the image file.
source = node['uri']
- uri_parts = urlparse(source)
+ uri_parts = urllib.parse.urlparse(source)
if uri_parts.scheme in ('', 'file'):
- source = url2pathname(uri_parts.path)
- if not os.path.isabs(source):
+ source = urllib.parse.unquote(uri_parts.path)
+ if source.startswith('/'):
+ root_prefix = Path(self.settings.root_prefix)
+ source = (root_prefix/source[1:]).as_posix()
+ else:
# adapt relative paths
docsource, line = utils.get_source_line(node)
if docsource:
@@ -2143,9 +2145,9 @@
spec = (os.path.abspath(source), destination,)
else:
try:
- with urlopen(source) as imgfile:
+ with urllib.request.urlopen(source) as imgfile:
content = imgfile.read()
- except URLError as err:
+ except urllib.error.URLError as err:
self.document.reporter.warning(
f'Cannot open image URL "{source}". {err}')
return
Modified: trunk/docutils/test/data/help/docutils.txt
===================================================================
--- trunk/docutils/test/data/help/docutils.txt 2023-11-29 16:57:50 UTC (rev 9491)
+++ trunk/docutils/test/data/help/docutils.txt 2023-11-29 16:58:13 UTC (rev 9492)
@@ -19,6 +19,8 @@
--date, -d Include the date at the end of the document (UTC).
--time, -t Include the time & date (UTC).
--no-datestamp Do not include a datestamp of any kind.
+--root-prefix=<path> Base directory for absolute paths when reading from
+ the local filesystem. Default "/".
--source-link, -s Include a "View document source" link.
--source-url=<URL> Use <URL> for a source link; implies --source-link.
--no-source-link Do not include a "View document source" link.
Modified: trunk/docutils/test/data/help/rst2html.txt
===================================================================
--- trunk/docutils/test/data/help/rst2html.txt 2023-11-29 16:57:50 UTC (rev 9491)
+++ trunk/docutils/test/data/help/rst2html.txt 2023-11-29 16:58:13 UTC (rev 9492)
@@ -20,6 +20,8 @@
--date, -d Include the date at the end of the document (UTC).
--time, -t Include the time & date (UTC).
--no-datestamp Do not include a datestamp of any kind.
+--root-prefix=<path> Base directory for absolute paths when reading from
+ the local filesystem. Default "/".
--source-link, -s Include a "View document source" link.
--source-url=<URL> Use <URL> for a source link; implies --source-link.
--no-source-link Do not include a "View document source" link.
Modified: trunk/docutils/test/data/help/rst2latex.txt
===================================================================
--- trunk/docutils/test/data/help/rst2latex.txt 2023-11-29 16:57:50 UTC (rev 9491)
+++ trunk/docutils/test/data/help/rst2latex.txt 2023-11-29 16:58:13 UTC (rev 9492)
@@ -20,6 +20,8 @@
--date, -d Include the date at the end of the document (UTC).
--time, -t Include the time & date (UTC).
--no-datestamp Do not include a datestamp of any kind.
+--root-prefix=<path> Base directory for absolute paths when reading from
+ the local filesystem. Default "/".
--source-link, -s Include a "View document source" link.
--source-url=<URL> Use <URL> for a source link; implies --source-link.
--no-source-link Do not include a "View document source" link.
Added: trunk/docutils/test/test_parsers/test_rst/test_root_prefix.py
===================================================================
--- trunk/docutils/test/test_parsers/test_rst/test_root_prefix.py (rev 0)
+++ trunk/docutils/test/test_parsers/test_rst/test_root_prefix.py 2023-11-29 16:58:13 UTC (rev 9492)
@@ -0,0 +1,131 @@
+#! /usr/bin/env python3
+# $Id$
+# Author: Günter Milde
+# Maintainer: doc...@li...
+# :Copyright: 2022 Günter Milde,
+# :License: Released under the terms of the `2-Clause BSD license`_, in short:
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+# This file is offered as-is, without any warranty.
+#
+# .. _2-Clause BSD license: https://opensource.org/licenses/BSD-2-Clause
+
+"""Test configurable root directory for included files
+
+Cf. feature-requests #91.
+"""
+
+import os
+from pathlib import Path
+import sys
+import unittest
+
+if __name__ == '__main__':
+ # prepend the "docutils root" to the Python library path
+ # so we import the local `docutils` package.
+ sys.path.insert(0, str(Path(__file__).parents[3]))
+
+from docutils.frontend import get_default_settings
+from docutils.parsers.rst import Parser
+from docutils.utils import new_document
+
+ROOT_PREFIX = (Path(__file__).parent/'test_directives').as_posix()
+REL_PREFIX = os.path.relpath(ROOT_PREFIX).replace('\\', '/')
+
+
+class ParserTestCase(unittest.TestCase):
+
+ def test_parser(self):
+ parser = Parser()
+ settings = get_default_settings(Parser)
+ settings.warning_stream = ''
+ settings.root_prefix = ROOT_PREFIX
+ for name, cases in totest.items():
+ for casenum, (case_input, case_expected) in enumerate(cases):
+ with self.subTest(id=f'totest[{name!r}][{casenum}]'):
+ document = new_document('test data', settings.copy())
+ parser.parse(case_input, document)
+ output = document.pformat()
+ self.assertEqual(output, case_expected)
+
+
+totest = {}
+
+totest['include-root'] = [
+# locate included files using "include-root" setting value
+["""\
+.. include:: /include 11.txt
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ some text
+"""],
+# Do we want to support a leading backslash to signify a path root?
+# ["""\
+# .. include:: \include 11.txt
+# """,
+# """\
+# <document source="test data">
+# <paragraph>
+# some text
+# """],
+["""\
+.. include:: /include 11.txt
+ :parser: rst
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ some text
+"""],
+["""\
+.. include:: /include 11.txt
+ :literal:
+""",
+f"""\
+<document source="test data">
+ <literal_block source="{REL_PREFIX}/include 11.txt" xml:space="preserve">
+ some text
+"""],
+["""\
+.. include:: /include 11.txt
+ :code:
+""",
+f"""\
+<document source="test data">
+ <literal_block classes="code" source="{REL_PREFIX}/include 11.txt" xml:space="preserve">
+ some text
+"""],
+# search included CSV files using "include-root" setting value
+["""\
+.. CSV-table::
+ :file: /include 11.txt
+""",
+"""\
+<document source="test data">
+ <table>
+ <tgroup cols="1">
+ <colspec colwidth="100">
+ <tbody>
+ <row>
+ <entry>
+ <paragraph>
+ some text
+"""],
+["""\
+.. raw:: txt
+ :file: /include 11.txt
+""",
+f"""\
+<document source="test data">
+ <raw format="txt" source="{REL_PREFIX}/include 11.txt" xml:space="preserve">
+ some text
+"""],
+]
+
+
+if __name__ == '__main__':
+ unittest.main()
Property changes on: trunk/docutils/test/test_parsers/test_rst/test_root_prefix.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Modified: trunk/docutils/test/test_writers/test_html4css1_parts.py
===================================================================
--- trunk/docutils/test/test_writers/test_html4css1_parts.py 2023-11-29 16:57:50 UTC (rev 9491)
+++ trunk/docutils/test/test_writers/test_html4css1_parts.py 2023-11-29 16:58:13 UTC (rev 9492)
@@ -24,7 +24,9 @@
import docutils
import docutils.core
+ROOT_PREFIX = (Path(__file__).parent.parent/'functional'/'input').as_posix()
+
class Html4WriterPublishPartsTestCase(unittest.TestCase):
"""
Test case for HTML writer via the publish_parts interface.
@@ -379,6 +381,20 @@
}],
])
+totest['root_prefix'] = ({'root_prefix': ROOT_PREFIX,
+ 'stylesheet_path': '',
+ 'embed_stylesheet': False}, [
+["""\
+.. image:: /data/blue%20square.png
+ :scale: 100%
+""",
+{'fragment': '''\
+<img alt="/data/blue%20square.png" src="/data/blue%20square.png"\
+ style="width: 32.0px; height: 32.0px;" />\n''',
+}],
+])
+
+
if __name__ == '__main__':
unittest.main()
Modified: trunk/docutils/test/test_writers/test_html5_polyglot_parts.py
===================================================================
--- trunk/docutils/test/test_writers/test_html5_polyglot_parts.py 2023-11-29 16:57:50 UTC (rev 9491)
+++ trunk/docutils/test/test_writers/test_html5_polyglot_parts.py 2023-11-29 16:58:13 UTC (rev 9492)
@@ -25,7 +25,9 @@
import docutils.core
from docutils.utils.code_analyzer import with_pygments
+ROOT_PREFIX = (Path(__file__).parent.parent/'functional'/'input').as_posix()
+
class Html5WriterPublishPartsTestCase(unittest.TestCase):
"""Test case for HTML writer via the publish_parts interface."""
@@ -488,6 +490,26 @@
])
+totest['root_prefix'] = ({'root_prefix': ROOT_PREFIX,
+ 'image_loading': 'embed',
+ 'stylesheet_path': '',
+ 'embed_stylesheet': False}, [
+["""\
+.. image:: /data/blue%20square.png
+ :scale: 100%
+.. figure:: /data/blue%20square.png
+""",
+{'fragment': '''\
+<img alt="/data/blue%20square.png" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAALElEQVR4nO3NMQEAMAjAsDFjvIhHFCbgSwU0kdXvsn96BwAAAAAAAAAAAIsNnEwBk52VRuMAAAAASUVORK5CYII="\
+ style="width: 32.0px; height: 32.0px;" />
+<figure>
+<img alt="/data/blue%20square.png" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAALElEQVR4nO3NMQEAMAjAsDFjvIhHFCbgSwU0kdXvsn96BwAAAAAAAAAAAIsNnEwBk52VRuMAAAAASUVORK5CYII=" />
+</figure>
+''',
+}],
+])
+
+
totest['no_backlinks'] = ({'footnote_backlinks': False,
'stylesheet_path': '',
'embed_stylesheet': False}, [
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2023-11-29 22:11:22
|
Revision: 9494
http://sourceforge.net/p/docutils/code/9494
Author: milde
Date: 2023-11-29 22:11:19 +0000 (Wed, 29 Nov 2023)
Log Message:
-----------
Log "root-prefix" changes. Fix link mismatch in config.txt.
Modified Paths:
--------------
trunk/docutils/HISTORY.txt
trunk/docutils/RELEASE-NOTES.txt
trunk/docutils/docs/user/config.txt
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2023-11-29 22:11:10 UTC (rev 9493)
+++ trunk/docutils/HISTORY.txt 2023-11-29 22:11:19 UTC (rev 9494)
@@ -66,6 +66,12 @@
- Don't split inside "< >" when parsing "option groups" (fixes bug #474).
+* docutils/parsers/rst/directives/misc.py,
+ docutils/parsers/rst/directives/tables.py
+
+ - Consider the root-prefix_ setting when including files with
+ "include", "raw", or "csv-table" directives.
+
* docutils/utils/roman.py
- Update to version `1.4 <https://pypi.org/project/roman/4.1/>`__.
@@ -88,6 +94,8 @@
- New auxiliary function `HTMLTranslator.uri2imagepath()`
ensures the image file can also be read when
CWD and output directory differ.
+ - Consider the root-prefix_ setting when converting an image URI
+ to a local filesystem path.
* docutils/writers/latex2e/__init__.py
@@ -126,7 +134,9 @@
- Warn, if image scaling fails because the image file cannot be read.
+.. _root-prefix: docs/user/config.html#root-prefix
+
Release 0.20.1 (2023-05-17)
===========================
Modified: trunk/docutils/RELEASE-NOTES.txt
===================================================================
--- trunk/docutils/RELEASE-NOTES.txt 2023-11-29 22:11:10 UTC (rev 9493)
+++ trunk/docutils/RELEASE-NOTES.txt 2023-11-29 22:11:19 UTC (rev 9494)
@@ -188,6 +188,13 @@
configuration setting is None, '', 'utf-8-sig', 'utf-16', or 'utf-32'.
Do not remove other ZWNBSPs.
+* Configuration changes:
+
+ - New command line setting root-prefix_.
+ Configurable root directory for included files.
+
+ .. _root-prefix: docs/user/config.html#root-prefix
+
* "html5" writer:
Stop setting the "footnote-reference" class value for footnote references.
You can use the CSS selector ``[role="doc-noteref"]``
Modified: trunk/docutils/docs/user/config.txt
===================================================================
--- trunk/docutils/docs/user/config.txt 2023-11-29 22:11:10 UTC (rev 9493)
+++ trunk/docutils/docs/user/config.txt 2023-11-29 22:11:19 UTC (rev 9494)
@@ -520,7 +520,7 @@
Base directory, prepended to a filesystem path__ starting with "/" when
including files with the "include_", "raw_", or "csv-table_" directives.
-Also applied when a writer converts an image URI to a local filesystem
+Also applied when a writer converts an image URI__ to a local filesystem
path in order to determine the image size or embed the image in the output.
Default: "/" (no change).
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2023-11-30 21:56:03
|
Revision: 9495
http://sourceforge.net/p/docutils/code/9495
Author: milde
Date: 2023-11-30 21:55:47 +0000 (Thu, 30 Nov 2023)
Log Message:
-----------
Small documentation fixes (typos, spelling, wording, DTD changes)
Modified Paths:
--------------
trunk/docutils/HISTORY.txt
trunk/docutils/RELEASE-NOTES.txt
trunk/docutils/docs/ref/doctree.txt
trunk/docutils/docs/ref/rst/directives.txt
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2023-11-29 22:11:19 UTC (rev 9494)
+++ trunk/docutils/HISTORY.txt 2023-11-30 21:55:47 UTC (rev 9495)
@@ -511,6 +511,10 @@
Release 0.18b1 (2021-10-05)
===========================
+* docs/ref/docutils.dtd
+
+ - New document tree element <meta>.
+
* docutils/frontend.py
- The default value for the `auto_id_prefix`_ setting changed to "%":
@@ -705,6 +709,10 @@
.. _pip: https://pypi.org/project/pip/
+* docs/ref/docutils.dtd
+
+ - The "title" attribute of <sidebar> elements is now optional.
+
* docutils/MANIFEST.in
- Exclude test outputs.
@@ -897,6 +905,11 @@
__ https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#escaping-mechanism
+* docs/ref/docutils.dtd
+
+ - Use "parameter entities" for `class names`, `reference names`,
+ and `ids`.
+
* docutils/io.py
- Remove the `handle_io_errors` option from io.FileInput/Output.
@@ -990,6 +1003,10 @@
- Dropped support for Python 2.4, 2.5, 3.1, and 3.2.
- Infrastructure automation.
+* docs/ref/docutils.dtd
+
+ - The <table> element accepts the new attribute "width".
+
* docs/ref/rst/restructuredtext.txt
- Document rST syntax change: Tokens like ``:this:example:`` are now valid
@@ -1173,6 +1190,10 @@
Release 0.13.1 (2016-12-09)
===========================
+* docs/ref/docutils.dtd
+
+ - Add the document tree elements <math> and <math_block> (already in use).
+
* docutils/languages/fa.py
docutils/parsers/rst/languages/fa.py
docutils/languages/la.py
Modified: trunk/docutils/RELEASE-NOTES.txt
===================================================================
--- trunk/docutils/RELEASE-NOTES.txt 2023-11-29 22:11:19 UTC (rev 9494)
+++ trunk/docutils/RELEASE-NOTES.txt 2023-11-30 21:55:47 UTC (rev 9495)
@@ -190,7 +190,7 @@
* Configuration changes:
- - New command line setting root-prefix_.
+ - New configuration setting root-prefix_.
Configurable root directory for included files.
.. _root-prefix: docs/user/config.html#root-prefix
Modified: trunk/docutils/docs/ref/doctree.txt
===================================================================
--- trunk/docutils/docs/ref/doctree.txt 2023-11-29 22:11:19 UTC (rev 9494)
+++ trunk/docutils/docs/ref/doctree.txt 2023-11-30 21:55:47 UTC (rev 9495)
@@ -114,7 +114,7 @@
----------------------
Structural subelements are child elements of structural elements.
-Simple structuctural subelements (title_, subtitle_) contain text
+Simple structural subelements (title_, subtitle_) contain text
data; the others are compound and do not directly contain text data.
Category members: title_, subtitle_, decoration_, docinfo_, meta_,
@@ -708,7 +708,7 @@
reStructuredText source::
- As a great paleontologist once said,
+ As a great palaeontologist once said,
This theory, that is mine, is mine.
@@ -717,7 +717,7 @@
Pseudo-XML_ fragment from simple parsing::
<paragraph>
- As a great paleontologist once said,
+ As a great palaeontologist once said,
<block_quote>
<paragraph>
This theory, that is mine, is mine.
@@ -2247,7 +2247,7 @@
``footnote``
============
-The ``footnote`` element is used for labeled notes_ that provide
+The ``footnote`` element is used for labelled notes_ that provide
additional context to a passage of text (*footnotes* or *endnotes*).
The corresponding footnote mark in running text is set by the
`footnote_reference`_ element.
@@ -2550,7 +2550,7 @@
:Processing:
The specified image is included into the output document.
- Depending on the output format, this is done by refering
+ Depending on the output format, this is done by referring
to the image URI or by embedding the image files content.
:Parents:
@@ -2683,7 +2683,7 @@
``inline`` is analogous to the HTML "span" element.
:Processing:
- Writers typically pass the classes_ attribute to the output document
+ Writers_ typically pass the classes_ attribute to the output document
and leave styling to the backend or a custom stylesheet_. They may
also process the classes_ attribute and convert the ``inline``
element to a specific element or render the content distinctly
@@ -3128,7 +3128,7 @@
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.
+The document's `title attribute`_ stores the metadata document title.
Details
@@ -3845,7 +3845,7 @@
can also be likened to super-footnotes; their content is outside of
the flow of the document's main text.
-The ``sidebar`` element is a nonrecursive section_-like construct
+The ``sidebar`` element is a non-recursive section_-like construct
which may occur at the top level of a section_ wherever a body element
(list, table, etc.) is allowed. In other words, ``sidebar`` elements
cannot nest inside body elements, so you can't have a ``sidebar``
@@ -4363,7 +4363,7 @@
``topic``
=========
-The ``topic`` element is a nonrecursive section_-like construct which
+The ``topic`` element is a non-recursive section_-like construct which
may occur at the top level of a section_ wherever a body element
(list, table, etc.) is allowed. In other words, ``topic`` elements
cannot nest inside body elements, so you can't have a ``topic`` inside
@@ -4849,7 +4849,7 @@
The purpose of the attribute is to indicate an "is-a" variant relationship,
to allow an extensible way of defining sub-classes of existing elements. It
-can be used to carry context forward between a Docutils Reader and Writer,
+can be used to carry context forward between a Docutils Reader_ and Writer_,
when a custom structure is reduced to a standardized document tree. One
common use is in conjunction with stylesheets, to add selection criteria.
It should not be used to carry formatting instructions or arbitrary content.
@@ -4862,8 +4862,10 @@
elements.
.. _"class" directive: rst/directives.html#class
+.. _reader: ../peps/pep-0258.html#readers
+.. _writer:
+.. _writers: ../peps/pep-0258.html#writers
-
``colwidth``
============
Modified: trunk/docutils/docs/ref/rst/directives.txt
===================================================================
--- trunk/docutils/docs/ref/rst/directives.txt 2023-11-29 22:11:19 UTC (rev 9494)
+++ trunk/docutils/docs/ref/rst/directives.txt 2023-11-30 21:55:47 UTC (rev 9495)
@@ -84,7 +84,7 @@
:Directive Options: class_, name_
:Directive Content: Interpreted as body elements.
-Specific admontions are rendered with a title matching the admonition type.
+Specific admonitions are rendered with a title matching the admonition type.
For example::
.. DANGER::
@@ -276,7 +276,7 @@
baseline); they are only useful for inline images (substitutions).
The values "left", "center", and "right" control an image's
horizontal alignment, allowing the image to float and have the
- text flow around it. The specific behavior depends upon the
+ text flow around it. The specific behaviour depends upon the
browser or rendering software used.
``target`` : URI_ or `reference name`_
@@ -336,7 +336,7 @@
``align`` : "left", "center", or "right"
The horizontal alignment of the figure, allowing the image to
- float and have the text flow around it. The specific behavior
+ float and have the text flow around it. The specific behaviour
depends upon the browser or rendering software used.
In addition, the following options are recognized:
@@ -932,7 +932,7 @@
``escape`` : character_
A character used to escape the delimiter_ or quote_ characters from
the CSV parser. The default is no escape character -- fields may
- contain delimiter or newline characers if they are quoted, two quote
+ contain delimiter or newline characters if they are quoted, two quote
characters stand for a literal one, e.g., ``"He said, ""Hi!"""``.
.. Caution:: Setting ``escape`` to ``\`` (backslash) interferes with
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2023-12-01 13:25:43
|
Revision: 9496
http://sourceforge.net/p/docutils/code/9496
Author: milde
Date: 2023-12-01 13:25:40 +0000 (Fri, 01 Dec 2023)
Log Message:
-----------
New image directive option "loading".
The new option sets the `<image>` element's "loading" attribute
to one of "embed", "link", "lazy" as an indication for the
preferred handling of the image by the writer.
Default and actual handling depend on the writer.
Currently only observed by the HTML5 writer, where it overrides the
"image_loading" configuration setting for the respective image.
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/user/config.txt
trunk/docutils/docutils/parsers/rst/directives/images.py
trunk/docutils/docutils/writers/_html_base.py
trunk/docutils/test/functional/expected/misc_rst_html5.html
trunk/docutils/test/functional/expected/standalone_rst_html5.html
trunk/docutils/test/functional/input/data/embed_images.txt
trunk/docutils/test/functional/input/data/html5-features.txt
trunk/docutils/test/test_parsers/test_rst/test_directives/test_figures.py
trunk/docutils/test/test_parsers/test_rst/test_directives/test_images.py
trunk/docutils/test/test_writers/test_html5_polyglot_parts.py
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2023-11-30 21:55:47 UTC (rev 9495)
+++ trunk/docutils/HISTORY.txt 2023-12-01 13:25:40 UTC (rev 9496)
@@ -17,13 +17,19 @@
Changes since 0.20.1
====================
-* Drop support for Python 3.7 and 3.8.
+* General
-* Updated build stystem to use Flit_ (cf. patch #186 by Adam Turner).
- Removed ``setup.py``.
+ - Drop support for Python 3.7 and 3.8.
+ - Updated build stystem to use Flit_ (patch #186 by Adam Turner).
+ Removed ``setup.py``.
+
.. _Flit: https://github.com/pypa/flit/
+* docs/ref/docutils.dtd
+
+ - The <image> element accepts the new attribute "loading".
+
* docutils/io.py
- Simpler and more secure `input encoding`_ default behaviour:
@@ -54,6 +60,10 @@
- Remove compatibility hacks `nodes.reprunicode` and `nodes.ensure_str()`.
+* docutils/parsers/rst/directives/images.py
+
+ - New "image" directive option "loading".
+
* docutils/parsers/rst/directives/tables.py
- Use the same CSV format for the ``:header:`` option and the main data
@@ -96,6 +106,7 @@
CWD and output directory differ.
- Consider the root-prefix_ setting when converting an image URI
to a local filesystem path.
+ - New <image> attribute "loading" overrides "image-loading" setting.
* docutils/writers/latex2e/__init__.py
Modified: trunk/docutils/RELEASE-NOTES.txt
===================================================================
--- trunk/docutils/RELEASE-NOTES.txt 2023-11-30 21:55:47 UTC (rev 9495)
+++ trunk/docutils/RELEASE-NOTES.txt 2023-12-01 13:25:40 UTC (rev 9496)
@@ -188,6 +188,12 @@
configuration setting is None, '', 'utf-8-sig', 'utf-16', or 'utf-32'.
Do not remove other ZWNBSPs.
+* New attribute loading__ for the Docutils doctree node: <image> storing
+ the new "loading" option of the `"image" directive`_.
+
+ __ docs/ref/doctree.html#loading
+ .. _"image" directive: docs/ref/rst/directives.html#image
+
* Configuration changes:
- New configuration setting root-prefix_.
Modified: trunk/docutils/docs/ref/doctree.txt
===================================================================
--- trunk/docutils/docs/ref/doctree.txt 2023-11-30 21:55:47 UTC (rev 9495)
+++ trunk/docutils/docs/ref/doctree.txt 2023-12-01 13:25:40 UTC (rev 9496)
@@ -2563,7 +2563,7 @@
:Attributes:
The ``image`` element contains the `common attributes`_
- plus uri, align_, alt, height_, width_, and scale_.
+ plus uri, alt_, align_, height_, width_, scale_, and loading_.
:Parameter Entities:
The `%body.elements;`_ parameter entity directly includes
@@ -4957,6 +4957,26 @@
The ``ltrim`` attribute is used in the substitution_definition_ element.
+``loading``
+===========
+
+Attribute type: EnumeratedType_, one of "embed", "link", or "lazy".
+Default value: none.
+
+The ``loading`` attribute is used in the image_ element to
+indicate the preferred handling by the Docutils writer_. [#]_
+The default depends on the writer and the image_loading_
+configuration setting.
+
+.. [#] Currently only recognized by the HTML5 writer.
+ The ODF/ODT writer always embeds images in the
+ output document, XML and LaTeX writers link to the image.
+ The behaviour may change for the ODT and XML writers
+ (images cannot be embedded in a LaTeX source).
+
+.. _image_loading: ../user/config.html#image-loading
+
+
``morecols``
============
@@ -5508,7 +5528,6 @@
reference_, revision_, status_, strong_, substitution_definition_,
substitution_reference_, subtitle_, target_, term_, title_, version_
-
..
Local Variables:
Modified: trunk/docutils/docs/ref/docutils.dtd
===================================================================
--- trunk/docutils/docs/ref/docutils.dtd 2023-11-30 21:55:47 UTC (rev 9495)
+++ trunk/docutils/docs/ref/docutils.dtd 2023-12-01 13:25:40 UTC (rev 9496)
@@ -563,7 +563,8 @@
alt CDATA #IMPLIED
height %measure; #IMPLIED
width %measure; #IMPLIED
- scale %number; #IMPLIED>
+ scale %number; #IMPLIED
+ loading (embed | link | lazy) #IMPLIED>
<!ELEMENT caption %text.model;>
<!ATTLIST caption %basic.atts;>
Modified: trunk/docutils/docs/ref/rst/directives.txt
===================================================================
--- trunk/docutils/docs/ref/rst/directives.txt 2023-11-30 21:55:47 UTC (rev 9495)
+++ trunk/docutils/docs/ref/rst/directives.txt 2023-12-01 13:25:40 UTC (rev 9496)
@@ -213,6 +213,7 @@
:Directive Arguments: one, required (image URI_)
:Directive Options: `see below <image options_>`__
:Directive Content: none
+:Configuration Setting: image_loading_ (only `HTML5 writer`_)
An "image" is a simple picture::
@@ -236,6 +237,7 @@
:height: 100px
:width: 200 px
:scale: 50 %
+ :loading: embed
:alt: alternate text
:align: right
@@ -284,7 +286,30 @@
option argument may be a URI (relative or absolute), or a
`reference name`_ with underscore suffix (e.g. ```a name`_``).
+``loading`` : ["embed", "link", "lazy"]
+ Indicate the preferred handling by the Docutils Writer. [#]_
+ :embed: Embed the image into the output document.
+ :link: Refer to the image via its URI.
+ :lazy: Refer to the image. The HTML5 writer additionally
+ specifies the `lazy loading attribute`_.
+
+ (New in Docutils 0.21.)
+
+.. [#] Currently only recognized by the `HTML5 writer`_
+ (overriding the `image_loading`_ configuration setting).
+ The ODF/ODT writer always embeds images in the
+ ``*.odt`` document, XML and LaTeX writers link to the image.
+ The behaviour may change for the ODT and XML writers but
+ images cannot be embedded in a LaTeX source.
+
+.. _image element: ../doctree.html#image
+.. _"loading" attribute: ../doctree.html#loading
+.. _image_loading: ../../user/config.html#image-loading
+.. _lazy loading attribute: https://html.spec.whatwg.org/multipage/
+ urls-and-fetching.html#lazy-loading-attributes
+
+
Figure
======
Modified: trunk/docutils/docs/user/config.txt
===================================================================
--- trunk/docutils/docs/user/config.txt 2023-11-30 21:55:47 UTC (rev 9495)
+++ trunk/docutils/docs/user/config.txt 2023-12-01 13:25:40 UTC (rev 9496)
@@ -1088,7 +1088,7 @@
initial_header_level
~~~~~~~~~~~~~~~~~~~~
-The initial level for header elements. This does not affect the
+The initial level for section header elements. This does not affect the
document title & subtitle; see doctitle_xform_.
Default: writer dependent (see `[html4css1 writer]`_, `[html5 writer]`_,
@@ -1424,18 +1424,24 @@
"""""""""""""
Indicate at which point images should be loaded.
+Overridden by the `"image" directive`_'s ``:loading:`` option.
+
Supported values:
+ embed:
+ Embed images into the HTML document
+ (ignored for videos).
+ link:
+ Refer to images in the HTML document (default).
+ lazy:
+ Refer to images. Additionally specify the
+ `lazy loading attribute`_ to defer fetching the image.
-:embed: Embed images into the HTML document
- (ignored for videos).
-:link: Refer to images in the HTML document (default).
-:lazy: Refer to images. Additionally specify the `lazy loading attribute`_
- to defer fetching the image.
Default: "link". Option: ``--image-loading``.
New in Docutils 0.18.
+.. _"image" directive: ../ref/rst/directives.html#image
.. _lazy loading attribute: https://html.spec.whatwg.org/multipage/
urls-and-fetching.html#lazy-loading-attributes
Modified: trunk/docutils/docutils/parsers/rst/directives/images.py
===================================================================
--- trunk/docutils/docutils/parsers/rst/directives/images.py 2023-11-30 21:55:47 UTC (rev 9495)
+++ trunk/docutils/docutils/parsers/rst/directives/images.py 2023-12-01 13:25:40 UTC (rev 9496)
@@ -32,13 +32,18 @@
align_h_values = ('left', 'center', 'right')
align_v_values = ('top', 'middle', 'bottom')
align_values = align_v_values + align_h_values
+ loading_values = ('embed', 'link', 'lazy')
def align(argument):
- # This is not callable as self.align. We cannot make it a
+ # This is not callable as `self.align()`. We cannot make it a
# staticmethod because we're saving an unbound method in
# option_spec below.
return directives.choice(argument, Image.align_values)
+ def loading(argument):
+ # This is not callable as `self.loading()` (see above).
+ return directives.choice(argument, Image.loading_values)
+
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
@@ -48,6 +53,7 @@
'scale': directives.percentage,
'align': align,
'target': directives.unchanged_required,
+ 'loading': loading,
'class': directives.class_option,
'name': directives.unchanged}
Modified: trunk/docutils/docutils/writers/_html_base.py
===================================================================
--- trunk/docutils/docutils/writers/_html_base.py 2023-11-30 21:55:47 UTC (rev 9495)
+++ trunk/docutils/docutils/writers/_html_base.py 2023-12-01 13:25:40 UTC (rev 9496)
@@ -1033,6 +1033,7 @@
def visit_image(self, node):
uri = node['uri']
+ alt = node.get('alt', uri)
uri_parts = urllib.parse.urlparse(uri)
imagepath = ''
mimetype = mimetypes.guess_type(uri)[0]
@@ -1095,6 +1096,7 @@
del atts[att_name]
if style:
atts['style'] = ' '.join(style)
+
# No newlines around inline images or if surrounded by <a>...</a>.
if (isinstance(node.parent, nodes.TextElement)
or (isinstance(node.parent, nodes.reference)
@@ -1103,20 +1105,16 @@
else:
suffix = '\n'
- # moving image -> use <video>
+ # ``:loading:`` option (embed, link, lazy)
+ # get default from config setting
+ # exception: only embed videos if told via directive option
if mimetype in self.videotypes:
- fallback = node.get('alt', uri)
- atts['title'] = fallback
- if 'controls' in node['classes']:
- node['classes'].remove('controls')
- atts['controls'] = 'controls'
- self.body.append(
- self.starttag(node, "video", suffix, src=uri, **atts)
- + f'<a href="{uri}">{fallback}</a>{suffix}</video>{suffix}')
- return
+ loading = 'link'
+ else:
+ loading = getattr(self.settings, 'image_loading', 'link')
+ loading = node.get('loading', loading)
- # Embed image file (embedded SVG or data URI):
- if self.image_loading == 'embed':
+ if loading == 'embed':
if uri_parts.scheme not in ('', 'file'):
self.document.reporter.error(
f'Cannot embed remote image "{uri}"')
@@ -1129,24 +1127,31 @@
self.document.reporter.error('Cannot embed image %r: %s'
% (uri, err.strerror))
else:
- self.settings.record_dependencies.add(
- urllib.parse.unquote(uri))
+ self.settings.record_dependencies.add(imagepath)
# TODO: insert SVG as-is?
# if mimetype == 'image/svg+xml':
# read/parse, apply arguments,
# insert as <svg ....> ... </svg> # (about 1/3 less data)
data64 = base64.b64encode(imagedata).decode()
- uri = 'data:%s;base64,%s' % (mimetype, data64)
- elif self.image_loading == 'lazy':
+ uri = f'data:{mimetype};base64,{data64}'
+ elif loading == 'lazy':
atts['loading'] = 'lazy'
- if mimetype == 'application/x-shockwave-flash':
+ if mimetype in self.videotypes:
+ atts['title'] = alt
+ alt_link = node['uri'] # use original URI also when embedding
+ if 'controls' in node['classes']:
+ node['classes'].remove('controls')
+ atts['controls'] = 'controls'
+ tag = (self.starttag(node, "video", suffix, src=uri, **atts)
+ + f'<a href="{alt_link}">{alt}</a>{suffix}</video>{suffix}')
+ elif mimetype == 'application/x-shockwave-flash':
atts['type'] = mimetype
# do NOT use an empty tag: incorrect rendering in browsers
tag = (self.starttag(node, 'object', '', data=uri, **atts)
- + node.get('alt', uri) + '</object>' + suffix)
+ + alt + '</object>' + suffix)
else:
- atts['alt'] = node.get('alt', node['uri'])
+ atts['alt'] = alt
tag = self.emptytag(node, 'img', suffix, src=uri, **atts)
self.body.append(tag)
Modified: trunk/docutils/test/functional/expected/misc_rst_html5.html
===================================================================
--- trunk/docutils/test/functional/expected/misc_rst_html5.html 2023-11-30 21:55:47 UTC (rev 9495)
+++ trunk/docutils/test/functional/expected/misc_rst_html5.html 2023-12-01 13:25:40 UTC (rev 9496)
@@ -119,6 +119,9 @@
</figcaption>
</figure>
<p>Embedded inline image <img alt="inline-embedded" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABGdBTUEAANkE3LLaAgAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAAZQTFRF////AAAAVcLTfgAAAAF0Uk5TAEDm2GYAAAA2SURBVHicYmBRYOAQYJCQYJC+wSBjAUL2fxjq6hgueTNM7AQh3g0MzAdAiP0BUBYAAAD//wMA4pkLDrFBDzUAAAAASUVORK5CYII=" style="height: 0.8em;" /> scaled to a height of 0.8 em.</p>
+<img alt="../../../docs/user/rst/images/biohazard.svg" class="align-left" loading="lazy" src="../../../docs/user/rst/images/biohazard.svg" style="width: 2em; height: 2em;" />
+<p>The <span class="docutils literal">:loading:</span> option of <a class="reference external" href="https://docutils.sourceforge.io/docs/ref/rst/directives.html#images">image and figure directives</a> overrides the
+<a class="reference external" href="https://docutils.sourceforge.io/docs/user/config.html#image-loading">image_loading</a> setting for the respective image.</p>
</section>
<section id="moving-images-video">
<h2><a class="toc-backref" href="#contents" role="doc-backlink">Moving images (video)</a><a class="self-link" title="link to this section" href="#moving-images-video"></a></h2>
Modified: trunk/docutils/test/functional/expected/standalone_rst_html5.html
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_html5.html 2023-11-30 21:55:47 UTC (rev 9495)
+++ trunk/docutils/test/functional/expected/standalone_rst_html5.html 2023-12-01 13:25:40 UTC (rev 9496)
@@ -142,7 +142,7 @@
<li><p><a class="reference internal" href="#custom-roles" id="toc-entry-42"><span class="sectnum">2.23 </span>Custom Roles</a></p></li>
</ul>
</li>
-<li><p><a class="reference internal" href="#changes-to-the-html4css1-writer" id="toc-entry-43"><span class="sectnum">3 </span>Changes to the <cite>html4css1</cite> Writer</a></p>
+<li><p><a class="reference internal" href="#differences-to-the-html4css1-writer" id="toc-entry-43"><span class="sectnum">3 </span>Differences to the <cite>html4css1</cite> Writer</a></p>
<ul class="auto-toc">
<li><p><a class="reference internal" href="#field-list-rendering" id="toc-entry-44"><span class="sectnum">3.1 </span>Field List Rendering</a></p></li>
<li><p><a class="reference internal" href="#styling-with-class-arguments" id="toc-entry-45"><span class="sectnum">3.2 </span>Styling with Class Arguments</a></p>
@@ -194,7 +194,7 @@
(<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="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="brackets" href="#footnote-7" id="footnote-reference-26" 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="brackets" href="#footnote-13" id="footnote-reference-27" role="doc-noteref"><span class="fn-bracket">[</span>13<span class="fn-bracket">]</span></a>), footnote references (manually
+references</a> <a class="brackets" href="#footnote-7" id="footnote-reference-27" 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="brackets" href="#footnote-14" id="footnote-reference-28" role="doc-noteref"><span class="fn-bracket">[</span>14<span class="fn-bracket">]</span></a>), footnote references (manually
numbered <a class="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="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="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="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" /> &
@@ -575,7 +575,7 @@
</ul>
</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="brackets" href="#footnote-14" id="footnote-reference-28" role="doc-noteref"><span class="fn-bracket">[</span>14<span class="fn-bracket">]</span></a>.</p>
+others, please see <a class="reference external" href="https://docutils.sourceforge.io/docs/ref/rst/directives.html">reStructuredText Directives</a> <a class="brackets" href="#footnote-15" id="footnote-reference-29" role="doc-noteref"><span class="fn-bracket">[</span>15<span class="fn-bracket">]</span></a>.</p>
<section id="document-parts">
<h4><a class="toc-backref" href="#toc-entry-55" role="doc-backlink"><span class="sectnum">2.14.1 </span>Document Parts</a></h4>
<p>An example of the "contents" directive can be seen above this section
@@ -836,7 +836,7 @@
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="footnote-7" role="doc-footnote">
<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-18">1</a>,<a role="doc-backlink" href="#footnote-reference-19">2</a>,<a role="doc-backlink" href="#footnote-reference-20">3</a>,<a role="doc-backlink" href="#footnote-reference-26">4</a>)</span>
+<span class="backrefs">(<a role="doc-backlink" href="#footnote-reference-18">1</a>,<a role="doc-backlink" href="#footnote-reference-19">2</a>,<a role="doc-backlink" href="#footnote-reference-20">3</a>,<a role="doc-backlink" href="#footnote-reference-27">4</a>)</span>
<p><a class="reference external" href="http://www.python.org/">http://www.python.org/</a></p>
</aside>
<aside class="footnote brackets" id="footnote-8" role="doc-footnote">
@@ -845,46 +845,50 @@
</aside>
<aside class="footnote brackets" id="footnote-9" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-22">9</a><span class="fn-bracket">]</span></span>
-<p><a class="reference external" href="https://www.w3.org/TR/html52/interactive-elements.html#the-details-element">https://www.w3.org/TR/html52/interactive-elements.html#the-details-element</a></p>
+<p><a class="reference external" href="https://docutils.sourceforge.io/docs/user/config.html#image-loading">https://docutils.sourceforge.io/docs/user/config.html#image-loading</a></p>
</aside>
<aside class="footnote brackets" id="footnote-10" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-23">10</a><span class="fn-bracket">]</span></span>
-<p><a class="reference external" href="https://docutils.sourceforge.io/docs/user/config.html#table-style">https://docutils.sourceforge.io/docs/user/config.html#table-style</a></p>
+<p><a class="reference external" href="https://www.w3.org/TR/html52/interactive-elements.html#the-details-element">https://www.w3.org/TR/html52/interactive-elements.html#the-details-element</a></p>
</aside>
<aside class="footnote brackets" id="footnote-11" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-24">11</a><span class="fn-bracket">]</span></span>
-<p><a class="reference external" href="http://tug.ctan.org/tex-archive/macros/latex/contrib/booktabs/booktabs.pdf">http://tug.ctan.org/tex-archive/macros/latex/contrib/booktabs/booktabs.pdf</a></p>
+<p><a class="reference external" href="https://docutils.sourceforge.io/docs/user/config.html#table-style">https://docutils.sourceforge.io/docs/user/config.html#table-style</a></p>
</aside>
<aside class="footnote brackets" id="footnote-12" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-25">12</a><span class="fn-bracket">]</span></span>
-<p><a class="reference external" href="https://docutils.sourceforge.io/docs/dev/todo.html#interpreted-text">https://docutils.sourceforge.io/docs/dev/todo.html#interpreted-text</a></p>
+<p><a class="reference external" href="http://tug.ctan.org/tex-archive/macros/latex/contrib/booktabs/booktabs.pdf">http://tug.ctan.org/tex-archive/macros/latex/contrib/booktabs/booktabs.pdf</a></p>
</aside>
<aside class="footnote brackets" id="footnote-13" role="doc-footnote">
-<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-27">13</a><span class="fn-bracket">]</span></span>
-<p><a class="reference external" href="https://docutils.sourceforge.io/">https://docutils.sourceforge.io/</a></p>
+<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-26">13</a><span class="fn-bracket">]</span></span>
+<p><a class="reference external" href="https://docutils.sourceforge.io/docs/dev/todo.html#interpreted-text">https://docutils.sourceforge.io/docs/dev/todo.html#interpreted-text</a></p>
</aside>
<aside class="footnote brackets" id="footnote-14" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-28">14</a><span class="fn-bracket">]</span></span>
-<p><a class="reference external" href="https://docutils.sourceforge.io/docs/ref/rst/directives.html">https://docutils.sourceforge.io/docs/ref/rst/directives.html</a></p>
+<p><a class="reference external" href="https://docutils.sourceforge.io/">https://docutils.sourceforge.io/</a></p>
</aside>
<aside class="footnote brackets" id="footnote-15" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-29">15</a><span class="fn-bracket">]</span></span>
-<p><a class="reference external" href="https://docutils.sourceforge.io/docs/ref/rst/directives.html#metadata">https://docutils.sourceforge.io/docs/ref/rst/directives.html#metadata</a></p>
+<p><a class="reference external" href="https://docutils.sourceforge.io/docs/ref/rst/directives.html">https://docutils.sourceforge.io/docs/ref/rst/directives.html</a></p>
</aside>
<aside class="footnote brackets" id="footnote-16" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-30">16</a><span class="fn-bracket">]</span></span>
-<p><a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag">https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag</a></p>
+<p><a class="reference external" href="https://docutils.sourceforge.io/docs/ref/rst/directives.html#metadata">https://docutils.sourceforge.io/docs/ref/rst/directives.html#metadata</a></p>
</aside>
<aside class="footnote brackets" id="footnote-17" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-31">17</a><span class="fn-bracket">]</span></span>
-<p><a class="reference external" href="https://stackoverflow.com/questions/39547412/same-font-size-for-h1-and-h2-in-article">https://stackoverflow.com/questions/39547412/same-font-size-for-h1-and-h2-in-article</a></p>
+<p><a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag">https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag</a></p>
</aside>
<aside class="footnote brackets" id="footnote-18" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-32">18</a><span class="fn-bracket">]</span></span>
-<p><a class="reference external" href="https://html.spec.whatwg.org/#text-level-semantics">https://html.spec.whatwg.org/#text-level-semantics</a></p>
+<p><a class="reference external" href="https://stackoverflow.com/questions/39547412/same-font-size-for-h1-and-h2-in-article">https://stackoverflow.com/questions/39547412/same-font-size-for-h1-and-h2-in-article</a></p>
</aside>
<aside class="footnote brackets" id="footnote-19" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-33">19</a><span class="fn-bracket">]</span></span>
+<p><a class="reference external" href="https://html.spec.whatwg.org/#text-level-semantics">https://html.spec.whatwg.org/#text-level-semantics</a></p>
+</aside>
+<aside class="footnote brackets" id="footnote-20" role="doc-footnote">
+<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#footnote-reference-34">20</a><span class="fn-bracket">]</span></span>
<p><a class="reference external" href="https://html.spec.whatwg.org/multipage/edits.html">https://html.spec.whatwg.org/multipage/edits.html</a></p>
</aside>
</aside>
@@ -1036,7 +1040,7 @@
</section>
<section id="meta">
<h4><a class="toc-backref" href="#toc-entry-65" role="doc-backlink"><span class="sectnum">2.14.11 </span>Meta</a></h4>
-<p>The <a class="reference external" href="https://docutils.sourceforge.io/docs/ref/rst/directives.html#metadata">“meta” directive</a> <a class="brackets" href="#footnote-15" id="footnote-reference-29" role="doc-noteref"><span class="fn-bracket">[</span>15<span class="fn-bracket">]</span></a> is used to specify metadata to be stored in,
+<p>The <a class="reference external" href="https://docutils.sourceforge.io/docs/ref/rst/directives.html#metadata">“meta” directive</a> <a class="brackets" href="#footnote-16" id="footnote-reference-30" role="doc-noteref"><span class="fn-bracket">[</span>16<span class="fn-bracket">]</span></a> is used to specify metadata to be stored in,
e.g., HTML META tags or ODT file properties.</p>
</section>
</section>
@@ -1251,13 +1255,13 @@
</ul>
</section>
</section>
-<section id="changes-to-the-html4css1-writer">
-<h2><a class="toc-backref" href="#toc-entry-43" role="doc-backlink"><span class="sectnum">3 </span>Changes to the <cite>html4css1</cite> Writer</a></h2>
+<section id="differences-to-the-html4css1-writer">
+<h2><a class="toc-backref" href="#toc-entry-43" role="doc-backlink"><span class="sectnum">3 </span>Differences to the <cite>html4css1</cite> Writer</a></h2>
<ul>
<li><p>Use only <a class="reference internal" href="#meta">meta</a> keywords recognized by HTML 5.
Add HTML5-compatible meta tags for docinfo items
"authors", "date", and "copyright".</p>
-<p>Add a <a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_...
[truncated message content] |
|
From: <mi...@us...> - 2023-12-06 20:48:45
|
Revision: 9497
http://sourceforge.net/p/docutils/code/9497
Author: milde
Date: 2023-12-06 20:48:38 +0000 (Wed, 06 Dec 2023)
Log Message:
-----------
Validate and fix `docutils XML` output.
Fix "xml" writer:
The <meta> element must be empty (no whitespace allowed inside).
Fix definition of <meta> in the DTD.
<meta> does *not* take the basic attributes, instead a long list
of custom ones similar to it's HTML role model.
Modified Paths:
--------------
trunk/docutils/docs/dev/testing.txt
trunk/docutils/docs/ref/docutils.dtd
trunk/docutils/docutils/writers/docutils_xml.py
trunk/docutils/test/functional/expected/standalone_rst_docutils_xml.xml
Modified: trunk/docutils/docs/dev/testing.txt
===================================================================
--- trunk/docutils/docs/dev/testing.txt 2023-12-01 13:25:40 UTC (rev 9496)
+++ trunk/docutils/docs/dev/testing.txt 2023-12-06 20:48:38 UTC (rev 9497)
@@ -286,9 +286,5 @@
``functional/expected/`` (overwriting the old expected output), and
commit the change.
-.. [#] The validity of `Docutils XML` can be tested with
- ``xmllint <document-referencing-local-Docutils-DTD>.xml --valid --noout``.
-
- .. note: the ``--dtdvalid`` and ``--nonet`` options do not help override
- a reference to the PUBLIC "docutils.dtd" if there is a local version
- on the system (e.g. /usr/share/xml/docutils/docutils.dtd in Debian).
+.. [#] `Docutils XML` can be validated with
+ ``xmllint --dtdvalid docs/ref/docutils.dtd --noout *.xml``.
Modified: trunk/docutils/docs/ref/docutils.dtd
===================================================================
--- trunk/docutils/docs/ref/docutils.dtd 2023-12-01 13:25:40 UTC (rev 9496)
+++ trunk/docutils/docs/ref/docutils.dtd 2023-12-06 20:48:38 UTC (rev 9497)
@@ -132,7 +132,7 @@
resolve to either an internal or external reference.
-->
<!ENTITY % refname.att
- " refname %refname.type; #IMPLIED ">
+ " refname %refname.type; #IMPLIED ">
<!ENTITY % additional.reference.atts "">
<!-- Collected hyperlink reference attributes. -->
@@ -167,8 +167,7 @@
<!ENTITY % additional.bibliographic.elements "">
<!ENTITY % bibliographic.elements
" author | authors | organization | address | contact
- | version | revision | status | date | copyright
- | field
+ | version | revision | status | date | copyright | field
%additional.bibliographic.elements; ">
<!ENTITY % additional.section.elements "">
@@ -227,7 +226,7 @@
<!-- These parameter entities customize the table model DTD. -->
<!ENTITY % bodyatt " %basic.atts; "> <!-- table elt -->
<!-- 1 colspec element is expected per table column: -->
-<!ENTITY % tbl.tgroup.mdl "colspec+,thead?,tbody">
+<!ENTITY % tbl.tgroup.mdl "colspec+,thead?,tbody">
<!ENTITY % tbl.tgroup.att " %basic.atts; ">
<!ENTITY % tbl.thead.att " %basic.atts; ">
<!ENTITY % tbl.tbody.att " %basic.atts; ">
@@ -253,7 +252,7 @@
<!-- Optional elements may be generated by internal processing. -->
<!ELEMENT document
( (title, subtitle?)?,
- meta?,
+ meta*,
decoration?,
(docinfo, transition?)?,
%structure.model; )>
@@ -323,9 +322,17 @@
<!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;>
+<!-- Container for "hidden" meta-data. Attributes follow HTML -->
+<!ELEMENT meta EMPTY>
+<!ATTLIST meta
+ name NMTOKEN #IMPLIED
+ content CDATA #REQUIRED
+ http-equiv CDATA #IMPLIED
+ scheme CDATA #IMPLIED
+ lang CDATA #IMPLIED
+ dir (ltr | rtl | auto) #IMPLIED
+ media CDATA #IMPLIED
+ >
<!--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Modified: trunk/docutils/docutils/writers/docutils_xml.py
===================================================================
--- trunk/docutils/docutils/writers/docutils_xml.py 2023-12-01 13:25:40 UTC (rev 9496)
+++ trunk/docutils/docutils/writers/docutils_xml.py 2023-12-06 20:48:38 UTC (rev 9497)
@@ -111,7 +111,7 @@
# generic visit and depart methods
# --------------------------------
- simple_nodes = (nodes.TextElement,
+ simple_nodes = (nodes.TextElement, nodes.meta,
nodes.image, nodes.colspec, nodes.transition)
def default_visit(self, node):
Modified: trunk/docutils/test/functional/expected/standalone_rst_docutils_xml.xml
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_docutils_xml.xml 2023-12-01 13:25:40 UTC (rev 9496)
+++ trunk/docutils/test/functional/expected/standalone_rst_docutils_xml.xml 2023-12-06 20:48:38 UTC (rev 9497)
@@ -4,10 +4,8 @@
<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>
+ <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>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2023-12-06 20:48:55
|
Revision: 9498
http://sourceforge.net/p/docutils/code/9498
Author: milde
Date: 2023-12-06 20:48:52 +0000 (Wed, 06 Dec 2023)
Log Message:
-----------
New CSS stylesheet for italic field names in field-lists.
The current default are bold field names.
However, in many contexts bold names are too heavy.
The additional stylesheet is a backwards-compatible way to
get better looking documentation. See docutils.conf for usage.
Modified Paths:
--------------
trunk/docutils/docutils/writers/html5_polyglot/responsive.css
trunk/docutils/docutils.conf
Added Paths:
-----------
trunk/docutils/docutils/writers/html5_polyglot/italic-field-names.css
Added: trunk/docutils/docutils/writers/html5_polyglot/italic-field-names.css
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/italic-field-names.css (rev 0)
+++ trunk/docutils/docutils/writers/html5_polyglot/italic-field-names.css 2023-12-06 20:48:52 UTC (rev 9498)
@@ -0,0 +1,26 @@
+/* italic-field-name.css: */
+/* Alternative style for Docutils field-lists */
+
+/* :Copyright: © 2023 Günter Milde. */
+/* :License: Released under the terms of the `2-Clause BSD license`_, */
+/* in short: */
+/* */
+/* Copying and distribution of this file, with or without modification, */
+/* are permitted in any medium without royalty provided the copyright */
+/* notice and this notice are preserved. */
+/* */
+/* This file is offered as-is, without any warranty. */
+/* */
+/* .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause */
+
+/* In many contexts, a **bold** field name is too heavy styling. */
+/* Use *italic* instead:: */
+
+dl.field-list > dt {
+ font-weight: normal;
+ font-style: italic;
+}
+dl.field-list > dt > .colon {
+ font-style: normal;
+ padding-left: 0.05ex;
+}
Property changes on: trunk/docutils/docutils/writers/html5_polyglot/italic-field-names.css
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Modified: trunk/docutils/docutils/writers/html5_polyglot/responsive.css
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/responsive.css 2023-12-06 20:48:38 UTC (rev 9497)
+++ trunk/docutils/docutils/writers/html5_polyglot/responsive.css 2023-12-06 20:48:52 UTC (rev 9498)
@@ -131,6 +131,10 @@
/* Lists */
+dl.field-list.narrow, dl.docinfo, dl.option-list {
+ --field-indent: 2.4em;
+}
+
ul, ol {
padding-left: 1.1em; /* indent by bullet width (Firefox, DejaVu fonts) */
}
@@ -389,9 +393,6 @@
body {
--field-indent: 4em;
}
- dl.field-list.narrow, dl.docinfo, dl.option-list {
- --field-indent: 2.4em;
- }
pre, pre * {
font-size: 0.9em;
/* overflow: auto; */
Modified: trunk/docutils/docutils.conf
===================================================================
--- trunk/docutils/docutils.conf 2023-12-06 20:48:38 UTC (rev 9497)
+++ trunk/docutils/docutils.conf 2023-12-06 20:48:52 UTC (rev 9498)
@@ -16,7 +16,7 @@
math-output: MathML
# MathML will become the default for HTML5 in Docutils 0.22
stylesheet-dirs: docutils/writers/html5_polyglot/
-stylesheet-path: minimal.css, responsive.css
+stylesheet-path: minimal.css, responsive.css, italic-field-names.css
section-self-link: yes
table-style: colwidths-grid
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2023-12-06 20:49:11
|
Revision: 9499
http://sourceforge.net/p/docutils/code/9499
Author: milde
Date: 2023-12-06 20:49:08 +0000 (Wed, 06 Dec 2023)
Log Message:
-----------
Documentation revision.
Use `<...>` notation for Document Tree elements
(similar to the [MDN](https://developer.mozilla.org/docs/Web/HTML)).
Format RELEASE NOTES for more consistency.
Less section nesting in "config" doc.
The `<h6>` section headings came out in smaller font size that the main text
with the standard firefox and chromium style sheets.
Small fixes and additions.
Modified Paths:
--------------
trunk/docutils/RELEASE-NOTES.txt
trunk/docutils/docs/index.txt
trunk/docutils/docs/ref/doctree.txt
trunk/docutils/docs/ref/rst/restructuredtext.txt
trunk/docutils/docs/ref/rst/roles.txt
trunk/docutils/docs/user/config.txt
trunk/docutils/docs/user/html.txt
trunk/docutils/docs/user/latex.txt
trunk/docutils/docs/user/todo-lists.txt
trunk/docutils/docs/user/tools.txt
Modified: trunk/docutils/RELEASE-NOTES.txt
===================================================================
--- trunk/docutils/RELEASE-NOTES.txt 2023-12-06 20:48:52 UTC (rev 9498)
+++ trunk/docutils/RELEASE-NOTES.txt 2023-12-06 20:49:08 UTC (rev 9499)
@@ -161,18 +161,20 @@
Release 0.21 (unpublished)
==========================
-* Drop support for Python 3.7 and 3.8.
+* General:
-* Provide ``rst2*`` "console_scripts" `entry points`_
- (without the ``.py`` extension) instead of installing the
- ``rst2*.py`` `front end tools`_ in the binary PATH. [#]_
+ - Drop support for Python 3.7 and 3.8.
- Exceptions: ``rstpep2html.py`` and ``rst2odt_prepstyles.py``:
+ - Provide ``rst2*`` "console_scripts" `entry points`_
+ (without the ``.py`` extension) instead of installing the
+ ``rst2*.py`` `front end tools`_ in the binary PATH. [#]_
- - Use ``docutils --reader=pep --writer=pep_html`` for a PEP preview. [#]_
- - Use ``python -m docutils.writers.odf_odt.prepstyles``
- to `strip the page size`__ from an ODT writer stylesheet.
+ Exceptions: ``rstpep2html.py`` and ``rst2odt_prepstyles.py``:
+ - Use ``docutils --reader=pep --writer=pep_html`` for a PEP preview. [#]_
+ - Use ``python -m docutils.writers.odf_odt.prepstyles``
+ to `strip the page size`__ from an ODT writer stylesheet.
+
__ docs/user/odt.html#page-size
.. [#] Some Linux distributions already use the short names.
@@ -179,20 +181,15 @@
.. [#] The final rendering is done by a Sphinx-based build system
(cf. :PEP:`676`).
-* Simpler and more secure `input encoding`_ default behaviour:
+* reStructuredText:
- Do not use the locale encoding as fallback if Python is started in
- `UTF-8 mode`_. Stop using "latin1" as second fallback.
+ - Use the same CSV format for the ``:header:`` option and the main data
+ of the "csv-table_" directive.
- Remove BOM (U+FEFF ZWNBSP at start of data) only if the `input_encoding`_
- configuration setting is None, '', 'utf-8-sig', 'utf-16', or 'utf-32'.
- Do not remove other ZWNBSPs.
+ - New option "loading" for the `"image" directive`_.
+ Sets the new attribute loading__ of the <image> doctree element.
-* New attribute loading__ for the Docutils doctree node: <image> storing
- the new "loading" option of the `"image" directive`_.
-
__ docs/ref/doctree.html#loading
- .. _"image" directive: docs/ref/rst/directives.html#image
* Configuration changes:
@@ -199,28 +196,51 @@
- New configuration setting root-prefix_.
Configurable root directory for included files.
- .. _root-prefix: docs/user/config.html#root-prefix
+ - Simpler and more secure `input encoding`_ default behaviour:
-* "html5" writer:
- Stop setting the "footnote-reference" class value for footnote references.
- You can use the CSS selector ``[role="doc-noteref"]``
- since Docutils 0.18 (see minimal.css for examples).
+ Do not use the locale encoding as fallback if Python is started in
+ `UTF-8 mode`_. Stop using "latin1" as second fallback.
-* Use the same CSV format for the ``:header:`` option and the main data
- of the "csv-table_" directive.
+ Remove BOM (U+FEFF ZWNBSP at start of data) only if the `input_encoding`_
+ configuration setting is None, '', 'utf-8-sig', 'utf-16', or 'utf-32'.
+ Do not remove other ZWNBSPs.
+* Output changes:
+
+ HTML5:
+ Stop setting the "footnote-reference" class value for footnote
+ references. Use the CSS selector ``[role="doc-noteref"]``
+ (works since Docutils 0.18, see minimal.css for examples).
+
* Removed objects:
- - `nodes.reprunicode` and `nodes.ensure_str()`
- (not required with Python 3),
- `utils.Reporter.set_conditions()` (obsolete)
- `core.Publisher.setup_option_parser()` (internal, obsolete)
+ `docutils.nodes.reprunicode`, `docutils.nodes.ensure_str()`
+ Python 2 compatibility hacks
+ `docutils.utils.Reporter.set_conditions()`
+ obsolete
+ `docutils.core.Publisher.setup_option_parser()`
+ internal, obsolete
- - File ``install.py``. See README.txt__ for alternatives.
+* New files:
+ ``docutils/writers/html5_polyglot/italic-field-names.css``
+ Alternative style for Docutils field-lists.
+
+* Removed files:
+
+ ``install.py``, ``setup.py``
+ Metadata is now stored in ``pyproject.toml``,
+ supported by pip_ since version 19.0 (2019-01-22).
+ See README__ for installation alternatives.
+
+ __ README.html#installation
+
+* Bugfixes and improvements (see HISTORY_).
+
.. _input encoding: docs/api/publisher.html#encodings
.. _csv-table: docs/ref/rst/directives.html#csv-table
-__ README.html#installation
+.. _"image" directive: docs/ref/rst/directives.html#image
+.. _root-prefix: docs/user/config.html#root-prefix
Release 0.20.1 (2023-05-17)
Modified: trunk/docutils/docs/index.txt
===================================================================
--- trunk/docutils/docs/index.txt 2023-12-06 20:48:52 UTC (rev 9498)
+++ trunk/docutils/docs/index.txt 2023-12-06 20:49:08 UTC (rev 9499)
@@ -14,7 +14,7 @@
.. _Docutils distribution: https://docutils.sourceforge.io/#download
.. header::
- Docutils_ | Overview | About__ | Users__ | Reference__ | Developers__
+ Docutils_ | Overview | About__ | Users__ | Reference__ | API_ | Developers__
.. _Docutils: https://docutils.sourceforge.io/
__ `project fundamentals`_
@@ -26,70 +26,64 @@
.. contents::
-Project Fundamentals
-====================
+Docutils Stakeholders
+=====================
-These files are for all `Docutils stakeholders`_. They are kept at the
-top level of the Docutils project directory.
+can be categorized in several groups:
+ .. class:: details
-.. class:: narrow run-in
+ End-users
+ users of reStructuredText and the Docutils tools.
+ Although some are developers (e.g. Python developers utilizing
+ reStructuredText for docstrings in their source), many are not.
+ Client-developers
+ developers using Docutils as a library,
+ programmers developing *with* Docutils.
+ Component-developers:
+ those who implement application-specific components,
+ directives, and/or roles, separately from Docutils.
+ Core-developers
+ developers of the Docutils codebase and participants
+ in the Docutils project community.
+ Re-implementers
+ developers of alternate implementations of Docutils.
-:README_: Project overview: quick-start, requirements,
- installation, and usage.
-:COPYING_: Conditions for Docutils redistribution, with links to
- licenses.
-:FAQ_: Docutils Frequently Asked Questions. If you have a
- question or issue, there's a good chance it's already
- answered here.
-:BUGS_: A list of known bugs, and how to report a bug.
-:RELEASE-NOTES_: Summary of the major changes in recent releases and
- notice of future incompatible changes.
-:HISTORY_: Detailed change history log.
-:THANKS_: Acknowledgements.
-
-.. _README: ../README.html
-.. _BUGS: ../BUGS.html
-.. _COPYING: ../COPYING.html
-.. _Docutils FAQ:
-.. _FAQ: ../FAQ.html
-.. _RELEASE-NOTES: ../RELEASE-NOTES.html
-.. _HISTORY: ../HISTORY.html
-.. _THANKS: ../THANKS.html
-
-
-.. _docutils stakeholders:
.. class:: details
-Docutils Stakeholders …
- can be categorized in several groups:
+There's a lot of overlap between these groups.
+ Most (perhaps all) developers are also end-users.
+ Core-developers are also client-developers, and may also
+ be component-developers in other projects.
+ Component-developers are also client-developers.
- End-users:
- users of reStructuredText and the Docutils tools.
- Although some are developers (e.g. Python developers utilizing
- reStructuredText for docstrings in their source), many are not.
- Client-developers:
- developers using Docutils as a library,
- programmers developing *with* Docutils.
+Project Fundamentals
+====================
- Component-developers:
- those who implement application-specific components,
- directives, and/or roles, separately from Docutils.
+These files are for all `Docutils stakeholders`_. They are kept at the
+top level of the Docutils project directory.
- Core-developers:
- developers of the Docutils codebase and participants
- in the Docutils project community.
+`README <../README.html>`_:
+ Project overview: quick-start, requirements,
+ installation, and usage.
- Re-implementers:
- developers of alternate implementations of Docutils.
+`COPYING <../COPYING.html>`_:
+ Conditions for Docutils redistribution,
+ with links to licenses.
+`FAQ <../FAQ.html>`_:
+ Docutils Frequently Asked Questions. If you have a question or issue,
+ there's a good chance it's already answered here.
+`BUGS <../BUGS.html>`_:
+ A list of known bugs, and how to report a bug.
+`RELEASE-NOTES <../RELEASE-NOTES.html>`_:
+ Summary of the major changes in recent releases and
+ notice of future incompatible changes.
+`HISTORY <../HISTORY.html>`_:
+ Detailed change history log.
+`THANKS <../THANKS.html>`_:
+ Acknowledgements.
- There's a lot of overlap between these groups. Most (perhaps all)
- core-developers, component-developers, client-developers, and
- re-implementers are also end-users. Core-developers are also
- client-developers, and may also be component-developers in other
- projects. Component-developers are also client-developers.
-
.. _user:
Introductory & Tutorial Material for End-Users
@@ -201,8 +195,7 @@
Instructions for Developers
===========================
-:Security: `Deploying Docutils Securely <howto/security.html>`__
-
+* `Deploying Docutils Securely <howto/security.html>`__
* `Inside A Docutils Command-Line Front-End Tool <howto/cmdline-tool.html>`__
* `Runtime Settings Processing <dev/runtime-settings-processing.html>`__
* `Writing HTML (CSS) Stylesheets for Docutils
Modified: trunk/docutils/docs/ref/doctree.txt
===================================================================
--- trunk/docutils/docs/ref/doctree.txt 2023-12-06 20:48:52 UTC (rev 9498)
+++ trunk/docutils/docs/ref/doctree.txt 2023-12-06 20:49:08 UTC (rev 9499)
@@ -79,8 +79,9 @@
+---------+
The Docutils document model uses a simple, recursive model for section
-structure. A document_ node may contain body elements and section_
-elements. Sections in turn may contain body elements and sections.
+structure. A `\<document>`_ node may contain body elements and
+`\<section>`_ elements.
+Sections in turn may contain body elements and sections.
The level (depth) of a section element is determined from its physical
nesting level; unlike other document models (``<h1>`` in HTML_,
``<sect1>`` in DocBook_, ``<div1>`` in XMLSpec_) the level is not
@@ -95,8 +96,16 @@
occur at the same level.
.. _HTML: https://www.w3.org/TR/html52/
+.. _XMLSpec: https://www.w3.org/XML/1998/06/xmlspec-report.htm
.. _DocBook: https://tdg.docbook.org/tdg/5.1/
-.. _XMLSpec: https://www.w3.org/XML/1998/06/xmlspec-report.htm
+.. _DocBook <caution>: https://tdg.docbook.org/tdg/5.1/caution.html
+.. _DocBook <footnote>: https://tdg.docbook.org/tdg/5.1/footnote.html
+.. _DocBook <footnoteref>: https://tdg.docbook.org/tdg/5.1/footnoteref.html
+.. _DocBook <imagedata>: https://tdg.docbook.org/tdg/5.1/imagedata
+.. _DocBook <important>: https://tdg.docbook.org/tdg/5.1/important.html
+.. _DocBook <note>: https://tdg.docbook.org/tdg/5.1/note.html
+.. _DocBook <tip>: https://tdg.docbook.org/tdg/5.1/tip.html
+.. _DocBook <warning>: https://tdg.docbook.org/tdg/5.1/warning.html
Structural Elements
@@ -107,7 +116,7 @@
elements or further structural elements. Structural elements can only
be child elements of other structural elements.
-Category members: document_, section_, topic_, sidebar_
+Category members: `\<document>`_, `\<section>`_, `\<topic>`_, `\<sidebar>`_
Structural Subelements
@@ -114,33 +123,36 @@
----------------------
Structural subelements are child elements of structural elements.
-Simple structural subelements (title_, subtitle_) contain text
-data; the others are compound and do not directly contain text data.
+Simple structural subelements (`\<title>`_, `\<subtitle>`_) contain text
+data; the others are compound elements and do not directly contain text
+data.
-Category members: title_, subtitle_, decoration_, docinfo_, meta_,
-transition_
+Category members: `\<title>`_, `\<subtitle>`_, `\<decoration>`_,
+`\<docinfo>`_, `\<meta>`_, `\<transition>`_
Bibliographic Elements
``````````````````````
-The docinfo_ element is an optional child of document_. It groups
-bibliographic elements together. All bibliographic elements except
-authors_ and field_ contain text data. authors_ contains further
-bibliographic elements (most notably author_). field_ contains
-field_name_ and field_body_ body subelements.
+The `\<docinfo>`_ element is an optional child of `\<document>`_.
+It groups bibliographic elements together. All bibliographic elements
+except `\<authors>`_ and `\<field>`_ contain text data. `\<authors>`_
+contains further bibliographic elements (most notably `\<author>`_).
+`\<field>`_ contains `\<field_name>`_ and `\<field_body>`_ body
+subelements.
-Category members: address_, author_, authors_, contact_, copyright_,
-date_, field_, organization_, revision_, status_, version_
+Category members: `\<address>`_, `\<author>`_, `\<authors>`_,
+`\<contact>`_, `\<copyright>`_, `\<date>`_, `\<field>`_,
+`\<organization>`_, `\<revision>`_, `\<status>`_, `\<version>`_
Decorative Elements
```````````````````
-The decoration_ element is also an optional child of document_. It
-groups together elements used to generate page headers and footers.
+The `\<decoration>`_ element is also an optional child of `\<document>`_.
+It groups together elements used to generate page headers and footers.
-Category members: footer_, header_
+Category members: `\<footer>`_, `\<header>`_
Body Elements
@@ -147,18 +159,23 @@
=============
Body elements are contained within structural elements and compound
-body elements. There are two subcategories of body elements: simple
-and compound.
+body elements. There are two subcategories of body elements: simple__
+and compound__.
-Category members: admonition_, attention_, block_quote_, bullet_list_,
-caution_, citation_, comment_, compound_, container_, danger_,
-definition_list_, doctest_block_, enumerated_list_, error_,
-field_list_, figure_, footnote_, hint_, image_, important_,
-line_block_, literal_block_, note_, option_list_, paragraph_,
-pending_, raw_, rubric_, substitution_definition_, system_message_,
-table_, target_, tip_, warning_
+Category members: `\<admonition>`_, `\<attention>`_, `\<block_quote>`_,
+`\<bullet_list>`_, `\<caution>`_, `\<citation>`_, `\<comment>`_,
+`\<compound>`_, `\<container>`_, `\<danger>`_, `\<definition_list>`_,
+`\<doctest_block>`_, `\<enumerated_list>`_, `\<error>`_,
+`\<field_list>`_, `\<figure>`_, `\<footnote>`_, `\<hint>`_, `\<image>`_,
+`\<important>`_, `\<line_block>`_, `\<literal_block>`_, `\<note>`_,
+`\<option_list>`_, `\<paragraph>`_, `\<pending>`_, `\<raw>`_,
+`\<rubric>`_, `\<substitution_definition>`_, `\<system_message>`_,
+`\<table>`_, `\<target>`_, `\<tip>`_, `\<warning>`_
+__ simple body elements
+__ compound body elements
+
Simple Body Elements
--------------------
@@ -166,9 +183,9 @@
that contain text data may also contain inline elements. Such
elements therefore have a "mixed content model".
-Category members: comment_, doctest_block_, image_, literal_block_,
-math_block_, paragraph_, pending_, raw_, rubric_, substitution_definition_,
-target_
+Category members: `\<comment>`_, `\<doctest_block>`_, `\<image>`_,
+`\<literal_block>`_, `\<math_block>`_, `\<paragraph>`_, `\<pending>`_,
+`\<raw>`_, `\<rubric>`_, `\<substitution_definition>`_, `\<target>`_
Compound Body Elements
@@ -177,31 +194,34 @@
Compound body elements contain local substructure (body subelements)
and further body elements. They do not directly contain text data.
-Category members: admonition_, attention_, block_quote_, bullet_list_,
-caution_, citation_, compound_, container_, danger_, definition_list_,
-enumerated_list_, error_, field_list_, figure_, footnote_, hint_,
-important_, line_block, note_, option_list_, system_message_, table_,
-tip_, warning_
+Category members: `\<admonition>`_, `\<attention>`_, `\<block_quote>`_,
+`\<bullet_list>`_, `\<caution>`_, `\<citation>`_, `\<compound>`_,
+`\<container>`_, `\<danger>`_, `\<definition_list>`_,
+`\<enumerated_list>`_, `\<error>`_, `\<field_list>`_, `\<figure>`_,
+`\<footnote>`_, `\<hint>`_, `\<important>`_, `\<line_block>`_,
+`\<note>`_, `\<option_list>`_, `\<system_message>`_, `\<table>`_,
+`\<tip>`_, `\<warning>`_
Body Subelements
````````````````
-Compound body elements contain specific subelements (e.g. bullet_list_
-contains list_item_). Subelements may themselves be compound elements
-(containing further child elements, like field_) or simple data
-elements (containing text data, like field_name_). These subelements
+Compound body elements contain specific subelements (e.g. `\<bullet_list>`_
+contains `\<list_item>`_). Subelements may themselves be compound elements
+(containing further child elements, like `\<field>`_) or simple data
+elements (containing text data, like `\<field_name>`_). These subelements
always occur within specific parent elements, never at the body
element level (beside paragraphs, etc.).
-Category members (simple): attribution_, caption_, classifier_,
-colspec_, field_name_, label_, line_, option_argument_,
-option_string_, term_
+Category members (simple): `\<attribution>`_, `\<caption>`_,
+`\<classifier>`_, `\<colspec>`_, `\<field_name>`_, `\<label>`_,
+`\<line>`_, `\<option_argument>`_, `\<option_string>`_, `\<term>`_
-Category members (compound): definition_, definition_list_item_,
-description_, entry_, field_, field_body_, legend_, list_item_,
-option_, option_group_, option_list_item_, row_, tbody_, tgroup_,
-thead_
+Category members (compound): `\<definition>`_,
+`\<definition_list_item>`_, `\<description>`_, `\<entry>`_, `\<field>`_,
+`\<field_body>`_, `\<legend>`_, `\<list_item>`_, `\<option>`_,
+`\<option_group>`_, `\<option_list_item>`_, `\<row>`_, `\<tbody>`_,
+`\<tgroup>`_, `\<thead>`_
Inline Elements
@@ -211,10 +231,12 @@
further inline elements. Inline elements are contained within simple
body elements. Most inline elements have a "mixed content model".
-Category members: abbreviation_, acronym_, citation_reference_,
-emphasis_, footnote_reference_, generated_, image_, inline_, literal_,
-math_, problematic_, reference_, strong_, subscript_,
-substitution_reference_, superscript_, target_, title_reference_, raw_
+Category members: `\<abbreviation>`_, `\<acronym>`_,
+`\<citation_reference>`_, `\<emphasis>`_, `\<footnote_reference>`_,
+`\<generated>`_, `\<image>`_, `\<inline>`_, `\<literal>`_,
+`\<math>`_, `\<problematic>`_, `\<raw>`_, `\<reference>`_,
+`\<strong>`_, `\<subscript>`_, `\<substitution_reference>`_,
+`\<superscript>`_, `\<target>`_, `\<title_reference>`_
-------------------
@@ -285,107 +307,79 @@
its writing.
-``abbreviation``
-================
+<abbreviation>
+==============
-The ``abbreviation`` element is an inline element used to represent an
-abbreviation being used in the document. An example of an abbreviation is 'St'
-being used instead of 'Street'.
+The <abbreviation> element is an inline element used to represent an
+abbreviation being used in the document.
+An example of an abbreviation is 'St' being used instead of 'Street'.
-
Details
-------
-:Category:
- `Inline Elements`_
+:Category: `Inline Elements`_
+:Analogues: <abbreviation> is analogous to the HTML <abbr> element.
+:Parents: All elements employing the `%inline.elements;`_ parameter
+ entity in their content models may contain <abbreviation>.
+:Children: <abbreviation> elements may contain text data plus `inline
+ elements`_ (`%text.model;`_).
+:Attributes: The <abbreviation> element contains only the `common attributes`_.
-:Analogues:
- ``abbreviation`` is analogous to the HTML "abbr" element.
-
-:Parents:
- All elements employing the `%inline.elements;`_ parameter entity in their
- content models may contain ``abbreviation``.
-
-:Children:
- ``abbreviation`` elements may contain text data plus `inline elements`_.
-
- .. parsed-literal::
-
- `%text.model;`_
-
-:Attributes:
- The ``abbreviation`` element contains only the `common attributes`_.
-
-
Examples
--------
-The ``abbreviation`` element is not exposed in default restructured text. It
-can only be accessed through custom roles.
+The reStructuredText `abbreviation role`_ creates an <abbreviation> element::
-Pseudo-XML_ example from a custom `:abbr:` role::
+ :abbreviation:`St` is a common abbreviation for "street".
+Pseudo-XML_ fragment from simple parsing::
+
<paragraph>
- <abbreviation explanation="Street">
+ <abbreviation>
St
is a common abbreviation for "street".
+.. _abbreviation role: rst/roles.html#abbreviation
-``acronym``
-===========
+<acronym>
+=========
+
`To be completed`_.
-``address``
+<address>
===========
-The ``address`` element holds the surface mailing address information
-for the author (individual or group) of the document, or a third-party
+The <address> element holds the surface mailing address information
+for the author(s) (individual or group) of the document, or a third-party
contact address. Its structure is identical to that of the
-literal_block_ element: whitespace is significant, especially
+`\<literal_block>`_ element: whitespace is significant, especially
newlines.
-
Details
-------
-:Category:
- `Bibliographic Elements`_
+:Category: `Bibliographic Elements`_
+:Analogues: <address> is analogous to the DocBook_ <address> element.
+:Processing: As with the `\<literal_block>`_ element, newlines and other
+ whitespace is significant and must be preserved.
+ However, a monospaced typeface need not be used.
+ See also `\<docinfo>`_.
+:Parents: The following elements may contain <address>:
+ `\<docinfo>`_, `\<authors>`_.
+:Children: <address> elements contain text data plus `inline elements`_
+ (`%text.model;`_).
+:Attributes: The <address> element contains the `common attributes`_
+ plus `xml:space`_.
+:Parameter Entities: The `%bibliographic.elements;`_ parameter entity
+ directly includes <address>.
-:Analogues:
- ``address`` is analogous to the DocBook "address" element.
-
-:Processing:
- As with the literal_block_ element, newlines and other whitespace
- is significant and must be preserved. However, a monospaced
- typeface need not be used.
-
- See also docinfo_.
-
-:Parents:
- The following elements may contain ``address``: docinfo_, authors_
-
-:Children:
- ``address`` elements contain text data plus `inline elements`_.
-
- .. parsed-literal::
-
- `%text.model;`_
-
-:Attributes:
- The ``address`` element contains the `common attributes`_ plus
- `xml:space`_.
-
-:Parameter Entities:
- The `%bibliographic.elements;`_ parameter entity directly includes
- ``address``.
-
-
Examples
--------
-reStructuredText_ source::
+In reStructuredText, "address" is one of the registered
+`bibliographic fields`_::
Document Title
==============
@@ -393,7 +387,7 @@
:Address: 123 Example Ave.
Example, EX
-Complete pseudo-XML_ result after parsing and applying transforms::
+Complete pseudo-XML_ result after parsing and applying transforms_::
<document ids="document-title" names="document title">
<title>
@@ -403,121 +397,97 @@
123 Example Ave.
Example, EX
-See docinfo_ for a more complete example, including processing
+See `\<docinfo>`_ for a more complete example, including processing
context.
-``admonition``
-==============
+<admonition>
+============
-This element is a generic, titled admonition. Also see the specific
-admonition elements Docutils offers (in alphabetical order): caution_,
-danger_, error_, hint_, important_, note_, tip_, warning_.
+The <admonition> element is a generic, titled *admonition*,
+a distinctive and self-contained notice.
+See also the specific admonition elements
+`\<attention>`_ `\<caution>`_, `\<danger>`_, `\<error>`_, `\<hint>`_,
+`\<important>`_, `\<note>`_, `\<tip>`_, and `\<warning>`_.
Details
-------
-:Category:
- `Compound Body Elements`_
+:Category: `Compound Body Elements`_
-:Analogues:
- ``admonition`` has no direct analogues in common DTDs. It can be
- emulated with primitives and type effects.
+:Analogues: The generic <admonition> has no direct analogues in common DTDs.
+ It can be emulated with primitives and type effects.
+ The specific admonitions `\<caution>`_, `\<note>`_,
+ `\<tip>`_, and `\<warning>`_ are analogous to the
+ respective DocBook_ elements.
- The specific admonitions caution_, note_, tip_, and warning_
- are analogous to the respective DocBook elements.
+:Processing: Rendered distinctly (inset and/or in a box, etc.).
-:Processing:
- Rendered distinctly (inset and/or in a box, etc.).
+:Parents: All elements employing the `%body.elements;`_
+ or `%structure.model;`_ parameter entities in
+ their content models may contain <admonition>.
-:Parents:
- All elements employing the `%body.elements;`_ or
- `%structure.model;`_ parameter entities in their content models
- may contain ``admonition``.
+:Children: <admonition> elements begin with a `\<title>`_ and may contain
+ one or more `body elements`_.
-:Children:
- ``admonition`` elements begin with a title_ and may contain one or
- more `body elements`_. ::
+:Attributes: The <admonition> element contains only the `common attributes`_.
- (title_, (`%body.elements;`_)+)
+:Parameter Entities: The `%body.elements;`_ parameter entity directly
+ includes <admonition>. The `%structure.model;`_
+ parameter entity indirectly includes <admonition>.
-:Attributes:
- The ``admonition`` element contains only the `common attributes`_.
-
-:Parameter Entities:
- The `%body.elements;`_ parameter entity directly includes
- ``admonition``. The `%structure.model;`_ parameter entity
- indirectly includes ``admonition``.
-
-
Examples
--------
-reStructuredText source::
+The reStructuredText `"admonition" directive`_ creates a generic
+<admonition> element::
- .. admonition:: And, by the way...
+ .. admonition:: By the way...
You can make up your own admonition too.
Pseudo-XML_ fragment from simple parsing::
- <admonition class="admonition-and-by-the-way">
+ <admonition class="admonition-by-the-way">
<title>
- And, by the way...
+ By the way...
<paragraph>
You can make up your own admonition too.
+.. _"admonition" directive: rst/directives.html#admonition
-``attention``
-=============
-The ``attention`` element is an admonition, a distinctive and
-self-contained notice. Also see the other admonition elements
-Docutils offers (in alphabetical order): caution_, danger_, error_,
-hint_, important_, note_, tip_, warning_, and the generic admonition_.
+<attention>
+===========
+The <attention> element is an *admonition*, a distinctive and
+self-contained notice. See also the generic `\<admonition>`_
+and the other specific admonition elements `\<caution>`_,
+`\<danger>`_, `\<error>`_, `\<hint>`_, `\<important>`_, `\<note>`_,
+`\<tip>`_, and `\<warning>`_.
Details
-------
-:Category:
- `Compound Body Elements`_
+:Category: `Compound Body Elements`_
+:Analogues: <attention> has no direct analogues in common DTDs.
+ It can be emulated with primitives and type effects.
+:Processing: Rendered distinctly (inset and/or in a box, etc.),
+ with the generated title "Attention!" (or similar).
+:Parents: All elements employing the `%body.elements;`_ or
+ `%structure.model;`_ parameter entities in their
+ content models may contain <attention>.
+:Children: <attention> elements contain one or more `body elements`_.
+:Attributes: The <attention> element contains only the `common attributes`_.
+:Parameter Entities: The `%body.elements;`_ parameter entity
+ directly includes <attention>. The `%structure.model;`_
+ parameter entity indirectly includes <attention>.
-:Analogues:
- ``attention`` has no direct analogues in common DTDs. It can be
- emulated with primitives and type effects.
-
-:Processing:
- Rendered distinctly (inset and/or in a box, etc.), with the
- generated title "Attention!" (or similar).
-
-
-:Parents:
- All elements employing the `%body.elements;`_ or
- `%structure.model;`_ parameter entities in their content models
- may contain ``attention``.
-
-:Children:
- ``attention`` elements contain one or more `bod...
[truncated message content] |
|
From: <mi...@us...> - 2023-12-14 22:38:51
|
Revision: 9500
http://sourceforge.net/p/docutils/code/9500
Author: milde
Date: 2023-12-14 22:38:49 +0000 (Thu, 14 Dec 2023)
Log Message:
-----------
Add/fix source and line attributes for doctree elements.
Add "source" and "line" attributes to `<image>`, `<figure>`,
`<list_item>`, <math_block>, and `<definition>` nodes.
Fix "line" attribute for `<definition_list>`, `<definition_list_item>`,
and `<term>` nodes, cf. [r9475].
Modified Paths:
--------------
trunk/docutils/docutils/parsers/rst/directives/body.py
trunk/docutils/docutils/parsers/rst/directives/images.py
trunk/docutils/docutils/parsers/rst/states.py
trunk/docutils/test/test_parsers/test_rst/includes/include14.txt
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_source_line.py
Modified: trunk/docutils/docutils/parsers/rst/directives/body.py
===================================================================
--- trunk/docutils/docutils/parsers/rst/directives/body.py 2023-12-06 20:49:08 UTC (rev 9499)
+++ trunk/docutils/docutils/parsers/rst/directives/body.py 2023-12-14 22:38:49 UTC (rev 9500)
@@ -210,7 +210,8 @@
if not block:
continue
node = nodes.math_block(self.block_text, block, **self.options)
- node.line = self.content_offset + 1
+ (node.source,
+ node.line) = self.state_machine.get_source_and_line(self.lineno)
self.add_name(node)
_nodes.append(node)
return _nodes
Modified: trunk/docutils/docutils/parsers/rst/directives/images.py
===================================================================
--- trunk/docutils/docutils/parsers/rst/directives/images.py 2023-12-06 20:49:08 UTC (rev 9499)
+++ trunk/docutils/docutils/parsers/rst/directives/images.py 2023-12-14 22:38:49 UTC (rev 9500)
@@ -97,6 +97,8 @@
del self.options['target']
set_classes(self.options)
image_node = nodes.image(self.block_text, **self.options)
+ (image_node.source,
+ image_node.line) = self.state_machine.get_source_and_line(self.lineno)
self.add_name(image_node)
if reference_node:
reference_node += image_node
@@ -130,6 +132,8 @@
if isinstance(image_node, nodes.system_message):
return [image_node]
figure_node = nodes.figure('', image_node)
+ (figure_node.source, figure_node.line
+ ) = self.state_machine.get_source_and_line(self.lineno)
if figwidth == 'image':
if PIL and self.state.document.settings.file_insertion_enabled:
imagepath = url2pathname(image_node['uri'])
Modified: trunk/docutils/docutils/parsers/rst/states.py
===================================================================
--- trunk/docutils/docutils/parsers/rst/states.py 2023-12-06 20:49:08 UTC (rev 9499)
+++ trunk/docutils/docutils/parsers/rst/states.py 2023-12-14 22:38:49 UTC (rev 9500)
@@ -1265,18 +1265,17 @@
def bullet(self, match, context, next_state):
"""Bullet list item."""
- bulletlist = nodes.bullet_list()
- (bulletlist.source,
- bulletlist.line) = self.state_machine.get_source_and_line()
- self.parent += bulletlist
- bulletlist['bullet'] = match.string[0]
+ ul = nodes.bullet_list()
+ ul.source, ul.line = self.state_machine.get_source_and_line()
+ self.parent += ul
+ ul['bullet'] = match.string[0]
i, blank_finish = self.list_item(match.end())
- bulletlist += i
+ ul += i
offset = self.state_machine.line_offset + 1 # next line
new_line_offset, blank_finish = self.nested_list_parse(
self.state_machine.input_lines[offset:],
input_offset=self.state_machine.abs_line_offset() + 1,
- node=bulletlist, initial_state='BulletList',
+ node=ul, initial_state='BulletList',
blank_finish=blank_finish)
self.goto_line(new_line_offset)
if not blank_finish:
@@ -1284,6 +1283,7 @@
return [], next_state, []
def list_item(self, indent):
+ src, srcline = self.state_machine.get_source_and_line()
if self.state_machine.line[indent:]:
indented, line_offset, blank_finish = (
self.state_machine.get_known_indented(indent))
@@ -1291,6 +1291,7 @@
indented, indent, line_offset, blank_finish = (
self.state_machine.get_first_known_indented(indent))
listitem = nodes.list_item('\n'.join(indented))
+ listitem.source, listitem.line = src, srcline
if indented:
self.nested_parse(indented, input_offset=line_offset,
node=listitem)
@@ -2728,17 +2729,18 @@
def indent(self, match, context, next_state):
"""Definition list item."""
- definitionlist = nodes.definition_list()
- (definitionlist.src,
- definitionlist.line) = self.state_machine.get_source_and_line()
- definitionlistitem, blank_finish = self.definition_list_item(context)
- definitionlist += definitionlistitem
- self.parent += definitionlist
+ dl = nodes.definition_list()
+ # the definition list starts on the line before the indent:
+ lineno = self.state_machine.abs_line_number() - 1
+ dl.source, dl.line = self.state_machine.get_source_and_line(lineno)
+ dl_item, blank_finish = self.definition_list_item(context)
+ dl += dl_item
+ self.parent += dl
offset = self.state_machine.line_offset + 1 # next line
newline_offset, blank_finish = self.nested_list_parse(
self.state_machine.input_lines[offset:],
input_offset=self.state_machine.abs_line_offset() + 1,
- node=definitionlist, initial_state='DefinitionList',
+ node=dl, initial_state='DefinitionList',
blank_finish=blank_finish, blank_finish_state='Definition')
self.goto_line(newline_offset)
if not blank_finish:
@@ -2840,24 +2842,30 @@
return parent_node.children
def definition_list_item(self, termline):
+ # the parser is already on the second (indented) line:
+ dd_lineno = self.state_machine.abs_line_number()
+ dt_lineno = dd_lineno - 1
(indented, indent, line_offset, blank_finish
) = self.state_machine.get_indented()
- itemnode = nodes.definition_list_item(
- '\n'.join(termline + list(indented)))
- lineno = self.state_machine.abs_line_number() - 1
- (itemnode.source,
- itemnode.line) = self.state_machine.get_source_and_line(lineno)
- termlist, messages = self.term(termline, lineno)
- itemnode += termlist
- definition = nodes.definition('', *messages)
- itemnode += definition
+ dl_item = nodes.definition_list_item(
+ '\n'.join(termline + list(indented)))
+ (dl_item.source,
+ dl_item.line) = self.state_machine.get_source_and_line(dt_lineno)
+ dt_nodes, messages = self.term(termline, dt_lineno)
+ dl_item += dt_nodes
+ dd = nodes.definition('', *messages)
+ dd.source, dd.line = self.state_machine.get_source_and_line(dd_lineno)
+ dl_item += dd
if termline[0][-2:] == '::':
- definition += self.reporter.info(
+ dd += self.reporter.info(
'Blank line missing before literal block (after the "::")? '
'Interpreted as a definition list item.',
- line=lineno+1)
- self.nested_parse(indented, input_offset=line_offset, node=definition)
- return itemnode, blank_finish
+ line=dd_lineno)
+ # TODO: drop a definition if it is an empty comment to allow
+ # definition list items with several terms?
+ # https://sourceforge.net/p/docutils/feature-requests/60/
+ self.nested_parse(indented, input_offset=line_offset, node=dd)
+ return dl_item, blank_finish
classifier_delimiter = re.compile(' +: +')
@@ -2865,10 +2873,9 @@
"""Return a definition_list's term and optional classifiers."""
assert len(lines) == 1
text_nodes, messages = self.inline_text(lines[0], lineno)
- term_node = nodes.term(lines[0])
- (term_node.source,
- term_node.line) = self.state_machine.get_source_and_line(lineno)
- node_list = [term_node]
+ dt = nodes.term(lines[0])
+ dt.source, dt.line = self.state_machine.get_source_and_line(lineno)
+ node_list = [dt]
for i in range(len(text_nodes)):
node = text_nodes[i]
if isinstance(node, nodes.Text):
@@ -2921,8 +2928,8 @@
def indent(self, match, context, next_state):
"""Definition list item."""
- itemnode, blank_finish = self.definition_list_item(context)
- self.parent += itemnode
+ dl_item, blank_finish = self.definition_list_item(context)
+ self.parent += dl_item
self.blank_finish = blank_finish
return [], 'DefinitionList', []
Modified: trunk/docutils/test/test_parsers/test_rst/includes/include14.txt
===================================================================
--- trunk/docutils/test/test_parsers/test_rst/includes/include14.txt 2023-12-06 20:49:08 UTC (rev 9499)
+++ trunk/docutils/test/test_parsers/test_rst/includes/include14.txt 2023-12-14 22:38:49 UTC (rev 9500)
@@ -15,5 +15,5 @@
Generic admonition text in line 16
-line 18
- definition list item in line 19
+term on line 18
+ definition in line 19
Modified: trunk/docutils/test/test_parsers/test_rst/test_definition_lists.py
===================================================================
--- trunk/docutils/test/test_parsers/test_rst/test_definition_lists.py 2023-12-06 20:49:08 UTC (rev 9499)
+++ trunk/docutils/test/test_parsers/test_rst/test_definition_lists.py 2023-12-14 22:38:49 UTC (rev 9500)
@@ -23,6 +23,9 @@
class ParserTestCase(unittest.TestCase):
+
+ maxDiff = None
+
def test_parser(self):
parser = Parser()
settings = get_default_settings(Parser)
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 2023-12-06 20:49:08 UTC (rev 9499)
+++ trunk/docutils/test/test_parsers/test_rst/test_directives/test_include.py 2023-12-14 22:38:49 UTC (rev 9500)
@@ -772,7 +772,7 @@
<term>
A literal block::
<definition>
- <system_message level="1" line="57" source="{include10}" type="INFO">
+ <system_message level="1" line="56" source="{include10}" type="INFO">
<paragraph>
Blank line missing before literal block (after the "::")? Interpreted as a definition list item.
<paragraph>
Modified: trunk/docutils/test/test_parsers/test_rst/test_source_line.py
===================================================================
--- trunk/docutils/test/test_parsers/test_rst/test_source_line.py 2023-12-06 20:49:08 UTC (rev 9499)
+++ trunk/docutils/test/test_parsers/test_rst/test_source_line.py 2023-12-14 22:38:49 UTC (rev 9500)
@@ -81,9 +81,11 @@
in line 6
* bullet list in line 9
-* second item in line 10
+*
+ second item in line 10
+ paragraph starts in line 11
-1. enumerated list in line 12
+#. enumerated list in line 14
""",
"""\
<document source="test data">
@@ -100,16 +102,17 @@
attribution
in line 6
<bullet_list bullet="*" internal:line="9" internal:source="test data">
- <list_item internal:source="test data">
+ <list_item internal:line="9" internal:source="test data">
<paragraph internal:line="9" internal:source="test data">
bullet list in line 9
- <list_item internal:source="test data">
- <paragraph internal:line="10" internal:source="test data">
+ <list_item internal:line="10" internal:source="test data">
+ <paragraph internal:line="11" internal:source="test data">
second item in line 10
- <enumerated_list enumtype="arabic" internal:line="12" internal:source="test data" prefix="" suffix=".">
- <list_item internal:source="test data">
- <paragraph internal:line="12" internal:source="test data">
- enumerated list in line 12
+ paragraph starts in line 11
+ <enumerated_list enumtype="arabic" internal:line="14" internal:source="test data" prefix="" suffix=".">
+ <list_item internal:line="14" internal:source="test data">
+ <paragraph internal:line="14" internal:source="test data">
+ enumerated list in line 14
"""],
["""\
Paragraph
@@ -191,14 +194,14 @@
attribution
in line 6
<bullet_list bullet="*" internal:line="9" internal:source="{include14}">
- <list_item internal:source="{include14}">
+ <list_item internal:line="9" internal:source="{include14}">
<paragraph internal:line="9" internal:source="{include14}">
bullet list in line 9
- <list_item internal:source="{include14}">
+ <list_item internal:line="10" internal:source="{include14}">
<paragraph internal:line="10" internal:source="{include14}">
second item in line 10
<enumerated_list enumtype="arabic" internal:line="12" internal:source="{include14}" prefix="" suffix=".">
- <list_item internal:source="{include14}">
+ <list_item internal:line="12" internal:source="{include14}">
<paragraph internal:line="12" internal:source="{include14}">
enumerated list in line 12
<admonition classes="admonition-line-14" internal:line="14" internal:source="{include14}">
@@ -206,13 +209,13 @@
line 14
<paragraph internal:line="16" internal:source="{include14}">
Generic admonition text in line 16
- <definition_list internal:line="19" internal:source="{include14}">
- <definition_list_item internal:line="19" internal:source="{include14}">
- <term internal:line="19" internal:source="{include14}">
- line 18
- <definition>
+ <definition_list internal:line="18" internal:source="{include14}">
+ <definition_list_item internal:line="18" internal:source="{include14}">
+ <term internal:line="18" internal:source="{include14}">
+ term on line 18
+ <definition internal:line="19" internal:source="{include14}">
<paragraph internal:line="19" internal:source="{include14}">
- definition list item in line 19
+ definition in line 19
"""],
["""\
Paragraph
@@ -244,6 +247,30 @@
<paragraph internal:line="11" internal:source="test data">
Final paragraph in line 11
"""],
+["""\
+Paragraph
+
+.. image:: line-3.png
+ :width: 3em
+
+.. figure:: line-6.png
+
+ caption on line 8
+
+Final paragraph in line 10
+""",
+"""\
+<document source="test data">
+ <paragraph internal:line="1" internal:source="test data">
+ Paragraph
+ <image internal:line="3" internal:source="test data" uri="line-3.png" width="3em">
+ <figure internal:line="6" internal:source="test data">
+ <image internal:line="6" internal:source="test data" uri="line-6.png">
+ <caption internal:line="8" internal:source="test data">
+ caption on line 8
+ <paragraph internal:line="10" internal:source="test data">
+ Final paragraph in line 10
+"""],
])
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2023-12-14 22:39:01
|
Revision: 9501
http://sourceforge.net/p/docutils/code/9501
Author: milde
Date: 2023-12-14 22:38:58 +0000 (Thu, 14 Dec 2023)
Log Message:
-----------
Refactor "_html_base" writer.
Auxiliary method `HTMLTranslator.image_size()` to bring
`HTMLTranslator.visit_image()` to a reasonable size.
Improve/test error reporting when an image file cannot be read.
Sort methods in `HTMLTranslator`.
Small cleanups and optimizations.
Modified Paths:
--------------
trunk/docutils/docutils/writers/_html_base.py
trunk/docutils/test/test_writers/test_html5_polyglot_misc.py
trunk/docutils/test/test_writers/test_html5_polyglot_parts.py
Modified: trunk/docutils/docutils/writers/_html_base.py
===================================================================
--- trunk/docutils/docutils/writers/_html_base.py 2023-12-14 22:38:49 UTC (rev 9500)
+++ trunk/docutils/docutils/writers/_html_base.py 2023-12-14 22:38:58 UTC (rev 9501)
@@ -358,28 +358,6 @@
+ self.body_pre_docinfo + self.docinfo
+ self.body + self.body_suffix)
- def encode(self, text):
- """Encode special characters in `text` & return."""
- # Use only named entities known in both XML and HTML
- # other characters are automatically encoded "by number" if required.
- # @@@ A codec to do these and all other HTML entities would be nice.
- text = str(text)
- return text.translate(self.special_characters)
-
- def cloak_mailto(self, uri):
- """Try to hide a mailto: URL from harvesters."""
- # Encode "@" using a URL octet reference (see RFC 1738).
- # Further cloaking with HTML entities will be done in the
- # `attval` function.
- return uri.replace('@', '%40')
-
- def cloak_email(self, addr):
- """Try to hide the link text of a email link from harversters."""
- # Surround at-signs and periods with <span> tags. ("@" has
- # already been encoded to "@" by the `encode` method.)
- addr = addr.replace('@', '<span>@</span>')
- return addr.replace('.', '<span>.</span>')
-
def attval(self, text,
whitespace=re.compile('[\n\r\t\v\f]')):
"""Cleanse, HTML encode, and return attribute value text."""
@@ -390,6 +368,81 @@
encoded = encoded.replace('.', '.')
return encoded
+ def cloak_email(self, addr):
+ """Try to hide the link text of a email link from harversters."""
+ # Surround at-signs and periods with <span> tags. ("@" has
+ # already been encoded to "@" by the `encode` method.)
+ addr = addr.replace('@', '<span>@</span>')
+ return addr.replace('.', '<span>.</span>')
+
+ def cloak_mailto(self, uri):
+ """Try to hide a mailto: URL from harvesters."""
+ # Encode "@" using a URL octet reference (see RFC 1738).
+ # Further cloaking with HTML entities will be done in the
+ # `attval` function.
+ return uri.replace('@', '%40')
+
+ def encode(self, text):
+ """Encode special characters in `text` & return."""
+ # Use only named entities known in both XML and HTML
+ # other characters are automatically encoded "by number" if required.
+ # @@@ A codec to do these and all other HTML entities would be nice.
+ text = str(text)
+ return text.translate(self.special_characters)
+
+ def image_size(self, node):
+ # Determine the image size from the node arguments or the image file.
+ # Return a (hopefully empty) list of system messages
+ # and a string that is suitable as "style" argument value,
+ # e.g., ``([], 'width: 4px; height: 2em;')``.
+ size = [node.get('width', None), node.get('height', None)]
+ messages = []
+ if 'scale' in node:
+ if 'width' not in node or 'height' not in node:
+ # try reading size from image file
+ reading_problems = []
+ uri = node['uri']
+ if not PIL:
+ reading_problems.append('Requires Python Imaging Library.')
+ if mimetypes.guess_type(uri)[0] in self.videotypes:
+ reading_problems.append('PIL cannot read video images.')
+ if not self.settings.file_insertion_enabled:
+ reading_problems.append('Reading external files disabled.')
+ if not reading_problems:
+ try:
+ imagepath = self.uri2imagepath(uri)
+ with PIL.Image.open(imagepath) as img:
+ imgsize = img.size
+ except (ValueError, OSError, UnicodeEncodeError) as err:
+ reading_problems.append(str(err))
+ else:
+ self.settings.record_dependencies.add(
+ imagepath.replace('\\', '/'))
+ if reading_problems:
+ msg = ['Cannot scale image!',
+ f'Could not get size from "{uri}":',
+ *reading_problems]
+ messages.append(self.document.reporter.warning(
+ '\n '.join(msg), base_node=node))
+ else:
+ for i in range(2):
+ size[i] = size[i] or '%dpx' % imgsize[i]
+ # scale provided/determined size values:
+ factor = float(node['scale']) / 100
+ for i in range(2):
+ if size[i]:
+ match = re.match(r'([0-9.]+)(\S*)$', size[i])
+ size[i] = '%s%s' % (factor * float(match.group(1)),
+ match.group(2))
+ style_arg = []
+ for i, _name in enumerate(('width', 'height')):
+ if size[i]:
+ # Interpret unitless values as pixels:
+ if re.match(r'^[0-9.]+$', size[i]):
+ size[i] += 'px'
+ style_arg.append('%s: %s;' % (_name, size[i]))
+ return messages, ' '.join(style_arg)
+
def stylesheet_call(self, path, adjust_path=None):
"""Return code to reference or embed stylesheet file `path`"""
if adjust_path is None:
@@ -511,6 +564,8 @@
"""
destination = self.settings._destination or ''
uri_parts = urllib.parse.urlparse(uri)
+ if uri_parts.scheme not in ('', 'file'):
+ raise ValueError('Can only read local images.')
imagepath = urllib.request.url2pathname(uri_parts.path)
if imagepath.startswith('/'):
root_prefix = Path(self.settings.root_prefix)
@@ -1034,98 +1089,32 @@
def visit_image(self, node):
uri = node['uri']
alt = node.get('alt', uri)
- uri_parts = urllib.parse.urlparse(uri)
- imagepath = ''
mimetype = mimetypes.guess_type(uri)[0]
atts = {} # attributes for the HTML tag
+ messages = [] # system_message nodes
if 'align' in node:
atts['class'] = 'align-%s' % node['align']
- # image size
- if 'width' in node:
- atts['width'] = node['width']
- if 'height' in node:
- atts['height'] = node['height']
- if 'scale' in node:
- if 'width' not in node or 'height' not in node:
- # try reading size from image file
- scaling_problems = []
- if uri_parts.scheme not in ('', 'file'):
- scaling_problems.append('Can only read local images.')
- if not PIL:
- scaling_problems.append('Requires Python Imaging Library.')
- if mimetype in self.videotypes:
- scaling_problems.append('PIL cannot read video images.')
- if not self.settings.file_insertion_enabled:
- scaling_problems.append('Reading external files disabled.')
- if not scaling_problems:
- imagepath = self.uri2imagepath(uri)
- try:
- with PIL.Image.open(imagepath) as img:
- imgsize = img.size
- except (OSError, UnicodeEncodeError) as err:
- scaling_problems.append(str(err))
- else:
- self.settings.record_dependencies.add(
- imagepath.replace('\\', '/'))
- if scaling_problems:
- msg = ['Cannot scale image!',
- f'Could not get size from "{imagepath or uri}":',
- *scaling_problems]
- self.document.reporter.warning('\n '.join(msg))
- else:
- if 'width' not in atts:
- atts['width'] = '%dpx' % imgsize[0]
- if 'height' not in atts:
- atts['height'] = '%dpx' % imgsize[1]
- # scale provided/determined size values:
- for att_name in 'width', 'height':
- if att_name in atts:
- match = re.match(r'([0-9.]+)(\S*)$', atts[att_name])
- assert match
- atts[att_name] = '%s%s' % (
- float(match.group(1)) * (float(node['scale']) / 100),
- match.group(2))
# set size with "style" attribute (more universal, accepts dimensions)
- style = []
- for att_name in 'width', 'height':
- if att_name in atts:
- # Interpret unitless values as pixels:
- if re.match(r'^[0-9.]+$', atts[att_name]):
- atts[att_name] += 'px'
- style.append('%s: %s;' % (att_name, atts[att_name]))
- del atts[att_name]
- if style:
- atts['style'] = ' '.join(style)
+ msgs, size = self.image_size(node)
+ messages += msgs
+ if size:
+ atts['style'] = size
- # No newlines around inline images or if surrounded by <a>...</a>.
- if (isinstance(node.parent, nodes.TextElement)
- or (isinstance(node.parent, nodes.reference)
- and not isinstance(node.parent.parent, nodes.TextElement))):
- suffix = ''
- else:
- suffix = '\n'
-
- # ``:loading:`` option (embed, link, lazy)
- # get default from config setting
+ # ``:loading:`` option (embed, link, lazy), default from setting,
# exception: only embed videos if told via directive option
- if mimetype in self.videotypes:
- loading = 'link'
- else:
- loading = getattr(self.settings, 'image_loading', 'link')
- loading = node.get('loading', loading)
-
+ loading = node.get('loading',
+ 'link' if mimetype in self.videotypes
+ else self.image_loading)
if loading == 'embed':
- if uri_parts.scheme not in ('', 'file'):
- self.document.reporter.error(
- f'Cannot embed remote image "{uri}"')
- # TODO: read with urllib.request?
- imagepath = imagepath or self.uri2imagepath(uri)
try:
+ imagepath = self.uri2imagepath(uri)
with open(imagepath, 'rb') as imagefile:
imagedata = imagefile.read()
- except OSError as err:
- self.document.reporter.error('Cannot embed image %r: %s'
- % (uri, err.strerror))
+ except (ValueError, OSError) as err:
+ messages.append(self.document.reporter.error(
+ f'Cannot embed image "{uri}":\n {err}', base_node=node))
+ # TODO: read external files with urllib.request?
+ # (cf. odtwriter)
else:
self.settings.record_dependencies.add(imagepath)
# TODO: insert SVG as-is?
@@ -1137,6 +1126,13 @@
elif loading == 'lazy':
atts['loading'] = 'lazy'
+ # No newlines around inline images or if surrounded by <a>...</a>.
+ if (isinstance(node.parent, nodes.TextElement)
+ or (isinstance(node.parent, nodes.reference)
+ and not isinstance(node.parent.parent, nodes.TextElement))):
+ suffix = ''
+ else:
+ suffix = '\n'
if mimetype in self.videotypes:
atts['title'] = alt
alt_link = node['uri'] # use original URI also when embedding
@@ -1154,6 +1150,9 @@
atts['alt'] = alt
tag = self.emptytag(node, 'img', suffix, src=uri, **atts)
self.body.append(tag)
+ for message in messages:
+ if self.settings.report_level <= message['level']:
+ message.walkabout(self)
def depart_image(self, node):
pass
@@ -1267,12 +1266,11 @@
}
def visit_math(self, node, math_env=''):
- # If the method is called from visit_math_block(), math_env != ''.
-
+ # Also called from `visit_math_block()` (with math_env != '').
if self.math_output not in self.math_tags:
self.document.reporter.error(
f'math-output format "{self.math_output}" not supported '
- 'falling back to "latex"')
+ 'falling back to "latex"', base_node=node)
self.math_output = 'latex'
tag = self.math_tags[self.math_output][math_env == '']
clsarg = self.math_tags[self.math_output][2]
@@ -1303,9 +1301,9 @@
try:
self.mathjax_url = self.math_output_options[0]
except IndexError:
- self.document.reporter.warning('No MathJax URL specified, '
- 'using local fallback '
- '(see config.html)')
+ self.document.reporter.warning(
+ 'No MathJax URL specified, using local fallback '
+ '(see config.html).', base_node=node)
# append configuration, if not already present in the URL:
# input LaTeX with AMS, output common HTML
if '?' not in self.mathjax_url:
@@ -1350,16 +1348,10 @@
except OSError:
raise OSError('is "latexmlmath" in your PATH?')
except SyntaxError as err:
- err_node = self.document.reporter.error(err, base_node=node)
- self.visit_system_message(err_node)
- self.body.append(self.starttag(node, 'p'))
- self.body.append(','.join(err.args))
- self.body.append('</p>\n')
- self.body.append(self.starttag(node, 'pre',
- CLASS='literal-block'))
- self.body.append(self.encode(math_code))
- self.body.append('\n</pre>\n')
- self.depart_system_message(err_node)
+ message = self.document.reporter.error(err, base_node=node)
+ message.append(nodes.literal_block('', self.encode(math_code)))
+ if self.settings.report_level <= message['level']:
+ message.walkabout(self)
raise nodes.SkipNode
# append to document body
if tag:
Modified: trunk/docutils/test/test_writers/test_html5_polyglot_misc.py
===================================================================
--- trunk/docutils/test/test_writers/test_html5_polyglot_misc.py 2023-12-14 22:38:49 UTC (rev 9500)
+++ trunk/docutils/test/test_writers/test_html5_polyglot_misc.py 2023-12-14 22:38:58 UTC (rev 9501)
@@ -175,8 +175,8 @@
class MathTestCase(unittest.TestCase):
- """Attention: This class tests the current implementation of maths support
- which is open to change in future Docutils releases. """
+ """Provisional: This class tests the current implementation of maths
+ support which is open to change in future Docutils releases. """
mathjax_script = '<script type="text/javascript" src="%s">'
default_mathjax_url = ('file:/usr/share/javascript/mathjax/MathJax.js'
Modified: trunk/docutils/test/test_writers/test_html5_polyglot_parts.py
===================================================================
--- trunk/docutils/test/test_writers/test_html5_polyglot_parts.py 2023-12-14 22:38:49 UTC (rev 9500)
+++ trunk/docutils/test/test_writers/test_html5_polyglot_parts.py 2023-12-14 22:38:58 UTC (rev 9501)
@@ -35,7 +35,7 @@
def test_publish(self):
if not with_pygments:
- del totest['code_parsing']
+ del totest['syntax_highlight']
writer_name = 'html5'
for name, (settings_overrides, cases) in totest.items():
for casenum, (case_input, case_expected) in enumerate(cases):
@@ -471,8 +471,8 @@
totest['lazy_loading'] = ({'image_loading': 'lazy',
'stylesheet_path': '',
- 'embed_stylesheet': False}, [
-
+ 'embed_stylesheet': False,
+ 'report_level': 4}, [
["""\
.. image:: dummy.png
.. image:: dummy.png
@@ -479,7 +479,7 @@
:loading: link
.. figure:: dummy.png
.. figure:: dummy.png
- :loading: link
+ :loading: embed
""",
{'fragment': '''\
<img alt="dummy.png" loading="lazy" src="dummy.png" />
@@ -584,5 +584,69 @@
}],
])
+totest['image_messages'] = ({'stylesheet_path': '',
+ 'embed_stylesheet': False,
+ 'warning_stream': '',
+ }, [
+["""\
+.. image:: dummy.png
+ :scale: 100%
+ :loading: embed
+
+.. image:: dummy.mp4
+ :scale: 100%
+""",
+{'fragment': '''\
+<img alt="dummy.png" src="dummy.png" />
+<aside class="system-message">
+<p class="system-message-title">System Message: WARNING/2 \
+(<span class="docutils literal"><string></span>, line 1)</p>
+<p>Cannot scale image!
+ Could not get size from "dummy.png":
+ [Errno 2] No such file or directory: 'dummy.png'</p>
+</aside>
+<aside class="system-message">
+<p class="system-message-title">System Message: ERROR/3 \
+(<span class="docutils literal"><string></span>, line 1)</p>
+<p>Cannot embed image "dummy.png":
+ [Errno 2] No such file or directory: 'dummy.png'</p>
+</aside>
+<video src="dummy.mp4" title="dummy.mp4">
+<a href="dummy.mp4">dummy.mp4</a>
+</video>
+<aside class="system-message">
+<p class="system-message-title">System Message: WARNING/2 \
+(<span class="docutils literal"><string></span>, line 5)</p>
+<p>Cannot scale image!
+ Could not get size from "dummy.mp4":
+ PIL cannot read video images.</p>
+</aside>
+''',
+}],
+["""\
+.. image:: https://dummy.png
+ :scale: 100%
+ :loading: embed
+""",
+{'fragment': '''\
+<img alt="https://dummy.png" src="https://dummy.png" />
+<aside class="system-message">
+<p class="system-message-title">System Message: WARNING/2 \
+(<span class="docutils literal"><string></span>, line 1)</p>
+<p>Cannot scale image!
+ Could not get size from "https://dummy.png":
+ Can only read local images.</p>
+</aside>
+<aside class="system-message">
+<p class="system-message-title">System Message: ERROR/3 \
+(<span class="docutils literal"><string></span>, line 1)</p>
+<p>Cannot embed image "https://dummy.png":
+ Can only read local images.</p>
+</aside>
+''',
+}],
+])
+
+
if __name__ == '__main__':
unittest.main()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2024-01-07 10:21:04
|
Revision: 9505
http://sourceforge.net/p/docutils/code/9505
Author: milde
Date: 2024-01-07 10:21:01 +0000 (Sun, 07 Jan 2024)
Log Message:
-----------
Continue/fix "html" writer revision.
More descriptive/correct variable names.
Newlines around block-level `<a>` elements (images with hyperlink ref).
Fix conditionals for newlines around `<img>` elements.
Report writer errors from inline nodes after the containing paragraph.
Test writer error reporting.
Fix CSS rule for inline images.
(Images with hyperlink are nested in `<a>` elements.)
Modified Paths:
--------------
trunk/docutils/HISTORY.txt
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/standalone_rst_html4css1.html
trunk/docutils/test/functional/expected/standalone_rst_html5.html
trunk/docutils/test/test_writers/test_html5_polyglot_parts.py
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2024-01-05 20:50:11 UTC (rev 9504)
+++ trunk/docutils/HISTORY.txt 2024-01-07 10:21:01 UTC (rev 9505)
@@ -99,7 +99,11 @@
* docutils/writers/_html_base.py
- - Support for video inclusion via `<video>` tags
+ - Stop setting the "footnote-reference" class value for footnote references.
+ Since 0.18, you can use the CSS selector ``[role="doc-noteref"]``.
+ - Support reading/embedding images also with "file:" URI.
+ - Warn, if image scaling fails because the image file cannot be read.
+ - Support video inclusion via `<video>` tags
(moved here from writers/html5_polyglot/__init__.py).
- New auxiliary function `HTMLTranslator.uri2imagepath()`
ensures the image file can also be read when
@@ -107,7 +111,11 @@
- Consider the root-prefix_ setting when converting an image URI
to a local filesystem path.
- New <image> attribute "loading" overrides "image-loading" setting.
+ - Write system messages for errors/warnings during the writing stage
+ (image transformations, math content conversion, ...).
+ .. _root-prefix: docs/user/config.html#root-prefix
+
* docutils/writers/latex2e/__init__.py
- Fix placement of hyperlink target (label) for tables (bug #440).
@@ -136,18 +144,7 @@
__ docs/user/config.html#theme-url
__ docs/user/config.html#theme
-* docutils/writers/_html_base.py
- - Stop setting the "footnote-reference" class value for footnote references.
- Since 0.18, you can use the CSS selector ``[role="doc-noteref"]``.
-
- - Support reading/embedding images with "file:" URIs.
-
- - Warn, if image scaling fails because the image file cannot be read.
-
-.. _root-prefix: docs/user/config.html#root-prefix
-
-
Release 0.20.1 (2023-05-17)
===========================
Modified: trunk/docutils/docutils/writers/_html_base.py
===================================================================
--- trunk/docutils/docutils/writers/_html_base.py 2024-01-05 20:50:11 UTC (rev 9504)
+++ trunk/docutils/docutils/writers/_html_base.py 2024-01-07 10:21:01 UTC (rev 9505)
@@ -355,8 +355,9 @@
self.author_in_authors = False # for html4css1
self.math_header = []
self.messages = []
- """List of system_message nodes with errors, warnings, ...
- about problems during writing. Clean up in `depart_*()` methods!
+ """Queue of system_message nodes (writing issues).
+
+ Call `report_messages()` in `depart_*_block()` methods to clean up!
"""
def astext(self):
@@ -399,9 +400,9 @@
def image_size(self, node):
# Determine the image size from the node arguments or the image file.
- # Return a (hopefully empty) list of system messages
- # and a string that is suitable as "style" argument value,
- # e.g., ``([], 'width: 4px; height: 2em;')``.
+ # Return a size declaration suitable as "style" argument value,
+ # e.g., ``'width: 4px; height: 2em;'``.
+ # TODO: consider feature-request #102?
size = [node.get('width', None), node.get('height', None)]
if 'scale' in node:
if 'width' not in node or 'height' not in node:
@@ -440,14 +441,14 @@
match = re.match(r'([0-9.]+)(\S*)$', size[i])
size[i] = '%s%s' % (factor * float(match.group(1)),
match.group(2))
- style_arg = []
- for i, _name in enumerate(('width', 'height')):
+ size_declarations = []
+ for i, dimension in enumerate(('width', 'height')):
if size[i]:
# Interpret unitless values as pixels:
if re.match(r'^[0-9.]+$', size[i]):
size[i] += 'px'
- style_arg.append('%s: %s;' % (_name, size[i]))
- return ' '.join(style_arg)
+ size_declarations.append(f'{dimension}: {size[i]};')
+ return ' '.join(size_declarations)
def stylesheet_call(self, path, adjust_path=None):
"""Return code to reference or embed stylesheet file `path`"""
@@ -1099,13 +1100,15 @@
uri = node['uri']
alt = node.get('alt', uri)
mimetype = mimetypes.guess_type(uri)[0]
+ element = '' # the HTML element (including potential children)
atts = {} # attributes for the HTML tag
+ # alignment is handled by CSS rules
if 'align' in node:
atts['class'] = 'align-%s' % node['align']
# set size with "style" attribute (more universal, accepts dimensions)
- size = self.image_size(node)
- if size:
- atts['style'] = size
+ size_declaration = self.image_size(node)
+ if size_declaration:
+ atts['style'] = size_declaration
# ``:loading:`` option (embed, link, lazy), default from setting,
# exception: only embed videos if told via directive option
@@ -1132,33 +1135,36 @@
data64 = base64.b64encode(imagedata).decode()
uri = f'data:{mimetype};base64,{data64}'
- # No newlines around inline images or if surrounded by <a>...</a>.
- if (isinstance(node.parent, nodes.TextElement)
- or (isinstance(node.parent, nodes.reference)
- and not isinstance(node.parent.parent, nodes.TextElement))):
+ # No newlines around inline images (but all images may be nested
+ # in a `reference` node which is a `TextElement` instance):
+ if (not isinstance(node.parent, nodes.TextElement)
+ or isinstance(node.parent, nodes.reference)
+ and not isinstance(node.parent.parent, nodes.TextElement)):
+ suffix = '\n'
+ else:
suffix = ''
- else:
- suffix = '\n'
+
if mimetype in self.videotypes:
atts['title'] = alt
- alt_link = node['uri'] # use original URI also when embedding
if 'controls' in node['classes']:
node['classes'].remove('controls')
atts['controls'] = 'controls'
- tag = (self.starttag(node, "video", suffix, src=uri, **atts)
- + f'<a href="{alt_link}">{alt}</a>{suffix}</video>{suffix}')
+ element = (self.starttag(node, "video", suffix, src=uri, **atts)
+ + f'<a href="{node["uri"]}">{alt}</a>{suffix}'
+ + f'</video>{suffix}')
elif mimetype == 'application/x-shockwave-flash':
atts['type'] = mimetype
- # do NOT use an empty tag: incorrect rendering in browsers
- tag = (self.starttag(node, 'object', '', data=uri, **atts)
- + alt + '</object>' + suffix)
+ element = (self.starttag(node, 'object', '', data=uri, **atts)
+ + alt + '</object>' + suffix)
else:
atts['alt'] = alt
- tag = self.emptytag(node, 'img', suffix, src=uri, **atts)
- self.body.append(tag)
+ element = self.emptytag(node, 'img', suffix, src=uri, **atts)
+ self.body.append(element)
+ if suffix: # block-element
+ self.report_messages()
def depart_image(self, node):
- self.report_messages()
+ pass
def visit_inline(self, node):
self.body.append(self.starttag(node, 'span', ''))
@@ -1366,7 +1372,7 @@
raise nodes.SkipChildren
def depart_math(self, node):
- self.report_messages()
+ pass
def visit_math_block(self, node):
math_env = pick_math_environment(node.astext())
@@ -1456,6 +1462,8 @@
if not (isinstance(node.parent, (nodes.list_item, nodes.entry))
and (len(node.parent) == 1)):
self.body.append('\n')
+ if not isinstance(node.parent, nodes.system_message):
+ self.report_messages()
def visit_problematic(self, node):
if node.hasattr('refid'):
@@ -1484,7 +1492,8 @@
raise nodes.SkipNode
def visit_reference(self, node):
- atts = {'class': 'reference'}
+ atts = {'classes': ['reference']}
+ suffix = ''
if 'refuri' in node:
atts['href'] = node['refuri']
if (self.settings.cloak_email_addresses
@@ -1491,18 +1500,17 @@
and atts['href'].startswith('mailto:')):
atts['href'] = self.cloak_mailto(atts['href'])
self.in_mailto = True
- atts['class'] += ' external'
+ atts['classes'].append('external')
else:
assert 'refid' in node, \
'References must have "refuri" or "refid" attribute.'
atts['href'] = '#' + node['refid']
- atts['class'] += ' internal'
+ atts['classes'].append('internal')
if len(node) == 1 and isinstance(node[0], nodes.image):
- atts['class'] += ' image-reference'
+ atts['classes'].append('image-reference')
if not isinstance(node.parent, nodes.TextElement):
- assert len(node) == 1 and isinstance(node[0], nodes.image)
- atts['class'] += ' image-reference'
- self.body.append(self.starttag(node, 'a', '', **atts))
+ suffix = '\n'
+ self.body.append(self.starttag(node, 'a', suffix, **atts))
def depart_reference(self, node):
self.body.append('</a>')
Modified: trunk/docutils/docutils/writers/html4css1/__init__.py
===================================================================
--- trunk/docutils/docutils/writers/html4css1/__init__.py 2024-01-05 20:50:11 UTC (rev 9504)
+++ trunk/docutils/docutils/writers/html4css1/__init__.py 2024-01-07 10:21:01 UTC (rev 9505)
@@ -595,13 +595,13 @@
del atts[att_name]
if style:
atts['style'] = ' '.join(style)
- if (isinstance(node.parent, nodes.TextElement)
- or (isinstance(node.parent, nodes.reference)
- and not isinstance(node.parent.parent, nodes.TextElement))):
- # Inline context or surrounded by <a>...</a>.
+ # No newlines around inline images.
+ if (not isinstance(node.parent, nodes.TextElement)
+ or isinstance(node.parent, nodes.reference)
+ and not isinstance(node.parent.parent, nodes.TextElement)):
+ suffix = '\n'
+ else:
suffix = ''
- else:
- suffix = '\n'
if 'align' in node:
atts['class'] = 'align-%s' % node['align']
if ext in self.object_image_types:
@@ -753,6 +753,8 @@
def depart_paragraph(self, node):
self.body.append(self.context.pop())
+ if not isinstance(node.parent, nodes.system_message):
+ self.report_messages()
# ersatz for first/last pseudo-classes
def visit_sidebar(self, node):
Modified: trunk/docutils/docutils/writers/html5_polyglot/minimal.css
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/minimal.css 2024-01-05 20:50:11 UTC (rev 9504)
+++ trunk/docutils/docutils/writers/html5_polyglot/minimal.css 2024-01-07 10:21:01 UTC (rev 9505)
@@ -272,4 +272,4 @@
}
svg { width: auto; height: auto; } /* enable scaling of SVG images */
/* inline images */
-p > img, p > svg, p > video { display: inline; }
+p img, p svg, p video { display: inline; }
Modified: trunk/docutils/test/functional/expected/standalone_rst_html4css1.html
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_html4css1.html 2024-01-05 20:50:11 UTC (rev 9504)
+++ trunk/docutils/test/functional/expected/standalone_rst_html4css1.html 2024-01-07 10:21:01 UTC (rev 9505)
@@ -38,7 +38,7 @@
</pre>
</td></tr>
<tr><th class="docinfo-name">Contact:</th>
-<td><a class="first last reference external" href="mailto:goodger@python.org">goodger@python.org</a></td></tr>
+<td><a class="reference external first last" href="mailto:goodger@python.org">goodger@python.org</a></td></tr>
<tr><th class="docinfo-name">Authors:</th>
<td>Me
<br />Myself
@@ -587,7 +587,9 @@
<div class="section" id="images-and-figures">
<h3><a class="toc-backref" href="#toc-entry-47">2.14.2 Images and Figures</a></h3>
<p>An image directive (also clickable -- a hyperlink reference):</p>
-<a class="reference internal image-reference" href="#directives"><img alt="../../../docs/user/rst/images/title.png" class="class1 class2" src="../../../docs/user/rst/images/title.png" style="width: 70%;" /></a>
+<a class="reference internal image-reference" href="#directives">
+<img alt="../../../docs/user/rst/images/title.png" class="class1 class2" src="../../../docs/user/rst/images/title.png" style="width: 70%;" />
+</a>
<p>Image with multiple IDs:</p>
<span id="image-target-2"></span><span id="image-target-1"></span><img alt="../../../docs/user/rst/images/biohazard.png" id="image-target-3" src="../../../docs/user/rst/images/biohazard.png" />
<p>A centered image:</p>
@@ -1314,7 +1316,9 @@
but clipped in an <tt class="docutils literal"><object></tt> or SVG <tt class="docutils literal"><image></tt> node.</p>
<object class="align-left" data="../../../docs/user/rst/images/biohazard-scaling.svg" style="height: 1.2em;" type="image/svg+xml">../../../docs/user/rst/images/biohazard-scaling.svg</object>
<p>Image with <cite>viewBox</cite>, 1.2 em high, left aligned and <object data="../../../docs/user/rst/images/biohazard-scaling.svg" style="height: 1.2em;" type="image/svg+xml">inline-svg</object> inline.</p>
-<a class="reference internal image-reference" href="#svg-images"><object class="align-left" data="../../../docs/user/rst/images/biohazard-scaling.svg" style="width: 15mm; height: 5mm;" type="image/svg+xml">../../../docs/user/rst/images/biohazard-scaling.svg</object></a>
+<a class="reference internal image-reference" href="#svg-images">
+<object class="align-left" data="../../../docs/user/rst/images/biohazard-scaling.svg" style="width: 15mm; height: 5mm;" type="image/svg+xml">../../../docs/user/rst/images/biohazard-scaling.svg</object>
+</a>
<p>Image with <cite>viewBox</cite>, 5 mm x 15 mm, with hyperlink reference set in rST.</p>
<object class="align-left" data="../../../docs/user/rst/images/biohazard.svg" style="width: 15mm; height: 5mm;" type="image/svg+xml">../../../docs/user/rst/images/biohazard.svg</object>
<p>Image without <cite>viewBox</cite>, 5 mm x 15 mm.</p>
@@ -1324,7 +1328,9 @@
<p>Image with embedded bitmap and hyperlink, without <cite>viewBox</cite>.
Does not scale in <tt class="docutils literal"><object></tt> node.</p>
<object class="align-left" data="../input/data/object-with-hyperlink.svg" style="width: 2.4em;" type="image/svg+xml">../input/data/object-with-hyperlink.svg</object>
-<a class="reference external image-reference" href="http://oreillymedia.github.io/svg-essentials-examples/ch14/animated_clock_js.svg"><object class="align-right" data="http://oreillymedia.github.io/svg-essentials-examples/ch14/animated_clock_js.svg" style="height: 3em;" type="image/svg+xml">[animated clock]</object></a>
+<a class="reference external image-reference" href="http://oreillymedia.github.io/svg-essentials-examples/ch14/animated_clock_js.svg">
+<object class="align-right" data="http://oreillymedia.github.io/svg-essentials-examples/ch14/animated_clock_js.svg" style="height: 3em;" type="image/svg+xml">[animated clock]</object>
+</a>
<p>Hyperlinks and script actions attached to SVG elements work in images
included as <tt class="docutils literal"><object></tt> but fail in images included as <tt class="docutils literal"><img></tt>.
Hyperlinks specified in the rST (<tt class="docutils literal">:target:</tt> directive option) always
Modified: trunk/docutils/test/functional/expected/standalone_rst_html5.html
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_html5.html 2024-01-05 20:50:11 UTC (rev 9504)
+++ trunk/docutils/test/functional/expected/standalone_rst_html5.html 2024-01-07 10:21:01 UTC (rev 9505)
@@ -585,7 +585,9 @@
<section id="images-and-figures">
<h4><a class="toc-backref" href="#toc-entry-56" role="doc-backlink"><span class="sectnum">2.14.2 </span>Images and Figures</a></h4>
<p>An image directive (also clickable -- a hyperlink reference):</p>
-<a class="reference internal image-reference" href="#directives"><img alt="../../../docs/user/rst/images/title.png" class="class1 class2" src="../../../docs/user/rst/images/title.png" style="width: 70%;" /></a>
+<a class="reference internal image-reference" href="#directives">
+<img alt="../../../docs/user/rst/images/title.png" class="class1 class2" src="../../../docs/user/rst/images/title.png" style="width: 70%;" />
+</a>
<p>Image with multiple IDs:</p>
<span id="image-target-2"></span><span id="image-target-1"></span><img alt="../../../docs/user/rst/images/biohazard.png" id="image-target-3" src="../../../docs/user/rst/images/biohazard.png" />
<p>A centered image:</p>
@@ -1823,7 +1825,9 @@
but clipped in an <span class="docutils literal"><object></span> or SVG <span class="docutils literal"><image></span> node.</p>
<img alt="../../../docs/user/rst/images/biohazard-scaling.svg" class="align-left" src="../../../docs/user/rst/images/biohazard-scaling.svg" style="height: 1.2em;" />
<p>Image with <cite>viewBox</cite>, 1.2 em high, left aligned and <img alt="inline-svg" src="../../../docs/user/rst/images/biohazard-scaling.svg" style="height: 1.2em;" /> inline.</p>
-<a class="reference internal image-reference" href="#svg-images"><img alt="../../../docs/user/rst/images/biohazard-scaling.svg" class="align-left" src="../../../docs/user/rst/images/biohazard-scaling.svg" style="width: 15mm; height: 5mm;" /></a>
+<a class="reference internal image-reference" href="#svg-images">
+<img alt="../../../docs/user/rst/images/biohazard-scaling.svg" class="align-left" src="../../../docs/user/rst/images/biohazard-scaling.svg" style="width: 15mm; height: 5mm;" />
+</a>
<p>Image with <cite>viewBox</cite>, 5 mm x 15 mm, with hyperlink reference set in rST.</p>
<img alt="../../../docs/user/rst/images/biohazard.svg" class="align-left" src="../../../docs/user/rst/images/biohazard.svg" style="width: 15mm; height: 5mm;" />
<p>Image without <cite>viewBox</cite>, 5 mm x 15 mm.</p>
@@ -1833,7 +1837,9 @@
<p>Image with embedded bitmap and hyperlink, without <cite>viewBox</cite>.
Does not scale in <span class="docutils literal"><object></span> node.</p>
<img alt="../input/data/object-with-hyperlink.svg" class="align-left" src="../input/data/object-with-hyperlink.svg" style="width: 2.4em;" />
-<a class="reference external image-reference" href="http://oreillymedia.github.io/svg-essentials-examples/ch14/animated_clock_js.svg"><img alt="[animated clock]" class="align-right" src="http://oreillymedia.github.io/svg-essentials-examples/ch14/animated_clock_js.svg" style="height: 3em;" /></a>
+<a class="reference external image-reference" href="http://oreillymedia.github.io/svg-essentials-examples/ch14/animated_clock_js.svg">
+<img alt="[animated clock]" class="align-right" src="http://oreillymedia.github.io/svg-essentials-examples/ch14/animated_clock_js.svg" style="height: 3em;" />
+</a>
<p>Hyperlinks and script actions attached to SVG elements work in images
included as <span class="docutils literal"><object></span> but fail in images included as <span class="docutils literal"><img></span>.
Hyperlinks specified in the rST (<span class="docutils literal">:target:</span> directive option) always
Modified: trunk/docutils/test/test_writers/test_html5_polyglot_parts.py
===================================================================
--- trunk/docutils/test/test_writers/test_html5_polyglot_parts.py 2024-01-05 20:50:11 UTC (rev 9504)
+++ trunk/docutils/test/test_writers/test_html5_polyglot_parts.py 2024-01-07 10:21:01 UTC (rev 9505)
@@ -513,6 +513,9 @@
'embed_stylesheet': False,
'report_level': 4}, [
["""\
+Lazy loading by default, overridden by :loading: option
+("cannot embed" warning ignored).
+
.. image:: dummy.png
.. image:: dummy.png
:loading: link
@@ -521,6 +524,8 @@
:loading: embed
""",
{'fragment': """\
+<p>Lazy loading by default, overridden by :loading: option
+("cannot embed" warning ignored).</p>
<img alt="dummy.png" loading="lazy" src="dummy.png" />
<img alt="dummy.png" src="dummy.png" />
<figure>
@@ -686,8 +691,29 @@
</aside>
""",
}],
+[r"""Broken :math:`\sin \my`.
+""",
+{'fragment': """\
+<p>Broken \\sin \\my.</p>
+<aside class="system-message">
+<p class="system-message-title">System Message: ERROR/3 (<span class="docutils literal"><string></span>, line 1)</p>
+<p>Unknown LaTeX command: \\my</p>
+</aside>
+"""}],
])
+totest['no_system_messages'] = ({'stylesheet_path': '',
+ 'embed_stylesheet': False,
+ 'math_output': 'mathml',
+ 'report_level': 4,
+ 'warning_stream': '',
+ }, [
+[r"""Broken :math:`\sin \my`.
+""",
+{'fragment': '<p>Broken \\sin \\my.</p>\n'
+}],
+])
+
if __name__ == '__main__':
unittest.main()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2024-01-07 10:21:15
|
Revision: 9506
http://sourceforge.net/p/docutils/code/9506
Author: milde
Date: 2024-01-07 10:21:12 +0000 (Sun, 07 Jan 2024)
Log Message:
-----------
Simplify `frontend.validate_*()` function interface.
Allow `frontend.validate_*()` functions to be called with just
the "value" argument.
Keep the legacy interface for use with "optparse".
Modified Paths:
--------------
trunk/docutils/HISTORY.txt
trunk/docutils/docutils/frontend.py
trunk/docutils/test/test_settings.py
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2024-01-07 10:21:01 UTC (rev 9505)
+++ trunk/docutils/HISTORY.txt 2024-01-07 10:21:12 UTC (rev 9506)
@@ -30,6 +30,11 @@
- The <image> element accepts the new attribute "loading".
+* docutils/frontend.py
+
+ - Allow `validate_*()` functions to be called with just the "value"
+ argument but keep the legacy interface for use with optparse.
+
* docutils/io.py
- Simpler and more secure `input encoding`_ default behaviour:
Modified: trunk/docutils/docutils/frontend.py
===================================================================
--- trunk/docutils/docutils/frontend.py 2024-01-07 10:21:01 UTC (rev 9505)
+++ trunk/docutils/docutils/frontend.py 2024-01-07 10:21:12 UTC (rev 9506)
@@ -27,10 +27,10 @@
Also exports the following functions:
Interface function:
- `get_default_settings()`. New in 0.19.
+ `get_default_settings()`. New in 0.19.
Option callbacks:
- `store_multiple()`, `read_config_file()`. Deprecated.
+ `store_multiple()`, `read_config_file()`. Deprecated.
Setting validators:
`validate_encoding()`, `validate_encoding_error_handler()`,
@@ -90,8 +90,13 @@
parser.values.update(new_settings, parser)
-def validate_encoding(setting, value, option_parser,
+def validate_encoding(setting, value=None, option_parser=None,
config_parser=None, config_section=None):
+ # All arguments except `value` are ignored
+ # (kept for compatibility with "optparse" module).
+ # If there is only one positional argument, it is interpreted as `value`.
+ if value is None:
+ value = setting
if value == '':
return None # allow overwriting a config file value
try:
@@ -102,8 +107,13 @@
return value
-def validate_encoding_error_handler(setting, value, option_parser,
+def validate_encoding_error_handler(setting, value=None, option_parser=None,
config_parser=None, config_section=None):
+ # All arguments except `value` are ignored
+ # (kept for compatibility with "optparse" module).
+ # If there is only one positional argument, it is interpreted as `value`.
+ if value is None:
+ value = setting
try:
codecs.lookup_error(value)
except LookupError:
@@ -119,13 +129,11 @@
setting, value, option_parser, config_parser=None, config_section=None):
"""
Side-effect: if an error handler is included in the value, it is inserted
- into the appropriate place as if it was a separate setting/option.
+ into the appropriate place as if it were a separate setting/option.
"""
if ':' in value:
encoding, handler = value.split(':')
- validate_encoding_error_handler(
- setting + '_error_handler', handler, option_parser,
- config_parser, config_section)
+ validate_encoding_error_handler(handler)
if config_parser:
config_parser.set(config_section, setting + '_error_handler',
handler)
@@ -133,42 +141,57 @@
setattr(option_parser.values, setting + '_error_handler', handler)
else:
encoding = value
- validate_encoding(setting, encoding, option_parser,
- config_parser, config_section)
- return encoding
+ return validate_encoding(encoding)
-def validate_boolean(setting, value, option_parser,
+def validate_boolean(setting, value=None, option_parser=None,
config_parser=None, config_section=None):
"""Check/normalize boolean settings:
True: '1', 'on', 'yes', 'true'
False: '0', 'off', 'no','false', ''
+
+ All arguments except `value` are ignored
+ (kept for compatibility with "optparse" module).
+ If there is only one positional argument, it is interpreted as `value`.
"""
+ if value is None:
+ value = setting
if isinstance(value, bool):
return value
try:
- return option_parser.booleans[value.strip().lower()]
+ return OptionParser.booleans[value.strip().lower()]
except KeyError:
raise LookupError('unknown boolean value: "%s"' % value)
-def validate_ternary(setting, value, option_parser,
+def validate_ternary(setting, value=None, option_parser=None,
config_parser=None, config_section=None):
"""Check/normalize three-value settings:
True: '1', 'on', 'yes', 'true'
False: '0', 'off', 'no','false', ''
any other value: returned as-is.
+
+ All arguments except `value` are ignored
+ (kept for compatibility with "optparse" module).
+ If there is only one positional argument, it is interpreted as `value`.
"""
+ if value is None:
+ value = setting
if isinstance(value, bool) or value is None:
return value
try:
- return option_parser.booleans[value.strip().lower()]
+ return OptionParser.booleans[value.strip().lower()]
except KeyError:
return value
-def validate_nonnegative_int(setting, value, option_parser,
+def validate_nonnegative_int(setting, value=None, option_parser=None,
config_parser=None, config_section=None):
+ # All arguments except `value` are ignored
+ # (kept for compatibility with "optparse" module).
+ # If there is only one positional argument, it is interpreted as `value`.
+ if value is None:
+ value = setting
value = int(value)
if value < 0:
raise ValueError('negative value; must be positive or zero')
@@ -175,19 +198,30 @@
return value
-def validate_threshold(setting, value, option_parser,
+def validate_threshold(setting, value=None, option_parser=None,
config_parser=None, config_section=None):
+ # All arguments except `value` are ignored
+ # (kept for compatibility with "optparse" module).
+ # If there is only one positional argument, it is interpreted as `value`.
+ if value is None:
+ value = setting
try:
return int(value)
except ValueError:
try:
- return option_parser.thresholds[value.lower()]
+ return OptionParser.thresholds[value.lower()]
except (KeyError, AttributeError):
raise LookupError('unknown threshold: %r.' % value)
def validate_colon_separated_string_list(
- setting, value, option_parser, config_parser=None, config_section=None):
+ setting, value=None, option_parser=None,
+ config_parser=None, config_section=None):
+ # All arguments except `value` are ignored
+ # (kept for compatibility with "optparse" module).
+ # If there is only one positional argument, it is interpreted as `value`.
+ if value is None:
+ value = setting
if not isinstance(value, list):
value = value.split(':')
else:
@@ -196,10 +230,16 @@
return value
-def validate_comma_separated_list(setting, value, option_parser,
+def validate_comma_separated_list(setting, value=None, option_parser=None,
config_parser=None, config_section=None):
"""Check/normalize list arguments (split at "," and strip whitespace).
+
+ All arguments except `value` are ignored
+ (kept for compatibility with "optparse" module).
+ If there is only one positional argument, it is interpreted as `value`.
"""
+ if value is None:
+ value = setting
# `value` may be ``bytes``, ``str``, or a ``list`` (when given as
# command line option and "action" is "append").
if not isinstance(value, list):
@@ -212,8 +252,13 @@
return value
-def validate_url_trailing_slash(
- setting, value, option_parser, config_parser=None, config_section=None):
+def validate_url_trailing_slash(setting, value=None, option_parser=None,
+ config_parser=None, config_section=None):
+ # All arguments except `value` are ignored
+ # (kept for compatibility with "optparse" module).
+ # If there is only one positional argument, it is interpreted as `value`.
+ if value is None:
+ value = setting
if not value:
return './'
elif value.endswith('/'):
@@ -222,8 +267,13 @@
return value + '/'
-def validate_dependency_file(setting, value, option_parser,
+def validate_dependency_file(setting, value=None, option_parser=None,
config_parser=None, config_section=None):
+ # All arguments except `value` are ignored
+ # (kept for compatibility with "optparse" module).
+ # If there is only one positional argument, it is interpreted as `value`.
+ if value is None:
+ value = setting
try:
return utils.DependencyList(value)
except OSError:
@@ -231,11 +281,15 @@
return utils.DependencyList(None)
-def validate_strip_class(setting, value, option_parser,
+def validate_strip_class(setting, value=None, option_parser=None,
config_parser=None, config_section=None):
+ # All arguments except `value` are ignored
+ # (kept for compatibility with "optparse" module).
+ # If there is only one positional argument, it is interpreted as `value`.
+ if value is None:
+ value = setting
# value is a comma separated string list:
- value = validate_comma_separated_list(setting, value, option_parser,
- config_parser, config_section)
+ value = validate_comma_separated_list(value)
# validate list elements:
for cls in value:
normalized = docutils.nodes.make_id(cls)
@@ -245,15 +299,20 @@
return value
-def validate_smartquotes_locales(setting, value, option_parser,
+def validate_smartquotes_locales(setting, value=None, option_parser=None,
config_parser=None, config_section=None):
"""Check/normalize a comma separated list of smart quote definitions.
- Return a list of (language-tag, quotes) string tuples."""
+ Return a list of (language-tag, quotes) string tuples.
+ All arguments except `value` are ignored
+ (kept for compatibility with "optparse" module).
+ If there is only one positional argument, it is interpreted as `value`.
+ """
+ if value is None:
+ value = setting
# value is a comma separated string list:
- value = validate_comma_separated_list(setting, value, option_parser,
- config_parser, config_section)
+ value = validate_comma_separated_list(value)
# validate list elements
lc_quotes = []
for item in value:
Modified: trunk/docutils/test/test_settings.py
===================================================================
--- trunk/docutils/test/test_settings.py 2024-01-07 10:21:01 UTC (rev 9505)
+++ trunk/docutils/test/test_settings.py 2024-01-07 10:21:12 UTC (rev 9506)
@@ -287,10 +287,8 @@
)
def test_validate_boolean(self):
- for t in self.boolean_settings:
- self.assertEqual(
- frontend.validate_boolean(None, t[0], self.option_parser),
- t[1])
+ for v, result in self.boolean_settings:
+ self.assertEqual(frontend.validate_boolean(v), result)
def test_validate_ternary(self):
tests = (
@@ -297,46 +295,50 @@
('500V', '500V'),
('parrot', 'parrot'),
)
- for t in self.boolean_settings + tests:
+ for v, result in self.boolean_settings + tests:
+ self.assertEqual(frontend.validate_ternary(v), result)
+
+ def test_validate_threshold(self):
+ tests = (('1', 1),
+ ('info', 1),
+ ('warning', 2),
+ ('error', 3),
+ ('severe', 4),
+ ('none', 5),
+ )
+ for v, result in tests:
self.assertEqual(
- frontend.validate_ternary(None, t[0], self.option_parser),
- t[1])
+ frontend.validate_threshold(v), result)
+ with self.assertRaisesRegex(LookupError, "unknown threshold: 'debug'"):
+ frontend.validate_threshold('debug')
def test_validate_colon_separated_string_list(self):
- tests = (
- ('a', ['a']),
- ('a:b', ['a', 'b']),
- (['a'], ['a']),
- (['a', 'b:c'], ['a', 'b', 'c']),
- )
- for t in tests:
- self.assertEqual(frontend.validate_colon_separated_string_list(
- None, t[0], None),
- t[1])
+ tests = (('a', ['a']),
+ ('a:b', ['a', 'b']),
+ (['a'], ['a']),
+ (['a', 'b:c'], ['a', 'b', 'c']),
+ )
+ for v, result in tests:
+ self.assertEqual(
+ frontend.validate_colon_separated_string_list(v), result)
def test_validate_comma_separated_list(self):
- tests = (
- ('a', ['a']),
- ('a,b', ['a', 'b']),
- (['a'], ['a']),
- (['a', 'b,c'], ['a', 'b', 'c']),
- )
- for t in tests:
- self.assertEqual(
- frontend.validate_comma_separated_list(None, t[0], None),
- t[1])
+ tests = (('a', ['a']),
+ ('a,b', ['a', 'b']),
+ (['a'], ['a']),
+ (['a', 'b,c'], ['a', 'b', 'c']),
+ )
+ for v, result in tests:
+ self.assertEqual(frontend.validate_comma_separated_list(v), result)
def test_validate_url_trailing_slash(self):
- tests = (
- ('', './'),
- (None, './'),
- ('http://example.org', 'http://example.org/'),
- ('http://example.org/', 'http://example.org/'),
- )
- for t in tests:
- self.assertEqual(
- frontend.validate_url_trailing_slash(None, t[0], None),
- t[1])
+ tests = (('', './'),
+ (None, './'),
+ ('http://example.org', 'http://example.org/'),
+ ('http://example.org/', 'http://example.org/'),
+ )
+ for v, result in tests:
+ self.assertEqual(frontend.validate_url_trailing_slash(v), result)
def test_validate_smartquotes_locales(self):
tests = (
@@ -345,10 +347,8 @@
([('sd', '«»°°'), 'ds:°°«»'], [('sd', '«»°°'), ('ds', '°°«»')]),
('frs:« : »:((:))', [('frs', ['« ', ' »', '((', '))'])]),
)
- for t in tests:
- self.assertEqual(
- frontend.validate_smartquotes_locales(None, t[0], None),
- t[1])
+ for v, result in tests:
+ self.assertEqual(frontend.validate_smartquotes_locales(v), result)
def test_set_conditions_deprecation_warning(self):
reporter = utils.Reporter('test', 1, 4)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2024-01-07 10:21:26
|
Revision: 9507
http://sourceforge.net/p/docutils/code/9507
Author: milde
Date: 2024-01-07 10:21:21 +0000 (Sun, 07 Jan 2024)
Log Message:
-----------
New function `frontend.validate_math_output()`.
Define/Use a dedicated validating function for the value of the "math_output"
configuration setting.
Modified Paths:
--------------
trunk/docutils/HISTORY.txt
trunk/docutils/docutils/frontend.py
trunk/docutils/docutils/writers/_html_base.py
trunk/docutils/test/test_settings.py
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2024-01-07 10:21:12 UTC (rev 9506)
+++ trunk/docutils/HISTORY.txt 2024-01-07 10:21:21 UTC (rev 9507)
@@ -34,6 +34,7 @@
- Allow `validate_*()` functions to be called with just the "value"
argument but keep the legacy interface for use with optparse.
+ - New function `frontend.validate_math_output()`.
* docutils/io.py
Modified: trunk/docutils/docutils/frontend.py
===================================================================
--- trunk/docutils/docutils/frontend.py 2024-01-07 10:21:12 UTC (rev 9506)
+++ trunk/docutils/docutils/frontend.py 2024-01-07 10:21:21 UTC (rev 9507)
@@ -252,6 +252,42 @@
return value
+def validate_math_output(setting, value=None, option_parser=None,
+ config_parser=None, config_section=None):
+ """Check "math-output" setting, return list with "format" and "options".
+
+ See also https://docutils.sourceforge.io/docs/user/config.html#math-output
+
+ Argument list for compatibility with "optparse" module.
+ All arguments except `value` are ignored.
+ If there is only one positional argument, it is interpreted as `value`.
+ """
+ if value is None:
+ value = setting
+
+ formats = ('html', 'latex', 'mathml', 'mathjax')
+ tex2mathml_converters = ('', 'latexml', 'ttm', 'blahtexml', 'pandoc')
+
+ if not value:
+ return []
+ values = value.split(maxsplit=1)
+ format = values[0].lower()
+ try:
+ options = values[1]
+ except IndexError:
+ options = ''
+ if format not in formats:
+ raise LookupError(f'Unknown math output format: "{value}",\n'
+ f' choose from {formats}.')
+ if format == 'mathml':
+ converter = options.lower()
+ if converter not in tex2mathml_converters:
+ raise LookupError(f'MathML converter "{options}" not supported,\n'
+ f' choose from {tex2mathml_converters}.')
+ options = converter
+ return [format, options]
+
+
def validate_url_trailing_slash(setting, value=None, option_parser=None,
config_parser=None, config_section=None):
# All arguments except `value` are ignored
Modified: trunk/docutils/docutils/writers/_html_base.py
===================================================================
--- trunk/docutils/docutils/writers/_html_base.py 2024-01-07 10:21:12 UTC (rev 9506)
+++ trunk/docutils/docutils/writers/_html_base.py 2024-01-07 10:21:21 UTC (rev 9507)
@@ -117,7 +117,8 @@
'or "LaTeX") and option(s). '
'(default: "HTML math.css")',
['--math-output'],
- {'default': 'HTML math.css'}),
+ {'default': 'HTML math.css',
+ 'validator': frontend.validate_math_output}),
('Prepend an XML declaration. ',
['--xml-declaration'],
{'default': False, 'action': 'store_true',
@@ -300,9 +301,12 @@
FutureWarning, stacklevel=8)
self.image_loading = getattr(settings,
'image_loading', _image_loading_default)
- self.math_output = settings.math_output.split()
- self.math_output_options = self.math_output[1:]
- self.math_output = self.math_output[0].lower()
+ # backwards compatibiltiy: validate/convert programatically set strings
+ if isinstance(self.settings.math_output, str):
+ self.settings.math_output = frontend.validate_math_output(
+ self.settings.math_output)
+ (self.math_output,
+ self.math_options) = self.settings.math_output
# set up "parts" (cf. docs/api/publisher.html#publish-parts-details)
#
@@ -1276,11 +1280,6 @@
def visit_math(self, node, math_env=''):
# Also called from `visit_math_block()` (with math_env != '').
- if self.math_output not in self.math_tags:
- self.document.reporter.error(
- f'math-output format "{self.math_output}" not supported '
- 'falling back to "latex"', base_node=node)
- self.math_output = 'latex'
# LaTeX container
wrappers = {
# math_mode: (inline, block)
@@ -1291,8 +1290,8 @@
}
wrapper = wrappers[self.math_output][math_env != '']
if (self.math_output == 'mathml'
- and (not self.math_output_options
- or self.math_output_options[0] == 'blahtexml')):
+ and (not self.math_options
+ or self.math_options == 'blahtexml')):
wrapper = None
# get and wrap content
math_code = node.astext().translate(unichar2tex.uni2tex_table)
@@ -1305,9 +1304,9 @@
if self.math_output in ('latex', 'mathjax'):
math_code = self.encode(math_code)
if self.math_output == 'mathjax' and not self.math_header:
- try:
- self.mathjax_url = self.math_output_options[0]
- except IndexError:
+ if self.math_options:
+ self.mathjax_url = self.math_options
+ else:
self.document.reporter.warning(
'No MathJax URL specified, using local fallback '
'(see config.html).', base_node=node)
@@ -1317,11 +1316,11 @@
self.mathjax_url += '?config=TeX-AMS_CHTML'
self.math_header = [self.mathjax_script % self.mathjax_url]
elif self.math_output == 'html':
- if self.math_output_options and not self.math_header:
+ if self.math_options and not self.math_header:
self.math_header = [self.stylesheet_call(
utils.find_file_in_dirs(s, self.settings.stylesheet_dirs),
adjust_path=True)
- for s in self.math_output_options[0].split(',')]
+ for s in self.math_options.split(',')]
# TODO: fix display mode in matrices and fractions
math2html.DocumentParameters.displaymode = (math_env != '')
math_code = math2html.math2html(math_code)
@@ -1329,7 +1328,7 @@
if 'XHTML 1' in self.doctype:
self.doctype = self.doctype_mathml
self.content_type = self.content_type_mathml
- converter = ' '.join(self.math_output_options).lower()
+ converter = self.math_options
try:
if converter == 'latexml':
math_code = tex2mathml_extern.latexml(
Modified: trunk/docutils/test/test_settings.py
===================================================================
--- trunk/docutils/test/test_settings.py 2024-01-07 10:21:12 UTC (rev 9506)
+++ trunk/docutils/test/test_settings.py 2024-01-07 10:21:21 UTC (rev 9507)
@@ -331,6 +331,29 @@
for v, result in tests:
self.assertEqual(frontend.validate_comma_separated_list(v), result)
+ def test_validate_math_output(self):
+ tests = (('', []),
+ ('LaTeX ', ['latex', '']),
+ ('MathML', ['mathml', '']),
+ ('MathML PanDoc', ['mathml', 'pandoc']),
+ ('HTML math.css, X.css', ['html', 'math.css, X.css']),
+ ('MathJax /MathJax.js', ['mathjax', '/MathJax.js']),
+ )
+ for v, result in tests:
+ self.assertEqual(frontend.validate_math_output(v), result)
+
+ def test_validate_math_output_errors(self):
+ tests = (('XML', 'Unknown math output format: "XML",\n'
+ " choose from ('html', 'latex', 'mathml', 'mathjax')."),
+ ('MathML blame', 'MathML converter "blame" not supported,\n'
+ " choose from ('', 'latexml', 'ttm', 'blahtexml', "
+ "'pandoc')."),
+ )
+ for value, message in tests:
+ with self.assertRaises(LookupError) as cm:
+ frontend.validate_math_output(value)
+ self.assertEqual(message, str(cm.exception))
+
def test_validate_url_trailing_slash(self):
tests = (('', './'),
(None, './'),
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2024-01-12 11:32:33
|
Revision: 9510
http://sourceforge.net/p/docutils/code/9510
Author: milde
Date: 2024-01-12 11:32:31 +0000 (Fri, 12 Jan 2024)
Log Message:
-----------
Style fixes and todo note.
Fix trailing backslashes and overlong lines after warning from flake8.
Add todo note and link for "Docutils Link List" updating.
Modified Paths:
--------------
trunk/docutils/docs/ref/rst/mathematics.txt
trunk/docutils/docs/user/links.txt
trunk/docutils/docutils/writers/manpage.py
Modified: trunk/docutils/docs/ref/rst/mathematics.txt
===================================================================
--- trunk/docutils/docs/ref/rst/mathematics.txt 2024-01-09 23:28:57 UTC (rev 9509)
+++ trunk/docutils/docs/ref/rst/mathematics.txt 2024-01-12 11:32:31 UTC (rev 9510)
@@ -936,7 +936,7 @@
Without additional packages, LaTeX supports "blackboard-bold" only for
capital Latin letters.
Unicode supports also small Latin letters, some Greek letters, and digits:
-`\mathbb{A \ldots Z a \ldots z}
+`\mathbb{A \ldots Z a \ldots z}
\mathbb\Gamma \mathbb{\Pi} \mathbb {\Sigma} \mathbb\gamma \mathbb \pi
\mathbb{0 \ldots 9}`.
@@ -1058,15 +1058,15 @@
.. math::
\left.( b \right) \ \bigl( b \Bigr) \ \biggl( b \Biggr)
- \quad
+ \quad
\left.[ b \right] \ \bigl[ b \Bigr] \ \biggl[ b \Biggr]
- \quad
+ \quad
\left.\{ b \right\} \ \bigl\{ b \Bigr\} \ \biggl\{ b \Biggr\}
- \quad
+ \quad
\left.\langle b \right\rangle \ \bigl\langle b \Bigr\rangle \ \biggl\langle b \Biggr\rangle
\left.\lceil b \right\rceil \ \bigl\lceil b \Bigr\rceil \ \biggl\lceil b \Biggr\rceil
- \quad
+ \quad
\left.\lfloor b \right\rfloor \ \bigl\lfloor b \Bigr\rfloor \ \biggl\lfloor b \Biggr\rfloor
\quad
\left.\lvert b \right\rvert \ \bigl\lvert b \Bigr\rvert \ \biggl\lvert b \Biggr\rvert
@@ -1083,11 +1083,11 @@
.. math::
\left.| b \right| \ \bigl| b \Bigr| \ \biggl| b \Biggr|
- \quad
+ \quad
\left.\vert b \right\vert \ \bigl\vert b \Bigr\vert \ \biggl\vert b \Biggr\vert
- \quad
+ \quad
\left.\| b \right\| \ \bigl\| b \Bigr\| \ \biggl\| b \Biggr\|
- \quad
+ \quad
\left.\Vert b \right\Vert \ \bigl\Vert b \Bigr\Vert \ \biggl\Vert b \Biggr\Vert
\left.\arrowvert b \right\arrowvert \ \bigl\arrowvert b \Bigr\arrowvert \ \biggl\arrowvert b \Biggr\arrowvert
Modified: trunk/docutils/docs/user/links.txt
===================================================================
--- trunk/docutils/docs/user/links.txt 2024-01-09 23:28:57 UTC (rev 9509)
+++ trunk/docutils/docs/user/links.txt 2024-01-12 11:32:31 UTC (rev 9510)
@@ -456,3 +456,6 @@
.. _rst2outline: https://docutils.sourceforge.io/sandbox/rst2outline/
* Pandoc_ can also be used to produce slides
+
+.. TODO: update with input from
+ https://stackoverflow.com/questions/2746692/restructuredtext-tool-support
Modified: trunk/docutils/docutils/writers/manpage.py
===================================================================
--- trunk/docutils/docutils/writers/manpage.py 2024-01-09 23:28:57 UTC (rev 9509)
+++ trunk/docutils/docutils/writers/manpage.py 2024-01-12 11:32:31 UTC (rev 9510)
@@ -1079,8 +1079,7 @@
if not self._has_a_table:
self._has_a_table = True
# the comment to hint that preprocessor tbl should be called
- self.head.insert(0, "'\\\" t\n")
- # single apostrophe, backslash, double apostroph, blank, character-t
+ self.head.insert(0, "'\\\" t\n") # ``'\" t`` + newline
def depart_table(self, node):
self.ensure_eol()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2024-01-13 09:50:10
|
Revision: 9511
http://sourceforge.net/p/docutils/code/9511
Author: milde
Date: 2024-01-13 09:50:07 +0000 (Sat, 13 Jan 2024)
Log Message:
-----------
Refactor/fix HTML math handling.
Use custom exception `utils.math.MathSyntaxError` instead of
abusing `SyntaxError` for LaTeX math syntax errors.
Unify interface of LaTeX -> MathML conversion functions.
Run external MathML converters with `subprocess.run()`.
Revise pre- and post-processing.
Improve error reporting.
Use WARNING instead of ERROR for TeX to MathML conversion errors.
(The source is included in the output as TeX code, so no data is lost.)
Provisional test script for external TeX to MathML converters.
(Placed in a separate directory not to be run by "alltests".
It tests a rather arcane use case, requires optional helpers, and is slow.)
Modified Paths:
--------------
trunk/docutils/HISTORY.txt
trunk/docutils/docutils/utils/math/__init__.py
trunk/docutils/docutils/utils/math/latex2mathml.py
trunk/docutils/docutils/utils/math/tex2mathml_extern.py
trunk/docutils/docutils/writers/_html_base.py
trunk/docutils/docutils/writers/html4css1/html4css1.css
trunk/docutils/docutils/writers/html5_polyglot/minimal.css
trunk/docutils/test/test_writers/test_html5_polyglot_parts.py
Added Paths:
-----------
trunk/docutils/test/extra/
trunk/docutils/test/extra/test_math_conversion.py
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2024-01-12 11:32:31 UTC (rev 9510)
+++ trunk/docutils/HISTORY.txt 2024-01-13 09:50:07 UTC (rev 9511)
@@ -88,6 +88,13 @@
- Consider the root-prefix_ setting when including files with
"include", "raw", or "csv-table" directives.
+* docutils/utils/math/*
+
+ - Use custom exception `utils.math.MathError` instead of
+ abusing `SyntaxError` for LaTeX math syntax errors.
+ - Unify interface of LaTeX -> MathML conversion functions.
+ Improve error reporting.
+
* docutils/utils/roman.py
- Update to version `1.4 <https://pypi.org/project/roman/4.1/>`__.
Modified: trunk/docutils/docutils/utils/math/__init__.py
===================================================================
--- trunk/docutils/docutils/utils/math/__init__.py 2024-01-12 11:32:31 UTC (rev 9510)
+++ trunk/docutils/docutils/utils/math/__init__.py 2024-01-13 09:50:07 UTC (rev 9511)
@@ -26,6 +26,17 @@
# =================================
+class MathError(ValueError):
+ """Exception for math syntax and math conversion errors.
+
+ The additional attribute `details` may hold a list of Docutils
+ nodes suitable as children for a ``<system_message>``.
+ """
+ def __init__(self, msg, details=[]):
+ super().__init__(msg)
+ self.details = details
+
+
def toplevel_code(code):
"""Return string (LaTeX math) `code` with environments stripped out."""
chunks = code.split(r'\begin{')
Modified: trunk/docutils/docutils/utils/math/latex2mathml.py
===================================================================
--- trunk/docutils/docutils/utils/math/latex2mathml.py 2024-01-12 11:32:31 UTC (rev 9510)
+++ trunk/docutils/docutils/utils/math/latex2mathml.py 2024-01-13 09:50:07 UTC (rev 9511)
@@ -26,7 +26,7 @@
import re
import unicodedata
-from docutils.utils.math import tex2unichar, toplevel_code
+from docutils.utils.math import MathError, tex2unichar, toplevel_code
# Character data
@@ -399,7 +399,7 @@
`None`.
"""
if self.full():
- raise SyntaxError('Node %s already full!' % self)
+ raise MathError(f'Node {self} already full!')
self.children.append(child)
child.parent = self
if self.full():
@@ -620,7 +620,7 @@
# 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!
+# docutils.utils.math.MathError: Node munder(mi('lim'), mo('-'), accent=False) already full!
# >>> munder(mo('-'), mi('lim'), accent=False, switch=True).toprettyxml()
# '<munder accent="false">\n <mi>lim</mi>\n <mo>-</mo>\n</munder>'
@@ -759,7 +759,7 @@
if nest_level == 0:
break
else:
- raise SyntaxError('Group without closing bracket')
+ raise MathError('Group without closing bracket!')
return string[1:split_index-1], string[split_index:]
@@ -821,7 +821,7 @@
try:
return m.group('optarg'), m.group('remainder')
except AttributeError:
- raise SyntaxError('Could not extract optional argument from %r' % string)
+ raise MathError(f'Could not extract optional argument from "{string}"!')
# Test:
# >>> tex_optarg(' [optional argument] after whitespace')
@@ -828,10 +828,12 @@
# ('optional argument', ' after whitespace')
# >>> tex_optarg('[missing right bracket')
# Traceback (most recent call last):
-# SyntaxError: Could not extract optional argument from '[missing right bracket'
+# ...
+# docutils.utils.math.MathError: 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]]'
+# ...
+# docutils.utils.math.MathError: Could not extract optional argument from "[group with [nested group]]"!
def parse_latex_math(node, string):
@@ -888,7 +890,8 @@
elif c in "+*=<>,.!?`';@":
node = node.append(mo(c))
else:
- raise SyntaxError('Unsupported character: "%s"' % c)
+ raise MathError(f'Unsupported character: "{c}"!')
+ # TODO: append as <mi>?
return tree
# Test:
@@ -915,6 +918,9 @@
# math(msub(mi('x'), mi('α')))
# >>> parse_latex_math(math(), 'x_\\text{in}')
# math(msub(mi('x'), mtext('in')))
+# >>> parse_latex_math(math(), '2⌘')
+# Traceback (most recent call last):
+# docutils.utils.math.MathError: Unsupported character: "⌘"!
def handle_cmd(name, node, string): # noqa: C901 TODO make this less complex
@@ -1053,8 +1059,8 @@
try:
delimiter = stretchables[delimiter.lstrip('\\')]
except KeyError:
- raise SyntaxError('Unsupported "\\%s" delimiter "%s"!'
- % (name, delimiter))
+ raise MathError(f'Unsupported "\\{name}" delimiter '
+ f'"{delimiter}"!')
if size:
delimiter_attributes['maxsize'] = size
delimiter_attributes['minsize'] = size
@@ -1070,6 +1076,7 @@
return node, string
if name == 'not':
+ # negation: LaTeX just overlays next symbol with "/".
arg, string = tex_token(string)
if arg == '{':
return node, '{\\not ' + string
@@ -1077,7 +1084,7 @@
try:
arg = operators[arg[1:]]
except KeyError:
- raise SyntaxError('\\not: Cannot negate: "%s"!'%arg)
+ raise MathError(rf'"\not" cannot negate: "{arg}"!')
arg = unicodedata.normalize('NFC', arg+'\u0338')
node = node.append(mo(arg))
return node, string
@@ -1213,8 +1220,8 @@
elif node.__class__.__name__ == 'math':
node.append(new_node)
else:
- raise SyntaxError('Declaration "\\%s" must be first command '
- 'in a group.' % name)
+ raise MathError(rf'Declaration "\{name}" must be first command '
+ 'in a group!')
return new_node, string
if name.endswith('limits'):
@@ -1232,7 +1239,7 @@
if name == 'end':
return end_environment(node, string)
- raise SyntaxError('Unknown LaTeX command: \\' + name)
+ raise MathError(rf'Unknown LaTeX command "\{name}".')
# >>> handle_cmd('left', math(), '[a\\right]')
# (mrow(mo('[')), 'a\\right]')
@@ -1268,6 +1275,11 @@
# (munderover(mo('⟵'), mi('α')), '{10}')
# >>> handle_cmd('xleftarrow', math(), r'[\alpha=5]{10}')
# (munderover(mo('⟵'), mrow(mi('α'), mo('='), mn('5'))), '{10}')
+# >>> handle_cmd('left', math(), '< a)')
+# Traceback (most recent call last):
+# docutils.utils.math.MathError: Unsupported "\left" delimiter "<"!
+# >>> handle_cmd('not', math(), '{< b} c') # LaTeX ignores the braces, too.
+# (math(), '{\\not < b} c')
def handle_script_or_limit(node, c, limits=''):
@@ -1327,7 +1339,7 @@
node.append(mtable(mtr(entry), **attributes))
node = entry
else:
- raise SyntaxError('Environment not supported!')
+ raise MathError(f'Environment "{name}" not supported!')
return node, string
@@ -1342,7 +1354,7 @@
elif name == 'cases':
node = node.close()
else:
- raise SyntaxError('Environment not supported!')
+ raise MathError(f'Environment "{name}" not supported!')
return node, string
@@ -1386,15 +1398,15 @@
# {'class': 'align', 'displaystyle': True, 'columnalign': 'right left right left', 'columnspacing': '0 2em 0'}
-def tex2mathml(tex_math, inline=True):
+def tex2mathml(tex_math, as_block=False):
"""Return string with MathML code corresponding to `tex_math`.
- Set `inline` to False for displayed math.
+ Set `as_block` to ``True`` for displayed formulas.
"""
# Set up tree
math_tree = math(xmlns='http://www.w3.org/1998/Math/MathML')
node = math_tree
- if not inline:
+ if as_block:
math_tree['display'] = 'block'
rows = toplevel_code(tex_math).split(r'\\')
if len(rows) > 1:
@@ -1409,11 +1421,11 @@
# <math xmlns="http://www.w3.org/1998/Math/MathML">
# <mn>3</mn>
# </math>
-# >>> print(tex2mathml('3', inline=False))
+# >>> print(tex2mathml('3', as_block=True))
# <math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
# <mn>3</mn>
# </math>
-# >>> print(tex2mathml(r'a & b \\ c & d', inline=False))
+# >>> print(tex2mathml(r'a & b \\ c & d', as_block=True))
# <math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
# <mtable class="align" displaystyle="true" columnalign="right left" columnspacing="0">
# <mtr>
@@ -1434,7 +1446,7 @@
# </mtr>
# </mtable>
# </math>
-# >>> print(tex2mathml(r'a \\ b', inline=False))
+# >>> print(tex2mathml(r'a \\ b', as_block=True))
# <math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
# <mtable class="align" displaystyle="true">
# <mtr>
@@ -1451,6 +1463,10 @@
# </math>
+# TODO: raise error if <sqrt> doesnot have a base character (missing children)
+# >> '\sqrt[3]'
+# Maybe also other nodes...
+
# TODO: look up more symbols from tr25, e.g.
#
#
Modified: trunk/docutils/docutils/utils/math/tex2mathml_extern.py
===================================================================
--- trunk/docutils/docutils/utils/math/tex2mathml_extern.py 2024-01-12 11:32:31 UTC (rev 9510)
+++ trunk/docutils/docutils/utils/math/tex2mathml_extern.py 2024-01-13 09:50:07 UTC (rev 9511)
@@ -1,6 +1,6 @@
# :Id: $Id$
# :Copyright: © 2015 Günter Milde.
-# :License: Released under the terms of the `2-Clause BSD license`_, in short:
+# :License: Released under the terms of the `2-Clause BSD license`__, in short:
#
# Copying and distribution of this file, with or without modification,
# are permitted in any medium without royalty provided the copyright
@@ -7,7 +7,7 @@
# notice and this notice are preserved.
# This file is offered as-is, without any warranty.
#
-# .. _2-Clause BSD license: https://opensource.org/licenses/BSD-2-Clause
+# __ https://opensource.org/licenses/BSD-2-Clause
"""Wrappers for TeX->MathML conversion by external tools
@@ -17,8 +17,11 @@
import subprocess
+from docutils import nodes
+from docutils.utils.math import MathError, pick_math_environment
+
+# `latexml` expects a complete document:
document_template = r"""\documentclass{article}
-\usepackage{amsmath}
\begin{document}
%s
\end{document}
@@ -25,161 +28,206 @@
"""
-def latexml(math_code, reporter=None):
- """Convert LaTeX math code to MathML with LaTeXML_
+def _check_result(result, details=[]):
+ # raise MathError if the conversion went wrong
+ # :details: list of doctree nodes with additional info
+ msg = ''
+ if not details and result.stderr:
+ details = [nodes.paragraph('', result.stderr, classes=['pre-wrap'])]
+ if details:
+ msg = f'TeX to MathML converter `{result.args[0]}` failed:'
+ elif result.returncode:
+ msg = (f'TeX to MathMl converter `{result.args[0]}` '
+ f'exited with Errno {result.returncode}.')
+ elif not result.stdout:
+ msg = f'TeX to MathML converter `{result.args[0]}` returned no MathML.'
+ if msg:
+ raise MathError(msg, details=details)
- .. _LaTeXML: http://dlmf.nist.gov/LaTeXML/
+
+def blahtexml(math_code, as_block=False):
+ """Convert LaTeX math code to MathML with blahtexml__.
+
+ __ http://gva.noekeon.org/blahtexml/
"""
- p = subprocess.Popen(['latexml',
- '-', # read from stdin
- '--preload=amsfonts',
- '--preload=amsmath',
- '--inputencoding=utf8',
- ],
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- close_fds=True)
- p.stdin.write((document_template % math_code).encode('utf-8'))
- p.stdin.close()
- latexml_code = p.stdout.read()
- latexml_err = p.stderr.read().decode('utf-8')
- if reporter and (latexml_err.find('Error') >= 0 or not latexml_code):
- reporter.error(latexml_err)
+ args = ['blahtexml',
+ '--mathml',
+ '--indented',
+ '--spacing', 'moderate',
+ '--mathml-encoding', 'raw',
+ '--other-encoding', 'raw',
+ '--doctype-xhtml+mathml',
+ '--annotate-TeX',
+ ]
+ mathml_args = ' display="block"' if as_block else ''
- post_p = subprocess.Popen(['latexmlpost',
- '-',
- '--nonumbersections',
- '--format=xhtml',
- # '--linelength=78', # experimental
- '--'
- ],
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- close_fds=True)
- post_p.stdin.write(latexml_code)
- post_p.stdin.close()
- result = post_p.stdout.read().decode('utf-8')
- post_p_err = post_p.stderr.read().decode('utf-8')
- if reporter and (post_p_err.find('Error') >= 0 or not result):
- reporter.error(post_p_err)
+ if pick_math_environment(math_code).startswith('align'):
+ math_code = r'\begin{aligned}%s\end{aligned}' % math_code
- # extract MathML code:
- start, end = result.find('<math'), result.find('</math>')+7
- result = result[start:end]
- if 'class="ltx_ERROR' in result:
- raise SyntaxError(result)
- return result
+ result = subprocess.run(args, input=math_code,
+ capture_output=True, text=True)
+ # blahtexml writes <error> messages to stdout
+ if '<error>' in result.stdout:
+ result.stderr = result.stdout[result.stdout.find('<message>')+9:
+ result.stdout.find('</message>')]
+ else:
+ result.stdout = result.stdout[result.stdout.find('<markup>')+9:
+ result.stdout.find('</markup>')]
+ _check_result(result)
+ return (f'<math xmlns="http://www.w3.org/1998/Math/MathML"{mathml_args}>'
+ f'\n{result.stdout}</math>')
-def ttm(math_code, reporter=None):
- """Convert LaTeX math code to MathML with TtM_
- .. _TtM: http://hutchinson.belmont.ma.us/tth/mml/
+def latexml(math_code, as_block=False):
+ """Convert LaTeX math code to MathML with LaTeXML__.
+
+ Comprehensive macro support but **very** slow.
+
+ __ http://dlmf.nist.gov/LaTeXML/
"""
- p = subprocess.Popen(['ttm',
- # '-i', # italic font for equations. Default roman.
- '-u', # unicode encoding. (Default iso-8859-1).
- '-r', # output raw MathML (no wrapper)
- ],
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- close_fds=True)
- p.stdin.write((document_template % math_code).encode('utf-8'))
- p.stdin.close()
- result = p.stdout.read()
- err = p.stderr.read().decode('utf-8')
- if err.find('**** Unknown') >= 0:
- msg = '\n'.join(line for line in err.splitlines()
- if line.startswith('****'))
- raise SyntaxError('\nMessage from external converter TtM:\n'+msg)
- if reporter and err.find('**** Error') >= 0 or not result:
- reporter.error(err)
- start, end = result.find('<math'), result.find('</math>')+7
- return result[start:end]
+ # LaTeXML works in 2 stages, expects complete documents.
+ #
+ # The `latexmlmath`__ convenience wrapper does not support block-level
+ # (displayed) equations.
+ #
+ # __ https://metacpan.org/dist/LaTeXML/view/bin/latexmlmath
+ args1 = ['latexml',
+ '-', # read from stdin
+ '--preload=amsmath',
+ '--preload=amssymb', # also loads amsfonts
+ '--inputencoding=utf8',
+ '--',
+ ]
+ result1 = subprocess.run(args1, input=document_template % math_code,
+ capture_output=True, text=True)
+ if result1.stdout:
+ result1.stderr = '\n'.join(line for line in result1.stderr.splitlines()
+ if line.startswith('Error:')
+ or line.startswith('Warning:')
+ or line.startswith('Fatal:'))
+ _check_result(result1)
-def blahtexml(math_code, inline=True, reporter=None):
- """Convert LaTeX math code to MathML with blahtexml_
+ args2 = ['latexmlpost',
+ '-',
+ '--nonumbersections',
+ '--format=html5', # maths included as MathML
+ '--omitdoctype', # Make it simple, we only need the maths.
+ '--noscan', # ...
+ '--nocrossref',
+ '--nographicimages',
+ '--nopictureimages',
+ '--'
+ ]
+ result2 = subprocess.run(args2, input=result1.stdout,
+ capture_output=True, text=True)
+ # Extract MathML from HTML document:
+ # <table> with <math> in cells for "align", <math> element else.
+ start = result2.stdout.find('<table class="ltx_equationgroup')
+ if start != -1:
+ stop = result2.stdout.find('</table>', start)+8
+ result2.stdout = result2.stdout[start:stop].replace(
+ 'ltx_equationgroup', 'borderless align-center')
+ else:
+ result2.stdout = result2.stdout[result2.stdout.find('<math'):
+ result2.stdout.find('</math>')+7]
+ # Search for error messages
+ if result2.stdout:
+ _msg_source = result2.stdout # latexmlpost reports errors in output
+ else:
+ _msg_source = result2.stderr # just in case
+ result2.stderr = '\n'.join(line for line in _msg_source.splitlines()
+ if line.startswith('Error:')
+ or line.startswith('Warning:')
+ or line.startswith('Fatal:'))
+ _check_result(result2)
+ return result2.stdout
- .. _blahtexml: http://gva.noekeon.org/blahtexml/
+
+def pandoc(math_code, as_block=False):
+ """Convert LaTeX math code to MathML with pandoc__.
+
+ __ https://pandoc.org/
"""
- options = ['--mathml',
- '--indented',
- '--spacing', 'moderate',
- '--mathml-encoding', 'raw',
- '--other-encoding', 'raw',
- '--doctype-xhtml+mathml',
- '--annotate-TeX',
- ]
- if inline:
- mathmode_arg = ''
- else:
- mathmode_arg = ' display="block"'
- options.append('--displaymath')
+ args = ['pandoc',
+ '--mathml',
+ '--from=latex',
+ ]
+ result = subprocess.run(args, input=math_code,
+ capture_output=True, text=True)
- p = subprocess.Popen(['blahtexml']+options,
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- close_fds=True)
- p.stdin.write(math_code.encode('utf-8'))
- p.stdin.close()
- result = p.stdout.read().decode('utf-8')
- err = p.stderr.read().decode('utf-8')
+ result.stdout = result.stdout[result.stdout.find('<math'):
+ result.stdout.find('</math>')+7]
+ # Pandoc (2.9.2.1) messages are pre-formatted for the terminal:
+ # 1. summary
+ # 2. math source (part)
+ # 3. error spot indicator '^' (works only in a literal block)
+ # 4. assumed problem
+ # 5. assumed solution (may be wrong or confusing)
+ # Construct a "details" list:
+ details = []
+ if result.stderr:
+ lines = result.stderr.splitlines()
+ details.append(nodes.paragraph('', lines[0]))
+ details.append(nodes.literal_block('', '\n'.join(lines[1:3])))
+ details.append(nodes.paragraph('', '\n'.join(lines[3:]),
+ classes=['pre-wrap']))
+ _check_result(result, details=details)
+ return result.stdout
- if result.find('<error>') >= 0:
- msg = result[result.find('<message>')+9:result.find('</message>')]
- raise SyntaxError('\nMessage from external converter blahtexml:\n%s'
- % msg)
- if reporter and (err.find('**** Error') >= 0 or not result):
- reporter.error(err)
- start, end = result.find('<markup>')+9, result.find('</markup>')
- result = ('<math xmlns="http://www.w3.org/1998/Math/MathML"%s>\n'
- '%s</math>\n') % (mathmode_arg, result[start:end])
- return result
+def ttm(math_code, as_block=False):
+ """Convert LaTeX math code to MathML with TtM__.
-def pandoc(math_code, reporter=None):
- """Convert LaTeX math code to MathML with pandoc_
+ Aged, limited, but fast.
- .. _pandoc: https://pandoc.org/
+ __ http://silas.psfc.mit.edu/tth/mml/
"""
- p = subprocess.Popen(['pandoc',
- '--mathml',
- '--from=latex',
- ],
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- close_fds=True)
- p.stdin.write(math_code.encode('utf-8'))
- p.stdin.close()
- result = p.stdout.read().decode('utf-8')
- err = p.stderr.read().decode('utf-8').strip()
- x = p.wait()
+ args = ['ttm',
+ '-L', # source is LaTeX snippet
+ '-r'] # output MathML snippet
- if err:
- if reporter:
- reporter.error(err)
- raise SyntaxError('\nError message from external converter pandoc:\n%s'
- % err)
- if x != 0:
- raise SyntaxError('\nError code from external converter pandoc:\n%s'
- % x)
+ # Supports only ASCII and "latin extended" characters (Docutils converts
+ # most math characters to LaTeX commands before calling ttm).
+ try:
+ result = subprocess.run(args, input=math_code, capture_output=True,
+ text=True, encoding='ISO-8859-1')
+ except UnicodeEncodeError as err:
+ raise MathError(err)
- start, end = result.find('<math'), result.find('</math>')+7
- return result[start:end]
+ result.stdout = result.stdout[result.stdout.find('<math'):
+ result.stdout.find('</math>')+7]
+ if as_block:
+ result.stdout = result.stdout.replace('<math xmlns=',
+ '<math display="block" xmlns=')
+ result.stderr = '\n'.join(line[5:] + '.'
+ for line in result.stderr.splitlines()
+ if line.startswith('**** '))
+ _check_result(result)
+ return result.stdout
# self-test
if __name__ == "__main__":
- example = ('\\frac{\\partial \\sin^2(\\alpha)}{\\partial \\vec r}'
- '\\varpi \\mathbb{R} \\, \\text{Grüße}')
+ example = (r'\frac{\partial \sin^2(\alpha)}{\partial \vec r}'
+ r'\varpi \mathbb{R} \, \text{Grüße}')
+ # print(blahtexml(example, as_block=True))
+ # print(blahtexml(example))
# print(latexml('$'+example+'$'))
- # print(ttm('$'+example.replace('\\mathbb{R}', '')+'$'))
- print(blahtexml(example))
- # print(pandoc('$'+example+'$'))
+ print(pandoc('$'+example+'$'))
+ # print(ttm('$'+example.replace(r'\mathbb', r'\mathbf')+'$'))
+
+ buggy = r'\sinc \phy'
+ # buggy = '\sqrt[e]'
+ try:
+ # print(blahtexml(buggy))
+ # print(latexml(f'${buggy}$'))
+ print(pandoc(f'${buggy}$'))
+ # print(ttm(f'${buggy}$'))
+ except MathError as err:
+ print(err)
+ print(err.details)
+ for node in err.details:
+ print(node.astext())
Modified: trunk/docutils/docutils/writers/_html_base.py
===================================================================
--- trunk/docutils/docutils/writers/_html_base.py 2024-01-12 11:32:31 UTC (rev 9510)
+++ trunk/docutils/docutils/writers/_html_base.py 2024-01-13 09:50:07 UTC (rev 9511)
@@ -30,8 +30,9 @@
from docutils.parsers.rst.directives import length_or_percentage_or_unitless
from docutils.parsers.rst.directives.images import PIL
from docutils.transforms import writer_aux
-from docutils.utils.math import (unichar2tex, pick_math_environment,
- math2html, latex2mathml, tex2mathml_extern)
+from docutils.utils.math import (MathError, math2html, latex2mathml,
+ pick_math_environment,
+ tex2mathml_extern, unichar2tex)
class Writer(writers.Writer):
@@ -1271,17 +1272,19 @@
# As there is no native HTML math support, we provide alternatives
# for the math-output: LaTeX and MathJax simply wrap the content,
# HTML and MathML also convert the math_code.
- # HTML container
- math_tags = {
- # math_output: (block, inline, class-arguments)
- 'html': ('div', 'span', 'formula'),
- 'latex': ('pre', 'tt', 'math'),
- 'mathml': ('div', '', ''),
- 'mathjax': ('div', 'span', 'math'),
- }
+ # HTML element:
+ math_tags = { # format: (inline, block, [class arguments])
+ 'html': ('span', 'div', ['formula']),
+ 'latex': ('tt', 'pre', ['math']),
+ 'mathjax': ('span', 'div', ['math']),
+ 'mathml': ('', 'div', []),
+ 'problematic': ('span', 'pre', ['math', 'problematic']),
+ }
def visit_math(self, node, math_env=''):
# Also called from `visit_math_block()` (with math_env != '').
+ is_block = isinstance(node, nodes.math_block)
+ format = self.math_output
# LaTeX container
wrappers = {
# math_mode: (inline, block)
@@ -1289,6 +1292,7 @@
'latex': (None, None),
'mathml': ('$%s$', '\\begin{%s}\n%s\n\\end{%s}'),
'mathjax': (r'\(%s\)', '\\begin{%s}\n%s\n\\end{%s}'),
+ 'problematic': (None, None),
}
wrapper = wrappers[self.math_output][math_env != '']
if (self.math_output == 'mathml'
@@ -1302,73 +1306,65 @@
math_code = wrapper % (math_env, math_code, math_env)
except TypeError: # wrapper with one "%s"
math_code = wrapper % math_code
- # settings and conversion
- if self.math_output in ('latex', 'mathjax'):
- math_code = self.encode(math_code)
- if self.math_output == 'mathjax' and not self.math_header:
- if self.math_options:
- self.mathjax_url = self.math_options
- else:
- self.document.reporter.warning(
- 'No MathJax URL specified, using local fallback '
- '(see config.html).', base_node=node)
- # append configuration, if not already present in the URL:
- # input LaTeX with AMS, output common HTML
- if '?' not in self.mathjax_url:
- self.mathjax_url += '?config=TeX-AMS_CHTML'
- self.math_header = [self.mathjax_script % self.mathjax_url]
- elif self.math_output == 'html':
+
+ # preamble code and conversion
+ if format == 'html':
if self.math_options and not self.math_header:
- self.math_header = [self.stylesheet_call(
- utils.find_file_in_dirs(s, self.settings.stylesheet_dirs),
- adjust_path=True)
+ self.math_header = [
+ self.stylesheet_call(utils.find_file_in_dirs(
+ s, self.settings.stylesheet_dirs), adjust_path=True)
for s in self.math_options.split(',')]
# TODO: fix display mode in matrices and fractions
- math2html.DocumentParameters.displaymode = (math_env != '')
+ math2html.DocumentParameters.displaymode = is_block
math_code = math2html.math2html(math_code)
- elif self.math_output == 'mathml':
+ elif format == 'latex':
+ math_code = ...
[truncated message content] |
|
From: <mi...@us...> - 2024-01-13 09:50:23
|
Revision: 9512
http://sourceforge.net/p/docutils/code/9512
Author: milde
Date: 2024-01-13 09:50:21 +0000 (Sat, 13 Jan 2024)
Log Message:
-----------
Simplify HTML math handling.
Define new function `utils.math.wrap_math_code()`.
Use it to simplify the `HTMLTranslator.visit_math()` method.
Modified Paths:
--------------
trunk/docutils/docutils/utils/math/__init__.py
trunk/docutils/docutils/utils/math/tex2mathml_extern.py
trunk/docutils/docutils/writers/_html_base.py
trunk/docutils/test/functional/expected/math_output_html.html
trunk/docutils/test/test_utils.py
Modified: trunk/docutils/docutils/utils/math/__init__.py
===================================================================
--- trunk/docutils/docutils/utils/math/__init__.py 2024-01-13 09:50:07 UTC (rev 9511)
+++ trunk/docutils/docutils/utils/math/__init__.py 2024-01-13 09:50:21 UTC (rev 9512)
@@ -61,3 +61,12 @@
if not numbered:
env += '*'
return env
+
+
+def wrap_math_code(code, as_block):
+ # Wrap math-code in mode-switching TeX command/environment.
+ # If `as_block` is True, use environment for displayed equation(s).
+ if as_block:
+ env = pick_math_environment(code)
+ return '\\begin{%s}\n%s\n\\end{%s}' % (env, code, env)
+ return '$%s$' % code
Modified: trunk/docutils/docutils/utils/math/tex2mathml_extern.py
===================================================================
--- trunk/docutils/docutils/utils/math/tex2mathml_extern.py 2024-01-13 09:50:07 UTC (rev 9511)
+++ trunk/docutils/docutils/utils/math/tex2mathml_extern.py 2024-01-13 09:50:21 UTC (rev 9512)
@@ -18,7 +18,7 @@
import subprocess
from docutils import nodes
-from docutils.utils.math import MathError, pick_math_environment
+from docutils.utils.math import MathError, wrap_math_code
# `latexml` expects a complete document:
document_template = r"""\documentclass{article}
@@ -59,11 +59,13 @@
'--doctype-xhtml+mathml',
'--annotate-TeX',
]
+ # "blahtexml" expects LaTeX code without math-mode-switch.
+ # We still need to tell it about displayed equation(s).
mathml_args = ' display="block"' if as_block else ''
+ _wrapped = wrap_math_code(math_code, as_block)
+ if '{align*}' in _wrapped:
+ math_code = _wrapped.replace('{align*}', '{aligned}')
- if pick_math_environment(math_code).startswith('align'):
- math_code = r'\begin{aligned}%s\end{aligned}' % math_code
-
result = subprocess.run(args, input=math_code,
capture_output=True, text=True)
@@ -100,7 +102,9 @@
'--inputencoding=utf8',
'--',
]
- result1 = subprocess.run(args1, input=document_template % math_code,
+ math_code = document_template % wrap_math_code(math_code, as_block)
+
+ result1 = subprocess.run(args1, input=math_code,
capture_output=True, text=True)
if result1.stdout:
result1.stderr = '\n'.join(line for line in result1.stderr.splitlines()
@@ -154,7 +158,7 @@
'--mathml',
'--from=latex',
]
- result = subprocess.run(args, input=math_code,
+ result = subprocess.run(args, input=wrap_math_code(math_code, as_block),
capture_output=True, text=True)
result.stdout = result.stdout[result.stdout.find('<math'):
@@ -187,12 +191,14 @@
args = ['ttm',
'-L', # source is LaTeX snippet
'-r'] # output MathML snippet
+ math_code = wrap_math_code(math_code, as_block)
- # Supports only ASCII and "latin extended" characters (Docutils converts
- # most math characters to LaTeX commands before calling ttm).
+ # "ttm" does not support UTF-8 input. (Docutils converts most math
+ # characters to LaTeX commands before calling this function.)
try:
- result = subprocess.run(args, input=math_code, capture_output=True,
- text=True, encoding='ISO-8859-1')
+ result = subprocess.run(args, input=math_code,
+ capture_output=True, text=True,
+ encoding='ISO-8859-1')
except UnicodeEncodeError as err:
raise MathError(err)
@@ -213,12 +219,33 @@
if __name__ == "__main__":
example = (r'\frac{\partial \sin^2(\alpha)}{\partial \vec r}'
r'\varpi \mathbb{R} \, \text{Grüße}')
- # print(blahtexml(example, as_block=True))
- # print(blahtexml(example))
- # print(latexml('$'+example+'$'))
- print(pandoc('$'+example+'$'))
- # print(ttm('$'+example.replace(r'\mathbb', r'\mathbf')+'$'))
+ print("""<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<title>test external mathml converters</title>
+</head>
+<body>
+<p>Test external converters</p>
+<p>
+""")
+ print(f'latexml: {latexml(example)},')
+ print(f'ttm: {ttm(example.replace("mathbb", "mathbf"))},')
+ print(f'blahtexml: {blahtexml(example)},')
+ print(f'pandoc: {pandoc(example)}.')
+ print('</p>')
+
+ print('<p>latexml:</p>')
+ print(latexml(example, as_block=True))
+ print('<p>ttm:</p>')
+ print(ttm(example.replace('mathbb', 'mathbf'), as_block=True))
+ print('<p>blahtexml:</p>')
+ print(blahtexml(example, as_block=True))
+ print('<p>pandoc:</p>')
+ print(pandoc(example, as_block=True))
+
+ print('</main>\n</body>\n</html>')
+
buggy = r'\sinc \phy'
# buggy = '\sqrt[e]'
try:
Modified: trunk/docutils/docutils/writers/_html_base.py
===================================================================
--- trunk/docutils/docutils/writers/_html_base.py 2024-01-13 09:50:07 UTC (rev 9511)
+++ trunk/docutils/docutils/writers/_html_base.py 2024-01-13 09:50:21 UTC (rev 9512)
@@ -30,9 +30,8 @@
from docutils.parsers.rst.directives import length_or_percentage_or_unitless
from docutils.parsers.rst.directives.images import PIL
from docutils.transforms import writer_aux
-from docutils.utils.math import (MathError, math2html, latex2mathml,
- pick_math_environment,
- tex2mathml_extern, unichar2tex)
+from docutils.utils.math import (latex2mathml, math2html, tex2mathml_extern,
+ unichar2tex, wrap_math_code, MathError)
class Writer(writers.Writer):
@@ -1281,31 +1280,11 @@
'problematic': ('span', 'pre', ['math', 'problematic']),
}
- def visit_math(self, node, math_env=''):
- # Also called from `visit_math_block()` (with math_env != '').
+ def visit_math(self, node):
+ # Also called from `visit_math_block()`:
is_block = isinstance(node, nodes.math_block)
format = self.math_output
- # LaTeX container
- wrappers = {
- # math_mode: (inline, block)
- 'html': ('$%s$', '\\begin{%s}\n%s\n\\end{%s}'),
- 'latex': (None, None),
- 'mathml': ('$%s$', '\\begin{%s}\n%s\n\\end{%s}'),
- 'mathjax': (r'\(%s\)', '\\begin{%s}\n%s\n\\end{%s}'),
- 'problematic': (None, None),
- }
- wrapper = wrappers[self.math_output][math_env != '']
- if (self.math_output == 'mathml'
- and (not self.math_options
- or self.math_options == 'blahtexml')):
- wrapper = None
- # get and wrap content
math_code = node.astext().translate(unichar2tex.uni2tex_table)
- if wrapper:
- try: # wrapper with three "%s"
- math_code = wrapper % (math_env, math_code, math_env)
- except TypeError: # wrapper with one "%s"
- math_code = wrapper % math_code
# preamble code and conversion
if format == 'html':
@@ -1314,8 +1293,9 @@
self.stylesheet_call(utils.find_file_in_dirs(
s, self.settings.stylesheet_dirs), adjust_path=True)
for s in self.math_options.split(',')]
+ math2html.DocumentParameters.displaymode = is_block
# TODO: fix display mode in matrices and fractions
- math2html.DocumentParameters.displaymode = is_block
+ math_code = wrap_math_code(math_code, is_block)
math_code = math2html.math2html(math_code)
elif format == 'latex':
math_code = self.encode(math_code)
@@ -1332,6 +1312,10 @@
if '?' not in self.mathjax_url:
self.mathjax_url += '?config=TeX-AMS_CHTML'
self.math_header = [self.mathjax_script % self.mathjax_url]
+ if is_block:
+ math_code = wrap_math_code(math_code, is_block)
+ else:
+ math_code = rf'\({math_code}\)'
math_code = self.encode(math_code)
elif format == 'mathml':
if 'XHTML 1' in self.doctype:
@@ -1372,8 +1356,7 @@
pass
def visit_math_block(self, node):
- math_env = pick_math_environment(node.astext())
- self.visit_math(node, math_env=math_env)
+ self.visit_math(node)
def depart_math_block(self, node):
self.report_messages(node)
Modified: trunk/docutils/test/functional/expected/math_output_html.html
===================================================================
--- trunk/docutils/test/functional/expected/math_output_html.html 2024-01-13 09:50:07 UTC (rev 9511)
+++ trunk/docutils/test/functional/expected/math_output_html.html 2024-01-13 09:50:21 UTC (rev 9512)
@@ -68,7 +68,7 @@
directives:</p>
<p>The Schrödinger equation</p>
<div class="formula" id="eq-schrodinger">
-<i>i</i><i>ħ</i><span class="fraction"><span class="ignored">(</span><span class="numerator">∂</span><span class="ignored">)/(</span><span class="denominator">∂<i>t</i></span><span class="ignored">)</span></span>Ψ = <i>Ĥ</i>Ψ,
+<i>i</i><i>ℏ</i><span class="fraction"><span class="ignored">(</span><span class="numerator">∂</span><span class="ignored">)/(</span><span class="denominator">∂<i>t</i></span><span class="ignored">)</span></span>Ψ = <i>Ĥ</i>Ψ,
</div>
<p>with the <em>wave function</em> <span class="formula">Ψ</span>, describes how the quantum state of a
physical system changes in time.</p>
Modified: trunk/docutils/test/test_utils.py
===================================================================
--- trunk/docutils/test/test_utils.py 2024-01-13 09:50:07 UTC (rev 9511)
+++ trunk/docutils/test/test_utils.py 2024-01-13 09:50:21 UTC (rev 9512)
@@ -20,7 +20,8 @@
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
import docutils
-from docutils import utils, nodes
+from docutils import nodes, utils
+import docutils.utils.math
TEST_ROOT = Path(__file__).parent # ./test/ from the docutils root
@@ -417,5 +418,26 @@
utils.get_stylesheet_list(self)
+class MathTests(unittest.TestCase):
+
+ tests = [('a + b = c', 'equation*'),
+ (r'x = \begin{cases} -1&x<0 \\ 1&x>0 \end{cases}', 'equation*'),
+ (r'a + 2b = c \\ 3a + b = 2c', 'align*'),
+ ]
+
+ def test_pick_math_environment(self):
+ for sample, result in self.tests:
+ self.assertEqual(utils.math.pick_math_environment(sample), result)
+
+ def test_wrap_math_code(self):
+ for sample, env in self.tests:
+ self.assertEqual(utils.math.wrap_math_code(sample, as_block=False),
+ f'${sample}$')
+ self.assertEqual(utils.math.wrap_math_code(sample, as_block=True),
+ f'\\begin{{{env}}}\n'
+ f'{sample}\n'
+ f'\\end{{{env}}}')
+
+
if __name__ == '__main__':
unittest.main()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mi...@us...> - 2024-01-13 11:10:50
|
Revision: 9513
http://sourceforge.net/p/docutils/code/9513
Author: milde
Date: 2024-01-13 11:10:47 +0000 (Sat, 13 Jan 2024)
Log Message:
-----------
Fixes in `utils.math`.
Avoid side-effect of importing "latex2mathml" on "tex2unichar".
(This led to the merge of `\hslash` and `\hbar` also with
"--math-output=html".)
Use MathML element <mi> (identifier) instead of <mo> (operator)
for "mathord" symbols.
Sort {U+0127} (`\hslash`) as "mathord", not mathalpha in "tex2unichar".
(Avoids "double italisation" with "math2html".)
Some simplifications in "math2html.py": sort {U+0127} (`\hbar`) as mathalpha
so it gets italicised.
Modified Paths:
--------------
trunk/docutils/HISTORY.txt
trunk/docutils/docutils/utils/math/latex2mathml.py
trunk/docutils/docutils/utils/math/math2html.py
trunk/docutils/docutils/utils/math/tex2unichar.py
trunk/docutils/test/functional/expected/math_output_html.html
trunk/docutils/test/functional/expected/math_output_mathml.html
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2024-01-13 09:50:21 UTC (rev 9512)
+++ trunk/docutils/HISTORY.txt 2024-01-13 11:10:47 UTC (rev 9513)
@@ -94,6 +94,9 @@
abusing `SyntaxError` for LaTeX math syntax errors.
- Unify interface of LaTeX -> MathML conversion functions.
Improve error reporting.
+ - Elimitate side-effect of importing "latex2mathml" on "tex2unichar".
+ - Sort ℏ (`\hslash`) as "mathord", not "mathalpha".
+ - Use MathML element <mi> instead of <mo> for character class "mathord".
* docutils/utils/roman.py
Modified: trunk/docutils/docutils/utils/math/latex2mathml.py
===================================================================
--- trunk/docutils/docutils/utils/math/latex2mathml.py 2024-01-13 09:50:21 UTC (rev 9512)
+++ trunk/docutils/docutils/utils/math/latex2mathml.py 2024-01-13 11:10:47 UTC (rev 9513)
@@ -37,10 +37,12 @@
# identifiers -> <mi>
-letters = tex2unichar.mathalpha
-letters['hbar'] = '\u210F' # compatibility mapping to ℏ (\hslash).
-# (ħ LATIN SMALL LETTER H WITH STROKE is upright)
+letters = {'hbar': 'ℏ'} # Compatibility mapping: \hbar resembles italic ħ
+# "unicode-math" unifies \hbar and \hslash to ℏ.
+letters.update(tex2unichar.mathalpha)
+ordinary = tex2unichar.mathord # Miscellaneous symbols
+
# special case: Capital Greek letters: (upright in TeX style)
greek_capitals = {
'Phi': '\u03a6', 'Xi': '\u039e', 'Sigma': '\u03a3',
@@ -83,6 +85,8 @@
# math font selection -> <mi mathvariant=...> or <mstyle mathvariant=...>
+# TODO: the "mathvariant" attribute is not supported by Chromium and
+# deprecated in the MathML specs (except with value "normal" for single chars).
math_alphabets = {
# 'cmdname': 'mathvariant value' # package
'boldsymbol': 'bold',
@@ -163,7 +167,6 @@
}
operators.update(tex2unichar.mathbin) # Binary symbols
operators.update(tex2unichar.mathrel) # Relation symbols, arrow symbols
-operators.update(tex2unichar.mathord) # Miscellaneous symbols
operators.update(tex2unichar.mathpunct) # Punctuation
operators.update(tex2unichar.mathop) # Variable-sized symbols
operators.update(stretchables)
@@ -952,6 +955,13 @@
node = node.append(new_node)
return node, string
+ if name in ordinary:
+ # <mi mathvariant="normal"> well supported by Chromium but
+ # Firefox 115.5.0 puts additional space after the symbol, e.g.
+ # <mi mathvariant="normal">∂</mi><mi>t</mi> looks like <mo>∂</mo>…
+ # return node.append(mi(ordinary[name], mathvariant='normal')), string
+ return node.append(mi(ordinary[name])), string
+
if name in functions:
# use <mi> followed by invisible function applicator character
# (see https://www.w3.org/TR/MathML3/chapter3.html#presm.mi)
@@ -1377,6 +1387,7 @@
# Return dictionary with attributes to style an <mtable> as align environment:
+# TODO: "columnalign" disregarded by Chromium and webkit
def align_attributes(rows):
atts = {'class': 'align',
'displaystyle': True}
Modified: trunk/docutils/docutils/utils/math/math2html.py
===================================================================
--- trunk/docutils/docutils/utils/math/math2html.py 2024-01-13 09:50:21 UTC (rev 9512)
+++ trunk/docutils/docutils/utils/math/math2html.py 2024-01-13 11:10:47 UTC (rev 9513)
@@ -61,11 +61,6 @@
message = Trace.prefix + message
Trace.show(message, sys.stderr)
- def fatal(cls, message):
- "Show an error message and terminate"
- Trace.error('FATAL: ' + message)
- exit(-1)
-
def show(cls, message, channel):
"Show a message out of a channel"
channel.write(message + '\n')
@@ -73,7 +68,6 @@
debug = classmethod(debug)
message = classmethod(message)
error = classmethod(error)
- fatal = classmethod(fatal)
show = classmethod(show)
@@ -140,6 +134,7 @@
'\\oe': 'œ',
'\\ss': 'ß',
'\\th': 'þ',
+ '\\hbar': 'ħ', # cf. \hslash: ℏ in tex2unichar
}
for key, value in tex2unichar.mathalpha.items():
alphacommands['\\'+key] = value
@@ -206,9 +201,8 @@
'\\euro': '€',
'\\guillemotleft': '«',
'\\guillemotright': '»',
- '\\hbar': '<i>\u0127</i>', # ħ LATIN SMALL LETTER H WITH STROKE
'\\lVert': '‖',
- '\\Arrowvert': '\u2016', # ‖
+ '\\Arrowvert': '‖',
'\\lvert': '|',
'\\newline': '<br/>',
'\\nobreakspace': ' ',
Modified: trunk/docutils/docutils/utils/math/tex2unichar.py
===================================================================
--- trunk/docutils/docutils/utils/math/tex2unichar.py 2024-01-13 09:50:21 UTC (rev 9512)
+++ trunk/docutils/docutils/utils/math/tex2unichar.py 2024-01-13 11:10:47 UTC (rev 9513)
@@ -69,7 +69,6 @@
'eth': '\xf0', # ð LATIN SMALL LETTER ETH
'gamma': '\u03b3', # γ GREEK SMALL LETTER GAMMA
'gimel': '\u2137', # ℷ GIMEL SYMBOL
- 'hslash': '\u210f', # ℏ PLANCK CONSTANT OVER TWO PI
'imath': '\u0131', # ı LATIN SMALL LETTER DOTLESS I
'iota': '\u03b9', # ι GREEK SMALL LETTER IOTA
'jmath': '\u0237', # ȷ LATIN SMALL LETTER DOTLESS J
@@ -348,6 +347,7 @@
'gemini': '\u264a', # ♊ GEMINI
'girl': '\u2640', # ♀ FEMALE SIGN
'heartsuit': '\u2661', # ♡ WHITE HEART SUIT
+ 'hslash': '\u210f', # ℏ PLANCK CONSTANT OVER TWO PI
'infty': '\u221e', # ∞ INFINITY
'invdiameter': '\u2349', # ⍉ APL FUNCTIONAL SYMBOL CIRCLE BACKSLASH
'invneg': '\u2310', # ⌐ REVERSED NOT SIGN
Modified: trunk/docutils/test/functional/expected/math_output_html.html
===================================================================
--- trunk/docutils/test/functional/expected/math_output_html.html 2024-01-13 09:50:21 UTC (rev 9512)
+++ trunk/docutils/test/functional/expected/math_output_html.html 2024-01-13 11:10:47 UTC (rev 9513)
@@ -68,7 +68,7 @@
directives:</p>
<p>The Schrödinger equation</p>
<div class="formula" id="eq-schrodinger">
-<i>i</i><i>ℏ</i><span class="fraction"><span class="ignored">(</span><span class="numerator">∂</span><span class="ignored">)/(</span><span class="denominator">∂<i>t</i></span><span class="ignored">)</span></span>Ψ = <i>Ĥ</i>Ψ,
+<i>i</i><i>ħ</i><span class="fraction"><span class="ignored">(</span><span class="numerator">∂</span><span class="ignored">)/(</span><span class="denominator">∂<i>t</i></span><span class="ignored">)</span></span>Ψ = <i>Ĥ</i>Ψ,
</div>
<p>with the <em>wave function</em> <span class="formula">Ψ</span>, describes how the quantum state of a
physical system changes in time.</p>
Modified: trunk/docutils/test/functional/expected/math_output_mathml.html
===================================================================
--- trunk/docutils/test/functional/expected/math_output_mathml.html 2024-01-13 09:50:21 UTC (rev 9512)
+++ trunk/docutils/test/functional/expected/math_output_mathml.html 2024-01-13 11:10:47 UTC (rev 9513)
@@ -187,9 +187,9 @@
<mi>i</mi>
<mi>ℏ</mi>
<mfrac>
- <mo>∂</mo>
+ <mi>∂</mi>
<mrow>
- <mo>∂</mo>
+ <mi>∂</mi>
<mi>t</mi>
</mrow>
</mfrac>
@@ -343,9 +343,9 @@
<mo>∫</mo>
<mrow>
<mo>−</mo>
- <mo>∞</mo>
+ <mi>∞</mi>
</mrow>
- <mo>∞</mo>
+ <mi>∞</mi>
</msubsup>
<mi>s</mi>
<mo stretchy="false">(</mo>
@@ -370,9 +370,9 @@
<mo>∫</mo>
<mrow>
<mo>−</mo>
- <mo>∞</mo>
+ <mi>∞</mi>
</mrow>
- <mo>∞</mo>
+ <mi>∞</mi>
</msubsup>
<mi>s</mi>
<mo stretchy="false">(</mo>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|