Bläddra i källkod

Added graphviz plugin for liquid tags

Victor Dorneanu 10 år sedan
förälder
incheckning
b9b7f25aaf
1 ändrade filer med 128 tillägg och 0 borttagningar
  1. 128 0
      liquid_tags/graphviz.py

+ 128 - 0
liquid_tags/graphviz.py

@@ -0,0 +1,128 @@
+"""
+GraphViz Tag
+---------
+This implements a Liquid-style graphviz tag for Pelican. You can use different
+Graphviz programs like dot, neato, twopi etc. [1]
+
+
+[1] http://www.graphviz.org/
+
+Syntax
+------
+{% graphviz 
+    <program> {
+        <DOT code>
+    }
+%}
+
+Examples
+--------
+{% graphviz 
+    dot {
+        digraph graphname {
+            a -> b -> c;
+            b -> d;
+        }
+    }
+%}
+
+
+{% graphviz 
+    twopi {
+        <code goes here>
+    }
+%}
+
+
+{% graphviz 
+    neato {
+        <code goes here>
+    }
+%}
+
+...
+
+
+Output
+------
+<div class="graphviz" style="align: center;"><img src="data:image/png;base64,_BASE64_IMAGE DATA_/></div>
+
+"""
+
+import base64
+import re
+from .mdx_liquid_tags import LiquidTags
+
+SYNTAX = '{% dot graphviz [program] [dot code] %}'
+DOT_BLOCK_RE = re.compile(r'^\s*(?P<program>\w+)\s*\{\s*(?P<code>.*\})\s*\}$', re.MULTILINE | re.DOTALL)
+
+
+def run_graphviz(program, code, options=[], format='png'):
+    """ Runs graphviz programs and returns image data 
+        
+        Copied from https://github.com/tkf/ipython-hierarchymagic/blob/master/hierarchymagic.py
+    """
+    import os
+    from subprocess import Popen, PIPE
+
+    dot_args = [program] + options + ['-T', format]
+
+    if os.name == 'nt':
+        # Avoid opening shell window.
+        # * https://github.com/tkf/ipython-hierarchymagic/issues/1
+        # * http://stackoverflow.com/a/2935727/727827
+        p = Popen(dot_args, stdout=PIPE, stdin=PIPE, stderr=PIPE, creationflags=0x08000000)
+    else:
+        p = Popen(dot_args, stdout=PIPE, stdin=PIPE, stderr=PIPE)
+        wentwrong = False
+
+    try:
+        # Graphviz may close standard input when an error occurs,
+        # resulting in a broken pipe on communicate()
+        stdout, stderr = p.communicate(code.encode('utf-8'))
+    except (OSError, IOError) as err:
+        if err.errno != EPIPE:
+            raise
+        wentwrong = True
+    except IOError as err:
+        if err.errno != EINVAL:
+            raise
+        wentwrong = True
+
+    if wentwrong:
+    # in this case, read the standard output and standard error streams
+    # directly, to get the error message(s)
+        stdout, stderr = p.stdout.read(), p.stderr.read()
+        p.wait()
+
+    if p.returncode != 0:
+        raise RuntimeError('dot exited with error:\n[stderr]\n{0}'.format(stderr.decode('utf-8')))
+
+    return stdout
+
+
+@LiquidTags.register('graphviz')
+def graphviz_parser(preprocessor, tag, markup):
+    """ Simple Graphviz parser """
+
+    # Parse the markup string
+    m = DOT_BLOCK_RE.search(markup)
+    if m:
+        # Get program and DOT code
+        code = m.group('code')
+        program = m.group('program').strip()
+
+        # Run specified program with our markup
+        output = run_graphviz(program, code)
+
+        # Return Base64 encoded image
+        return '<div class="graphviz" style="align: center;"><img src="data:image/png;base64,%s"></div>' % base64.b64encode(output)
+
+    else:
+        raise ValueError('Error processing input. '
+                         'Expected syntax: {0}'.format(SYNTAX))
+
+#----------------------------------------------------------------------
+# This import allows image tag to be a Pelican plugin
+from .liquid_tags import register
+