mldblog: Plug-In
02010-Nov-14, Sun 11:00 in /mldblog [mldblog] [permalink]
This is part of a series of posts documenting the code of mldblog.

How are plug-ins located?

mldblog scans for plug-ins by enumerating all files in $DIR_PLUGINS with the extension .pm.
.pm was chosen to allow automatic syntax highlighting in editors that base that functionality on a file's extension.
The load-order of plug-ins is undefined.

What can plug-ins do?

A plug-in exports a number of functions that are called by mldblog during its execution. Basically it's a module that is handled in an object orientated way. So each function's first parameter is $self. However, because every plug-in is loaded and instantiated only once, there is no need to write a plug-in that way. But don't forget that the first parameter of each function is $self.


new() is called immediately after the plug-in was loaded. At the very least it should contain
return bless({}, $_[0]);
But as mentioned before, there is never more than one instance of a plug-in, hence there is no need to use that blessed hash-reference to store plug-in specific data. Instead variables in file-scope can be used. This way you can forget about all those $self->... you'd have to use otherwise. Being lazy is actually allowed!

post_header($self, \@entries)

This function is called right after the headers of all entries have been read.
The parameter \@entries contains all hash-references generated by read_header(). Its structure can be seen here. post_header() can be used to parse plug-in specific header fields like X-PLUGIN-KEY ($e->{header}->{'x-plugin-key'}).

The plug-in specific data that shall be accessible by the templates can be stored in two different locations. The entry-specific data has to be stored in $e->{X}->{PLUGIN}, while the global data has to be located in $mldblog::G->{X}->{PLUGIN}. This nesting is required to avoid name-clashes between plug-ins and mldblog.

filter_pre_sort($self, \@IN, \@OUT) & filter_post_sort($self, \@IN, \@OUT)

Those functions are called right before and after the sorting of the array of entries. With this functions entries can be dropped that do not match a specific search criteria before the sort (e.g. cats plug-in) or can be limited to some number of entries after the sort (e.g. pages plug-in).
The function has to add all entries that it wants to keep to \@OUT and return 1. If no filtering is required the return value has to evaluate to FALSE (0, '', undef) and no copying of the elements from \@IN to \@OUT has to be performed.

render($self, $type, \%entry_hash)

render() is called multiple times:
  1. Once before any rendering of header, entry or footer has happened. In this case \%entry_hash is undef. This function call can be used to inject global data into mldblog::G.
  2. For each entry right before render_template('entry.$type', \%entry_hash) is called. Before the call to render() however, three keys are added to the entry's hash:
      article, # contains the article of the entry
      moddate_string, # moddate as string via render_date("date.$type", $moddate)
      header = {
        date_string # date as string via render_date("date.$type", $date)
No comments
New comments disabled