From: Vladimír Vondruš
Date: Sun, 14 Oct 2018 14:35:40 +0000 (+0200)
Subject: m.dot: compatibility with graph figures from m.components.
X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~cjwatson/git?a=commitdiff_plain;h=37d15bf4756ba30a0bed4f12f119fb99ecc1fd9a;p=blog.git
m.dot: compatibility with graph figures from m.components.
---
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'
})