summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docutils/HISTORY.txt1
-rw-r--r--docutils/RELEASE-NOTES.txt4
-rw-r--r--docutils/docs/user/config.txt26
-rw-r--r--docutils/docutils/writers/_html_base.py48
-rw-r--r--docutils/docutils/writers/html4css1/__init__.py9
-rw-r--r--docutils/docutils/writers/html5_polyglot/__init__.py9
-rw-r--r--docutils/test/functional/expected/embed_images_html5.html32
-rw-r--r--docutils/test/functional/input/embed_images.txt25
-rw-r--r--docutils/test/functional/tests/embed_images_html5.py14
9 files changed, 145 insertions, 23 deletions
diff --git a/docutils/HISTORY.txt b/docutils/HISTORY.txt
index 31507c122..d20229244 100644
--- a/docutils/HISTORY.txt
+++ b/docutils/HISTORY.txt
@@ -25,6 +25,7 @@ Changes Since 0.16
- Installing with ``setup.py`` now requires ``setuptools``.
Alternatively, install with `pip`_ (or "manually").
- Apply patch for bug #399 Fixes in Korean translation.
+ - Implement feature request #40 `Option to embed images as data URI`.
* docutils/MANIFEST.in
diff --git a/docutils/RELEASE-NOTES.txt b/docutils/RELEASE-NOTES.txt
index c405c0d9a..4760b2440 100644
--- a/docutils/RELEASE-NOTES.txt
+++ b/docutils/RELEASE-NOTES.txt
@@ -78,6 +78,8 @@ Release 0.17
* Installing with ``setup.py`` now requires setuptools_.
Alternatively, install with pip_.
+
+* HTML writers: new option to embed images.
* HTML5 writer:
@@ -101,8 +103,6 @@ Release 0.17
.. _initial_header_level: docs/user/config.html#initial-header-level
__ https://stackoverflow.com/questions/39547412/same-font-size-for-h1-and-h2-in-article
-
-
* LaTeX writer:
- New configuration setting `legacy_class_functions`_.
diff --git a/docutils/docs/user/config.txt b/docutils/docs/user/config.txt
index 2ca4c30c1..641fd977a 100644
--- a/docutils/docs/user/config.txt
+++ b/docutils/docs/user/config.txt
@@ -956,6 +956,21 @@ attributes (values "compact" and "open") in the document.
Default: enabled (True).
Options: ``--compact-field-lists, --no-compact-field-lists``.
+embed_images
+~~~~~~~~~~~~
+
+Embed images in the output HTML file. If the image can be read from
+the local file system and its MIME type can be determined, it is
+base64_ encoded and included as a `data URI`_.
+
+Default: disabled (False).
+Options: ``--embed-images``, ``--link-images``
+
+New in Docutils 0.17.
+
+.. _base64: https://en.wikipedia.org/wiki/Base64
+.. _data URI: https://en.wikipedia.org/wiki/Data_URI_scheme
+
.. _embed_stylesheet [html writers]:
@@ -1033,7 +1048,7 @@ the output document. Supported values are (case insensitive):
* It is recommended to install__ the MathJax library on the same
server as the rest of the deployed site files.
- __ http://docs.mathjax.org/en/latest/installation.html
+ __ https://www.mathjax.org/#installnow
Example: Install the library at the top level of the web
server’s hierarchy in the directory ``MathJax`` and set::
@@ -1046,13 +1061,14 @@ the output document. Supported values are (case insensitive):
Downside: Downloads JavaScript code from a third-party site --- opens
the door to cross-site scripting attacs!
- Example: MathJax.org recommends ``cdnjs.cloudflare.com``::
+ Example: MathJax `getting started`__ documentation uses::
math-output: mathjax
- https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js
+ https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
- See https://cdnjs.com/about and https://www.cloudflare.com/terms/ for
- details and terms of use.
+ See https://www.jsdelivr.com/ for details and terms of use.
+
+ __ https://www.mathjax.org/#gettingstarted
* Use a local MathJax installation on the *client* machine, e.g.::
diff --git a/docutils/docutils/writers/_html_base.py b/docutils/docutils/writers/_html_base.py
index 4352eb346..c7ff96e81 100644
--- a/docutils/docutils/writers/_html_base.py
+++ b/docutils/docutils/writers/_html_base.py
@@ -17,9 +17,11 @@
"""common definitions for Docutils HTML writers"""
-import sys
-import os.path
+import base64
+import mimetypes
+import os, os.path
import re
+import sys
try: # check for the Python Imaging Library
import PIL.Image
@@ -905,19 +907,10 @@ class HTMLTranslator(nodes.NodeVisitor):
self.header.extend(header)
del self.body[start:]
- # Image types to place in an <object> element
- object_image_types = {'.swf': 'application/x-shockwave-flash'}
-
def visit_image(self, node):
atts = {}
uri = node['uri']
- ext = os.path.splitext(uri)[1].lower()
- if ext in self.object_image_types:
- atts['data'] = uri
- atts['type'] = self.object_image_types[ext]
- else:
- atts['src'] = uri
- atts['alt'] = node.get('alt', uri)
+ mimetype = mimetypes.guess_type(uri)[0]
# image size
if 'width' in node:
atts['width'] = node['width']
@@ -966,12 +959,35 @@ class HTMLTranslator(nodes.NodeVisitor):
suffix = ''
if 'align' in node:
atts['class'] = 'align-%s' % node['align']
- if ext in self.object_image_types:
+ # Embed image file (embedded SVG or data URI):
+ if self.settings.embed_images or ('embed' in node):
+ err_msg = ''
+ if not mimetype:
+ err_msg = 'unknown MIME type for "%s"' % uri
+ if not self.settings.file_insertion_enabled:
+ err_msg = 'file insertion disabled.'
+ try:
+ with open(url2pathname(uri), 'rb') as imagefile:
+ imagedata = imagefile.read()
+ except IOError as err:
+ err_msg = str(err)
+ if not err_msg:
+ # TODO (test mimetype for SVG and insert directly)
+ data64 = base64.b64encode(imagedata).decode()
+ uri = u'data:%s;base64,%s' % (mimetype, data64)
+ else:
+ # raise NotImplementedError(os.getcwd() + err_msg)
+ self.document.reporter.error("Cannot embed image\n "+err_msg)
+
+ if mimetype == 'application/x-shockwave-flash':
+ atts['type'] = mimetype
# do NOT use an empty tag: incorrect rendering in browsers
- self.body.append(self.starttag(node, 'object', '', **atts) +
- node.get('alt', uri) + '</object>' + suffix)
+ tag = (self.starttag(node, 'object', '', data=uri, **atts)
+ + node.get('alt', uri) + '</object>' + suffix)
else:
- self.body.append(self.emptytag(node, 'img', suffix, **atts))
+ atts['alt'] = node.get('alt', node['uri'])
+ tag = self.emptytag(node, 'img', suffix, src=uri, **atts)
+ self.body.append(tag)
def depart_image(self, node):
pass
diff --git a/docutils/docutils/writers/html4css1/__init__.py b/docutils/docutils/writers/html4css1/__init__.py
index b3af3d996..f5dfd540c 100644
--- a/docutils/docutils/writers/html4css1/__init__.py
+++ b/docutils/docutils/writers/html4css1/__init__.py
@@ -124,6 +124,15 @@ class Writer(writers._html_base.Writer):
('Disable compact simple field lists.',
['--no-compact-field-lists'],
{'dest': 'compact_field_lists', 'action': 'store_false'}),
+ ('Embed images in the output HTML file, if the image '
+ 'files are accessible during processing.',
+ ['--embed-images'],
+ {'default': 0, 'action': 'store_true',
+ 'validator': frontend.validate_boolean}),
+ ('Link to images in the output HTML file. '
+ 'This is the default.',
+ ['--link-images'],
+ {'dest': 'embed_images', 'action': 'store_false'}),
('Added to standard table classes. '
'Defined styles: "borderless". Default: ""',
['--table-style'],
diff --git a/docutils/docutils/writers/html5_polyglot/__init__.py b/docutils/docutils/writers/html5_polyglot/__init__.py
index e98dba121..311623df0 100644
--- a/docutils/docutils/writers/html5_polyglot/__init__.py
+++ b/docutils/docutils/writers/html5_polyglot/__init__.py
@@ -114,6 +114,15 @@ class Writer(writers._html_base.Writer):
('Disable compact simple field lists.',
['--no-compact-field-lists'],
{'dest': 'compact_field_lists', 'action': 'store_false'}),
+ ('Embed images in the output HTML file, if the image '
+ 'files are accessible during processing.',
+ ['--embed-images'],
+ {'default': 0, 'action': 'store_true',
+ 'validator': frontend.validate_boolean}),
+ ('Link to images in the output HTML file. '
+ 'This is the default.',
+ ['--link-images'],
+ {'dest': 'embed_images', 'action': 'store_false'}),
('Added to standard table classes. '
'Defined styles: borderless, booktabs, '
'align-left, align-center, align-right, colwidths-auto. '
diff --git a/docutils/test/functional/expected/embed_images_html5.html b/docutils/test/functional/expected/embed_images_html5.html
new file mode 100644
index 000000000..a8bcef150
--- /dev/null
+++ b/docutils/test/functional/expected/embed_images_html5.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta charset="utf-8"/>
+<meta name="generator" content="Docutils 0.17b.dev: http://docutils.sourceforge.net/" />
+<title>Embedded Images</title>
+<link rel="stylesheet" href="../../../docutils/writers/html5_polyglot/minimal.css" type="text/css" />
+<link rel="stylesheet" href="../../../docutils/writers/html5_polyglot/plain.css" type="text/css" />
+</head>
+<body>
+<main id="embedded-images">
+<h1 class="title">Embedded Images</h1>
+
+<p>The “embed” flag tells Docutils that it should
+try to embed the image in the output document.</p>
+<p>If the image can be read from the local file system, it is <a class="reference external" href="https://en.wikipedia.org/wiki/Base64">base64</a>
+encoded and included as a <a class="reference external" href="https://en.wikipedia.org/wiki/Data_URI_scheme">data URI</a>.
+In future, SVG images may be directly inserted into HTML5.</p>
+<blockquote>
+<figure class="align-center">
+<img alt="biohazard" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiCiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIKICAgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczpzb2RpcG9kaT0iaHR0cDovL3NvZGlwb2RpLnNvdXJjZWZvcmdlLm5ldC9EVEQvc29kaXBvZGktMC5kdGQiCiAgIHhtbG5zOmlua3NjYXBlPSJodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy9uYW1lc3BhY2VzL2lua3NjYXBlIgogICBzb2RpcG9kaTpkb2NuYW1lPSJiaW9oYXphcmQuc3ZnIgogICBpbmtzY2FwZTp2ZXJzaW9uPSIwLjQ3IHIyMjU4MyIKICAgc29kaXBvZGk6dmVyc2lvbj0iMC4zMiIKICAgaWQ9InN2ZzI0MTU5IgogICBoZWlnaHQ9IjQ4IgogICB3aWR0aD0iNDgiCiAgIHZlcnNpb249IjEuMCI+CiAgPHRpdGxlCiAgICAgaWQ9InRpdGxlMjgzNyI+QmlvaGF6YXJkPC90aXRsZT4KICA8bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGE3Ij4KICAgIDxyZGY6UkRGPgogICAgICA8Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+CiAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+CiAgICAgICAgPGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPgogICAgICAgIDxkYzp0aXRsZT5CaW9oYXphcmQ8L2RjOnRpdGxlPgogICAgICAgIDxjYzpsaWNlbnNlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9wdWJsaWNkb21haW4vIiAvPgogICAgICAgIDxkYzpkZXNjcmlwdGlvbj5TdGFuZGFsb25lIGJpb2hhemFyZCBzeW1ib2wsIHdpdGggbm8gYm9yZGVyLCBiYWNrZ3JvdW5kIG9yIGRlc2NyaXB0aXZlIHRleHQuPC9kYzpkZXNjcmlwdGlvbj4KICAgICAgICA8ZGM6Y3JlYXRvcj4KICAgICAgICAgIDxjYzpBZ2VudD4KICAgICAgICAgICAgPGRjOnRpdGxlPlNpbHNvcjwvZGM6dGl0bGU+CiAgICAgICAgICA8L2NjOkFnZW50PgogICAgICAgIDwvZGM6Y3JlYXRvcj4KICAgICAgICA8ZGM6aWRlbnRpZmllcj48L2RjOmlkZW50aWZpZXI+CiAgICAgICAgPGRjOnNvdXJjZT48L2RjOnNvdXJjZT4KICAgICAgICA8ZGM6cmVsYXRpb24+aHR0cDovL2RlLndpa2lwZWRpYS5vcmcvd2lraS9EYXRlaTpCaW9oYXphcmRfc3ltYm9sLnN2ZzwvZGM6cmVsYXRpb24+CiAgICAgICAgPGRjOnB1Ymxpc2hlcj4KICAgICAgICAgIDxjYzpBZ2VudD4KICAgICAgICAgICAgPGRjOnRpdGxlPldpa2lwZWRpYTwvZGM6dGl0bGU+CiAgICAgICAgICA8L2NjOkFnZW50PgogICAgICAgIDwvZGM6cHVibGlzaGVyPgogICAgICAgIDxkYzpjb250cmlidXRvcj4KICAgICAgICAgIDxjYzpBZ2VudD4KICAgICAgICAgICAgPGRjOnRpdGxlPkJhc3RpcXVlLCBBbmR1eCwgTWFyaWFuU2lnbGVyLCBHTTwvZGM6dGl0bGU+CiAgICAgICAgICA8L2NjOkFnZW50PgogICAgICAgIDwvZGM6Y29udHJpYnV0b3I+CiAgICAgIDwvY2M6V29yaz4KICAgICAgPGNjOkxpY2Vuc2UKICAgICAgICAgcmRmOmFib3V0PSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9wdWJsaWNkb21haW4vIj4KICAgICAgICA8Y2M6cGVybWl0cwogICAgICAgICAgIHJkZjpyZXNvdXJjZT0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjUmVwcm9kdWN0aW9uIiAvPgogICAgICAgIDxjYzpwZXJtaXRzCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyNEaXN0cmlidXRpb24iIC8+CiAgICAgICAgPGNjOnBlcm1pdHMKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL25zI0Rlcml2YXRpdmVXb3JrcyIgLz4KICAgICAgPC9jYzpMaWNlbnNlPgogICAgPC9yZGY6UkRGPgogIDwvbWV0YWRhdGE+CiAgPGRlZnMKICAgICBpZD0iZGVmczUiPgogICAgPGlua3NjYXBlOnBlcnNwZWN0aXZlCiAgICAgICBzb2RpcG9kaTp0eXBlPSJpbmtzY2FwZTpwZXJzcDNkIgogICAgICAgaW5rc2NhcGU6dnBfeD0iMCA6IDE3OC4xMzEyNiA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF95PSIwIDogMTAwMCA6IDAiCiAgICAgICBpbmtzY2FwZTp2cF96PSIzNzYuNDM3NSA6IDE3OC4xMzEyNiA6IDEiCiAgICAgICBpbmtzY2FwZTpwZXJzcDNkLW9yaWdpbj0iMTg4LjIxODc1IDogMTE4Ljc1NDE3IDogMSIKICAgICAgIGlkPSJwZXJzcGVjdGl2ZTI4MzUiIC8+CiAgPC9kZWZzPgogIDxzb2RpcG9kaTpuYW1lZHZpZXcKICAgICBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJzdmcyNDE1OSIKICAgICBpbmtzY2FwZTp3aW5kb3cteT0iMzMiCiAgICAgaW5rc2NhcGU6d2luZG93LXg9IjAiCiAgICAgaW5rc2NhcGU6Y3k9IjIyLjQ1NTQxOCIKICAgICBpbmtzY2FwZTpjeD0iMjIuMTUyNjM5IgogICAgIGlua3NjYXBlOnpvb209IjguOTMxNjY5MyIKICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSI3NzEiCiAgICAgaW5rc2NhcGU6d2luZG93LXdpZHRoPSI5OTMiCiAgICAgaW5rc2NhcGU6cGFnZXNoYWRvdz0iMiIKICAgICBpbmtzY2FwZTpwYWdlb3BhY2l0eT0iMC4wIgogICAgIGJvcmRlcm9wYWNpdHk9IjEuMCIKICAgICBib3JkZXJjb2xvcj0iIzY2NjY2NiIKICAgICBwYWdlY29sb3I9IiNmZmZmZmYiCiAgICAgaWQ9ImJhc2UiCiAgICAgc2hvd2dyaWQ9ImZhbHNlIgogICAgIGlua3NjYXBlOndpbmRvdy1tYXhpbWl6ZWQ9IjAiIC8+CiAgPHBhdGgKICAgICBpZD0icGF0aDcyMTQiCiAgICAgc3R5bGU9ImZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZTtkaXNwbGF5OmlubGluZSIKICAgICBkPSJtIDIzLjU4NTE2MywxLjM3Nzc3MSBjIC03LjNlLTUsMS4xZS00IDYuMmUtNSwwLjAwMzkgMCwwLjAwMzkgMC4wMDEzLC0zLjU0ZS00IDAuMDAyNiwtMC4wMDMyIDAuMDAzOSwtMC4wMDM5IC00Ljc4ZS00LDAgLTAuMDAzNCwtMi4zZS01IC0wLjAwMzksMCB6IG0gLTAuMjkzMjg3LDAuMDExNzMgYyAtMC4wMDI3LDMuMzllLTQgLTAuMDA1MSwwLjAwMzIgLTAuMDA3OCwwLjAwMzkgMC4wMTA0NywtNi40N2UtNCAwLjAyMDgsLTAuMDAzMiAwLjAzMTMsLTAuMDAzOSAtMC4wMDI2LDMuMWUtNSAtMC4wMDUzLC0xLjE4ZS00IC0wLjAwNzgsMCAtMC4wMDU3LDIuNmUtNCAtMC4wMTAxNiwtNi45NGUtNCAtMC4wMTU2NCwwIHogbSAxLjQyMzQsMC4wMDc4IGMgMC4wMjA4NSwwLjAwMTYgMC4wNDE3NiwwLjAwMjMgMC4wNjI1NywwLjAwMzkgLTAuMDIwNDcsLTAuMDAxNiAtMC4wNDIwNCwtMC4wMDMyIC0wLjA2MjU3LC0wLjAwMzkgeiBtIDAuMDYyNTcsMC4wMDM5IGMgNS4yNjU5ODcsMC40MTg1NDcgOS40MTI0NTQsNC44MzMyMzQzIDkuNDEyNDU0LDEwLjIwNjI1OCAwLDUuNDcwNzY3IC00LjMwMzU1Myw5LjkzMjc4MSAtOS43MDU3NDMsMTAuMjEwMTgyIGwgMCwyLjA5NjAwNCBjIDEuNDc0ODUyLDAuMjMzMTcgMi42MDQzNzEsMS41MTM5OTMgMi42MDQzNzEsMy4wNTQwNTkgMCwwLjM3NjkzMiAtMC4wNjc4NiwwLjczNzM5MyAtMC4xOTE2MTQsMS4wNzE0NjUgbCAxLjkxNjEyNSwxLjEwNjY1MyBjIDIuOTYxMTgsLTQuNDczMDQyIDguOTM1NDg1LC01LjkzMjU4NiAxMy42NDM1NDMsLTMuMjE0Mzk1IDQuNjk2ODU4LDIuNzExNzM5IDYuNDMxMTE3LDguNTk0NzA2IDQuMDYyOTUxLDEzLjM4OTM3MyAzLjI1MDEyLC02LjMyNTkyNyAwLjk5MDAzNywtMTQuMTY2NTg2IC01LjIzNjA3OSwtMTcuNzYxMjQ2IC0xLjU1Nzc4MywtMC44OTkzODMgLTMuMjE3NTYsLTEuNDQ3MzAyIC00Ljg5NTg4MywtMS42NzM2NjYgMC42NDI0MjYsLTEuNTY2Mjk5IDAuOTk3MTU5LC0zLjI4MTM4NCAwLjk5NzE1OSwtNS4wNzk2NzggMCwtNy4xMzY5NDk3IC01LjU3NjYzOSwtMTIuOTc5NTM2IC0xMi42MDcyODQsLTEzLjQwNTAwOSB6IG0gLTEuNzE2NjgyLDAuMDA3OCBjIC02Ljk5NTUwNywwLjQ2MjA0NyAtMTIuNTM2ODk3LDYuMjg1NDY5MyAtMTIuNTM2ODk3LDEzLjM5NzE4NyAwLDEuNzQ3MSAwLjMzMzkyLDMuNDE2ODI3IDAuOTQyNDE4LDQuOTQ2NzA5IEMgOS44MzgyOTkyLDE5Ljk5MTQ5OCA4LjIyNDA3MjIsMjAuNTMzOTg5IDYuNzExNTc5MiwyMS40MDcyMiAwLjUyNzE0NTU1LDI0Ljk3NzgwNiAtMS43MzgzMjk1LDMyLjczNTk4OSAxLjQxNjg0MzksMzkuMDM5NDM0IC0wLjg2MTIxMjg1LDM0LjI2NzczIDAuODg1Nzg1ODUsMjguNDYzNjYzIDUuNTQyMzU1MiwyNS43NzUxODYgMTAuMjgwMTc5LDIzLjAzOTgxNCAxNi4yOTU0MTYsMjQuNTM1ODkzIDE5LjIzNjczMSwyOS4wNzU2MSBsIDEuODQ5NjUzLC0xLjA2NzU1IGMgLTAuMTE2MjQ1LC0wLjMyNDk1OCAtMC4xNzU5NjgsLTAuNjc1NDIyIC0wLjE3NTk2OCwtMS4wNDAxNzcgMCwtMS40NzQ2ODQgMS4wMzM5MDQsLTIuNzA4MSAyLjQxNjY1MywtMy4wMTQ5NjMgbCAwLC0yLjEzODk5OCBjIC01LjM1NDM2MSwtMC4zMjc5NTkgLTkuNjA0MDUzLC00Ljc2OTg3OCAtOS42MDQwNTMsLTEwLjIwNjI4NCAwLC01LjM0ODQzNzcgNC4xMDY1MTEsLTkuNzQ1NTgxIDkuMzM4MTQxLC0xMC4xOTg0MzYgeiBtIDAuNTk4MywxMi44NTc1MzkgYyAtMi43MDI1MTMsMC4wNjIxNSAtNS4xOTM5LDAuOTgyMTk5IC03LjIzODIzOSwyLjQ3OTIzOSAwLjE2MzMxOSwwLjI0MTY3OCAwLjMzODgsMC40NzU1ODEgMC41MjM5OTUsMC42OTk5NjggMC4xODUyMTEsMC4yMjQzNzkgMC4zODEwMTgsMC40Mzk2NiAwLjU4NjU3MiwwLjY0NTIyIDAuMjA1NTUyLDAuMjA1NTUyIDAuNDIwODM4LDAuNDAxMzY4IDAuNjQ1MjMzLDAuNTg2NTY1IDAuMTY0OTc0LDAuMTM2MTY5IDAuMzQxNzMsMC4yNTg3NjMgMC41MTYxNzQsMC4zODMyMjYgMS41MDkwNDEsLTAuOTkwODAxIDMuMzE2MTU3LC0xLjU3MTk5MyA1LjI2MzQ2NiwtMS41NzE5OTMgMS45NDcyODYsLThlLTYgMy43NTA1MDYsMC41ODExOTIgNS4yNTk1NDUsMS41NzE5OTMgMC4xNzQ0NDYsLTAuMTI0NDYzIDAuMzUxMTkzLC0wLjI0NzA1NyAwLjUxNjE3NiwtMC4zODMyMjYgMC4yMjQzOSwtMC4xODUxOTcgMC40Mzk2NzMsLTAuMzgxMDEzIDAuNjQ1MjE5LC0wLjU4NjU2NSAwLjIwNTU2NywtMC4yMDU1NiAwLjQwMTM3NSwtMC40MjA4NDEgMC41ODY1NzgsLTAuNjQ1MjIgMC4xODUxOTUsLTAuMjI0Mzg3IDAuMzYwNjY5LC0wLjQ1ODI5IDAuNTIzOTk4LC0wLjY5OTk2OCAtMi4xMTgyMjgsLTEuNTUxMTQzIC00LjcxNjA1MSwtMi40NzkyMzkgLTcuNTMxNTE2LC0yLjQ3OTIzOSAtMC4wNjU5OSwwIC0wLjEzMzY4OSwtNy44OGUtNCAtMC4xOTk0NDUsMCAtMC4wMzIxLDUuMDRlLTQgLTAuMDY1NzIsLTcuMzNlLTQgLTAuMDk3NzUsMCB6IG0gLTEyLjMxNzkxLDExLjI3Nzg2NyBjIC0wLjI4NDIyMywyLjYxMDAwMyAwLjIxMTE5OSw1LjMyMzk3MSAxLjYxODkyNCw3Ljc2MjI0IDEuNDA3NzM0LDIuNDM4MjUyIDMuNTEwMTU4LDQuMjI4MDU2IDUuOTEyNTkyLDUuMjg2OTE2IDAuMTI3NjQ4LC0wLjI2MjI4NCAwLjI0MjM5NCwtMC41MzI5NjcgMC4zNDQxMjEsLTAuODA1NTU2IDAuMTAxNzMxLC0wLjI3MjU3MyAwLjE5MDY3NiwtMC41NDgyMDkgMC4yNjU5MDIsLTAuODI4OTk5IDAuMDc1MjUsLTAuMjgwNzk3IDAuMTM5NTA0LC0wLjU2NTU2NCAwLjE4NzcwNCwtMC44NTI0ODEgMC4wMzU0NSwtMC4yMTA5NjQgMC4wNTM3NCwtMC40MjQxMSAwLjA3NDMxLC0wLjYzNzQxNSAtMS42MTI1ODgsLTAuODExNDYzIC0zLjAxODkyNSwtMi4wODcxNTcgLTMuOTkyNTc0LC0zLjc3MzU3OCAtMC45NzM2NTIsLTEuNjg2NDEyIC0xLjM3NDQzNiwtMy41MzkzOTkgLTEuMjcwODk5LC01LjM0MTY2NCAtMC4xOTQ5OTUsLTAuMDg4ODQgLTAuMzkwMDYyLC0wLjE3OTM5MSAtMC41OTA0ODIsLTAuMjU0MTg3IC0wLjI3MjU3NywtMC4xMDE3MSAtMC41NDgyMTYsLTAuMTkwNjY0IC0wLjgyOTAxMiwtMC4yNjU5MDkgLTAuMjgwNzk0LC0wLjA3NTIzIC0wLjU2NTU1MiwtMC4xMzU1ODUgLTAuODUyNDczLC0wLjE4Mzc4NiAtMC4yODY5MTksLTAuMDQ4MjEgLTAuNTc3MTU1LC0wLjA4NDk5IC0wLjg2ODExOSwtMC4xMDU1ODIgeiBtIDI1LjMxNjIzNCwwLjE1MjQ5OCBjIC0wLjI5MDk3NiwwLjAyMDY0IC0wLjU4MTE5NiwwLjA1NzQzIC0wLjg2ODExOCwwLjEwNTU5MiAtMC4yODY5MjQsMC4wNDgyMSAtMC41NzE2OTQsMC4xMDg1NTEgLTAuODUyNDg5LDAuMTgzNzk2IC0wLjI4MDc4LDAuMDc1MjMgLTAuNTYwMzMxLDAuMTY0MTg4IC0wLjgzMjkxNywwLjI2NTkxNiAtMC4yMDA0MTYsMC4wNzQ3NSAtMC4zOTE1NjgsMC4xNjkyMzggLTAuNTg2NTYyLDAuMjU4MDc5IDAuMTAzNTI5LDEuODAyMjU3IC0wLjI5NzI1NCwzLjY1NTI2OCAtMS4yNzA5MDQsNS4zNDE2NzIgLTAuOTczNjQ0LDEuNjg2NDA1IC0yLjM3OTk4NywyLjk1ODE5OCAtMy45OTI1NTYsMy43Njk2NjMgMC4wMjA1NiwwLjIxMzI5NiAwLjAzODg1LDAuNDI2NDUgMC4wNzQyOSwwLjYzNzQwNiAwLjA0ODIsMC4yODY5MjUgMC4xMDg1NDQsMC41NzE2ODQgMC4xODM3ODcsMC44NTI0OSAwLjA3NTI0LDAuMjgwNzg5IDAuMTY0MTk1LDAuNTYwMzQ5IDAuMjY1OTE3LDAuODMyOTEzIDAuMTAxNzEsMC4yNzI1OTggMC4yMTY0OCwwLjUzOTM1NyAwLjM0NDExNSwwLjgwMTY1IDIuNDAyNDQxLC0xLjA1ODg3IDQuNTA0ODYzLC0yLjg0NDc1NiA1LjkxMjU5LC01LjI4MzAxOCAxLjQwNzc0OSwtMi40MzgyNjggMS45MDcwNTgsLTUuMTU2MTUxIDEuNjIyODQzLC03Ljc2NjE1NSB6IG0gLTE0Ljk4NDgzNiwzLjMwMDQyNCAtMS44NjEzNzYsMS4wNzkyODYgYyAyLjM5MzE3NSw0LjgwMDk3IDAuNjcyNDgsMTAuNzAyNDQ4IC00LjAzNTU2NCwxMy40MjA2NTQgLTQuNjg0ODc2LDIuNzA0ODA3IC0xMC42Mjg1NDE4LDEuMjgxNDM3IC0xMy42MDQ0NTM4LC0zLjE0MDA4NyAzLjg2MTY0NSw1Ljk1MDI4NiAxMS43NTg0Njk4LDcuOTAwODQyIDE3Ljk3MjQxMDgsNC4zMTMyMSAxLjUwNTI3MSwtMC44NjkwNzEgMi43NzUwNjIsLTEuOTg5NDMxIDMuNzkzMTMzLC0zLjI3MzAyNiAxLjAzODA2MiwxLjM0OTMyMyAyLjM1MTg2NCwyLjUyMTE3OCAzLjkxODI2NiwzLjQyNTUzOSA2LjIyMDkzMiwzLjU5MTY1MiAxNC4xMjcyNjMsMS42MzMxNyAxNy45ODQxNSwtNC4zMzI3NjggLTIuOTcwNDAxLDQuNDQwNjU4IC04LjkyMjcxNSw1Ljg3NzIzMSAtMTMuNjE2MTc0LDMuMTY3NDYxIC00LjczNzgxOCwtMi43MzUzODggLTYuNDQ5NTExLC04LjY5MzQ2NSAtMy45ODg2NTksLTEzLjUxMDU5IEwgMjYuMjk5MDIsMjkuMDI4NjE3IGMgLTAuNTY1NjkyLDAuNjI5ODQ0IC0xLjM4Njc2OCwxLjAyODQ0OCAtMi4yOTkzNDgsMS4wMjg0NDggLTAuOTI3NTc3LDAgLTEuNzYwMjk5LC0wLjQxMTc5MSAtMi4zMjY3MiwtMS4wNTk3MzYgeiIgLz4KPC9zdmc+Cg==" />
+<figcaption>
+<p>SVG image embedded in a figure.</p>
+</figcaption>
+</figure>
+</blockquote>
+<p>Embedded inline image <img alt="inline-embedded" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABGdBTUEAANkE3LLaAgAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAAZQTFRF////AAAAVcLTfgAAAAF0Uk5TAEDm2GYAAAA2SURBVHicYmBRYOAQYJCQYJC+wSBjAUL2fxjq6hgueTNM7AQh3g0MzAdAiP0BUBYAAAD//wMA4pkLDrFBDzUAAAAASUVORK5CYII=" style="height: 0.8em;" /> scaled to a height of 0.8 em.</p>
+<blockquote>
+</blockquote>
+</main>
+</body>
+</html>
diff --git a/docutils/test/functional/input/embed_images.txt b/docutils/test/functional/input/embed_images.txt
new file mode 100644
index 000000000..bd42e35aa
--- /dev/null
+++ b/docutils/test/functional/input/embed_images.txt
@@ -0,0 +1,25 @@
+Embedded Images
+---------------
+
+The "embed" flag tells Docutils that it should
+try to embed the image in the output document.
+
+If the image can be read from the local file system, it is base64_
+encoded and included as a `data URI`_.
+In future, SVG images may be directly inserted into HTML5.
+
+ .. figure:: ../docs/user/rst/images/biohazard.svg
+ :alt: biohazard
+ :align: center
+
+ SVG image embedded in a figure.
+
+
+Embedded inline image |inline-embedded| scaled to a height of 0.8 em.
+
+ .. |inline-embedded| image:: ../docs/user/rst/images/biohazard.png
+ :height: 0.8 em
+
+.. _base64: https://en.wikipedia.org/wiki/Base64
+.. _data URI: https://en.wikipedia.org/wiki/Data_URI_scheme
+
diff --git a/docutils/test/functional/tests/embed_images_html5.py b/docutils/test/functional/tests/embed_images_html5.py
new file mode 100644
index 000000000..3adac07a7
--- /dev/null
+++ b/docutils/test/functional/tests/embed_images_html5.py
@@ -0,0 +1,14 @@
+with open('functional/tests/_standalone_rst_defaults.py') as _f:
+ exec(_f.read())
+
+# Source and destination file names.
+test_source = "embed_images.txt"
+test_destination = "embed_images_html5.html"
+
+# Keyword parameters passed to publish_file.
+writer_name = "html5"
+
+# Settings:
+settings_overrides['smart_quotes'] = 'yes'
+settings_overrides['embed_images'] = 'yes'
+