* Add a linkmap plugin (requires graphviz).
authorjoey <joey@0fa5a96a-9a0e-0410-b3b2-a0fd24251071>
Thu, 7 Sep 2006 05:31:01 +0000 (05:31 +0000)
committerjoey <joey@0fa5a96a-9a0e-0410-b3b2-a0fd24251071>
Thu, 7 Sep 2006 05:31:01 +0000 (05:31 +0000)
IkiWiki/Plugin/linkmap.pm [new file with mode: 0644]
debian/changelog
doc/bugs/rss_feed_cleanup_on_delete.mdwn
doc/ikiwiki.setup
doc/plugins/linkmap.mdwn [new file with mode: 0644]
doc/todo/link_map.mdwn
doc/todo/plugin.mdwn

diff --git a/IkiWiki/Plugin/linkmap.pm b/IkiWiki/Plugin/linkmap.pm
new file mode 100644 (file)
index 0000000..356306e
--- /dev/null
@@ -0,0 +1,106 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::linkmap;
+
+use warnings;
+use strict;
+use IkiWiki;
+use IPC::Open2;
+
+sub import { #{{{
+       IkiWiki::hook(type => "preprocess", id => "linkmap",
+               call => \&preprocess);
+       IkiWiki::hook(type => "format", id => "linkmap",
+               call => \&format);
+} # }}}
+
+my $mapnum=0;
+my %maps;
+
+sub preprocess (@) { #{{{
+       my %params=@_;
+       $params{pages}="*" unless defined $params{pages};
+       
+       # Needs to update whenever a page is added or removed, so
+       # register a dependency.
+       IkiWiki::add_depends($params{page}, $params{pages});
+       
+       # Can't just return the linkmap here, since the htmlscrubber
+       # scrubs out all <object> tags (with good reason!)
+       # Instead, insert a placeholder tag, which will be expanded during
+       # formatting.
+       $mapnum++;
+       $maps{$mapnum}=\%params;
+       return "<div class=\"linkmap$mapnum\"></div>";
+} # }}}
+
+sub format (@) { #{{{
+        my %params=@_;
+
+       $params{content}=~s/<div class=\"linkmap(\d+)"><\/div>/genmap($1)/eg;
+
+        return $params{content};
+} # }}}
+
+sub genmap ($) { #{{{
+       my $mapnum=shift;
+       return "" unless exists $maps{$mapnum};
+       my %params=%{$maps{$mapnum}};
+
+       # Get all the items to map.
+       my %mapitems = ();
+       foreach my $item (keys %IkiWiki::links) {
+               if (IkiWiki::pagespec_match($item, $params{pages})) {
+                       my $link=IkiWiki::htmlpage($item);
+                       $link=IkiWiki::abs2rel($link, IkiWiki::dirname($params{page}));
+                       $mapitems{$item}=$link;
+               }
+       }
+
+       # Use ikiwiki's function to create the file, this makes sure needed
+       # subdirs are there and does some sanity checking.
+       IkiWiki::writefile("$params{page}.png", $IkiWiki::config{destdir}, "");
+
+       # Run dot to create the graphic and get the map data.
+       # TODO: should really add the png to renderedfiles and call
+       # check_overwrite, but currently renderedfiles
+       # only supports listing one file per page.
+       my $tries=10;
+       my $pid;
+       while (1) {
+               eval {
+                       $pid=open2(*IN, *OUT, "dot /dev/stdin -Tpng -o '$IkiWiki::config{destdir}/$params{page}.png' -Tcmapx");
+               };
+               last unless $@;
+               $tries--;
+               if ($tries < 1) {
+                       return "failed to run dot: $@";
+               }
+       }
+       # open2 doesn't respect "use open ':utf8'"
+       binmode (IN, ':utf8'); 
+       binmode (OUT, ':utf8'); 
+
+       print OUT "digraph linkmap$mapnum {\n";
+       print OUT "concentrate=true;\n";
+       foreach my $item (keys %mapitems) {
+               print OUT "\"$item\" [shape=box,href=\"$mapitems{$item}\"];\n";
+               foreach my $link (map { IkiWiki::bestlink($item, $_) } @{$IkiWiki::links{$item}}) {
+                       print OUT "\"$item\" -> \"$link\";\n"
+                               if $mapitems{$link};
+               }
+       }
+       print OUT "}\n";
+       close OUT;
+
+       local $/=undef;
+       my $ret="<object data=\"".
+               IkiWiki::abs2rel("$params{page}.png", IkiWiki::dirname($params{page})).
+               "\" type=\"image/png\" usemap=\"#linkmap$mapnum\">\n".
+                <IN>.
+                "</object>";
+       close IN;
+       waitpid $pid, 0;
+       return $ret;
+} #}}}
+
+1
index 3e7c3e0825883782c070f20932f88e757194e9d1..0a761c9ec9185f41924e12f4ea372e45b355e99d 100644 (file)
@@ -8,8 +8,9 @@ ikiwiki (1.25) UNRELEASED; urgency=low
   * Add support for mercurial, contributed by Emanuele Aina.
   * Include <link rel> tag for RSS feeds, used by some aggregators and
     firefox to find the feed.
+  * Add a linkmap plugin (requires graphviz).
 
- -- Joey Hess <joeyh@debian.org>  Wed,  6 Sep 2006 16:42:21 -0400
+ -- Joey Hess <joeyh@debian.org>  Thu,  7 Sep 2006 00:11:18 -0400
 
 ikiwiki (1.24) unstable; urgency=low
 
index 5fe2bcd550477fb4c083fb2925f498fc34f5f84e..32cdba0ccc0b91b28049250e453aa3e5e6582ae7 100644 (file)
@@ -1,2 +1,4 @@
 If a page stops inlining anthing, its rss feed file will linger around and
 not be deleted.
+
+(The linkmap plugin has the same problem with the png files it creates.)
index ac84352df3e51f47f7e7128e8f0b18c784248d1d..ab5c9eb35fb581971591d07cade902defe3badca 100644 (file)
@@ -93,7 +93,7 @@ use IkiWiki::Setup::Standard {
        # To add plugins, list them here.
        #add_plugins => [qw{meta tag pagecount brokenlinks search smiley
        #                   wikitext camelcase pagestats htmltidy fortune
-       #                   sidebar map rst toc}],
+       #                   sidebar map rst toc linkmap}],
        # If you want to disable any of the default plugins, list them here.
        #disable_plugins => [qw{inline htmlscrubber}],
 }
diff --git a/doc/plugins/linkmap.mdwn b/doc/plugins/linkmap.mdwn
new file mode 100644 (file)
index 0000000..35dcf8f
--- /dev/null
@@ -0,0 +1,23 @@
+[[template id=plugin name=linkmap included=1 author="Joey Hess"]]
+[[tag type/meta]]
+[[tag type/slow]]
+the mapped pages is changed, which can make the wiki a bit slow.
+This plugin uses graphviz to generate a graph showing the links between a
+set of pages in the wiki. Example usage:
+
+       \[[linkmap pages="* and !blog/* and !*/Discussion"]]
+
+Only links between mapped pages will be shown; links pointing to or from
+unmapped pages will be omitted. If the pages to include are not specified,
+the links between all pages (and other files) in the wiki are mapped. For
+best results, only a small set of pages should be mapped, since otherwise
+the map can become very large, unweildy, and complicated. Also, the map is
+rebuilt whenever one of the mapped pages is changed, which can make the
+wiki a bit slow.
+
+This plugin is included in ikiwiki, but is not enabled by default.
+
+If this plugin is enabled, here is a link map of the index page and all
+pages it links to:
+
+[[linkmap pages="index or (backlink(index) and !*.png)"]]
index e7cb0ca2ff30a252b602c64b4c24c57dd3597da3..a02a792e48b6df6511114b061ede6422ce81e188 100644 (file)
@@ -3,4 +3,4 @@ An idea: Use graphviz to generate a map of all the links between pages.
 
 Graphviz can output image maps. -- ChristofferSawicki
 
-This could be a [[plugin]].
\ No newline at end of file
+[[todo/done]]
index ae56004774fe96c87a72238f9d0337754c917fa7..fdd37d95491c91f3e89b9e875ba90aa41c6eb9ff 100644 (file)
@@ -1,7 +1,6 @@
 Suggestions of ideas for plugins:
 
 * list of registered users - tricky because it sorta calls for a way to rebuild the page when a new user is registered. Might be better as a cgi?
-* a [[link_map]]
 * [[sigs]] ?
 
 * Support [[RecentChanges]] as a regular page containing a plugin that