Usage:
<graph border=1 align=center>
graph test123 {
a -- b -- c;
a -- {x y};
x -- c [w=10.0];
x -- y [w=5.0,len=3];
}
</graph>
will be subsituted with a rendered version of this graph at run-time.
Note that there are lots of things which need improving about this patch: in particular, the graph should be rendered once and stored (either in the DB object or the HtmlCache) until it changes!
Another fix required: client-side image maps are generated (graph nodes labelled with URL="http://foo") but these should also allow URL="WikiName"
--- wiki.pl.orig Sun Apr 22 01:44:10 2001
+++ wiki.pl Fri Feb 14 12:44:22 2003
@@ -386,6 +386,9 @@
} elsif ($action eq 'history') {
&DoHistory($id) if &ValidIdOrDie($id);
return 1;
+ } elsif ($action eq 'graph') {
+ &DoGraph($id, &GetParam('name', ''));
+ return 1;
}
return 0; # Request not handled
}
@@ -460,7 +463,7 @@
&OpenKeptRevisions('text_default') if (!$openKept);
$fullHtml .= &GetDiffHTML($showDiff, $id, $diffRevision, $newText);
}
- $fullHtml .= &WikiToHTML($Text{'text'});
+ $fullHtml .= &WikiToHTML($Text{'text'}, $id);
$fullHtml .= "<hr>\n" if (!&GetParam('embed', $EmbedWiki));
if (($id eq $RCName) || (T($RCName) eq $id) || (T($id) eq $RCName)) {
print $fullHtml;
@@ -773,6 +776,24 @@
return $html;
}
+# FIXME: Use the HtmlCache for storing the image; or should we define
+# a section 'graph_<name>' and store the graph there?
+sub DoGraph {
+ my ($id, $name) = @_;
+ my $fullPage = $q->header(-type=>'image/png');
+ &OpenPage($id);
+ &OpenDefaultText();
+ my $tmp = $Text{'text'};
+ while ($tmp =~ s#<graph([^>]*)>((.|\n)*?)</graph>##i) {
+ my ($opt, $data) = ($1, $2);
+ if ($data =~ /\s*\S+\s*(\S+)/ && $1 eq $name) {
+ $fullPage .= RunDot($data, "-Tpng");
+ last;
+ }
+ }
+ print $fullPage;
+}
+
# ==== HTML and page-oriented functions ====
sub ScriptLink {
my ($action, $text) = @_;
@@ -1151,7 +1172,7 @@
# ==== Common wiki markup ====
sub WikiToHTML {
- my ($pageText) = @_;
+ my ($pageText, $id) = @_;
%SaveUrl = ();
%SaveNumUrl = ();
@@ -1163,7 +1184,7 @@
}
$pageText = &QuoteHtml($pageText);
$pageText =~ s/\\ *\r?\n/ /g; # Join lines with backslash at end
- $pageText = &CommonMarkup($pageText, 1, 0); # Multi-line markup
+ $pageText = &CommonMarkup($pageText, 1, 0, $id); # Multi-line markup
$pageText = &WikiLinesToHtml($pageText); # Line-oriented markup
$pageText =~ s/$FS(\d+)$FS/$SaveUrl{$1}/ge; # Restore saved text
$pageText =~ s/$FS(\d+)$FS/$SaveUrl{$1}/ge; # Restore nested saved text
@@ -1171,7 +1192,7 @@
}
sub CommonMarkup {
- my ($text, $useImage, $doLines) = @_;
+ my ($text, $useImage, $doLines, $id) = @_;
local $_ = $text;
if ($doLines < 2) { # 2 = do line-oriented only
@@ -1180,6 +1201,8 @@
# The <pre> tag wraps the stored text with the HTML <pre> tag
s/\<pre\>((.|\n)*?)\<\/pre\>/&StorePre($1, "pre")/ige;
s/\<code\>((.|\n)*?)\<\/code\>/&StorePre($1, "code")/ige;
+ # The <graph> tag wraps a call to dot/neato
+ s/\<graph([^\&]*)\>((.|\n)*?)\<\/graph\>/&StoreGraph($2, $1, $id)/ige;
if ($HtmlTags) {
my ($t);
foreach $t (@HtmlPairs) {
@@ -1381,6 +1404,54 @@
return $FS . $SaveUrlIndex++ . $FS;
}
+# FIXME: replace this with open2() and fork() to avoid the temporary file?
+sub RunDot {
+ my $src = shift;
+ my $cmd;
+ $cmd = "/usr/local/bin/dot" if $src =~ /^\s*digraph/;
+ $cmd = "/usr/local/bin/neato" if $src =~ /^\s*graph/;
+ return "[unknown graph type]" unless $cmd;
+ open F, "|$cmd @_ >/tmp/graphviz.$$ 2>/dev/null";
+ print F $src;
+ close F;
+ if (0) { # FIXME: how to detect an error reliably?
+ unlink "/tmp/graphviz.$$";
+ return "[@_ $? $!]";
+ }
+ open F, "</tmp/graphviz.$$";
+ my $result = "";
+ while (<F>) {
+ $result .= $_;
+ }
+ close F;
+ unlink "/tmp/graphviz.$$";
+ return $result;
+}
+
+sub StoreGraph {
+ my ($src, $opt, $id) = @_;
+ $src =~ s/\</</g;
+ $src =~ s/\>/>/g;
+ $src =~ s/\&/\&/g;
+ $opt = " border=0 align=center" unless $opt;
+ my $name;
+ return StoreRaw("<p>[Unable to find graph name]</p>")
+ unless $src =~ /\s*\S+\s*(\S+)/;
+ $name = $1;
+ my $out = RunDot($src, "-Tcmap");
+ return StoreRaw("<p>$out</p>")
+ if $out =~ /^\[/; # error indication
+ return StoreRaw("<div$opt><img src=\"$ScriptName?action=graph&id=$id&name=$name\" border=0></div>")
+ unless $out ne '';
+ return StoreRaw(<<END);
+<div$opt>
+<img src="$ScriptName?action=graph&id=$id&name=$name"$opt usemap="#$name">
+<map name="$name">
+$out</map>
+</div>
+END
+}
+
sub StorePre {
my ($html, $tag) = @_;
@@ -2632,7 +2703,7 @@
}
$MainPage = $id;
$MainPage =~ s|/.*||; # Only the main page name (remove subpage)
- print &WikiToHTML($oldText) . "<hr>\n";
+ print &WikiToHTML($oldText, $id) . "<hr>\n";
print "<h2>", T('Preview only, not yet saved'), "</h2>\n";
}
print &GetHistoryLink($id, T('View other revisions')) . "<br>\n";
yes
Im not administrator, Succeeded install graphviz package to my "home account directory", but i can't sure to use "/tmp" directory. how can I do it? Can I get some proto-type source to debug? -- anonymous
I don't think this gives Wiki:VisualTour type functionality. It does implement pretty cool graph markup though. Are there any WikiPatches that generate digraph source for WikiLinks?
Unfortunately, I couldn't get this to work under Windows 98. How do you get perl and piping to work?