from docutils import nodes from docutils.parsers.rst import Directive, directives from sphinx.util.docutils import SphinxDirective from shutil import which from pathlib import Path import shlex import subprocess import tempfile class D2langDirective(SphinxDirective): required_arguments = 0 has_content = True optional_arguments = 3 option_spec = { 'layout': directives.unchanged_required, 'filename': directives.unchanged_required, } def run(self): d2_bin = which('d2') srcdir = self.state.document.settings.env.srcdir diag_source = self.content if 'filename' in self.options: output_fname = self.options.get('filename') else: output_fname = 'test.svg' if 'layout' in self.options: layout = self.options.get('layout') else: layout = 'dagre' if self.arguments: path = Path(srcdir + self.arguments[0]) if path.is_file(): build_svg(self.arguments[0], srcdir, output_fname, layout) else: raise else: with tempfile.NamedTemporaryFile() as fp: for line in self.content.data: fp.write(bytes(line,'utf-8')) fp.write(bytes('\n','utf-8')) fp.seek(0) build_svg(fp.name, srcdir, output_fname, layout) image_node = nodes.image(uri=output_fname) return [image_node] def build_svg(diag_src, out_dir, filename, layout): d2_bin = which('d2') cmd_line = '%s -l %s %s %s' % (d2_bin, layout, diag_src, out_dir + "/" + filename) args = shlex.split(cmd_line) subprocess.run(args) return True