SF.net SVN: docutils:[9913] trunk/docutils

milde--- via Docutils-checkins <[email protected]>
Newsgroups gmane.text.docutils.cvs
Message-ID <[email protected]>
Revision: 9913
          http://sourceforge.net/p/docutils/code/9913
Author:   milde
Date:     2024-08-21 13:44:48 +0000 (Wed, 21 Aug 2024)
Log Message:
-----------
Refactor HTML5 writer tests.

New test script "test_html5_polyglot.py":
Split basic output tests (which happen to use the "fragment" returned
by `publish_parts()` to get the interesting part of the output)
from other tests of `publish_parts()`

Really test all returned parts in "test_html5_polyglot_parts.py".
Fill in parts that are built out of other parts in a helper function
instead of pruning parts.
Add test cases for input that goes to special parts.

Disable default style sheet ("stylesheet_path" setting) by for tests
not requiring a stylesheet.

Modified Paths:
--------------
    trunk/docutils/docs/api/publisher.rst
    trunk/docutils/test/test_writers/test_html5_polyglot_misc.py
    trunk/docutils/test/test_writers/test_html5_polyglot_parts.py

Added Paths:
-----------
    trunk/docutils/test/test_writers/test_html5_polyglot.py

Modified: trunk/docutils/docs/api/publisher.rst
===================================================================
--- trunk/docutils/docs/api/publisher.rst	2024-08-21 13:44:37 UTC (rev 9912)
+++ trunk/docutils/docs/api/publisher.rst	2024-08-21 13:44:48 UTC (rev 9913)
@@ -603,7 +603,7 @@
 
   Default: "restructuredtext".
 
