1 # -*- coding: utf-8 -*-
6 Allow embeded ASCII art to be rendered as nice looking images
7 using the aafigure reStructuredText extension.
9 See the README file for details.
11 :copyright: Copyright 2009 by Leandro Lucarella <llucax@gmail.com> \
12 (based on sphinxcontrib.mscgen).
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 metadata_fname = '%s.aafig' % fname
78 if hasattr(self.builder, 'imgpath'):
80 relfn = posixpath.join(self.builder.imgpath, fname)
81 outfn = path.join(self.builder.outdir, '_images', fname)
85 outfn = path.join(self.builder.outdir, fname)
87 if path.isfile(outfn):
89 if options['format'].lower() == 'svg':
90 f = file(metadata_fname, 'r')
93 return relfn, outfn, id, extra
95 ensuredir(path.dirname(outfn))
97 # merge default options
98 for (k, v) in self.builder.config.aafig_default_options.items():
103 (visitor, output) = aafigure.render(text, outfn, options)
105 except aafigure.UnsupportedFormatError, e:
106 raise MscgenError(str(e))
109 if options['format'].lower() == 'svg':
110 extra = visitor.get_size_attrs()
111 f = file(metadata_fname, 'w')
115 return relfn, outfn, id, extra
118 def render_html(self, node, text, options, prefix=DEFAULT_PREFIX, imgcls=None):
120 options['format'] = self.builder.config.aafig_format['html']
121 fname, outfn, id, extra = render_aafigure(self, text, options, prefix)
122 except AafigError, exc:
123 self.builder.warn('aafigure error: ' + str(exc))
126 self.body.append(self.starttag(node, 'p', CLASS='aafigure'))
128 self.body.append(self.encode(text))
130 imgcss = imgcls and 'class="%s"' % imgcls or ''
131 if options['format'].lower() == 'svg':
132 self.body.append('<object type="image/svg+xml" data="%s" %s %s />'
133 (fname, extra, imgcss))
135 self.body.append('<img src="%s" alt="%s" %s/>\n' %
136 (fname, self.encode(text).strip(), imgcss))
137 self.body.append('</p>\n')
141 def html_visit(self, node):
142 render_html(self, node, node['text'], node['options'])
145 def render_latex(self, node, text, options, prefix=DEFAULT_PREFIX):
147 options['format'] = self.builder.config.aafig_format['latex']
148 fname, outfn, id, extra = render_aafigure(self, text, options, prefix)
149 except AafigError, exc:
150 self.builder.warn('aafigure error: ' + str(exc))
153 if fname is not None:
154 self.body.append('\\includegraphics[]{%s}' % fname)
158 def latex_visit(self, node):
159 render_latex(self, node, node['text'], node['options'])
163 app.add_node(aafig, html=(html_visit, None), latex=(latex_visit, None))
164 app.add_directive('aafig', Aafig)
165 app.add_config_value('aafig_format', dict(html='svg', latex='pdf'), 'html')
166 app.add_config_value('aafig_default_options', dict(), 'html')