SF.net SVN: docutils:[9916] trunk/docutils/test/test_writers
milde--- via Docutils-checkins <[email protected]>
| Newsgroups | gmane.text.docutils.cvs |
|---|---|
| Message-ID | <[email protected]> |
Revision: 9916
http://sourceforge.net/p/docutils/code/9916
Author: milde
Date: 2024-08-21 13:45:27 +0000 (Wed, 21 Aug 2024)
Log Message:
-----------
Refactor HTML4 writer tests.
New test script "test_html4css1.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_html4css1_parts.py".
Cf. "Refactor HTML5 writer tests".
Modified Paths:
--------------
trunk/docutils/test/test_writers/test_html4css1_parts.py
Added Paths:
-----------
trunk/docutils/test/test_writers/test_html4css1.py
Added: trunk/docutils/test/test_writers/test_html4css1.py
===================================================================
--- trunk/docutils/test/test_writers/test_html4css1.py (rev 0)
+++ trunk/docutils/test/test_writers/test_html4css1.py 2024-08-21 13:45:27 UTC (rev 9916)
@@ -0,0 +1,596 @@
+#! /usr/bin/env python3
+
+# $Id$
+# Author: reggie dugard <[email protected]>
+# Copyright: This module has been placed in the public domain.
+
+"""Test HTML4 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.utils.code_analyzer import with_pygments
+from docutils.writers import html4css1
+
+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()
+
+
+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']
+ 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=html4css1.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 <tt class="docutils literal">inline literal</tt></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.
+""",
+"""\
+<table class="docutils citation" frame="void" id="cit2022" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label">[CIT2022]</td><td>A citation.</td></tr>
+</tbody>
+</table>
+""",
+],
+])
+
+
+totest['no_title_promotion'] = ({'doctitle_xform': False}, [
+["""\
++++++
+Title
++++++
+
+Not A Subtitle
+==============
+
+Some stuff
+
+Section
+-------
+
+Some more stuff
+
+Another Section
+...............
+
+And even more stuff
+""",
+"""\
+<div class="section" id="title">
+<h1>Title</h1>
+<div class="section" id="not-a-subtitle">
+<h2>Not A Subtitle</h2>
+<p>Some stuff</p>
+<div class="section" id="section">
+<h3>Section</h3>
+<p>Some more stuff</p>
+<div class="section" id="another-section">
+<h4>Another Section</h4>
+<p>And even more stuff</p>
+</div>
+</div>
+</div>
+</div>
+""",
+],
+["""\
+* bullet
+* list
+""",
+"""\
+<ul class="simple">
+<li>bullet</li>
+<li>list</li>
+</ul>
+""",
+],
+["""\
+.. table::
+ :align: right
+
+ +-----+-----+
+ | 1 | 2 |
+ +-----+-----+
+ | 3 | 4 |
+ +-----+-----+
+""",
+"""\
+<table border="1" class="docutils align-right">
+<colgroup>
+<col width="50%" />
+<col width="50%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>1</td>
+<td>2</td>
+</tr>
+<tr><td>3</td>
+<td>4</td>
+</tr>
+</tbody>
+</table>
+""",
+],
+["""\
+Not a docinfo.
+
+:This: .. _target:
+
+ is
+:a:
+:simple:
+:field: list
+""",
+"""\
+<p>Not a docinfo.</p>
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field"><th class="field-name">This:</th><td class="field-body"><p class="first last" id="target">is</p>
+</td>
+</tr>
+<tr class="field"><th class="field-name">a:</th><td class="field-body"></td>
+</tr>
+<tr class="field"><th class="field-name">simple:</th><td class="field-body"></td>
+</tr>
+<tr class="field"><th class="field-name">field:</th><td class="field-body">list</td>
+</tr>
+</tbody>
+</table>
+""",
+],
+["""\
+Not a docinfo.
+
+:This is: a
+:simple field list with loooong field: names
+""",
+"""\
+<p>Not a docinfo.</p>
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field"><th class="field-name">This is:</th><td class="field-body">a</td>
+</tr>
+<tr class="field"><th class="field-name" colspan="2">simple field list with loooong field:</th></tr>
+<tr class="field"><td> </td><td class="field-body">names</td>
+</tr>
+</tbody>
+</table>
+""",
+],
+["""\
+Not a docinfo.
+
+.. class:: field-indent-200
+
+:This: is a
+:simple: field list with custom indent.
+""",
+"""\
+<p>Not a docinfo.</p>
+<table class="field-indent-200 docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field"><th class="field-name">This:</th><td class="field-body">is a</td>
+</tr>
+<tr class="field"><th class="field-name">simple:</th><td class="field-body">field list with custom indent.</td>
+</tr>
+</tbody>
+</table>
+""",
+],
+["""\
+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>
+<table class="field-indent-200uf docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field"><th class="field-name">This:</th><td class="field-body">is a</td>
+</tr>
+<tr class="field"><th class="field-name">simple:</th><td class="field-body">field list without custom indent,
+because the unit "uf" is invalid.</td>
+</tr>
+</tbody>
+</table>
+""",
+],
+["""\
+.. figure:: dummy.png
+
+ The figure's caption.
+
+ A legend.
+
+ The legend's second paragraph.
+""",
+"""\
+<div class="figure">
+<img alt="dummy.png" src="dummy.png" />
+<p class="caption">The figure's caption.</p>
+<div class="legend">
+<p>A legend.</p>
+<p>The legend's second paragraph.</p>
+</div>
+</div>
+""",
+],
+["""\
+.. figure:: dummy.png
+
+ The figure's caption, no legend.
+""",
+"""\
+<div class="figure">
+<img alt="dummy.png" src="dummy.png" />
+<p class="caption">The figure's caption, no legend.</p>
+</div>
+""",
+],
+["""\
+.. figure:: dummy.png
+
+ ..
+
+ A legend without caption.
+""",
+"""\
+<div class="figure">
+<img alt="dummy.png" src="dummy.png" />
+<div class="legend">
+A legend without caption.</div>
+</div>
+""",
+],
+["""\
+.. figure:: dummy.png
+
+No caption nor legend.
+""",
+"""\
+<div class="figure">
+<img alt="dummy.png" src="dummy.png" />
+</div>
+<p>No caption nor legend.</p>
+""",
+],
+[f"""\
+.. include:: {DATA_ROOT}/multiple-term-definition.xml
+ :parser: xml
+""",
+"""\
+<dl class="docutils">
+<dt>New in Docutils 0.22</dt>
+<dd><p class="first">A definition list item may contain several
+terms with optional classifier(s).</p>
+<p class="last">However, there is currently no corresponding
+reStructuredText syntax.</p>
+</dd>
+<dt>term 2a</dt>
+<dt>term 2b</dt>
+<dd>definition 2</dd>
+<dt>term 3a <span class="classifier-delimiter">:</span> <span class="classifier">classifier 3a</span> <span class="classifier-delimiter">:</span> <span class="classifier">classifier 3aa</span><dt>term 3b <span class="classifier-delimiter">:</span> <span class="classifier">classifier 3b</span></dt>
+<dd>definition 3</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
+("cannot embed" warning ignored).</p>
+<img alt="dummy.png" src="dummy.png" />
+<img alt="dummy.png" src="dummy.png" />
+<div class="figure">
+<img alt="dummy.png" src="dummy.png" />
+</div>
+<div class="figure">
+<img alt="dummy.png" src="dummy.png" />
+</div>
+""",
+],
+])
+
+
+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/blue%20square.png" style="width: 32.0px; height: 32.0px;" />
+<div class="figure">
+<img alt="/data/blue%20square.png" src="/data/blue%20square.png" />
+</div>
+"""
+],
+])
+
+
+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="footnote-reference" href="#f1" id="footnote-reference-1">[1]</a> <a class="footnote-reference" href="#f2" id="footnote-reference-2">[2]</a> and two citations <a class="citation-reference" href="#once" id="citation-reference-1">[once]</a> <a class="citation-reference" href="#twice" id="citation-reference-2">[twice]</a>.</p>
+<p>The latter are referenced a second time <a class="footnote-reference" href="#f2" id="footnote-reference-3">[2]</a> <a class="citation-reference" href="#twice" id="citation-reference-3">[twice]</a>.</p>
+<table class="docutils footnote" frame="void" id="f1" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label">[1]</td><td>referenced once</td></tr>
+</tbody>
+</table>
+<table class="docutils footnote" frame="void" id="f2" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label">[2]</td><td>referenced twice</td></tr>
+</tbody>
+</table>
+<table class="docutils citation" frame="void" id="once" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label">[once]</td><td>citation referenced once</td></tr>
+</tbody>
+</table>
+<table class="docutils citation" frame="void" id="twice" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label">[twice]</td><td>citation referenced twice</td></tr>
+</tbody>
+</table>
+""",
+],
+])
+
+
+totest['syntax_highlight'] = ({'syntax_highlight': 'short',
+ }, [
+["""\
+.. code:: shell
+
+ cat <<EOF
+ Hello World
+ EOF
+""",
+"""\
+<pre class="code shell literal-block">
+cat <span class="s"><<EOF
+Hello World
+EOF</span>
+</pre>
+""",
+],
+["""\
+.. role:: shell(code)
+ :language: shell
+
+:shell:`cat <<EOF Hello World EOF`
+""",
+"""\
+<p><code class="shell">cat <span class="s"><<EOF Hello World EOF</span></code></p>
+""",
+],
+])
+
+
+totest['system_messages'] = ({'math_output': 'mathml',
+ 'warning_stream': '',
+ }, [
+# No warning with HTML4 ("embed" error is silently ignored).
+["""\
+.. image:: https://dummy.png
+ :loading: embed
+""",
+"""\
+<img alt="https://dummy.png" src="https://dummy.png" />
+""",
+],
+# No error with HTML4 (silently ignored)
+[f"""\
+.. image:: {DATA_ROOT.as_uri()}/circle-broken.svg
+ :loading: embed
+""",
+"""\
+<object data="file:///usr/local/src/docutils-git-svn/docutils/test/data/circle-broken.svg" type="image/svg+xml">file:///usr/local/src/docutils-git-svn/docutils/test/data/circle-broken.svg</object>
+"""
+],
+[r"""Broken :math:`\sin \my`.
+""",
+"""\
+<p>Broken <span class="math problematic">\\sin \\my</span>.</p>
+<div class="system-message">
+<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils"><string></tt>, line 1)</p>
+Unknown LaTeX command "\\my".</div>
+"""],
+])
+
+totest['system_messages-PIL'] = ({'math_output': 'mathml',
+ 'warning_stream': '',
+ }, [
+["""\
+.. image:: dummy.png
+ :scale: 100%
+ :loading: embed
+""",
+"""\
+<img alt="dummy.png" src="dummy.png" />
+""",
+],
+["""\
+.. image:: dummy.mp4
+ :scale: 100%
+""",
+"""\
+<object data="dummy.mp4" type="video/mp4">dummy.mp4</object>
+""",
+],
+["""\
+.. image:: https://dummy.png
+ :scale: 100%
+ :loading: embed
+""",
+"""\
+<img alt="https://dummy.png" src="https://dummy.png" />
+""",
+],
+])
+
+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" />
+<object data="dummy.mp4" type="video/mp4">dummy.mp4</object>
+""",
+],
+[f"""\
+.. image:: {DATA_ROOT.as_uri()}/circle-broken.svg
+ :loading: embed
+""",
+"""\
+<object data="file:///usr/local/src/docutils-git-svn/docutils/test/data/circle-broken.svg" type="image/svg+xml">file:///usr/local/src/docutils-git-svn/docutils/test/data/circle-broken.svg</object>
+"""],
+[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_html4css1.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_html4css1_parts.py
===================================================================
--- trunk/docutils/test/test_writers/test_html4css1_parts.py 2024-08-21 13:45:18 UTC (rev 9915)
+++ trunk/docutils/test/test_writers/test_html4css1_parts.py 2024-08-21 13:45:27 UTC (rev 9916)
@@ -5,11 +5,9 @@
# Copyright: This module has been placed in the public domain.
"""
-Test for fragment code in HTML writer.
+Test `core.publish_parts()`__ with the html4css1 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
@@ -23,142 +21,145 @@
import docutils
import docutils.core
-from docutils.parsers.rst.directives.images import PIL
from docutils.writers import html4css1
-ROOT_PREFIX = (Path(__file__).parent.parent/'functional'/'input').as_posix()
-if PIL:
- SCALING_OUTPUT = 'style="width: 32.0px; height: 32.0px;" '
-else:
- SCALING_OUTPUT = ''
+# 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()
-class Html4WriterPublishPartsTestCase(unittest.TestCase):
- """
- Test case for HTML writer via the publish_parts interface.
- """
+# 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}<div class="document">\n',
+ 'body_suffix': '</div>\n{footer}</body>\n</html>\n',
+ 'docinfo': '',
+ 'encoding': 'utf-8',
+ 'errors': 'xmlcharrefreplace',
+ 'footer': '',
+ 'fragment': '',
+ 'head': '{meta}<title>{metatitle}</title>\n',
+ 'head_prefix':
+ '<?xml version="1.0" encoding="utf-8"?>\n'
+ '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'
+ ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n'
+ '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n'
+ '<head>\n',
+ 'header': '',
+ 'html_body': '{header}<div class="document">\n{fragment}</div>\n{footer}',
+ 'html_head': '{meta}<title>{metatitle}</title>\n',
+ 'html_prolog':
+ '<?xml version="1.0" encoding="%s"?>\n'
+ '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'
+ ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n',
+ 'html_subtitle': '',
+ 'html_title': '',
+ 'meta': '<meta http-equiv="Content-Type" content="text/html; charset=%s" />\n'
+ f'<meta name="generator" content="Docutils {docutils.__version__}: https://docutils.sourceforge.io/" />\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',
+ }
- maxDiff = None
- def test_publish(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=html4css1.Writer(),
- settings_overrides={
- '_disable_config': True,
- 'strict_visitor': True,
- 'stylesheet_path': '',
- **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)
+def format_parts(parts):
+ # fill in part values that depend on other parts
+ # https://docutils.sourceforge.io/docs/api/publisher.html#html4-writer
- standard_content_type_template = ('<meta http-equiv="Content-Type"'
- ' content="text/html; charset=%s" />\n')
- standard_generator_template = (
- '<meta name="generator"'
- f' content="Docutils {docutils.__version__}: '
- f'https://docutils.sourceforge.io/" />\n')
- standard_html_meta_value = (
- standard_content_type_template
- + standard_generator_template)
- standard_meta_value = standard_html_meta_value % 'utf-8'
- standard_html_prolog = (
- '<?xml version="1.0" encoding="%s"?>\n'
- '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" '
- '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n')
- standard_html_body_template = '<div class="document">\n%s</div>\n'
+ # metadata title: either the visible title or document['source']
+ metatitle = parts['title'] or '<string>'
- 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><string></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}
+ # "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
-totest = {}
+class Html5WriterPublishPartsTestCase(unittest.TestCase):
+ """Test HTML5 writer `publish_parts()` interface."""
-totest['title_promotion'] = ({}, [
-["""\
-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 <tt class="docutils literal">inline literal</tt></p>\n',
-],
-["""\
-Simple ``inline\xA0literal`` with NBSP
-""",
-'<p>Simple <tt class="docutils literal">inline literal</tt> with NBSP</p>\n',
-],
-["""\
-A simple `anonymous reference`__
+ maxDiff = None
-__ 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.
+ def test_publish_parts(self):
+ for name, (settings_overrides, cases) in totest.items():
+ 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=html4css1.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]}')
-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>
-""",
-],
-["""\
+totest = {}
+
+totest['standard'] = ({}, [
+ ['', # 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': '<div class="header">\ncustom document header\n'
+ '<hr class="header"/>\n</div>\n',
+ 'body_prefix': '</head>\n'
+ '<body>\n'
+ '<div class="header">\n'
+ 'custom document header\n'
+ '<hr class="header"/>\n'
+ '</div>\n'
+ '<div class="document">\n',
+ 'fragment': '<p>A paragraph.</p>\n',
+ }
+ ],
+ ['.. footer:: custom document footer\n\n'
+ 'A paragraph.',
+ {'footer': '<div class="footer">\n'
+ '<hr class="footer" />\n'
+ 'custom document footer\n</div>\n',
+ 'fragment': '<p>A paragraph.</p>\n',
+ }
+ ],
+ ["""\
+++++
Title
+++++
@@ -178,7 +179,10 @@
And even more stuff
""",
-{'fragment': """\
+ {'body_pre_docinfo': '<h1 class="title">Title</h1>\n'
+ '<h2 class="subtitle" id="subtitle">Subtitle</h2>\n',
+ 'body_prefix': '</head>\n<body>\n<div class="document" id="title">\n',
+ 'fragment': """\
<p>Some stuff</p>
<div class="section" id="section">
<h1>Section</h1>
@@ -189,7 +193,8 @@
</div>
</div>
""",
- 'html_body': """<div class="document" id="title">
+ 'html_body': """\
+<div class="document" id="title">
<h1 class="title">Title</h1>
<h2 class="subtitle" id="subtitle">Subtitle</h2>
<p>Some stuff</p>
@@ -203,13 +208,12 @@
</div>
</div>
""",
- 'html_head': '...<title>Title</title>\n',
- 'html_subtitle': '<h2 class="subtitle" id="subtitle">Subtitle</h2>\n',
- 'html_title': '<h1 class="title">Title</h1>\n',
- 'subtitle': 'Subtitle',
- 'title': 'Title'
-}],
-["""\
+ 'html_subtitle': '<h2 class="subtitle" id="subtitle">Subtitle</h2>\n',
+ 'html_title': '<h1 class="title">Title</h1>\n',
+ 'subtitle': 'Subtitle',
+ 'title': 'Title'
+ }],
+ ["""\
+++++
Title
+++++
@@ -218,7 +222,10 @@
Some stuff
""",
-{'docinfo': """<table class="docinfo" frame="void" rules="none">
+ {'body_pre_docinfo': '<h1 class="title">Title</h1>\n',
+ 'body_prefix': '</head>\n<body>\n<div class="document" id="title">\n',
+ 'docinfo': """\
+<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
@@ -227,8 +234,9 @@
</tbody>
</table>
""",
- 'fragment': '<p>Some stuff</p>\n',
- 'html_body': """<div class="document" id="title">
+ 'fragment': '<p>Some stuff</p>\n',
+ 'html_body': """\
+<div class="document" id="title">
<h1 class="title">Title</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
@@ -241,50 +249,14 @@
<p>Some stuff</p>
</div>
""",
- '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['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 <tt class="docutils literal">inline literal</tt></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
+++++
@@ -304,7 +276,7 @@
And even more stuff
""",
-"""\
+ {'fragment': """\
<div class="section" id="title">
<h1>Title</h1>
<div class="section" id="not-a-subtitle">
@@ -320,109 +292,25 @@
</div>
</div>
</div>
-""",
-],
-["""\
-* bullet
-* list
-""",
-"""\
-<ul class="simple">
-<li>bullet</li>
-<li>list</li>
-</ul>
-""",
-],
-["""\
-.. table::
- :align: right
+"""},
+ ],
+ ])
- +-----+-----+
- | 1 | 2 |
- +-----+-----+
- | 3 | 4 |
- +-----+-----+
-""",
-"""\
-<table border="1" class="docutils align-right">
-<colgroup>
-<col width="50%" />
-<col width="50%" />
-</colgroup>
-<tbody valign="top">
-<tr><td>1</td>
-<td>2</td>
-</tr>
-<tr><td>3</td>
-<td>4</td>
-</tr>
-</tbody>
-</table>
-""",
-],
-["""\
-Not a docinfo.
+totest['unknown-encoding'] = ({'output_encoding': 'unicode'}, [
+ ['Simple String\n',
+ {'encoding': 'unicode',
+ 'fragment': '<p>Simple String</p>\n',
+ 'head_prefix':
+ '<?xml version="1.0"?>\n'
+ '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'
+ ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n'
+ '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n'
+ '<head>\n',
+ 'html_head': f'{default_parts["meta"]}<title>{{metatitle}}</title>\n',
+ 'meta': f'<meta name="generator" content="Docutils {docutils.__version__}: https://docutils.sourceforge.io/" />\n',
+ }],
+ ])
-:This: .. _target:
- is
-:a:
-:simple:
-:field: list
-""",
-"""\
-<p>Not a docinfo.</p>
-<table class="docutils field-list" frame="void" rules="none">
-<col class="field-name" />
-<col class="field-body" />
-<tbody valign="top">
-<tr class="field"><th class="field-name">This:</th><td class="field-body"><p class="first last" id="target">is</p>
-</td>
-</tr>
-<tr class="field"><th class="field-name">a:</th><td class="field-body"></td>
-</tr>
-<tr class="field"><th class="field-name">simple:</th><td class="field-body"></td>
-</tr>
-<tr class="field"><th class="field-name">field:</th><td class="field-body">list</td>
-</tr>
-</tbody>
-</table>
-""",
-],
-["""\
-Not a docinfo.
-
-:This is: a
-:simple field list with loooong field: names
-""",
-"""\
-<p>Not a docinfo.</p>
-<table class="docutils field-list" frame="void" rules="none">
-<col class="field-name" />
-<col class="field-body" />
-<tbody valign="top">
-<tr class="field"><th class="field-name">This is:</th><td class="field-body">a</td>
-</tr>
-<tr class="field"><th class="field-name" colspan="2">simple field list with loooong field:</th></tr>
-<tr class="field"><td> </td><td class="field-body">names</td>
-</tr>
-</tbody>
-</table>
-""",
-],
-])
-
-totest['root_prefix'] = ({'root_prefix': ROOT_PREFIX}, [
-
-["""\
-.. image:: /data/blue%20square.png
- :scale: 100%
-""",
-'<img alt="/data/blue%20square.png"'
-f' src="/data/blue%20square.png" {SCALING_OUTPUT}/>\n',
-],
-])
-
-
if __name__ == '__main__':
unittest.main()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.