-_`writer` : str | docutils.parsers.Writer
+_`writer` : str | docutils.writers.Writer
   `Writer component name`_ or instance. [#component-names]_
 
   Default: "pseudoxml".

Copied: trunk/docutils/test/test_writers/test_html5_polyglot.py (from rev 9912, trunk/docutils/test/test_writers/test_html5_polyglot_parts.py)
===================================================================
--- trunk/docutils/test/test_writers/test_html5_polyglot.py	                        (rev 0)
+++ trunk/docutils/test/test_writers/test_html5_polyglot.py	2024-08-21 13:44:48 UTC (rev 9913)
@@ -0,0 +1,672 @@
+#! /usr/bin/env python3
+
+# $Id$
+# Author: reggie dugard <[email protected]>
+# Copyright: This module has been placed in the public domain.
+
+"""Test HTML5 writer output ("fragment" part).
+
+This is the document body (not HTML <body>).
+"""
+
+from pathlib import Path
+import re
+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__).resolve().parents[2]))
+
+import docutils
+import docutils.core
+from docutils.parsers.rst.directives.images import PIL
+from docutils.utils.code_analyzer import with_pygments
+
+if with_pygments:
+    import pygments
+    _pv = re.match(r'^([0-9]+)\.([0-9]*)', pygments.__version__)
+    if (int(_pv[1]), int(_pv[2])) >= (2, 14):
+        # pygments output changed in version 2.14
+        with_pygments = False
+
+# TEST_ROOT is ./test/ from the docutils root
+TEST_ROOT = Path(__file__).parents[1]
+DATA_ROOT = TEST_ROOT / 'data'
+ROOT_PREFIX = (TEST_ROOT / 'functional/input').as_posix()
+
+# Pillow/PIL is optional:
+if PIL:
+    REQUIRES_PIL = ''
+    ONLY_LOCAL = 'Can only read local images.'
+    DUMMY_PNG_NOT_FOUND = "[Errno 2] No such file or directory: 'dummy.png'"
+    # Pillow reports the absolute path since version 10.3.0 (cf. [bugs: 485])
+    if (tuple(int(i) for i in PIL.__version__.split('.')) >= (10, 3)):
+        DUMMY_PNG_NOT_FOUND = ("[Errno 2] No such file or directory: '%s'"
+                               % Path('dummy.png').resolve())
+    SCALING_OUTPUT = 'style="width: 32.0px; height: 32.0px;" '
+    NO_PIL_SYSTEM_MESSAGE = ''
+else:
+    REQUIRES_PIL = '\n  Requires Python Imaging Library.'
+    ONLY_LOCAL = 'Requires Python Imaging Library.'
+    DUMMY_PNG_NOT_FOUND = 'Requires Python Imaging Library.'
+    SCALING_OUTPUT = ''
+    NO_PIL_SYSTEM_MESSAGE = (
+        '<aside class="system-message">\n'
+        '<p class="system-message-title">System Message:'
+        ' WARNING/2 (<span class="docutils literal">'
+        '&lt;string&gt;</span>, line 1)</p>\n'
+        '<p>Cannot scale image!\n'
+        '  Could not get size from &quot;/data/blue%20square.png&quot;:\n'
+        '  Requires Python Imaging Library.</p>\n'
+        '</aside>\n')
+
+
+class Html5WriterPublishPartsTestCase(unittest.TestCase):
+    """Test case for HTML5 writer via the publish_parts() interface."""
+
+    maxDiff = None
+
+    def test_publish(self):
+        if not with_pygments:
+            del totest['syntax_highlight']
+        writer = 'html5'
+        for name, (settings_overrides, cases) in totest.items():
+            for casenum, (case_input, case_expected) in enumerate(cases):
+                with self.subTest(id=f'totest[{name!r}][{casenum}]'):
+                    parts = docutils.core.publish_parts(
+                        source=case_input,
+                        writer=writer,
+                        settings_overrides={
+                            '_disable_config': True,
+                            'strict_visitor': True,
+                            'stylesheet_path': '',
+                            'section_self_link': True,
+                            **settings_overrides,
+                        }
+                    )
+                    self.assertEqual(case_expected, parts['body'])
+
+
+totest = {}
+
+totest['standard'] = ({}, [
+["""\
+Simple String
+""",
+'<p>Simple String</p>\n',
+],
+["""\
+Simple String with *markup*
+""",
+'<p>Simple String with <em>markup</em></p>\n',
+],
+["""\
+Simple String with an even simpler ``inline literal``
+""",
+'<p>Simple String with an even simpler <span class="docutils literal">inline literal</span></p>\n',
+],
+["""\
+A simple `anonymous reference`__
+
+__ http://www.test.com/test_url
+""",
+'<p>A simple <a class="reference external" href="http://www.test.com/test_url">anonymous reference</a></p>\n',
+],
+["""\
+One paragraph.
+
+Two paragraphs.
+""",
+"""\
+<p>One paragraph.</p>
+<p>Two paragraphs.</p>
+""",
+],
+["""\
+A simple `named reference`_ with stuff in between the
+reference and the target.
+
+.. _`named reference`: http://www.test.com/test_url
+""",
+"""\
+<p>A simple <a class="reference external" href="http://www.test.com/test_url">named reference</a> with stuff in between the
+reference and the target.</p>
+""",
+],
+["""\
+.. [CIT2022] A citation.
+""",
+"""\
+<div role="list" class="citation-list">
+<div class="citation" id="cit2022" role="doc-biblioentry">
+<span class="label"><span class="fn-bracket">[</span>CIT2022<span class="fn-bracket">]</span></span>
+<p>A citation.</p>
+</div>
+</div>
+""",
+],
+])
+
+
+totest['no_title_promotion'] = ({'doctitle_xform': False}, [
+["""\
++++++
+Title
++++++
+
+Not A Subtitle
+==============
+
+Some stuff
+
+Section
+-------
+
+Some more stuff
+
+Another Section
+...............
+
+And even more stuff
+""",
+"""\
+<section id="title">
+<h2>Title<a class="self-link" title="link to this section" href="#title"></a></h2>
+<section id="not-a-subtitle">
+<h3>Not A Subtitle<a class="self-link" title="link to this section" href="#not-a-subtitle"></a></h3>
+<p>Some stuff</p>
+<section id="section">
+<h4>Section<a class="self-link" title="link to this section" href="#section"></a></h4>
+<p>Some more stuff</p>
+<section id="another-section">
+<h5>Another Section<a class="self-link" title="link to this section" href="#another-section"></a></h5>
+<p>And even more stuff</p>
+</section>
+</section>
+</section>
+</section>
+""",
+],
+["""\
+* bullet
+* list
+""",
+"""\
+<ul class="simple">
+<li><p>bullet</p></li>
+<li><p>list</p></li>
+</ul>
+""",
+],
+["""\
+.. table::
+   :align: right
+
+   +-----+-----+
+   |  1  |  2  |
+   +-----+-----+
+   |  3  |  4  |
+   +-----+-----+
+""",
+"""\
+<table class="align-right">
+<tbody>
+<tr><td><p>1</p></td>
+<td><p>2</p></td>
+</tr>
+<tr><td><p>3</p></td>
+<td><p>4</p></td>
+</tr>
+</tbody>
+</table>
+""",
+],
+["""\
+Not a docinfo.
+
+:This: .. _target:
+
+       is
+:a:
+:simple:
+:field: list
+""",
+"""\
+<p>Not a docinfo.</p>
+<dl class="field-list simple">
+<dt>This<span class="colon">:</span></dt>
+<dd><p id="target">is</p>
+</dd>
+<dt>a<span class="colon">:</span></dt>
+<dd><p></p></dd>
+<dt>simple<span class="colon">:</span></dt>
+<dd><p></p></dd>
+<dt>field<span class="colon">:</span></dt>
+<dd><p>list</p>
+</dd>
+</dl>
+""",
+],
+["""\
+Not a docinfo.
+
+:This is: a
+:simple field list with loooong field: names
+""",
+"""\
+<p>Not a docinfo.</p>
+<dl class="field-list simple">
+<dt>This is<span class="colon">:</span></dt>
+<dd><p>a</p>
+</dd>
+<dt>simple field list with loooong field<span class="colon">:</span></dt>
+<dd><p>names</p>
+</dd>
+</dl>
+""",
+],
+["""\
+Not a docinfo.
+
+.. class:: field-indent-200
+
+:This: is a
+:simple: field list with custom indent.
+""",
+"""\
+<p>Not a docinfo.</p>
+<dl class="field-list simple" style="--field-indent: 200px;">
+<dt>This<span class="colon">:</span></dt>
+<dd><p>is a</p>
+</dd>
+<dt>simple<span class="colon">:</span></dt>
+<dd><p>field list with custom indent.</p>
+</dd>
+</dl>
+""",
+],
+["""\
+Not a docinfo.
+
+.. class:: field-indent-200uf
+
+:This: is a
+:simple: field list without custom indent,
+         because the unit "uf" is invalid.
+""",
+"""\
+<p>Not a docinfo.</p>
+<dl class="field-indent-200uf field-list simple">
+<dt>This<span class="colon">:</span></dt>
+<dd><p>is a</p>
+</dd>
+<dt>simple<span class="colon">:</span></dt>
+<dd><p>field list without custom indent,
+because the unit &quot;uf&quot; is invalid.</p>
+</dd>
+</dl>
+""",
+],
+["""\
+.. figure:: dummy.png
+
+   The figure's caption.
+
+   A legend.
+
+   The legend's second paragraph.
+""",
+"""\
+<figure>
+<img alt="dummy.png" src="dummy.png" />
+<figcaption>
+<p>The figure's caption.</p>
+<div class="legend">
+<p>A legend.</p>
+<p>The legend's second paragraph.</p>
+</div>
+</figcaption>
+</figure>
+""",
+],
+["""\
+.. figure:: dummy.png
+
+   The figure's caption, no legend.
+""",
+"""\
+<figure>
+<img alt="dummy.png" src="dummy.png" />
+<figcaption>
+<p>The figure's caption, no legend.</p>
+</figcaption>
+</figure>
+""",
+],
+["""\
+.. figure:: dummy.png
+
+   ..
+
+   A legend without caption.
+""",
+"""\
+<figure>
+<img alt="dummy.png" src="dummy.png" />
+<figcaption>
+<div class="legend">
+<p>A legend without caption.</p>
+</div>
+</figcaption>
+</figure>
+""",
+],
+["""\
+.. figure:: dummy.png
+
+No caption nor legend.
+""",
+"""\
+<figure>
+<img alt="dummy.png" src="dummy.png" />
+</figure>
+<p>No caption nor legend.</p>
+""",
+],
+[f"""\
+.. include:: {DATA_ROOT}/multiple-term-definition.xml
+   :parser: xml
+""",
+"""\
+<dl>
+<dt>New in Docutils 0.22</dt>
+<dd><p>A definition list item may contain several
+terms with optional classifier(s).</p>
+<p>However, there is currently no corresponding
+reStructuredText syntax.</p>
+</dd>
+<dt>term 2a</dt>
+<dt>term 2b</dt>
+<dd><p>definition 2</p>
+</dd>
+<dt>term 3a<span class="classifier">classifier 3a</span><span class="classifier">classifier 3aa</span><dt>term 3b<span class="classifier">classifier 3b</span></dt>
+<dd><p>definition 3</p>
+</dd>
+</dl>
+""",
+],
+])
+
+
+totest['lazy_loading'] = ({'image_loading': 'lazy',
+                           'report_level': 4}, [
+["""\
+Lazy loading by default, overridden by :loading: option
+("cannot embed" warning ignored).
+
+.. image:: dummy.png
+.. image:: dummy.png
+   :loading: link
+.. figure:: dummy.png
+.. figure:: dummy.png
+   :loading: embed
+""",
+"""\
+<p>Lazy loading by default, overridden by :loading: option
+(&quot;cannot embed&quot; warning ignored).</p>
+<img alt="dummy.png" loading="lazy" src="dummy.png" />
+<img alt="dummy.png" src="dummy.png" />
+<figure>
+<img alt="dummy.png" loading="lazy" src="dummy.png" />
+</figure>
+<figure>
+<img alt="dummy.png" src="dummy.png" />
+</figure>
+""",
+],
+])
+
+
+totest['root_prefix'] = ({'root_prefix': ROOT_PREFIX,
+                          'image_loading': 'embed',
+                          'warning_stream': '',
+                          }, [
+["""\
+.. image:: /data/blue%20square.png
+   :scale: 100%
+.. figure:: /data/blue%20square.png
+""",
+'<img alt="/data/blue%20square.png" src="data:image/png;base64,'
+'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAALElEQVR4nO3NMQ'
+'EAMAjAsDFjvIhHFCbgSwU0kdXvsn96BwAAAAAAAAAAAIsNnEwBk52VRuMAAAAA'
+'SUVORK5CYII="'
+f' {SCALING_OUTPUT}/>\n{NO_PIL_SYSTEM_MESSAGE}'
+'<figure>\n'
+'<img alt="/data/blue%20square.png" src="data:image/png;base64,'
+'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAALElEQVR4nO3NMQ'
+'EAMAjAsDFjvIhHFCbgSwU0kdXvsn96BwAAAAAAAAAAAIsNnEwBk52VRuMAAAAA'
+'SUVORK5CYII=" />\n'
+'</figure>\n',
+],
+])
+
+
+totest['no_backlinks'] = ({'footnote_backlinks': False}, [
+
+["""\
+Two footnotes [#f1]_ [#f2]_ and two citations [once]_ [twice]_.
+
+The latter are referenced a second time [#f2]_ [twice]_.
+
+.. [#f1] referenced once
+.. [#f2] referenced twice
+.. [once] citation referenced once
+.. [twice] citation referenced twice
+""",
+"""\
+<p>Two footnotes <a class="brackets" href="#f1" id="footnote-reference-1" role="doc-noteref"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></a> <a class="brackets" href="#f2" id="footnote-reference-2" role="doc-noteref"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></a> and two citations <a class="citation-reference" href="#once" id="citation-reference-1" role="doc-biblioref">[once]</a> <a class="citation-reference" href="#twice" id="citation-reference-2" role="doc-biblioref">[twice]</a>.</p>
+<p>The latter are referenced a second time <a class="brackets" href="#f2" id="footnote-reference-3" role="doc-noteref"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></a> <a class="citation-reference" href="#twice" id="citation-reference-3" role="doc-biblioref">[twice]</a>.</p>
+<aside class="footnote-list brackets">
+<aside class="footnote brackets" id="f1" role="doc-footnote">
+<span class="label"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></span>
+<p>referenced once</p>
+</aside>
+<aside class="footnote brackets" id="f2" role="doc-footnote">
+<span class="label"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></span>
+<p>referenced twice</p>
+</aside>
+</aside>
+<div role="list" class="citation-list">
+<div class="citation" id="once" role="doc-biblioentry">
+<span class="label"><span class="fn-bracket">[</span>once<span class="fn-bracket">]</span></span>
+<p>citation referenced once</p>
+</div>
+<div class="citation" id="twice" role="doc-biblioentry">
+<span class="label"><span class="fn-bracket">[</span>twice<span class="fn-bracket">]</span></span>
+<p>citation referenced twice</p>
+</div>
+</div>
+""",
+],
+])
+
+
+totest['syntax_highlight'] = ({'syntax_highlight': 'short',
+                               }, [
+["""\
+.. code:: shell
+
+    cat <<EOF
+    Hello World
+    EOF
+""",
+"""\
+<pre class="code shell literal-block"><code>cat <span class="s">&lt;&lt;EOF
+Hello World
+EOF</span></code></pre>
+""",
+],
+["""\
+.. role:: shell(code)
+   :language: shell
+
+:shell:`cat <<EOF Hello World EOF`
+""",
+"""\
+<p><code class="shell">cat <span class="s">&lt;&lt;EOF Hello World EOF</span></code></p>
+""",
+],
+])
+
+
+totest['system_messages'] = ({'math_output': 'mathml',
+                              'warning_stream': '',
+                              }, [
+["""\
+.. image:: https://dummy.png
+   :loading: embed
+""",
+"""\
+<img alt="https://dummy.png" src="https://dummy.png" />
+<aside class="system-message">
+<p class="system-message-title">System Message: ERROR/3 \
+(<span class="docutils literal">&lt;string&gt;</span>, line 1)</p>
+<p>Cannot embed image &quot;https://dummy.png&quot;:
+  Can only read local images.</p>
+</aside>
+""",
+],
+[f"""\
+.. image:: {DATA_ROOT.as_uri()}/circle-broken.svg
+   :loading: embed
+""",
+f"""\
+<svg xmlns="http://www.w3.org/2000/svg"
+     viewBox="0 0 10 10">
+  <circle cx="5" cy="5" r="4" fill="lightblue" x/>
+</svg>
+
+<aside class="system-message">
+<p class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">&lt;string&gt;</span>, line 1)</p>
+<p>Cannot parse SVG image &quot;{DATA_ROOT.as_uri()}/circle-broken.svg&quot;:
+  not well-formed (invalid token): line 3, column 48</p>
+</aside>
+"""
+],
+[r"""Broken :math:`\sin \my`.
+""",
+"""\
+<p>Broken <span class="math problematic">\\sin \\my</span>.</p>
+<aside class="system-message">
+<p class="system-message-title">System Message: WARNING/2 (<span class="docutils literal">&lt;string&gt;</span>, line 1)</p>
+<p>Unknown LaTeX command &quot;\\my&quot;.</p>
+</aside>
+"""],
+])
+
+totest['system_messages-PIL'] = ({'math_output': 'mathml',
+                                  'warning_stream': '',
+                                  }, [
+["""\
+.. image:: dummy.png
+   :scale: 100%
+   :loading: embed
+""",
+f"""\
+<img alt="dummy.png" src="dummy.png" />
+<aside class="system-message">
+<p class="system-message-title">System Message: WARNING/2 \
+(<span class="docutils literal">&lt;string&gt;</span>, line 1)</p>
+<p>Cannot scale image!
+  Could not get size from &quot;dummy.png&quot;:
+  {DUMMY_PNG_NOT_FOUND}</p>
+</aside>
+<aside class="system-message">
+<p class="system-message-title">System Message: ERROR/3 \
+(<span class="docutils literal">&lt;string&gt;</span>, line 1)</p>
+<p>Cannot embed image &quot;dummy.png&quot;:
+  [Errno 2] No such file or directory: 'dummy.png'</p>
+</aside>
+""",
+],
+["""\
+.. image:: dummy.mp4
+   :scale: 100%
+""",
+f"""\
+<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">&lt;string&gt;</span>, line 1)</p>
+<p>Cannot scale image!
+  Could not get size from &quot;dummy.mp4&quot;:{REQUIRES_PIL}
+  PIL cannot read video images.</p>
+</aside>
+""",
+],
+["""\
+.. image:: https://dummy.png
+   :scale: 100%
+   :loading: embed
+""",
+f"""\
+<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">&lt;string&gt;</span>, line 1)</p>
+<p>Cannot scale image!
+  Could not get size from &quot;https://dummy.png&quot;:
+  {ONLY_LOCAL}</p>
+</aside>
+<aside class="system-message">
+<p class="system-message-title">System Message: ERROR/3 \
+(<span class="docutils literal">&lt;string&gt;</span>, line 1)</p>
+<p>Cannot embed image &quot;https://dummy.png&quot;:
+  Can only read local images.</p>
+</aside>
+""",
+],
+])
+
+totest['no_system_messages'] = ({'math_output': 'mathml',
+                                 'report_level': 4,
+                                 'warning_stream': '',
+                                 }, [
+["""\
+.. image:: dummy.png
+   :scale: 100%
+   :loading: embed
+
+.. image:: dummy.mp4
+   :scale: 100%
+""",
+"""\
+<img alt="dummy.png" src="dummy.png" />
+<video src="dummy.mp4" title="dummy.mp4">
+<a href="dummy.mp4">dummy.mp4</a>
+</video>
+""",
+],
+[f"""\
+.. image:: {DATA_ROOT.as_uri()}/circle-broken.svg
+   :loading: embed
+""",
+"""\
+<svg xmlns="http://www.w3.org/2000/svg"
+     viewBox="0 0 10 10">
+  <circle cx="5" cy="5" r="4" fill="lightblue" x/>
+</svg>
+
+"""],
+[r'Broken :math:`\sin \my`.',
+'<p>Broken <tt class="math">\\sin \\my</tt>.</p>\n'
+],
+])
+
+
+if __name__ == '__main__':
+    unittest.main()


