116 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			116 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Python
		
	
	
	
| # XXX this file is messy since it tries to deal with several docutils versions
 | |
| import py
 | |
| 
 | |
| from py.__.rest.convert import convert_dot, latexformula2png
 | |
| 
 | |
| import sys
 | |
| import docutils
 | |
| from docutils import nodes
 | |
| from docutils.parsers.rst import directives, states, roles
 | |
| from docutils.parsers.rst.directives import images
 | |
| 
 | |
| if hasattr(images, "image"):
 | |
|     directives_are_functions = True
 | |
| else:
 | |
|     directives_are_functions = False
 | |
| 
 | |
| try:
 | |
|     from docutils.utils import unescape # docutils version > 0.3.5
 | |
| except ImportError:
 | |
|     from docutils.parsers.rst.states import unescape # docutils 0.3.5
 | |
| 
 | |
| if not directives_are_functions:
 | |
|     ImageClass = images.Image
 | |
| 
 | |
| else:
 | |
|     class ImageClass(object):
 | |
|         option_spec = images.image.options
 | |
|         def run(self):
 | |
|             return images.image('image',
 | |
|                                 self.arguments,
 | |
|                                 self.options,
 | |
|                                 self.content,
 | |
|                                 self.lineno,
 | |
|                                 self.content_offset,
 | |
|                                 self.block_text,
 | |
|                                 self.state,
 | |
|                                 self.state_machine)
 | |
| 
 | |
| 
 | |
| backend_to_image_format = {"html": "png", "latex": "pdf"}
 | |
| 
 | |
| class GraphvizDirective(ImageClass):
 | |
|     def convert(self, fn, path):
 | |
|         path = py.path.local(path).dirpath()
 | |
|         dot = path.join(fn)
 | |
|         result = convert_dot(dot, backend_to_image_format[_backend])
 | |
|         return result.relto(path)
 | |
| 
 | |
|     def run(self):
 | |
|         newname = self.convert(self.arguments[0],
 | |
|                                self.state.document.settings._source)
 | |
|         text = self.block_text.replace("graphviz", "image", 1)
 | |
|         self.block_text = text.replace(self.arguments[0], newname, 1)
 | |
|         self.name = 'image'
 | |
|         self.arguments = [newname]
 | |
|         return ImageClass.run(self)
 | |
|     
 | |
|     def old_interface(self):
 | |
|         def f(name, arguments, options, content, lineno,
 | |
|               content_offset, block_text, state, state_machine):
 | |
|             for arg in "name arguments options content lineno " \
 | |
|                        "content_offset block_text state state_machine".split():
 | |
|                 setattr(self, arg, locals()[arg])
 | |
|             return self.run()
 | |
|         f.arguments = (1, 0, 1)
 | |
|         f.options = self.option_spec
 | |
|         return f
 | |
| 
 | |
| 
 | |
| _backend = None
 | |
| def set_backend_and_register_directives(backend):
 | |
|     #XXX this is only used to work around the inflexibility of docutils:
 | |
|     # a directive does not know the target format
 | |
|     global _backend
 | |
|     _backend = backend
 | |
|     if not directives_are_functions:
 | |
|         directives.register_directive("graphviz", GraphvizDirective)
 | |
|     else:
 | |
|         directives.register_directive("graphviz",
 | |
|                                       GraphvizDirective().old_interface())
 | |
|     roles.register_canonical_role("latexformula", latexformula_role)
 | |
| 
 | |
| def latexformula_role(name, rawtext, text, lineno, inliner,
 | |
|                       options={}, content=[]):
 | |
|     if _backend == 'latex':
 | |
|         options['format'] = 'latex'
 | |
|         return roles.raw_role(name, rawtext, text, lineno, inliner,
 | |
|                               options, content)
 | |
|     else:
 | |
|         # XXX: make the place of the image directory configurable
 | |
|         sourcedir = py.path.local(inliner.document.settings._source).dirpath()
 | |
|         imagedir = sourcedir.join("img")
 | |
|         if not imagedir.check():
 | |
|             imagedir.mkdir()
 | |
|         # create halfway senseful imagename:
 | |
|         # use hash of formula + alphanumeric characters of it
 | |
|         # could
 | |
|         imagename = "%s_%s.png" % (
 | |
|             hash(text), "".join([c for c in text if c.isalnum()]))
 | |
|         image = imagedir.join(imagename)
 | |
|         latexformula2png(unescape(text, True), image)
 | |
|         imagenode = nodes.image(image.relto(sourcedir), uri=image.relto(sourcedir))
 | |
|         return [imagenode], []
 | |
| latexformula_role.content = True
 | |
| latexformula_role.options = {}
 | |
| 
 | |
| def register_linkrole(role_name, callback):
 | |
|     def source_role(name, rawtext, text, lineno, inliner, options={},
 | |
|                     content=[]):
 | |
|         text, target = callback(name, text)
 | |
|         reference_node = nodes.reference(rawtext, text, name=text, refuri=target)
 | |
|         return [reference_node], []
 | |
|     source_role.content = True
 | |
|     source_role.options = {}
 | |
|     roles.register_canonical_role(role_name, source_role)
 |