mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Add image format handling.
This commit is contained in:
parent
66b5f39bc7
commit
b05861454c
3
CHANGES
3
CHANGES
@ -38,6 +38,9 @@ New features added
|
||||
- The directories in the `html_static_path` can now contain
|
||||
subdirectories.
|
||||
|
||||
* The image directive now supports specifying the extension as ``.*``,
|
||||
which makes the builder select the one that matches best.
|
||||
|
||||
* The new config value `exclude_trees` can be used to exclude whole
|
||||
subtrees from the search for source files.
|
||||
|
||||
|
9
TODO
9
TODO
@ -13,12 +13,3 @@ Sphinx
|
||||
- "often used" combo box in sidebar
|
||||
- source file cross-references?
|
||||
|
||||
Web App
|
||||
*******
|
||||
|
||||
- fix /download
|
||||
|
||||
- discuss and debug comments system
|
||||
- prepare for databases other than sqlite for comments
|
||||
- add search via Xapian or Nucular (Python indexer - nucular.sf.net)
|
||||
- optionally have a contents tree view in the sidebar (AJAX based)?
|
||||
|
25
doc/rest.rst
25
doc/rest.rst
@ -72,7 +72,7 @@ or roman numerals, such as ::
|
||||
|
||||
A. First item
|
||||
B. Second item
|
||||
|
||||
|
||||
|
||||
Nested lists are possible, but be aware that they must be separated from the
|
||||
parent list items by blank lines::
|
||||
@ -214,12 +214,27 @@ Images
|
||||
|
||||
reST supports an image directive, used like so::
|
||||
|
||||
.. image:: filename
|
||||
.. image:: gnu.png
|
||||
(options)
|
||||
|
||||
When used within Sphinx, the ``filename`` given must be relative to the source
|
||||
file, and Sphinx will automatically copy image files over to a subdirectory of
|
||||
the output directory on building.
|
||||
When used within Sphinx, the file name given (here ``gnu.png``) must be relative
|
||||
to the source file, and Sphinx will automatically copy image files over to a
|
||||
subdirectory of the output directory on building (e.g. the ``_static`` directory
|
||||
for HTML output.)
|
||||
|
||||
Sphinx extends the standard docutils behavior by allowing an asterisk for the
|
||||
extension::
|
||||
|
||||
.. image:: gnu.*
|
||||
|
||||
Sphinx then searches for all images matching the provided pattern and determines
|
||||
their type. Each builder then chooses the best image out of these candidates.
|
||||
For instance, if the file name ``gnu.*`` was given and two files :file:`gnu.pdf`
|
||||
and :file:`gnu.png` existed in the source tree, the LaTeX builder would choose
|
||||
the former, while the HTML builder would prefer the latter.
|
||||
|
||||
.. versionchanged:: 0.4
|
||||
Added the support for file names ending in an asterisk.
|
||||
|
||||
|
||||
Footnotes
|
||||
|
@ -62,6 +62,9 @@ class Builder(object):
|
||||
self.info = app.info
|
||||
self.config = app.config
|
||||
|
||||
# images that need to be copied over (source -> dest)
|
||||
self.images = {}
|
||||
|
||||
# if None, this is set in load_env()
|
||||
self.env = env
|
||||
self.freshenv = freshenv
|
||||
@ -118,6 +121,28 @@ class Builder(object):
|
||||
if l == 0:
|
||||
self.info()
|
||||
|
||||
supported_image_types = []
|
||||
|
||||
def post_process_images(self, doctree):
|
||||
"""
|
||||
Pick the best candidate for all image URIs.
|
||||
"""
|
||||
for node in doctree.traverse(nodes.image):
|
||||
uri = node['candidates'].get('*', None)
|
||||
if not uri:
|
||||
for imgtype in self.supported_image_types:
|
||||
uri = node['candidates'].get(imgtype, None)
|
||||
if uri:
|
||||
node['uri'] = uri
|
||||
break
|
||||
else:
|
||||
self.warn('%s:%s: %s' %
|
||||
(node.source, node.lineno,
|
||||
'No matching candidate for uri: %(uri)s' % node))
|
||||
continue
|
||||
if uri in self.env.images:
|
||||
self.images[uri] = self.env.images[uri][1]
|
||||
|
||||
# build methods
|
||||
|
||||
def load_env(self):
|
||||
@ -271,6 +296,8 @@ class StandaloneHTMLBuilder(Builder):
|
||||
copysource = True
|
||||
out_suffix = '.html'
|
||||
indexer_format = 'json'
|
||||
supported_image_types = ['image/svg+xml', 'image/png', 'image/gif',
|
||||
'image/jpeg']
|
||||
|
||||
def init(self):
|
||||
"""Load templates."""
|
||||
@ -323,7 +350,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
|
||||
favicon = self.config.html_favicon and \
|
||||
path.basename(self.config.html_favicon) or ''
|
||||
if os.path.splitext(favicon)[1] != '.ico':
|
||||
if favicon and os.path.splitext(favicon)[1] != '.ico':
|
||||
self.warn('html_favicon is not an .ico file')
|
||||
|
||||
if not isinstance(self.config.html_use_opensearch, basestring):
|
||||
@ -407,6 +434,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
)
|
||||
|
||||
def write_doc(self, docname, doctree):
|
||||
self.post_process_images(doctree)
|
||||
destination = StringOutput(encoding='utf-8')
|
||||
doctree.settings = self.docsettings
|
||||
|
||||
@ -504,10 +532,10 @@ class StandaloneHTMLBuilder(Builder):
|
||||
self.info()
|
||||
|
||||
# copy image files
|
||||
if self.env.images:
|
||||
if self.images:
|
||||
self.info(bold('copying images...'), nonl=1)
|
||||
ensuredir(path.join(self.outdir, '_images'))
|
||||
for src, (_, dest) in self.env.images.iteritems():
|
||||
for src, dest in self.images.iteritems():
|
||||
self.info(' '+src, nonl=1)
|
||||
shutil.copyfile(path.join(self.srcdir, src),
|
||||
path.join(self.outdir, '_images', dest))
|
||||
@ -636,6 +664,8 @@ class PickleHTMLBuilder(StandaloneHTMLBuilder):
|
||||
name = 'pickle'
|
||||
out_suffix = '.fpickle'
|
||||
indexer_format = 'pickle'
|
||||
supported_image_types = ('image/svg+xml', 'image/png', 'image/gif',
|
||||
'image/jpeg')
|
||||
|
||||
def init(self):
|
||||
self.init_translator_class()
|
||||
@ -711,6 +741,7 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
|
||||
|
||||
# don't copy the reST source
|
||||
copysource = False
|
||||
supported_image_types = ['image/png', 'image/gif', 'image/jpeg']
|
||||
|
||||
def init(self):
|
||||
StandaloneHTMLBuilder.init(self)
|
||||
@ -726,6 +757,8 @@ class LaTeXBuilder(Builder):
|
||||
Builds LaTeX output to create PDF.
|
||||
"""
|
||||
name = 'latex'
|
||||
supported_image_types = ['application/pdf', 'image/png', 'image/gif',
|
||||
'image/jpeg']
|
||||
|
||||
def init(self):
|
||||
self.docnames = []
|
||||
@ -787,6 +820,7 @@ class LaTeXBuilder(Builder):
|
||||
self.info("processing " + targetname + "... ", nonl=1)
|
||||
doctree = self.assemble_doctree(docname, toctree_only,
|
||||
appendices=(docclass == 'manual') and appendices or [])
|
||||
self.post_process_images(doctree)
|
||||
self.info("writing... ", nonl=1)
|
||||
doctree.settings = docsettings
|
||||
doctree.settings.author = author
|
||||
@ -852,9 +886,9 @@ class LaTeXBuilder(Builder):
|
||||
|
||||
def finish(self):
|
||||
# copy image files
|
||||
if self.env.images:
|
||||
if self.images:
|
||||
self.info(bold('copying images...'), nonl=1)
|
||||
for src, (_, dest) in self.env.images.iteritems():
|
||||
for src, dest in self.images.iteritems():
|
||||
self.info(' '+src, nonl=1)
|
||||
shutil.copyfile(path.join(self.srcdir, src),
|
||||
path.join(self.outdir, dest))
|
||||
|
@ -14,9 +14,11 @@ import os
|
||||
import time
|
||||
import heapq
|
||||
import types
|
||||
import imghdr
|
||||
import difflib
|
||||
import cPickle as pickle
|
||||
from os import path
|
||||
from glob import glob
|
||||
from string import uppercase
|
||||
from itertools import izip, groupby
|
||||
try:
|
||||
@ -511,25 +513,43 @@ class BuildEnvironment:
|
||||
existing_names = set(v[1] for v in self.images.itervalues())
|
||||
docdir = path.dirname(self.doc2path(docname, base=None))
|
||||
for node in doctree.traverse(nodes.image):
|
||||
# Map the mimetype to the corresponding image. The writer may
|
||||
# choose the best image from these candidates. The special key * is
|
||||
# set if there is only single candiate to be used by a writer.
|
||||
node['candidates'] = candidates = {}
|
||||
imguri = node['uri']
|
||||
if imguri.find('://') != -1:
|
||||
self.warn(docname, 'Nonlocal image URI found: %s' % imguri, node.line)
|
||||
candidates['*'] = imguri
|
||||
continue
|
||||
imgpath = path.normpath(path.join(docdir, imguri))
|
||||
if imgpath.endswith(os.extsep + '*'):
|
||||
for filename in glob(imgpath):
|
||||
basename, ext = os.path.splitext(filename)
|
||||
if ext == '.pdf':
|
||||
candidates['application/pdf'] = filename
|
||||
elif ext == '.svg':
|
||||
candidates['image/svg+xml'] = filename
|
||||
else:
|
||||
imgtype = imghdr.what(filename)
|
||||
if imgtype:
|
||||
candidates['image/' + imgtype] = filename
|
||||
else:
|
||||
imgpath = path.normpath(path.join(docdir, imguri))
|
||||
node['uri'] = imgpath
|
||||
self.dependencies.setdefault(docname, set()).add(imgpath)
|
||||
if not os.access(path.join(self.srcdir, imgpath), os.R_OK):
|
||||
self.warn(docname, 'Image file not readable: %s' % imguri, node.line)
|
||||
if imgpath in self.images:
|
||||
self.images[imgpath][0].add(docname)
|
||||
candidates['*'] = imgpath
|
||||
for img in candidates.itervalues():
|
||||
self.dependencies.setdefault(docname, set()).add(img)
|
||||
if not os.access(path.join(self.srcdir, img), os.R_OK):
|
||||
self.warn(docname, 'Image file not readable: %s' % img, node.line)
|
||||
if img in self.images:
|
||||
self.images[img][0].add(docname)
|
||||
continue
|
||||
uniquename = path.basename(imgpath)
|
||||
uniquename = path.basename(img)
|
||||
base, ext = path.splitext(uniquename)
|
||||
i = 0
|
||||
while uniquename in existing_names:
|
||||
i += 1
|
||||
uniquename = '%s%s%s' % (base, i, ext)
|
||||
self.images[imgpath] = (set([docname]), uniquename)
|
||||
self.images[img] = (set([docname]), uniquename)
|
||||
existing_names.add(uniquename)
|
||||
|
||||
def process_metadata(self, docname, doctree):
|
||||
|
@ -250,9 +250,9 @@ class HTMLTranslator(BaseTranslator):
|
||||
def visit_image(self, node):
|
||||
olduri = node['uri']
|
||||
# rewrite the URI if the environment knows about it
|
||||
if olduri in self.builder.env.images:
|
||||
if olduri in self.builder.images:
|
||||
node['uri'] = posixpath.join(self.builder.imgpath,
|
||||
self.builder.env.images[olduri][1])
|
||||
self.builder.images[olduri])
|
||||
BaseTranslator.visit_image(self, node)
|
||||
|
||||
def visit_toctree(self, node):
|
||||
|
@ -630,8 +630,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
pre.append('\n')
|
||||
post.append('\n')
|
||||
pre.reverse()
|
||||
if node['uri'] in self.builder.env.images:
|
||||
uri = self.builder.env.images[node['uri']][1]
|
||||
if node['uri'] in self.builder.images:
|
||||
uri = self.builder.images[node['uri']]
|
||||
else:
|
||||
uri = node['uri']
|
||||
if uri.find('://') != -1:
|
||||
|
Loading…
Reference in New Issue
Block a user