Property changes on: trunk/docutils/test/test_writers/test_html5_polyglot.py
___________________________________________________________________
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/test/test_writers/test_html5_polyglot_misc.py
===================================================================
--- trunk/docutils/test/test_writers/test_html5_polyglot_misc.py	2024-08-21 13:44:37 UTC (rev 9912)
+++ trunk/docutils/test/test_writers/test_html5_polyglot_misc.py	2024-08-21 13:44:48 UTC (rev 9913)
@@ -36,7 +36,7 @@
         # error handler.
         settings_overrides = {
             'output_encoding': 'latin1',
-            'stylesheet': '',
+            'stylesheet_path': '',
             '_disable_config': True}
         result = core.publish_string(
             'EUR = \u20ac', writer='html5_polyglot',
@@ -49,7 +49,6 @@
 class MovingArgsTestCase(unittest.TestCase):
 
     mys = {'stylesheet_path': '',
-           # 'embed_stylesheet': False,
            '_disable_config': True,
            }
 
@@ -99,8 +98,8 @@
         mys = {'_disable_config': True}
         styles = core.publish_parts(self.data, writer='html5_polyglot',
                                     settings_overrides=mys)['stylesheet']
-        self.assertIn('Minimal style sheet '
-                      'for the HTML output of Docutils.', styles)
+        self.assertIn('Minimal style sheet for the HTML output of Docutils.',
+                      styles)
 
     def test_default_stylesheet_linked(self):
         # default style sheet, linked
@@ -141,7 +140,8 @@
         styles = core.publish_parts(self.data, writer='html5_polyglot',
                                     settings_overrides=mys)['stylesheet']
         if (TEST_ROOT / '../docutils/writers/html5_polyglot/').is_dir():
-            self.assertIn('docutils/writers/html5_polyglot/minimal.css', styles)
+            self.assertIn('docutils/writers/html5_polyglot/minimal.css',
+                          styles)
         self.assertIn(f'href="{ham_css}"', styles)
 
     def test_custom_stylesheet_dir_embedded(self):

Modified: trunk/docutils/test/test_writers/test_html5_polyglot_parts.py
===================================================================
--- trunk/docutils/test/test_writers/test_html5_polyglot_parts.py	2024-08-21 13:44:37 UTC (rev 9912)
+++ trunk/docutils/test/test_writers/test_html5_polyglot_parts.py	2024-08-21 13:44:48 UTC (rev 9913)
@@ -5,15 +5,12 @@
 # Copyright: This module has been placed in the public domain.
 
 """
-Test for fragment code in HTML writer.
+Test `core.publish_parts()`__ with the HTML5 writer.
 
-Note: the 'body' and 'whole' entries have been removed from the parts
-dictionaries (redundant), along with 'meta' and 'stylesheet' entries with
-standard values, and any entries with empty values.
+__ https://docutils.sourceforge.io/docs/api/publisher.html#publish-parts
 """
 
 from pathlib import Path
-import re
 import sys
 import unittest
 
@@ -24,182 +21,136 @@
 
 import docutils
 import docutils.core
-from docutils.parsers.rst.directives.images import PIL
-from docutils.utils.code_analyzer import with_pygments
+from docutils.writers import html5_polyglot
 
-if with_pygments:
-    import pygments
-    _pv = re.match(r'^([0-9]+)\.([0-9]*)', pygments.__version__)
-    if (int(_pv[1]), int(_pv[2])) >= (2, 14):
-        # pygments output changed in version 2.14
-        with_pygments = False
-
 # TEST_ROOT is ./test/ from the docutils root
 TEST_ROOT = Path(__file__).parents[1]
 DATA_ROOT = TEST_ROOT / 'data'
 ROOT_PREFIX = (TEST_ROOT / 'functional/input').as_posix()
 
-# Pillow/PIL is optional:
-if PIL:
-    REQUIRES_PIL = ''
-    ONLY_LOCAL = 'Can only read local images.'
-    DUMMY_PNG_NOT_FOUND = "[Errno 2] No such file or directory: 'dummy.png'"
-    # Pillow reports the absolute path since version 10.3.0 (cf. [bugs: 485])
-    if (tuple(int(i) for i in PIL.__version__.split('.')) >= (10, 3)):
-        DUMMY_PNG_NOT_FOUND = ("[Errno 2] No such file or directory: '%s'"
-                               % Path('dummy.png').resolve())
-    SCALING_OUTPUT = 'style="width: 32.0px; height: 32.0px;" '
-    NO_PIL_SYSTEM_MESSAGE = ''
-else:
-    REQUIRES_PIL = '\n  Requires Python Imaging Library.'
-    ONLY_LOCAL = 'Requires Python Imaging Library.'
-    DUMMY_PNG_NOT_FOUND = 'Requires Python Imaging Library.'
-    SCALING_OUTPUT = ''
-    NO_PIL_SYSTEM_MESSAGE = (
-        '<aside class="system-message">\n'
-        '<p class="system-message-title">System Message:'
-        ' WARNING/2 (<span class="docutils literal">'
-        '&lt;string&gt;</span>, line 1)</p>\n'
-        '<p>Cannot scale image!\n'
-        '  Could not get size from &quot;/data/blue%20square.png&quot;:\n'
-        '  Requires Python Imaging Library.</p>\n'
-        '</aside>\n')
 
+# Parts returned by `publish_parts()` for the HTML5 writer by default:
+#   * empty input string
+#   * default configuration settings.
+# See format_parts() below for the substitution of unresolved format markers.
+default_parts = {
+    'body': '{fragment}',
+    'body_pre_docinfo': '',
+    'body_prefix': '</head>\n<body>\n{header}<main>\n',
+    'body_suffix': '</main>\n{footer}</body>\n</html>\n',
+    'docinfo': '',
+    'encoding': 'utf-8',
+    'errors': 'xmlcharrefreplace',
+    'footer': '',
+    'fragment': '',
+    'head': '{meta}<title>{metatitle}</title>\n',
+    'head_prefix':
+        '<!DOCTYPE html>\n'
+        '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n'
+        '<head>\n',
+    'header': '',
+    'html_body': '{header}<main>\n{fragment}</main>\n{footer}',
+    'html_head': '{meta}<title>{metatitle}</title>\n',
+    'html_prolog': '<!DOCTYPE html>\n',
+    'html_subtitle': '',
+    'html_title': '',
+    'meta': '<meta charset="%s" />\n'
+            f'<meta name="generator" content="Docutils {docutils.__version__}: https://docutils.sourceforge.io/" />\n'
+            '<meta name="viewport" content="width=device-width, initial-scale=1" />\n',
+    'stylesheet': '',
+    'subtitle': '',
+    'title': '',
+    'version': f'{docutils.__version__}',
+    'whole':
+        '{head_prefix}\n'
+        '{head}\n'
+        '{stylesheet}\n'
+        '{body_prefix}\n'
+        '{body_pre_docinfo}\n'
+        '{docinfo}\n'
+        '{body}\n'
+        '{body_suffix}\n',
+    }
 
+
+def format_parts(parts):
+    # fill in part values that depend on other parts
+    # https://docutils.sourceforge.io/docs/api/publisher.html#html4-writer
+
+    # metadata title: either the visible title or document['source']
+    metatitle = parts['title'] or '&lt;string&gt;'
+
+    # "html_head" leaves the encoding unresolved, as "%s":
+    parts['html_head'] = parts['html_head'].format(metatitle=metatitle,
+                                                   **parts)
+    # now resolve encoding:
+    try:
+        parts['meta'] = parts['meta'] % parts['encoding']
+    except TypeError:  # charset-<meta> missing if encoding is 'unicode'
+        pass
+    parts['head'] = parts['head'].format(metatitle=metatitle, **parts)
+    parts['body_prefix'] = parts['body_prefix'].format(**parts)
+    parts['body'] = parts['body'].format(**parts)
+    parts['body_suffix'] = parts['body_suffix'].format(**parts)
+    parts['html_body'] = parts['html_body'].format(**parts)
+    # newlines are stripped when parts are used to expand the template file
+    parts['whole'] = parts['whole'].format(**{k: v.rstrip('\n')
+                                              for k, v in parts.items()})
+    return parts
+
+
 class Html5WriterPublishPartsTestCase(unittest.TestCase):
-    """Test case for HTML writer via the publish_parts interface."""
+    """Test HTML5 writer `publish_parts()` interface."""
 
     maxDiff = None
 
-    def test_publish(self):
-        if not with_pygments:
-            del totest['syntax_highlight']
-        writer = 'html5'
+    def test_publish_parts(self):
         for name, (settings_overrides, cases) in totest.items():
-            for casenum, (case_input, case_expected) in enumerate(cases):
-                with self.subTest(id=f'totest[{name!r}][{casenum}]'):
-                    parts = docutils.core.publish_parts(
-                        source=case_input,
-                        writer=writer,
-                        settings_overrides={
-                            '_disable_config': True,
-                            'strict_visitor': True,
-                            'stylesheet_path': '',
-                            'section_self_link': True,
-                            **settings_overrides,
-                        }
-                    )
-                    # if the formatted output is a just single fragment,
-                    # compare the text directly for a nicer diff on failure
-                    formatted = self.format_output(parts)
-                    if len(formatted) == 1 and 'fragment' in formatted:
-                        fragment = formatted['fragment']
-                        self.assertEqual(case_expected, fragment)
-                    else:
-                        self.assertEqual(case_expected, formatted)
+            for casenum, (case_input, expected_parts) in enumerate(cases):
+                _stgns = {'_disable_config': True,
+                          'strict_visitor': True,
+                          'stylesheet_path': '',
+                          'section_self_link': True,
+                          **settings_overrides,
+                          }
+                parts = docutils.core.publish_parts(source=case_input,
+                                                    writer=html5_polyglot.Writer(),
+                                                    settings_overrides=_stgns,
+                                                    )
+                expected = format_parts(default_parts | expected_parts)
+                for key in parts.keys():
+                    with self.subTest(id=f'totest[{name!r}][{casenum}][{key}]'):
+                        self.assertEqual(f'{expected[key]}',
+                                         f'{parts[key]}')
 
-    standard_content_type_template = '<meta charset="%s" />\n'
-    standard_generator_template = (
-        '<meta name="generator"'
-        f' content="Docutils {docutils.__version__}: '
-        'https://docutils.sourceforge.io/" />\n')
-    standard_viewport_value = (
-        '<meta name="viewport"'
-        ' content="width=device-width, initial-scale=1" />\n')
-    standard_html_meta_value = (standard_content_type_template
-                                + standard_generator_template
-                                + standard_viewport_value)
-    standard_meta_value = standard_html_meta_value % 'utf-8'
-    standard_html_prolog = '<!DOCTYPE html>\n'
-    standard_html_body_template = '<main>\n%s</main>\n'
 
-    def format_output(self, parts):
-        """Minimize & standardize the output."""
-        # remove redundant parts & uninteresting parts:
-        del parts['whole']
-        assert parts['body'] == parts['fragment']
-        del parts['body']
-        del parts['body_pre_docinfo']
-        del parts['body_prefix']
-        del parts['body_suffix']
-        del parts['head']
-        del parts['head_prefix']
-        del parts['encoding']
-        del parts['errors']
-        del parts['version']
-        # remove standard portions:
-        parts['meta'] = parts['meta'].replace(self.standard_meta_value, '')
-        parts['html_head'] = parts['html_head'].replace(
-            self.standard_html_meta_value, '...')
-        parts['html_head'] = parts['html_head'].replace(
-            '...<title>&lt;string&gt;</title>\n', '')
-        parts['html_prolog'] = parts['html_prolog'].replace(
-            self.standard_html_prolog, '')
-        parts['html_body'] = parts['html_body'].replace(
-            self.standard_html_body_template % parts['fragment'], '')
-        # remove empty keys and return
-        return {k: v for k, v in parts.items() if v}
-
-
 totest = {}
 
 totest['standard'] = ({}, [
-["""\
-Simple String
-""",
-'<p>Simple String</p>\n',
-],
-["""\
-Simple String with *markup*
-""",
-'<p>Simple String with <em>markup</em></p>\n',
-],
-["""\
-Simple String with an even simpler ``inline literal``
-""",
-'<p>Simple String with an even simpler <span class="docutils literal">inline literal</span></p>\n',
-],
-["""\
-A simple `anonymous reference`__
-
-__ http://www.test.com/test_url
-""",
-'<p>A simple <a class="reference external" href="http://www.test.com/test_url">anonymous reference</a></p>\n',
-],
-["""\
-One paragraph.
-
-Two paragraphs.
-""",
-"""\
-<p>One paragraph.</p>
-<p>Two paragraphs.</p>
-""",
-],
-["""\
-A simple `named reference`_ with stuff in between the
-reference and the target.
-
-.. _`named reference`: http://www.test.com/test_url
-""",
-"""\
-<p>A simple <a class="reference external" href="http://www.test.com/test_url">named reference</a> with stuff in between the
-reference and the target.</p>
-""",
-],
-["""\
-.. [CIT2022] A citation.
-""",
-"""\
-<div role="list" class="citation-list">
-<div class="citation" id="cit2022" role="doc-biblioentry">
-<span class="label"><span class="fn-bracket">[</span>CIT2022<span class="fn-bracket">]</span></span>
-<p>A citation.</p>
-</div>
-</div>
-""",
-],
-["""\
+    ['',  # empty input string
+     {}   # results in default parts
+     ],
+    ['Simple String with *markup*',
+     {'fragment': '<p>Simple String with <em>markup</em></p>\n'}
+     ],
+    ['.. header:: custom document header\n\n'
+     'A paragraph.',
+     {'header': '<header>\n<p>custom document header</p>\n</header>\n',
+      'body_prefix': '</head>\n'
+                     '<body>\n'
+                     '<header>\n'
+                     '<p>custom document header</p>\n</header>\n'
+                     '<main>\n',
+      'fragment': '<p>A paragraph.</p>\n',
+      }
+     ],
+    ['.. footer:: custom document footer\n\n'
+     'A paragraph.',
+     {'footer': '<footer>\n<p>custom document footer</p>\n</footer>\n',
+      'fragment': '<p>A paragraph.</p>\n',
+      }
+     ],
+    ["""\
 +++++
 Title
 +++++
@@ -219,7 +170,10 @@
 
 And even more stuff
 """,
-{'fragment': """\
+    {'body_pre_docinfo': '<h1 class="title">Title</h1>\n'
+                         '<p class="subtitle" id="subtitle">Subtitle</p>\n',
+     'body_prefix': '</head>\n<body>\n<main id="title">\n',
+     'fragment': """\
 <p>Some stuff</p>
 <section id="section">
 <h2>Section<a class="self-link" title="link to this section" href="#section"></a></h2>
@@ -230,7 +184,7 @@
 </section>
 </section>
 """,
- 'html_body': """\
+     'html_body': """\
 <main id="title">
 <h1 class="title">Title</h1>
 <p class="subtitle" id="subtitle">Subtitle</p>
@@ -245,13 +199,12 @@
 </section>
 </main>
 """,
- 'html_head': '...<title>Title</title>\n',
- 'html_subtitle': '<p class="subtitle" id="subtitle">Subtitle</p>\n',
- 'html_title': '<h1 class="title">Title</h1>\n',
- 'subtitle': 'Subtitle',
- 'title': 'Title'
-}],
-["""\
+     'html_subtitle': '<p class="subtitle" id="subtitle">Subtitle</p>\n',
+     'html_title': '<h1 class="title">Title</h1>\n',
+     'subtitle': 'Subtitle',
+     'title': 'Title'
+     }],
+    ["""\
 +++++
 Title
 +++++
@@ -260,14 +213,16 @@
 
 Some stuff
 """,
-{'docinfo': """\
+    {'body_pre_docinfo': '<h1 class="title">Title</h1>\n',
+     'body_prefix': '</head>\n<body>\n<main id="title">\n',
+     'docinfo': """\
 <dl class="docinfo simple">
 <dt class="author">Author<span class="colon">:</span></dt>
 <dd class="author"><p>me</p></dd>
 </dl>
 """,
- 'fragment': '<p>Some stuff</p>\n',
- 'html_body': """\
+     'fragment': '<p>Some stuff</p>\n',
+     'html_body': """\
 <main id="title">
 <h1 class="title">Title</h1>
 <dl class="docinfo simple">
@@ -277,63 +232,14 @@
 <p>Some stuff</p>
 </main>
 """,
- 'html_head': """\
-...<meta name="author" content="me" />
-<title>Title</title>
-""",
- 'html_title': '<h1 class="title">Title</h1>\n',
- 'meta': '<meta name="author" content="me" />\n',
- 'title': 'Title'
-}],
-])
+     'html_title': '<h1 class="title">Title</h1>\n',
+     'meta': default_parts['meta'] + '<meta name="author" content="me" />\n',
+     'title': 'Title'
+     }],
+    ])
 
