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?