mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Support images in Data URI on non-HTML builders
This commit is contained in:
parent
be261ed71e
commit
ebdec70dfc
3
CHANGES
3
CHANGES
@ -106,7 +106,8 @@ Features added
|
|||||||
``suppress_warnings``
|
``suppress_warnings``
|
||||||
* #2803: Discovery of builders by entry point
|
* #2803: Discovery of builders by entry point
|
||||||
* #1764, #1676: Allow setting 'rel' and 'title' attributes for stylesheets
|
* #1764, #1676: Allow setting 'rel' and 'title' attributes for stylesheets
|
||||||
* #3589: Support remote images
|
* #3589: Support remote images on non-HTML builders
|
||||||
|
* #3589: Support images in Data URI on non-HTML builders
|
||||||
|
|
||||||
Bugs fixed
|
Bugs fixed
|
||||||
----------
|
----------
|
||||||
|
@ -227,7 +227,6 @@ General configuration
|
|||||||
* app.add_generic_role
|
* app.add_generic_role
|
||||||
* app.add_source_parser
|
* app.add_source_parser
|
||||||
* download.not_readable
|
* download.not_readable
|
||||||
* image.data_uri
|
|
||||||
* image.not_readable
|
* image.not_readable
|
||||||
* ref.term
|
* ref.term
|
||||||
* ref.ref
|
* ref.ref
|
||||||
|
@ -65,6 +65,7 @@ class Builder(object):
|
|||||||
#: Image files are searched in the order in which they appear here.
|
#: Image files are searched in the order in which they appear here.
|
||||||
supported_image_types = [] # type: List[unicode]
|
supported_image_types = [] # type: List[unicode]
|
||||||
supported_remote_images = True
|
supported_remote_images = True
|
||||||
|
supported_data_uri_images = False
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
# type: (Sphinx) -> None
|
# type: (Sphinx) -> None
|
||||||
|
@ -103,6 +103,7 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
html_scaled_image_link = True
|
html_scaled_image_link = True
|
||||||
supported_image_types = ['image/svg+xml', 'image/png',
|
supported_image_types = ['image/svg+xml', 'image/png',
|
||||||
'image/gif', 'image/jpeg']
|
'image/gif', 'image/jpeg']
|
||||||
|
supported_data_uri_images = True
|
||||||
searchindex_filename = 'searchindex.js'
|
searchindex_filename = 'searchindex.js'
|
||||||
add_permalinks = True
|
add_permalinks = True
|
||||||
allow_sharp_as_current_path = True
|
allow_sharp_as_current_path = True
|
||||||
|
@ -59,8 +59,6 @@ class ImageCollector(EnvironmentCollector):
|
|||||||
node['candidates'] = candidates
|
node['candidates'] = candidates
|
||||||
imguri = node['uri']
|
imguri = node['uri']
|
||||||
if imguri.startswith('data:'):
|
if imguri.startswith('data:'):
|
||||||
logger.warning('image data URI found. some builders might not support',
|
|
||||||
location=node, type='image', subtype='data_uri')
|
|
||||||
candidates['?'] = imguri
|
candidates['?'] = imguri
|
||||||
continue
|
continue
|
||||||
elif imguri.find('://') != -1:
|
elif imguri.find('://') != -1:
|
||||||
|
@ -10,13 +10,14 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
from hashlib import sha1
|
||||||
|
|
||||||
from six import text_type
|
from six import text_type
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
|
|
||||||
from sphinx.transforms import SphinxTransform
|
from sphinx.transforms import SphinxTransform
|
||||||
from sphinx.util import logging, requests
|
from sphinx.util import logging, requests
|
||||||
from sphinx.util.images import guess_mimetype
|
from sphinx.util.images import guess_mimetype, get_image_extension, parse_data_uri
|
||||||
from sphinx.util.osutil import ensuredir
|
from sphinx.util.osutil import ensuredir
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
@ -43,6 +44,11 @@ class BaseImageConverter(SphinxTransform):
|
|||||||
# type: (nodes.Node) -> None
|
# type: (nodes.Node) -> None
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
def imagedir(self):
|
||||||
|
# type: () -> unicode
|
||||||
|
return os.path.join(self.app.doctreedir, 'images')
|
||||||
|
|
||||||
|
|
||||||
class ImageDownloader(BaseImageConverter):
|
class ImageDownloader(BaseImageConverter):
|
||||||
default_priority = 100
|
default_priority = 100
|
||||||
@ -56,14 +62,13 @@ class ImageDownloader(BaseImageConverter):
|
|||||||
|
|
||||||
def handle(self, node):
|
def handle(self, node):
|
||||||
# type: (nodes.Node) -> None
|
# type: (nodes.Node) -> None
|
||||||
imgdir = os.path.join(self.app.doctreedir, 'images')
|
|
||||||
basename = os.path.basename(node['uri'])
|
basename = os.path.basename(node['uri'])
|
||||||
if '?' in basename:
|
if '?' in basename:
|
||||||
basename = basename.split('?')[0]
|
basename = basename.split('?')[0]
|
||||||
dirname = node['uri'].replace('://', '/').translate({ord("?"): u"/",
|
dirname = node['uri'].replace('://', '/').translate({ord("?"): u"/",
|
||||||
ord("&"): u"/"})
|
ord("&"): u"/"})
|
||||||
ensuredir(os.path.join(imgdir, dirname))
|
ensuredir(os.path.join(self.imagedir, dirname))
|
||||||
path = os.path.join(imgdir, dirname, basename)
|
path = os.path.join(self.imagedir, dirname, basename)
|
||||||
try:
|
try:
|
||||||
r = requests.get(node['uri'])
|
r = requests.get(node['uri'])
|
||||||
if r.status_code != 200:
|
if r.status_code != 200:
|
||||||
@ -85,9 +90,43 @@ class ImageDownloader(BaseImageConverter):
|
|||||||
(node['uri'], text_type(exc)))
|
(node['uri'], text_type(exc)))
|
||||||
|
|
||||||
|
|
||||||
|
class DataURIExtractor(BaseImageConverter):
|
||||||
|
default_priority = 150
|
||||||
|
|
||||||
|
def match(self, node):
|
||||||
|
# type: (nodes.Node) -> bool
|
||||||
|
if self.app.builder.supported_data_uri_images:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return 'data:' in node['uri']
|
||||||
|
|
||||||
|
def handle(self, node):
|
||||||
|
# type: (nodes.Node) -> None
|
||||||
|
image = parse_data_uri(node['uri'])
|
||||||
|
ext = get_image_extension(image.mimetype)
|
||||||
|
if ext is None:
|
||||||
|
logger.warning('Unknown image format: %s...', node['uri'][:32],
|
||||||
|
location=node)
|
||||||
|
return
|
||||||
|
|
||||||
|
ensuredir(os.path.join(self.imagedir, 'embeded'))
|
||||||
|
digest = sha1(image.data).hexdigest()
|
||||||
|
path = os.path.join(self.imagedir, 'embeded', digest + ext)
|
||||||
|
self.app.env.original_image_uri[path] = node['uri']
|
||||||
|
|
||||||
|
with open(path, 'wb') as f:
|
||||||
|
f.write(image.data)
|
||||||
|
|
||||||
|
node['candidates'].pop('?')
|
||||||
|
node['candidates'][image.mimetype] = path
|
||||||
|
node['uri'] = path
|
||||||
|
self.app.env.images.add_file(self.env.docname, path)
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app):
|
||||||
# type: (Sphinx) -> Dict[unicode, Any]
|
# type: (Sphinx) -> Dict[unicode, Any]
|
||||||
app.add_post_transform(ImageDownloader)
|
app.add_post_transform(ImageDownloader)
|
||||||
|
app.add_post_transform(DataURIExtractor)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'version': 'builtin',
|
'version': 'builtin',
|
||||||
|
Loading…
Reference in New Issue
Block a user