Georg Brandl avatar Georg Brandl committed 484082c Merge

merge with trunk

Comments (0)

Files changed (14)

 
 Other contributors, listed alphabetically, are:
 
+* Henrique Bastos -- SVG support for graphviz extension
 * Daniel Bültmann -- todo extension
 * Michael Droettboom -- inheritance_diagram extension
 * Charles Duffy -- original graphviz extension
 
 * Added Epub builder.
 
+* #309: The ``graphviz`` extension can now output SVG instead of PNG
+  images, controlled by the ``graphviz_output_format`` config value.
+
 * #284: All docinfo metadata is now put into the document metadata, not
   just the author.
 
 Release 0.6.4 (in development)
 ==============================
 
+* The ``alt`` text of inheritance diagrams is now much cleaner.
+
+* Ignore images in section titles when generating link captions.
+
 * #310: support exception messages in the ``testoutput`` blocks of
   the ``doctest`` extension.
 
 
 check:
 	@$(PYTHON) utils/check_sources.py -i build -i dist -i sphinx/style/jquery.js \
-		-i sphinx/pycode/pgen2 -i sphinx/util/smartypants.py \
+		-i sphinx/pycode/pgen2 -i sphinx/util/smartypants.py -i .ropeproject \
 		-i doc/_build -i ez_setup.py -i tests/path.py -i tests/coverage.py -i env .
 
 clean: clean-pyc clean-patchfiles

doc/ext/extlinks.rst

    You can also use the usual "explicit title" syntax supported by other roles
    that generate links, i.e. ``:issue:`this issue <123>```.  In this case, the
    *prefix* is not relevant.
+
+.. note::
+
+   Since links are generated from the role in the reading stage, they appear as
+   ordinary links to e.g. the ``linkcheck`` builder.

doc/ext/graphviz.rst

             "bar" -> "baz";
          }
 
-   In HTML output, the code will be rendered to a PNG image.  In LaTeX output,
-   the code will be rendered to an embeddable PDF file.
+   In HTML output, the code will be rendered to a PNG or SVG image (see
+   :confval:`graphviz_output_format`).  In LaTeX output, the code will be
+   rendered to an embeddable PDF file.
 
 
 .. directive:: graph
    Additional command-line arguments to give to dot, as a list.  The default is
    an empty list.  This is the right place to set global graph, node or edge
    attributes via dot's ``-G``, ``-N`` and ``-E`` options.
+
+.. confval:: graphviz_output_format
+
+   The output format for Graphviz when building HTML files.  This must be either
+   ``'png'`` or ``'svg'``; the default is ``'png'``.
+
+   .. versionadded:: 1.0
+      Previously, output always was PNG.
   on the right side.  There are currently no options beyond *nosidebar*.
 
 * **scrolls** -- A more lightweight theme, based on `the Jinja documentation
-  <http://jinja.pocoo.org/documentation/2>`_.  The following color options are
+  <http://jinja.pocoo.org/2/documentation/>`_.  The following color options are
   available:
 
   - **headerbordercolor**

sphinx/builders/html.py

                 else:
                     stripped = ''
 
+                # we stripped the whole module name
+                if not mn:
+                    continue
+
                 if fl != mn[0].lower() and mn[0] != '_':
                     # heading
                     letter = mn[0].upper()

sphinx/builders/linkcheck.py

             lineno = node.line
 
         if uri[0:5] == 'http:' or uri[0:6] == 'https:':
+            if lineno:
+                self.info('(line %3d) ' % lineno, nonl=1)
             self.info(uri, nonl=1)
 
             if uri in self.broken:

sphinx/environment.py

 
 from sphinx import addnodes
 from sphinx.util import movefile, get_matching_docs, SEP, ustrftime, \
-     docname_join, FilenameUniqDict, url_re, make_refnode
+     docname_join, FilenameUniqDict, url_re, make_refnode, clean_astext
 from sphinx.errors import SphinxError, ExtensionError
 
 
                           node.line)
             self.anonlabels[name] = docname, labelid
             if node.tagname == 'section':
-                sectname = node[0].astext() # node[0] == title node
+                sectname = clean_astext(node[0]) # node[0] == title node
             elif node.tagname == 'figure':
                 for n in node:
                     if n.tagname == 'caption':
-                        sectname = n.astext()
+                        sectname = clean_astext(n)
                         break
                 else:
                     continue
                         # toctree originates
                         ref = toctreenode['parent']
                         if not title:
