Skip to content

Instantly share code, notes, and snippets.

@esle
Created February 20, 2012 06:08
Show Gist options
  • Save esle/1868078 to your computer and use it in GitHub Desktop.
Save esle/1868078 to your computer and use it in GitHub Desktop.
dot directive for reStructuredText, with this you can write ..dot:: things
"""
dot directive (require graphviz)
"""
from docutils import nodes
from docutils.parsers.rst import directives, Directive
import subprocess as sp
nthUnnamed = 0
class Dot(Directive):
required_arguments = 0
optional_arguments = 1
has_content = True
final_argument_whitespace = True
'''dot image generator'''
def run(self):
self.assert_has_content()
global nthUnnamed
try:
filename = self.arguments[0]
except:
filename = ('dot%d.png' % nthUnnamed)
nthUnnamed += 1
content = '\n'.join(self.content)
filetype = filename[filename.rfind('.')+1:]
args = ['dot', '-o'+filename, '-T'+filetype]
dot = sp.Popen(args, 0, None, sp.PIPE)
dot.stdin.write( content )
dot.stdin.close()
ret = dot.wait()
if ret:
return [nodes.error('some error occured')]
else:
return [nodes.raw('', '<img src="%s" alt="%s"/>'%(filename, filename), format='html')]
@simon-gunacker
Copy link

Nice work. Any idea how I can make this run for pdf files?

@gbuzogany
Copy link

gbuzogany commented Jan 14, 2019

For python3 (so you can use with OmniMarkup for example):

"""
dot directive (require graphviz)
"""

import base64
from docutils import nodes
from docutils.parsers.rst import directives, Directive

import subprocess as sp

nthUnnamed = 0
class Dot(Directive):
    required_arguments = 0
    optional_arguments = 1
    has_content = True
    final_argument_whitespace = True

    '''dot image generator'''
    def run(self):
        self.assert_has_content()
        global nthUnnamed
        try:
            filename = self.arguments[0]
        except:
            filename = ('dot%d.png' % nthUnnamed)
            nthUnnamed += 1
        content = '\n'.join(self.content)

        return self.render(content, filename)

    def render(self, content, filename):
        filetype = filename[filename.rfind('.')+1:]
        args = ['dot', '-T'+filetype]
        html = None

        dot = sp.Popen(args, stdin=sp.PIPE, stderr=sp.PIPE,stdout=sp.PIPE)
        output = dot.communicate( content.encode('utf-8'))

        encoded = base64.b64encode(output[0]).decode('utf-8')

        html = '<img src="data:image/%s;base64,%s" >' % (filetype, encoded)

        if html:
                return [nodes.raw('', html, format='html')]
        else:
                return [nodes.raw('', '<p>Error : ' + err + '</p><pre>' + content + '</pre>', format='html')]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment