1 # -*- coding: utf-8 -*-
6 Allow mscgen-formatted :abbr:`MSC (Message Sequence Chart)` graphs to be
7 included in Sphinx-generated documents inline.
9 See the README file for details.
11 :copyright: Copyright 2009 by Leandro Lucarella (based on \
13 :license: BSD, see LICENSE for details.
19 from hashlib import sha1 as sha
23 from docutils import nodes
24 from docutils.parsers.rst import directives
26 from sphinx.errors import SphinxError
27 from sphinx.util import ensuredir
28 from sphinx.util.compat import Directive
32 DEFAULT_PREFIX = 'aafig'
34 class AafigError(SphinxError):
35 category = 'aafig error'
38 class aafig(nodes.General, nodes.Element):
42 class Aafig(Directive):
44 Directive to insert an ASCII art figure to be rendered by aafigure.
47 required_arguments = 0
48 optional_arguments = 0
49 final_argument_whitespace = False
57 textual = directives.flag,
58 proportional = directives.flag,
63 node['text'] = '\n'.join(self.content)
64 if 'textual' in self.options: self.options['textual'] = True
65 if 'proportional' in self.options: self.options['proportional'] = True
66 node['options'] = self.options
70 def render_aafigure(self, text, options, prefix):
72 Render an ASCII art figure into the requested format output file.
74 hashkey = text.encode('utf-8') + str(options)
75 id = sha(hashkey).hexdigest()
76 fname = '%s-%s.%s' % (prefix, id, options['format'])
77 if hasattr(self.builder, 'imgpath'):
79 relfn = posixpath.join(self.builder.imgpath, fname)
80 outfn = path.join(self.builder.outdir, '_images', fname)
84 outfn = path.join(self.builder.outdir, fname)
86 if path.isfile(outfn):
87 return relfn, outfn, id
89 ensuredir(path.dirname(outfn))
92 aafigure.render(text, outfn, options)
93 except aafigure.UnsupportedFormatError, e:
94 raise MscgenError(str(e))
96 return relfn, outfn, id
99 def render_html(self, node, text, options, prefix=DEFAULT_PREFIX, imgcls=None):
101 options['format'] = self.builder.config.aafig_format['html']
102 fname, outfn, id = render_aafigure(self, text, options, prefix)
103 except AafigError, exc:
104 self.builder.warn('aafigure error: ' + str(exc))
107 self.body.append(self.starttag(node, 'p', CLASS='aafigure'))
109 self.body.append(self.encode(text))
111 imgcss = imgcls and 'class="%s"' % imgcls or ''
112 # nothing in image map
113 self.body.append('<img src="%s" alt="%s" %s/>\n' %
114 (fname, self.encode(text).strip(), imgcss))
115 self.body.append('</p>\n')
119 def html_visit(self, node):
120 render_html(self, node, node['text'], node['options'])
123 def render_latex(self, node, text, options, prefix=DEFAULT_PREFIX):
125 options['format'] = self.builder.config.aafig_format['latex']
126 fname, outfn, id = render_aafigure(self, text, options, prefix)
127 except AafigError, exc:
128 self.builder.warn('aafigure error: ' + str(exc))
131 if fname is not None:
132 self.body.append('\\includegraphics[]{%s}' % fname)
136 def latex_visit(self, node):
137 render_latex(self, node, node['text'], node['options'])
140 app.add_node(aafig, html=(html_visit, None), latex=(latex_visit, None))
141 app.add_directive('aafig', Aafig)
142 app.add_config_value('aafig_format', dict(html='svg', latex='pdf'), 'html')