-                            title = self.titles[ref].astext()
+                            title = clean_astext(self.titles[ref])
                         reference = nodes.reference('', '',
                                                     refuri=ref,
                                                     anchorname='',
                             # reference with explicit title
                             caption = node.astext()
                         else:
-                            caption = self.titles[docname].astext()
+                            caption = clean_astext(self.titles[docname])
                         innernode = nodes.emphasis(caption, caption)
                         newnode = nodes.reference('', '')
                         newnode['refuri'] = builder.get_relative_uri(

sphinx/ext/graphviz.py

 import re
 import posixpath
 from os import path
+from math import ceil
 from subprocess import Popen, PIPE
 try:
     from hashlib import sha1 as sha
 
 
 mapname_re = re.compile(r'<map id="(.*?)"')
+svg_dim_re = re.compile(r'<svg\swidth="(\d+)pt"\sheight="(\d+)pt"', re.M)
 
 
 class GraphvizError(SphinxError):
     return relfn, outfn
 
 
-def render_dot_html(self, node, code, options, prefix='graphviz', imgcls=None):
+def get_svg_tag(svgref, svgfile, imgcls=None):
+    # Webkit can't figure out svg dimensions when using object tag
+    # so we need to get it from the svg file
+    fp = open(svgfile, 'r')
     try:
-        fname, outfn = render_dot(self, code, options, 'png', prefix)
+        for line in fp:
+            match = svg_dim_re.match(line)
+            if match:
+                dimensions = match.groups()
+                break
+        else:
+            dimensions = None
+    finally:
+        fp.close()
+
+    # We need this hack to make WebKit show our object tag properly
+    def pt2px(x):
+        return int(ceil((96.0/72.0) * float(x)))
+
+    if dimensions:
+        style = ' width="%s" height="%s"' % tuple(map(pt2px, dimensions))
+    else:
+        style = ''
+
+    # The object tag works fine on Firefox and WebKit
+    # Besides it's a hack, this strategy does not mess with templates.
+    imgcss = imgcls and ' class="%s"' % imgcls or ''
+    return '<object type="image/svg+xml" data="%s"%s%s/>\n' % \
+           (svgref, imgcss, style)
+
+
+def render_dot_html(self, node, code, options, prefix='graphviz',
+                    imgcls=None, alt=None):
+    format = self.builder.config.graphviz_output_format
+    try:
+        if format not in ('png', 'svg'):
+            raise GraphvizError("graphviz_output_format must be one of 'png', "
+                                "'svg', but is %r" % format)
+        fname, outfn = render_dot(self, code, options, format, prefix)
     except GraphvizError, exc:
         self.builder.warn('dot code %r: ' % code + str(exc))
         raise nodes.SkipNode
     if fname is None:
         self.body.append(self.encode(code))
     else:
-        mapfile = open(outfn + '.map', 'rb')
-        try:
-            imgmap = mapfile.readlines()
-        finally:
-            mapfile.close()
-        imgcss = imgcls and 'class="%s"' % imgcls or ''
-        if len(imgmap) == 2:
-            # nothing in image map (the lines are <map> and </map>)
-            self.body.append('<img src="%s" alt="%s" %s/>\n' %
-                             (fname, self.encode(code).strip(), imgcss))
+        if alt is None:
+            alt = self.encode(code).strip()
+        if format == 'svg':
+            svgtag = get_svg_tag(fname, outfn, imgcls)
+            self.body.append(svgtag)
         else:
-            # has a map: get the name of the map and connect the parts
-            mapname = mapname_re.match(imgmap[0]).group(1)
-            self.body.append('<img src="%s" alt="%s" usemap="#%s" %s/>\n' %
-                             (fname, self.encode(code).strip(),
-                              mapname, imgcss))
-            self.body.extend(imgmap)
+            mapfile = open(outfn + '.map', 'rb')
+            try:
+                imgmap = mapfile.readlines()
+            finally:
+                mapfile.close()
+            imgcss = imgcls and 'class="%s"' % imgcls or ''
+            if len(imgmap) == 2:
+                # nothing in image map (the lines are <map> and </map>)
+                self.body.append('<img src="%s" alt="%s" %s/>\n' %
+                                 (fname, alt, imgcss))
+            else:
+                # has a map: get the name of the map and connect the parts
+                mapname = mapname_re.match(imgmap[0]).group(1)
+                self.body.append('<img src="%s" alt="%s" usemap="#%s" %s/>\n' %
+                                 (fname, alt, mapname, imgcss))
+                self.body.extend(imgmap)
+
     self.body.append('</p>\n')
     raise nodes.SkipNode
 
     app.add_directive('digraph', GraphvizSimple)
     app.add_config_value('graphviz_dot', 'dot', 'html')
     app.add_config_value('graphviz_dot_args', [], 'html')
+    app.add_config_value('graphviz_output_format', 'png', 'html')

sphinx/ext/inheritance_diagram.py

         node['graph'] = graph
         # Store the original content for use as a hash
         node['parts'] = self.options.get('parts', 0)
-        node['content'] = ' '.join(class_names)
+        node['content'] = ', '.join(class_names)
         return [node]
 
 
             urls[child['reftitle']] = '#' + child.get('refid')
 
     dotcode = graph.generate_dot(name, parts, urls, env=self.builder.env)
-    render_dot_html(self, node, dotcode, [], 'inheritance', 'inheritance')
+    render_dot_html(self, node, dotcode, [], 'inheritance', 'inheritance',
+                    alt='Inheritance diagram of ' + node['content'])
     raise nodes.SkipNode
 
 

sphinx/themes/default/static/default.css_t

 th {
     background-color: #ede;
 }
+
+.warning tt {
+    background: #efc2c2;
+}
+
+.note tt {
+    background: #d6d6d6;
+}

sphinx/util/__init__.py

         shutil.copytree(source, target)
 
 
+def clean_astext(node):
+    """Like node.astext(), but ignore images."""
+    node = node.deepcopy()
+    for img in node.traverse(docutils.nodes.image):
+        img['alt'] = ''
+    return node.astext()
+
 
 def split_explicit_title(text):
     """Split role content into title and target, if given."""

utils/check_sources.py

 
 
 name_mail_re = r'[\w ]+(<.*?>)?'
-copyright_re = re.compile(r'^    :copyright: Copyright 200\d(-200\d)? '
+copyright_re = re.compile(r'^    :copyright: Copyright 200\d(-20\d\d)? '
                           r'by %s(, %s)*[,.]$' %
                           (name_mail_re, name_mail_re))
 license_re = re.compile(r"    :license: (.*?).\n")
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.