a6275aeed84d06b35729b840575cdd1bb943cc90
[ikiwiki.git] / doc / plugins / contrib / mscgen.mdwn
1 [[!tag type/widget]]
2
3 This plugin provides the msc [[ikiwiki/directive]].
4 This directive allows embedding [mscgen](http://www.mcternan.me.uk/mscgen/)
5 message sequence chart graphs in a page.
6
7 Here's an mscgen source example.
8
9     \[[!msc src="""
10       arcgradient = 8;
11
12       a [label="Client"],b [label="Server"];
13
14       a=>b [label="data1"];
15       a-xb [label="data2"];
16       a=>b [label="data3"];
17       a<=b [label="ack1, nack2"];
18       a=>b [label="data2", arcskip="1"];
19       |||;
20       a<=b [label="ack3"];
21       |||;
22     """]]
23
24 And here's the resulting graph.
25
26 [[!msc src=<<"""
27   arcgradient = 8;
28
29   a [label="Client"],b [label="Server"];
30
31   a=>b [label="data1"];
32   a-xb [label="data2"];
33   a=>b [label="data3"];
34   a<=b [label="ack1, nack2"];
35   a=>b [label="data2", arcskip="1"];
36   |||;
37   a<=b [label="ack3"];
38   |||;
39 """]]
40
41 Security implications: to be determined.
42
43 This plugin uses the [[!cpan Digest::SHA]] perl module.
44
45 This plugin borrows heavily from the [[graphviz|plugins/graphviz]] plugin written by [[JoshTriplett]].
46
47 I couldn't upload an attachment, so here's the plugin source.
48
49 [[!format perl """
50 #!/usr/bin/perl
51 # mscgen plugin for ikiwiki: render mscgen source as an image.
52 # Terry Golubiewski
53 # Derived from graphviz plugin by Josh Triplett.
54 package IkiWiki::Plugin::mscgen;
55
56 use warnings;
57 use strict;
58 use IkiWiki 3.00;
59 use IPC::Open2;
60
61 sub import {
62         hook(type => "getsetup", id => "mscgen", call => \&getsetup);
63         hook(type => "preprocess", id => "msc", call => \&graph);
64 }
65
66 sub getsetup () {
67         return
68                 plugin => {
69                         safe => 1,
70                         rebuild => undef,
71                         section => "widget",
72                 },
73 }
74
75 sub render_graph (\%) {
76         my %params = %{(shift)};
77
78         my $src = "msc {\n";
79         $src .= $params{src};
80         $src .= "\n}\n";
81
82         # Use the sha1 of the mscgen code as part of its filename.
83         eval q{use Digest::SHA};
84         error($@) if $@;
85         my $dest=$params{page}."/msc-".
86                 IkiWiki::possibly_foolish_untaint(Digest::SHA::sha1_hex($src)).
87                 ".png";
88         will_render($params{page}, $dest);
89
90         if (! -e "$config{destdir}/$dest") {
91                 my $pid;
92                 my $sigpipe=0;
93                 $SIG{PIPE}=sub { $sigpipe=1 };
94                 $pid=open2(*IN, *OUT, 'mscgen', '-Tpng', '-i-', '-o-');
95
96                 # open2 doesn't respect "use open ':utf8'"
97                 binmode (OUT, ':utf8');
98
99                 print OUT $src;
100                 close OUT;
101
102                 my $png;
103                 {
104                         local $/ = undef;
105                         $png = <IN>;
106                 }
107                 close IN;
108
109                 waitpid $pid, 0;
110                 $SIG{PIPE}="DEFAULT";
111                 error gettext("failed to run mscgen") if $sigpipe;
112
113                 if (! $params{preview}) {
114                         writefile($dest, $config{destdir}, $png, 1);
115                 }
116                 else {
117                         # in preview mode, embed the image in a data uri
118                         # to avoid temp file clutter
119                         eval q{use MIME::Base64};
120                         error($@) if $@;
121                         return "<img src=\"data:image/png;base64,".
122                                 encode_base64($png)."\" />";
123                 }
124         }
125
126         return "<img src=\"".urlto($dest, $params{destpage})."\" />\n";
127 }
128
129 sub graph (@) {
130         my %params=@_;
131         $params{src} = "" unless defined $params{src};
132         return render_graph(%params);
133 }
134
135 1
136 """]]