-totest['standard'] = ({'output_encoding': 'unicode'}, [
-["""\
-Simple String
-""",
-{'fragment': '<p>Simple String</p>\n',
- 'meta': """\
-<meta name="generator" content="Docutils 0.22b.dev: https://docutils.sourceforge.io/" />
-<meta name="viewport" content="width=device-width, initial-scale=1" />
-""",
-}],
-])
-
 totest['no_title_promotion'] = ({'doctitle_xform': False}, [
-["""\
-Simple String
-""",
-'<p>Simple String</p>\n',
-],
-["""\
-Simple String with *markup*
-""",
-'<p>Simple String with <em>markup</em></p>\n',
-],
-["""\
-Simple String with an even simpler ``inline literal``
-""",
-'<p>Simple String with an even simpler <span class="docutils literal">inline literal</span></p>\n',
-],
-["""\
-A simple `anonymous reference`__
-
-__ http://www.test.com/test_url
-""",
-'<p>A simple <a class="reference external" href="http://www.test.com/test_url">anonymous reference</a></p>\n',
-],
-["""\
-A simple `named reference`_ with stuff in between the
-reference and the target.
-
-.. _`named reference`: http://www.test.com/test_url
-""",
-"""\
-<p>A simple <a class="reference external" href="http://www.test.com/test_url">named reference</a> with stuff in between the
-reference and the target.</p>
-""",
-],
-["""\
+    ["""\
 +++++
 Title
 +++++
@@ -353,7 +259,7 @@
 
 And even more stuff
 """,
-"""\
+     {'fragment': """\
 <section id="title">
 <h2>Title<a class="self-link" title="link to this section" href="#title"></a></h2>
 <section id="not-a-subtitle">
@@ -369,486 +275,19 @@
 </section>
 </section>
 </section>
-""",
-],
-["""\
-* bullet
-* list
-""",
-"""\
-<ul class="simple">
-<li><p>bullet</p></li>
-<li><p>list</p></li>
-</ul>
-""",
-],
-["""\
-.. table::
-   :align: right
+"""},
+     ],
+    ])
 
