From 37d15bf4756ba30a0bed4f12f119fb99ecc1fd9a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 14 Oct 2018 16:35:40 +0200 Subject: [PATCH] m.dot: compatibility with graph figures from m.components. --- doc/plugins/plots-and-graphs.rst | 37 +++++++++++++ pelican-plugins/dot2svg.py | 5 +- pelican-plugins/m/dot.py | 21 +++++++- pelican-plugins/m/test/dot/page-236.html | 68 ++++++++++++++++++++++++ pelican-plugins/m/test/dot/page-238.html | 68 ++++++++++++++++++++++++ pelican-plugins/m/test/dot/page.html | 68 ++++++++++++++++++++++++ pelican-plugins/m/test/dot/page.rst | 13 +++++ pelican-plugins/m/test/test_dot.py | 6 +-- 8 files changed, 280 insertions(+), 6 deletions(-) diff --git a/doc/plugins/plots-and-graphs.rst b/doc/plugins/plots-and-graphs.rst index 3d00e267..6ee8aa9c 100644 --- a/doc/plugins/plots-and-graphs.rst +++ b/doc/plugins/plots-and-graphs.rst @@ -283,3 +283,40 @@ equivalent to :dot:`graph` and :dot:`strict graph` in the DOT language: 0 -- 1 -- 2 -- 3 -- 4 -- 0 -- 2 -- 4 --1 3 [style=filled] + +`Graph figure`_ +--------------- + +See the `m.components <{filename}/plugins/components.rst#code-math-and-graph-figure>`__ +plugin for details about graph figures using the :rst:`.. graph-figure::` +directive. + +.. code-figure:: + + .. code:: rst + + .. graph-figure:: Impenetrable logic + + .. digraph:: + + rankdir=LR + yes [shape=circle, class="m-primary", style=filled] + no [shape=circle, class="m-primary"] + yes -> no [label="no", class="m-primary"] + no -> no [label="no"] + + No. + + .. graph-figure:: Impenetrable logic + + .. digraph:: + + rankdir=LR + yes [shape=circle, class="m-primary", style=filled] + no [shape=circle, class="m-primary"] + yes -> no [label="no", class="m-primary"] + no -> no [label="no"] + + .. class:: m-noindent + + No. diff --git a/pelican-plugins/dot2svg.py b/pelican-plugins/dot2svg.py index 9ff78113..5c224bd8 100644 --- a/pelican-plugins/dot2svg.py +++ b/pelican-plugins/dot2svg.py @@ -32,7 +32,7 @@ _patch_src = re.compile(r"""<\?xml version="1\.0" encoding="UTF-8" standalone="n viewBox="(?P[^"]+)" xmlns="http://www\.w3\.org/2000/svg" xmlns:xlink="http://www\.w3\.org/1999/xlink"> +_patch_dst = r""" \n""") @@ -63,7 +63,7 @@ _font_size = 0.0 # converting to rem here def _pt2em(pt): return pt/_font_size -def dot2svg(source): +def dot2svg(source, attribs=''): try: ret = subprocess.run(['dot', '-Tsvg', '-Gfontname={}'.format(_font), @@ -84,6 +84,7 @@ def dot2svg(source): # Remove preamble and fixed size def patch_repl(match): return _patch_dst.format( + attribs=attribs, width=_pt2em(float(match.group('width'))), height=_pt2em(float(match.group('height'))), viewBox=match.group('viewBox')) diff --git a/pelican-plugins/m/dot.py b/pelican-plugins/m/dot.py index b5f8855b..85987a65 100644 --- a/pelican-plugins/m/dot.py +++ b/pelican-plugins/m/dot.py @@ -33,6 +33,17 @@ from docutils.parsers.rst.roles import set_classes import dot2svg +def _is_graph_figure(parent): + # The parent has to be a figure, marked as m-figure + if not isinstance(parent, nodes.figure): return False + if 'm-figure' not in parent.get('classes', []): return False + + # And as a first visible node of such type + for child in parent: + if not isinstance(child, nodes.Invisible): return False + + return True + class Dot(rst.Directive): has_content = True optional_arguments = 1 @@ -43,8 +54,16 @@ class Dot(rst.Directive): def run(self, source): set_classes(self.options) - svg = dot2svg.dot2svg(source) + # If this is the first real node inside a graph figure, put the SVG + # directly inside + parent = self.state.parent + if _is_graph_figure(parent): + svg = dot2svg.dot2svg(source, attribs=' class="{}"'.format(' '.join(['m-graph'] + self.options.get('classes', [])))) + node = nodes.raw('', svg, format='html') + return [node] + # Otherwise wrap it in a
+ svg = dot2svg.dot2svg(source) container = nodes.container(**self.options) container['classes'] = ['m-graph'] + container['classes'] node = nodes.raw('', svg, format='html') diff --git a/pelican-plugins/m/test/dot/page-236.html b/pelican-plugins/m/test/dot/page-236.html index 1963b629..cc067475 100644 --- a/pelican-plugins/m/test/dot/page-236.html +++ b/pelican-plugins/m/test/dot/page-236.html @@ -200,6 +200,74 @@ and the arrowheads, nothing else. Non-default font size should be preserved.

+
+ + +A to B + +a + +a + + +b + +b + + +a->b + + + + + +
This is a title.
+

This is a description.

+
+
+ + + +a + +a + + +b + +b + + +a->b + + + + + +

The graph below should not be styled as a part of the figure:

+
+ + +A to B + +a + +a + + +b + +b + + +a->b + + + + + +
+
diff --git a/pelican-plugins/m/test/dot/page-238.html b/pelican-plugins/m/test/dot/page-238.html index c0c85a9d..e8607d6d 100644 --- a/pelican-plugins/m/test/dot/page-238.html +++ b/pelican-plugins/m/test/dot/page-238.html @@ -200,6 +200,74 @@ and the arrowheads, nothing else. Non-default font size should be preserved.

+
+ + +A to B + +a + +a + + +b + +b + + +a->b + + + + + +
This is a title.
+

This is a description.

+
+
+ + + +a + +a + + +b + +b + + +a->b + + + + + +

The graph below should not be styled as a part of the figure:

+
+ + +A to B + +a + +a + + +b + +b + + +a->b + + + + + +
+
diff --git a/pelican-plugins/m/test/dot/page.html b/pelican-plugins/m/test/dot/page.html index 4c5ecc00..ff53a240 100644 --- a/pelican-plugins/m/test/dot/page.html +++ b/pelican-plugins/m/test/dot/page.html @@ -200,6 +200,74 @@ and the arrowheads, nothing else. Non-default font size should be preserved.

+
+ + +A to B + +a + +a + + +b + +b + + +a->b + + + + + +
This is a title.
+

This is a description.

+
+
+ + + +a + +a + + +b + +b + + +a->b + + + + + +

The graph below should not be styled as a part of the figure:

+
+ + +A to B + +a + +a + + +b + +b + + +a->b + + + + + +
+
diff --git a/pelican-plugins/m/test/dot/page.rst b/pelican-plugins/m/test/dot/page.rst index 87e2c7fd..c3d09d29 100644 --- a/pelican-plugins/m/test/dot/page.rst +++ b/pelican-plugins/m/test/dot/page.rst @@ -63,3 +63,16 @@ Structs: a -> b This is a description. + +.. graph-figure:: + + .. digraph:: + + a -> b + + The graph below should not be styled as a part of the figure: + + .. digraph:: A to B + :class: m-danger + + a -> b diff --git a/pelican-plugins/m/test/test_dot.py b/pelican-plugins/m/test/test_dot.py index 3a3dc7b5..13e8a89a 100644 --- a/pelican-plugins/m/test/test_dot.py +++ b/pelican-plugins/m/test/test_dot.py @@ -43,7 +43,7 @@ class Dot(PluginTestCase): "The math plugin requires at least Python 3.5 installed. Dot < 2.40.1 has a completely different output.") def test(self): self.run_pelican({ - 'PLUGINS': ['m.htmlsanity', 'm.dot'], + 'PLUGINS': ['m.htmlsanity', 'm.components', 'm.dot'], 'M_DOT_FONT': 'DejaVu Sans' }) @@ -55,7 +55,7 @@ class Dot(PluginTestCase): "The math plugin requires at least Python 3.5 installed. Dot < 2.38 and dot > 2.38 has a completely different output.") def test_238(self): self.run_pelican({ - 'PLUGINS': ['m.htmlsanity', 'm.dot'], + 'PLUGINS': ['m.htmlsanity', 'm.components', 'm.dot'], 'M_DOT_FONT': 'DejaVu Sans' }) @@ -66,7 +66,7 @@ class Dot(PluginTestCase): "The math plugin requires at least Python 3.5 installed. Dot > 2.36 has a completely different output.") def test_236(self): self.run_pelican({ - 'PLUGINS': ['m.htmlsanity', 'm.dot'], + 'PLUGINS': ['m.htmlsanity', 'm.components', 'm.dot'], 'M_DOT_FONT': 'DejaVu Sans' }) -- 2.30.2