<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>HOWTO Add a New Document Component to MKDoc</title>
<link rev="made" href="mailto:sam@slab.(none)" />
</head>
<body style="background-color: white">
<p><a name="__index__"></a></p>
<!-- INDEX BEGIN -->
<!--
<ul>
        <li><a href="#howto_add_a_new_document_component_to_mkdoc">HOWTO Add a New Document Component to MKDoc</a></li>
        <ul>
                <li><a href="#the_fictitious_pod_component">The Fictitious POD Component</a></li>
                <li><a href="#it_s_gotta_have_flo">It's Gotta Have Flo</a></li>
                <li><a href="#every_component_needs_an_editor">Every Component Needs an Editor</a></li>
                <li><a href="#templates_mk_the_doc_go_round">Templates MK the Doc Go Round</a></li>
                <li><a href="#another_day__another_template">Another Day, Another Template</a></li>
                <li><a href="#finally__time_to_code">Finally, Time to Code</a></li>
                <li><a href="#further_development">Further Development</a></li>
        </ul>
</ul>
-->
<!-- INDEX END -->
<p>
</p>
<h1><a name="howto_add_a_new_document_component_to_mkdoc">HOWTO Add a New Document Component to MKDoc</a></h1>
<style type="text/css">
.illus { border: 1px dotted black;
margin: 5px;
padding:3px;
}
</style><p>This HOWTO will show you how to add a new document component to MKDoc.
A document component allows editors to add content to documents and
manages the display of content to users. For example, editors use the
HTML component to add HTML to their documents and the file component
to attach files to documents.</p>
<p>
</p>
<h2><a name="the_fictitious_pod_component">The Fictitious POD Component</a></h2>
<p>For the purposes of illustration I'll walk through the process of
creating a POD component. POD stands for Plain Old Documentation;
it's a markup language which is easy to write and easy to read. I'm
writing this HOWTO in POD right now, and this section looks like:</p>
<pre>
=head2 The Fictitious POD Component</pre>
<pre>
For the purposes of illustration I'll walk through the process of
creating a POD component. POD stands for Plain Old Documentation;
it's a markup language which is easy to write and easy to read. I'm
writing this HOWTO in POD right now, and this section looks like:</pre>
<p>Of course, a POD component wouldn't really make a very good addition
to MKDoc because POD is mostly used by Perl programmers writing code
documentation. For more information about POD see:</p>
<pre>
<a href="http://www.perlpod.com/5.8.4/pod/perlpod.html">http://www.perlpod.com/5.8.4/pod/perlpod.html</a></pre>
<p>
</p>
<h2><a name="it_s_gotta_have_flo">It's Gotta Have Flo</a></h2>
<p>All the code for the MKDoc component system is contained in the
<code>flo/</code> directory inside the MKDoc root. Why <code>flo</code>? Bruno Postle
told me, ``Florence is Adam's fourth (I think) child, she is about four
years old and some of this code is even older.''</p>
<p>The <code>flo</code> system is highly object-oriented, using several layers of
inheritance to implement its functionality. All components inherit
their functionality from the <code>flo::Component</code> base-class.</p>
<p>
</p>
<h2><a name="every_component_needs_an_editor">Every Component Needs an Editor</a></h2>
<p>When you create a new MKDoc Document you'll eventually end up at the
component editor screen. Here you'll see an interface listing all the
component types available:</p>
<div class="illus"><img src="mkd_component_howto1.png"></div><p>This is actually a list of files in the <code>flo/editor</code> directory,
reformatted to be easier to read:</p>
<pre>
Discussion.pm
File.pm
Headlines.pm
Html.pm
Image.pm
Link.pm
Photo.pm
Poll.pm
Price.pm
RSS.pm
Text.pm
TimeRange.pm</pre>
<p>Each of these <code>.pm</code> files implements a sub-class of <code>flo::Component</code>
(not <code>flo::Editor</code> as you might expect, that class does something
else). These classes are responsible for managing both the editing of
data and the output of the data for visitors to the site.</p>
<p>To get started with the POD component I'll create
<code>flo/editor/POD.pm</code>. The easiest way to create a new editor is to
copy an existing editor and use that code as a base. In this case I
copied <code>flo/editor/Text.pm</code> since the POD component will be most like
Text:</p>
<pre>
$ cp flo/editor/Text.pm flo/editor/POD.pm</pre>
<p>After editing the <code>package</code> line to read:</p>
<pre>
package flo::editor::POD;</pre>
<p>and restarting Apache, the POD component is available for adding to
documents. However, actually attempting to add it to a document
results in an error. That's because every editor requires a template.</p>
<p>
</p>
<h2><a name="templates_mk_the_doc_go_round">Templates MK the Doc Go Round</a></h2>
<p>When you add a component to a document in MKDoc the next thing you see
is an interface to edit that component. In the case of Text that's an
HTML <code>textarea</code> and some buttons. This comes from a Petal template
stored in <code>templates/editor</code>.</p>
<p>Just like before I'll start by copying the template for the Text
component:</p>
<pre>
$ cp -a templates/editor/text templates/editor/pod</pre>
<p>I used <code>cp -a</code> because <code>templates/editor/text</code> is actually a
directory containing a single file, <code>en.html</code>. If the text component
is ever translated into other languages then those files will sit
alongside <code>en.html</code>.</p>
<p>To get this template ready for use I did a search-and-replace on the
copied file, changing occurrences of 'text' into 'pod'. Of course I
was careful not to translate <code>textarea</code> into <code>podarea</code>!</p>
<p>After this work the POD component is basically functional:</p>
<div class="illus"><img src="mkd_component_howto2.png"></div><p>You can enter POD into the textarea and save to the database. There
are two obvious problems at this stage. First, the editing interface
doesn't have any color. That's easily remedied by adding a class in
<code>skins/admin.css</code>:</p>
<pre>
.pod-component {
color: #000;
background-color: #9C6;
}</pre>
<p>Second, nothing is displaying outside the editing interface. Users
visiting the documents aren't seeing the POD entered in the editor.
To fix this we'll need</p>
<p>
</p>
<h2><a name="another_day__another_template">Another Day, Another Template</a></h2>
<p>Display of documents to visitors is controlled by
<code>templates/document/default/en.html</code>. It contains a list of
component types to loop through which will show up on the page. To
add the POD component to this list I changed this line:</p>
<pre>
Body_Loop self/components_list --text --html --image
--photo --file --poll --discussion --headlines
--rss;</pre>
<p>To read:</p>
<pre>
Body_Loop self/components_list --text --html --image
--photo --file --poll --discussion --headlines
--rss --pod;</pre>
<p>Now the POD text shows up on rendered pages, just like text. For
example, here's the test document I created earlier with the POD
contents ``=head1 Hello World!'' showing:</p>
<div class="illus"><img src="mkd_component_howto3.png"></div><p>
</p>
<h2><a name="finally__time_to_code">Finally, Time to Code</a></h2>
<p>Now that we've got the component working in the editor it's time to
get the output right. Instead of just showing the raw POD entered by
the editor I'd rather show the rendered output. I'll use
Pod::Simple::HTML from the Pod::Simple distribution
( <a href="http://search.cpan.org/~sburke/Pod-Simple/">http://search.cpan.org/~sburke/Pod-Simple/</a> ) to render the POD as
HTML. Thus, the first thing to do is add a <code>use</code> line to
<code>flo/editor/POD.pm</code>:</p>
<pre>
use Pod::Simple::HTML;</pre>
<p>Then all that's needed is a new <code>html()</code> method in
flo::editor::POD which uses the Pod::Simple API to create HTML from
POD:</p>
<pre>
sub html {
my $self = shift;
my $data = $self->{'data'};</pre>
<pre>
# translate POD to HTML
my $parser = Pod::Simple::HTML->new();
my $output;
$parser->output_string(\$output);
$parser->parse_string_document($data);
return $output;
}</pre>
<p>After these changes, and a quick Apache restart, the component is full
functional, turning POD formatting instructions into HTML:</p>
<div class="illus"><img src="mkd_component_howto4.png"></div><p>
</p>
<h2><a name="further_development">Further Development</a></h2>
<p>That's all it takes to get a new component up and running. However,
there's a lot more work that can be done to make components work
better. Here are a few ideas to give you an idea of what's possible:</p>
<ul>
<li></li>
The POD component should detect invalid POD and explain the problem to
the editor. The way to do this is via the <code>MKDoc::Ouch</code> API. You
can find lots of samples of <code>MKDoc::Ouch</code> usage in the more
complicated components like Headlines and TimeRange.
<p></p>
<li></li>
The help text in the POD editor interface needs work and should point
to a full introduction to POD.
<p></p>
<li></li>
Translating POD to HTML is a time-consuming process. The
flo::editor::POD object should cache the translation internally so it
can be called multiple times with no additional cost.
<p></p></ul>
<p>Of course, the possibilities don't end there. MKDoc's component
system is quite flexible. For more ideas check out the code for the
other components and their super-class, flo::Component.</p>
</body>
</html>