-   +-----+-----+
-   |  1  |  2  |
-   +-----+-----+
-   |  3  |  4  |
-   +-----+-----+
-""",
-"""\
-<table class="align-right">
-<tbody>
-<tr><td><p>1</p></td>
-<td><p>2</p></td>
-</tr>
-<tr><td><p>3</p></td>
-<td><p>4</p></td>
-</tr>
-</tbody>
-</table>
-""",
-],
-["""\
-Not a docinfo.
+totest['unknown-encoding'] = ({'output_encoding': 'unicode'}, [
+    ['Simple String\n',
+     {'encoding': 'unicode',
+      'fragment': '<p>Simple String</p>\n',
+      'html_head': f'{default_parts["meta"]}<title>{{metatitle}}</title>\n',
+      'meta': default_parts['meta'].removeprefix('<meta charset="%s" />\n'),
+      }],
+    ])
 
-:This: .. _target:
 
-       is
-:a:
-:simple:
-:field: list
-""",
-"""\
-<p>Not a docinfo.</p>
-<dl class="field-list simple">
-<dt>This<span class="colon">:</span></dt>
-<dd><p id="target">is</p>
-</dd>
-<dt>a<span class="colon">:</span></dt>
-<dd><p></p></dd>
-<dt>simple<span class="colon">:</span></dt>
-<dd><p></p></dd>
-<dt>field<span class="colon">:</span></dt>
-<dd><p>list</p>
-</dd>
-</dl>
-""",
-],
-["""\
-Not a docinfo.
-
-:This is: a
-:simple field list with loooong field: names
-""",
-"""\
-<p>Not a docinfo.</p>
-<dl class="field-list simple">
-<dt>This is<span class="colon">:</span></dt>
-<dd><p>a</p>
-</dd>
-<dt>simple field list with loooong field<span class="colon">:</span></dt>
-<dd><p>names</p>
-</dd>
-</dl>
-""",
-],
-["""\
-Not a docinfo.
-
-.. class:: field-indent-200
-
-:This: is a
-:simple: field list with custom indent.
-""",
-"""\
-<p>Not a docinfo.</p>
-<dl class="field-list simple" style="--field-indent: 200px;">
-<dt>This<span class="colon">:</span></dt>
-<dd><p>is a</p>
-</dd>
-<dt>simple<span class="colon">:</span></dt>
-<dd><p>field list with custom indent.</p>
-</dd>
-</dl>
-""",
-],
-["""\
-Not a docinfo.
-
-.. class:: field-indent-200uf
-
-:This: is a
-:simple: field list without custom indent,
-         because the unit "uf" is invalid.
-""",
-"""\
-<p>Not a docinfo.</p>
-<dl class="field-indent-200uf field-list simple">
-<dt>This<span class="colon">:</span></dt>
-<dd><p>is a</p>
-</dd>
-<dt>simple<span class="colon">:</span></dt>
-<dd><p>field list without custom indent,
-because the unit &quot;uf&quot; is invalid.</p>
-</dd>
-</dl>
-""",
-],
-["""\
-.. figure:: dummy.png
-
-   The figure's caption.
-
-   A legend.
-
-   The legend's second paragraph.
-""",
-"""\
-<figure>
-<img alt="dummy.png" src="dummy.png" />
-<figcaption>
-<p>The figure's caption.</p>
-<div class="legend">
-<p>A legend.</p>
-<p>The legend's second paragraph.</p>
-</div>
-</figcaption>
-</figure>
-""",
-],
-["""\
-.. figure:: dummy.png
-
-   The figure's caption, no legend.
-""",
-"""\
-<figure>
-<img alt="dummy.png" src="dummy.png" />
-<figcaption>
-<p>The figure's caption, no legend.</p>
-</figcaption>
-</figure>
-""",
-],
-["""\
-.. figure:: dummy.png
-
-   ..
-
-   A legend without caption.
-""",
-"""\
-<figure>
-<img alt="dummy.png" src="dummy.png" />
-<figcaption>
-<div class="legend">
-<p>A legend without caption.</p>
-</div>
-</figcaption>
-</figure>
-""",
-],
-["""\
-.. figure:: dummy.png
-
-No caption nor legend.
-""",
-"""\
-<figure>
-<img alt="dummy.png" src="dummy.png" />
-</figure>
-<p>No caption nor legend.</p>
-""",
-],
-[f"""\
-.. include:: {DATA_ROOT}/multiple-term-definition.xml
-   :parser: xml
-""",
-"""\
-<dl>
-<dt>New in Docutils 0.22</dt>
-<dd><p>A definition list item may contain several
-terms with optional classifier(s).</p>
-<p>However, there is currently no corresponding
-reStructuredText syntax.</p>
-</dd>
-<dt>term 2a</dt>
-<dt>term 2b</dt>
-<dd><p>definition 2</p>
-</dd>
-<dt>term 3a<span class="classifier">classifier 3a</span><span class="classifier">classifier 3aa</span><dt>term 3b<span class="classifier">classifier 3b</span></dt>
-<dd><p>definition 3</p>
-</dd>
-</dl>
-""",
-],
-])
-
-
-totest['lazy_loading'] = ({'image_loading': 'lazy',
-                           'report_level': 4}, [
-["""\
-Lazy loading by default, overridden by :loading: option
-("cannot embed" warning ignored).
-
-.. image:: dummy.png
-.. image:: dummy.png
-   :loading: link
-.. figure:: dummy.png
-.. figure:: dummy.png
-   :loading: embed
-""",
-"""\
-<p>Lazy loading by default, overridden by :loading: option
-(&quot;cannot embed&quot; warning ignored).</p>
-<img alt="dummy.png" loading="lazy" src="dummy.png" />
-<img alt="dummy.png" src="dummy.png" />
-<figure>
-<img alt="dummy.png" loading="lazy" src="dummy.png" />
-</figure>
-<figure>
-<img alt="dummy.png" src="dummy.png" />
-</figure>
-""",
-],
-])
-
-
-totest['root_prefix'] = ({'root_prefix': ROOT_PREFIX,
-                          'image_loading': 'embed',
-                          'warning_stream': '',
-                          }, [
-["""\
-.. image:: /data/blue%20square.png
-   :scale: 100%
-.. figure:: /data/blue%20square.png
-""",
-'<img alt="/data/blue%20square.png" src="data:image/png;base64,'
-'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAALElEQVR4nO3NMQ'
-'EAMAjAsDFjvIhHFCbgSwU0kdXvsn96BwAAAAAAAAAAAIsNnEwBk52VRuMAAAAA'
-'SUVORK5CYII="'
-f' {SCALING_OUTPUT}/>\n{NO_PIL_SYSTEM_MESSAGE}'
-'<figure>\n'
-'<img alt="/data/blue%20square.png" src="data:image/png;base64,'
-'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAALElEQVR4nO3NMQ'
-'EAMAjAsDFjvIhHFCbgSwU0kdXvsn96BwAAAAAAAAAAAIsNnEwBk52VRuMAAAAA'
-'SUVORK5CYII=" />\n'
-'</figure>\n',
-],
-])
-
-
-totest['no_backlinks'] = ({'footnote_backlinks': False}, [
-
-["""\
-Two footnotes [#f1]_ [#f2]_ and two citations [once]_ [twice]_.
-
-The latter are referenced a second time [#f2]_ [twice]_.
-
-.. [#f1] referenced once
-.. [#f2] referenced twice
-.. [once] citation referenced once
-.. [twice] citation referenced twice
-""",
-"""\
-<p>Two footnotes <a class="brackets" href="#f1" id="footnote-reference-1" role="doc-noteref"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></a> <a class="brackets" href="#f2" id="footnote-reference-2" role="doc-noteref"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></a> and two citations <a class="citation-reference" href="#once" id="citation-reference-1" role="doc-biblioref">[once]</a> <a class="citation-reference" href="#twice" id="citation-reference-2" role="doc-biblioref">[twice]</a>.</p>
-<p>The latter are referenced a second time <a class="brackets" href="#f2" id="footnote-reference-3" role="doc-noteref"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></a> <a class="citation-reference" href="#twice" id="citation-reference-3" role="doc-biblioref">[twice]</a>.</p>
-<aside class="footnote-list brackets">
-<aside class="footnote brackets" id="f1" role="doc-footnote">
-<span class="label"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></span>
-<p>referenced once</p>
-</aside>
-<aside class="footnote brackets" id="f2" role="doc-footnote">
-<span class="label"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></span>
-<p>referenced twice</p>
-</aside>
-</aside>
-<div role="list" class="citation-list">
-<div class="citation" id="once" role="doc-biblioentry">
-<span class="label"><span class="fn-bracket">[</span>once<span class="fn-bracket">]</span></span>
-<p>citation referenced once</p>
-</div>
-<div class="citation" id="twice" role="doc-biblioentry">
-<span class="label"><span class="fn-bracket">[</span>twice<span class="fn-bracket">]</span></span>
-<p>citation referenced twice</p>
-</div>
-</div>
-""",
-],
-])
-
-
-totest['syntax_highlight'] = ({'syntax_highlight': 'short',
-                               }, [
-["""\
-.. code:: shell
-
-    cat <<EOF
-    Hello World
-    EOF
-""",
-"""\
-<pre class="code shell literal-block"><code>cat <span class="s">&lt;&lt;EOF
-Hello World
-EOF</span></code></pre>
-""",
-],
-["""\
-.. role:: shell(code)
-   :language: shell
-
-:shell:`cat <<EOF Hello World EOF`
-""",
-"""\
-<p><code class="shell">cat <span class="s">&lt;&lt;EOF Hello World EOF</span></code></p>
-""",
-],
-])
-
-
-totest['system_messages'] = ({'math_output': 'mathml',
-                              'warning_stream': '',
-                              }, [
-["""\
-.. image:: https://dummy.png
-   :loading: embed
-""",
-"""\
-<img alt="https://dummy.png" src="https://dummy.png" />
-<aside class="system-message">
-<p class="system-message-title">System Message: ERROR/3 \
-(<span class="docutils literal">&lt;string&gt;</span>, line 1)</p>
-<p>Cannot embed image &quot;https://dummy.png&quot;:
-  Can only read local images.</p>
-</aside>
-""",
-],
-[f"""\
-.. image:: {DATA_ROOT.as_uri()}/circle-broken.svg
-   :loading: embed
-""",
-f"""\
-<svg xmlns="http://www.w3.org/2000/svg"
-     viewBox="0 0 10 10">
-  <circle cx="5" cy="5" r="4" fill="lightblue" x/>
-</svg>
-
-<aside class="system-message">
-<p class="system-message-title">System Message: ERROR/3 (<span class="docutils literal">&lt;string&gt;</span>, line 1)</p>
-<p>Cannot parse SVG image &quot;{DATA_ROOT.as_uri()}/circle-broken.svg&quot;:
-  not well-formed (invalid token): line 3, column 48</p>
-</aside>
-"""
-],
-[r"""Broken :math:`\sin \my`.
-""",
-"""\
-<p>Broken <span class="math problematic">\\sin \\my</span>.</p>
-<aside class="system-message">
-<p class="system-message-title">System Message: WARNING/2 (<span class="docutils literal">&lt;string&gt;</span>, line 1)</p>
-<p>Unknown LaTeX command &quot;\\my&quot;.</p>
-</aside>
-"""],
-])
-
-totest['system_messages-PIL'] = ({'math_output': 'mathml',
-                                  'warning_stream': '',
-                                  }, [
-["""\
-.. image:: dummy.png
-   :scale: 100%
-   :loading: embed
-""",
-f"""\
-<img alt="dummy.png" src="dummy.png" />
-<aside class="system-message">
-<p class="system-message-title">System Message: WARNING/2 \
-(<span class="docutils literal">&lt;string&gt;</span>, line 1)</p>
-<p>Cannot scale image!
-  Could not get size from &quot;dummy.png&quot;:
-  {DUMMY_PNG_NOT_FOUND}</p>
-</aside>
-<aside class="system-message">
-<p class="system-message-title">System Message: ERROR/3 \
-(<span class="docutils literal">&lt;string&gt;</span>, line 1)</p>
-<p>Cannot embed image &quot;dummy.png&quot;:
-  [Errno 2] No such file or directory: 'dummy.png'</p>
-</aside>
-""",
-],
-["""\
-.. image:: dummy.mp4
-   :scale: 100%
-""",
-f"""\
-<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">&lt;string&gt;</span>, line 1)</p>
-<p>Cannot scale image!
-  Could not get size from &quot;dummy.mp4&quot;:{REQUIRES_PIL}
-  PIL cannot read video images.</p>
-</aside>
-""",
-],
-["""\
-.. image:: https://dummy.png
-   :scale: 100%
-   :loading: embed
-""",
-f"""\
-<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">&lt;string&gt;</span>, line 1)</p>
-<p>Cannot scale image!
-  Could not get size from &quot;https://dummy.png&quot;:
-  {ONLY_LOCAL}</p>
-</aside>
-<aside class="system-message">
-<p class="system-message-title">System Message: ERROR/3 \
-(<span class="docutils literal">&lt;string&gt;</span>, line 1)</p>
-<p>Cannot embed image &quot;https://dummy.png&quot;:
-  Can only read local images.</p>
-</aside>
-""",
-],
-])
-
-totest['no_system_messages'] = ({'math_output': 'mathml',
-                                 'report_level': 4,
-                                 'warning_stream': '',
-                                 }, [
-["""\
-.. image:: dummy.png
-   :scale: 100%
-   :loading: embed
-
-.. image:: dummy.mp4
-   :scale: 100%
-""",
-"""\
-<img alt="dummy.png" src="dummy.png" />
-<video src="dummy.mp4" title="dummy.mp4">
-<a href="dummy.mp4">dummy.mp4</a>
-</video>
-""",
-],
-[f"""\
-.. image:: {DATA_ROOT.as_uri()}/circle-broken.svg
-   :loading: embed
-""",
-"""\
-<svg xmlns="http://www.w3.org/2000/svg"
-     viewBox="0 0 10 10">
-  <circle cx="5" cy="5" r="4" fill="lightblue" x/>
-</svg>
-
-"""],
-[r'Broken :math:`\sin \my`.',
-'<p>Broken <tt class="math">\\sin \\my</tt>.</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.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.