[Home]WikiPatches/GraphViz

UseModWiki | WikiPatches | RecentChanges | Preferences

Feature inspired by Wiki:MiniRubyWiki. Install the software from http://www.graphviz.org/ for this to work.

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";

is it like Wiki:VisualTour ? - anonymous

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?


UseModWiki | WikiPatches | RecentChanges | Preferences
Edit text of this page | View other revisions | Search MetaWiki
Last edited May 22, 2009 1:51 pm by Juanmamp (diff)
Search: