Blosxoms, Bryars and Blikis
by Simon Cozens
|
Pages: 1, 2
Everything's a Wiki
So much for blogs, for the time being. The other movement in social software at the moment is Ward Cunningham's wiki. A wiki has three important characteristics: a simple mark-up language, the ability for the viewer to modify the page, and the ability to create links from one wiki page to another.
Despite initial predictions that they'd be unusable due to widespread graffiti, vandalism, and other kinds of kicking down the sandcastle, wikis have turned out to work quite well in practice, with sites like Wikipedia collecting a great store of information from contributors both regular and occasional.
CPAN has a fair collection of wiki implementations, including
Kwiki, CGI::Wiki,
Apache::MiniWiki,
and others. However, there may well be times when it makes sense
to create a new implementation, particularly when the wiki is to
be embedded in another application.
What does it mean to embed a wiki? An example will demonstrate it best. Imagine a web-mail system like IMP or SquirrelMail. Now we want to add the ability to write a short note or annotation on a given message, so that it can be referred back to later. If I get a mail from my friend Al arranging to meet up for a drink at the pub, I'd want to annotate the mail with Al's mobile phone number, directions to the pub, and the fact that I need to take the book that I borrowed from him last month. Then, in an ideal world, the mail system would collect all the notes, work out the date and time of the meeting, and tell my calendaring software about it, but that's another story for a different time.
The fact is that once we have these sticky notes for mail, we
might want to use them to refer to other mail, group them
together in fluid topics, and so on. For instance, if I
mentioned in the annotation that this was an
AlMeeting, I would expect that text to be magically
marked up as a link to all the other AlMeeting
mails. Here we've got the three elements of a wiki -- annotation
editing, a simple markup language, and the ability to link.
While the editing is a simple matter of linking your CGI
parameters with your database, something that should be second
nature to those who want to avoid
writing code, the other two components take a little bit of
work. Thankfully, chromatic has written a handy module, Text::WikiFormat.
With WikiFormat, you can pass a text string marked
up in wiki format to Text::WikiFormat::format, and
it will return you HTML:
print Text::WikiFormat::format(<<EOF);
= A Test Post =
I found this '''very''' interesting WikiLink recently.
EOF
__DATA__
<h1>A Test Post</h1>
<p> <br />
I found this <strong>very</strong> interesting
<a href="WikiLink">WikiLink</a> recently. <br />
</p>
This gives us the simple markup, but it doesn't do much about
the linkability; for an embedded wiki, we're going to need finer-grained control over how the links are constructed. For
instance, we might want to pass the link name to a particular
URL with a particular CGI parameter. Thankfully,
Text::WikiFormat supports two optional parameters
in addition to the text to be formatted: the first is a hash
reference overriding how the wiki text is marked up to HTML, and
the second is a hash reference of options, such as the URL
prefix for links.
So, if we have an application that displays a page given a parameter in the URL, we can just say:
Text::WikiFormat::format($text, {},
{ prefix => "http://www.myhost.int/wiki?page=" });
And there we have it, an instant wiki.
Of course, in the context of our webmail application, we may
have to do something more convoluted. For instance, we might
want a link to SimonCozens to resolve to all mail
from that person, if it can be understood as a person who sends
email, or to a similarly marked-up set of messages, like an
AlMeeting, if it can't. For this, we need to
introduce a bit of logic and decide how to form the link.
As we mentioned above, Text::WikiFormat allows us
to specify replacements for the way markup is translated to
HTML. WikiFormat uses a hash-ref internally to turn
wiki "tags" into HTML, and we can, in fact, put in a subroutine
reference for the link tag and have that emit the
appropriate HTML link.
sub markup {
my $text = shift;
Text::WikiFormat::format(shift, { link => \&my_link });
}
sub my_link {
my $linkname = shift;
my $name = $linkname;
($name=$linkname) =~ s/(?<=[a-z])(?=[A-Z])/ /g;
if (have_mail_from($name)) {
# Valid correspondent, link to page of their mail
my $id = correspondent_id($name);
return qq{<A HREF="/mail/search?correspondent=$id">}.$name.
"</A>";
}
# Not a correspondent, just a wiki page
return qq{<A HREF="/wiki?$linkname">}.$linkname.
"</A>";
}
What's going on here? First, we receive the link name in
StudlyCaps every time format sees a link. We then
convert it to a real name, by inserting a space in the gaps
between a lowercase character and an uppercase one. Now we have
a name like "Simon Cozens" that we can search our mailstore for,
and if we find someone, we can return the URL to a page about
their mail. Otherwise, we return a wiki page. We've used our
webmail annotations to refer to either real people or to other
annotations, stealthily embedding a wiki in the application, with
minimal effort.
Creating the Bliki
With that example of how to create a custom wiki from an existing application, let's return to Bryar and our blogging software.
The concept of a bliki -- a cross between a wiki and a blog -- may seem like a bizarre one at first, but it's such a natural synergy that it's been independently invented by multiple people, including Martin Fowler and many others.
Depending on how you look at it, a bliki is either an ordinary wiki with a blog-style front-end showing the latest posts, or an ordinary blog with wiki-like markup and interconnections between the posts. The only difference between these views is how easy it is to edit the posts. We'll stick with the "ordinary blog" viewpoint, since editing posts over the Web is a boring and solved problem, and one not really related to the technology we're looking at today.
How are we going to extend Bryar to become a bliki? It's obvious
that Text::WikiFormat is going to be involved
somewhere, and it would be helpful to use the
Bryar::DataSource::FlatFile class too. First, we
inherit from the FlatFile class, and override the
make_document method, which is responsible for
turning a filename into a Bryar::Document:
package Bryar::DataSource::FlatFile::Bliki;
use base 'Bryar::DataSource::FlatFile';
use strict;
use Text::WikiFormat;
sub make_document {
my ($self, $filename) = @_;
}
Here the format will be slightly different -- the filename (such
as "MyWikiPost.txt") will be used to form both the
title and the ID of the document, and the content of the
document will be transformed via WikiFormatter
wholesale.
sub make_document {
my ($self, $file) = @_;
return unless $file and open my $in, $file;
my $when = (stat $file)[9];
my $who = getpwuid((stat $file)[4]);
$file =~ s/\.txt$//;
my $dir = dirname($file);
$dir =~ s{^\./?}{};
my $category = $dir || "main";
local $/;
my $text = <$in>;
return Bryar::Document->new(
title => $file,
content => Text::WikiFormat::format($text, {}, {prefix => "id_"}),
epoch => $when,
author => $who,
id => $file,
category => $category,
);
}
We change the prefix for links to be a relative link of the form
id_PostName, since this is how Bryar deals with
references to other blog posts, by default. (Of course, we could
change this by modifying the FrontEnd class, but this seems to
work fine.)
It took 30 lines of code to convert Bryar into a simple bliki, many of which were stolen from the superclass. Now let's look at something a bit different.
Everything's a Blog
I mentioned when introducing Bryar that it was based on the Model-View-Controller (MVC) pattern, although I didn't realize this while designing it.
The MVC pattern is described in this entry in Ward Cunningham's own wiki, as being made up of three parts:
- A model, therefore is an object representing data or even activity, e.g. a database table or even some plant-floor production-machine process.
- A view is some form of visualization of the state of the model.
- A controller offers facilities to change the state of the model.
All kinds of things follow the MVC design. In Bryar, the model is the data source object; the view is the templating object; the controller is the Collector object. A web browser might be described as a controller that contains all its logic, a view which contains the user interface, and the pane of rendered HTML, and the model of the entire Worldwide Web.
But some web-based applications follow Bryar's MVC approach particularly closely. Imagine, for instance, a company's product catalog on the Web. The catalog data will be stored in some kind of database, and will be presented via a templating system, with a controller that will decide which products to show. Isn't that exactly the same as reading some blog posts from a database (albeit potentially one that looks a lot like a filesystem), rendering them via templating system, with a controller deciding which posts to show?
Indeed, many of the views you will want of the catalog data are exactly what you'd want from a blog: display the most recent products, display all products, search by product name or description, and a detailed display of a single product.
We've seen it take 30 lines to turn a blog into a bliki. To
turn a blog into a complete product catalog web site takes a
subclass of the Bryar::DataSource::DBI class (to
talk to the product database) and the
Bryar::Document class (to take more details, a URL
to a photo, and so on). The rest is a matter of templating, and
that's a designer's job!
Social Software
I consider the emergence of interest in social software to be one of the most fascinating trends in software engineering this year. Two of the most powerful and popular aspects of this, wikis and blogs, are particularly well-suited for extension and embedding, and Perl is a particularly well-suited language for achieving this.
Although part of the point of this article was to demonstrate Bryar, there were several other important points. First, that there are plenty of Perl implementations of both wikis and blogs that you can choose from; second, that Perl makes it really easy to create your own blog or wiki and customize to your own purposes, including embedding them in an existing application.
But finally, the point was to encourage you to think about good design and the power of extensible applications; if you can create a tool that is both powerful and generalizable -- just like Perl itself -- it may end up doing wildly different things to what you initially intended!

