Revision: 84 Author: matt Date: 2006-08-15 22:37:33 +0000 (Tue, 15 Aug 2006)
Log Message: ----------- First serious stab at writing docs, plus a pod doc viewer. Modified Paths: -------------- trunk/TODO.txt trunk/demo/stylesheets/default.css trunk/lib/AxKit2/Config/Global.pm trunk/lib/AxKit2/Config/Location.pm trunk/lib/AxKit2/Config/Server.pm trunk/lib/AxKit2/Config.pm trunk/lib/AxKit2/HTTPHeaders.pm trunk/lib/AxKit2/Plugin.pm trunk/lib/AxKit2/Processor.pm trunk/lib/AxKit2.pm Added Paths: ----------- trunk/demo/xslt/main.xsl trunk/demo/xslt/pod.xsl trunk/lib/AxKit2/Docs/ trunk/lib/AxKit2/Docs/WritingPlugins.pod trunk/plugins/demo/doc_viewer Modified: trunk/TODO.txt =================================================================== --- trunk/TODO.txt 2006-08-14 22:38:21 UTC (rev 83) +++ trunk/TODO.txt 2006-08-15 22:37:33 UTC (rev 84) @@ -26,3 +26,5 @@ - Support HTMLDoc. - Support PassiveTeX. + +- Allow console to reload plugins Modified: trunk/demo/stylesheets/default.css =================================================================== --- trunk/demo/stylesheets/default.css 2006-08-14 22:38:21 UTC (rev 83) +++ trunk/demo/stylesheets/default.css 2006-08-15 22:37:33 UTC (rev 84) @@ -12,6 +12,7 @@ margin: 1px; } div#content { + background: white; position: relative; margin-top: 3em; margin-bottom: 6em; @@ -84,3 +85,162 @@ margin-left: auto; margin-right: auto; } +span.section-title1, +span.section-title2, +span.section-title3, +span.section-title4, +h1, h2, h3, h4, h5, h6 { + font-family: Verdana, sans-serif; + font-weight: bold; + color: navy; +} + +h1, span.section-title1 { + font-size: 26px; +} + +h2 { + font-size: 22px; + border-bottom: 1px solid silver; +} + +h3 { + font-size: 18px; + margin-top: 15px; + margin-bottom: 5px; +} + +h4 { + font-size: 14px; +} + +h5 { + font-size: 10px; +} + +hr { + color: silver; + background-color: silver; + height: 1px; + border-top: none; +} + +/* --- Body and Main Content Rules --------------------------------------- */ + +body { + background-color: #93A9D5; +} + +div, td { + font-size: 14px; + font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif; +} + +p { + margin-top: 5px; + margin-bottom: 10px; + margin-left: 5px; +} + +a:link, a:visited { + text-decoration: none; + color: blue; +} + +div.toc { + color: blue; + background-color: #eee; + border-color: black; + border-width: 2px; + border-style: solid; + margin: 1px 0px 1px 0px; + padding: 2px 0px 3px 5px; +} + +div.main-content { + background-color: white; + border-color: black; + border-width: 2px; + border-style: solid; + margin: 1px 0px 1px 0px; + padding: 2px 2px 5px 5px; +} + +div.toc-item { + font-size: 12px; + margin: 0px 0px 2px 25px; +} + +div.header { + background-color: #eee; + border-color: black; + border-width: 2px; + border-style: solid; + margin: 1px 0px 1px 0px; + padding: 0px 0px 0px 10px; + height: 40px; +} + +div.footer-nav { + background-color: #eee; + border-color: black; + border-width: 2px; + border-style: solid; + margin: 1px 0px 1px 0px; + padding: 1px; +} + +div.legal { + font-size: 12px; + color: white; + text-align: center; +} + +div.section { + padding-left: 20px; + width: 95%; +} + +div.sidemenu { + width: auto; + margin-right: 3px; +} + +div.sidemenumenu { + background: none #fff; + border: solid 2px #000; + padding-bottom: 3px; + margin-bottom: 3px; +} + +div.sidemenutitle { + background: none #eee; + border-bottom: solid 1px #000; + font-weight: bold; + padding: 3px; + margin-bottom: 2px; + font-size: 90%; +} + +div.sidemenuitem { + padding-left: 3px; + padding-right: 3px; + font-size: 90%; +} + +div.sidemenuitem img { + vertical-align: middle; +} + +pre.verbatim { + background: #DDD; + width: 90%; + margin: 0.5em -4px 0.5em; + padding: 0.5em 1em 0.25em; + border: 1px solid gray; + white-space: pre; + font: 90% monospace; +} + +a:hover { text-decoration: underline; } + Added: trunk/demo/xslt/main.xsl =================================================================== --- trunk/demo/xslt/main.xsl 2006-08-14 22:38:21 UTC (rev 83) +++ trunk/demo/xslt/main.xsl 2006-08-15 22:37:33 UTC (rev 84) @@ -0,0 +1,29 @@ +<?xml version="1.0"?> +<xsl:stylesheet + version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" +> + +<xsl:include href="pod.xsl"/> + +<xsl:output method="html"/> + +<xsl:template match="/"> + <html> + <head> + <title>AxKit Docs :: <xsl:value-of select="/xspwiki/page"/></title> + <link rel="stylesheet" href="/stylesheets/default.css"/> + </head> + + <body> + <div class="topbanner"> + AxKit Docs + </div> + <div class="main-content"> + <xsl:apply-templates/> + </div> + </body> + </html> +</xsl:template> + +</xsl:stylesheet> Added: trunk/demo/xslt/pod.xsl =================================================================== --- trunk/demo/xslt/pod.xsl 2006-08-14 22:38:21 UTC (rev 83) +++ trunk/demo/xslt/pod.xsl 2006-08-15 22:37:33 UTC (rev 84) @@ -0,0 +1,108 @@ +<?xml version="1.0"?> +<xsl:stylesheet + version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" +> + +<xsl:template match="pod"> + <xsl:apply-templates mode="pod"/> +</xsl:template> + +<xsl:template match="para" mode="pod"> + <p><xsl:apply-templates mode="pod"/></p> +</xsl:template> + +<xsl:template match="verbatim" mode="pod"> + <pre class="verbatim"><xsl:apply-templates mode="pod"/></pre> +</xsl:template> + +<xsl:template match="link" mode="pod"> + <xsl:choose> + <xsl:when test='string-length(@section) and not( string-length(@page) )'> + <xsl:choose> + <xsl:when test='starts-with(@section, "/")'> + <a href="/[EMAIL PROTECTED]"><xsl:apply-templates mode="pod"/></a> + </xsl:when> + <xsl:otherwise> + <a href="#{translate(@section,' ','-')}"><xsl:apply-templates mode="pod"/></a> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise> + <a href="./[EMAIL PROTECTED](@section,' ','-')}"><xsl:apply-templates mode="pod"/></a> + </xsl:otherwise> + </xsl:choose> +</xsl:template> + +<xsl:template match="xlink" mode="pod"> + <a href="[EMAIL PROTECTED]"><xsl:apply-templates mode="pod"/></a><img src="/img/out.png"/> +</xsl:template> + +<xsl:template match="head1" mode="pod"> + <h1><a name="{translate(.,' ','-')}"><xsl:apply-templates mode="pod"/></a></h1> +</xsl:template> + +<xsl:template match="head2" mode="pod"> + <h2><a name="{translate(.,' ','-')}"><xsl:apply-templates mode="pod"/></a></h2> +</xsl:template> + +<xsl:template match="head3" mode="pod"> + <h3><a name="{translate(.,' ','-')}"><xsl:apply-templates mode="pod"/></a></h3> +</xsl:template> + +<xsl:template match="head4" mode="pod"> + <h4><a name="{translate(.,' ','-')}"><xsl:apply-templates mode="pod"/></a></h4> +</xsl:template> + +<xsl:template match="itemizedlist" mode="pod"> + <ul><xsl:apply-templates mode="pod"/></ul> +</xsl:template> + +<xsl:template match="orderedlist" mode="pod"> + <ol><xsl:apply-templates mode="pod"/></ol> +</xsl:template> + +<xsl:template match="listitem" mode="pod"> + <li><xsl:apply-templates mode="pod"/></li> +</xsl:template> + +<xsl:template match="itemtext" mode="pod"> + <span class="itemtext"><xsl:apply-templates mode="pod"/></span> +</xsl:template> + +<xsl:template match="hr" mode="pod"> + <hr/> +</xsl:template> + +<xsl:template match="C" mode="pod"> + <code><xsl:apply-templates mode="pod"/></code> +</xsl:template> + +<xsl:template match="B" mode="pod"> + <b><xsl:apply-templates mode="pod"/></b> +</xsl:template> + +<xsl:template match="I" mode="pod"> + <i><xsl:apply-templates mode="pod"/></i> +</xsl:template> + +<xsl:template match="F" mode="pod"> + <code class="file"><xsl:apply-templates mode="pod"/></code> +</xsl:template> + +<xsl:template match="indent" mode="pod"> + <blockquote><xsl:apply-templates mode="pod"/></blockquote> +</xsl:template> + +<xsl:template match="[EMAIL PROTECTED]'image']" mode="pod"> + <img src="{.}"/> +</xsl:template> + +<xsl:template match="*|@*" mode="pod"> + <xsl:copy> + <xsl:apply-templates select="@*" mode="pod"/> + <xsl:apply-templates mode="pod"/> + </xsl:copy> +</xsl:template> + +</xsl:stylesheet> Modified: trunk/lib/AxKit2/Config/Global.pm =================================================================== --- trunk/lib/AxKit2/Config/Global.pm 2006-08-14 22:38:21 UTC (rev 83) +++ trunk/lib/AxKit2/Config/Global.pm 2006-08-15 22:37:33 UTC (rev 84) @@ -34,12 +34,6 @@ $self->{ConsoleAddr}; } -sub styleroot { - my $self = shift; - @_ and $self->{StylesheetRoot} = shift; - $self->{StylesheetRoot}; -} - sub dirindex { my $self = shift; @_ and $self->{DirectoryIndex} = shift; Modified: trunk/lib/AxKit2/Config/Location.pm =================================================================== --- trunk/lib/AxKit2/Config/Location.pm 2006-08-14 22:38:21 UTC (rev 83) +++ trunk/lib/AxKit2/Config/Location.pm 2006-08-15 22:37:33 UTC (rev 84) @@ -44,12 +44,6 @@ $self->{DocumentRoot} || $self->server->docroot; } -sub styleroot { - my $self = shift; - @_ and $self->{StylesheetRoot} = shift; - $self->{StylesheetRoot} || $self->server->styleroot; -} - sub dirindex { my $self = shift; @_ and $self->{DirectoryIndex} = shift; Modified: trunk/lib/AxKit2/Config/Server.pm =================================================================== --- trunk/lib/AxKit2/Config/Server.pm 2006-08-14 22:38:21 UTC (rev 83) +++ trunk/lib/AxKit2/Config/Server.pm 2006-08-15 22:37:33 UTC (rev 84) @@ -48,12 +48,6 @@ $self->{DocumentRoot} || $self->global->docroot; } -sub styleroot { - my $self = shift; - @_ and $self->{StylesheetRoot} = shift; - $self->{StylesheetRoot} || $self->global->styleroot; -} - sub dirindex { my $self = shift; @_ and $self->{DirectoryIndex} = shift; Modified: trunk/lib/AxKit2/Config.pm =================================================================== --- trunk/lib/AxKit2/Config.pm 2006-08-14 22:38:21 UTC (rev 83) +++ trunk/lib/AxKit2/Config.pm 2006-08-15 22:37:33 UTC (rev 84) @@ -17,6 +17,7 @@ DirectoryIndex => [\&TAKE1, sub { my $conf = shift; $conf->dirindex($_[0]) }], ConsolePort => [\&TAKE1, sub { my $conf = shift; $conf->isa('AxKit2::Config::Global') || die "ConsolePort only allowed at global level"; $conf->console_port($_[0]) }], ConsoleAddr => [\&TAKE1, sub { my $conf = shift; $conf->isa('AxKit2::Config::Global') || die "ConsoleAddr only allowed at global level"; $conf->console_addr($_[0]) }], + PluginDir => [\&TAKE1, sub { my $conf = shift; $conf->plugin_dir($_[0]) }], ); our $GLOBAL = AxKit2::Config::Global->new(); Added: trunk/lib/AxKit2/Docs/WritingPlugins.pod =================================================================== --- trunk/lib/AxKit2/Docs/WritingPlugins.pod 2006-08-14 22:38:21 UTC (rev 83) +++ trunk/lib/AxKit2/Docs/WritingPlugins.pod 2006-08-15 22:37:33 UTC (rev 84) @@ -0,0 +1,263 @@ +=head1 Writing Plugins + +Everything in AxKit2 is controlled via plugins. This helps keep the core of +AxKit2 very simple and lightweight, yet makes it very powerful and extensible. + +Although AxKit comes with some included plugins to deliver flat files, and some +demo plugins to show how to transform XML, the real power of AxKit2 will only +be realised when you write your own plugin. Don't be afraid - this is very +simple to do. + +To make life easy, lets step through a working example. + +=head1 A Simple XSLT Engine + +We'll start with a simple plugin that transforms XML files to HTML using +XSLT. This example will cover some of the basics of how the XML transformation +system of AxKit2 works. + +=head2 Setting up the Directories + +Start in the AxKit2 root directory (where you can run C<./axkit> from). First +we'll create a directory to store your XML and your stylesheets: + + $ mkdir myfirstplugin + $ mkdir myfirstplugin/webroot + $ mkdir myfirstplugin/stylesheets + $ mkdir myfirstplugin/plugins + +=head2 Server Configuration + +Now we need to tell AxKit where all our files are and what port to listen on. +Here's a minimal config which you should store in F<myfirstplugin/axkit.conf>: + + # Setup error logging to the maximum level: + Plugin logging/warn + LogLevel LOGDEBUG + + # we need to load this to map URLs to filenames + Plugin uri_to_file + + # Setup our server + <Server> + Port 8080 + DocumentRoot myfirstplugin/webroot + DirectoryIndex index.xml + + # Load our plugin + PluginDir myfirstplugin/plugins + Plugin serve_xml + </Server> + +Now we can try and start AxKit and see what happens: + + $ ./axkit -c myfirstplugin/axkit.conf + L7 uri_to_file register_hook: uri_translation => hook_uri_translation + could not open myfirstplugin/plugins/serve_xml: No such file or directory + at lib/AxKit2/Plugin.pm line 103, <$fh> line 13. + +Well we should have expected this -- we haven't written our plugin yet! + +=head2 Plugin Code + +So load up your editor on F<myfirstplugin/plugins/serve_xml> and enter the +following perl code: + + #!/usr/bin/perl -w + + sub hook_xmlresponse { + my ($self, $input) = @_; + + $self->log(LOGDEBUG, "Serving up a file"); + + my $stylesheet = './myfirstplugin/stylesheets/default.xsl'; + + my $out = $input->transform(XSLT($stylesheet)); + + return OK, $out; + } + +The key part of this is the C<< $input->transform(...) >> method call, which +transforms the input using the given transformation types. Available types +include C<XSP()>, C<TAL()>, C<XPathScript()> and of course C<XSLT()>. + +Once the transformation is done we return C<< OK, $out >> to let AxKit know that +the transformation was successful and we should deliver the result to the +browser. + +[As a sidenote here, I include the #! perl shebang line to help syntax +highlighters know that this is perl code.] + +Now if you run AxKit again we shouldn't see any error, but instead some debug +output telling us our plugin was loaded: + + $ ./axkit -c myfirstplugin/axkit.conf + L7 uri_to_file register_hook: uri_translation => hook_uri_translation + L7 serve_xml register_hook: xmlresponse => hook_xmlresponse + +Now if we point a web browser at this server we will get an error because we +haven't created an F<index.xml> and F<default.xsl> yet. So lets do that now. + +=head2 XML and XSLT Files + +F<myfirstplugin/webroot/index.xml>: + + <?xml version="1.0"?> + <dromedaries> + <species name="Camel"> + <humps>1 or 2</humps> + <disposition>Cranky</disposition> + </species> + <species name="Llama"> + <humps>1 (sort of)</humps> + <disposition>Aloof</disposition> + </species> + <species name="Alpaca"> + <humps>(see Llama)</humps> + <disposition>Friendly</disposition> + </species> + </dromedaries> + +F<myfirstplugin/stylesheets/default.xsl>: + + <?xml version="1.0"?> + <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + version="1.0"> + <xsl:template match="/"> + <html> + <head><title>Know Your Dromedaries</title></head> + <body> + <table bgcolor="eeeeee" border="1"> + <tr> + <th>Species</th> + <th>No of Humps</th> + <th>Disposition</th> + </tr> + <xsl:for-each select="dromedaries"> + <xsl:apply-templates select="./species" /> + </xsl:for-each> + </table> + </body> + </html> + </xsl:template> + <xsl:template match="species"> + <tr> + <td><xsl:value-of select="@name" /></td> + <td><xsl:value-of select="./humps" /></td> + <td><xsl:value-of select="./disposition" /></td> + </tr> + </xsl:template> + </xsl:stylesheet> + +Now when you request the page you should get a HTML table listing the +dromedaries in the index.xml file. + +Some browsers might also request the non-existant favicon.ico too, which may +cause an error to appear in the terminal. Don't worry about that for now. + +Congratulations, your first plugin is complete! + + + +=head1 Making Your Plugin Configurable + +One area where AxKit2 really shines is that each plugin can define its own +configuration parameters. Our plugin is a perfect candidate for that because +we hard-coded the XSLT stylesheet. Lets make that configurable now. + +To add configuration parameters we need to specify them as soon as the plugin +is loaded, in the plugin's C<init()> method. + + + +=over 4 + +B<A Sidetrack - What is a 'Plugin'?> + +Skip this section if you don't want to know the gory details - you don't need +to know about for writing simple plugins. + +Knowledgable perl hackers will have noticed that our C<hook_xmlresponse> method +above received two parameters, the first being C<$self>, and yet we didn't +create a perl class with all the annoying C<bless> verbiage. Well yes, a plugin +is a perl class, and C<$self> is an instance of that class. We simply went out +of our way to hide all the horrible perl guts from you. + +If you prefer all the perl guts to be exposed, you can create a full blown +package as your plugin instead, install it in the usual perl install locations, +and load it with: + + Plugin My::Plugin + +As long as it has '::' in the name, AxKit will recognise it as a perl module and +load it that way. Just be sure to 'use base q(AxKit2::Plugin)' so you get all +the base class methods. + +=back + + + +The C<init()> method allows us to setup any plugin-wide defaults such as +database connections. To add configuration directives we just call the +C<add_config()> method like so: + + sub init { + my $self = shift; + $self->register_config('XSLT_Style', sub { $self->set_style(@_) }); + } + +There we added a configuration directive called C<XSLT_Style> which we'll use +to define our stylesheet. We just need to implement the C<set_style()> method: + + sub set_style { + my ($self, $config, $style) = @_; + my $key = $self->plugin_name . '::style'; + $config->notes($key, $style); + } + +There we store the configuration in the C<$config->notes()> table (mod_perl +users will recognise this as a dictionary storage container), making sure we +don't clobber anyone elses name by using the key I<plugin_name>::style. + +Now we also need the corresponding C<get_style()> method: + + sub get_style { + my $self = shift; + $self->config->notes($self->plugin_name . '::style'); + } + +Simple huh? + +Now we need to tie all that together. First add this to your config after +"C<Plugin serve_xml>": + + XSLT_Style myfirstplugin/stylesheets/default.xsl + +And now modify your C<hook_xmlresponse()> method to get this new value using +C<get_style()>: + + sub hook_xmlresponse { + my ($self, $input) = @_; + + $self->log(LOGDEBUG, "Serving up a file"); + + my $stylesheet = $self->get_style; + + my $out = $input->transform(XSLT($stylesheet)); + + return OK, $out; + } + +And we're done! Run (or restart) axkit (C<./axkit -c myfirstplugin/axkit.conf>) +and ensure that it all works. + + + + +=head1 Multiple Transformations + +=head1 Caching + +=head1 What Are the APIs? + +=cut Modified: trunk/lib/AxKit2/HTTPHeaders.pm =================================================================== --- trunk/lib/AxKit2/HTTPHeaders.pm 2006-08-14 22:38:21 UTC (rev 83) +++ trunk/lib/AxKit2/HTTPHeaders.pm 2006-08-15 22:37:33 UTC (rev 84) @@ -341,6 +341,11 @@ $self->{vernum}; } +sub request_line { + my AxKit2::HTTPHeaders $self = shift; + $self->{requestLine}; +} + sub header { my AxKit2::HTTPHeaders $self = shift; my $key = shift; Modified: trunk/lib/AxKit2/Plugin.pm =================================================================== --- trunk/lib/AxKit2/Plugin.pm 2006-08-14 22:38:21 UTC (rev 83) +++ trunk/lib/AxKit2/Plugin.pm 2006-08-15 22:37:33 UTC (rev 84) @@ -7,10 +7,11 @@ use AxKit2::Constants; # more or less in the order they will fire +# DON'T FORGET - edit "AVAILABLE HOOKS" below. our @hooks = qw( - logging config pre-connection connect post_read_request - body_data uri_translation access_control authentication authorization - fixup mime_map xmlresponse response response_sent disconnect error + logging connect post_read_request body_data uri_translation access_control + authentication authorization mime_map xmlresponse response + response_sent disconnect error ); our %hooks = map { $_ => 1 } @hooks; @@ -23,7 +24,7 @@ sub register_hook { my ($self, $hook, $method, $unshift) = @_; - $self->log(LOGDEBUG, "register_hook: $self, $hook, $method"); + $self->log(LOGDEBUG, "register_hook: $hook => $method"); die $self->plugin_name . " : Invalid hook: $hook" unless $hooks{$hook}; push @{$self->{__hooks}{$hook}}, sub { @@ -134,3 +135,43 @@ } 1; + +__END__ + +=head1 NAME + +AxKit2::Plugin - base class for all plugins + +=head1 DESCRIPTION + +=head1 AVAILABLE HOOKS + +=head2 logging + +=head2 connect + +=head2 post_read_request + +=head2 body_data + +=head2 uri_translation + +=head2 access_control + +=head2 authentication + +=head2 authorization + +=head2 mime_map + +=head2 xmlresponse + +=head2 response + +=head2 response_sent + +=head2 disconnect + +=head2 error + +=cut Modified: trunk/lib/AxKit2/Processor.pm =================================================================== --- trunk/lib/AxKit2/Processor.pm 2006-08-14 22:38:21 UTC (rev 83) +++ trunk/lib/AxKit2/Processor.pm 2006-08-15 22:37:33 UTC (rev 84) @@ -55,9 +55,9 @@ if (ref($input) eq 'XML::LibXML::Document') { return $input; } - elsif (my $fh = eval { *{$input}{IO} }) { + elsif (ref($input) eq 'GLOB') { # parse $fh - return $self->{input} = $parser->parse_fh($fh); + return $self->{input} = $parser->parse_fh($input); } else { # assume string Modified: trunk/lib/AxKit2.pm =================================================================== --- trunk/lib/AxKit2.pm 2006-08-14 22:38:21 UTC (rev 83) +++ trunk/lib/AxKit2.pm 2006-08-15 22:37:33 UTC (rev 84) @@ -38,9 +38,11 @@ Just start the server: - ./axkit + $ cp etc/axkit.conf.sample etc/axkit.conf + $ ./axkit -To do anything complex read the documentation and start writing plugins. +To do anything more than run the demo files you'll need to read the +documentation and start writing plugins. =head1 DESCRIPTION @@ -48,14 +50,94 @@ footsteps of AxKit-1 (ONE). AxKit makes content generation easy by providing powerful tools to push XML through stylesheets. This helps ensure your web applications don't suffer from XSS bugs, and provides standardised templating -tools so that your template authors don't need to learn a new Perl templating -tool. +tools so that your template authors don't need to learn new Perl templating +tools. +In doing all this AxKit harnesses the power of XML. Feel the power. + =head1 PLUGINS Everything AxKit2 does is controlled by a plugin, and thus a lot of the -documentation for things that AxKit2 does is held within the plugin itself. +documentation for things that AxKit2 does is held within the provided plugins. +To get started writing plugins see L<AxKit2::Docs::WritingPlugins>. + +=head2 CORE PLUGINS + +The following are the core plugins which ship with AxKit2: + +=over 4 + +=item * B<cachecache> - A cache plugin that gives every plugin access to a +cache. + +See L<plugins::cachecache>. + +=item * B<dir_to_xml> - Provides XML for a directory request. + +See L<plugins::dir_to_xml>. + +=item * B<error_xml> - When an exception/error occurs this plugin generates +XML (with an optional stacktrace) for what happened, and allows you to apply +XSLT to that XML to display it in the browser. + +See L<plugins::error_xml>. + +=item * B<fast_mime_map> - Maps files to a MIME type for output in the +F<Content-Type> header using the file extension only. + +See L<plugins::fast_mime_map>. + +=item * B<magic_mime_map> - Maps files to a MIME type using F<File::MMagic>. + +See L<plugins::magic_mime_map>. + +=item * B<request_log> - Logs requests in the Apache combined log format. + +See L<plugins::request_log>. + +=item * B<serve_cgi> - Runs CGI scripts. + +See L<plugins::serve_cgi>. + +=item * B<serve_file> - Serves plain files. + +See L<plugins::serve_file>. + +=item * B<stats> - Provides access statistics for the console. + +See L<plugins::stats>. + +=item * B<uri_to_file> - Maps URLs to filenames. + +See L<plugins::uri_to_file>. + +=item * B<logging/warn> - Logging output to STDERR via warn(). + +See L<plugins::logging/warn>. + +=back + +=head1 CONSOLE + +AxKit2 has a console which you can log into to view current and trend activity +on your server. To setup the console add the following config: + + ConsolePort 18000 + Plugin stats + +This creates the console on C<localhost:18000>, and loads the stats plugin to +provide trend statistics on your server. To use the console just telnet to +port 18000. There is online help there and it should be obvious what each +function does. + +To provide additional stats, modify the stats plugin or write your own. Whatever +C<get_stats> returns will be output in the console when asked for statistics. + +=head1 API DOCUMENTATION + +TODO - fill in as I write more docs for each module. + =head1 Why 2.0? In creating AxKit2 the following goals were aimed for: @@ -76,6 +158,13 @@ Many people wanted a straight port to Apache2/mod_perl2, so that they could get their AxKit code migrated off the Apache1.x platform. This would have been -one route to go down, a route which we looked at very seriously. However it is -not the path we chose for a number of reasons which you can find in the AxKit -mailing list archives. +one route to go down, a route which we looked at very seriously. However already +taking up the mantle of an Apache2 version of AxKit is Tom Schindl's +Apache2::TomKit distribution. Please check that out if you absolutely need +mod_perl2 integration. + +=head1 LICENSE + +AxKit2 is licensed under the Apache License, Version 2.0. + +=cut Added: trunk/plugins/demo/doc_viewer =================================================================== --- trunk/plugins/demo/doc_viewer 2006-08-14 22:38:21 UTC (rev 83) +++ trunk/plugins/demo/doc_viewer 2006-08-15 22:37:33 UTC (rev 84) @@ -0,0 +1,42 @@ +#!/usr/bin/perl -w + +use Pod::SAX; +use XML::LibXML::SAX::Builder; + +sub hook_xmlresponse { + my ($self, $input) = @_; + + my $uri = $self->client->headers_in->request_uri(); + + $self->log(LOGDEBUG, "request for $uri"); + + $uri =~ s/\/docs//; + + # map URI to path + if ($uri eq '/') { + $uri = 'lib/AxKit2.pm'; + } + elsif ($uri =~ /::/) { + $uri =~ s/^\///; + $uri = "lib/$uri" unless $uri =~ /plugins::/; + $uri =~ s/::/\//g; + $uri .= '.pm' if -e "${uri}.pm"; + $uri .= '.pod' if -e "${uri}.pod"; + } + else { + # Ignore? + } + + my $builder = XML::LibXML::SAX::Builder->new(); + my $p = Pod::SAX->new( Handler => $builder ); + + $p->parse_file($uri); + + my $doc = $builder->result(); + + $input->dom($doc); + + my $out = $input->transform(XSLT('demo/xslt/main.xsl')); + + return OK, $out; +}