|
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.
|